Hi all,
I noticed today that when including a role using the dict form, it will also provide a variable named ‘role’ to all role tasks:
roles:
- { role: foobar, version: 1.2.3 }
However, when processing role dependencies, this variable is explicitly removed (see line 287 in lib/ansible/playbooks/play.py):
if ‘role’ in dep_vars:
del dep_vars[‘role’]
Is there any reason why this is done?
I wrote a few include files for very common tasks that I include in multiple roles – but the task might sometimes want to know which role it has been included from (e.g., to find template files in that role’s directory).
Is it possible to provide the role name in the ‘role’ variable in all cases, i.e., also when using the simpler role syntax:
roles:
Greetings,
Christian
The role_name variable should be available in all roles, so relying on that variable being set should not be required. If I remember correctly, that is removed from the dictionary there to make sure the parent role’s name does not override dependent roles, otherwise it would be merged in to their variables incorrectly.
If I put this into roles/foobar/tasks/main.yml, it fails with “role_name is undefined”:
- debug: msg=“{{ role_name }}”
I do see a variable called “role_names”, though, which contains all roles loaded in the current play, but that’s obviously not what I was hoping for…
" but the task might sometimes want to know which role it has been included from (e.g., to find template files in that role’s directory)."
Roles should be written so they don’t need this knowledge.
Already roles contain a “template/” directory, so they find templates in there automatically, so you shouldn’t need to path them.
Unless you use a lookup plugin, which looks in files/
I'm actually wondering what the benefit is to split out templates/ and
files/
I think I should start to `ln -s files templates`
“I’m actually wondering what the benefit is to split out templates/ and files/”
So you can tell what is copied verbatim with what is a jinja2 template.
Thanks for your reply (also thanks to James, btw). This might be getting slightly off-topic, but I’d really like to hear your opinion and see whether there is a more ansible-like way of doing this:
I am trying to avoid copy’n’paste as much as possible and created a few include files with tasks that I use in almost every role. For example, making sure a service is started and enabled, or defining reload/restart handlers – and they all use the same logic of mapping “apache” to whatever the actual service name is on the OS (“apache2”, “httpd”, etc.), mapping package names etc. (discovering {{ansible_pkg_mgr}} made me switch to roles finally, btw, because apt/yum/portage was the (almost) only reason I needed group_by and multiple plays for different distros).
One of those common tasks is loading variables using include_vars with {{ansible_distribution}} or {{ansible_os_family}} (whichever vars-file exist), so it has to know the role’s vars/ directory. With this, most of my {{role}}/tasks/main.yml become nicely clean and concise:
- include: …/…/common/tasks/include_vars.yml
- include: …/…/common/tasks/pkg_mgr.yml pkgs=foobar,libfoo
- include: …/…/common/tasks/service.yml name=foobar
If the role is called foobar and only needs one package, I can even omit the name and pkgs parameters, and only define svc[‘foobar’] and pkg[‘foobar’] in vars/{{distro}}.yml if service or package name are different from “foobar”.
Another common task is installing a new Apache vhost config. I am doomed to work with three different distros – the snippet can be reused on every server, but the way it’s installed is different. I am trying to avoid teaching all of my {{webapp}} roles how to install a vhost, and instead do something like
- include: …/…/common/tasks/include_vars.yml role=apache
- include: …/…/apache/tasks/vhost.yml
which then finds “apache_vhost.conf” in the current role’s templates/ directory.
“Thanks for your reply (also thanks to James, btw). This might be getting slightly off-topic, but I’d really like to hear your opinion and see whether there is a more ansible-like way of doing this:”
If so, I would recommend starting a new post. I’m also not seeing a question mark in this post so am not sure what to answer.