From 73c883c1220d906686f26a0e00a5e00af120fce0 Mon Sep 17 00:00:00 2001 From: James Cammarata Date: Wed, 5 Mar 2014 14:25:24 -0600 Subject: [PATCH] Keep track of role dependencies across plays Also fixes a bug in which tags specified on top-level roles were not being passed down to dependent roles. Fixes #4656 --- CHANGELOG.md | 1 + lib/ansible/playbook/__init__.py | 9 ++++++++- lib/ansible/playbook/play.py | 18 ++++++++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6033074015..35934bc541 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Ansible Changes By Release Major features/changes: * The deprecated legacy variable templating system has been finally removed. Use {{ foo }} always not $foo or ${foo}. +* Role dependencies are now tracked across multiple plays, making common roles easier to include in dependencies without any special variable tricks. New Modules: diff --git a/lib/ansible/playbook/__init__.py b/lib/ansible/playbook/__init__.py index 6596552625..3fd84239fb 100644 --- a/lib/ansible/playbook/__init__.py +++ b/lib/ansible/playbook/__init__.py @@ -240,13 +240,20 @@ class PlayBook(object): plays = [] matched_tags_all = set() unmatched_tags_all = set() + included_roles = [] # loop through all patterns and run them self.callbacks.on_start() for (play_ds, play_basedir) in zip(self.playbook, self.play_basedirs): - play = Play(self, play_ds, play_basedir, vault_password=self.vault_password) + play = Play(self, play_ds, play_basedir, included_roles=included_roles, vault_password=self.vault_password) assert play is not None + # add any new roles brought in by this play to the + # global list of roles we're tracking + for role in play.included_roles: + if role not in included_roles: + included_roles.append(role) + 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 diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py index e9f00e4702..b9f740f2be 100644 --- a/lib/ansible/playbook/play.py +++ b/lib/ansible/playbook/play.py @@ -49,7 +49,7 @@ class Play(object): # ************************************************* - def __init__(self, playbook, ds, basedir, vault_password=None): + def __init__(self, playbook, ds, basedir, included_roles=[], vault_password=None): ''' constructor loads from a play datastructure ''' for x in ds.keys(): @@ -81,7 +81,7 @@ class Play(object): self._update_vars_files_for_host(None) # now we load the roles into the datastructure - self.included_roles = [] + self.included_roles = included_roles ds = self._load_roles(self.roles, ds) # and finally re-process the vars files as they may have @@ -227,6 +227,20 @@ class Play(object): if meta_data: allow_dupes = utils.boolean(meta_data.get('allow_duplicates','')) + # if any tags were specified as role/dep variables, merge + # them into the passed_vars so they're passed on to any + # further dependencies too, and so we only have one place + # (passed_vars) to look for tags going forward + def __merge_tags(var_obj): + old_tags = passed_vars.get('tags', []) + new_tags = var_obj.get('tags', []) + if isinstance(new_tags, basestring): + new_tags = [new_tags, ] + return list(set(old_tags + new_tags)) + + passed_vars['tags'] = __merge_tags(role_vars) + passed_vars['tags'] = __merge_tags(dep_vars) + # if tags are set from this role, merge them # into the tags list for the dependent role if "tags" in passed_vars: