From bffa5255825a1243b06fc975a2edff23f8f7acf8 Mon Sep 17 00:00:00 2001 From: ChrisWi Date: Sat, 24 Aug 2024 16:39:08 +0200 Subject: [PATCH 1/2] zypper_repository: extend module with possibility to modify repos --- plugins/modules/zypper_repository.py | 99 +++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 16 deletions(-) diff --git a/plugins/modules/zypper_repository.py b/plugins/modules/zypper_repository.py index 5a0356cc37b..41201411d21 100644 --- a/plugins/modules/zypper_repository.py +++ b/plugins/modules/zypper_repository.py @@ -3,6 +3,7 @@ # Copyright (c) 2013, Matthias Vogelgesang # Copyright (c) 2014, Justin Lecher +# Copyright (c) 2017, Christian Wittmer # # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later @@ -15,9 +16,9 @@ --- module: zypper_repository author: "Matthias Vogelgesang (@matze)" -short_description: Add and remove Zypper repositories +short_description: Add, modify and remove zypper repositories description: - - Add or remove Zypper repositories on SUSE and openSUSE + - Add, modify or remove zypper repositories on SLE and openSUSE extends_documentation_fragment: - community.general.attributes attributes: @@ -32,13 +33,24 @@ type: str repo: description: - - URI of the repository or .repo file. Required when state=present. + - URI of the repository or .repo file. Required when O(state=present) and O(action=add). type: str - state: + action: + required: false + choices: [ "add", "modify", "remove" ] + default: "add" description: - - A source string state. + - The action you want to perform. C(add, modify or remove) + - When wanting to C(add) a repo you can omit either O(action=add) or O(state=present) cause of their defaults. + - When wanting to C(modify) a repo then just use O(action=modify) + - When wanting to C(remove) a repo then just use one of O(state=absent) or O(action=remove) + - When using with C(modify) you should not run another task with C(add) before or afterwards cause of idempotency. + type: str + state: choices: [ "absent", "present" ] default: "present" + description: + - A source string state. type: str description: description: @@ -128,6 +140,20 @@ name: my_ci_repo state: present runrefresh: true + +- name: "Modify (disable) repo (e.g. installed via template)" + community.general.zypper_repository: + action: modify + name: 15.5-update-sle + autorefresh: false + enabled: false + +- name: "Modify (enable) repo (e.g. installed via template)" + community.general.zypper_repository: + action: modify + name: 15.6-update-sle + autorefresh: true + enabled: true ''' import traceback @@ -293,6 +319,36 @@ def addmodify_repo(module, repodata, old_repos, zypper_version, warnings): return rc, stdout, stderr +def modify_repo(module, repodata, zypper_version, warnings): + "Modifys the repo like name, enable/disable, refresh/no-refresh, priority" + cmd = _get_cmd('modifyrepo') + if repodata['name']: + cmd.extend(['--name', repodata['name']]) + + # priority on addrepo available since 1.12.25 + # https://github.com/openSUSE/zypper/blob/b9b3cb6db76c47dc4c47e26f6a4d2d4a0d12b06d/package/zypper.changes#L327-L336 + if repodata['priority']: + if zypper_version >= LooseVersion('1.12.25'): + cmd.extend(['--priority', str(repodata['priority'])]) + else: + warnings.append("Setting priority only available for zypper >= 1.12.25. Ignoring priority argument.") + + if repodata['enabled'] == '1': + cmd.append('--enable') + else: + cmd.append('--disable') + + if repodata['autorefresh'] == '1': + cmd.append('--refresh') + else: + cmd.append('--no-refresh') + + cmd.append(repodata['alias']) + + rc, stdout, stderr = module.run_command(cmd, check_rc=False) + return rc, stdout, stderr + + def remove_repo(module, repo): "Removes the repo." cmd = _get_cmd(module, 'removerepo', repo) @@ -325,6 +381,7 @@ def main(): module = AnsibleModule( argument_spec=dict( name=dict(required=False), + action=dict(choices=['add', 'modify', 'remove'], default='add'), repo=dict(required=False), state=dict(choices=['present', 'absent'], default='present'), runrefresh=dict(required=False, default=False, type='bool'), @@ -337,11 +394,12 @@ def main(): auto_import_keys=dict(required=False, default=False, type='bool'), ), supports_check_mode=False, - required_one_of=[['state', 'runrefresh']], + required_one_of=[['action', 'state', 'runrefresh']], ) repo = module.params['repo'] alias = module.params['name'] + action = module.params['action'] state = module.params['state'] overwrite_multiple = module.params['overwrite_multiple'] auto_import_keys = module.params['auto_import_keys'] @@ -381,17 +439,19 @@ def exit_unchanged(): else: module.fail_json(msg='repo=* can only be used with the runrefresh option.') - if state == 'present' and not repo: - module.fail_json(msg='Module option state=present requires repo') - if state == 'absent' and not repo and not alias: - module.fail_json(msg='Alias or repo parameter required when state=absent') + if state == 'present' and action == 'add' and not repo: + module.fail_json(msg='Missing option: \'repo\' (URI). Required when state=present and action=add') + if action == 'modify' and not alias: + module.fail_json(msg='Missing option: \'name\' (Alias). Required when action=modify') + if (state == 'absent' or action == 'remove') and not alias: + module.fail_json(msg='Missing option: \'name\' (Alias). Required when state=absent or action=remove') if repo and repo.endswith('.repo'): if alias: module.fail_json(msg='Incompatible option: \'name\'. Do not use name when adding .repo files') else: - if not alias and state == "present": - module.fail_json(msg='Name required when adding non-repo files.') + if not alias and state == 'present' and action == 'add': + module.fail_json(msg='Missing option: \'name\' (Alias). Required when adding non-repo files.') # Download / Open and parse .repo file to ensure idempotency if repo and repo.endswith('.repo'): @@ -450,7 +510,7 @@ def exit_unchanged(): else: shortname = repo - if state == 'present': + if action == 'add' and state == 'present': if exists and not mod: if runrefresh: runrefreshrepo(module, auto_import_keys, shortname) @@ -458,15 +518,22 @@ def exit_unchanged(): rc, stdout, stderr = addmodify_repo(module, repodata, old_repos, zypper_version, warnings) if rc == 0 and (runrefresh or auto_import_keys): runrefreshrepo(module, auto_import_keys, shortname) - elif state == 'absent': + elif action == 'modify' and state == 'present': + if exists and not mod: + exit_unchanged() + if not exists: + exit_unchanged() + rc, stdout, stderr = modify_repo(module, repodata, zypper_version, warnings) + elif action == 'remove' or state == 'absent': if not exists: exit_unchanged() rc, stdout, stderr = remove_repo(module, shortname) if rc == 0: - module.exit_json(changed=True, repodata=repodata, state=state, warnings=warnings) + module.exit_json(changed=True, repodata=repodata, action=action, state=state, warnings=warnings) else: - module.fail_json(msg="Zypper failed with rc %s" % rc, rc=rc, stdout=stdout, stderr=stderr, repodata=repodata, state=state, warnings=warnings) + module.fail_json(msg="zypper failed with rc %s" % rc, rc=rc, stdout=stdout, stderr=stderr, repodata=repodata, action=action, state=state, + warnings=warnings) if __name__ == '__main__': From 1c7dae123a421beca7fa6ab878503ad00c2a8c9c Mon Sep 17 00:00:00 2001 From: ChrisWi Date: Sat, 24 Aug 2024 18:12:26 +0200 Subject: [PATCH 2/2] Add changelog fragment: 8795-extend-zypper_repository.yml --- changelogs/fragments/8795-extend-zypper_repository.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelogs/fragments/8795-extend-zypper_repository.yml diff --git a/changelogs/fragments/8795-extend-zypper_repository.yml b/changelogs/fragments/8795-extend-zypper_repository.yml new file mode 100644 index 00000000000..4764da5a0ae --- /dev/null +++ b/changelogs/fragments/8795-extend-zypper_repository.yml @@ -0,0 +1,3 @@ +minor_changes: + - zypper_repository add action with choices add, modify and remove + (https://github.com/ansible-collections/community.general/pull/8795).