Blob Blame History Raw
diff -uNr vanilla/lib/ansible/modules/extras/packaging/os/dnf.py ansible-2.2.0.0/lib/ansible/modules/extras/packaging/os/dnf.py
--- vanilla/lib/ansible/modules/extras/packaging/os/dnf.py	2016-10-31 20:43:38.000000000 -0700
+++ ansible-2.2.0.0/lib/ansible/modules/extras/packaging/os/dnf.py	2016-11-04 10:27:21.501410357 -0700
@@ -179,7 +179,7 @@
     base = dnf.Base()
     _configure_base(module, base, conf_file, disable_gpg_check)
     _specify_repositories(base, disablerepo, enablerepo)
-    base.fill_sack()
+    base.fill_sack(load_system_repo='auto')
     return base
 
 
@@ -256,6 +256,9 @@
 
 
 def ensure(module, base, state, names):
+    # Accumulate failures.  Package management modules install what they can
+    # and fail with a message about what they can't.
+    failures = []
     allow_erasing = False
     if names == ['*'] and state == 'latest':
         base.upgrade_all()
@@ -264,34 +267,70 @@
         if group_specs:
             base.read_comps()
 
+        pkg_specs = [p.strip() for p in pkg_specs]
+        filenames = [f.strip() for f in filenames]
         groups = []
-        for group_spec in group_specs:
+        environments = []
+        for group_spec in (g.strip() for g in group_specs):
             group = base.comps.group_by_pattern(group_spec)
             if group:
                 groups.append(group)
             else:
-                module.fail_json(
-                    msg="No group {} available.".format(group_spec))
+                environment = base.comps.environment_by_pattern(group_spec)
+                if environment:
+                    environments.append(environment.id)
+                else:
+                    module.fail_json(
+                        msg="No group {} available.".format(group_spec))
 
         if state in ['installed', 'present']:
             # Install files.
-            _install_remote_rpms(base, (f.strip() for f in filenames))
+            _install_remote_rpms(base, filenames)
+
             # Install groups.
-            for group in (g.strip() for g in groups):
-                base.group_install(group, const.GROUP_PACKAGE_TYPES)
+            for group in groups:
+                try:
+                    base.group_install(group, const.GROUP_PACKAGE_TYPES)
+                except exceptions.Error as e:
+                    # In dnf 2.0 if all the mandatory packages in a group do
+                    # not install, an error is raised.  We want to capture
+                    # this but still install as much as possible.
+                    failures.append((group, e))
+
+            for environment in environments:
+                try:
+                    base.environment_install(environment, const.GROUP_PACKAGE_TYPES)
+                except exceptions.Error as e:
+                    failures.append((group, e))
+
             # Install packages.
-            for pkg_spec in (p.strip() for p in pkg_specs):
+            for pkg_spec in pkg_specs:
                 _mark_package_install(module, base, pkg_spec)
 
         elif state == 'latest':
             # "latest" is same as "installed" for filenames.
             _install_remote_rpms(base, filenames)
+
             for group in groups:
                 try:
-                    base.group_upgrade(group)
-                except exceptions.CompsError:
-                    # If not already installed, try to install.
-                    base.group_install(group, const.GROUP_PACKAGE_TYPES)
+                    try:
+                        base.group_upgrade(group)
+                    except exceptions.CompsError:
+                        # If not already installed, try to install.
+                        base.group_install(group, const.GROUP_PACKAGE_TYPES)
+                except exceptions.Error as e:
+                    failures.append((group, e))
+
+            for environment in environments:
+                try:
+                    try:
+                        base.environment_upgrade(environment)
+                    except exceptions.CompsError:
+                        # If not already installed, try to install.
+                        base.environment_install(group, const.GROUP_PACKAGE_TYPES)
+                except exceptions.Error as e:
+                    failures.append((group, e))
+
             for pkg_spec in pkg_specs:
                 # best effort causes to install the latest package
                 # even if not previously installed
@@ -304,22 +343,41 @@
                 module.fail_json(
                     msg="Cannot remove paths -- please specify package name.")
 
-            installed = base.sack.query().installed()
             for group in groups:
-                if installed.filter(name=group.name):
+                try:
                     base.group_remove(group)
+                except dnf.exceptions.CompsError:
+                    # Group is already uninstalled.
+                    pass
+
+            for envioronment in environments:
+                try:
+                    base.environment_remove(environment)
+                except dnf.exceptions.CompsError:
+                    # Environment is already uninstalled.
+                    pass
+
+            installed = base.sack.query().installed()
             for pkg_spec in pkg_specs:
                 if installed.filter(name=pkg_spec):
                     base.remove(pkg_spec)
+
             # Like the dnf CLI we want to allow recursive removal of dependent
             # packages
             allow_erasing = True
 
     if not base.resolve(allow_erasing=allow_erasing):
+        if failures:
+            module.fail_json(msg='Failed to install some of the specified packages',
+                    failures=failures)
         module.exit_json(msg="Nothing to do")
     else:
         if module.check_mode:
+            if failures:
+                module.fail_json(msg='Failed to install some of the specified packages',
+                        failures=failures)
             module.exit_json(changed=True)
+
         base.download_packages(base.transaction.install_set)
         base.do_transaction()
         response = {'changed': True, 'results': []}
@@ -328,6 +386,9 @@
         for package in base.transaction.remove_set:
             response['results'].append("Removed: {0}".format(package))
 
+        if failures:
+            module.fail_json(msg='Failed to install some of the specified packages',
+                    failures=failures)
         module.exit_json(**response)