Answers: <p>Different approaches can be useful for different setups. You can use <em>tags</em> in some cases, or <em>conditional includes</em> (as you describe) in other cases.</p>
  
  <blockquote>
    <p>On the other hand, it generates quite a payload of “skipped” tasks in ansible logs, which raises a red sign to me.</p>
  </blockquote>
  
  <p>You should get familiar with <a href="https://serverfault.com/questions/875247/whats-the-difference-between-include-tasks-and-import-tasks">difference between static and dynamic includes</a> in Ansible.</p>
  
  <p>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 <code>when</code> statement.</p>
  
  <p><code>tasks/main.yml</code> of your role with actions <code>install</code>/<code>uninstall</code>:</p>
  
  <pre><code>- include: install.yml
    when: action == 'install'
  - include: uninstall.yml
    when: action == 'uninstall'
  </code></pre>
  
  <p>But if you use dynamic includes, only required tasks are added to execution queue and <code>skipped</code> message is displayed for skipped includes.</p>
  
  <p><code>tasks/main.yml</code>:</p>
  
  <pre><code>- include_tasks: install.yml
    when: action == 'install'
  - include_tasks: uninstall.yml
    when: action == 'uninstall'
  </code></pre>
  
  <p>More on that, you can avoid <code>skipped</code> message altogether like this:</p>
  
  <p><code>tasks/main.yml</code>:</p>
  
  <pre><code>- include_tasks: '{{ action }}.yml'
  </code></pre>
  
  <p>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.</p>
  
Answers: CC BY-SA 3.0
Answers: 2018-03-01T15:45:39.180Z
Answers: 2018-03-01T15:45:39.180Z
Answers: Konstantin Suvorov
Body: <p>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.</p>
  
  <p>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 <code>main.yml</code> file in the task as an entrypoint to select actual tasks according to role parameters?</p>
  
  <p>For instance a <code>framework</code> role could feature:</p>
  
  <ul>
  <li><p>a <code>defaults/main.yml</code> file that understands the <code>framework</code> variable that could be define by a vars file shared by all playbooks in a project like</p>
  
  <p>framework:
    java: [tomcat, mysql]
    php: yes</p></li>
  </ul>
  
  <p>so that after processing the <code>defaults/main.yml</code> file the following variables:</p>
  
  <pre><code>framework__enable_java_core: yes
  framework__enable_java_tomcat: yes
  framework__enable_java_mysql: yes
  framework__enable_php_core: yes
  </code></pre>
  
  <p>are defined and can be used by the role to actually know which tasks to perform.</p>
  
  <ul>
  <li><p>several tasks like <code>java.yml</code>, <code>php.yml</code> pro framework, which select actions to perform according to a <code>when: action == 'WHATEVER-ACTION</code> is to perform; the <code>main.yml</code> then leek all the corresponding tasks.</p></li>
  <li><p>playbooks that say</p></li>
  </ul>
  
  <p>for instance</p>
  
  <pre><code>roles:
  - { role: framework, action: apt-setup }
  </code></pre>
  
  <p>or</p>
  
  <pre><code>roles:
  - { role: framework, action: install }
  </code></pre>
  
  <p>or</p>
  
  <pre><code>roles:
  - { role: framework, action: uninstall }
  </code></pre>
  
  <p>This kind of approaches turns out to <a href="https://github.com/michipili/bsdowl" rel="nofollow noreferrer">scale very well when working with Makefiles</a>.  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.</p>
  
  <p>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?</p>
  
Tags: <ansible><architecture>
Title: In ansible how to select specific tasks in a role according to the playbook or a more general parameter?
UserDisplayName: Michaël Le Barbier
ThreadText: # In ansible how to select specific tasks in a role according to the playbook or a more general parameter?
  
  (Asked by: username_0 on 2018-03-01)
  
  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
  
  ```
  roles:
  - { role: framework, action: apt-setup }
  
  ```
  
  or
  
  ```
  roles:
  - { role: framework, action: install }
  
  ```
  
  or
  
  ```
  roles:
  - { role: framework, action: uninstall }
  
  ```
  
  This kind of approaches turns out to [scale very well when working with Makefiles](https://github.com/michipili/bsdowl). 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?
  
  **Tags:** ansible, architecture
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2018-03-01. Score: 8 | Accepted answer
  
  Different approaches can be useful for different setups. You can use *tags* in some cases, or *conditional includes* (as you describe) in other cases.
  
  > On the other hand, it generates quite a payload of “skipped” tasks in ansible logs, which raises a red sign to me.
  
  You should get familiar with [difference between static and dynamic includes](https://serverfault.com/questions/875247/whats-the-difference-between-include-tasks-and-import-tasks) 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.
  
  `tasks/main.yml`:
  
  ```
  - 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:
  
  `tasks/main.yml`:
  
  ```
  - 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.
  
  
  ---
  
  