Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tags from various levels should sum together. #5622

Closed
LukaszC opened this issue Jan 14, 2014 · 6 comments
Closed

Tags from various levels should sum together. #5622

LukaszC opened this issue Jan 14, 2014 · 6 comments
Assignees
Labels
bug This issue/PR relates to a bug. P1 Priority 1 - Immediate Attention Required; Release Immediately After Fixed

Comments

@LukaszC
Copy link

LukaszC commented Jan 14, 2014

We've noticed that tags assigned on various levels (playbook, tasks include) does not sum together but are rather overridden (counterintuitive I think).

Lets assume that I have two roles (roleA and roleB), in addition roleA depends on roleB.
Each role consists of two files in tasks/ subdirectory, main.yml and tasks.yml, where main.yml simply includes tasks.yml and assigns tag "tagRoleA". Same structure is for true for roleB, but the tag is called "tagRoleB". task.yml contains only one debug task.
Now, my playbook defines play with only one role: { role: roleA, tags: tagPlay }, as you can see we provide tags to the role "invocation" in playbook.

The behaviour I would expect it that roleA fires when we run ansible-playbook with following tags: NONE, tagPlay, tagRoleA. Moreover roleB will be invoked always when roleA is triggered.
However the behaviour is rather surprising (at least for me). When we run the playbook with tag "tagPlay", then we get error message that "tagPlay" is an unknown tag and only "tagRoleA" and "tagRoleB" are recognized as valid tags. When we run the playbook with tag "tagRoleA" then only roleA will be fired, roleB will not be triggered.

As far as I've managed to notice it is the include+tags definition which makes i.e. the tags defined at playbook level to disappear, but it is very convenient combination if you consider it together with issue: #5512

$ ansible --version
ansible 1.4.3

diff a/hosts b/hosts
--- /dev/null
+++ b/hosts
@@ -0,0 +1 @@
+localhost ansible_connection=local
diff a/play.yml b/play.yml
--- /dev/null
+++ b/play.yml
@@ -0,0 +1,4 @@
+---
+- hosts: localhost
+  roles:
+    - { role: roleA, tags: tagPlay }
diff a/roles/roleA/meta/main.yml b/roles/roleA/meta/main.yml
--- /dev/null
+++ b/roles/roleA/meta/main.yml
@@ -0,0 +1,2 @@
+dependencies:
+  - { role: roleB }
diff a/roles/roleA/tasks/main.yml b/roles/roleA/tasks/main.yml
--- /dev/null
+++ b/roles/roleA/tasks/main.yml
@@ -0,0 +1,3 @@
+- include: tasks.yml
+  tags:
+    - tagRoleA
diff a/roles/roleA/tasks/tasks.yml b/roles/roleA/tasks/tasks.yml
--- /dev/null
+++ b/roles/roleA/tasks/tasks.yml
@@ -0,0 +1,2 @@
+- name: "Debug from RoleA"
+  debug: msg="Debug from RoleA"
diff a/roles/roleB/tasks/main.yml b/roles/roleB/tasks/main.yml
--- /dev/null
+++ b/roles/roleB/tasks/main.yml
@@ -0,0 +1,3 @@
+- include: tasks.yml
+  tags:
+    - tagRoleB
diff a/roles/roleB/tasks/tasks.yml b/roles/roleB/tasks/tasks.yml
--- /dev/null
+++ b/roles/roleB/tasks/tasks.yml
@@ -0,0 +1,2 @@
+- name: "Debug from RoleB"
+  debug: msg="Debug from RoleB"
@mpdehaan
Copy link
Contributor

I'm finding these diffs a little hard to read, can you reformat this so to just show the files in question (or to maybe link a gist?)

Thanks!

@LukaszC
Copy link
Author

LukaszC commented Jan 15, 2014

Indeed I wasn't sure if it is a good way to share the example. The best would probably be tar.gz/zip.

It should be possible to copy the content of the diff above to a file (i.e. 1.patch) and run: patch -p1 < 1.patch

@mpdehaan mpdehaan added P2 and removed P2 labels Mar 19, 2014
@jctanner jctanner self-assigned this Mar 19, 2014
@jctanner
Copy link
Contributor

NONE is not a valid tag for devel ...

$ ansible-playbook -i inventory site.yml -t NONE,tagPlay,tagRoleA
ERROR: tag(s) not found in playbook: NONE.  possible values: tagRoleB

Dropping the NONE tag, I get the following result ..

$ ansible-playbook -i inventory site.yml -t tagPlay

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

TASK: [roleB | debug msg="roleB main"] **************************************** 
ok: [localhost] => {
    "item": "", 
    "msg": "roleB main"
}

TASK: [roleA | debug msg="roleA main"] **************************************** 
ok: [localhost] => {
    "item": "", 
    "msg": "roleA main"
}

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

