Using Ansible and Ansible Tower with shared roles
// Ansible Blog
Roles are an essential part of Ansible, and help in structuring your automation content. The idea is to have clearly defined roles for dedicated tasks. During your automation code, the roles will be called by the Ansible Playbooks.
Since roles usually have a well defined purpose, they make it easy to reuse your code for yourself, but also in your team. And you can even share roles with the global community. In fact, the Ansible community created Ansible Galaxy as a central place to display, search and view Ansible roles from thousands of people.
So what does a role look like? Basically it is a predefined structure of folders and files to hold your automation code. There is a folder for your templates, a folder to keep files with tasks, one for handlers, another one for your default variables, and so on:
tasks/ handlers/ files/ templates/ vars/ defaults/ meta/
In folders which contain Ansible code - like tasks, handlers, vars, defaults - there are
main.yml files. Those contain the relevant Ansible bits. In case of the
tasks directory, they often include other yaml files within the same directory. Roles even provide ways to test your automation code - in an automated fashion, of course.
This post will show how roles can be shared with others, be used in your projects and how this works with Red Hat Ansible Tower.
Share Roles via Repositories
Roles can be part of your project repository. They usually sit underneath a dedicated
roles/ directory. But keeping roles in your own repository makes it hard to share them with others, to be reused and improved by them. If someone works on a different team, or on a different project, they might not have access to your repository - or they may use their own anyway. So even if you send them a copy of your role, they could add it to their own repository, making it hard to exchange improvements, bug fixes and changes across totally different repositories.
For that reason, a better way is to keep a role in its own repository. That way it can be easily shared and improved. However, to be available to a playbook, the role still needs to be included. Technically there are multiple ways to do that.
For example there can be a global roles directory outside your project where all roles are kept. This can be referenced in
ansible.cfg. However, this requires that all developer setups and also the environment in which the automation is finally executed have the same global directory structure. This is not very practical.
When Git is used as the version control system, there is also the possibility of importing roles from other repositories via Git submodules, or even using Git subtrees. However, this requires quite some knowledge about advanced Git features by each and everyone using it - so it is far from simple.
The best way to make shared roles available to your playbooks is to use a function built into Ansible itself: by using the command
ansible-galaxy , ansible galaxy can read a file specifying which external roles need to be imported for a successful Ansible run:
requirements.yml. It lists external roles and their sources. If needed, it can also point to a specific version:
# from GitHub - src: https://github.com/bennojoy/nginx # from GitHub, overriding the name and specifying a tag - src: https://github.com/bennojoy/nginx version: master name: nginx_role # from Bitbucket - src: git+http://bitbucket.org/willthames/git-ansible-galaxy version: v1.4 # from galaxy - src: yatesr.timezone
file can be used via the command
ansible-galaxy. It reads the file and downloads all specified roles to the appropriate path:
ansible-galaxy install -r roles/requirements.yml - extracting nginx to /home/rwolters/ansible/roles/nginx - nginx was installed successfully - extracting nginx_role to /home/rwolters/ansible/roles/nginx_role - nginx_role (master) was installed successfully ...
The output also highlights when a specific version was downloaded. You will find a copy of each role in your
roles/ directory - so make sure that you do not accidentally add the downloaded roles to your repository! The best option is to add them to the
This way, roles can be imported into the project and are available to all playbooks while they are still shared via a central repository. Changes to the role need to be made in the dedicated repository - which ensures that no light-minded and project specific changes are done in the role.
At the same time the version attribute in
requirements.yml ensures that the used role can be pinned to a certain release tag value, commit hash, or branch name. This is useful in case the development of a role is quickly moving forward, but your project has longer development cycles.
Using Roles in Ansible Tower
If you use automation on larger, enterprise scales you most likely will start using Ansible Tower sooner or later. So how do roles work with Ansible Tower? In fact - just like mentioned above. Each time Ansible Tower checks out a project it looks for a
roles/requirements.yml. If such a file is present, a new version of each listed role is copied to the local checkout of the project and thus available to the relevant playbooks.
That way shared roles can easily be reused in Ansible Tower - it is built in right from the start!
Best Practices and Things to Keep in Mind
There are a few best practices around sharing of Ansible roles that make your life easier. The first is the naming and location of the roles directory. While it is possible to name the directory any way via the
ansible.cfg, we strongly recommend to stick to the directory name
roles, sitting in the root of your project directory. Do not choose another name for it or move it to some subdirectory.
The same is true for
requirements.yml: have one requirements.yml only, and keep it at
roles/requirements.yml. While it is technically possible to have multiple files and spread them across your project, this will not work when the project is imported into Ansible Tower.
Also, if the roles are not only shared among multiple users, but are also developed with others or not by you at all, it might make sense to pin the role to the actual commit you've tested your setup against. That way you will avoid unwanted changes in the role behaviour.
Find, reuse, and share the best Ansible content on Ansible Galaxy.
Learn more about roles on Ansible Docs.
Read in my feedly