Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

localhost is ignored when using dynamic inventory with --limit localhost #38221

Closed
gintautassulskus opened this issue Apr 3, 2018 · 7 comments
Labels
affects_2.5 This issue/PR affects Ansible v2.5 bug This issue/PR relates to a bug. support:core This issue/PR relates to code supported by the Ansible Engineering Team.

Comments

@gintautassulskus
Copy link

ISSUE TYPE
  • Bug Report
COMPONENT NAME

limit

ANSIBLE VERSION
2.5.0
CONFIGURATION
OS / ENVIRONMENT
SUMMARY

I have a playbook with two plays:

- name: Play 1
   hosts: localhost
- name: Play 2 
   hosts: all:!localhost

The following command behaves differently depending on what is returned by the dynamic inventory :
ansible-playbook -i dynamic_inventory --list-hosts --limit=localhost
Where dynamic_inventory is a dynamic inventory script. Namely, openstack.py executed against Rackspace environent (not officially supported I believe).

If the dynamic inventory is empty, I get a match:

  play #1 (localhost): Play 1	
    pattern: [u'localhost']
    hosts (1):
      localhost

  play #2 (all:!localhost): Play 2
    pattern: [u'all:!localhost']
    hosts (0):

If the dynamic inventory is NOT empty, then I receive the following error:
ERROR! Specified hosts and/or --limit does not match any hosts

It is not possible to limit the execution to localhost when the inventory is not empty.
I think the behaviour should be consistent and localhost treated as a first-class citizen.

STEPS TO REPRODUCE

Run ansible-playbook -i dynamic_inventory --list-hosts --limit=localhost. I do not have a static inventory to test the behaviour. The simples case
ansible-playbook -i localhost, example.yml --limit localhost --list-hosts does work.

  #example playbook
- name: Play 1
  hosts: localhost
  gather_facts: no
  pre_tasks:
    - debug:
        msg: bla


- name: Play 2
  hosts: all:!localhost
  gather_facts: no
  pre_tasks:
    - debug:
        msg: bla
EXPECTED RESULTS

Regardless of the dynamic inventory result, ansible-playbook -i dynamic_inventory --list-hosts --limit=localhost should return a match:

  play #1 (localhost): Play 1	
    pattern: [u'localhost']
    hosts (1):
      localhost

  play #2 (all:!localhost): Play 2
    pattern: [u'all:!localhost']
    hosts (0):
ACTUAL RESULTS
ERROR! Specified hosts and/or --limit does not match any hosts
@sivel
Copy link
Member

sivel commented Apr 3, 2018

I'm not sure if this is a bug or not.

The current implementation of --limit would require localhost to be returned by the dynamic inventory script, or any inventory for that matter.

