include_roles, with tags from a dictionary loop?

527 views
Skip to first unread message

dkol...@olearycomputers.com

unread,
Jan 11, 2022, 9:53:19 AM1/11/22
to Ansible Project
Hey;

I'm having difficulty coming up with the right syntax to add/include roles, with tags, from a loop such that I can limit execution to specific tags.  

In the tasks section, this syntax works:

############################################################
# This syntax works but isn't very flexible.  It does, however,
# allow us to select specific tasks to run.
  - name: include root role
    include_role:
      name: root
    tags:
      - rootpwd
      - rootbin
      - rootkeys
      - drex

  - name: include commone role
    include_role:
      name: common


and I can limit execution by running  'ansible-playbook ./pb.yml -l grp -l rootpwd' for instance.  That's not very flexible; however, as I'd like to avoid having to edit the playbook every time a role gets a new tag.  

I have a structure in my group_vars/all file thusly:

commonroles:
  - { n: common,  t: [ 'nil' ] }
  - { n: root,    t: [ 'rootpwd', 'rootbin', 'rootkeys', 'drex' ] }


Debug tasks show I have the syntax the way I expect; however, I can't seem to get the include_role module to use the structure

For example, this syntax, in the tasks section, results in no tags::

  - name: include common roles
    include_role:
      name: "{{rolename.n}}"
      apply:
        tags: "{{rolename.t}}"
    loop: "{{commonroles}}"
    loop_control:
      loop_var: rolename


$ ansible-playbook ./configmgmt.yml -l amwtest --list-tags

playbook: ./configmgmt.yml

  play #1 (all): Main configuration management playbook TAGS: []
      TASK TAGS: []


Without the --ilst-tags, this results in an error:

FAILED! => {"msg": "the field 'tags' should be a list of ((<class 'str'>,), <class 'int'>), but the item '['nil']' is a <class 'list'>

So, it seems my issue is how I'm trying to present the tags...

Any ideas on how I can create a data structure of roles and tags that's usable by include_role  via a loop?

Thanks for any hints/tips/suggestions.

Doug O'Leary

Stefan Hornburg (Racke)

unread,
Jan 11, 2022, 10:20:29 AM1/11/22
to ansible...@googlegroups.com
On 11/01/2022 15:53, dkol...@olearycomputers.com wrote:
> Hey;
>
> I'm having difficulty coming up with the right syntax to add/include roles, with tags, from a loop such that I can limit execution to specific tags.

Hello,

in my opinion tags should be use to control the playbook flow and not to determine which role is getting to applied to a server.

This belongs to the inventory:

- import_role:
name: mysql
when: "'mysql_servers' in group_names"

- import_role:
name: nginx
when: "'nginx_servers' in group_names"

This is more flexible than tags and a better place for the assignment of the roles.

Regards
Racke
> --
> You received this message because you are subscribed to the Google Groups "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com <mailto:ansible-proje...@googlegroups.com>.
> To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/1ca6c514-2fb0-42d4-a9d1-a8225fbd389fn%40googlegroups.com <https://groups.google.com/d/msgid/ansible-project/1ca6c514-2fb0-42d4-a9d1-a8225fbd389fn%40googlegroups.com?utm_medium=email&utm_source=footer>.


--
Ecommerce and Linux consulting + Perl and web application programming.
Debian and Sympa administration.

OpenPGP_signature

dkol...@olearycomputers.com

unread,
Jan 11, 2022, 10:37:42 AM1/11/22
to Ansible Project
Hey;  Thanks for the reply.  For clarity, I'm not using tags to identify what roles get assigned to specific hosts - I'm (going to be) using ansible group membership for that.  I have a dynamic inventory script that generates host groups very reliably - I've been using it with ad-hoc runs for months to great effect.  These two roles - and maybe a couple of more - will be applied to all hosts and I'll have another set of roles for specific host types.

The root role, for instance, has 4 included tasks:

$ grep include roles/root/tasks/main.yml
- include_tasks: rootpwd.yml
- include_tasks: rootbin.yml
- include_tasks: root_keys.yml
- include_tasks: drexercise.yml

The initial use case is testing to verify the new included task actually works; however, when all is said and done, being able to execute just the drexercise for our periodic dr tests, rather than the entire playbook including all applicaiton settings, would be much quicker.

Thanks again for the reply.

Doug

Brian Coca

unread,
Jan 11, 2022, 12:15:30 PM1/11/22
to Ansible Project
You cannot limit tag execution this way, that ONLY applies the tag to
the include task itself, then the tag must be selected or rejected
from CLI --tags/--skip-tags.

The `tags:` keyword is ONLY for assignment of tags, never for selection.

--
----------
Brian Coca

dkol...@olearycomputers.com

unread,
Jan 11, 2022, 1:07:57 PM1/11/22
to Ansible Project
Hey;

thanks for the reply.  I'm not real clear on your meaning, though.  I already know this works.  When I include the roles explicitly, with tags, I can limit execution to a specific tag via the --tags cli arg.  Example:

[[snip]]
############################################################
# This syntax works but isn't very flexible.  It does, however,
# allow us to select specific tasks to run.
  - name: include root role
    include_role:
      name: root
    tags:
      - rootpwd
      - rootbin
      - rootkeys
      - drex

  - name: include commone role
    include_role:
      name: common


$ ansible-playbook ./pb.yml -l amwtest --tags drex

The playbook run referenced, when the roles are explicitly defined like that, only executes the tasks tagged as drex.  I'm looking to loop through a defined set of roles and apply role-specific tags to them.  

this doesn't work; at least not with anything close to what I showed above.  I really seems like there should be a way to do this, though.

commonroles:
  - { n: common,  t: [ 'dirperms', 'kernelparms' ] }
  - { n: root,    t: [ 'rootpwd', 'rootbin',  'rootkeys' 'drex' ] }


Thanks

Doug

Brian Coca

unread,
Jan 11, 2022, 2:05:59 PM1/11/22
to Ansible Project
yes, sorry, i had incorrectly inferred from your previous email that
you were trying to do the limiting via `tags:`, also note that while
tags: on include_role affects the execution of the 'include_role'
itself, it does not tag the included tasks, you nee to use apply: for
such things (unlike import_ which ignores the tags: and is always used
for imported tasks to inherit).


--
----------
Brian Coca

Todd Lewis

unread,
Jan 11, 2022, 3:02:55 PM1/11/22
to Ansible Project
The "FAILED! …" message you cited is (I'm guessing; if I'm wrong I'll gladly give you a refund) due to the hopeless ambiguities created by python's treatment of strings as lists, and because Ansible is more an extension of python than it is an application written in python, so stuff like this — obscure references to inaccessible details — percolates up to the user level. (Why would an application throw implementation-language specific errors like that at users? Because the application is "python with Ansible extensions!") Try changing your line to

apply:
  tags: "{{ [ rolename.t ] }}"

or go with

apply:
  tags:
    - "{{ rolename.t }}"

or even

apply:
  tags: "{{ rolename.t | join(',') }}"

which should have the same effect, but doesn't always because, well, python.

But more to the point: you don't want to do this with tags. In fact I doubt this will work despite your earlier testing which lead you to believe this is a fruitful approach. Defer your insanity by using "tasks_from: '{{ ... }}'" and structure your, er, structure to reflect your roles' task files, possibly moderated by clever used of ansible_run_tags if you must.

Or maybe it'll work! I hope I'm wrong. Really. Good luck.
Reply all
Reply to author
Forward
0 new messages