Repository: ansible/ansible

Issue:
Empty groups trip "could not match supplied host pattern" warning
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
core

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.4.2.0
  config file = /root/ansible/ansible.cfg
  configured module search path = [u'/root/ansible/library']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Aug  4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
```

##### CONFIGURATION
N/A

##### OS / ENVIRONMENT
N/A

##### SUMMARY

The new 2.4 [warning](https://github.com/ansible/ansible/blob/devel/lib/ansible/inventory/manager.py#L545) on misspelled groups is quite noisy. There is no distinction made between an empty group and a misspelled one. Having ansible generate a warning about them on every run is not helpful and confuses our users. They are defined, and they are defined to be empty.


##### STEPS TO REPRODUCE

Any empty group used as a host pattern in a playbook.

```
- name: Tier 3 (Re)start NG applications
  hosts: ng-app-tier-3
  roles: [ng-app-instance-condrestart]

- name: Tier 4 (Re)start NG applications
  hosts: ng-app-tier-4
  roles: [ng-app-instance-condrestart]

- name: Tier 5 (Re)start NG applications
  hosts: ng-app-tier-5
  roles: [ng-app-instance-condrestart]
```


##### EXPECTED RESULTS

No warnings emitted for defined but empty groups.

##### ACTUAL RESULTS

<!--- Paste verbatim command output between quotes below -->
```
$ ansible-playbook site-ng.yml --list-hosts
 [WARNING]: Could not match supplied host pattern, ignoring: ng-app-tier-3

 [WARNING]: Could not match supplied host pattern, ignoring: ng-app-tier-6

 [WARNING]: Could not match supplied host pattern, ignoring: ng-app-tier-7

  play #17 (ng-app-tier-3): Tier 3 (Re)start NG applications	TAGS: []
    pattern: [u'ng-app-tier-3']
    hosts (0):

  play #18 (ng-app-tier-4): Tier 4 (Re)start NG applications	TAGS: []
    pattern: [u'ng-app-tier-4']
    hosts (12):
      ...snip

  play #19 (ng-app-tier-5): Tier 5 (Re)start NG applications	TAGS: []
    pattern: [u'ng-app-tier-5']
    hosts (98):
      ...snip

  play #20 (ng-app-tier-6): Tier 6 (Re)start NG applications	TAGS: []
    pattern: [u'ng-app-tier-6']
    hosts (0):

  play #21 (ng-app-tier-7): Tier 7 (Re)start NG applications	TAGS: []
    pattern: [u'ng-app-tier-7']
    hosts (0):
```



Discussion:
For what it's worth, I think the misspell detection is good. We've had that happen to us. But we definitely have groups that are empty in one inventory and not another (for instance our blue/green stacks are not fully fleshed out in pre-production environments).

I don't have any good suggestions to addressing this. Maybe a play level `empty_pattern_okay` flag? I dunno.
Also raised at https://github.com/ansible/ansible/issues/36306
I'm also hit by this. I'm using a `group_by` play to split hosts between a `foreman_managed` and `foreman_unmanaged` group. When I limit my play to *just* hosts that aren't managed by Foreman, I see this error.

```
# site.yml
- hosts: all
  tasks:
    - name: Assign foreman_managed / foreman_unmanaged groups
      group_by:
        key: foreman_{{ 'managed' if foreman is defined and foreman['managed'] else 'unmanaged' }}

- hosts: foreman_managed
  roles:
    - foreman_managed
```

For a host that winds up in `foreman_unmanaged`, I see the following output.

```
$ awx-cli job launch -J 'Apply Site' --limit abauer.desk --monitor
------Starting Standard Out Stream------
Identity added: /tmp/awx_980_Ry8OcM/credential_4 (/tmp/awx_980_Ry8OcM/credential_4)
SSH password:
SUDO password[defaults to SSH password]:

PLAY [all] *********************************************************************


TASK [Gathering Facts] *********************************************************
ok: [abauer.desk]

PLAY [all] *********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [abauer.desk]

TASK [Assign foreman_managed / foreman_unmanaged groups] ***********************
ok: [abauer.desk]
 [WARNING]: Could not match supplied host pattern, ignoring: foreman_managed


PLAY [foreman_managed] *********************************************************
skipping: no hosts matched
```

So long as there's at least one host that goes to `foreman_managed`, this warning doesn't appear.

I hope there comes to be an elegant way to avoid this, though none come easily to mind. Obviously it's not easy to walk all of the logic routes to try and generate the empty groups for all possible outcomes in the inventory. Maybe a way to suppress the warnings for particular groups or for particular plays is the best that can be done.
I'm also in favor of the option to silence this warning.

I have a single playbook with multiple plays that are intended to import the correct role depending on which group a host is in. So it is normal behaviour for only 1 out of 3 of the plays to match hosts.

I structured the playbook this way because if I have one play that conditionally imports the roles, then I either trip over #31751 or #18594

Resolving patch:
diff --git a/lib/ansible/inventory/manager.py b/lib/ansible/inventory/manager.py
--- a/lib/ansible/inventory/manager.py
+++ b/lib/ansible/inventory/manager.py
@@ -544,8 +544,10 @@ def _enumerate_matches(self, pattern):
             if implicit:
                 results.append(implicit)
 
-        if not results and pattern != 'all':
+        # Display warning if specified host pattern did not match any groups or hosts
+        if not results and not matching_groups and pattern != 'all':
             display.warning("Could not match supplied host pattern, ignoring: %s" % pattern)
+
         return results
 
     def list_hosts(self, pattern="all"):


Test patch: