fixed lookup search path (#16630)
* fixed lookup search path added ansible_search_path var that contains the proper list and in order removed roledir var which was only used by first_found, rest used role_path added needle function for lookups that mirrors the action plugin one, now both types of plugins use same pathing. * added missing os import * renamed as per feedback * fixed missing rename in first_found * also fixed first_found * fixed import to match new error class * fixed getattr ref
This commit is contained in:
parent
221520cbad
commit
3c39bb5633
11 changed files with 87 additions and 84 deletions
|
@ -83,12 +83,8 @@ class TaskExecutor:
|
||||||
display.debug("in run()")
|
display.debug("in run()")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# lookup plugins need to know if this task is executing from
|
# get search path for this task to pass to lookup plugins
|
||||||
# a role, so that it can properly find files/templates/etc.
|
self._job_vars['ansible_search_path'] = self._task.get_search_path()
|
||||||
roledir = None
|
|
||||||
if self._task._role:
|
|
||||||
roledir = self._task._role._role_path
|
|
||||||
self._job_vars['roledir'] = roledir
|
|
||||||
|
|
||||||
items = self._get_loop_items()
|
items = self._get_loop_items()
|
||||||
if items is not None:
|
if items is not None:
|
||||||
|
@ -192,7 +188,18 @@ class TaskExecutor:
|
||||||
except AnsibleUndefinedVariable as e:
|
except AnsibleUndefinedVariable as e:
|
||||||
display.deprecated("Skipping task due to undefined Error, in the future this will be a fatal error.: %s" % to_bytes(e))
|
display.deprecated("Skipping task due to undefined Error, in the future this will be a fatal error.: %s" % to_bytes(e))
|
||||||
return None
|
return None
|
||||||
items = self._shared_loader_obj.lookup_loader.get(self._task.loop, loader=self._loader, templar=templar).run(terms=loop_terms, variables=self._job_vars, wantlist=True)
|
|
||||||
|
# get lookup
|
||||||
|
mylookup = self._shared_loader_obj.lookup_loader.get(self._task.loop, loader=self._loader, templar=templar)
|
||||||
|
|
||||||
|
# give lookup task 'context' for subdir (mostly needed for first_found)
|
||||||
|
for subdir in ['tempalte', 'var', 'file']: #TODO: move this to constants?
|
||||||
|
if subdir in self._task.name:
|
||||||
|
break
|
||||||
|
setattr(mylookup,'_subdir', subdir + 's')
|
||||||
|
|
||||||
|
# run lookup
|
||||||
|
items = mylookup.run(terms=loop_terms, variables=self._job_vars, wantlist=True)
|
||||||
else:
|
else:
|
||||||
raise AnsibleError("Unexpected failure in finding the lookup named '%s' in the available lookup plugins" % self._task.loop)
|
raise AnsibleError("Unexpected failure in finding the lookup named '%s' in the available lookup plugins" % self._task.loop)
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
from ansible.compat.six import iteritems, string_types
|
from ansible.compat.six import iteritems, string_types
|
||||||
|
|
||||||
from ansible.errors import AnsibleError, AnsibleParserError
|
from ansible.errors import AnsibleError, AnsibleParserError
|
||||||
|
@ -454,3 +456,24 @@ class Task(Base, Conditional, Taggable, Become):
|
||||||
|
|
||||||
def _get_attr_loop_control(self):
|
def _get_attr_loop_control(self):
|
||||||
return self._attributes['loop_control']
|
return self._attributes['loop_control']
|
||||||
|
|
||||||
|
|
||||||
|
def get_search_path(self):
|
||||||
|
'''
|
||||||
|
Return the list of paths you should search for files, in order.
|
||||||
|
This follows role/playbook dependency chain.
|
||||||
|
'''
|
||||||
|
path_stack = []
|
||||||
|
|
||||||
|
dep_chain = self._block.get_dep_chain()
|
||||||
|
# inside role: add the dependency chain from current to dependant
|
||||||
|
if dep_chain:
|
||||||
|
path_stack.extend(reversed([x._role_path for x in dep_chain]))
|
||||||
|
|
||||||
|
# add path of task itself, unless it is already in the list
|
||||||
|
task_dir = os.path.dirname(self.get_path())
|
||||||
|
if task_dir not in path_stack:
|
||||||
|
path_stack.append(task_dir)
|
||||||
|
|
||||||
|
return path_stack
|
||||||
|
|
||||||
|
|
|
@ -831,18 +831,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||||
to get back the first existing file found.
|
to get back the first existing file found.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
path_stack = []
|
path_stack = self._task.get_search_path()
|
||||||
|
|
||||||
dep_chain = self._task._block.get_dep_chain()
|
|
||||||
# inside role: add the dependency chain
|
|
||||||
if dep_chain:
|
|
||||||
path_stack.extend(reversed([x._role_path for x in dep_chain]))
|
|
||||||
|
|
||||||
|
|
||||||
task_dir = os.path.dirname(self._task.get_path())
|
|
||||||
# include from diff directory: add it to file path
|
|
||||||
if not task_dir.endswith('tasks') and task_dir != self._loader.get_basedir():
|
|
||||||
path_stack.append(task_dir)
|
|
||||||
|
|
||||||
result = self._loader.path_dwim_relative_stack(path_stack, dirname, needle)
|
result = self._loader.path_dwim_relative_stack(path_stack, dirname, needle)
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ __metaclass__ = type
|
||||||
from abc import ABCMeta, abstractmethod
|
from abc import ABCMeta, abstractmethod
|
||||||
|
|
||||||
from ansible.compat.six import with_metaclass
|
from ansible.compat.six import with_metaclass
|
||||||
|
from ansible.errors import AnsibleFileNotFound
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from __main__ import display
|
from __main__ import display
|
||||||
|
@ -101,3 +102,19 @@ class LookupBase(with_metaclass(ABCMeta, object)):
|
||||||
result_string = to_unicode(result_string)
|
result_string = to_unicode(result_string)
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def find_file_in_search_path(self, myvars, subdir, needle):
|
||||||
|
'''
|
||||||
|
Return a file (needle) in the task's expected search path.
|
||||||
|
'''
|
||||||
|
|
||||||
|
if 'ansible_search_path' in myvars:
|
||||||
|
paths = myvars['ansible_search_path']
|
||||||
|
else:
|
||||||
|
paths = self.get_basedir(myvars)
|
||||||
|
|
||||||
|
result = self._loader.path_dwim_relative_stack(paths, subdir, needle)
|
||||||
|
if result is None:
|
||||||
|
raise AnsibleFileNotFound("Unable to find '%s' in expected paths." % needle)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
|
@ -72,8 +72,6 @@ class LookupModule(LookupBase):
|
||||||
|
|
||||||
def run(self, terms, variables=None, **kwargs):
|
def run(self, terms, variables=None, **kwargs):
|
||||||
|
|
||||||
basedir = self.get_basedir(variables)
|
|
||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
|
|
||||||
for term in terms:
|
for term in terms:
|
||||||
|
@ -100,7 +98,7 @@ class LookupModule(LookupBase):
|
||||||
if paramvals['delimiter'] == 'TAB':
|
if paramvals['delimiter'] == 'TAB':
|
||||||
paramvals['delimiter'] = "\t"
|
paramvals['delimiter'] = "\t"
|
||||||
|
|
||||||
lookupfile = self._loader.path_dwim_relative(basedir, 'files', paramvals['file'])
|
lookupfile = self.find_file_in_search_path(variables, 'files', paramvals['file'])
|
||||||
var = self.read_csv(lookupfile, key, paramvals['delimiter'], paramvals['encoding'], paramvals['default'], paramvals['col'])
|
var = self.read_csv(lookupfile, key, paramvals['delimiter'], paramvals['encoding'], paramvals['default'], paramvals['col'])
|
||||||
if var is not None:
|
if var is not None:
|
||||||
if type(var) is list:
|
if type(var) is list:
|
||||||
|
|
|
@ -33,18 +33,11 @@ class LookupModule(LookupBase):
|
||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
|
|
||||||
basedir = self.get_basedir(variables)
|
|
||||||
|
|
||||||
for term in terms:
|
for term in terms:
|
||||||
display.debug("File lookup term: %s" % term)
|
display.debug("File lookup term: %s" % term)
|
||||||
|
|
||||||
# Special handling of the file lookup, used primarily when the
|
# Find the file in the expected search path
|
||||||
# lookup is done from a role. If the file isn't found in the
|
lookupfile = self.find_file_in_search_path(variables, 'files', term)
|
||||||
# basedir of the current file, use dwim_relative to look in the
|
|
||||||
# role/files/ directory, and finally the playbook directory
|
|
||||||
# itself (which will be relative to the current working dir)
|
|
||||||
|
|
||||||
lookupfile = self._loader.path_dwim_relative(basedir, 'files', term)
|
|
||||||
display.vvvv("File lookup using %s as file" % lookupfile)
|
display.vvvv("File lookup using %s as file" % lookupfile)
|
||||||
try:
|
try:
|
||||||
if lookupfile:
|
if lookupfile:
|
||||||
|
|
|
@ -26,12 +26,10 @@ class LookupModule(LookupBase):
|
||||||
|
|
||||||
def run(self, terms, variables=None, **kwargs):
|
def run(self, terms, variables=None, **kwargs):
|
||||||
|
|
||||||
basedir = self.get_basedir(variables)
|
|
||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
for term in terms:
|
for term in terms:
|
||||||
term_file = os.path.basename(term)
|
term_file = os.path.basename(term)
|
||||||
dwimmed_path = self._loader.path_dwim_relative(basedir, 'files', os.path.dirname(term))
|
dwimmed_path = self.find_file_in_search_path(variables, 'files', os.path.dirname(term))
|
||||||
globbed = glob.glob(os.path.join(dwimmed_path, term_file))
|
globbed = glob.glob(os.path.join(dwimmed_path, term_file))
|
||||||
ret.extend(g for g in globbed if os.path.isfile(g))
|
ret.extend(g for g in globbed if os.path.isfile(g))
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -118,12 +118,11 @@ __metaclass__ = type
|
||||||
# - ../files/baz
|
# - ../files/baz
|
||||||
# ignore_errors: true
|
# ignore_errors: true
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from jinja2.exceptions import UndefinedError
|
from jinja2.exceptions import UndefinedError
|
||||||
|
|
||||||
from ansible.errors import AnsibleLookupError, AnsibleUndefinedVariable
|
from ansible.errors import AnsibleFileNotFound, AnsibleLookupError, AnsibleUndefinedVariable
|
||||||
from ansible.plugins.lookup import LookupBase
|
from ansible.plugins.lookup import LookupBase
|
||||||
from ansible.utils.boolean import boolean
|
from ansible.utils.boolean import boolean
|
||||||
|
|
||||||
|
@ -131,7 +130,6 @@ class LookupModule(LookupBase):
|
||||||
|
|
||||||
def run(self, terms, variables, **kwargs):
|
def run(self, terms, variables, **kwargs):
|
||||||
|
|
||||||
result = None
|
|
||||||
anydict = False
|
anydict = False
|
||||||
skip = False
|
skip = False
|
||||||
|
|
||||||
|
@ -173,28 +171,20 @@ class LookupModule(LookupBase):
|
||||||
else:
|
else:
|
||||||
total_search = self._flatten(terms)
|
total_search = self._flatten(terms)
|
||||||
|
|
||||||
roledir = variables.get('roledir')
|
|
||||||
for fn in total_search:
|
for fn in total_search:
|
||||||
try:
|
try:
|
||||||
fn = self._templar.template(fn)
|
fn = self._templar.template(fn)
|
||||||
except (AnsibleUndefinedVariable, UndefinedError) as e:
|
except (AnsibleUndefinedVariable, UndefinedError):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if os.path.isabs(fn) and os.path.exists(fn):
|
# get subdir if set by task executor, default to files otherwise
|
||||||
return [fn]
|
subdir = getattr(self, '_subdir', 'files')
|
||||||
else:
|
path = None
|
||||||
if roledir is not None:
|
try:
|
||||||
# check the templates and vars directories too,if they exist
|
path = self.find_file_in_search_path(variables, subdir, fn)
|
||||||
for subdir in ('templates', 'vars', 'files'):
|
return [path]
|
||||||
path = self._loader.path_dwim_relative(roledir, subdir, fn)
|
except AnsibleFileNotFound:
|
||||||
if os.path.exists(path):
|
continue
|
||||||
return [path]
|
|
||||||
|
|
||||||
# if none of the above were found, just check the
|
|
||||||
# current filename against the current dir
|
|
||||||
path = self._loader.path_dwim(fn)
|
|
||||||
if os.path.exists(path):
|
|
||||||
return [path]
|
|
||||||
else:
|
else:
|
||||||
if skip:
|
if skip:
|
||||||
return []
|
return []
|
||||||
|
|
|
@ -107,7 +107,7 @@ class LookupModule(LookupBase):
|
||||||
except (ValueError, AssertionError) as e:
|
except (ValueError, AssertionError) as e:
|
||||||
raise AnsibleError(e)
|
raise AnsibleError(e)
|
||||||
|
|
||||||
path = self._loader.path_dwim_relative(basedir, 'files', paramvals['file'])
|
path = self.find_file_in_search_path(variables, 'files', paramvals['file'])
|
||||||
if paramvals['type'] == "properties":
|
if paramvals['type'] == "properties":
|
||||||
var = self.read_properties(path, key, paramvals['default'], paramvals['re'])
|
var = self.read_properties(path, key, paramvals['default'], paramvals['re'])
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -18,7 +18,6 @@ from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
import shelve
|
import shelve
|
||||||
import os
|
|
||||||
|
|
||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
from ansible.plugins.lookup import LookupBase
|
from ansible.plugins.lookup import LookupBase
|
||||||
|
@ -43,9 +42,6 @@ class LookupModule(LookupBase):
|
||||||
ret = []
|
ret = []
|
||||||
|
|
||||||
for term in terms:
|
for term in terms:
|
||||||
playbook_path = None
|
|
||||||
relative_path = None
|
|
||||||
|
|
||||||
paramvals = {"file": None, "key": None}
|
paramvals = {"file": None, "key": None}
|
||||||
params = term.split()
|
params = term.split()
|
||||||
|
|
||||||
|
@ -59,24 +55,18 @@ class LookupModule(LookupBase):
|
||||||
# In case "file" or "key" are not present
|
# In case "file" or "key" are not present
|
||||||
raise AnsibleError(e)
|
raise AnsibleError(e)
|
||||||
|
|
||||||
file = paramvals['file']
|
|
||||||
key = paramvals['key']
|
key = paramvals['key']
|
||||||
basedir_path = self._loader.path_dwim(file)
|
|
||||||
|
|
||||||
# Search also in the role/files directory and in the playbook directory
|
# Search also in the role/files directory and in the playbook directory
|
||||||
if 'role_path' in variables:
|
shelvefile = self.find_file_in_search_path(variables, 'files', paramvals['file'])
|
||||||
relative_path = self._loader.path_dwim_relative(variables['role_path'], 'files', file)
|
|
||||||
if 'playbook_dir' in variables:
|
|
||||||
playbook_path = self._loader.path_dwim_relative(variables['playbook_dir'],'files', file)
|
|
||||||
|
|
||||||
for path in (basedir_path, relative_path, playbook_path):
|
if shelvefile:
|
||||||
if path and os.path.exists(path):
|
res = self.read_shelve(shelvefile, key)
|
||||||
res = self.read_shelve(path, key)
|
if res is None:
|
||||||
if res is None:
|
raise AnsibleError("Key %s not found in shelve file %s" % (key, file))
|
||||||
raise AnsibleError("Key %s not found in shelve file %s" % (key, file))
|
# Convert the value read to string
|
||||||
# Convert the value read to string
|
ret.append(str(res))
|
||||||
ret.append(str(res))
|
break
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
raise AnsibleError("Could not locate shelve file in lookup: %s" % file)
|
raise AnsibleError("Could not locate shelve file in lookup: %s" % file)
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ __metaclass__ = type
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from ansible import constants as C
|
|
||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
from ansible.plugins.lookup import LookupBase
|
from ansible.plugins.lookup import LookupBase
|
||||||
from ansible.utils.unicode import to_unicode
|
from ansible.utils.unicode import to_unicode
|
||||||
|
@ -36,26 +35,25 @@ class LookupModule(LookupBase):
|
||||||
def run(self, terms, variables, **kwargs):
|
def run(self, terms, variables, **kwargs):
|
||||||
|
|
||||||
convert_data_p = kwargs.get('convert_data', True)
|
convert_data_p = kwargs.get('convert_data', True)
|
||||||
basedir = self.get_basedir(variables)
|
|
||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
|
|
||||||
for term in terms:
|
for term in terms:
|
||||||
display.debug("File lookup term: %s" % term)
|
display.debug("File lookup term: %s" % term)
|
||||||
|
|
||||||
lookupfile = self._loader.path_dwim_relative(basedir, 'templates', term)
|
lookupfile = self.find_file_in_search_path(variables, 'templates', term)
|
||||||
display.vvvv("File lookup using %s as file" % lookupfile)
|
display.vvvv("File lookup using %s as file" % lookupfile)
|
||||||
if lookupfile and os.path.exists(lookupfile):
|
if lookupfile:
|
||||||
with open(lookupfile, 'r') as f:
|
with open(lookupfile, 'r') as f:
|
||||||
template_data = to_unicode(f.read())
|
template_data = to_unicode(f.read())
|
||||||
|
|
||||||
searchpath = [self._loader._basedir, os.path.dirname(lookupfile)]
|
# set jinja2 internal search path for includes
|
||||||
if 'role_path' in variables:
|
if 'ansible_search_path' in variables:
|
||||||
if C.DEFAULT_ROLES_PATH:
|
searchpath = variables['ansible_search_path']
|
||||||
searchpath[:0] = C.DEFAULT_ROLES_PATH
|
else:
|
||||||
searchpath.insert(1, variables['role_path'])
|
searchpath = [self._loader._basedir, os.path.dirname(lookupfile)]
|
||||||
|
|
||||||
self._templar.environment.loader.searchpath = searchpath
|
self._templar.environment.loader.searchpath = searchpath
|
||||||
|
|
||||||
|
# do the templating
|
||||||
res = self._templar.template(template_data, preserve_trailing_newlines=True,convert_data=convert_data_p)
|
res = self._templar.template(template_data, preserve_trailing_newlines=True,convert_data=convert_data_p)
|
||||||
ret.append(res)
|
ret.append(res)
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in a new issue