Overview
Ansible playbooks work quite differently than ad-hoc commands. For a newbe Ansible user it might be irritating that you can’t choose your target hosts at runtime when running an Ansible playbook. Here is a way around this.
can’t choose target hosts with playbooks
As i started with Ansible i first used some ad-hoc commands to have some kind of remote execution or remote administration interface. With each command i choose the server (or server group) on which this command should be run.
As i wanted more complex remote administration to be run, i stuck with the use case and put the commands in a (predefined) playbook, which should be run on hosts of my choice. But playbooks are primarily not meant for remote administration and therefor Ansible-playbook -command does not accept a hostname or host group as parameter.
The idea of Ansible playbooks is a predefined orchestration over a couple of hosts. As the playbooks are capable to manage a service which expands over many hosts (e.g a more tear application, or a ha-cluster) the nodes on which the commands are to be executed are defined within the playbook.
In short words:
a) adhoc commands need a host, hostgroup specified to run
b) playbooks have their target-hosts defined inside the playbook – if you do want your playbook be variable you could work around like this
Choosing the target hosts on runtime by handing over variables
You can provide variables at the command line which can be used within the playbook:
ansible-playbook ./playbook.yml --extra-vars server=servers
where “servers” is a single server or a servergroup according to your ansible-hosts file.
Inside the playbook you have use the variable within the hosts-selection:
- hosts: "{{ server }}" tasks: ......
Choosing the target hosts on runtime by limiting target hosts
As knowledge evolves i would like to suggest a streamlined aproach:
Write your playbook to address all servers and then limit the target hosts with the –limit directive:
ansible-playbook ./playbook.yml --limit servers
where “servers” is a single server or a servergroup according to your ansible-hosts file.
Inside the playbook you have the widest hosts-selection:
- hosts: all tasks: ......
Note:
If you forget to specify the target host(s) on the cmd line,
a) you will run into errors with the first approach,
b) while executing on all host with the second approach.
Maybe there are reasons to stick with the first choice.
Reboot arbitrary Servers with a playbook
As an example i would like to provide the reboot playbook. Putting reboot into a playbook is a bit more challanging, as you get disconnected from the host and would like to reconnect when it is up and running again.
I’ve looked at [1] to get the right ideas:
cat /etc/ansible/reboot.yml # reboot a system # from http://stackoverflow.com/questions/23877781/how-to-wait-for-server-restart-using-ansible/28070759#28070759 - hosts: "{{ server }}" tasks: - name: Restart a server shell: echo "Rebooting $hostname" notify: - Restart server - Wait for server to restart handlers: - name: Restart server command: sleep 2 && shutdown -r now "Reboot triggered by Ansible" async: 1 poll: 0 ignore_errors: true - name: Wait for server to restart local_action: module: wait_for host={{ inventory_hostname }} port=22 delay=1 timeout=300
This is called as
# ansible-playbook ./reboot.yml --extra-vars server=hostgroup
where hostgroup can be any concrete host or hostgroup defined in /etc/ansible/hosts
Conclusion
Choosing the target hosts at run time is not the natural use case Ansible playbooks are meant for. Being able to consume predefined multi-step tasks on the hosts you desire at runtime will definitly help to streamline day to day administration tasks.
[1] http://stackoverflow.com/questions/23877781/how-to-wait-for-server-restart-using-ansible/28070759#28070759