Implicit localhost (http://docs.ansible.com/ansible/devel/inventory/implicit_localhost.html) is created just in time during playbook execution as referenced if localhost does not exist in the inventory.

Due to this, the creation of implicit localhost, happens long after inventory has been parsed and the limit applied to the inventory.

I am leaning toward this not being a bug.

@ansibot ansibot added affects_2.5 This issue/PR affects Ansible v2.5 bug This issue/PR relates to a bug. needs_triage Needs a first human triage before being processed. support:core This issue/PR relates to code supported by the Ansible Engineering Team. labels Apr 3, 2018
@gintautassulskus
Copy link
Author

gintautassulskus commented Apr 3, 2018

I find this behaviour confusing from the user's perspective. Please consider the following use case based on the example playbook, provided in the original post.

The first playPlay 1 should execute on localhost and create server instances. The second play Play 2 is supposed to run on all created server instances. With --limit I can then create and provision different groups of servers, e.g.: staging or prod.

In case I want to create and provision prod group, I would run the playbook with --limit localhost, prod. There are three cases here:

  1. If there are no active instances on the cloud (dynamic inventory is empty), the ansible will execute the playbook, matching the localhost and prod hosts.
  2. If the dynamic inventory returns the prod group, then the ansible will run as well.
  3. If the prod group has not yet been created but the dynamic inventory returns something, e.g. a list of staging group servers, then the script will fail with ERROR! Specified hosts and/or --limit does not match any hosts.

Maybe technically this behaviour is correct, but I believe the focus here should be on the user's perspective. The latter, in my opinion, could benefit from improved consistency.

@sivel sivel removed the needs_triage Needs a first human triage before being processed. label Apr 3, 2018
@sivel
Copy link
Member

sivel commented Apr 3, 2018

cc @bcoca thoughts here?

I'm leaning perhaps more towards a docs update to mention that --limit does not work with implicit localhost.

@bcoca
Copy link
Member

bcoca commented Apr 3, 2018

The error is not cause of limit not matching an existing host, that would be a warning:

#> ansible-playbook ... --limit dont
...
[WARNING]: Could not match supplied host pattern, ignoring: dont

The issue is that once the limit is applied, the play selection doesn't match any hosts (we might want better wording on error here).

It seems to work as expected, if localhost is in inventory, no hosts are matched, if the localhost is 'implicit', we create it on demand and ignore inventory restrictions as they don't apply to the 'magical host' we just created.

@welchwilmerck
Copy link
Contributor

I've worked extensively with dynamic inventory in AWS and have gotten to all work together in one playbook - launch instances and then, based on group membership, run plays on instances.

First, use a variable to set the pattern to match in 'hosts:', not hard coding it to 'all' and then adding the pattern to '--limit'. You'll need the pattern in more places than just 'hosts:'.

ansible-playbook -e sdlc_stage=prod ...
  -name: Now, configure hosts
   hosts: {{ sdlc_stage }}

I believe the real issue you're having is that once you get the instances started, the rest of the playbook doesn't know about them. The issue here is that whatever inventory you declared on the command line is sourced into memory at the beginning of the ansible-playbook and never re-read. You have to update the in-memory inventory if you add hosts:

So, somewhere in your 'Play 1', you need something like this:

- name: Wait for SSH to come up
  wait_for: host={{ item.private_ip }} port=22 delay=5 timeout=320 state=started

- name: Add new instance to in-memory representation of group
  add_host:
    hostname: "{{ item.private_ip }}"
    ansible_host: "{{ item.private_ip }}"
    ec2_private_ip_address: "{{ item.private_ip }}"
    ec2_instance_type: "{{ item.instance_type }}"
    ansible_user: ubuntu
    groups: {{ sdlc_stage }}

@bitsmaestro
Copy link

interestingly in same scenario ansible doesnet gives any error

ping command without any host match

$ ansible localhost -i inventory --limit="\!all" -m ping
$

ping command with host match

$ ansible localhost -i inventory -m ping
localhost | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

@jimi-c
Copy link
Member

jimi-c commented May 8, 2020

The issue here is that the all group explicitly leaves out the implicit localhost created internally. Because of that, the implicit localhost is never included there. However, when it's included via the dynamic inventory script it's placed in the all group because it's no longer implicitly created. You can read more about that here: https://docs.ansible.com/ansible/latest/inventory/implicit_localhost.html

As such, this is not a bug but expected behavior, and we'll close this issue now.

If you have any further questions, please let us know by stopping by one of the two mailing lists, as appropriate:

Because this project is very active, we're unlikely to see comments made on closed tickets, but the mailing list is a great way to ask questions, or post if you don't think this particular issue is resolved.

Thank you!

@jimi-c jimi-c closed this as completed May 8, 2020
@ansible ansible locked and limited conversation to collaborators Jun 5, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affects_2.5 This issue/PR affects Ansible v2.5 bug This issue/PR relates to a bug. support:core This issue/PR relates to code supported by the Ansible Engineering Team.
Projects
None yet
Development

No branches or pull requests

7 participants