diff --git a/changelogs/fragments/tags-var.yaml b/changelogs/fragments/tags-var.yaml new file mode 100644 index 00000000000..40c581cd723 --- /dev/null +++ b/changelogs/fragments/tags-var.yaml @@ -0,0 +1,2 @@ +bugfixes: +- tags - allow tags to be specified by a variable (https://github.com/ansible/ansible/issues/49825) diff --git a/lib/ansible/playbook/taggable.py b/lib/ansible/playbook/taggable.py index 38b43620a00..d8a715826da 100644 --- a/lib/ansible/playbook/taggable.py +++ b/lib/ansible/playbook/taggable.py @@ -19,8 +19,6 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type -import itertools - from ansible.errors import AnsibleError from ansible.module_utils.six import string_types from ansible.playbook.attribute import FieldAttribute @@ -32,9 +30,6 @@ class Taggable: untagged = frozenset(['untagged']) _tags = FieldAttribute(isa='list', default=list, listof=(string_types, int), extend=True) - def __init__(self): - super(Taggable, self).__init__() - def _load_tags(self, attr, ds): if isinstance(ds, list): return ds @@ -54,13 +49,14 @@ class Taggable: templar = Templar(loader=self._loader, variables=all_vars) tags = templar.template(self.tags) - if not isinstance(tags, list): - if tags.find(',') != -1: - tags = set(tags.split(',')) + _temp_tags = set() + for tag in tags: + if isinstance(tag, list): + _temp_tags.update(tag) else: - tags = set([tags]) - else: - tags = set([i for i, _ in itertools.groupby(tags)]) + _temp_tags.add(tag) + tags = _temp_tags + self.tags = list(tags) else: # this makes isdisjoint work for untagged tags = self.untagged diff --git a/test/integration/targets/tags/runme.sh b/test/integration/targets/tags/runme.sh index 311933902f4..949fbd5fb94 100755 --- a/test/integration/targets/tags/runme.sh +++ b/test/integration/targets/tags/runme.sh @@ -14,7 +14,7 @@ export LC_ALL=en_US.UTF-8 # Run everything by default [ "$("${COMMAND[@]}" | grep -F Task_with | xargs)" = \ -"Task_with_tag TAGS: [tag] Task_with_always_tag TAGS: [always] Task_with_unicode_tag TAGS: [くらとみ] Task_with_list_of_tags TAGS: [café, press] Task_without_tag TAGS: []" ] +"Task_with_tag TAGS: [tag] Task_with_always_tag TAGS: [always] Task_with_unicode_tag TAGS: [くらとみ] Task_with_list_of_tags TAGS: [café, press] Task_without_tag TAGS: [] Task_with_csv_tags TAGS: [tag1, tag2] Task_with_templated_tags TAGS: [tag3]" ] # Run the exact tags, and always [ "$("${COMMAND[@]}" --tags tag | grep -F Task_with | xargs)" = \ @@ -22,11 +22,11 @@ export LC_ALL=en_US.UTF-8 # Skip one tag [ "$("${COMMAND[@]}" --skip-tags tag | grep -F Task_with | xargs)" = \ -"Task_with_always_tag TAGS: [always] Task_with_unicode_tag TAGS: [くらとみ] Task_with_list_of_tags TAGS: [café, press] Task_without_tag TAGS: []" ] +"Task_with_always_tag TAGS: [always] Task_with_unicode_tag TAGS: [くらとみ] Task_with_list_of_tags TAGS: [café, press] Task_without_tag TAGS: [] Task_with_csv_tags TAGS: [tag1, tag2] Task_with_templated_tags TAGS: [tag3]" ] # Skip a unicode tag [ "$("${COMMAND[@]}" --skip-tags 'くらとみ' | grep -F Task_with | xargs)" = \ -"Task_with_tag TAGS: [tag] Task_with_always_tag TAGS: [always] Task_with_list_of_tags TAGS: [café, press] Task_without_tag TAGS: []" ] +"Task_with_tag TAGS: [tag] Task_with_always_tag TAGS: [always] Task_with_list_of_tags TAGS: [café, press] Task_without_tag TAGS: [] Task_with_csv_tags TAGS: [tag1, tag2] Task_with_templated_tags TAGS: [tag3]" ] # Run just a unicode tag and always [ "$("${COMMAND[@]}" --tags 'くらとみ' | grep -F Task_with | xargs)" = \ @@ -39,3 +39,11 @@ export LC_ALL=en_US.UTF-8 # Run tag with never [ "$("${COMMAND[@]}" --tags donever | grep -F Task_with | xargs)" = \ "Task_with_always_tag TAGS: [always] Task_with_never_tag TAGS: [donever, never]" ] + +# Run csv tags +[ "$("${COMMAND[@]}" --tags tag1 | grep -F Task_with | xargs)" = \ +"Task_with_always_tag TAGS: [always] Task_with_csv_tags TAGS: [tag1, tag2]" ] + +# Run templated tags +[ "$("${COMMAND[@]}" --tags tag3 | grep -F Task_with | xargs)" = \ +"Task_with_always_tag TAGS: [always] Task_with_templated_tags TAGS: [tag3]" ] diff --git a/test/integration/targets/tags/test_tags.yml b/test/integration/targets/tags/test_tags.yml index 5f575da7627..a53ba1ade88 100644 --- a/test/integration/targets/tags/test_tags.yml +++ b/test/integration/targets/tags/test_tags.yml @@ -3,6 +3,9 @@ hosts: localhost gather_facts: False connection: local + vars: + the_tags: + - tag3 tasks: - name: Task_with_tag debug: msg= @@ -23,3 +26,9 @@ - name: Task_with_never_tag debug: msg=NEVER tags: ['never', 'donever'] + - name: Task_with_csv_tags + debug: msg=csv + tags: tag1,tag2 + - name: Task_with_templated_tags + debug: msg=templated + tags: "{{ the_tags }}" diff --git a/test/units/playbook/test_taggable.py b/test/units/playbook/test_taggable.py index 573c1329245..ab5f86b46a6 100644 --- a/test/units/playbook/test_taggable.py +++ b/test/units/playbook/test_taggable.py @@ -98,8 +98,5 @@ class TestTaggable(unittest.TestCase): def test_evaluate_tags_accepts_lists(self): self.assert_evaluate_equal(True, ['tag1', 'tag2'], ['tag2'], []) - def test_evaluate_tags_accepts_strings(self): - self.assert_evaluate_equal(True, 'tag1,tag2', ['tag2'], []) - def test_evaluate_tags_with_repeated_tags(self): self.assert_evaluate_equal(False, ['tag', 'tag'], [], ['tag'])