From 95fa770ba0d9b59b1877974bcae98b7606b3b19d Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Sun, 8 Feb 2015 22:51:18 -0500 Subject: [PATCH] adds complex tag management Adds a special tag: - always: always runs no matter what --tags, --skip-tags say Adds 4 special keywords for --tags/skip-tags - all: all tagged + untagged tasks - tagged: only tagged tasks - untagged: only untagged tasks - always: only run tasks tagged 'always' --- lib/ansible/playbook/__init__.py | 45 ++++++++++++++++++++++++-------- lib/ansible/playbook/play.py | 23 ++++++++++++++-- lib/ansible/playbook/task.py | 5 +++- 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/lib/ansible/playbook/__init__.py b/lib/ansible/playbook/__init__.py index 7f4fd8cb1f3..5402ee530e5 100644 --- a/lib/ansible/playbook/__init__.py +++ b/lib/ansible/playbook/__init__.py @@ -36,6 +36,7 @@ import pipes # holds all other variables about a host SETUP_CACHE = ansible.cache.FactCache() VARS_CACHE = collections.defaultdict(dict) +RESERVED_TAGS = ['all','tagged','untagged','always'] class PlayBook(object): @@ -314,6 +315,7 @@ class PlayBook(object): assert play is not None matched_tags, unmatched_tags = play.compare_tags(self.only_tags) + matched_tags_all = matched_tags_all | matched_tags unmatched_tags_all = unmatched_tags_all | unmatched_tags @@ -332,10 +334,13 @@ class PlayBook(object): # the user can correct the arguments. unknown_tags = ((set(self.only_tags) | set(self.skip_tags)) - (matched_tags_all | unmatched_tags_all)) - unknown_tags.discard('all') + + for t in RESERVED_TAGS: + unknown_tags.discard(t) if len(unknown_tags) > 0: - unmatched_tags_all.discard('all') + for t in RESERVED_TAGS: + unmatched_tags_all.discard(t) msg = 'tag(s) not found in playbook: %s. possible values: %s' unknown = ','.join(sorted(unknown_tags)) unmatched = ','.join(sorted(unmatched_tags_all)) @@ -730,19 +735,37 @@ class PlayBook(object): # skip calling the handler till the play is finished continue - # only run the task if the requested tags match + # only run the task if the requested tags match or has 'always' tag should_run = False - for x in self.only_tags: + if 'always' in task.tags: + should_run = True + else: + u = set(['untagged']) + task_set = set(task.tags) - for y in task.tags: - if x == y: + if 'all' in self.only_tags: + should_run = True + elif 'tagged' in self.only_tags: + if task_set != u: + should_run = True + elif 'untagged' in self.only_tags: + if task_set == u: + should_run = True + else: + if len(set(task.tags).intersection(self.only_tags)) > 0: should_run = True - break - # Check for tags that we need to skip - if should_run: - if any(x in task.tags for x in self.skip_tags): - should_run = False + # Check for tags that we need to skip + if 'tagged' in self.skip_tags: + if task_set == u: + should_run = False + elif 'untagged' in self.only_tags: + if task_set != u: + should_run = False + else: + if should_run: + if len(set(task.tags).intersection(self.skip_tags)) > 0: + should_run = False if should_run: diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py index 74aa6a9f798..f1b3aacfad9 100644 --- a/lib/ansible/playbook/play.py +++ b/lib/ansible/playbook/play.py @@ -783,8 +783,27 @@ class Play(object): # compare the lists of tags using sets and return the matched and unmatched all_tags_set = set(all_tags) tags_set = set(tags) - matched_tags = all_tags_set & tags_set - unmatched_tags = all_tags_set - tags_set + + matched_tags = all_tags_set.intersection(tags_set) + unmatched_tags = all_tags_set.difference(tags_set) + + a = set(['always']) + u = set(['untagged']) + if 'always' in all_tags_set: + matched_tags = matched_tags.union(a) + unmatched_tags = all_tags_set.difference(a) + + if 'all' in tags_set: + matched_tags = matched_tags.union(all_tags_set) + unmatched_tags = set() + + if 'tagged' in tags_set: + matched_tags = all_tags_set.difference(u) + unmatched_tags = u + + if 'untagged' in tags_set and 'untagged' in all_tags_set: + matched_tags = matched_tags.union(u) + unmatched_tags = unmatched_tags.difference(u) return matched_tags, unmatched_tags diff --git a/lib/ansible/playbook/task.py b/lib/ansible/playbook/task.py index bdffba5527c..f9a090b3636 100644 --- a/lib/ansible/playbook/task.py +++ b/lib/ansible/playbook/task.py @@ -129,7 +129,7 @@ class Task(object): # load various attributes self.name = ds.get('name', None) - self.tags = [ 'all' ] + self.tags = [ 'untagged' ] self.register = ds.get('register', None) self.sudo = utils.boolean(ds.get('sudo', play.sudo)) self.su = utils.boolean(ds.get('su', play.su)) @@ -316,6 +316,9 @@ class Task(object): self.tags.extend(apply_tags) self.tags.extend(import_tags) + if len(self.tags) > 1: + self.tags.remove('untagged') + if additional_conditions: new_conditions = additional_conditions[:] if self.when: