My understanding of Ansible roles is that they are the unit of reusability when implementing processes using Ansible, similarly to what a class or a package is in some computer languages.

It therefore seems natural to use roles to make all tasks understanding a given data structure in a specific role, but this yields the question of how to select the actual tasks to perform? Is it a good design to use the main.yml file in the task as an entrypoint to select actual tasks according to role parameters?

For instance a framework role could feature:

  • a defaults/main.yml file that understands the framework variable that could be define by a vars file shared by all playbooks in a project like

    framework: java: [tomcat, mysql] php: yes

so that after processing the defaults/main.yml file the following variables:

framework__enable_java_core: yes
framework__enable_java_tomcat: yes
framework__enable_java_mysql: yes
framework__enable_php_core: yes

are defined and can be used by the role to actually know which tasks to perform.

  • several tasks like java.yml, php.yml pro framework, which select actions to perform according to a when: action == 'WHATEVER-ACTION is to perform; the main.yml then leek all the corresponding tasks.

  • playbooks that say

for instance

- { role: framework, action: apt-setup }


- { role: framework, action: install }


- { role: framework, action: uninstall }

This kind of approaches turns out to scale very well when working with Makefiles. It is therefore tempting to use it again when writing complex ansible systems. On the one hand, it seems to fit quite naturally in the language used by ansible. On the other hand, it generates quite a payload of “skipped” tasks in ansible logs, which raises a red sign to me.

Is the approach I describe a sensible way to group data structures with the processes using it? (That is, to implement reutilisation!) If not, what would be a better way?


Different approaches can be useful for different setups. You can use tags in some cases, or conditional includes (as you describe) in other cases.


You should get familiar with difference between static and dynamic includes in Ansible.

So if you use static includes, you will get a lot of skipped tasks, because every task in every file is added to execution queue but most of them are skipped because of when statement.

tasks/main.yml of your role with actions install/uninstall:

- include: install.yml
  when: action == 'install'
- include: uninstall.yml
  when: action == 'uninstall'

But if you use dynamic includes, only required tasks are added to execution queue and skipped message is displayed for skipped includes.


- include_tasks: install.yml
  when: action == 'install'
- include_tasks: uninstall.yml
  when: action == 'uninstall'

More on that, you can avoid skipped message altogether like this:


- include_tasks: '{{ action }}.yml'

The drawback of dynamic includes is that you can't do complete static analysis of your playbook (like syntax checks, etc.) because many things are know only in runtime.

Your Answer

