Last active
December 4, 2019 12:38
-
-
Save ntrrgc/10007589 to your computer and use it in GitHub Desktop.
Fork of Ansible's ini_file, which does preserve comments and latter case
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# -*- coding: utf-8 -*- | |
# (c) 2014, Juan Luis Boya García <ntrrgc () gmail.com> | |
# (c) 2012, Jan-Piet Mens <jpmens () gmail.com> | |
# | |
# This file is part of Ansible | |
# | |
# Ansible is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# | |
# Ansible is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. | |
# | |
DOCUMENTATION = ''' | |
--- | |
module: ini_patch | |
short_description: Tweak settings in INI files without trimming comments nor case | |
description: | |
- This module is a fork of ini_file which uses ConfigObj instead of ConfigParser. | |
As a consequence, comments and letters' case is preserved. The interface is the | |
same as ini_file. | |
- Manage (add, remove, change) individual settings in an INI-style file without having | |
to manage the file as a whole with, say, M(template) or M(assemble). Adds missing | |
sections if they don't exist. | |
options: | |
dest: | |
description: | |
- Path to the INI-style file; this file is created if required | |
required: true | |
default: null | |
section: | |
description: | |
- Section name in INI file. This is added if C(state=present) automatically when | |
a single value is being set. | |
required: true | |
default: null | |
option: | |
description: | |
- if set (required for changing a I(value)), this is the name of the option. | |
- May be omitted if adding/removing a whole I(section). | |
required: false | |
default: null | |
value: | |
description: | |
- the string value to be associated with an I(option). May be omitted when removing an I(option). | |
required: false | |
default: null | |
backup: | |
description: | |
- Create a backup file including the timestamp information so you can get | |
the original file back if you somehow clobbered it incorrectly. | |
required: false | |
default: "no" | |
choices: [ "yes", "no" ] | |
others: | |
description: | |
- all arguments accepted by the M(file) module also work here | |
required: false | |
notes: | |
- While it is possible to add an I(option) without specifying a I(value), this makes | |
no sense. | |
requirements: [ ConfigObj ] | |
author: Juan Luis Boya García | |
''' | |
EXAMPLES = ''' | |
# Ensure "fav=lemonade is in section "[drinks]" in specified file | |
- ini_file: dest=/etc/conf section=drinks option=fav value=lemonade mode=0600 backup=yes | |
- ini_file: dest=/etc/anotherconf | |
section=drinks | |
option=temperature | |
value=cold | |
backup=yes | |
''' | |
import configobj | |
# ============================================================== | |
# do_ini | |
def do_ini(module, filename, section=None, option=None, value=None, state='present', backup=False): | |
changed = False | |
cp = configobj.ConfigObj(filename, list_values=False) | |
if state == 'absent': | |
if option is None and value is None: | |
if section in cp: | |
del cp[section] | |
changed = True | |
else: | |
if option is not None: | |
if section in cp and option in cp[section]: | |
del[section][option] | |
changed = True | |
if state == 'present': | |
if option is not None and value is not None: | |
try: | |
oldvalue = cp[section][option] | |
if str(value) != str(oldvalue): | |
cp[section][option] = value | |
changed = True | |
except KeyError: | |
if not section in cp: | |
cp[section] = {} | |
cp[section][option] = value | |
changed = True | |
if changed: | |
if backup: | |
module.backup_local(filename) | |
try: | |
f = open(filename, 'w') | |
cp.write(f) | |
except: | |
module.fail_json(msg="Can't creat %s" % filename) | |
return changed | |
# ============================================================== | |
# main | |
def main(): | |
module = AnsibleModule( | |
argument_spec = dict( | |
dest = dict(required=True), | |
section = dict(required=True), | |
option = dict(required=False), | |
value = dict(required=False), | |
backup = dict(default='no', type='bool'), | |
state = dict(default='present', choices=['present', 'absent']) | |
), | |
add_file_common_args = True | |
) | |
info = dict() | |
dest = os.path.expanduser(module.params['dest']) | |
section = module.params['section'] | |
option = module.params['option'] | |
value = module.params['value'] | |
state = module.params['state'] | |
backup = module.params['backup'] | |
changed = do_ini(module, dest, section, option, value, state, backup) | |
file_args = module.load_file_common_arguments(module.params) | |
changed = module.set_file_attributes_if_different(file_args, changed) | |
# Mission complete | |
module.exit_json(dest=dest, changed=changed, msg="OK") | |
# import module snippets | |
from ansible.module_utils.basic import * | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment