1

While many may like ansible, to me it seems with it rather conflating and somewhat redundant concepts like tags, roles, inventory/hosts files, hostgroups, playbooks, tasks "when" conditionals there is quite some challange to determine what eventually will be executed. The issue at core of this question is tags.

My understanding is that if I have a playbook in which there is a role that contains a list of tags, those are added (inherited) by all of the contained tasks

Example:

[----./playbook.yml----]

---
- hosts: all
  roles: 
  - {role: role01, tags: ['tag01', 'tag02']} 
  - {role: role02, tags: ['tag01', 'tag03']}

would mean that all tasks found in ./roles/role01/tasks/main.yml would implicitly be tagged with tag01 and tag02. Confirming this would be part of an answer to this question

Likewise all tasks in ./roles/role02/tasks/main.yml are hence tagged tag01 and tag03, right?

Now the issue here is that looking at the file ./roles/role01/tasks/main.yml I see this content

[----./roles/role01/tasks/main.yml----]
---
- block:
  - name: "upgrade all packages"
    yum:
      name: '*'
      state: latest
  tags:
    - tag01

Considering that the role is exclusively only ever refered from the line of ./playbook.yml shown above, I fail to see how it makes any sense to have the tag01 since it should be implicitly tagged given the line:

- {role: role01, tags: ['tag01', 'tag02']}

Also it completely disturbs me that another ansible concept block, had to be used here?

Aspects to the question:

  1. Was tagging in the role's main.yml superflous ?
  2. Why the use of a block (considering there is only one task anyway)?
β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
fraleone
  • 121
  • 4

1 Answers1

1

TL;Dr: yes indeed in the case explained in the question (the implicit tagging at the level of the ansible role, makes the tagging of the individual task/block inside of the role unnecessary and hence superfluous).

Longer information:

Ansible, sadly invites often overly complicated and contorted syntax and style. In this very case it was only an unnecessary duplicate tagging, combined with an equally not necessary using of the syntactical element of a block (in ansible playbook).

How was the behaviour of ansible with regards to tagging verified/tested? => with a shell/bash sctipt:

I have resorted to this shell script that should test, how ansible tags behave in relationship to this implicit inheritance with respect to roles.

the bash script will create an minimal ansible test case, which contains two roles role1 and role2, both being verbatim copies with exception of the name (so to be able to tell them appart) and with 2 tasks:

  • task(A) is not explicitly tagged
  • task(B) is explicitly tagged with the tag 'tag01'.

A necessary ansible playbook.yml and host/inventory file inventory.ini is also created in the script:

#!/bin/bash

#make a temporary directory for test
TEMPDIR="$(mktemp -d)"
#change to temporary directory
cd "$TEMPDIR"

# create ansible hosts file "./inventory.ini" 
# only host we need is the the local box (to be simple disregard any ssh overhead)
cat > inventory.ini <<'EOF'
[hosts]
localhost ansible_connection=local
EOF

# create ansilble role "role1"
# (to keep it simple, we have minimal role with only a tasks entry)
mkdir -p roles/role1/tasks
# (the content for the tasks/main.yml file are two tasks, with one task
#  namely task(A) not being explicitly and the task(B) being explicitly
#  tagged)
cat > roles/role1/tasks/main.yml <<'EOF'
---
# tasks file for role1 and role2

- name: "task(A) tagged not explicitly 'tag01'"
  debug:
    msg: "debug-msg: this is \"task(A) tag explicitly 'tag01'\" {{ role_name }} ."

- name: "task(B) tagged explicitly 'tag01'"
  debug:
    msg: "debug-msg: this is \"task(B) tagged explicitly 'tag01'\" {{ role_name }} ."
  tags:
  - tag01
EOF


# create ansible role "role2" as a verbatim copy of "role1"
cp -r roles/role1 roles/role2

# now create an ansible playbook that uses these two ansible roles 
# (note that for the role "role1" we used "implicit tagging"
cat > playbook.yml <<'EOF'
---
- hosts: all
  roles:
  - role: "role1"
    tags: 
    - "tag01"
  - role: "role2"
EOF

# show the test setup 
find . 

# TEST 1:
# run "playbook.yml" one time "as is" ( i.e. no using of tags -> "all tasks"
# should be run)
echo "TEST1" | tee TEST1
ansible-playbook -i inventory.ini playbook.yml | tee -a TEST1

# TEST 2:
# run "playbook.yml" with --tags command line options ( meaning this time
# we limit the task to be run to only those that have the specific tag)
echo "TEST2" | tee TEST2
ansible-playbook -i inventory.ini --tags 'tag01' playbook.yml | tee -a TEST2

# TEST 3:
# run "playbook.yml" with --skip-tags command line options ( meaning this time
# we limit the task to be run all, but those to tags to be "skipped")
echo "TEST3" | tee TEST3
ansible-playbook -i inventory.ini --skip-tags 'tag01' playbook.yml | tee -a TEST3

# show path of temporary directory 
echo "TEMPDIR is $TEMPDIR"

