Repository: ansible/ansible

Issue:
Ansible doesn't give an error when using a non existent group in a playbook
Issue Type:  Bug Report
Ansible Version: ansible 2.0.0 / 1.9.2

Steps To Reproduce:
Use `- hosts: group1:group2:group3:!group4` in any playbook. And as long as one group exists and matches one host, the play will run with no error.

Expected Results:
ansible-playbook .... : "Error: <group> doesn't exist"

Actual Results:
Playbooks are run anyway.



Discussion:
It's not entirely clear what you mean by "Use a group" here. I tried a play with `- hosts: foobar` and got the expected `skipping: no hosts matched` message.

I haven't tested everything, but in my case it is:

`- hosts: existing_group:!not_existing_one`

And i'm running the playbooks with `ansible-playbook -C`.

I think that as long as one host matches, the play will run and there will be no warning.

Not really something that is expected to e an error, as the hosts: stanza is usd to 'filter' hosts from the inventory. If you use non-existing groups, it actually means it can't find anything (be it hosts or groups) to filter on, so the end result is it doesn't match those hosts (or doesn't match that to-be-excluded-group) and doesn't return (or exclude) hosts, yielding an empty set of play hosts.

Keep in mind that as how this filtering happens on several levels, e.g. `ansible-playbook --limit`, which actually means when filtering out `hosts:` on a play, it doesn't know the original full set of hosts anymore, and can't distinguish between hosts/groups that were previously filtered out, and hosts/groups that plainly don't exist.

At least that is how it currently works. I agree this might sometimes give unexpected results when having a typo. For example you need to run a play, and absolutely need to filter out some hosts, that filtering will just silently fail if you mistype the exclusion...

On a more general level, I occasionaly had use cases where it would be helpfull to be able to access the full original inventory at times. So this might be a thing to keep in mind when redesigning the Inventory (cc @jimi-c @bcoca @abadger)

I think I understand the technical part (aka that's how YYY works), but I don't see any use case where I would want ansible not to ensure that the inclusion/exclusion of a group of hosts/host is possible according to the inventory.


Resolving patch:
diff --git a/lib/ansible/inventory/__init__.py b/lib/ansible/inventory/__init__.py
--- a/lib/ansible/inventory/__init__.py
+++ b/lib/ansible/inventory/__init__.py
@@ -480,18 +480,26 @@ def __append_host_to_results(host):
                     results.append(host)
 
         groups = self.get_groups()
+        matched = False
         for group in groups.values():
             if self._match(group.name, pattern):
+                matched = True
                 for host in group.get_hosts():
                     __append_host_to_results(host)
             else:
                 matching_hosts = self._match_list(group.get_hosts(), 'name', pattern)
-                for host in matching_hosts:
-                    __append_host_to_results(host)
+                if matching_hosts:
+                    matched = True
+                    for host in matching_hosts:
+                        __append_host_to_results(host)
 
         if pattern in C.LOCALHOST and len(results) == 0:
             new_host = self._create_implicit_localhost(pattern)
             results.append(new_host)
+            matched = True
+
+        if not matched:
+            display.warning("Could not match supplied host pattern, ignoring: %s" %  pattern)
         return results
 
     def _create_implicit_localhost(self, pattern):


Test patch: