From 8279557e8f36aef20d7034dfc62e2e3f1ef64461 Mon Sep 17 00:00:00 2001 From: James Cammarata Date: Mon, 3 Aug 2015 16:25:08 -0400 Subject: [PATCH] Allow role names to be templated Fixes #10858 --- lib/ansible/playbook/helpers.py | 4 ++-- lib/ansible/playbook/play.py | 2 +- lib/ansible/playbook/role/definition.py | 15 ++++++++++++++- lib/ansible/playbook/role/include.py | 8 ++++---- lib/ansible/playbook/role/metadata.py | 2 +- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/ansible/playbook/helpers.py b/lib/ansible/playbook/helpers.py index d982413971..ca9326b814 100644 --- a/lib/ansible/playbook/helpers.py +++ b/lib/ansible/playbook/helpers.py @@ -98,7 +98,7 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h return task_list -def load_list_of_roles(ds, current_role_path=None, variable_manager=None, loader=None): +def load_list_of_roles(ds, play, current_role_path=None, variable_manager=None, loader=None): ''' Loads and returns a list of RoleInclude objects from the datastructure list of role definitions @@ -112,7 +112,7 @@ def load_list_of_roles(ds, current_role_path=None, variable_manager=None, loader roles = [] for role_def in ds: - i = RoleInclude.load(role_def, current_role_path=current_role_path, variable_manager=variable_manager, loader=loader) + i = RoleInclude.load(role_def, play=play, current_role_path=current_role_path, variable_manager=variable_manager, loader=loader) roles.append(i) return roles diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py index f4c627b415..b1f5440d74 100644 --- a/lib/ansible/playbook/play.py +++ b/lib/ansible/playbook/play.py @@ -211,7 +211,7 @@ class Play(Base, Taggable, Become): if ds is None: ds = [] - role_includes = load_list_of_roles(ds, variable_manager=self._variable_manager, loader=self._loader) + role_includes = load_list_of_roles(ds, play=self, variable_manager=self._variable_manager, loader=self._loader) roles = [] for ri in role_includes: diff --git a/lib/ansible/playbook/role/definition.py b/lib/ansible/playbook/role/definition.py index 48d96e6f09..a54febe1fe 100644 --- a/lib/ansible/playbook/role/definition.py +++ b/lib/ansible/playbook/role/definition.py @@ -31,6 +31,7 @@ from ansible.playbook.base import Base from ansible.playbook.become import Become from ansible.playbook.conditional import Conditional from ansible.playbook.taggable import Taggable +from ansible.template import Templar from ansible.utils.path import unfrackpath @@ -41,7 +42,11 @@ class RoleDefinition(Base, Become, Conditional, Taggable): _role = FieldAttribute(isa='string') - def __init__(self, role_basedir=None): + def __init__(self, play=None, role_basedir=None, variable_manager=None, loader=None): + self._play = play + self._variable_manager = variable_manager + self._loader = loader + self._role_path = None self._role_basedir = role_basedir self._role_params = dict() @@ -112,6 +117,14 @@ class RoleDefinition(Base, Become, Conditional, Taggable): if not role_name or not isinstance(role_name, string_types): raise AnsibleError('role definitions must contain a role name', obj=ds) + # if we have the required datastructures, and if the role_name + # contains a variable, try and template it now + if self._play and self._variable_manager: + all_vars = self._variable_manager.get_vars(loader=self._loader, play=self._play) + templar = Templar(loader=self._loader, variables=all_vars) + if templar._contains_vars(role_name): + role_name = templar.template(role_name) + return role_name def _load_role_path(self, role_name): diff --git a/lib/ansible/playbook/role/include.py b/lib/ansible/playbook/role/include.py index 93cf0e2179..07ebf3f0d6 100644 --- a/lib/ansible/playbook/role/include.py +++ b/lib/ansible/playbook/role/include.py @@ -38,14 +38,14 @@ class RoleInclude(RoleDefinition): FIXME: docstring """ - def __init__(self, role_basedir=None): - super(RoleInclude, self).__init__(role_basedir=role_basedir) + def __init__(self, play=None, role_basedir=None, variable_manager=None, loader=None): + super(RoleInclude, self).__init__(play=play, role_basedir=role_basedir, variable_manager=variable_manager, loader=loader) @staticmethod - def load(data, current_role_path=None, parent_role=None, variable_manager=None, loader=None): + def load(data, play, current_role_path=None, parent_role=None, variable_manager=None, loader=None): assert isinstance(data, string_types) or isinstance(data, dict) or isinstance(data, AnsibleBaseYAMLObject) - ri = RoleInclude(role_basedir=current_role_path) + ri = RoleInclude(play=play, role_basedir=current_role_path, variable_manager=variable_manager, loader=loader) return ri.load_data(data, variable_manager=variable_manager, loader=loader) diff --git a/lib/ansible/playbook/role/metadata.py b/lib/ansible/playbook/role/metadata.py index 61e92ce9b5..cd56e60633 100644 --- a/lib/ansible/playbook/role/metadata.py +++ b/lib/ansible/playbook/role/metadata.py @@ -72,7 +72,7 @@ class RoleMetadata(Base): if self._owner: current_role_path = os.path.dirname(self._owner._role_path) - return load_list_of_roles(ds, current_role_path=current_role_path, variable_manager=self._variable_manager, loader=self._loader) + return load_list_of_roles(ds, play=self._owner._play, current_role_path=current_role_path, variable_manager=self._variable_manager, loader=self._loader) def _load_galaxy_info(self, attr, ds): '''