Having run this shell script it basically yields three results for

  1. Test 1 "TEST1", ansible-playbook -i inventory.ini playbook.yml: no tags usage => any implicit or explicit tagging is of no concurn all tasks for both roles role1 and role2 are run:
    TEST1

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

    TASK [Gathering Facts] **************************************************************************
    ok: [localhost]

    TASK [role1 : task(A) tagged not explicitly 'tag01'] **************************************************************************
    ok: [localhost] => {
        "msg": "debug-msg: this is \"task(A) tag explicitly 'tag01'\" role1 ."
    }

    TASK [role1 : task(B) tagged explicitly 'tag01'] **************************************************************************
    ok: [localhost] => {
        "msg": "debug-msg: this is \"task(B) tagged explicitly 'tag01'\" role1 ."
    }

    TASK [role2 : task(A) tagged not explicitly 'tag01'] **************************************************************************
    ok: [localhost] => {
        "msg": "debug-msg: this is \"task(A) tag explicitly 'tag01'\" role2 ."
    }

    TASK [role2 : task(B) tagged explicitly 'tag01'] **************************************************************************
    ok: [localhost] => {
        "msg": "debug-msg: this is \"task(B) tagged explicitly 'tag01'\" role2 ."
    }

    PLAY RECAP **************************************************************************
    localhost                  : ok=5    changed=0    unreachable=0    failed=0   
   
  1. Test 2 "TEST2", ansible-playbook -i inventory.ini --tags 'tag01' playbook.yml: tags are used => implicit and explicit tagging matters. Since tag01 is set for role1 at level of the role both contained tasks task(A) and task(B) are run. Contrastingly for role2 without the implictely inherited tagging only task(B) is run. The output shows that:
TEST2

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

    TASK [Gathering Facts] **************************************************************************
    ok: [localhost]

    TASK [role1 : task(A) tagged not explicitly 'tag01'] **************************************************************************
    ok: [localhost] => {
        "msg": "debug-msg: this is \"task(A) tag explicitly 'tag01'\" role1 ."
    }

    TASK [role1 : task(B) tagged explicitly 'tag01'] **************************************************************************
    ok: [localhost] => {
        "msg": "debug-msg: this is \"task(B) tagged explicitly 'tag01'\" role1 ."
    }

    TASK [role2 : task(B) tagged explicitly 'tag01'] **************************************************************************
    ok: [localhost] => {
        "msg": "debug-msg: this is \"task(B) tagged explicitly 'tag01'\" role2 ."
    }

    PLAY RECAP **************************************************************************
    localhost                  : ok=4    changed=0    unreachable=0    failed=0   
    
  1. Lastly the Test 3 "TEST3" inverts all with --skip-tags where the implicit tagging for role1 causes the whole role to be skipped. For ansible-playbook -i inventory.ini --skip-tags 'tag01' playbook.yml we have the following result:

TEST3

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

    TASK [Gathering Facts] **************************************************************************
    ok: [localhost]

    TASK [role2 : task(A) tagged not explicitly 'tag01'] **************************************************************************
    ok: [localhost] => {
        "msg": "debug-msg: this is \"task(A) tag explicitly 'tag01'\" role2 ."
    }

    PLAY RECAP **************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0   
    

In conclusion and to keep close with the topic of the question, the a tag for a task contained in a role, is superflous, if that very role is (a) already tagged itself in the playbook and hence makes all its task implicitly inherit the task and b) this is the only playbook the role is used anyway (as it was the case here).

Although the ouput can be generated via executing the shell script provided here its output as a courtesy and for being complete:

.
./playbook.yml
./roles
./roles/role2
./roles/role2/tasks
./roles/role2/tasks/main.yml
./roles/role1
./roles/role1/tasks
./roles/role1/tasks/main.yml
./inventory.ini
TEST1

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

TASK [Gathering Facts] **************************************************************************
ok: [localhost]

TASK [role1 : task(A) tagged not explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
    "msg": "debug-msg: this is \"task(A) tag explicitly 'tag01'\" role1 ."
}

TASK [role1 : task(B) tagged explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
    "msg": "debug-msg: this is \"task(B) tagged explicitly 'tag01'\" role1 ."
}

TASK [role2 : task(A) tagged not explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
    "msg": "debug-msg: this is \"task(A) tag explicitly 'tag01'\" role2 ."
}

TASK [role2 : task(B) tagged explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
    "msg": "debug-msg: this is \"task(B) tagged explicitly 'tag01'\" role2 ."
}

PLAY RECAP **************************************************************************
localhost                  : ok=5    changed=0    unreachable=0    failed=0   

TEST2

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

TASK [Gathering Facts] **************************************************************************
ok: [localhost]

TASK [role1 : task(A) tagged not explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
    "msg": "debug-msg: this is \"task(A) tag explicitly 'tag01'\" role1 ."
}

TASK [role1 : task(B) tagged explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
    "msg": "debug-msg: this is \"task(B) tagged explicitly 'tag01'\" role1 ."
}

TASK [role2 : task(B) tagged explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
    "msg": "debug-msg: this is \"task(B) tagged explicitly 'tag01'\" role2 ."
}

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

TEST3

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

TASK [Gathering Facts] **************************************************************************
ok: [localhost]

TASK [role2 : task(A) tagged not explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
    "msg": "debug-msg: this is \"task(A) tag explicitly 'tag01'\" role2 ."
}

PLAY RECAP **************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0   

TEMPDIR is /tmp/tmp.cPE6a4gGiG
fraleone
  • 121
  • 4