mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
[PR #7745/acc31730 backport][stable-8] Add dnf_config_manager module (#7794)
Add dnf_config_manager module (#7745)
* Add dnf_config_manager module
* add BOTMETA
* document return values
* improve error messages
* fix doc indent
* make regexes raw strings
* formatting improve
* fix indent
* update version_added
* Tweaks from feedback and unit testing
* fix copyright and python2.7
* remove shebang
* documentation updates
* Change return values to not have varying keys
* sort returned lists
(cherry picked from commit acc3173030
)
Co-authored-by: Andrew Hyatt <4400272+ahyattdev@users.noreply.github.com>
This commit is contained in:
parent
bf089294b4
commit
ce5417bb73
3 changed files with 629 additions and 0 deletions
2
.github/BOTMETA.yml
vendored
2
.github/BOTMETA.yml
vendored
|
@ -482,6 +482,8 @@ files:
|
||||||
maintainers: russoz
|
maintainers: russoz
|
||||||
$modules/dnf_versionlock.py:
|
$modules/dnf_versionlock.py:
|
||||||
maintainers: moreda
|
maintainers: moreda
|
||||||
|
$modules/dnf_config_manager.py:
|
||||||
|
maintainers: ahyattdev
|
||||||
$modules/dnsimple.py:
|
$modules/dnsimple.py:
|
||||||
maintainers: drcapulet
|
maintainers: drcapulet
|
||||||
$modules/dnsimple_info.py:
|
$modules/dnsimple_info.py:
|
||||||
|
|
225
plugins/modules/dnf_config_manager.py
Normal file
225
plugins/modules/dnf_config_manager.py
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023, Andrew Hyatt <andy@hyatt.xyz>
|
||||||
|
# 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
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
DOCUMENTATION = r'''
|
||||||
|
---
|
||||||
|
module: dnf_config_manager
|
||||||
|
short_description: Enable or disable dnf repositories using config-manager
|
||||||
|
version_added: 8.2.0
|
||||||
|
description:
|
||||||
|
- This module enables or disables repositories using the C(dnf config-manager) sub-command.
|
||||||
|
author: Andrew Hyatt (@ahyattdev) <andy@hyatt.xyz>
|
||||||
|
requirements:
|
||||||
|
- dnf
|
||||||
|
- dnf-plugins-core
|
||||||
|
extends_documentation_fragment:
|
||||||
|
- community.general.attributes
|
||||||
|
attributes:
|
||||||
|
check_mode:
|
||||||
|
support: full
|
||||||
|
diff_mode:
|
||||||
|
support: none
|
||||||
|
options:
|
||||||
|
name:
|
||||||
|
description:
|
||||||
|
- Repository ID, for example V(crb).
|
||||||
|
default: []
|
||||||
|
required: false
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
state:
|
||||||
|
description:
|
||||||
|
- Whether the repositories should be V(enabled) or V(disabled).
|
||||||
|
default: enabled
|
||||||
|
required: false
|
||||||
|
type: str
|
||||||
|
choices: [enabled, disabled]
|
||||||
|
seealso:
|
||||||
|
- module: ansible.builtin.dnf
|
||||||
|
- module: ansible.builtin.yum_repository
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = r'''
|
||||||
|
- name: Ensure the crb repository is enabled
|
||||||
|
community.general.dnf_config_manager:
|
||||||
|
name: crb
|
||||||
|
state: enabled
|
||||||
|
|
||||||
|
- name: Ensure the appstream and zfs repositories are disabled
|
||||||
|
community.general.dnf_config_manager:
|
||||||
|
name:
|
||||||
|
- appstream
|
||||||
|
- zfs
|
||||||
|
state: disabled
|
||||||
|
'''
|
||||||
|
|
||||||
|
RETURN = r'''
|
||||||
|
repo_states_pre:
|
||||||
|
description: Repo IDs before action taken.
|
||||||
|
returned: success
|
||||||
|
type: dict
|
||||||
|
contains:
|
||||||
|
enabled:
|
||||||
|
description: Enabled repository IDs.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
disabled:
|
||||||
|
description: Disabled repository IDs.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
sample:
|
||||||
|
enabled:
|
||||||
|
- appstream
|
||||||
|
- baseos
|
||||||
|
- crb
|
||||||
|
disabled:
|
||||||
|
- appstream-debuginfo
|
||||||
|
- appstream-source
|
||||||
|
- baseos-debuginfo
|
||||||
|
- baseos-source
|
||||||
|
- crb-debug
|
||||||
|
- crb-source
|
||||||
|
repo_states_post:
|
||||||
|
description: Repository states after action taken.
|
||||||
|
returned: success
|
||||||
|
type: dict
|
||||||
|
contains:
|
||||||
|
enabled:
|
||||||
|
description: Enabled repository IDs.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
disabled:
|
||||||
|
description: Disabled repository IDs.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
sample:
|
||||||
|
enabled:
|
||||||
|
- appstream
|
||||||
|
- baseos
|
||||||
|
- crb
|
||||||
|
disabled:
|
||||||
|
- appstream-debuginfo
|
||||||
|
- appstream-source
|
||||||
|
- baseos-debuginfo
|
||||||
|
- baseos-source
|
||||||
|
- crb-debug
|
||||||
|
- crb-source
|
||||||
|
changed_repos:
|
||||||
|
description: Repositories changed.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
sample: [ 'crb' ]
|
||||||
|
'''
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
DNF_BIN = "/usr/bin/dnf"
|
||||||
|
REPO_ID_RE = re.compile(r'^Repo-id\s*:\s*(\S+)$')
|
||||||
|
REPO_STATUS_RE = re.compile(r'^Repo-status\s*:\s*(disabled|enabled)$')
|
||||||
|
|
||||||
|
|
||||||
|
def get_repo_states(module):
|
||||||
|
rc, out, err = module.run_command([DNF_BIN, 'repolist', '--all', '--verbose'], check_rc=True)
|
||||||
|
|
||||||
|
repos = dict()
|
||||||
|
last_repo = ''
|
||||||
|
for i, line in enumerate(out.split('\n')):
|
||||||
|
m = REPO_ID_RE.match(line)
|
||||||
|
if m:
|
||||||
|
if len(last_repo) > 0:
|
||||||
|
module.fail_json(msg='dnf repolist parse failure: parsed another repo id before next status')
|
||||||
|
last_repo = m.group(1)
|
||||||
|
continue
|
||||||
|
m = REPO_STATUS_RE.match(line)
|
||||||
|
if m:
|
||||||
|
if len(last_repo) == 0:
|
||||||
|
module.fail_json(msg='dnf repolist parse failure: parsed status before repo id')
|
||||||
|
repos[last_repo] = m.group(1)
|
||||||
|
last_repo = ''
|
||||||
|
return repos
|
||||||
|
|
||||||
|
|
||||||
|
def set_repo_states(module, repo_ids, state):
|
||||||
|
module.run_command([DNF_BIN, 'config-manager', '--set-{0}'.format(state)] + repo_ids, check_rc=True)
|
||||||
|
|
||||||
|
|
||||||
|
def pack_repo_states_for_return(states):
|
||||||
|
enabled = []
|
||||||
|
disabled = []
|
||||||
|
for repo_id in states:
|
||||||
|
if states[repo_id] == 'enabled':
|
||||||
|
enabled.append(repo_id)
|
||||||
|
else:
|
||||||
|
disabled.append(repo_id)
|
||||||
|
|
||||||
|
# Sort for consistent results
|
||||||
|
enabled.sort()
|
||||||
|
disabled.sort()
|
||||||
|
|
||||||
|
return {'enabled': enabled, 'disabled': disabled}
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
module_args = dict(
|
||||||
|
name=dict(type='list', elements='str', required=False, default=[]),
|
||||||
|
state=dict(type='str', required=False, choices=['enabled', 'disabled'], default='enabled')
|
||||||
|
)
|
||||||
|
|
||||||
|
result = dict(
|
||||||
|
changed=False
|
||||||
|
)
|
||||||
|
|
||||||
|
module = AnsibleModule(
|
||||||
|
argument_spec=module_args,
|
||||||
|
supports_check_mode=True
|
||||||
|
)
|
||||||
|
|
||||||
|
if not os.path.exists(DNF_BIN):
|
||||||
|
module.fail_json(msg="%s was not found" % DNF_BIN)
|
||||||
|
|
||||||
|
repo_states = get_repo_states(module)
|
||||||
|
result['repo_states_pre'] = pack_repo_states_for_return(repo_states)
|
||||||
|
|
||||||
|
desired_repo_state = module.params['state']
|
||||||
|
names = module.params['name']
|
||||||
|
|
||||||
|
to_change = []
|
||||||
|
for repo_id in names:
|
||||||
|
if repo_id not in repo_states:
|
||||||
|
module.fail_json(msg="did not find repo with ID '{0}' in dnf repolist --all --verbose".format(repo_id))
|
||||||
|
if repo_states[repo_id] != desired_repo_state:
|
||||||
|
to_change.append(repo_id)
|
||||||
|
result['changed'] = len(to_change) > 0
|
||||||
|
result['changed_repos'] = to_change
|
||||||
|
|
||||||
|
if module.check_mode:
|
||||||
|
module.exit_json(**result)
|
||||||
|
|
||||||
|
if len(to_change) > 0:
|
||||||
|
set_repo_states(module, to_change, desired_repo_state)
|
||||||
|
|
||||||
|
repo_states_post = get_repo_states(module)
|
||||||
|
result['repo_states_post'] = pack_repo_states_for_return(repo_states_post)
|
||||||
|
|
||||||
|
for repo_id in to_change:
|
||||||
|
if repo_states_post[repo_id] != desired_repo_state:
|
||||||
|
module.fail_json(msg="dnf config-manager failed to make '{0}' {1}".format(repo_id, desired_repo_state))
|
||||||
|
|
||||||
|
module.exit_json(**result)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
402
tests/unit/plugins/modules/test_dnf_config_manager.py
Normal file
402
tests/unit/plugins/modules/test_dnf_config_manager.py
Normal file
|
@ -0,0 +1,402 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2023, Andrew Hyatt <andy@hyatt.xyz>
|
||||||
|
# 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
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
from ansible_collections.community.general.tests.unit.compat.mock import patch, call
|
||||||
|
from ansible_collections.community.general.plugins.modules import dnf_config_manager as dnf_config_manager_module
|
||||||
|
from ansible_collections.community.general.tests.unit.plugins.modules.utils import AnsibleExitJson, AnsibleFailJson, \
|
||||||
|
ModuleTestCase, set_module_args
|
||||||
|
|
||||||
|
# Return value on all-default arguments
|
||||||
|
mock_repolist_crb_enabled = """Loaded plugins: builddep, changelog, config-manager, copr, debug, debuginfo-install
|
||||||
|
DNF version: 4.14.0
|
||||||
|
cachedir: /var/cache/dnf
|
||||||
|
Last metadata expiration check: 1:20:49 ago on Fri 22 Dec 2023 06:05:13 PM UTC.
|
||||||
|
Repo-id : appstream
|
||||||
|
Repo-name : AlmaLinux 9 - AppStream
|
||||||
|
Repo-status : enabled
|
||||||
|
Repo-revision : 1703240474
|
||||||
|
Repo-updated : Fri 22 Dec 2023 10:21:14 AM UTC
|
||||||
|
Repo-pkgs : 5,897
|
||||||
|
Repo-available-pkgs: 5,728
|
||||||
|
Repo-size : 9.5 G
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/appstream
|
||||||
|
Repo-baseurl : http://mirror.cogentco.com/pub/linux/almalinux/9.3/AppStream/x86_64/os/ (9 more)
|
||||||
|
Repo-expire : 86,400 second(s) (last: Fri 22 Dec 2023 06:05:11 PM UTC)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-appstream.repo
|
||||||
|
|
||||||
|
Repo-id : appstream-debuginfo
|
||||||
|
Repo-name : AlmaLinux 9 - AppStream - Debug
|
||||||
|
Repo-status : disabled
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/appstream-debug
|
||||||
|
Repo-expire : 86,400 second(s) (last: unknown)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-appstream.repo
|
||||||
|
|
||||||
|
Repo-id : appstream-source
|
||||||
|
Repo-name : AlmaLinux 9 - AppStream - Source
|
||||||
|
Repo-status : disabled
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/appstream-source
|
||||||
|
Repo-expire : 86,400 second(s) (last: unknown)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-appstream.repo
|
||||||
|
|
||||||
|
Repo-id : baseos
|
||||||
|
Repo-name : AlmaLinux 9 - BaseOS
|
||||||
|
Repo-status : enabled
|
||||||
|
Repo-revision : 1703240561
|
||||||
|
Repo-updated : Fri 22 Dec 2023 10:22:41 AM UTC
|
||||||
|
Repo-pkgs : 1,244
|
||||||
|
Repo-available-pkgs: 1,244
|
||||||
|
Repo-size : 1.3 G
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/baseos
|
||||||
|
Repo-baseurl : http://mirror.cogentco.com/pub/linux/almalinux/9.3/BaseOS/x86_64/os/ (9 more)
|
||||||
|
Repo-expire : 86,400 second(s) (last: Fri 22 Dec 2023 06:05:11 PM UTC)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-baseos.repo
|
||||||
|
|
||||||
|
Repo-id : baseos-debuginfo
|
||||||
|
Repo-name : AlmaLinux 9 - BaseOS - Debug
|
||||||
|
Repo-status : disabled
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/baseos-debug
|
||||||
|
Repo-expire : 86,400 second(s) (last: unknown)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-baseos.repo
|
||||||
|
|
||||||
|
Repo-id : baseos-source
|
||||||
|
Repo-name : AlmaLinux 9 - BaseOS - Source
|
||||||
|
Repo-status : disabled
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/baseos-source
|
||||||
|
Repo-expire : 86,400 second(s) (last: unknown)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-baseos.repo
|
||||||
|
|
||||||
|
Repo-id : copr:copr.fedorainfracloud.org:uriesk:dracut-crypt-ssh
|
||||||
|
Repo-name : Copr repo for dracut-crypt-ssh owned by uriesk
|
||||||
|
Repo-status : enabled
|
||||||
|
Repo-revision : 1698291016
|
||||||
|
Repo-updated : Thu 26 Oct 2023 03:30:16 AM UTC
|
||||||
|
Repo-pkgs : 4
|
||||||
|
Repo-available-pkgs: 4
|
||||||
|
Repo-size : 102 k
|
||||||
|
Repo-baseurl : https://download.copr.fedorainfracloud.org/results/uriesk/dracut-crypt-ssh/epel-9-x86_64/
|
||||||
|
Repo-expire : 172,800 second(s) (last: Fri 22 Dec 2023 06:05:10 PM UTC)
|
||||||
|
Repo-filename : /etc/yum.repos.d/_copr:copr.fedorainfracloud.org:uriesk:dracut-crypt-ssh.repo
|
||||||
|
|
||||||
|
Repo-id : crb
|
||||||
|
Repo-name : AlmaLinux 9 - CRB
|
||||||
|
Repo-status : enabled
|
||||||
|
Repo-revision : 1703240590
|
||||||
|
Repo-updated : Fri 22 Dec 2023 10:23:10 AM UTC
|
||||||
|
Repo-pkgs : 1,730
|
||||||
|
Repo-available-pkgs: 1,727
|
||||||
|
Repo-size : 13 G
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/crb
|
||||||
|
Repo-baseurl : http://mirror.cogentco.com/pub/linux/almalinux/9.3/CRB/x86_64/os/ (9 more)
|
||||||
|
Repo-expire : 86,400 second(s) (last: Fri 22 Dec 2023 06:05:11 PM UTC)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-crb.repo
|
||||||
|
|
||||||
|
Repo-id : rpmfusion-nonfree-updates
|
||||||
|
Repo-name : RPM Fusion for EL 9 - Nonfree - Updates
|
||||||
|
Repo-status : enabled
|
||||||
|
Repo-revision : 1703248251
|
||||||
|
Repo-tags : binary-x86_64
|
||||||
|
Repo-updated : Fri 22 Dec 2023 12:30:53 PM UTC
|
||||||
|
Repo-pkgs : 65
|
||||||
|
Repo-available-pkgs: 65
|
||||||
|
Repo-size : 944 M
|
||||||
|
Repo-metalink : http://mirrors.rpmfusion.org/metalink?repo=nonfree-el-updates-released-9&arch=x86_64
|
||||||
|
Updated : Fri 22 Dec 2023 06:05:13 PM UTC
|
||||||
|
Repo-baseurl : http://uvermont.mm.fcix.net/rpmfusion/nonfree/el/updates/9/x86_64/ (33 more)
|
||||||
|
Repo-expire : 172,800 second(s) (last: Fri 22 Dec 2023 06:05:13 PM UTC)
|
||||||
|
Repo-filename : /etc/yum.repos.d/rpmfusion-nonfree-updates.repo
|
||||||
|
Total packages: 28,170
|
||||||
|
"""
|
||||||
|
|
||||||
|
mock_repolist_crb_disabled = """Loaded plugins: builddep, changelog, config-manager, copr, debug, debuginfo-install
|
||||||
|
DNF version: 4.14.0
|
||||||
|
cachedir: /var/cache/dnf
|
||||||
|
Last metadata expiration check: 1:20:49 ago on Fri 22 Dec 2023 06:05:13 PM UTC.
|
||||||
|
Repo-id : appstream
|
||||||
|
Repo-name : AlmaLinux 9 - AppStream
|
||||||
|
Repo-status : enabled
|
||||||
|
Repo-revision : 1703240474
|
||||||
|
Repo-updated : Fri 22 Dec 2023 10:21:14 AM UTC
|
||||||
|
Repo-pkgs : 5,897
|
||||||
|
Repo-available-pkgs: 5,728
|
||||||
|
Repo-size : 9.5 G
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/appstream
|
||||||
|
Repo-baseurl : http://mirror.cogentco.com/pub/linux/almalinux/9.3/AppStream/x86_64/os/ (9 more)
|
||||||
|
Repo-expire : 86,400 second(s) (last: Fri 22 Dec 2023 06:05:11 PM UTC)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-appstream.repo
|
||||||
|
|
||||||
|
Repo-id : appstream-debuginfo
|
||||||
|
Repo-name : AlmaLinux 9 - AppStream - Debug
|
||||||
|
Repo-status : disabled
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/appstream-debug
|
||||||
|
Repo-expire : 86,400 second(s) (last: unknown)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-appstream.repo
|
||||||
|
|
||||||
|
Repo-id : appstream-source
|
||||||
|
Repo-name : AlmaLinux 9 - AppStream - Source
|
||||||
|
Repo-status : disabled
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/appstream-source
|
||||||
|
Repo-expire : 86,400 second(s) (last: unknown)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-appstream.repo
|
||||||
|
|
||||||
|
Repo-id : baseos
|
||||||
|
Repo-name : AlmaLinux 9 - BaseOS
|
||||||
|
Repo-status : enabled
|
||||||
|
Repo-revision : 1703240561
|
||||||
|
Repo-updated : Fri 22 Dec 2023 10:22:41 AM UTC
|
||||||
|
Repo-pkgs : 1,244
|
||||||
|
Repo-available-pkgs: 1,244
|
||||||
|
Repo-size : 1.3 G
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/baseos
|
||||||
|
Repo-baseurl : http://mirror.cogentco.com/pub/linux/almalinux/9.3/BaseOS/x86_64/os/ (9 more)
|
||||||
|
Repo-expire : 86,400 second(s) (last: Fri 22 Dec 2023 06:05:11 PM UTC)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-baseos.repo
|
||||||
|
|
||||||
|
Repo-id : baseos-debuginfo
|
||||||
|
Repo-name : AlmaLinux 9 - BaseOS - Debug
|
||||||
|
Repo-status : disabled
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/baseos-debug
|
||||||
|
Repo-expire : 86,400 second(s) (last: unknown)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-baseos.repo
|
||||||
|
|
||||||
|
Repo-id : baseos-source
|
||||||
|
Repo-name : AlmaLinux 9 - BaseOS - Source
|
||||||
|
Repo-status : disabled
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/baseos-source
|
||||||
|
Repo-expire : 86,400 second(s) (last: unknown)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-baseos.repo
|
||||||
|
|
||||||
|
Repo-id : copr:copr.fedorainfracloud.org:uriesk:dracut-crypt-ssh
|
||||||
|
Repo-name : Copr repo for dracut-crypt-ssh owned by uriesk
|
||||||
|
Repo-status : enabled
|
||||||
|
Repo-revision : 1698291016
|
||||||
|
Repo-updated : Thu 26 Oct 2023 03:30:16 AM UTC
|
||||||
|
Repo-pkgs : 4
|
||||||
|
Repo-available-pkgs: 4
|
||||||
|
Repo-size : 102 k
|
||||||
|
Repo-baseurl : https://download.copr.fedorainfracloud.org/results/uriesk/dracut-crypt-ssh/epel-9-x86_64/
|
||||||
|
Repo-expire : 172,800 second(s) (last: Fri 22 Dec 2023 06:05:10 PM UTC)
|
||||||
|
Repo-filename : /etc/yum.repos.d/_copr:copr.fedorainfracloud.org:uriesk:dracut-crypt-ssh.repo
|
||||||
|
|
||||||
|
Repo-id : crb
|
||||||
|
Repo-name : AlmaLinux 9 - CRB
|
||||||
|
Repo-status : disabled
|
||||||
|
Repo-revision : 1703240590
|
||||||
|
Repo-updated : Fri 22 Dec 2023 10:23:10 AM UTC
|
||||||
|
Repo-pkgs : 1,730
|
||||||
|
Repo-available-pkgs: 1,727
|
||||||
|
Repo-size : 13 G
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/crb
|
||||||
|
Repo-baseurl : http://mirror.cogentco.com/pub/linux/almalinux/9.3/CRB/x86_64/os/ (9 more)
|
||||||
|
Repo-expire : 86,400 second(s) (last: Fri 22 Dec 2023 06:05:11 PM UTC)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-crb.repo
|
||||||
|
|
||||||
|
Repo-id : rpmfusion-nonfree-updates
|
||||||
|
Repo-name : RPM Fusion for EL 9 - Nonfree - Updates
|
||||||
|
Repo-status : enabled
|
||||||
|
Repo-revision : 1703248251
|
||||||
|
Repo-tags : binary-x86_64
|
||||||
|
Repo-updated : Fri 22 Dec 2023 12:30:53 PM UTC
|
||||||
|
Repo-pkgs : 65
|
||||||
|
Repo-available-pkgs: 65
|
||||||
|
Repo-size : 944 M
|
||||||
|
Repo-metalink : http://mirrors.rpmfusion.org/metalink?repo=nonfree-el-updates-released-9&arch=x86_64
|
||||||
|
Updated : Fri 22 Dec 2023 06:05:13 PM UTC
|
||||||
|
Repo-baseurl : http://uvermont.mm.fcix.net/rpmfusion/nonfree/el/updates/9/x86_64/ (33 more)
|
||||||
|
Repo-expire : 172,800 second(s) (last: Fri 22 Dec 2023 06:05:13 PM UTC)
|
||||||
|
Repo-filename : /etc/yum.repos.d/rpmfusion-nonfree-updates.repo
|
||||||
|
Total packages: 28,170
|
||||||
|
"""
|
||||||
|
|
||||||
|
mock_repolist_no_status = """Repo-id : appstream-debuginfo
|
||||||
|
Repo-name : AlmaLinux 9 - AppStream - Debug
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/appstream-debug
|
||||||
|
Repo-expire : 86,400 second(s) (last: unknown)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-appstream.repo
|
||||||
|
|
||||||
|
Repo-id : appstream-source
|
||||||
|
Repo-name : AlmaLinux 9 - AppStream - Source
|
||||||
|
Repo-status : disabled
|
||||||
|
Repo-mirrors : https://mirrors.almalinux.org/mirrorlist/9/appstream-source
|
||||||
|
Repo-expire : 86,400 second(s) (last: unknown)
|
||||||
|
Repo-filename : /etc/yum.repos.d/almalinux-appstream.repo
|
||||||
|
"""
|
||||||
|
|
||||||
|
mock_repolist_status_before_id = """
|
||||||
|
Repo-id : appstream-debuginfo
|
||||||
|
Repo-status : disabled
|
||||||
|
Repo-status : disabled
|
||||||
|
"""
|
||||||
|
|
||||||
|
expected_repo_states_crb_enabled = {'disabled': ['appstream-debuginfo',
|
||||||
|
'appstream-source',
|
||||||
|
'baseos-debuginfo',
|
||||||
|
'baseos-source'],
|
||||||
|
'enabled': ['appstream',
|
||||||
|
'baseos',
|
||||||
|
'copr:copr.fedorainfracloud.org:uriesk:dracut-crypt-ssh',
|
||||||
|
'crb',
|
||||||
|
'rpmfusion-nonfree-updates']}
|
||||||
|
|
||||||
|
expected_repo_states_crb_disabled = {'disabled': ['appstream-debuginfo',
|
||||||
|
'appstream-source',
|
||||||
|
'baseos-debuginfo',
|
||||||
|
'baseos-source',
|
||||||
|
'crb'],
|
||||||
|
'enabled': ['appstream',
|
||||||
|
'baseos',
|
||||||
|
'copr:copr.fedorainfracloud.org:uriesk:dracut-crypt-ssh',
|
||||||
|
'rpmfusion-nonfree-updates']}
|
||||||
|
|
||||||
|
call_get_repo_states = call(['/usr/bin/dnf', 'repolist', '--all', '--verbose'], check_rc=True)
|
||||||
|
call_disable_crb = call(['/usr/bin/dnf', 'config-manager', '--set-disabled', 'crb'], check_rc=True)
|
||||||
|
call_enable_crb = call(['/usr/bin/dnf', 'config-manager', '--set-enabled', 'crb'], check_rc=True)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDNFConfigManager(ModuleTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestDNFConfigManager, self).setUp()
|
||||||
|
self.mock_run_command = (patch('ansible.module_utils.basic.AnsibleModule.run_command'))
|
||||||
|
self.run_command = self.mock_run_command.start()
|
||||||
|
self.mock_path_exists = (patch('os.path.exists'))
|
||||||
|
self.path_exists = self.mock_path_exists.start()
|
||||||
|
self.path_exists.return_value = True
|
||||||
|
self.module = dnf_config_manager_module
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(TestDNFConfigManager, self).tearDown()
|
||||||
|
self.mock_run_command.stop()
|
||||||
|
self.mock_path_exists.stop()
|
||||||
|
|
||||||
|
def set_command_mock(self, execute_return=(0, '', ''), execute_side_effect=None):
|
||||||
|
self.run_command.reset_mock()
|
||||||
|
self.run_command.return_value = execute_return
|
||||||
|
self.run_command.side_effect = execute_side_effect
|
||||||
|
|
||||||
|
def execute_module(self, failed=False, changed=False):
|
||||||
|
if failed:
|
||||||
|
result = self.failed()
|
||||||
|
self.assertTrue(result['failed'])
|
||||||
|
else:
|
||||||
|
result = self.changed(changed)
|
||||||
|
self.assertEqual(result['changed'], changed)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def failed(self):
|
||||||
|
with self.assertRaises(AnsibleFailJson) as exc:
|
||||||
|
self.module.main()
|
||||||
|
|
||||||
|
result = exc.exception.args[0]
|
||||||
|
self.assertTrue(result['failed'])
|
||||||
|
return result
|
||||||
|
|
||||||
|
def changed(self, changed=False):
|
||||||
|
with self.assertRaises(AnsibleExitJson) as exc:
|
||||||
|
self.module.main()
|
||||||
|
|
||||||
|
result = exc.exception.args[0]
|
||||||
|
self.assertEqual(result['changed'], changed)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def test_get_repo_states(self):
|
||||||
|
set_module_args({})
|
||||||
|
self.set_command_mock(execute_return=(0, mock_repolist_crb_enabled, ''))
|
||||||
|
result = self.execute_module(changed=False)
|
||||||
|
self.assertEqual(result['repo_states_pre'], expected_repo_states_crb_enabled)
|
||||||
|
self.assertEqual(result['repo_states_post'], expected_repo_states_crb_enabled)
|
||||||
|
self.assertEqual(result['changed_repos'], [])
|
||||||
|
self.run_command.assert_has_calls(calls=[call_get_repo_states, call_get_repo_states], any_order=False)
|
||||||
|
|
||||||
|
def test_enable_disabled_repo(self):
|
||||||
|
set_module_args({
|
||||||
|
'name': ['crb'],
|
||||||
|
'state': 'enabled'
|
||||||
|
})
|
||||||
|
side_effects = [(0, mock_repolist_crb_disabled, ''), (0, '', ''), (0, mock_repolist_crb_enabled, '')]
|
||||||
|
self.set_command_mock(execute_side_effect=side_effects)
|
||||||
|
result = self.execute_module(changed=True)
|
||||||
|
self.assertEqual(result['repo_states_pre'], expected_repo_states_crb_disabled)
|
||||||
|
self.assertEqual(result['repo_states_post'], expected_repo_states_crb_enabled)
|
||||||
|
self.assertEqual(result['changed_repos'], ['crb'])
|
||||||
|
expected_calls = [call_get_repo_states, call_enable_crb, call_get_repo_states]
|
||||||
|
self.run_command.assert_has_calls(calls=expected_calls, any_order=False)
|
||||||
|
|
||||||
|
def test_enable_disabled_repo_check_mode(self):
|
||||||
|
set_module_args({
|
||||||
|
'name': ['crb'],
|
||||||
|
'state': 'enabled',
|
||||||
|
'_ansible_check_mode': True
|
||||||
|
})
|
||||||
|
side_effects = [(0, mock_repolist_crb_disabled, ''), (0, mock_repolist_crb_disabled, '')]
|
||||||
|
self.set_command_mock(execute_side_effect=side_effects)
|
||||||
|
result = self.execute_module(changed=True)
|
||||||
|
self.assertEqual(result['changed_repos'], ['crb'])
|
||||||
|
self.run_command.assert_has_calls(calls=[call_get_repo_states], any_order=False)
|
||||||
|
|
||||||
|
def test_disable_enabled_repo(self):
|
||||||
|
set_module_args({
|
||||||
|
'name': ['crb'],
|
||||||
|
'state': 'disabled'
|
||||||
|
})
|
||||||
|
side_effects = [(0, mock_repolist_crb_enabled, ''), (0, '', ''), (0, mock_repolist_crb_disabled, '')]
|
||||||
|
self.set_command_mock(execute_side_effect=side_effects)
|
||||||
|
result = self.execute_module(changed=True)
|
||||||
|
self.assertEqual(result['repo_states_pre'], expected_repo_states_crb_enabled)
|
||||||
|
self.assertEqual(result['repo_states_post'], expected_repo_states_crb_disabled)
|
||||||
|
self.assertEqual(result['changed_repos'], ['crb'])
|
||||||
|
expected_calls = [call_get_repo_states, call_disable_crb, call_get_repo_states]
|
||||||
|
self.run_command.assert_has_calls(calls=expected_calls, any_order=False)
|
||||||
|
|
||||||
|
def test_crb_already_enabled(self):
|
||||||
|
set_module_args({
|
||||||
|
'name': ['crb'],
|
||||||
|
'state': 'enabled'
|
||||||
|
})
|
||||||
|
side_effects = [(0, mock_repolist_crb_enabled, ''), (0, mock_repolist_crb_enabled, '')]
|
||||||
|
self.set_command_mock(execute_side_effect=side_effects)
|
||||||
|
result = self.execute_module(changed=False)
|
||||||
|
self.assertEqual(result['repo_states_pre'], expected_repo_states_crb_enabled)
|
||||||
|
self.assertEqual(result['repo_states_post'], expected_repo_states_crb_enabled)
|
||||||
|
self.assertEqual(result['changed_repos'], [])
|
||||||
|
self.run_command.assert_has_calls(calls=[call_get_repo_states, call_get_repo_states], any_order=False)
|
||||||
|
|
||||||
|
def test_get_repo_states_fail_no_status(self):
|
||||||
|
set_module_args({})
|
||||||
|
self.set_command_mock(execute_return=(0, mock_repolist_no_status, ''))
|
||||||
|
result = self.execute_module(failed=True)
|
||||||
|
self.assertEqual(result['msg'], 'dnf repolist parse failure: parsed another repo id before next status')
|
||||||
|
self.run_command.assert_has_calls(calls=[call_get_repo_states], any_order=False)
|
||||||
|
|
||||||
|
def test_get_repo_states_fail_status_before_id(self):
|
||||||
|
set_module_args({})
|
||||||
|
self.set_command_mock(execute_return=(0, mock_repolist_status_before_id, ''))
|
||||||
|
result = self.execute_module(failed=True)
|
||||||
|
self.assertEqual(result['msg'], 'dnf repolist parse failure: parsed status before repo id')
|
||||||
|
self.run_command.assert_has_calls(calls=[call_get_repo_states], any_order=False)
|
||||||
|
|
||||||
|
def test_failed__unknown_repo_id(self):
|
||||||
|
set_module_args({
|
||||||
|
'name': ['fake']
|
||||||
|
})
|
||||||
|
self.set_command_mock(execute_return=(0, mock_repolist_crb_disabled, ''))
|
||||||
|
result = self.execute_module(failed=True)
|
||||||
|
self.assertEqual(result['msg'], "did not find repo with ID 'fake' in dnf repolist --all --verbose")
|
||||||
|
self.run_command.assert_has_calls(calls=[call_get_repo_states], any_order=False)
|
||||||
|
|
||||||
|
def test_failed_state_change_ineffective(self):
|
||||||
|
set_module_args({
|
||||||
|
'name': ['crb'],
|
||||||
|
'state': 'enabled'
|
||||||
|
})
|
||||||
|
side_effects = [(0, mock_repolist_crb_disabled, ''), (0, '', ''), (0, mock_repolist_crb_disabled, '')]
|
||||||
|
self.set_command_mock(execute_side_effect=side_effects)
|
||||||
|
result = self.execute_module(failed=True)
|
||||||
|
self.assertEqual(result['msg'], "dnf config-manager failed to make 'crb' enabled")
|
||||||
|
expected_calls = [call_get_repo_states, call_enable_crb, call_get_repo_states]
|
||||||
|
self.run_command.assert_has_calls(calls=expected_calls, any_order=False)
|
Loading…
Reference in a new issue