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'
This commit is contained in:
Brian Coca 2015-02-08 22:51:18 -05:00
parent f61de115cd
commit 95fa770ba0
3 changed files with 59 additions and 14 deletions

View file

@ -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,18 +735,36 @@ 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:
for y in task.tags:
if x == y:
if 'always' in task.tags:
should_run = True
else:
u = set(['untagged'])
task_set = set(task.tags)
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 '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 any(x in task.tags for x in self.skip_tags):
if len(set(task.tags).intersection(self.skip_tags)) > 0:
should_run = False
if should_run:

View file

@ -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

View file

@ -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: