From 49836bb48464419f4bb59c31f34ad613290c6d4b Mon Sep 17 00:00:00 2001 From: Alexei Znamensky <103110+russoz@users.noreply.github.com> Date: Sat, 4 Jun 2022 19:13:53 +1200 Subject: [PATCH] gconftool2_info: new module (#4743) * gconftool2_info: new module * fixed imports * fixed docs for gconftool2_info * fixed docs for gconftool2_info * minor adjustment in docs * added tests * adjustments --- .github/BOTMETA.yml | 6 ++ meta/runtime.yml | 2 + plugins/module_utils/gconftool2.py | 26 +++++ plugins/modules/system/gconftool2_info.py | 74 +++++++++++++ .../modules/system/test_gconftool2_info.py | 102 ++++++++++++++++++ 5 files changed, 210 insertions(+) create mode 100644 plugins/module_utils/gconftool2.py create mode 100644 plugins/modules/system/gconftool2_info.py create mode 100644 tests/unit/plugins/modules/system/test_gconftool2_info.py diff --git a/.github/BOTMETA.yml b/.github/BOTMETA.yml index ecedff1e81..b4a97468db 100644 --- a/.github/BOTMETA.yml +++ b/.github/BOTMETA.yml @@ -254,6 +254,9 @@ files: maintainers: amigus endlesstrax $module_utils/: labels: module_utils + $module_utils/gconftool2.py: + maintainers: russoz + labels: gconftool2 $module_utils/gitlab.py: notify: jlozadad maintainers: $team_gitlab @@ -1052,6 +1055,9 @@ files: $modules/system/gconftool2.py: maintainers: Akasurde kevensen labels: gconftool2 + $modules/system/gconftool2_info.py: + maintainers: russoz + labels: gconftool2 $modules/system/homectl.py: maintainers: jameslivulpi $modules/system/interfaces_file.py: diff --git a/meta/runtime.yml b/meta/runtime.yml index c3a439b6f3..e15dafd653 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -292,6 +292,8 @@ plugin_routing: redirect: community.google.gce_tag gconftool2: redirect: community.general.system.gconftool2 + gconftool2_info: + redirect: community.general.system.gconftool2_info gcp_backend_service: tombstone: removal_version: 2.0.0 diff --git a/plugins/module_utils/gconftool2.py b/plugins/module_utils/gconftool2.py new file mode 100644 index 0000000000..df9608fb30 --- /dev/null +++ b/plugins/module_utils/gconftool2.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# (c) 2022, Alexei Znamensky +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +from ansible_collections.community.general.plugins.module_utils.cmd_runner import CmdRunner, fmt + + +def gconftool2_runner(module, **kwargs): + return CmdRunner( + module, + command='gconftool-2', + arg_formats=dict( + key=fmt.as_list(), + value_type=fmt.as_opt_val("--type"), + value=fmt.as_list(), + direct=fmt.as_bool("--direct"), + config_source=fmt.as_opt_val("--config-source"), + get=fmt.as_bool("--get"), + set_arg=fmt.as_bool("--set"), + unset=fmt.as_bool("--unset"), + ), + **kwargs + ) diff --git a/plugins/modules/system/gconftool2_info.py b/plugins/modules/system/gconftool2_info.py new file mode 100644 index 0000000000..36aa9aa238 --- /dev/null +++ b/plugins/modules/system/gconftool2_info.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# (c) 2022, Alexei Znamensky +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +module: gconftool2_info +author: + - "Alexei Znamensky (@russoz)" +short_description: Retrieve GConf configurations +version_added: 5.1.0 +description: + - This module allows retrieving application preferences from the GConf database, with the help of C(gconftool-2). +options: + key: + description: + - The key name for an element in the GConf database. + type: str + required: true +notes: + - See man gconftool-2(1) for more details. +seealso: + - name: gconf repository (archived) + description: Git repository for the project. It is an archived project, so the repository is read-only. + link: https://gitlab.gnome.org/Archive/gconf +''' + +EXAMPLES = """ +- name: Get value for a certain key in the database. + community.general.gconftool2_info: + key: /desktop/gnome/background/picture_filename + register: result +""" + +RETURN = ''' + value: + description: + - The value of the property. + returned: success + type: str + sample: Monospace 10 +''' + +from ansible_collections.community.general.plugins.module_utils.module_helper import ModuleHelper +from ansible_collections.community.general.plugins.module_utils.gconftool2 import gconftool2_runner + + +class GConftoolInfo(ModuleHelper): + output_params = ['key'] + module = dict( + argument_spec=dict( + key=dict(type='str', required=True, no_log=False), + ), + supports_check_mode=True, + ) + + def __init_module__(self): + self.runner = gconftool2_runner(self.module, check_rc=True) + + def __run__(self): + with self.runner.context(args_order=["get", "key"]) as ctx: + rc, out, err = ctx.run(get=True) + self.vars.value = None if err and not out else out.rstrip() + + +def main(): + GConftoolInfo.execute() + + +if __name__ == '__main__': + main() diff --git a/tests/unit/plugins/modules/system/test_gconftool2_info.py b/tests/unit/plugins/modules/system/test_gconftool2_info.py new file mode 100644 index 0000000000..97d349f428 --- /dev/null +++ b/tests/unit/plugins/modules/system/test_gconftool2_info.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +# Author: Alexei Znamensky (russoz@gmail.com) +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json + +from ansible_collections.community.general.plugins.modules.system import gconftool2_info + +import pytest + +TESTED_MODULE = gconftool2_info.__name__ + + +@pytest.fixture +def patch_gconftool2_info(mocker): + """ + Function used for mocking some parts of redhat_subscribtion module + """ + mocker.patch('ansible_collections.community.general.plugins.module_utils.mh.module_helper.AnsibleModule.get_bin_path', + return_value='/testbin/gconftool-2') + + +TEST_CASES = [ + [ + {'key': '/desktop/gnome/background/picture_filename'}, + { + 'id': 'test_simple_element_get', + 'run_command.calls': [ + ( + # Calling of following command will be asserted + ['/testbin/gconftool-2', '--get', '/desktop/gnome/background/picture_filename'], + # Was return code checked? + {'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': True}, + # Mock of returned code, stdout and stderr + (0, '100\n', '',), + ), + ], + 'value': '100', + } + ], + [ + {'key': '/desktop/gnome/background/picture_filename'}, + { + 'id': 'test_simple_element_get_not_found', + 'run_command.calls': [ + ( + # Calling of following command will be asserted + ['/testbin/gconftool-2', '--get', '/desktop/gnome/background/picture_filename'], + # Was return code checked? + {'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': True}, + # Mock of returned code, stdout and stderr + (0, '', "No value set for `/desktop/gnome/background/picture_filename'\n",), + ), + ], + 'value': None, + } + ], +] +TEST_CASES_IDS = [item[1]['id'] for item in TEST_CASES] + + +@pytest.mark.parametrize('patch_ansible_module, testcase', + TEST_CASES, + ids=TEST_CASES_IDS, + indirect=['patch_ansible_module']) +@pytest.mark.usefixtures('patch_ansible_module') +def test_gconftool2_info(mocker, capfd, patch_gconftool2_info, testcase): + """ + Run unit tests for test cases listen in TEST_CASES + """ + + # Mock function used for running commands first + call_results = [item[2] for item in testcase['run_command.calls']] + mock_run_command = mocker.patch( + 'ansible_collections.community.general.plugins.module_utils.mh.module_helper.AnsibleModule.run_command', + side_effect=call_results) + + # Try to run test case + with pytest.raises(SystemExit): + gconftool2_info.main() + + out, err = capfd.readouterr() + results = json.loads(out) + print("testcase =\n%s" % testcase) + print("results =\n%s" % results) + + for conditional_test_result in ('value',): + if conditional_test_result in testcase: + assert conditional_test_result in results, "'{0}' not found in {1}".format(conditional_test_result, results) + assert results[conditional_test_result] == testcase[conditional_test_result], \ + "'{0}': '{1}' != '{2}'".format(conditional_test_result, results[conditional_test_result], testcase[conditional_test_result]) + + assert mock_run_command.call_count == len(testcase['run_command.calls']) + if mock_run_command.call_count: + call_args_list = [(item[0][0], item[1]) for item in mock_run_command.call_args_list] + expected_call_args_list = [(item[0], item[1]) for item in testcase['run_command.calls']] + print("call args list =\n%s" % call_args_list) + print("expected args list =\n%s" % expected_call_args_list) + assert call_args_list == expected_call_args_list