Specified inventory, host pattern and/or --limit leaves us with no hosts to target

Hello -
I’m seeing the noted error in some, but not all, cases

ERROR! Specified inventory, host pattern and/or --limit leaves us with no hosts to target.

Its consistent on which of my workflow jobs it occurs, all the playbooks (both ones that succeed and ones that fail) use the same patterns.

All playbooks have this

---
- hosts: "{{ buildgroup }}"
  gather_facts: false

and buildgroup is an extra_var that is passed in (via AAP or with --extra-vars)

The workflow exists largely to split targets up into various groupings (DataCenters, Domains, Environments, OSes) and leverage different credentials. All of those playbooks are invoked with limits like :&DC1:&Ubunut:&Internal.

The oddity is that a few of the playbooks will consistently fail with the noted error, while others (using the same targeting) will consistently pass with an output like

skipping: no hosts matched

The only deviation I can find is that one of the playbooks that consistently skips (instead of fails) has its limit option set as &DC1 (without the leading :). This playbook behaves as expected consistently, but so do several others that do have the leading :.

Does anyone have any advice on how I can start digging into this oddity? Even running with verbosity turned all the way to 5, I am not getting any useful messages to help me isolate (and then correct) the differences here.

Thanks in advance

This error occurs if inventory parsed contains more than 0 hosts, and if the limit provided doesn’t match a host (for example, if it only matches an empty group). I would start by debugging the inventory, and making sure all limits should result in matching at least 1 host.

The hosts keyword also accepts a pattern, so if you want to ignore a pattern might match no hosts and just see skipping: no hosts matched, that could be another option.

This is suspicious:

:&DC1:&Ubunut:&Internal

Shouldn’t it be:
DC1:&Ubuntu:&Internal?

So that there is a first group after which the refinement is done?

I know what the error is saying. I don’t know why it happens on some-but-not-all of my plays

With this workflow, there is a very good chance that some plays won’t have any hosts that match. That’s kind of the point. What I am trying to sort out is how to differentiate “there is nothing to do” and “there was something to do, and it failed”

Again, most of my plays do this as expect but some do not. I’m trying to tease out the difference.

The intention is for the {{ buildgroup }} to be the starting group, and then be refined from there. What I am trying to do (and mostly succeeding, but with the noted errors) is say "all the hosts in {{ buildgroup }} and are in the DC1, Ubuntu, and Internal groups.

And the filtering is working as expected (hosts have the correct jobs run, and don’t run when they should not). What I’m not getting are useful statuses at the end. The workflow shows failed in cases where “there were not hosts to operate on” for some plays.

You haven’t shared anything about your inventory, so I can’t guess from no context. But that’s where I’d start digging to debug this issue.

With this workflow, there is a very good chance that some plays won’t have any hosts that match. That’s kind of the point.

That is considered a broken limit. I remembered that this issue has tripped up others in the past, specifically for empty groups Applying limit switch with an empty inventory group causes error not warning? · Issue #77510 · ansible/ansible · GitHub which is why I point it out. I opened a PR to turn it into a warning Warn instead of error if --limit matches groups but no hosts by s-hertel · Pull Request #77512 · ansible/ansible · GitHub, but it was declined.

Here’s a sanitized version of my regression testing inventory. Yes, I know that groups starting with numbers currently cause warnings.

# Domain groups
[00Int:children]
Test_Windows
Test_Linux
Test_SQL

[00Ext:children]
Test_DMZ_Win
Test_DMZ_Lin
DELEGATE_MPDMZ

# Data Center Groups
[02DC1:children]
Test_Windows
Test_Linux
Test_DMZ_Win
Test_DMZ_Lin

[02DC2:children]

# OS Groups
[03Windows:children]
Test_Windows
Test_DMZ_Win

[03Ubuntu:children]
Test_Linux
Test_DMZ_Lin

#Host Groups here
[Test_Windows]
testbuild01

[Test_Linux]
testbuild02

[Test_DMZ_Win]
testbuild04

[Test_DMZ_Lin]
testbuild05

And here a mock up of my workflow.

graph LR
    A(Start) --> B{Which Domain}
    B --> C(Int<br>Pre-Work<br>limit &00Int)
    B --> D(Ext<br>Pre-Work<br>limit &00Ext)
    C --> E{Which DC}
    D --> E
    E --> G(DC1<br>Build VM<br>limit :&02DC1)
    E --> H(DC2<br>Build VM<br>limit :&02DC2)
    G --> K(Customize VM<br>Windows<br>Ext<br>DC1<br>limit :&03Windows:&00Ext:&02DC1)
    G --> L(Customize VM<br>Windows<br>Int<br>DC1<br>limit :&03Windows:&00Int:&02DC1)
    G --> M(Customize VM<br>Linux<br>Ext<br>DC1<br>limit :&03Ubuntu:&00Ext:&02DC1)
    G --> N(Customize VM<br>Linux<br>Int<br>DC1<br>limit :&03Ubuntu:&00Int:&02DC1)
    H --> O(Customize VM<br>Windows<br>Ext<br>DC2<br>limit :&03Windows:&00Ext:&02DC2)
    H --> P(Customize VM<br>Windows<br>Int<br>DC2<br>limit :&03Windows:&00Int:&02DC2)
    H --> Q(Customize VM<br>Linux<br>Ext<br>DC2<br>limit :&03Ubuntu:&00Ext:&02DC2)
    H --> R(Customize VM<br>Linux<br>Int<br>DC2<br>limit :&03Ubuntu:&00Int:&02DC2)

The confusing part is that the place that regularly fails is the “Build” step when there are no targets in the datacenter (again, this is a normal circumstance).

At first, I looked at the difference between the “Pre” and “Build” steps (both only filter once, and one started with at : and one did not). Unfortunately, when I changed the filter on to match the “Pre” filters, it still didn’t work. Both playbooks start with the same opening block I referenced above, and their first task is an include: (yes, I know, deprecated. Also on the list)

The empty group 02DC2 would cause that error for every limit containing ‘&02DC2’ since it will never match any hosts.

So the issue is that the group itself is empty, not that the result of the filter is empty?

The & character specifies to use an intersection, so if you use :&02DC2 and 02DC2 contains no hosts, the limit produces no hosts, because it cannot create an intersection between the prior hosts that filter.

Yeah. There are times I want no hosts (ex: if an application has nothing in DC2, the whole DC2 branch of this workflow should run successfully, doing nothing). This is already successfully skipping tasks everywhere else in the workflow, but not on the “build” step.

I am testing out the suggestion from @shertel to see if that helps.

OK, after some testing, having an empty group in my inventory did seem to be the issue.

In hopes that this distinction will help someone in the future, the issue seems to be that with an empty group in the inventory, the set of filters will always result in an empty list, and NOT that the combination of filters sometimes results in an empty list.

I realize that documentation on patterns says its an intersection of groups. But It was the error I was getting did not make me realize that what it was say is “given the state of this inventory, this intersection cannot be anything other than empty”.

1 Like