Safely limiting Ansible playbooks to a single machine?

joemaller picture joemaller · Aug 12, 2013 · Viewed 227.1k times · Source

I'm using Ansible for some simple user management tasks with a small group of computers. Currently, I have my playbooks set to hosts: all and my hosts file is just a single group with all machines listed:

# file: hosts
[office]
imac-1.local
imac-2.local
imac-3.local

I've found myself frequently having to target a single machine. The ansible-playbook command can limit plays like this:

ansible-playbook --limit imac-2.local user.yml

But that seems kind of fragile, especially for a potentially destructive playbook. Leaving out the limit flag means the playbook would be run everywhere. Since these tools only get used occasionally, it seems worth taking steps to foolproof playback so we don't accidentally nuke something months from now.

Is there a best practice for limiting playbook runs to a single machine? Ideally the playbooks should be harmless if some important detail was left out.

Answer

joemaller picture joemaller · Aug 12, 2013

Turns out it is possible to enter a host name directly into the playbook, so running the playbook with hosts: imac-2.local will work fine. But it's kind of clunky.

A better solution might be defining the playbook's hosts using a variable, then passing in a specific host address via --extra-vars:

# file: user.yml  (playbook)
---
- hosts: '{{ target }}'
  user: ...

Running the playbook:

ansible-playbook user.yml --extra-vars "target=imac-2.local"

If {{ target }} isn't defined, the playbook does nothing. A group from the hosts file can also be passed through if need be. Overall, this seems like a much safer way to construct a potentially destructive playbook.

Playbook targeting a single host:

$ ansible-playbook user.yml --extra-vars "target=imac-2.local" --list-hosts

playbook: user.yml

  play #1 (imac-2.local): host count=1
    imac-2.local

Playbook with a group of hosts:

$ ansible-playbook user.yml --extra-vars "target=office" --list-hosts

playbook: user.yml

  play #1 (office): host count=3
    imac-1.local
    imac-2.local
    imac-3.local

Forgetting to define hosts is safe!

$ ansible-playbook user.yml --list-hosts

playbook: user.yml

  play #1 ({{target}}): host count=0