10

Ansible 2.8.1

In my playbook tasks/ dir:

main.yml
dev.yml

In main.yml I have a block like this:

- include_tasks: dev.yml
  when: ec2_tag_env == 'dev'

It works fine


However, if I try to call a specific task within dev.yml using a tag. It won't qualify the task during the run

For example, this tagged task within dev.yml:

- name: Pull the latest image
  docker_image:
    name: "{{ dev_image }}"
    source: pull
  tags:
    - container

When I run the playbook with -t container it will NOT qualify since the include_tasks step doesn't have that tag.


Adding the tag to include_tasks will of course fix the problem, but I would then need to keep track of tags as they get added to sub-tasks and add them here as well:

- include_tasks: dev.yml
  when: ec2_tag_env == 'dev'
  tags:
    - container

Questions

  • Is it possible to have Ansible just "know" what tasks are within the include_tasks block and pull the applicable tags?

  • What's the best practice for achieving this goal?

What I would prefer to not have to do:

  • Put everything main.yml. I have so many tasks in this playbook I really want to keep them organized in files.
  • Tag all my include_tasks blocks with all its sub-tags manually. Sounds like a nightmare to manage.

3 Answers 3

7

Q: "Is it possible to have Ansible just 'know' what tasks are within the include_tasks block and pull the applicable tags?"

A: What is inside included task will be available after the control flow reaches the include_task statement and the file is included. See the examples below under the line. For example, such tags won't be included in the list of available tags. See option --list-tags of ansible-playbook. In this respect, the answer is no. But, such tags may be available (after the control flow reaches the include_task statement) if also specified on the level of the include_task. Also, the special tag always makes such tags available.

Q: "What's the best practice for achieving this goal?"

A: There are two options:

  • Either use import_tasks. The imports are read when the playbook starts.

  • Or, use the special tag always. Ansible will always include the tasks from the file.


To clarify the differences. Given the file below

shell> cat install.yml
- debug:
    msg: Task 2
  tags: t2
- debug:
    msg: Task 3
  tags: t3
  1. The playbook
shell> cat pb1.yml
- hosts: localhost
  tasks:
    - debug:
        msg: Task 1
      tags: t1
    - include_tasks:
        file: install.yml

works as expected

shell> ansible-playbook pb1.yml

PLAY [localhost] *****************************************************************************

TASK [debug] *********************************************************************************
ok: [localhost] => 
  msg: Task 1

TASK [include_tasks] *************************************************************************
included: /export/scratch/tmp8/test-828/install.yml for localhost

TASK [debug] *********************************************************************************
ok: [localhost] => 
  msg: Task 2

TASK [debug] *********************************************************************************
ok: [localhost] => 
  msg: Task 3

PLAY RECAP ***********************************************************************************
localhost: ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

When the tags are used -t t1,t2, the task tagged t1 is executed, but the task tagged t2 is not because the file is not included

shell> ansible-playbook pb1.yml -t t1,t2

PLAY [localhost] *****************************************************************************

TASK [debug] *********************************************************************************
ok: [localhost] => 
  msg: Task 1

PLAY RECAP ***********************************************************************************
localhost: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

Note that, when started, the application knows nothing about the tags in the included file

shell> ansible-playbook pb1.yml --list-tags

playbook: pb1.yml

  play #1 (localhost): localhost    TAGS: []
      TASK TAGS: [t1]

  1. Tag always the task include_tasks
shell> cat pb2.yml
- hosts: localhost
  tasks:
    - debug:
        msg: Task 1
      tags: t1
    - include_tasks:
        file: install.yml
      tags: always

When started, the application still knows nothing about the tags in the included file but the tasks will be always included

shell> ansible-playbook pb2.yml --list-tags

playbook: pb1.yml

  play #1 (localhost): localhost    TAGS: []
      TASK TAGS: [always, t1]

When the tags -t t1,t2 are used now both tasks tagged t1 and t2 are executed

shell> ansible-playbook pb2.yml -t t1,t2

PLAY [localhost] *****************************************************************************

TASK [debug] *********************************************************************************
ok: [localhost] => 
  msg: Task 1

TASK [include_tasks] *************************************************************************
included: /export/scratch/tmp8/test-828/install.yml for localhost

TASK [debug] *********************************************************************************
ok: [localhost] => 
  msg: Task 2

PLAY RECAP ***********************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

  1. The tag always causes that the file install.yml will always be included when the control flow reaches the include_task statement. But this tag applies to the include_task only. It's not inherited by the tasks inside the file. If you want to apply tags to the tasks inside the file use the parameter apply. For example
shell> cat pb3.yml
- hosts: localhost
  tasks:
    - debug:
        msg: Task 1
      tags: t1
    - include_tasks:
        file: install.yml
        apply:
          tags: install
      tags: always

Note that also here, when started, the application knows nothing about both the applied tags and the tags in the included file

shell> ansible-playbook pb3.yml --list-tags

playbook: pb3.yml

  play #1 (localhost): localhost    TAGS: []
      TASK TAGS: [always, t1]

The only difference caused by the applied tag is that all included tasks can be triggered by this tag, e.g.

shell> ansible-playbook pb3.yml -t install

PLAY [localhost] *****************************************************************************

TASK [include_tasks] *************************************************************************
included: /export/scratch/tmp8/test-828/install.yml for localhost

TASK [debug] *********************************************************************************
ok: [localhost] => 
  msg: Task 2

TASK [debug] *********************************************************************************
ok: [localhost] => 
  msg: Task 3

PLAY RECAP ***********************************************************************************
localhost: ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

But, the applied tags won't help you in triggering the included tasks separately. It is also good to understand that the applied tags make no sense without the same tags, or special tag always, on the include_task level.

2
  • Do I understand this correctly? That the apply: tag: construct makes each task inside the included task file act as if it has the applied tag(s)? Would putting tags: 'install' on each task inside install.yml be similar to applying the 'install' tag on the include_task?
    – Jeter-work
    May 10, 2022 at 15:48
  • 1
    Exactly! This is the purpose of apply: tags. This substitutes the missing inheritance of tags on the include_tasks level. May 10, 2022 at 16:14
9

Kind of an old question, but for others who might struggle because they want or need to use include_tasks instead of import_tasks. To those who can use both, I would also highly recommend to use import_tasks like it was answered before:

In the official Ansible manual, the developers propose to use tags: always on include_tasks itself while applying other tags with apply: to the included tasks.

See this example (copied from the manual):

- name: Apply tags to tasks within included file
  include_tasks:
    file: install.yml
    apply:
      tags:
        - install
  tags:
    - always

This way ensures that Ansible will always (except when called with --skip-tags always) include the external tasks to be able to look at those specific tags, so if install.yml includes a task with tags: download this task will be run if Ansible was called with --tags download (without adding install).

-1

I would recommend the post about this from Red Hat: https://www.redhat.com/sysadmin/ansible-tags-fast-playbook-runs

1
  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
    – Dave M
    Nov 14, 2022 at 12:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .