ansible-core 2.17.6__py3-none-any.whl → 2.18.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ansible-core might be problematic. Click here for more details.
- ansible/__main__.py +2 -17
- ansible/cli/__init__.py +3 -15
- ansible/cli/config.py +187 -24
- ansible/cli/console.py +1 -1
- ansible/cli/doc.py +38 -16
- ansible/cli/galaxy.py +3 -49
- ansible/cli/inventory.py +2 -2
- ansible/cli/pull.py +2 -2
- ansible/cli/scripts/ansible_connection_cli_stub.py +1 -10
- ansible/config/base.yml +127 -57
- ansible/config/manager.py +89 -11
- ansible/constants.py +32 -9
- ansible/errors/__init__.py +5 -0
- ansible/executor/interpreter_discovery.py +1 -1
- ansible/executor/play_iterator.py +16 -0
- ansible/executor/playbook_executor.py +1 -4
- ansible/executor/powershell/become_wrapper.ps1 +4 -5
- ansible/executor/powershell/bootstrap_wrapper.ps1 +2 -3
- ansible/executor/powershell/exec_wrapper.ps1 +1 -1
- ansible/executor/powershell/module_manifest.py +2 -2
- ansible/executor/task_executor.py +50 -39
- ansible/executor/task_queue_manager.py +1 -1
- ansible/executor/task_result.py +1 -1
- ansible/galaxy/api.py +3 -4
- ansible/galaxy/collection/__init__.py +21 -10
- ansible/galaxy/collection/concrete_artifact_manager.py +2 -2
- ansible/galaxy/collection/galaxy_api_proxy.py +10 -16
- ansible/galaxy/collection/gpg.py +17 -23
- ansible/galaxy/data/COPYING +7 -0
- ansible/galaxy/data/apb/Dockerfile.j2 +1 -0
- ansible/galaxy/data/apb/Makefile.j2 +1 -0
- ansible/galaxy/data/apb/README.md +7 -3
- ansible/galaxy/data/apb/apb.yml.j2 +1 -0
- ansible/galaxy/data/apb/defaults/main.yml.j2 +1 -0
- ansible/galaxy/data/apb/handlers/main.yml.j2 +1 -0
- ansible/galaxy/data/apb/meta/main.yml.j2 +1 -0
- ansible/galaxy/data/apb/playbooks/deprovision.yml.j2 +1 -0
- ansible/galaxy/data/apb/playbooks/provision.yml.j2 +1 -0
- ansible/galaxy/data/apb/tasks/main.yml.j2 +1 -0
- ansible/galaxy/data/apb/tests/ansible.cfg +1 -0
- ansible/galaxy/data/apb/tests/inventory +1 -0
- ansible/galaxy/data/apb/tests/test.yml.j2 +1 -0
- ansible/galaxy/data/apb/vars/main.yml.j2 +1 -0
- ansible/galaxy/data/collections_galaxy_meta.yml +1 -0
- ansible/galaxy/data/container/defaults/main.yml.j2 +1 -0
- ansible/galaxy/data/container/handlers/main.yml.j2 +1 -0
- ansible/galaxy/data/container/meta/container.yml.j2 +1 -0
- ansible/galaxy/data/container/meta/main.yml.j2 +1 -0
- ansible/galaxy/data/container/tasks/main.yml.j2 +1 -0
- ansible/galaxy/data/container/tests/ansible.cfg +1 -0
- ansible/galaxy/data/container/tests/inventory +1 -0
- ansible/galaxy/data/container/tests/test.yml.j2 +1 -0
- ansible/galaxy/data/container/vars/main.yml.j2 +1 -0
- ansible/galaxy/data/default/collection/README.md.j2 +1 -0
- ansible/galaxy/data/default/collection/galaxy.yml.j2 +1 -0
- ansible/galaxy/data/default/collection/meta/runtime.yml +1 -0
- ansible/galaxy/data/default/collection/plugins/README.md.j2 +1 -0
- ansible/galaxy/data/default/role/defaults/main.yml.j2 +1 -0
- ansible/galaxy/data/default/role/handlers/main.yml.j2 +1 -0
- ansible/galaxy/data/default/role/meta/main.yml.j2 +1 -0
- ansible/galaxy/data/default/role/tasks/main.yml.j2 +1 -0
- ansible/galaxy/data/default/role/tests/inventory +1 -0
- ansible/galaxy/data/default/role/tests/test.yml.j2 +1 -0
- ansible/galaxy/data/default/role/vars/main.yml.j2 +1 -0
- ansible/galaxy/data/network/cliconf_plugins/example.py.j2 +1 -0
- ansible/galaxy/data/network/defaults/main.yml.j2 +1 -0
- ansible/galaxy/data/network/library/example_command.py.j2 +1 -0
- ansible/galaxy/data/network/library/example_config.py.j2 +1 -0
- ansible/galaxy/data/network/library/example_facts.py.j2 +1 -0
- ansible/galaxy/data/network/meta/main.yml.j2 +1 -0
- ansible/galaxy/data/network/module_utils/example.py.j2 +1 -0
- ansible/galaxy/data/network/netconf_plugins/example.py.j2 +1 -0
- ansible/galaxy/data/network/tasks/main.yml.j2 +1 -0
- ansible/galaxy/data/network/terminal_plugins/example.py.j2 +1 -0
- ansible/galaxy/data/network/tests/inventory +1 -0
- ansible/galaxy/data/network/tests/test.yml.j2 +1 -0
- ansible/galaxy/data/network/vars/main.yml.j2 +1 -0
- ansible/galaxy/dependency_resolution/providers.py +3 -3
- ansible/galaxy/role.py +1 -1
- ansible/galaxy/token.py +20 -8
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +0 -0
- ansible/module_utils/_internal/_concurrent/__init__.py +0 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +28 -0
- ansible/module_utils/_internal/_concurrent/_futures.py +21 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +2 -2
- ansible/module_utils/basic.py +8 -8
- ansible/module_utils/common/collections.py +1 -1
- ansible/module_utils/common/file.py +0 -6
- ansible/module_utils/common/process.py +22 -9
- ansible/module_utils/common/text/converters.py +5 -8
- ansible/module_utils/common/text/formatters.py +20 -4
- ansible/module_utils/common/validation.py +33 -25
- ansible/module_utils/compat/paramiko.py +6 -1
- ansible/module_utils/compat/selinux.py +2 -2
- ansible/module_utils/connection.py +8 -24
- ansible/module_utils/csharp/Ansible.Become.cs +14 -25
- ansible/module_utils/csharp/Ansible.Process.cs +1 -1
- ansible/module_utils/distro/__init__.py +1 -1
- ansible/module_utils/distro/_distro.py +8 -4
- ansible/module_utils/facts/collector.py +2 -0
- ansible/module_utils/facts/default_collectors.py +3 -1
- ansible/module_utils/facts/hardware/aix.py +54 -52
- ansible/module_utils/facts/hardware/darwin.py +37 -34
- ansible/module_utils/facts/hardware/freebsd.py +55 -15
- ansible/module_utils/facts/hardware/hpux.py +3 -0
- ansible/module_utils/facts/hardware/linux.py +101 -57
- ansible/module_utils/facts/hardware/netbsd.py +3 -0
- ansible/module_utils/facts/hardware/openbsd.py +4 -1
- ansible/module_utils/facts/hardware/sunos.py +7 -1
- ansible/module_utils/facts/network/aix.py +16 -17
- ansible/module_utils/facts/network/fc_wwn.py +4 -1
- ansible/module_utils/facts/network/hpux.py +21 -4
- ansible/module_utils/facts/network/iscsi.py +7 -8
- ansible/module_utils/facts/network/linux.py +0 -2
- ansible/module_utils/facts/other/facter.py +9 -4
- ansible/module_utils/facts/other/ohai.py +5 -5
- ansible/module_utils/facts/packages.py +49 -7
- ansible/module_utils/facts/sysctl.py +33 -31
- ansible/module_utils/facts/system/distribution.py +1 -1
- ansible/module_utils/facts/system/local.py +12 -22
- ansible/module_utils/facts/system/service_mgr.py +3 -1
- ansible/module_utils/facts/system/systemd.py +47 -0
- ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
- ansible/module_utils/splitter.py +1 -1
- ansible/modules/add_host.py +1 -1
- ansible/modules/apt.py +43 -32
- ansible/modules/apt_key.py +6 -6
- ansible/modules/apt_repository.py +23 -14
- ansible/modules/assemble.py +7 -2
- ansible/modules/assert.py +4 -4
- ansible/modules/blockinfile.py +3 -6
- ansible/modules/command.py +1 -1
- ansible/modules/copy.py +4 -4
- ansible/modules/cron.py +13 -10
- ansible/modules/deb822_repository.py +16 -17
- ansible/modules/debconf.py +9 -9
- ansible/modules/debug.py +1 -1
- ansible/modules/dnf.py +79 -164
- ansible/modules/dnf5.py +54 -29
- ansible/modules/dpkg_selections.py +2 -2
- ansible/modules/expect.py +2 -2
- ansible/modules/fetch.py +2 -2
- ansible/modules/file.py +5 -3
- ansible/modules/find.py +40 -12
- ansible/modules/gather_facts.py +4 -2
- ansible/modules/get_url.py +29 -24
- ansible/modules/git.py +35 -35
- ansible/modules/group.py +71 -1
- ansible/modules/hostname.py +2 -4
- ansible/modules/include_vars.py +5 -5
- ansible/modules/iptables.py +13 -16
- ansible/modules/known_hosts.py +16 -13
- ansible/modules/lineinfile.py +1 -4
- ansible/modules/meta.py +6 -1
- ansible/modules/mount_facts.py +651 -0
- ansible/modules/package_facts.py +63 -80
- ansible/modules/pause.py +4 -3
- ansible/modules/pip.py +14 -14
- ansible/modules/replace.py +1 -4
- ansible/modules/rpm_key.py +31 -11
- ansible/modules/service.py +8 -8
- ansible/modules/service_facts.py +20 -5
- ansible/modules/set_stats.py +1 -1
- ansible/modules/setup.py +3 -3
- ansible/modules/stat.py +3 -3
- ansible/modules/subversion.py +1 -1
- ansible/modules/systemd.py +16 -10
- ansible/modules/systemd_service.py +16 -10
- ansible/modules/sysvinit.py +4 -4
- ansible/modules/unarchive.py +35 -22
- ansible/modules/uri.py +24 -18
- ansible/modules/user.py +145 -12
- ansible/modules/validate_argument_spec.py +3 -3
- ansible/modules/wait_for_connection.py +2 -1
- ansible/modules/yum_repository.py +136 -179
- ansible/parsing/dataloader.py +2 -2
- ansible/parsing/mod_args.py +11 -10
- ansible/parsing/vault/__init__.py +8 -3
- ansible/parsing/yaml/constructor.py +10 -8
- ansible/parsing/yaml/objects.py +1 -1
- ansible/playbook/base.py +12 -23
- ansible/playbook/helpers.py +4 -0
- ansible/playbook/loop_control.py +8 -0
- ansible/playbook/play.py +4 -22
- ansible/playbook/play_context.py +0 -16
- ansible/playbook/playbook_include.py +2 -2
- ansible/playbook/role/__init__.py +2 -2
- ansible/plugins/__init__.py +2 -0
- ansible/plugins/action/__init__.py +7 -9
- ansible/plugins/action/dnf.py +7 -5
- ansible/plugins/action/package.py +5 -4
- ansible/plugins/action/reboot.py +2 -2
- ansible/plugins/become/__init__.py +1 -1
- ansible/plugins/callback/__init__.py +44 -3
- ansible/plugins/callback/default.py +1 -1
- ansible/plugins/cliconf/__init__.py +1 -1
- ansible/plugins/connection/paramiko_ssh.py +2 -80
- ansible/plugins/connection/psrp.py +33 -82
- ansible/plugins/connection/ssh.py +0 -8
- ansible/plugins/connection/winrm.py +46 -1
- ansible/plugins/doc_fragments/connection_pipelining.py +2 -2
- ansible/plugins/doc_fragments/constructed.py +10 -10
- ansible/plugins/doc_fragments/default_callback.py +8 -8
- ansible/plugins/doc_fragments/files.py +5 -5
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +6 -6
- ansible/plugins/doc_fragments/return_common.py +1 -1
- ansible/plugins/doc_fragments/shell_common.py +2 -10
- ansible/plugins/doc_fragments/shell_windows.py +0 -9
- ansible/plugins/doc_fragments/url.py +2 -2
- ansible/plugins/doc_fragments/url_windows.py +4 -5
- ansible/plugins/doc_fragments/validate.py +1 -1
- ansible/plugins/filter/core.py +2 -0
- ansible/plugins/filter/human_to_bytes.yml +9 -0
- ansible/plugins/filter/password_hash.yml +1 -1
- ansible/plugins/filter/strftime.yml +1 -1
- ansible/plugins/filter/to_nice_json.yml +7 -3
- ansible/plugins/filter/to_uuid.yml +1 -1
- ansible/plugins/inventory/script.py +1 -1
- ansible/plugins/list.py +1 -1
- ansible/plugins/loader.py +0 -11
- ansible/plugins/lookup/config.py +1 -1
- ansible/plugins/lookup/csvfile.py +21 -9
- ansible/plugins/lookup/env.py +8 -9
- ansible/plugins/lookup/ini.py +10 -1
- ansible/plugins/lookup/random_choice.py +2 -2
- ansible/plugins/lookup/url.py +7 -2
- ansible/plugins/shell/__init__.py +15 -20
- ansible/plugins/shell/powershell.py +9 -6
- ansible/plugins/strategy/__init__.py +16 -7
- ansible/plugins/test/core.py +23 -1
- ansible/plugins/test/issubset.yml +1 -1
- ansible/plugins/test/subset.yml +1 -1
- ansible/plugins/test/timedout.yml +20 -0
- ansible/plugins/test/vault_encrypted.yml +6 -6
- ansible/plugins/test/vaulted_file.yml +19 -0
- ansible/release.py +2 -2
- ansible/template/__init__.py +3 -8
- ansible/utils/collection_loader/_collection_finder.py +23 -55
- ansible/utils/display.py +44 -31
- ansible/utils/jsonrpc.py +1 -1
- ansible/utils/listify.py +1 -5
- ansible/utils/path.py +3 -0
- ansible/utils/vars.py +18 -27
- ansible/vars/manager.py +7 -150
- ansible/vars/plugins.py +1 -1
- ansible_core-2.18.0.dist-info/Apache-License.txt +202 -0
- {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/METADATA +36 -23
- ansible_core-2.18.0.dist-info/MIT-license.txt +14 -0
- ansible_core-2.18.0.dist-info/PSF-license.txt +48 -0
- {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/RECORD +316 -311
- {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/entry_points.txt +1 -1
- ansible_core-2.18.0.dist-info/simplified_bsd.txt +8 -0
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +5 -4
- ansible_test/_data/completion/windows.txt +4 -4
- ansible_test/_data/requirements/ansible-test.txt +1 -2
- ansible_test/_data/requirements/constraints.txt +1 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.in +1 -1
- ansible_test/_data/requirements/sanity.changelog.txt +4 -4
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.import.txt +1 -1
- ansible_test/_data/requirements/sanity.integration-aliases.txt +1 -1
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +6 -8
- ansible_test/_data/requirements/sanity.runtime-metadata.txt +2 -2
- ansible_test/_data/requirements/sanity.validate-modules.txt +3 -3
- ansible_test/_data/requirements/sanity.yamllint.in +1 -0
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_internal/ansible_util.py +8 -35
- ansible_test/_internal/ci/azp.py +1 -1
- ansible_test/_internal/classification/__init__.py +0 -2
- ansible_test/_internal/cli/parsers/key_value_parsers.py +3 -0
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -1
- ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
- ansible_test/_internal/commands/integration/cloud/nios.py +1 -1
- ansible_test/_internal/commands/sanity/__init__.py +96 -19
- ansible_test/_internal/commands/sanity/pylint.py +20 -24
- ansible_test/_internal/completion.py +2 -0
- ansible_test/_internal/constants.py +0 -1
- ansible_test/_internal/coverage_util.py +1 -2
- ansible_test/_internal/docker_util.py +1 -1
- ansible_test/_internal/encoding.py +4 -4
- ansible_test/_internal/host_configs.py +10 -0
- ansible_test/_internal/host_profiles.py +9 -13
- ansible_test/_internal/pypi_proxy.py +1 -1
- ansible_test/_internal/python_requirements.py +5 -14
- ansible_test/_internal/timeout.py +1 -1
- ansible_test/_internal/util.py +40 -0
- ansible_test/_internal/util_common.py +5 -1
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.json +3 -1
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +6 -3
- ansible_test/_util/controller/sanity/code-smell/empty-init.json +0 -2
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +5 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +5 -0
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +5 -0
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +6 -0
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +6 -0
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -19
- ansible_test/_util/controller/sanity/shellcheck/exclude.txt +1 -0
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +67 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +27 -5
- ansible_test/_util/target/cli/ansible_test_cli_stub.py +0 -0
- ansible_test/_util/target/common/constants.py +2 -2
- ansible_test/_util/target/injector/python.py +5 -0
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +6 -0
- ansible_test/_util/target/sanity/import/importer.py +1 -1
- ansible_test/_util/target/setup/bootstrap.sh +6 -17
- ansible_test/_util/target/setup/requirements.py +18 -24
- ansible_test/config/config.yml +1 -1
- ansible_core-2.17.6.data/scripts/ansible-test +0 -44
- ansible_test/_data/requirements/sanity.mypy.in +0 -10
- ansible_test/_data/requirements/sanity.mypy.txt +0 -18
- ansible_test/_internal/commands/sanity/mypy.py +0 -274
- ansible_test/_util/controller/sanity/mypy/ansible-core.ini +0 -116
- ansible_test/_util/controller/sanity/mypy/ansible-test.ini +0 -27
- ansible_test/_util/controller/sanity/mypy/modules.ini +0 -92
- ansible_test/_util/controller/sanity/mypy/packaging.ini +0 -20
- {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/COPYING +0 -0
- {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/WHEEL +0 -0
- {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/top_level.txt +0 -0
ansible/modules/dnf.py
CHANGED
|
@@ -55,14 +55,14 @@ options:
|
|
|
55
55
|
state:
|
|
56
56
|
description:
|
|
57
57
|
- Whether to install (V(present), V(latest)), or remove (V(absent)) a package.
|
|
58
|
-
- Default is V(None), however in effect the default action is V(present) unless the O(autoremove)
|
|
59
|
-
|
|
58
|
+
- Default is V(None), however in effect the default action is V(present) unless the O(autoremove=true),
|
|
59
|
+
then V(absent) is inferred.
|
|
60
60
|
choices: ['absent', 'present', 'installed', 'removed', 'latest']
|
|
61
61
|
type: str
|
|
62
62
|
|
|
63
63
|
enablerepo:
|
|
64
64
|
description:
|
|
65
|
-
-
|
|
65
|
+
- C(Repoid) of repositories to enable for the install/update operation.
|
|
66
66
|
These repos will not persist beyond the transaction.
|
|
67
67
|
When specifying multiple repos, separate them with a ",".
|
|
68
68
|
type: list
|
|
@@ -71,9 +71,9 @@ options:
|
|
|
71
71
|
|
|
72
72
|
disablerepo:
|
|
73
73
|
description:
|
|
74
|
-
-
|
|
74
|
+
- C(Repoid) of repositories to disable for the install/update operation.
|
|
75
75
|
These repos will not persist beyond the transaction.
|
|
76
|
-
When specifying multiple repos, separate them with a
|
|
76
|
+
When specifying multiple repos, separate them with a C(,).
|
|
77
77
|
type: list
|
|
78
78
|
elements: str
|
|
79
79
|
default: []
|
|
@@ -86,7 +86,7 @@ options:
|
|
|
86
86
|
disable_gpg_check:
|
|
87
87
|
description:
|
|
88
88
|
- Whether to disable the GPG checking of signatures of packages being
|
|
89
|
-
installed. Has an effect only if O(state
|
|
89
|
+
installed. Has an effect only if O(state=present) or O(state=latest).
|
|
90
90
|
- This setting affects packages installed from a repository as well as
|
|
91
91
|
"local" packages installed from the filesystem or a URL.
|
|
92
92
|
type: bool
|
|
@@ -111,13 +111,13 @@ options:
|
|
|
111
111
|
description:
|
|
112
112
|
- If V(true), removes all "leaf" packages from the system that were originally
|
|
113
113
|
installed as dependencies of user-installed packages but which are no longer
|
|
114
|
-
required by any such package. Should be used alone or when O(state
|
|
114
|
+
required by any such package. Should be used alone or when O(state=absent).
|
|
115
115
|
type: bool
|
|
116
116
|
default: "no"
|
|
117
117
|
version_added: "2.4"
|
|
118
118
|
exclude:
|
|
119
119
|
description:
|
|
120
|
-
- Package name(s) to exclude when state=present, or latest. This can be a
|
|
120
|
+
- Package name(s) to exclude when O(state=present), or latest. This can be a
|
|
121
121
|
list or a comma separated string.
|
|
122
122
|
version_added: "2.7"
|
|
123
123
|
type: list
|
|
@@ -126,14 +126,14 @@ options:
|
|
|
126
126
|
skip_broken:
|
|
127
127
|
description:
|
|
128
128
|
- Skip all unavailable packages or packages with broken dependencies
|
|
129
|
-
without raising an error. Equivalent to passing the --skip-broken option.
|
|
129
|
+
without raising an error. Equivalent to passing the C(--skip-broken) option.
|
|
130
130
|
type: bool
|
|
131
131
|
default: "no"
|
|
132
132
|
version_added: "2.7"
|
|
133
133
|
update_cache:
|
|
134
134
|
description:
|
|
135
135
|
- Force dnf to check if cache is out of date and redownload if needed.
|
|
136
|
-
Has an effect only if O(state
|
|
136
|
+
Has an effect only if O(state=present) or O(state=latest).
|
|
137
137
|
type: bool
|
|
138
138
|
default: "no"
|
|
139
139
|
aliases: [ expire-cache ]
|
|
@@ -141,7 +141,7 @@ options:
|
|
|
141
141
|
update_only:
|
|
142
142
|
description:
|
|
143
143
|
- When using latest, only update installed packages. Do not install packages.
|
|
144
|
-
- Has an effect only if O(state)
|
|
144
|
+
- Has an effect only if O(state=present) or O(state=latest).
|
|
145
145
|
default: "no"
|
|
146
146
|
type: bool
|
|
147
147
|
version_added: "2.7"
|
|
@@ -161,7 +161,7 @@ options:
|
|
|
161
161
|
version_added: "2.7"
|
|
162
162
|
enable_plugin:
|
|
163
163
|
description:
|
|
164
|
-
-
|
|
164
|
+
- C(Plugin) name to enable for the install/update operation.
|
|
165
165
|
The enabled plugin will not persist beyond the transaction.
|
|
166
166
|
version_added: "2.7"
|
|
167
167
|
type: list
|
|
@@ -169,7 +169,7 @@ options:
|
|
|
169
169
|
default: []
|
|
170
170
|
disable_plugin:
|
|
171
171
|
description:
|
|
172
|
-
-
|
|
172
|
+
- C(Plugin) name to disable for the install/update operation.
|
|
173
173
|
The disabled plugins will not persist beyond the transaction.
|
|
174
174
|
version_added: "2.7"
|
|
175
175
|
type: list
|
|
@@ -179,13 +179,14 @@ options:
|
|
|
179
179
|
description:
|
|
180
180
|
- Disable the excludes defined in DNF config files.
|
|
181
181
|
- If set to V(all), disables all excludes.
|
|
182
|
-
- If set to V(main), disable excludes defined in [main] in dnf.conf.
|
|
182
|
+
- If set to V(main), disable excludes defined in C([main]) in C(dnf.conf).
|
|
183
183
|
- If set to V(repoid), disable excludes defined for given repo id.
|
|
184
184
|
version_added: "2.7"
|
|
185
185
|
type: str
|
|
186
186
|
validate_certs:
|
|
187
187
|
description:
|
|
188
|
-
- This only applies if using a https url as the source of the rpm.
|
|
188
|
+
- This only applies if using a https url as the source of the rpm. For example, for localinstall.
|
|
189
|
+
If set to V(false), the SSL certificates will not be validated.
|
|
189
190
|
- This should only set to V(false) used on personally controlled sites using self-signed certificates as it avoids verifying the source site.
|
|
190
191
|
type: bool
|
|
191
192
|
default: "yes"
|
|
@@ -201,7 +202,7 @@ options:
|
|
|
201
202
|
description:
|
|
202
203
|
- Specify if the named package and version is allowed to downgrade
|
|
203
204
|
a maybe already installed higher version of that package.
|
|
204
|
-
Note that setting allow_downgrade=
|
|
205
|
+
Note that setting O(allow_downgrade=true) can make this module
|
|
205
206
|
behave in a non-idempotent way. The task could end up with a set
|
|
206
207
|
of packages that does not match the complete list of specified
|
|
207
208
|
packages to install (because dependencies between the downgraded
|
|
@@ -244,7 +245,7 @@ options:
|
|
|
244
245
|
version_added: "2.8"
|
|
245
246
|
allowerasing:
|
|
246
247
|
description:
|
|
247
|
-
- If V(true) it allows
|
|
248
|
+
- If V(true) it allows erasing of installed packages to resolve dependencies.
|
|
248
249
|
required: false
|
|
249
250
|
type: bool
|
|
250
251
|
default: "no"
|
|
@@ -288,20 +289,18 @@ attributes:
|
|
|
288
289
|
platform:
|
|
289
290
|
platforms: rhel
|
|
290
291
|
notes:
|
|
291
|
-
- When used with a C(loop:) each package will be processed individually, it is much more efficient to pass the list directly to the
|
|
292
|
+
- When used with a C(loop:) each package will be processed individually, it is much more efficient to pass the list directly to the O(name) option.
|
|
292
293
|
- Group removal doesn't work if the group was installed with Ansible because
|
|
293
294
|
upstream dnf's API doesn't properly mark groups as installed, therefore upon
|
|
294
295
|
removal the module is unable to detect that the group is installed
|
|
295
|
-
(https://bugzilla.redhat.com/show_bug.cgi?id=1620324)
|
|
296
|
+
U(https://bugzilla.redhat.com/show_bug.cgi?id=1620324).
|
|
296
297
|
- While O(use_backend=yum) and the ability to call the action plugin as
|
|
297
298
|
M(ansible.builtin.yum) are provided for syntax compatibility, the YUM
|
|
298
299
|
backend was removed in ansible-core 2.17 because the required libraries are
|
|
299
300
|
not available for any supported version of Python. If you rely on this
|
|
300
301
|
functionality, use an older version of Ansible.
|
|
301
302
|
requirements:
|
|
302
|
-
-
|
|
303
|
-
- python-dnf
|
|
304
|
-
- for the autoremove option you need dnf >= 2.0.1"
|
|
303
|
+
- python3-dnf
|
|
305
304
|
author:
|
|
306
305
|
- Igor Gnatenko (@ignatenkobrain) <i.gnatenko.brain@gmail.com>
|
|
307
306
|
- Cristian van Ee (@DJMuggs) <cristian at cvee.org>
|
|
@@ -402,7 +401,6 @@ import sys
|
|
|
402
401
|
|
|
403
402
|
from ansible.module_utils.common.text.converters import to_native, to_text
|
|
404
403
|
from ansible.module_utils.urls import fetch_file
|
|
405
|
-
from ansible.module_utils.compat.version import LooseVersion
|
|
406
404
|
|
|
407
405
|
from ansible.module_utils.basic import AnsibleModule
|
|
408
406
|
from ansible.module_utils.common.locale import get_best_parsable_locale
|
|
@@ -428,11 +426,7 @@ class DnfModule(YumDnf):
|
|
|
428
426
|
|
|
429
427
|
self._ensure_dnf()
|
|
430
428
|
self.pkg_mgr_name = "dnf"
|
|
431
|
-
|
|
432
|
-
try:
|
|
433
|
-
self.with_modules = dnf.base.WITH_MODULES
|
|
434
|
-
except AttributeError:
|
|
435
|
-
self.with_modules = False
|
|
429
|
+
self.with_modules = dnf.base.WITH_MODULES
|
|
436
430
|
|
|
437
431
|
def _sanitize_dnf_error_msg_install(self, spec, error):
|
|
438
432
|
"""
|
|
@@ -447,22 +441,6 @@ class DnfModule(YumDnf):
|
|
|
447
441
|
|
|
448
442
|
return error
|
|
449
443
|
|
|
450
|
-
def _sanitize_dnf_error_msg_remove(self, spec, error):
|
|
451
|
-
"""
|
|
452
|
-
For unhandled dnf.exceptions.Error scenarios, there are certain error
|
|
453
|
-
messages we want to ignore in a removal scenario as known benign
|
|
454
|
-
failures. Do that here.
|
|
455
|
-
"""
|
|
456
|
-
if (
|
|
457
|
-
'no package matched' in to_native(error) or
|
|
458
|
-
'No match for argument:' in to_native(error)
|
|
459
|
-
):
|
|
460
|
-
return (False, "{0} is not installed".format(spec))
|
|
461
|
-
|
|
462
|
-
# Return value is tuple of:
|
|
463
|
-
# ("Is this actually a failure?", "Error Message")
|
|
464
|
-
return (True, error)
|
|
465
|
-
|
|
466
444
|
def _package_dict(self, package):
|
|
467
445
|
"""Return a dictionary of information for the package."""
|
|
468
446
|
# NOTE: This no longer contains the 'dnfstate' field because it is
|
|
@@ -511,7 +489,6 @@ class DnfModule(YumDnf):
|
|
|
511
489
|
|
|
512
490
|
system_interpreters = ['/usr/libexec/platform-python',
|
|
513
491
|
'/usr/bin/python3',
|
|
514
|
-
'/usr/bin/python2',
|
|
515
492
|
'/usr/bin/python']
|
|
516
493
|
|
|
517
494
|
if not has_respawned():
|
|
@@ -526,7 +503,7 @@ class DnfModule(YumDnf):
|
|
|
526
503
|
# done all we can do, something is just broken (auto-install isn't useful anymore with respawn, so it was removed)
|
|
527
504
|
self.module.fail_json(
|
|
528
505
|
msg="Could not import the dnf python module using {0} ({1}). "
|
|
529
|
-
"Please install `python3-dnf`
|
|
506
|
+
"Please install `python3-dnf` package or ensure you have specified the "
|
|
530
507
|
"correct ansible_python_interpreter. (attempted {2})"
|
|
531
508
|
.format(sys.executable, sys.version.replace('\n', ''), system_interpreters),
|
|
532
509
|
results=[]
|
|
@@ -603,6 +580,11 @@ class DnfModule(YumDnf):
|
|
|
603
580
|
# setting this to an empty string instead of None appears to mimic the DNF CLI behavior
|
|
604
581
|
conf.substitutions['releasever'] = ''
|
|
605
582
|
|
|
583
|
+
# Honor installroot for dnf directories
|
|
584
|
+
# This will also perform variable substitutions in the paths
|
|
585
|
+
for opt in ('cachedir', 'logdir', 'persistdir'):
|
|
586
|
+
conf.prepend_installroot(opt)
|
|
587
|
+
|
|
606
588
|
# Set skip_broken (in dnf this is strict=0)
|
|
607
589
|
if self.skip_broken:
|
|
608
590
|
conf.strict = 0
|
|
@@ -653,22 +635,14 @@ class DnfModule(YumDnf):
|
|
|
653
635
|
"""Return a fully configured dnf Base object."""
|
|
654
636
|
base = dnf.Base()
|
|
655
637
|
self._configure_base(base, conf_file, disable_gpg_check, installroot, sslverify)
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
pass
|
|
662
|
-
try:
|
|
663
|
-
base.init_plugins(set(self.disable_plugin), set(self.enable_plugin))
|
|
664
|
-
base.pre_configure_plugins()
|
|
665
|
-
except AttributeError:
|
|
666
|
-
pass # older versions of dnf didn't require this and don't have these methods
|
|
638
|
+
|
|
639
|
+
base.setup_loggers()
|
|
640
|
+
base.init_plugins(set(self.disable_plugin), set(self.enable_plugin))
|
|
641
|
+
base.pre_configure_plugins()
|
|
642
|
+
|
|
667
643
|
self._specify_repositories(base, disablerepo, enablerepo)
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
except AttributeError:
|
|
671
|
-
pass # older versions of dnf didn't require this and don't have these methods
|
|
644
|
+
|
|
645
|
+
base.configure_plugins()
|
|
672
646
|
|
|
673
647
|
try:
|
|
674
648
|
if self.update_cache:
|
|
@@ -743,18 +717,25 @@ class DnfModule(YumDnf):
|
|
|
743
717
|
else:
|
|
744
718
|
return bool(installed_query)
|
|
745
719
|
|
|
746
|
-
def _is_newer_version_installed(self,
|
|
720
|
+
def _is_newer_version_installed(self, pkg_spec):
|
|
747
721
|
try:
|
|
748
|
-
if isinstance(
|
|
749
|
-
|
|
722
|
+
if isinstance(pkg_spec, dnf.package.Package):
|
|
723
|
+
installed = sorted(self.base.sack.query().installed().filter(name=pkg_spec.name, arch=pkg_spec.arch))[-1]
|
|
724
|
+
return installed.evr_gt(pkg_spec)
|
|
750
725
|
else:
|
|
751
|
-
available =
|
|
752
|
-
|
|
753
|
-
)
|
|
754
|
-
|
|
726
|
+
available = dnf.subject.Subject(pkg_spec).get_best_query(sack=self.base.sack).available()
|
|
727
|
+
installed = self.base.sack.query().installed().filter(name=available[0].name)
|
|
728
|
+
for arch in sorted(set(p.arch for p in installed)): # select only from already-installed arches for this case
|
|
729
|
+
installed_pkg = sorted(installed.filter(arch=arch))[-1]
|
|
730
|
+
try:
|
|
731
|
+
available_pkg = sorted(available.filter(arch=arch))[-1]
|
|
732
|
+
except IndexError:
|
|
733
|
+
continue # nothing currently available for this arch; keep going
|
|
734
|
+
if installed_pkg.evr_gt(available_pkg):
|
|
735
|
+
return True
|
|
736
|
+
return False
|
|
755
737
|
except IndexError:
|
|
756
738
|
return False
|
|
757
|
-
return installed > available
|
|
758
739
|
|
|
759
740
|
def _mark_package_install(self, pkg_spec, upgrade=False):
|
|
760
741
|
"""Mark the package for install."""
|
|
@@ -813,16 +794,13 @@ class DnfModule(YumDnf):
|
|
|
813
794
|
"results": []
|
|
814
795
|
}
|
|
815
796
|
except dnf.exceptions.Error as e:
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
'rc': 1,
|
|
824
|
-
"results": []
|
|
825
|
-
}
|
|
797
|
+
return {
|
|
798
|
+
'failed': True,
|
|
799
|
+
'msg': "Unknown Error occurred for package {0}.".format(pkg_spec),
|
|
800
|
+
'failure': " ".join((pkg_spec, to_native(e))),
|
|
801
|
+
'rc': 1,
|
|
802
|
+
"results": []
|
|
803
|
+
}
|
|
826
804
|
|
|
827
805
|
return {'failed': False, 'msg': msg, 'failure': '', 'rc': 0}
|
|
828
806
|
|
|
@@ -886,36 +864,20 @@ class DnfModule(YumDnf):
|
|
|
886
864
|
return not_installed
|
|
887
865
|
|
|
888
866
|
def _install_remote_rpms(self, filenames):
|
|
889
|
-
|
|
890
|
-
pkgs =
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
for
|
|
895
|
-
|
|
896
|
-
except IOError as e:
|
|
897
|
-
if to_text("Can not load RPM file") in to_text(e):
|
|
898
|
-
self.module.fail_json(
|
|
899
|
-
msg="Error occurred attempting remote rpm install of package: {0}. {1}".format(filename, to_native(e)),
|
|
900
|
-
results=[],
|
|
901
|
-
rc=1,
|
|
902
|
-
)
|
|
903
|
-
if self.update_only:
|
|
904
|
-
self._update_only(pkgs)
|
|
905
|
-
else:
|
|
906
|
-
for pkg in pkgs:
|
|
907
|
-
try:
|
|
908
|
-
if self._is_newer_version_installed(pkg):
|
|
909
|
-
if self.allow_downgrade:
|
|
910
|
-
self.base.package_install(pkg, strict=self.base.conf.strict)
|
|
911
|
-
else:
|
|
867
|
+
try:
|
|
868
|
+
pkgs = self.base.add_remote_rpms(filenames)
|
|
869
|
+
if self.update_only:
|
|
870
|
+
self._update_only(pkgs)
|
|
871
|
+
else:
|
|
872
|
+
for pkg in pkgs:
|
|
873
|
+
if not (self._is_newer_version_installed(pkg) and not self.allow_downgrade):
|
|
912
874
|
self.base.package_install(pkg, strict=self.base.conf.strict)
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
875
|
+
except Exception as e:
|
|
876
|
+
self.module.fail_json(
|
|
877
|
+
msg="Error occurred attempting remote rpm operation: {0}".format(to_native(e)),
|
|
878
|
+
results=[],
|
|
879
|
+
rc=1,
|
|
880
|
+
)
|
|
919
881
|
|
|
920
882
|
def _is_module_installed(self, module_spec):
|
|
921
883
|
if self.with_modules:
|
|
@@ -932,7 +894,7 @@ class DnfModule(YumDnf):
|
|
|
932
894
|
else:
|
|
933
895
|
return True # No stream provided, but module found
|
|
934
896
|
|
|
935
|
-
return False # seems like a
|
|
897
|
+
return False # seems like a logical default
|
|
936
898
|
|
|
937
899
|
def ensure(self):
|
|
938
900
|
|
|
@@ -1136,14 +1098,6 @@ class DnfModule(YumDnf):
|
|
|
1136
1098
|
except dnf.exceptions.CompsError:
|
|
1137
1099
|
# Group is already uninstalled.
|
|
1138
1100
|
pass
|
|
1139
|
-
except AttributeError:
|
|
1140
|
-
# Group either isn't installed or wasn't marked installed at install time
|
|
1141
|
-
# because of DNF bug
|
|
1142
|
-
#
|
|
1143
|
-
# This is necessary until the upstream dnf API bug is fixed where installing
|
|
1144
|
-
# a group via the dnf API doesn't actually mark the group as installed
|
|
1145
|
-
# https://bugzilla.redhat.com/show_bug.cgi?id=1620324
|
|
1146
|
-
pass
|
|
1147
1101
|
|
|
1148
1102
|
for environment in environments:
|
|
1149
1103
|
try:
|
|
@@ -1152,25 +1106,11 @@ class DnfModule(YumDnf):
|
|
|
1152
1106
|
# Environment is already uninstalled.
|
|
1153
1107
|
pass
|
|
1154
1108
|
|
|
1155
|
-
installed = self.base.sack.query().installed()
|
|
1156
1109
|
for pkg_spec in pkg_specs:
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
except dnf.exceptions.MarkingError as e:
|
|
1162
|
-
is_failure, handled_remove_error = self._sanitize_dnf_error_msg_remove(pkg_spec, to_native(e))
|
|
1163
|
-
if is_failure:
|
|
1164
|
-
failure_response['failures'].append('{0} - {1}'.format(pkg_spec, to_native(e)))
|
|
1165
|
-
else:
|
|
1166
|
-
response['results'].append(handled_remove_error)
|
|
1167
|
-
continue
|
|
1168
|
-
|
|
1169
|
-
installed_pkg = dnf.subject.Subject(pkg_spec).get_best_query(
|
|
1170
|
-
sack=self.base.sack).installed().run()
|
|
1171
|
-
|
|
1172
|
-
for pkg in installed_pkg:
|
|
1173
|
-
self.base.remove(str(pkg))
|
|
1110
|
+
try:
|
|
1111
|
+
self.base.remove(pkg_spec)
|
|
1112
|
+
except dnf.exceptions.MarkingError as e:
|
|
1113
|
+
response['results'].append(f"{e.value}: {pkg_spec}")
|
|
1174
1114
|
|
|
1175
1115
|
# Like the dnf CLI we want to allow recursive removal of dependent
|
|
1176
1116
|
# packages
|
|
@@ -1224,10 +1164,8 @@ class DnfModule(YumDnf):
|
|
|
1224
1164
|
|
|
1225
1165
|
self.base.download_packages(self.base.transaction.install_set)
|
|
1226
1166
|
except dnf.exceptions.DownloadError as e:
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
results=[],
|
|
1230
|
-
)
|
|
1167
|
+
failure_response['msg'] = "Failed to download packages: {0}".format(to_native(e))
|
|
1168
|
+
self.module.fail_json(**failure_response)
|
|
1231
1169
|
|
|
1232
1170
|
# Validate GPG. This is NOT done in dnf.Base (it's done in the
|
|
1233
1171
|
# upstream CLI subclass of dnf.Base)
|
|
@@ -1268,33 +1206,10 @@ class DnfModule(YumDnf):
|
|
|
1268
1206
|
failure_response['msg'] = "Depsolve Error occurred: {0}".format(to_native(e))
|
|
1269
1207
|
self.module.fail_json(**failure_response)
|
|
1270
1208
|
except dnf.exceptions.Error as e:
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
response['results'].append("Package already installed: {0}".format(to_native(e)))
|
|
1274
|
-
self.module.exit_json(**response)
|
|
1275
|
-
else:
|
|
1276
|
-
failure_response['msg'] = "Unknown Error occurred: {0}".format(to_native(e))
|
|
1277
|
-
self.module.fail_json(**failure_response)
|
|
1209
|
+
failure_response['msg'] = "Unknown Error occurred: {0}".format(to_native(e))
|
|
1210
|
+
self.module.fail_json(**failure_response)
|
|
1278
1211
|
|
|
1279
1212
|
def run(self):
|
|
1280
|
-
"""The main function."""
|
|
1281
|
-
|
|
1282
|
-
# Check if autoremove is called correctly
|
|
1283
|
-
if self.autoremove:
|
|
1284
|
-
if LooseVersion(dnf.__version__) < LooseVersion('2.0.1'):
|
|
1285
|
-
self.module.fail_json(
|
|
1286
|
-
msg="Autoremove requires dnf>=2.0.1. Current dnf version is %s" % dnf.__version__,
|
|
1287
|
-
results=[],
|
|
1288
|
-
)
|
|
1289
|
-
|
|
1290
|
-
# Check if download_dir is called correctly
|
|
1291
|
-
if self.download_dir:
|
|
1292
|
-
if LooseVersion(dnf.__version__) < LooseVersion('2.6.2'):
|
|
1293
|
-
self.module.fail_json(
|
|
1294
|
-
msg="download_dir requires dnf>=2.6.2. Current dnf version is %s" % dnf.__version__,
|
|
1295
|
-
results=[],
|
|
1296
|
-
)
|
|
1297
|
-
|
|
1298
1213
|
if self.update_cache and not self.names and not self.list:
|
|
1299
1214
|
self.base = self._base(
|
|
1300
1215
|
self.conf_file, self.disable_gpg_check, self.disablerepo,
|
ansible/modules/dnf5.py
CHANGED
|
@@ -17,7 +17,7 @@ options:
|
|
|
17
17
|
name:
|
|
18
18
|
description:
|
|
19
19
|
- "A package name or package specifier with version, like C(name-1.0).
|
|
20
|
-
When using state=latest, this can be
|
|
20
|
+
When using O(state=latest), this can be C(*) which means run: C(dnf -y update).
|
|
21
21
|
You can also pass a url or a local path to an rpm file.
|
|
22
22
|
To operate on several packages this can accept a comma separated string of packages or a list of packages."
|
|
23
23
|
- Comparison operators for package version are valid here C(>), C(<), C(>=), C(<=). Example - C(name >= 1.0).
|
|
@@ -37,15 +37,15 @@ options:
|
|
|
37
37
|
state:
|
|
38
38
|
description:
|
|
39
39
|
- Whether to install (V(present), V(latest)), or remove (V(absent)) a package.
|
|
40
|
-
- Default is V(None), however in effect the default action is V(present) unless the
|
|
41
|
-
|
|
40
|
+
- Default is V(None), however in effect the default action is V(present) unless the O(autoremove=true),
|
|
41
|
+
then V(absent) is inferred.
|
|
42
42
|
choices: ['absent', 'present', 'installed', 'removed', 'latest']
|
|
43
43
|
type: str
|
|
44
44
|
enablerepo:
|
|
45
45
|
description:
|
|
46
46
|
- I(Repoid) of repositories to enable for the install/update operation.
|
|
47
47
|
These repos will not persist beyond the transaction.
|
|
48
|
-
When specifying multiple repos, separate them with a
|
|
48
|
+
When specifying multiple repos, separate them with a C(,).
|
|
49
49
|
type: list
|
|
50
50
|
elements: str
|
|
51
51
|
default: []
|
|
@@ -53,7 +53,7 @@ options:
|
|
|
53
53
|
description:
|
|
54
54
|
- I(Repoid) of repositories to disable for the install/update operation.
|
|
55
55
|
These repos will not persist beyond the transaction.
|
|
56
|
-
When specifying multiple repos, separate them with a
|
|
56
|
+
When specifying multiple repos, separate them with a C(,).
|
|
57
57
|
type: list
|
|
58
58
|
elements: str
|
|
59
59
|
default: []
|
|
@@ -84,12 +84,12 @@ options:
|
|
|
84
84
|
description:
|
|
85
85
|
- If V(true), removes all "leaf" packages from the system that were originally
|
|
86
86
|
installed as dependencies of user-installed packages but which are no longer
|
|
87
|
-
required by any such package. Should be used alone or when O(state
|
|
87
|
+
required by any such package. Should be used alone or when O(state=absent).
|
|
88
88
|
type: bool
|
|
89
89
|
default: "no"
|
|
90
90
|
exclude:
|
|
91
91
|
description:
|
|
92
|
-
- Package name(s) to exclude when state=present
|
|
92
|
+
- Package name(s) to exclude when O(state=present) or O(state=latest). This can be a
|
|
93
93
|
list or a comma separated string.
|
|
94
94
|
type: list
|
|
95
95
|
elements: str
|
|
@@ -97,20 +97,20 @@ options:
|
|
|
97
97
|
skip_broken:
|
|
98
98
|
description:
|
|
99
99
|
- Skip all unavailable packages or packages with broken dependencies
|
|
100
|
-
without raising an error. Equivalent to passing the --skip-broken option.
|
|
100
|
+
without raising an error. Equivalent to passing the C(--skip-broken) option.
|
|
101
101
|
type: bool
|
|
102
102
|
default: "no"
|
|
103
103
|
update_cache:
|
|
104
104
|
description:
|
|
105
105
|
- Force dnf to check if cache is out of date and redownload if needed.
|
|
106
|
-
Has an effect only if O(state
|
|
106
|
+
Has an effect only if O(state=present) or O(state=latest).
|
|
107
107
|
type: bool
|
|
108
108
|
default: "no"
|
|
109
109
|
aliases: [ expire-cache ]
|
|
110
110
|
update_only:
|
|
111
111
|
description:
|
|
112
112
|
- When using latest, only update installed packages. Do not install packages.
|
|
113
|
-
- Has an effect only if O(state)
|
|
113
|
+
- Has an effect only if O(state=present) or O(state=latest).
|
|
114
114
|
default: "no"
|
|
115
115
|
type: bool
|
|
116
116
|
security:
|
|
@@ -127,17 +127,19 @@ options:
|
|
|
127
127
|
type: bool
|
|
128
128
|
enable_plugin:
|
|
129
129
|
description:
|
|
130
|
-
- This is currently a no-op as dnf5 itself does not implement this feature.
|
|
131
130
|
- I(Plugin) name to enable for the install/update operation.
|
|
132
131
|
The enabled plugin will not persist beyond the transaction.
|
|
132
|
+
- O(disable_plugin) takes precedence in case a plugin is listed in both O(enable_plugin) and O(disable_plugin).
|
|
133
|
+
- Requires python3-libdnf5 5.2.0.0+.
|
|
133
134
|
type: list
|
|
134
135
|
elements: str
|
|
135
136
|
default: []
|
|
136
137
|
disable_plugin:
|
|
137
138
|
description:
|
|
138
|
-
- This is currently a no-op as dnf5 itself does not implement this feature.
|
|
139
139
|
- I(Plugin) name to disable for the install/update operation.
|
|
140
140
|
The disabled plugins will not persist beyond the transaction.
|
|
141
|
+
- O(disable_plugin) takes precedence in case a plugin is listed in both O(enable_plugin) and O(disable_plugin).
|
|
142
|
+
- Requires python3-libdnf5 5.2.0.0+.
|
|
141
143
|
type: list
|
|
142
144
|
default: []
|
|
143
145
|
elements: str
|
|
@@ -145,7 +147,7 @@ options:
|
|
|
145
147
|
description:
|
|
146
148
|
- Disable the excludes defined in DNF config files.
|
|
147
149
|
- If set to V(all), disables all excludes.
|
|
148
|
-
- If set to V(main), disable excludes defined in [main] in dnf.conf.
|
|
150
|
+
- If set to V(main), disable excludes defined in C([main]) in C(dnf.conf).
|
|
149
151
|
- If set to V(repoid), disable excludes defined for given repo id.
|
|
150
152
|
type: str
|
|
151
153
|
validate_certs:
|
|
@@ -164,7 +166,7 @@ options:
|
|
|
164
166
|
description:
|
|
165
167
|
- Specify if the named package and version is allowed to downgrade
|
|
166
168
|
a maybe already installed higher version of that package.
|
|
167
|
-
Note that setting allow_downgrade=
|
|
169
|
+
Note that setting O(allow_downgrade=true) can make this module
|
|
168
170
|
behave in a non-idempotent way. The task could end up with a set
|
|
169
171
|
of packages that does not match the complete list of specified
|
|
170
172
|
packages to install (because dependencies between the downgraded
|
|
@@ -243,7 +245,6 @@ attributes:
|
|
|
243
245
|
platform:
|
|
244
246
|
platforms: rhel
|
|
245
247
|
requirements:
|
|
246
|
-
- "python3"
|
|
247
248
|
- "python3-libdnf5"
|
|
248
249
|
version_added: 2.15
|
|
249
250
|
"""
|
|
@@ -448,6 +449,29 @@ class Dnf5Module(YumDnf):
|
|
|
448
449
|
|
|
449
450
|
self.pkg_mgr_name = "dnf5"
|
|
450
451
|
|
|
452
|
+
def fail_on_non_existing_plugins(self, base):
|
|
453
|
+
# https://github.com/rpm-software-management/dnf5/issues/1460
|
|
454
|
+
try:
|
|
455
|
+
plugin_names = [p.get_name() for p in base.get_plugins_info()]
|
|
456
|
+
except AttributeError:
|
|
457
|
+
# plugins functionality requires python3-libdnf5 5.2.0.0+
|
|
458
|
+
# silently ignore here, the module will fail later when
|
|
459
|
+
# base.enable_disable_plugins is attempted to be used if
|
|
460
|
+
# user specifies enable_plugin/disable_plugin
|
|
461
|
+
return
|
|
462
|
+
|
|
463
|
+
msg = []
|
|
464
|
+
if enable_unmatched := set(self.enable_plugin).difference(plugin_names):
|
|
465
|
+
msg.append(
|
|
466
|
+
f"No matches were found for the following plugin name patterns while enabling libdnf5 plugins: {', '.join(enable_unmatched)}."
|
|
467
|
+
)
|
|
468
|
+
if disable_unmatched := set(self.disable_plugin).difference(plugin_names):
|
|
469
|
+
msg.append(
|
|
470
|
+
f"No matches were found for the following plugin name patterns while disabling libdnf5 plugins: {', '.join(disable_unmatched)}."
|
|
471
|
+
)
|
|
472
|
+
if msg:
|
|
473
|
+
self.module.fail_json(msg=" ".join(msg))
|
|
474
|
+
|
|
451
475
|
def _ensure_dnf(self):
|
|
452
476
|
locale = get_best_parsable_locale(self.module)
|
|
453
477
|
os.environ["LC_ALL"] = os.environ["LC_MESSAGES"] = locale
|
|
@@ -466,7 +490,6 @@ class Dnf5Module(YumDnf):
|
|
|
466
490
|
system_interpreters = [
|
|
467
491
|
"/usr/libexec/platform-python",
|
|
468
492
|
"/usr/bin/python3",
|
|
469
|
-
"/usr/bin/python2",
|
|
470
493
|
"/usr/bin/python",
|
|
471
494
|
]
|
|
472
495
|
|
|
@@ -490,12 +513,6 @@ class Dnf5Module(YumDnf):
|
|
|
490
513
|
)
|
|
491
514
|
|
|
492
515
|
def run(self):
|
|
493
|
-
if sys.version_info.major < 3:
|
|
494
|
-
self.module.fail_json(
|
|
495
|
-
msg="The dnf5 module requires Python 3.",
|
|
496
|
-
failures=[],
|
|
497
|
-
rc=1,
|
|
498
|
-
)
|
|
499
516
|
if not self.list and not self.download_only and os.geteuid() != 0:
|
|
500
517
|
self.module.fail_json(
|
|
501
518
|
msg="This command has to be run under the root user.",
|
|
@@ -503,13 +520,6 @@ class Dnf5Module(YumDnf):
|
|
|
503
520
|
rc=1,
|
|
504
521
|
)
|
|
505
522
|
|
|
506
|
-
if self.enable_plugin or self.disable_plugin:
|
|
507
|
-
self.module.fail_json(
|
|
508
|
-
msg="enable_plugin and disable_plugin options are not yet implemented in DNF5",
|
|
509
|
-
failures=[],
|
|
510
|
-
rc=1,
|
|
511
|
-
)
|
|
512
|
-
|
|
513
523
|
base = libdnf5.base.Base()
|
|
514
524
|
conf = base.get_config()
|
|
515
525
|
|
|
@@ -552,8 +562,23 @@ class Dnf5Module(YumDnf):
|
|
|
552
562
|
if self.download_dir:
|
|
553
563
|
conf.destdir = self.download_dir
|
|
554
564
|
|
|
565
|
+
if self.enable_plugin:
|
|
566
|
+
try:
|
|
567
|
+
base.enable_disable_plugins(self.enable_plugin, True)
|
|
568
|
+
except AttributeError:
|
|
569
|
+
self.module.fail_json(msg="'enable_plugin' requires python3-libdnf5 5.2.0.0+")
|
|
570
|
+
|
|
571
|
+
if self.disable_plugin:
|
|
572
|
+
try:
|
|
573
|
+
base.enable_disable_plugins(self.disable_plugin, False)
|
|
574
|
+
except AttributeError:
|
|
575
|
+
self.module.fail_json(msg="'disable_plugin' requires python3-libdnf5 5.2.0.0+")
|
|
576
|
+
|
|
555
577
|
base.setup()
|
|
556
578
|
|
|
579
|
+
# https://github.com/rpm-software-management/dnf5/issues/1460
|
|
580
|
+
self.fail_on_non_existing_plugins(base)
|
|
581
|
+
|
|
557
582
|
log_router = base.get_logger()
|
|
558
583
|
global_logger = libdnf5.logger.GlobalLogger()
|
|
559
584
|
global_logger.set(log_router.get(), libdnf5.logger.Logger.Level_DEBUG)
|