Fix role parameter precedence after 9a0f8f0

Fixes #9497
pull/9587/head
James Cammarata 10 years ago
parent 0edaa6f790
commit 4b6b58ab11

@ -402,6 +402,7 @@ class PlayBook(object):
play_vars=task.play_vars, play_vars=task.play_vars,
play_file_vars=task.play_file_vars, play_file_vars=task.play_file_vars,
role_vars=task.role_vars, role_vars=task.role_vars,
role_params=task.role_params,
default_vars=task.default_vars, default_vars=task.default_vars,
extra_vars=self.extra_vars, extra_vars=self.extra_vars,
private_key_file=self.private_key_file, private_key_file=self.private_key_file,

@ -221,6 +221,14 @@ class Play(object):
raise errors.AnsibleError("too many levels of recursion while resolving role dependencies") raise errors.AnsibleError("too many levels of recursion while resolving role dependencies")
for role in roles: for role in roles:
role_path,role_vars = self._get_role_path(role) role_path,role_vars = self._get_role_path(role)
# save just the role params for this role, which exclude the special
# keywords 'role', 'tags', and 'when'.
role_params = role_vars.copy()
for item in ('role', 'tags', 'when'):
if item in role_params:
del role_params[item]
role_vars = utils.combine_vars(passed_vars, role_vars) role_vars = utils.combine_vars(passed_vars, role_vars)
vars = self._resolve_main(utils.path_dwim(self.basedir, os.path.join(role_path, 'vars'))) vars = self._resolve_main(utils.path_dwim(self.basedir, os.path.join(role_path, 'vars')))
@ -249,6 +257,13 @@ class Play(object):
for dep in dependencies: for dep in dependencies:
allow_dupes = False allow_dupes = False
(dep_path,dep_vars) = self._get_role_path(dep) (dep_path,dep_vars) = self._get_role_path(dep)
# save the dep params, just as we did above
dep_params = dep_vars.copy()
for item in ('role', 'tags', 'when'):
if item in dep_params:
del dep_params[item]
meta = self._resolve_main(utils.path_dwim(self.basedir, os.path.join(dep_path, 'meta'))) meta = self._resolve_main(utils.path_dwim(self.basedir, os.path.join(dep_path, 'meta')))
if os.path.isfile(meta): if os.path.isfile(meta):
meta_data = utils.parse_yaml_from_file(meta, vault_password=self.vault_password) meta_data = utils.parse_yaml_from_file(meta, vault_password=self.vault_password)
@ -332,13 +347,13 @@ class Play(object):
dep_vars['when'] = tmpcond dep_vars['when'] = tmpcond
self._build_role_dependencies([dep], dep_stack, passed_vars=dep_vars, level=level+1) self._build_role_dependencies([dep], dep_stack, passed_vars=dep_vars, level=level+1)
dep_stack.append([dep,dep_path,dep_vars,dep_defaults_data]) dep_stack.append([dep, dep_path, dep_vars, dep_params, dep_defaults_data])
# only add the current role when we're at the top level, # only add the current role when we're at the top level,
# otherwise we'll end up in a recursive loop # otherwise we'll end up in a recursive loop
if level == 0: if level == 0:
self.included_roles.append(role) self.included_roles.append(role)
dep_stack.append([role,role_path,role_vars,defaults_data]) dep_stack.append([role, role_path, role_vars, role_params, defaults_data])
return dep_stack return dep_stack
def _load_role_vars_files(self, vars_files): def _load_role_vars_files(self, vars_files):
@ -400,12 +415,12 @@ class Play(object):
# make role_path available as variable to the task # make role_path available as variable to the task
for idx, val in enumerate(roles): for idx, val in enumerate(roles):
this_uuid = str(uuid.uuid4()) this_uuid = str(uuid.uuid4())
roles[idx][-2]['role_uuid'] = this_uuid roles[idx][-3]['role_uuid'] = this_uuid
roles[idx][-2]['role_path'] = roles[idx][1] roles[idx][-3]['role_path'] = roles[idx][1]
role_names = [] role_names = []
for (role,role_path,role_vars,default_vars) in roles: for (role, role_path, role_vars, role_params, default_vars) in roles:
# special vars must be extracted from the dict to the included tasks # special vars must be extracted from the dict to the included tasks
special_keys = [ "sudo", "sudo_user", "when", "with_items" ] special_keys = [ "sudo", "sudo_user", "when", "with_items" ]
special_vars = {} special_vars = {}
@ -438,13 +453,13 @@ class Play(object):
role_names.append(role_name) role_names.append(role_name)
if os.path.isfile(task): if os.path.isfile(task):
nt = dict(include=pipes.quote(task), vars=role_vars, default_vars=default_vars, role_name=role_name) nt = dict(include=pipes.quote(task), vars=role_vars, role_params=role_params, default_vars=default_vars, role_name=role_name)
for k in special_keys: for k in special_keys:
if k in special_vars: if k in special_vars:
nt[k] = special_vars[k] nt[k] = special_vars[k]
new_tasks.append(nt) new_tasks.append(nt)
if os.path.isfile(handler): if os.path.isfile(handler):
nt = dict(include=pipes.quote(handler), vars=role_vars, role_name=role_name) nt = dict(include=pipes.quote(handler), vars=role_vars, role_params=role_params, role_name=role_name)
for k in special_keys: for k in special_keys:
if k in special_vars: if k in special_vars:
nt[k] = special_vars[k] nt[k] = special_vars[k]
@ -509,7 +524,7 @@ class Play(object):
# ************************************************* # *************************************************
def _load_tasks(self, tasks, vars=None, default_vars=None, sudo_vars=None, def _load_tasks(self, tasks, vars=None, role_params=None, default_vars=None, sudo_vars=None,
additional_conditions=None, original_file=None, role_name=None): additional_conditions=None, original_file=None, role_name=None):
''' handle task and handler include statements ''' ''' handle task and handler include statements '''
@ -521,6 +536,8 @@ class Play(object):
additional_conditions = [] additional_conditions = []
if vars is None: if vars is None:
vars = {} vars = {}
if role_params is None:
role_params = {}
if default_vars is None: if default_vars is None:
default_vars = {} default_vars = {}
if sudo_vars is None: if sudo_vars is None:
@ -572,11 +589,15 @@ class Play(object):
included_additional_conditions.append(x[k]) included_additional_conditions.append(x[k])
elif type(x[k]) is list: elif type(x[k]) is list:
included_additional_conditions.extend(x[k]) included_additional_conditions.extend(x[k])
elif k in ("include", "vars", "default_vars", "sudo", "sudo_user", "role_name", "no_log"): elif k in ("include", "vars", "role_params", "default_vars", "sudo", "sudo_user", "role_name", "no_log"):
continue continue
else: else:
include_vars[k] = x[k] include_vars[k] = x[k]
# get any role parameters specified
role_params = x.get('role_params', {})
# get any role default variables specified
default_vars = x.get('default_vars', {}) default_vars = x.get('default_vars', {})
if not default_vars: if not default_vars:
default_vars = self.default_vars default_vars = self.default_vars
@ -609,7 +630,7 @@ class Play(object):
for y in data: for y in data:
if isinstance(y, dict) and 'include' in y: if isinstance(y, dict) and 'include' in y:
y['role_name'] = new_role y['role_name'] = new_role
loaded = self._load_tasks(data, mv, default_vars, included_sudo_vars, list(included_additional_conditions), original_file=include_filename, role_name=new_role) loaded = self._load_tasks(data, mv, role_params, default_vars, included_sudo_vars, list(included_additional_conditions), original_file=include_filename, role_name=new_role)
results += loaded results += loaded
elif type(x) == dict: elif type(x) == dict:
task = Task( task = Task(
@ -618,6 +639,7 @@ class Play(object):
play_vars=self.vars, play_vars=self.vars,
play_file_vars=self.vars_file_vars, play_file_vars=self.vars_file_vars,
role_vars=self.role_vars, role_vars=self.role_vars,
role_params=role_params,
default_vars=default_vars, default_vars=default_vars,
additional_conditions=list(additional_conditions), additional_conditions=list(additional_conditions),
role_name=role_name role_name=role_name

@ -26,7 +26,7 @@ class Task(object):
__slots__ = [ __slots__ = [
'name', 'meta', 'action', 'when', 'async_seconds', 'async_poll_interval', 'name', 'meta', 'action', 'when', 'async_seconds', 'async_poll_interval',
'notify', 'module_name', 'module_args', 'module_vars', 'play_vars', 'play_file_vars', 'role_vars', 'default_vars', 'notify', 'module_name', 'module_args', 'module_vars', 'play_vars', 'play_file_vars', 'role_vars', 'role_params', 'default_vars',
'play', 'notified_by', 'tags', 'register', 'role_name', 'play', 'notified_by', 'tags', 'register', 'role_name',
'delegate_to', 'first_available_file', 'ignore_errors', 'delegate_to', 'first_available_file', 'ignore_errors',
'local_action', 'transport', 'sudo', 'remote_user', 'sudo_user', 'sudo_pass', 'local_action', 'transport', 'sudo', 'remote_user', 'sudo_user', 'sudo_pass',
@ -45,7 +45,7 @@ class Task(object):
'su', 'su_user', 'su_pass', 'no_log', 'run_once', 'su', 'su_user', 'su_pass', 'no_log', 'run_once',
] ]
def __init__(self, play, ds, module_vars=None, play_vars=None, play_file_vars=None, role_vars=None, default_vars=None, additional_conditions=None, role_name=None): def __init__(self, play, ds, module_vars=None, play_vars=None, play_file_vars=None, role_vars=None, role_params=None, default_vars=None, additional_conditions=None, role_name=None):
''' constructor loads from a task or handler datastructure ''' ''' constructor loads from a task or handler datastructure '''
# meta directives are used to tell things like ansible/playbook to run # meta directives are used to tell things like ansible/playbook to run
@ -123,6 +123,7 @@ class Task(object):
self.play_vars = play_vars self.play_vars = play_vars
self.play_file_vars = play_file_vars self.play_file_vars = play_file_vars
self.role_vars = role_vars self.role_vars = role_vars
self.role_params = role_params
self.default_vars = default_vars self.default_vars = default_vars
self.play = play self.play = play
@ -226,6 +227,7 @@ class Task(object):
all_vars = utils.combine_vars(all_vars, self.play_file_vars) all_vars = utils.combine_vars(all_vars, self.play_file_vars)
all_vars = utils.combine_vars(all_vars, self.role_vars) all_vars = utils.combine_vars(all_vars, self.role_vars)
all_vars = utils.combine_vars(all_vars, self.module_vars) all_vars = utils.combine_vars(all_vars, self.module_vars)
all_vars = utils.combine_vars(all_vars, self.role_params)
self.async_seconds = ds.get('async', 0) # not async by default self.async_seconds = ds.get('async', 0) # not async by default
self.async_seconds = template.template_from_string(play.basedir, self.async_seconds, all_vars) self.async_seconds = template.template_from_string(play.basedir, self.async_seconds, all_vars)

@ -137,6 +137,7 @@ class Runner(object):
play_vars=None, # play_vars=None, #
play_file_vars=None, # play_file_vars=None, #
role_vars=None, # role_vars=None, #
role_params=None, #
default_vars=None, # default_vars=None, #
extra_vars=None, # extra vars specified with he playbook(s) extra_vars=None, # extra vars specified with he playbook(s)
is_playbook=False, # running from playbook or not? is_playbook=False, # running from playbook or not?
@ -182,6 +183,7 @@ class Runner(object):
self.play_vars = utils.default(play_vars, lambda: {}) self.play_vars = utils.default(play_vars, lambda: {})
self.play_file_vars = utils.default(play_file_vars, lambda: {}) self.play_file_vars = utils.default(play_file_vars, lambda: {})
self.role_vars = utils.default(role_vars, lambda: {}) self.role_vars = utils.default(role_vars, lambda: {})
self.role_params = utils.default(role_params, lambda: {})
self.default_vars = utils.default(default_vars, lambda: {}) self.default_vars = utils.default(default_vars, lambda: {})
self.extra_vars = utils.default(extra_vars, lambda: {}) self.extra_vars = utils.default(extra_vars, lambda: {})
@ -645,6 +647,8 @@ class Runner(object):
# followed by vars_cache things (set_fact, include_vars, and # followed by vars_cache things (set_fact, include_vars, and
# vars_files which had host-specific templating done) # vars_files which had host-specific templating done)
inject = utils.combine_vars(inject, self.vars_cache.get(host, {})) inject = utils.combine_vars(inject, self.vars_cache.get(host, {}))
# role parameters next
inject = utils.combine_vars(inject, self.role_params)
# and finally -e vars are the highest priority # and finally -e vars are the highest priority
inject = utils.combine_vars(inject, self.extra_vars) inject = utils.combine_vars(inject, self.extra_vars)
# and then special vars # and then special vars

Loading…
Cancel
Save