summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/general/plugins/modules/kdeconfig.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
commit975f66f2eebe9dadba04f275774d4ab83f74cf25 (patch)
tree89bd26a93aaae6a25749145b7e4bca4a1e75b2be /ansible_collections/community/general/plugins/modules/kdeconfig.py
parentInitial commit. (diff)
downloadansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.tar.xz
ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.zip
Adding upstream version 7.7.0+dfsg.upstream/7.7.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/community/general/plugins/modules/kdeconfig.py')
-rw-r--r--ansible_collections/community/general/plugins/modules/kdeconfig.py277
1 files changed, 277 insertions, 0 deletions
diff --git a/ansible_collections/community/general/plugins/modules/kdeconfig.py b/ansible_collections/community/general/plugins/modules/kdeconfig.py
new file mode 100644
index 000000000..42a08dd64
--- /dev/null
+++ b/ansible_collections/community/general/plugins/modules/kdeconfig.py
@@ -0,0 +1,277 @@
+#!/usr/bin/python
+
+# Copyright (c) 2023, Salvatore Mesoraca <s.mesoraca16@gmail.com>
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+# SPDX-License-Identifier: GPL-3.0-or-later
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+
+DOCUMENTATION = r'''
+---
+module: kdeconfig
+short_description: Manage KDE configuration files
+version_added: "6.5.0"
+description:
+ - Add or change individual settings in KDE configuration files.
+ - It uses B(kwriteconfig) under the hood.
+
+options:
+ path:
+ description:
+ - Path to the config file. If the file does not exist it will be created.
+ type: path
+ required: true
+ kwriteconfig_path:
+ description:
+ - Path to the kwriteconfig executable. If not specified, Ansible will try
+ to discover it.
+ type: path
+ values:
+ description:
+ - List of values to set.
+ type: list
+ elements: dict
+ suboptions:
+ group:
+ description:
+ - The option's group. One between this and I(groups) is required.
+ type: str
+ groups:
+ description:
+ - List of the option's groups. One between this and I(group) is required.
+ type: list
+ elements: str
+ key:
+ description:
+ - The option's name.
+ type: str
+ required: true
+ value:
+ description:
+ - The option's value. One between this and I(bool_value) is required.
+ type: str
+ bool_value:
+ description:
+ - Boolean value.
+ - One between this and I(value) is required.
+ type: bool
+ required: true
+ backup:
+ description:
+ - Create a backup file.
+ type: bool
+ default: false
+extends_documentation_fragment:
+ - files
+ - community.general.attributes
+attributes:
+ check_mode:
+ support: full
+ diff_mode:
+ support: full
+requirements:
+ - kwriteconfig
+author:
+ - Salvatore Mesoraca (@smeso)
+'''
+
+EXAMPLES = r'''
+- name: Ensure "Homepage=https://www.ansible.com/" in group "Branding"
+ community.general.kdeconfig:
+ path: /etc/xdg/kickoffrc
+ values:
+ - group: Branding
+ key: Homepage
+ value: https://www.ansible.com/
+ mode: '0644'
+
+- name: Ensure "KEY=true" in groups "Group" and "Subgroup", and "KEY=VALUE" in Group2
+ community.general.kdeconfig:
+ path: /etc/xdg/someconfigrc
+ values:
+ - groups: [Group, Subgroup]
+ key: KEY
+ bool_value: true
+ - group: Group2
+ key: KEY
+ value: VALUE
+ backup: true
+'''
+
+RETURN = r''' # '''
+
+import os
+import shutil
+import tempfile
+import traceback
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.common.text.converters import to_bytes, to_text
+
+
+class TemporaryDirectory(object):
+ """Basic backport of tempfile.TemporaryDirectory"""
+
+ def __init__(self, suffix="", prefix="tmp", dir=None):
+ self.name = None
+ self.name = tempfile.mkdtemp(suffix, prefix, dir)
+
+ def __enter__(self):
+ return self.name
+
+ def rm(self):
+ if self.name:
+ shutil.rmtree(self.name, ignore_errors=True)
+ self.name = None
+
+ def __exit__(self, exc, value, tb):
+ self.rm()
+
+ def __del__(self):
+ self.rm()
+
+
+def run_kwriteconfig(module, cmd, path, groups, key, value):
+ """Invoke kwriteconfig with arguments"""
+ args = [cmd, '--file', path, '--key', key]
+ for group in groups:
+ args.extend(['--group', group])
+ if isinstance(value, bool):
+ args.extend(['--type', 'bool'])
+ if value:
+ args.append('true')
+ else:
+ args.append('false')
+ else:
+ args.append(value)
+ module.run_command(args, check_rc=True)
+
+
+def run_module(module, tmpdir, kwriteconfig):
+ result = dict(changed=False, msg='OK', path=module.params['path'])
+ b_path = to_bytes(module.params['path'])
+ tmpfile = os.path.join(tmpdir, 'file')
+ b_tmpfile = to_bytes(tmpfile)
+ diff = dict(
+ before='',
+ after='',
+ before_header=result['path'],
+ after_header=result['path'],
+ )
+ try:
+ with open(b_tmpfile, 'wb') as dst:
+ try:
+ with open(b_path, 'rb') as src:
+ b_data = src.read()
+ except IOError:
+ result['changed'] = True
+ else:
+ dst.write(b_data)
+ try:
+ diff['before'] = to_text(b_data)
+ except UnicodeError:
+ diff['before'] = repr(b_data)
+ except IOError:
+ module.fail_json(msg='Unable to create temporary file', traceback=traceback.format_exc())
+
+ for row in module.params['values']:
+ groups = row['groups']
+ if groups is None:
+ groups = [row['group']]
+ key = row['key']
+ value = row['bool_value']
+ if value is None:
+ value = row['value']
+ run_kwriteconfig(module, kwriteconfig, tmpfile, groups, key, value)
+
+ with open(b_tmpfile, 'rb') as tmpf:
+ b_data = tmpf.read()
+ try:
+ diff['after'] = to_text(b_data)
+ except UnicodeError:
+ diff['after'] = repr(b_data)
+
+ result['changed'] = result['changed'] or diff['after'] != diff['before']
+
+ file_args = module.load_file_common_arguments(module.params)
+
+ if module.check_mode:
+ if not result['changed']:
+ shutil.copystat(b_path, b_tmpfile)
+ uid, gid = module.user_and_group(b_path)
+ os.chown(b_tmpfile, uid, gid)
+ if module._diff:
+ diff = {}
+ else:
+ diff = None
+ result['changed'] = module.set_fs_attributes_if_different(file_args, result['changed'], diff=diff)
+ if module._diff:
+ result['diff'] = diff
+ module.exit_json(**result)
+
+ if result['changed']:
+ if module.params['backup'] and os.path.exists(b_path):
+ result['backup_file'] = module.backup_local(result['path'])
+ try:
+ module.atomic_move(b_tmpfile, b_path)
+ except IOError:
+ module.ansible.fail_json(msg='Unable to move temporary file %s to %s, IOError' % (tmpfile, result['path']), traceback=traceback.format_exc())
+
+ if result['changed']:
+ module.set_fs_attributes_if_different(file_args, result['changed'])
+ else:
+ if module._diff:
+ diff = {}
+ else:
+ diff = None
+ result['changed'] = module.set_fs_attributes_if_different(file_args, result['changed'], diff=diff)
+ if module._diff:
+ result['diff'] = diff
+ module.exit_json(**result)
+
+
+def main():
+ single_value_arg = dict(group=dict(type='str'),
+ groups=dict(type='list', elements='str'),
+ key=dict(type='str', required=True, no_log=False),
+ value=dict(type='str'),
+ bool_value=dict(type='bool'))
+ required_alternatives = [('group', 'groups'), ('value', 'bool_value')]
+ module_args = dict(
+ values=dict(type='list',
+ elements='dict',
+ options=single_value_arg,
+ mutually_exclusive=required_alternatives,
+ required_one_of=required_alternatives,
+ required=True),
+ path=dict(type='path', required=True),
+ kwriteconfig_path=dict(type='path'),
+ backup=dict(type='bool', default=False),
+ )
+
+ module = AnsibleModule(
+ argument_spec=module_args,
+ add_file_common_args=True,
+ supports_check_mode=True,
+ )
+
+ kwriteconfig = None
+ if module.params['kwriteconfig_path'] is not None:
+ kwriteconfig = module.get_bin_path(module.params['kwriteconfig_path'], required=True)
+ else:
+ for progname in ('kwriteconfig5', 'kwriteconfig', 'kwriteconfig4'):
+ kwriteconfig = module.get_bin_path(progname)
+ if kwriteconfig is not None:
+ break
+ if kwriteconfig is None:
+ module.fail_json(msg='kwriteconfig is not installed')
+ for v in module.params['values']:
+ if not v['key']:
+ module.fail_json(msg="'key' cannot be empty")
+ with TemporaryDirectory(dir=module.tmpdir) as tmpdir:
+ run_module(module, tmpdir, kwriteconfig)
+
+
+if __name__ == '__main__':
+ main()