@ -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
# extr a 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 )
# 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 )
# FIXME: make sure all special vars are here
# Finally, we create special vars
#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 .
'''
all_vars [ ' playbook_dir ' ] = loader . get_basedir ( )
variables = dict ( )
variables [ ' playbook_dir ' ] = loader . get_basedir ( )
if host :
all_vars [ ' group_names ' ] = [ group . name for group in host . get_groups ( ) ]
variable s[ ' group_names ' ] = [ group . name for group in host . get_groups ( ) ]
if self . _inventory is not None :
all_vars [ ' groups ' ] = dict ( )
variable s[ ' groups ' ] = dict ( )
for ( group_name , group ) in iteritems ( self . _inventory . groups ) :
all_ vars[ ' groups ' ] [ group_name ] = [ h . name for h in group . get_hosts ( ) ]
variable s[ ' groups ' ] [ group_name ] = [ h . name for h in group . get_hosts ( ) ]
if include_hostvars :
hostvars_cache_entry = self . _get_cache_entry ( play = play )
@ -323,115 +347,108 @@ 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
# 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 :
# 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 )
items = [ ]
if task . loop is not None :
if task . loop in lookup_loader :
#TODO: remove convert_bare true and deprecate this in with_
try :
loop_terms = listify_lookup_plugin_terms ( terms = task . loop_args , templar = templar , loader = loader , fail_on_undefined = True , convert_bare = True )
except AnsibleUndefinedVariable as e :
if ' has no attribute ' in str ( e ) :
loop_terms = [ ]
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 )
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
if item is not None :
vars_copy [ ' item ' ] = item
templar . set_available_variables ( vars_copy )
delegated_host_name = templar . template ( task . delegate_to , fail_on_undefined = False )
if delegated_host_name in delegated_host_vars :
# no need to repeat ourselves, as the delegate_to value
# does not appear to be tied to the loop item variable
continue
# a dictionary of variables to use if we have to create a new host below
new_delegated_host_vars = dict (
ansible_host = delegated_host_name ,
ansible_user = C . DEFAULT_REMOTE_USER ,
ansible_connection = C . DEFAULT_TRANSPORT ,
)
# now try to find the delegated-to host in inventory, or failing that,
# create a new host on the fly so we can fetch variables for it
delegated_host = None
if self . _inventory is not None :
delegated_host = self . _inventory . get_host ( delegated_host_name )
# try looking it up based on the address field, and finally
# fall back to creating a host on the fly to use for the var lookup
if delegated_host is None :
for h in self . _inventory . get_hosts ( ignore_limits_and_restrictions = True ) :
# check if the address matches, or if both the delegated_to host
# and the current host are in the list of localhost aliases
if h . address == delegated_host_name or h . name in C . LOCALHOST and delegated_host_name in C . LOCALHOST :
delegated_host = h
break
else :
delegated_host = Host ( name = delegated_host_name )
delegated_host . vars . update ( new_delegated_host_vars )
else :
delegated_host = Host ( name = delegated_host_name )
delegated_host . vars . update ( new_delegated_host_vars )
# now we go fetch the vars for the delegated-to host and save them in our
# master dictionary of variables to be used later in the TaskExecutor/PlayContext
delegated_host_vars [ delegated_host_name ] = self . get_vars (
loader = loader ,
play = play ,
host = delegated_host ,
task = task ,
include_delegate_to = False ,
include_hostvars = False ,
)
all_vars [ ' ansible_delegated_vars ' ] = delegated_host_vars
variables [ ' role_path ' ] = task . _role . _role_path
if self . _inventory is not None :
all_ vars[ ' inventory_dir ' ] = self . _inventory . basedir ( )
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 ( ) ]
all_ vars[ ' play_hosts ' ] = host_list
all_ vars[ ' ansible_play_hosts ' ] = host_list
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
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
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
vars_copy = existing_variables . copy ( )
templar = Templar ( loader = loader , variables = vars_copy )
items = [ ]
if task . loop is not None :
if task . loop in lookup_loader :
#TODO: remove convert_bare true and deprecate this in with_
try :
loop_terms = listify_lookup_plugin_terms ( terms = task . loop_args , templar = templar , loader = loader , fail_on_undefined = True , convert_bare = True )
except AnsibleUndefinedVariable as e :
if ' has no attribute ' in str ( e ) :
loop_terms = [ ]
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 = vars_copy )
else :
raise AnsibleError ( " Unexpected failure in finding the lookup named ' %s ' in the available lookup plugins " % task . loop )
else :
items = [ None ]
delegated_host_vars = dict ( )
for item in items :
# update the variables with the item value for templating, in case we need it
if item is not None :
vars_copy [ ' item ' ] = item
templar . set_available_variables ( vars_copy )
delegated_host_name = templar . template ( task . delegate_to , fail_on_undefined = False )
if delegated_host_name in delegated_host_vars :
# no need to repeat ourselves, as the delegate_to value
# does not appear to be tied to the loop item variable
continue
# a dictionary of variables to use if we have to create a new host below
new_delegated_host_vars = dict (
ansible_host = delegated_host_name ,
ansible_user = C . DEFAULT_REMOTE_USER ,
ansible_connection = C . DEFAULT_TRANSPORT ,
)
# now try to find the delegated-to host in inventory, or failing that,
# create a new host on the fly so we can fetch variables for it
delegated_host = None
if self . _inventory is not None :
delegated_host = self . _inventory . get_host ( delegated_host_name )
# try looking it up based on the address field, and finally
# fall back to creating a host on the fly to use for the var lookup
if delegated_host is None :
for h in self . _inventory . get_hosts ( ignore_limits_and_restrictions = True ) :
# check if the address matches, or if both the delegated_to host
# and the current host are in the list of localhost aliases
if h . address == delegated_host_name or h . name in C . LOCALHOST and delegated_host_name in C . LOCALHOST :
delegated_host = h
break
else :
delegated_host = Host ( name = delegated_host_name )
delegated_host . vars . update ( new_delegated_host_vars )
else :
delegated_host = Host ( name = delegated_host_name )
delegated_host . vars . update ( new_delegated_host_vars )
# now we go fetch the vars for the delegated-to host and save them in our
# master dictionary of variables to be used later in the TaskExecutor/PlayContext
delegated_host_vars [ delegated_host_name ] = self . get_vars (
loader = loader ,
play = play ,
host = delegated_host ,
task = task ,
include_delegate_to = False ,
include_hostvars = False ,
)
return delegated_host_vars
def _get_inventory_basename ( self , path ) :
'''