Note that none of the included task files were run. This is the output when no tags are specified:

$ ansible-playbook -i inventory site.yml 

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

TASK: [roleB | debug msg="roleB main"] **************************************** 
ok: [localhost] => {
    "item": "", 
    "msg": "roleB main"
}

TASK: [roleB | debug msg="roleB tasks"] *************************************** 
ok: [localhost] => {
    "item": "", 
    "msg": "roleB tasks"
}

TASK: [roleA | debug msg="roleA main"] **************************************** 
ok: [localhost] => {
    "item": "", 
    "msg": "roleA main"
}

TASK: [roleA | debug msg="roleA tasks"] *************************************** 
ok: [localhost] => {
    "item": "", 
    "msg": "roleA tasks"
}

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

@jctanner
Copy link
Contributor

Preliminary patch:

diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py
index e3e5fef..a888ced 100644
--- a/lib/ansible/playbook/play.py
+++ b/lib/ansible/playbook/play.py
@@ -142,6 +142,7 @@ class Play(object):
         self._tasks      = self._load_tasks(self._ds.get('tasks', []), load_vars)
         self._handlers   = self._load_tasks(self._ds.get('handlers', []), load_vars)

+        self._late_merge_role_tags()

         if self.sudo_user != 'root':
             self.sudo = True
@@ -712,6 +713,33 @@ class Play(object):

     # *************************************************

+    def _late_merge_role_tags(self):
+        # build a local dict of tags for roles
+        role_tags = {}
+        for task in self._ds['tasks']:
+            if 'role_name' in task:
+                this_role = task['role_name']
+
+                if this_role not in role_tags:
+                    role_tags[this_role] = []
+
+                if 'tags' in task['vars']:
+                    if isinstance(task['vars']['tags'], basestring):
+                        role_tags[task['role_name']] += shlex.split(task['vars']['tags'])
+                    else:
+                        role_tags[task['role_name']] += task['vars']['tags']
+
+        # apply each role's tags to it's tasks
+        for idx, val in enumerate(self._tasks):
+            if hasattr(val, 'role_name'):
+                this_role = val.role_name
+                if this_role in role_tags:
+                    self._tasks[idx].tags = sorted(set(self._tasks[idx].tags + role_tags[this_role]))
+                    #import epdb; epdb.st()
+
+
+    # *************************************************
+
     def _has_vars_in(self, msg):
         return "$" in msg or "{{" in msg

@jctanner
Copy link
Contributor

@LukaszC this should be fixed based on my understanding of the issue.

@pyykkis
Copy link
Contributor

pyykkis commented Mar 30, 2014

@jctanner Does it also merge tags from multiple level of includes?

I'd like to give my role a top-level tag which is inherited to all tasks below and additionally tag individual tasks

# playbook.yml
---
  ...
  - roles: 
    - base
    - nginx

# roles/base/tasks/main.yml
---
- include: base.yml tags=base

# roles/base/tasks/base.yml
---
- include: ssh.yml tags=ssh
- include: ufw.yml tags=ufw
...

# roles/base/tasks/ssh.yml
---
...

As an end result, I'd like to be able to run playbook either with base or ssh tag, e.g.,

ansible-playbook playbook.yml --tags base
ansible-playbook playbook.yml --tags ssh

jimi-c pushed a commit that referenced this issue Dec 6, 2016
* Change example syntax on supervisorctl module

* Change example syntax or _ec2_ami_search module

* Change example syntax on cloudformation module

* Change example syntax on ec2 module

* Change example syntax on ec2_facts module

* Change example syntax on ec2_eip module

* Change example syntax on rds module

* Change example syntax on route53 module

* Change example syntax on s3 module

* Change example syntax on digital_ocean module

* Change example syntax on docker_service module

* Change example syntax on cloudformation module

* Change example syntax on gc_storage module

* Change example syntax on gce module

* Change example syntax on gce_mig module

* Change example syntax on _glance_image module

* Change example syntax on _keystone_user module

* Change example syntax on _nova_keypair module

* Change example syntax on _quantum_floating module

* Change example syntax on _quantum_floating_ip_associate module

* Change example syntax on _quantum_network module

* Change example syntax on _quantum_router module

* Change example syntax on _quantum_router_gateway module

* Change example syntax on _quantum_router_interface module

* Change example syntax on _quantum_subnet module

* SQUASH _quantum_subnet

* Add missing quotes
@ansibot ansibot added bug This issue/PR relates to a bug. and removed bug_report labels Mar 6, 2018
@ansible ansible locked and limited conversation to collaborators Apr 24, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug This issue/PR relates to a bug. P1 Priority 1 - Immediate Attention Required; Release Immediately After Fixed
Projects
None yet
Development

No branches or pull requests

5 participants