Mat
Mat

Reputation: 596

Ansible: applying tags at role execution

I'm trying to definitively understand how tags are applied at role execution in Ansible.

I read the docs at https://docs.ansible.com/ansible/latest/user_guide/playbooks_tags.html#adding-tags-to-roles and tried with a test role:

 ~/ansible/roles/internal/test/tasks > cat tag-foo.yml
---
- import_tasks: tag-foo.yml
  tags:
    - foo
    - foo2

- import_tasks: tag-bar.yml
  tags:
    - bar

- import_tasks: always.yml
  tags:
    - always

- import_tasks: never.yml
  tags:
    - never
    - nevermind

 ~/ansible/roles/internal/test/tasks > cat tag-foo.yml
---
- name: This is tag 'foo'
  debug:
    msg: This is tag 'foo'

 ~/ansible/roles/internal/test/tasks > cat tag-bar.yml
---
- name: This is tag 'bar'
  debug:
    msg: This is tag 'bar'

 ~/ansible/roles/internal/test/tasks > cat always.yml
---
- name: This is tag 'always'
  debug:
    msg: This is tag 'always'

 ~/ansible/roles/internal/test/tasks > cat never.yml
---
- name: This is tag 'never'
  debug:
    msg: This is tag 'never'

I created a test playbook file:

 ~/ansible > cat plays/test.yml
- hosts: all

  tasks:
    - name: Execute test role with all tags
      import_role:
        name: test
      tags: foo2

    - name: Execute test role with tag 'foo'
      import_role:
        name: test
      tags:
        - foo

What I don't understand is that if I execute the playbook with the foo tag, the role is executed both times and not only one time executing only the tasks from tag-foo.yml and the tag-always.yml:

 ~/ansible > ansible-playbook -i test.ini plays/test.yml -l test.domain.local -t foo

PLAY [all] ********************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************
ok: [test.domain.local]

TASK [test : This is tag 'foo'] ***********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'foo'"
}

TASK [test : This is tag 'always'] ********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'always'"
}

TASK [test : This is tag 'foo'] ***********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'foo'"
}

TASK [test : This is tag 'bar'] ***********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'bar'"
}

TASK [test : This is tag 'always'] ********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'always'"
}

TASK [test : This is tag 'never'] *********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'never'"
}

PLAY RECAP ********************************************************************************************************************************************
test.domain.local           : ok=7    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

What I want is to force tags from a single import_role statement without necessarily specifying it in the ansible-playbook command.

Edit: I tried to replace the import_role statement with include_role into the playbook adding the apply option to apply the foo tag:

- name: Execute test role with tag 'foo'
  include_role:
    name: test
    apply:
      tags:
        - foo

And I replaced import_tasks statement in the main.yml file of the role with include_tasks:

---
- include_tasks: tag-foo.yml
  tags:
    - foo
    - foo2

- include_tasks: tag-bar.yml
  tags:
    - bar

- include_tasks: always.yml
  tags:
    - always

- include_tasks: never.yml
  tags:
    - never
    - nevermind

But unfortunately nothing changed: the 'bar' task is executed anyway:

 ~/ansible > ansible-playbook -i test.ini plays/test.yml -l test.domain.local

PLAY [all] ********************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************
ok: [test.domain.local]

TASK [Execute test role with tag 'foo'] ***************************************************************************************************************

TASK [test : include_tasks] ***************************************************************************************************************************
included: /Users/me/ansible/roles/internal/test/tasks/tag-foo.yml for test.domain.local

TASK [test : This is tag 'foo'] ***********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'foo'"
}

TASK [test : include_tasks] ***************************************************************************************************************************
included: /Users/me/ansible/roles/internal/test/tasks/tag-bar.yml for test.domain.local

TASK [test : This is tag 'bar'] ***********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'bar'"
}

TASK [test : include_tasks] ***************************************************************************************************************************
included: /Users/me/ansible/roles/internal/test/tasks/always.yml for test.domain.local

TASK [test : This is tag 'always'] ********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'always'"
}

PLAY RECAP ********************************************************************************************************************************************
test.domain.local           : ok=7    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Upvotes: 4

Views: 5558

Answers (1)

zigarn
zigarn

Reputation: 11605

By using import_role, it's static re-use, the tag doesn't condition the import, but is added to every tasks of the imported role.

To condition the execution of the role with a tag, you should use a dynamic re-use with the include_role.

More documentation on import vs include: https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse.html#re-using-files-and-roles

Tags mechanism is made to be set through CLI. If you want to define different behavior of role through playbook, vars and when are better option:

- include_role: my_role
  vars:
     only_foo: True

# in my_role:
- debug:
     msg: Only on foo
  when: only_foo

Upvotes: 2

Related Questions