If you’re an Ansible user you know that in order to automate various IT services, you’ve got to write a playbook machine to a particular configuration. For complicated environments it’s common, and even preferred, that you break the work of a playbook into smaller blocks of execution called “roles,” which include the tasks required to implement one feature of a configuration. Roles are analogous to subroutines in a piece of software; by encapsulating the steps needed for each feature, roles becomes reusable elements that can be invoked from multiple playbooks to describe the actions that you want completed on a machine. A “playbook” is a list of tasks that sets a
For example, you may have a playbook that sets up a system as a web server. This particular playbook might: create some user accounts, customize the resolver configuration, enable SNMP for monitoring, and install apache. Each of those pieces is taken care of by a role.
In general, it all works great when you need to deploy consistent configurations for new machine in a production environment, but what happens when you’re testing and only want to setup apache without any of the other features? It would be nice if you could say “run only this role on that machine,” but there’s presently no convenient mechanism to do this.
To get around this limitation, I have a playbook called “runrole.yml” that acts like a template and that uses variables provided on the command line. Following up on the example above, if I want to run the ‘apache’ role on a system called ‘testbox’, I can do this:
ansible-playbook ./runrole.yml -e "role=apache onhosts=testbox"
The “-e” switch to the ansible-playbook command lets you provide ‘extra arguments’ to the playbook.
The playbook looks like this:
# A simple playbook that makes it easy to invoke a single role.
- hosts: ""
The “role” variable should be set to the name of a role that can be easily found in the roles search path. You can find specific details about how to set the roles search path on the Ansible web site.
The “onhosts” variable can be set to the name of a single host, a group name, or a comma-separated list of hosts and/or groups. The only requirement is that any hosts or groups mentioned need to be in your Ansible inventory.
Like any playbook, the default behavior is to gather facts from the hosts you’re running the role on. If you’re testing a role that doesn’t need any facts from the target host(s), you can speed up execution by including “gather=False” in the ‘-e’ clause to prevent the playbook from running the setup module.
It would look like this:
ansible-playbook ./runrole.yml -e "role=apache gather=False onhosts=testbox"
As you probably expect, all of the other options that normally work for Ansible-playbook are still valid, so you can use “–ask-pass”, “–become” or any other settings that you need. An important one that I sometimes forget is “–vault-pasword-file” which can be used whenever a role makes use of a vault.
For administrators doing DevOps work with Ansible, it can be handy to be able to execute a role from the command line to apply a piece of a configuration to a host for testing purposes. I wouldn’t recommend this for day-to-day operations but it’s very handy when you need to try something out. By taking advantage of variable substitution a simple template-like playbook like the one above enables easy ad-hoc execution of roles from the command line.