summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberto Murillo Silva <alberto.murillo.silva@intel.com>2017-01-16 20:42:23 -0600
committerToshio Kuratomi <a.badger@gmail.com>2017-05-04 13:52:16 -0700
commit136a6eec9ede9e82fcc4d37821e84e653dcde29b (patch)
treec6c303e42bb3c21dc69ba7c18fe1dc0ee74285a0
parent02057f481b42ee32a14f8570cbffb7ca586d05be (diff)
downloadansible-136a6eec9ede9e82fcc4d37821e84e653dcde29b.tar.gz
dnf: Add autoremove option
This allow users to write better playbooks by replacing - shell: dnf autoremove -y with - dnf: autoremove=yes Fixes #18815 Signed-off-by: Alberto Murillo Silva <alberto.murillo.silva@intel.com>
-rw-r--r--lib/ansible/modules/packaging/os/dnf.py59
1 files changed, 52 insertions, 7 deletions
diff --git a/lib/ansible/modules/packaging/os/dnf.py b/lib/ansible/modules/packaging/os/dnf.py
index 797dc1c8f9..d49d7a6472 100644
--- a/lib/ansible/modules/packaging/os/dnf.py
+++ b/lib/ansible/modules/packaging/os/dnf.py
@@ -97,7 +97,16 @@ options:
version_added: "2.3"
default: "/"
-notes: []
+ autoremove:
+ description:
+ - If C(yes), removes all "leaf" packages from the system that were originally
+ installed as dependencies of user-installed packages but which are no longer
+ required by any such package. Should be used alone or when state is I(absent)
+ required: false
+ choices: [ "yes", "no" ]
+ version_added: "2.4"
+
+notes: ["autoremove requires dnf >= 2.0.1"]
# informational: requirements for nodes
requirements:
- "python >= 2.6"
@@ -144,12 +153,21 @@ EXAMPLES = '''
dnf:
name: '@Development tools'
state: present
+
+- name: Autoremove unneeded packages installed as dependencies
+ dnf:
+ autoremove: yes
+
+- name: Uninstall httpd but keep its dependencies
+ dnf:
+ name: httpd
+ state: absent
+ autoremove: no
'''
import os
try:
import dnf
- import dnf
import dnf.cli
import dnf.const
import dnf.exceptions
@@ -161,6 +179,7 @@ except ImportError:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import PY2
+from distutils.version import LooseVersion
def _ensure_dnf(module):
@@ -314,11 +333,18 @@ def _install_remote_rpms(base, filenames):
base.package_install(pkg)
-def ensure(module, base, state, names):
+def ensure(module, base, state, names, autoremove):
# Accumulate failures. Package management modules install what they can
# and fail with a message about what they can't.
failures = []
allow_erasing = False
+
+ # Autoremove is called alone
+ # Jump to remove path where base.autoremove() is run
+ if not names and autoremove is not None:
+ names = []
+ state = 'absent'
+
if names == ['*'] and state == 'latest':
base.upgrade_all()
else:
@@ -398,6 +424,9 @@ def ensure(module, base, state, names):
else:
# state == absent
+ if autoremove is not None:
+ base.conf.clean_requirements_on_remove = autoremove
+
if filenames:
module.fail_json(
msg="Cannot remove paths -- please specify package name.")
@@ -425,6 +454,9 @@ def ensure(module, base, state, names):
# packages
allow_erasing = True
+ if autoremove:
+ base.autoremove()
+
if not base.resolve(allow_erasing=allow_erasing):
if failures:
module.fail_json(msg='Failed to install some of the '
@@ -460,7 +492,6 @@ def main():
argument_spec=dict(
name=dict(aliases=['pkg'], type='list'),
state=dict(
- default='installed',
choices=[
'absent', 'present', 'installed', 'removed', 'latest']),
enablerepo=dict(type='list', default=[]),
@@ -469,14 +500,28 @@ def main():
conf_file=dict(default=None, type='path'),
disable_gpg_check=dict(default=False, type='bool'),
installroot=dict(default='/', type='path'),
+ autoremove=dict(type='bool'),
),
- required_one_of=[['name', 'list']],
- mutually_exclusive=[['name', 'list']],
+ required_one_of=[['name', 'list', 'autoremove']],
+ mutually_exclusive=[['name', 'list'], ['autoremove', 'list']],
supports_check_mode=True)
params = module.params
_ensure_dnf(module)
+ # Check if autoremove is called correctly
+ if params['autoremove'] is not None:
+ if LooseVersion(dnf.__version__) < LooseVersion('2.0.1'):
+ module.fail_json(msg="Autoremove requires dnf>=2.0.1. Current dnf version is %s" % dnf.__version__)
+ if params['state'] not in ["absent", None]:
+ module.fail_json(msg="Autoremove should be used alone or with state=absent")
+
+ # Set state as installed by default
+ # This is not set in AnsibleModule() because the following shouldn't happend
+ # - dnf: autoremove=yes state=installed
+ if params['state'] is None:
+ params['state'] = 'installed'
+
if params['list']:
base = _base(
module, params['conf_file'], params['disable_gpg_check'],
@@ -491,7 +536,7 @@ def main():
module, params['conf_file'], params['disable_gpg_check'],
params['disablerepo'], params['enablerepo'], params['installroot'])
- ensure(module, base, params['state'], params['name'])
+ ensure(module, base, params['state'], params['name'], params['autoremove'])
if __name__ == '__main__':