Limit ansible playbook by `hosts` of plays

AJP picture AJP · Jun 14, 2017 · Viewed 7.1k times · Source

I have an inventory file like:

[my_domain]
255.255.255.255

[production:children]
my_domain


[load_balancer:children]
my_domain

[webservers:children]
my_domain

I have a playbook.yml like:

---

- hosts: webservers
  gather_facts: no
  tasks:
    - debug:
        msg: Hello webservers

- hosts: load_balancer
  gather_facts: no
  tasks:
    - debug:
        msg: Hello load_balancer

When running the following command it runs both the plays in the playbook, i.e. it prints "Hello webservers" and "Hello load_balancer":

ansible-playbook ./playbook.yml --limit "webservers:&production"

I can get it to only run the webservers play by adding a tag to it and using tags on the command line such as:

...
- hosts: webservers
  tags: ['webservers']
  # or if using roles then:
  # roles:
  #   - { role: provision_webserver, tags: [ 'provision_webservers' ] }
  ...

And use:

ansible-playbook ./playbook.yml --limit "webservers:&production" --tags "webservers"

I was hoping the limit arg would work not only on the inventory file but also on the hosts value of each play. The docs seem to suggest this is possible though they give the example using ansible and a one off command rather than ansible-playbook and a playbook:

This can mean what hosts to communicate with, but in terms of Playbooks it actually means what hosts to apply a particular configuration or IT process to.

I think the answer is that I am using playbooks wrong and should only have one play per playbook which necessarily means it will only have one hosts and you select which plays you want to run by changing the playbook<-abc>.yml you are using. However that last link also suggests you can just use --limit to set which hosts. Very confused.

Answer

Konstantin Suvorov picture Konstantin Suvorov · Jun 14, 2017

You are right, as per best practices you may want to split different types of configurations to separate playbooks to be able to run them separately.

But this piece of text may be a bit confusing:

This is analogous to the “–limit” parameter to ansible but a little more explicit:

ansible-playbook site.yml --limit webservers
ansible-playbook webservers.yml

It is true only if hosts in webservers group are not part of any other group. Otherwise (as in your example) if host server1 is in groups webservers and load_balancers, then plays for webservers and load balancers will be applied for this host.

Also, as you correctly noted, you can mark some parts of your playbooks with tags and use --tags to limit playbook runs by this criteria.

Sometime I use a trick to have the same host under different inventory names so Ansible treat them as different hosts:

[webservers]
myhost_ws ansible_host=myhost

[load_balancers]
myhost_lb ansible_host=myhost

This way myhost_ws and myhost_lb is actually the same server, but --limit webservers will execute only first play from this playbook:

- hosts: webservers
  ....

- hosts: load_balancers
  ....

But keep in mind that with this setup any fact gathered for myhost_ws during the first play are not available for myhost_lb during the second play directly (but you can still fetch them via hostvars['myhost_ws']).