'How to use tags in included/imported tasks?

There is an example playbook with the main task:

---
- name: Include tasks
  include_tasks: include_task.yml
  # args:
  #   apply:
  #     tags: task
  tags: task

- name: Import tasks
  import_tasks: import_task.yml
  tags: task

- name: Main task
  debug:
    msg: The main task
  tags: main

include_task.yml:

---
- name: Subtask3
  debug:
    msg: Subtask3 include
  tags: task1

- name: Subtask4
  debug:
    msg: Subtask4 include
  tags: task2

import_task.yml:

---
- name: Subtask1
  debug:
    msg: Subtask1 import
  tags: task1

- name: Subtask2
  debug:
    msg: Subtask2 import
  tags: task2

A few of examples expected usages:

❯ ansible-playbook playbooks/playground.yml
localhost | SUCCESS => {
    "changed": false,
    "include": "include_task.yml",
    "include_args": {}
}
localhost | SUCCESS => {
    "msg": "Subtask3 include"
}
localhost | SUCCESS => {
    "msg": "Subtask4 include"
}
localhost | SUCCESS => {
    "msg": "Subtask1 import"
}
localhost | SUCCESS => {
    "msg": "Subtask2 import"
}
localhost | SUCCESS => {
    "msg": "The main task"
}

❯ ansible-playbook playbooks/playground.yml -t main
localhost | SUCCESS => {
    "msg": "The main task"
}

And a few examples of wrong usages:

❯ ansible-playbook playbooks/playground.yml -t task
localhost | SUCCESS => {
    "changed": false,
    "include": "include_task.yml",
    "include_args": {}
}
localhost | SUCCESS => {
    "msg": "Subtask1 import"
}
localhost | SUCCESS => {
    "msg": "Subtask2 import"
}

❯ ansible-playbook playbooks/playground.yml -t task,task1
localhost | SUCCESS => {
    "changed": false,
    "include": "include_task.yml",
    "include_args": {}
}
localhost | SUCCESS => {
    "msg": "Subtask3 include"
}
localhost | SUCCESS => {
    "msg": "Subtask1 import"
}
localhost | SUCCESS => {
    "msg": "Subtask2 import"

❯ ansible-playbook playbooks/playground.yml -t task,task2
localhost | SUCCESS => {
    "changed": false,
    "include": "include_task.yml",
    "include_args": {}
}
localhost | SUCCESS => {
    "msg": "Subtask4 include"
}
localhost | SUCCESS => {
    "msg": "Subtask1 import"
}
localhost | SUCCESS => {
    "msg": "Subtask2 import"

If I uncomment the fragment with:

args:
    apply:
      tags: task

it returns "valid" output only for: ❯ ansible-playbook playbooks/playground.yml -t task

I would like to achieve: when I use task tag, both tasks from include_task.yml or/and import_task.yml are executed. When I use task,task1 tags only the first subtask will be executed. And the similar situation for task,task2 tags.

Generally I use tags only in main.yml file. But sometimes I need a larger granulation, so I want to use additional tags in included/imported tasks. Is this possible?

I'm not sure if this is the correct, proper use of nested tags for import_tasks:

❯ ansible-playbook playbooks/playground.yml -t task2
localhost | SUCCESS => {
    "msg": "Subtask2 import"
}

❯ ansible-playbook playbooks/playground.yml -t task1
localhost | SUCCESS => {
    "msg": "Subtask1 import"
}

It seems to me that for a larger playbook, it would be better to use: ansible-playbook playbooks/playground.yml -t task,task1 instead of ansible-playbook playbooks/playground.yml -t task1. Because tag task1 can be used in several places.



Solution 1:[1]

The results are by design. Quoting from Tag inheritance for includes:

If you add tags to an include, they apply only to the include itself, not to any tasks in the included file

This explains the 'wrong usages'

  • -t task The file is included, but Subtask3 and Subtask4 tagged task1 and task2 respectively do not execute. Imported Subtask1 and Subtask2 execute because they inherit the tag task from the import.

  • -t task,task1 Subtask3 executes because task1 applies. Subtask1 and Subtask2 execute because task applies

  • -t task,task2 The same as above but Subtask4 executes instead of Subtask3

The fragment below applies the tag task to the included tasks. This explains the 'valid' results.

args:
    apply:
      tags: task

The tasks below solve the problems. The file include_task.yml will be always included and the tag task will be applied to included tasks

    - include_tasks: include_task.yml
      args:
        apply:
          tags: task
      tags: always
    - import_tasks: import_task.yml
      tags: task

See abridged results below

shell> ansible-playbook pb.yml | grep msg:
  msg: Subtask3 include
  msg: Subtask4 include
  msg: Subtask1 import
  msg: Subtask2 import
shell> ansible-playbook pb.yml -t task | grep msg:
  msg: Subtask3 include
  msg: Subtask4 include
  msg: Subtask1 import
  msg: Subtask2 import
shell> ansible-playbook pb.yml -t task1 | grep msg:
  msg: Subtask3 include
  msg: Subtask1 import
shell> ansible-playbook pb.yml -t task2 | grep msg:
  msg: Subtask4 include
  msg: Subtask2 import

You can't expect -t task,task1 or -t task,task2 to be more restrictive compared to -t task.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Vladimir Botka