From f8ddf2eb04bc9e795f1d0567bc2fa979c7cf01b9 Mon Sep 17 00:00:00 2001 From: James Cammarata Date: Fri, 10 Jul 2015 02:43:53 -0400 Subject: [PATCH] Move role cache into the play to avoid roles crossing play boundaries --- lib/ansible/executor/playbook_executor.py | 4 ---- lib/ansible/playbook/play.py | 7 +++++++ lib/ansible/playbook/role/__init__.py | 24 ++++++---------------- lib/ansible/plugins/strategies/__init__.py | 4 ++-- 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/lib/ansible/executor/playbook_executor.py b/lib/ansible/executor/playbook_executor.py index 1a7301992b1..343ac4ed39f 100644 --- a/lib/ansible/executor/playbook_executor.py +++ b/lib/ansible/executor/playbook_executor.py @@ -25,7 +25,6 @@ from ansible import constants as C from ansible.errors import * from ansible.executor.task_queue_manager import TaskQueueManager from ansible.playbook import Playbook -from ansible.playbook.role import role_reset_has_run from ansible.plugins import module_loader from ansible.template import Templar @@ -84,9 +83,6 @@ class PlaybookExecutor: self._display.vv('%d plays in %s' % (len(plays), playbook_path)) for play in plays: - # clear out the flag on all roles indicating they had any tasks run - role_reset_has_run() - # clear any filters which may have been applied to the inventory self._inventory.remove_restriction() diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py index aa8d1092a52..2d31adec64c 100644 --- a/lib/ansible/playbook/play.py +++ b/lib/ansible/playbook/play.py @@ -88,6 +88,8 @@ class Play(Base, Taggable, Become): def __init__(self): super(Play, self).__init__() + self.ROLE_CACHE = {} + def __repr__(self): return self.get_name() @@ -322,3 +324,8 @@ class Play(Base, Taggable, Become): setattr(self, 'roles', roles) del data['roles'] + def copy(self): + new_me = super(Play, self).copy() + new_me.ROLE_CACHE = self.ROLE_CACHE.copy() + return new_me + diff --git a/lib/ansible/playbook/role/__init__.py b/lib/ansible/playbook/role/__init__.py index f1de615608f..ad9ad9c8bcb 100644 --- a/lib/ansible/playbook/role/__init__.py +++ b/lib/ansible/playbook/role/__init__.py @@ -41,7 +41,7 @@ from ansible.plugins import get_all_plugin_loaders, push_basedir from ansible.utils.vars import combine_vars -__all__ = ['Role', 'ROLE_CACHE', 'hash_params', 'role_reset_has_run'] +__all__ = ['Role', 'hash_params'] # FIXME: this should be a utility function, but can't be a member of # the role due to the fact that it would require the use of self @@ -64,17 +64,6 @@ def hash_params(params): s.update((k, v)) return frozenset(s) -# The role cache is used to prevent re-loading roles, which -# may already exist. Keys into this cache are the SHA1 hash -# of the role definition (for dictionary definitions, this -# will be based on the repr() of the dictionary object) -ROLE_CACHE = dict() - -def role_reset_has_run(): - for (role_name, cached_roles) in ROLE_CACHE.iteritems(): - for (hashed_params, role) in cached_roles.iteritems(): - role._had_task_run = False - class Role(Base, Become, Conditional, Taggable): def __init__(self, play=None): @@ -111,13 +100,12 @@ class Role(Base, Become, Conditional, Taggable): # specified for a role as the key and the Role() object itself. # We use frozenset to make the dictionary hashable. - #hashed_params = frozenset(role_include.get_role_params().iteritems()) params = role_include.get_role_params() params['tags'] = role_include.tags params['when'] = role_include.when hashed_params = hash_params(params) - if role_include.role in ROLE_CACHE: - for (entry, role_obj) in ROLE_CACHE[role_include.role].iteritems(): + if role_include.role in play.ROLE_CACHE: + for (entry, role_obj) in play.ROLE_CACHE[role_include.role].iteritems(): if hashed_params == entry: if parent_role: role_obj.add_parent(parent_role) @@ -126,10 +114,10 @@ class Role(Base, Become, Conditional, Taggable): r = Role(play=play) r._load_role_data(role_include, parent_role=parent_role) - if role_include.role not in ROLE_CACHE: - ROLE_CACHE[role_include.role] = dict() + if role_include.role not in play.ROLE_CACHE: + play.ROLE_CACHE[role_include.role] = dict() - ROLE_CACHE[role_include.role][hashed_params] = r + play.ROLE_CACHE[role_include.role][hashed_params] = r return r except RuntimeError: diff --git a/lib/ansible/plugins/strategies/__init__.py b/lib/ansible/plugins/strategies/__init__.py index f188b70a0a2..bcc57c8a412 100644 --- a/lib/ansible/plugins/strategies/__init__.py +++ b/lib/ansible/plugins/strategies/__init__.py @@ -28,7 +28,7 @@ from ansible.inventory.host import Host from ansible.inventory.group import Group from ansible.playbook.handler import Handler from ansible.playbook.helpers import load_list_of_blocks -from ansible.playbook.role import ROLE_CACHE, hash_params +from ansible.playbook.role import hash_params from ansible.plugins import _basedirs, filter_loader, lookup_loader, module_loader from ansible.template import Templar from ansible.utils.debug import debug @@ -193,7 +193,7 @@ class StrategyBase: if task_result._task._role is not None and result[0] in ('host_task_ok', 'host_task_failed'): # lookup the role in the ROLE_CACHE to make sure we're dealing # with the correct object and mark it as executed - for (entry, role_obj) in ROLE_CACHE[task_result._task._role._role_name].iteritems(): + for (entry, role_obj) in iterator._play.ROLE_CACHE[task_result._task._role._role_name].iteritems(): hashed_entry = hash_params(task_result._task._role._role_params) if entry == hashed_entry: role_obj._had_task_run = True