1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

Make sure magic variables are available when templating vars_files

Also does some reorganization/cleanup on the magic vars/delegated
variable generation portions of VariableManager to make the above
possible.

Fixes #12633
This commit is contained in:
James Cammarata 2015-10-05 16:31:08 -04:00
parent 284bd118a0
commit d91b3c6b9d
2 changed files with 119 additions and 102 deletions

View file

@ -486,7 +486,7 @@ class TaskExecutor:
del variables[i]
# now replace the interpreter values with those that may have come
# from the delegated-to host
delegated_vars = variables.get('ansible_delegated_vars', dict())
delegated_vars = variables.get('ansible_delegated_vars', dict()).get(self._host.name, dict())
if isinstance(delegated_vars, dict):
for i in delegated_vars:
if i.startswith("ansible_") and i.endswith("_interpreter"):

View file

@ -188,6 +188,14 @@ class VariableManager:
return VARIABLE_CACHE[cache_entry]
all_vars = defaultdict(dict)
magic_variables = self._get_magic_variables(
loader=loader,
play=play,
host=host,
task=task,
include_hostvars=include_hostvars,
include_delegate_to=include_delegate_to,
)
if play:
# first we compile any vars specified in defaults/main.yml
@ -247,9 +255,10 @@ class VariableManager:
all_vars = combine_vars(all_vars, play.get_vars())
for vars_file_item in play.get_vars_files():
# create a set of temporary vars here, which incorporate the
# extra vars so we can properly template the vars_files entries
# create a set of temporary vars here, which incorporate the extra
# and magic vars so we can properly template the vars_files entries
temp_vars = combine_vars(all_vars, self._extra_vars)
temp_vars = combine_vars(all_vars, magic_variables)
templar = Templar(loader=loader, variables=temp_vars)
# we assume each item in the list is itself a list, as we
@ -302,19 +311,34 @@ class VariableManager:
all_vars = combine_vars(all_vars, self._nonpersistent_fact_cache.get(host.name, dict()))
all_vars = combine_vars(all_vars, self._extra_vars)
all_vars = combine_vars(all_vars, magic_variables)
# FIXME: make sure all special vars are here
# Finally, we create special vars
# if we have a task and we're delegating to another host, figure out the
# variables for that host now so we don't have to rely on hostvars later
if task and task.delegate_to is not None and include_delegate_to:
all_vars['ansible_delegated_vars'] = self._get_delegated_vars(loader, play, task, all_vars)
all_vars['playbook_dir'] = loader.get_basedir()
#VARIABLE_CACHE[cache_entry] = all_vars
debug("done with get_vars()")
return all_vars
def _get_magic_variables(self, loader, play, host, task, include_hostvars, include_delegate_to):
'''
Returns a dictionary of so-called "magic" variables in Ansible,
which are special variables we set internally for use.
'''
variables = dict()
variables['playbook_dir'] = loader.get_basedir()
if host:
all_vars['group_names'] = [group.name for group in host.get_groups()]
variables['group_names'] = [group.name for group in host.get_groups()]
if self._inventory is not None:
all_vars['groups'] = dict()
variables['groups'] = dict()
for (group_name, group) in iteritems(self._inventory.groups):
all_vars['groups'][group_name] = [h.name for h in group.get_hosts()]
variables['groups'][group_name] = [h.name for h in group.get_hosts()]
if include_hostvars:
hostvars_cache_entry = self._get_cache_entry(play=play)
@ -323,19 +347,36 @@ class VariableManager:
else:
hostvars = HostVars(play=play, inventory=self._inventory, loader=loader, variable_manager=self)
HOSTVARS_CACHE[hostvars_cache_entry] = hostvars
all_vars['hostvars'] = hostvars
variables['hostvars'] = hostvars
variables['vars'] = hostvars[host.get_name()]
if task:
if task._role:
all_vars['role_path'] = task._role._role_path
variables['role_path'] = task._role._role_path
# if we have a task and we're delegating to another host, figure out the
# variables for that host now so we don't have to rely on hostvars later
if task.delegate_to is not None and include_delegate_to:
if self._inventory is not None:
variables['inventory_dir'] = self._inventory.basedir()
if play:
# add the list of hosts in the play, as adjusted for limit/filters
# DEPRECATED: play_hosts should be deprecated in favor of ansible_play_hosts,
# however this would take work in the templating engine, so for now
# we'll add both so we can give users something transitional to use
host_list = [x.name for x in self._inventory.get_hosts()]
variables['play_hosts'] = host_list
variables['ansible_play_hosts'] = host_list
# the 'omit' value alows params to be left out if the variable they are based on is undefined
variables['omit'] = self._omit_token
variables['ansible_version'] = CLI.version_info(gitinfo=False)
return variables
def _get_delegated_vars(self, loader, play, task, existing_variables):
# we unfortunately need to template the delegate_to field here,
# as we're fetching vars before post_validate has been called on
# the task that has been passed in
templar = Templar(loader=loader, variables=all_vars)
vars_copy = existing_variables.copy()
templar = Templar(loader=loader, variables=vars_copy)
items = []
if task.loop is not None:
@ -349,13 +390,12 @@ class VariableManager:
self._display.deprecated("Skipping task due to undefined attribute, in the future this will be a fatal error.")
else:
raise
items = lookup_loader.get(task.loop, loader=loader, templar=templar).run(terms=loop_terms, variables=all_vars)
items = lookup_loader.get(task.loop, loader=loader, templar=templar).run(terms=loop_terms, variables=vars_copy)
else:
raise AnsibleError("Unexpected failure in finding the lookup named '%s' in the available lookup plugins" % task.loop)
else:
items = [None]
vars_copy = all_vars.copy()
delegated_host_vars = dict()
for item in items:
# update the variables with the item value for templating, in case we need it
@ -408,30 +448,7 @@ class VariableManager:
include_hostvars=False,
)
all_vars['ansible_delegated_vars'] = delegated_host_vars
if self._inventory is not None:
all_vars['inventory_dir'] = self._inventory.basedir()
if play:
# add the list of hosts in the play, as adjusted for limit/filters
# DEPRECATED: play_hosts should be deprecated in favor of ansible_play_hosts,
# however this would take work in the templating engine, so for now
# we'll add both so we can give users something transitional to use
host_list = [x.name for x in self._inventory.get_hosts()]
all_vars['play_hosts'] = host_list
all_vars['ansible_play_hosts'] = host_list
# the 'omit' value alows params to be left out if the variable they are based on is undefined
all_vars['omit'] = self._omit_token
all_vars['ansible_version'] = CLI.version_info(gitinfo=False)
if 'hostvars' in all_vars and host:
all_vars['vars'] = all_vars['hostvars'][host.get_name()]
#VARIABLE_CACHE[cache_entry] = all_vars
debug("done with get_vars()")
return all_vars
return delegated_host_vars
def _get_inventory_basename(self, path):
'''