Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed lookup search path #16630

Merged
merged 7 commits into from
Jul 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 14 additions & 7 deletions lib/ansible/executor/task_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,8 @@ def run(self):
display.debug("in run()")

try:
# lookup plugins need to know if this task is executing from
# a role, so that it can properly find files/templates/etc.
roledir = None
if self._task._role:
roledir = self._task._role._role_path
self._job_vars['roledir'] = roledir
# get search path for this task to pass to lookup plugins
self._job_vars['ansible_search_path'] = self._task.get_search_path()

items = self._get_loop_items()
if items is not None:
Expand Down Expand Up @@ -192,7 +188,18 @@ def _get_loop_items(self):
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))
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?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

template is misspelled.

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:
raise AnsibleError("Unexpected failure in finding the lookup named '%s' in the available lookup plugins" % self._task.loop)

Expand Down
23 changes: 23 additions & 0 deletions lib/ansible/playbook/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

import os

from ansible.compat.six import iteritems, string_types

from ansible.errors import AnsibleError, AnsibleParserError
Expand Down Expand Up @@ -454,3 +456,24 @@ def _get_attr_loop(self):

def _get_attr_loop_control(self):
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

13 changes: 1 addition & 12 deletions lib/ansible/plugins/action/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -831,18 +831,7 @@ def _find_needle(self, dirname, needle):
to get back the first existing file found.
'''

path_stack = []

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)
path_stack = self._task.get_search_path()

result = self._loader.path_dwim_relative_stack(path_stack, dirname, needle)

Expand Down
17 changes: 17 additions & 0 deletions lib/ansible/plugins/lookup/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from abc import ABCMeta, abstractmethod

from ansible.compat.six import with_metaclass
from ansible.errors import AnsibleFileNotFound

try:
from __main__ import display
Expand Down Expand Up @@ -101,3 +102,19 @@ def run(self, terms, variables=None, **kwargs):
result_string = to_unicode(result_string)
"""
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
4 changes: 1 addition & 3 deletions lib/ansible/plugins/lookup/csvfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ def read_csv(self, filename, key, delimiter, encoding='utf-8', dflt=None, col=1)

def run(self, terms, variables=None, **kwargs):

basedir = self.get_basedir(variables)

ret = []

for term in terms:
Expand All @@ -100,7 +98,7 @@ def run(self, terms, variables=None, **kwargs):
if paramvals['delimiter'] == 'TAB':
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'])
if var is not None:
if type(var) is list:
Expand Down
11 changes: 2 additions & 9 deletions lib/ansible/plugins/lookup/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,11 @@ def run(self, terms, variables=None, **kwargs):

ret = []

basedir = self.get_basedir(variables)

for term in terms:
display.debug("File lookup term: %s" % term)

# Special handling of the file lookup, used primarily when the
# lookup is done from a role. If the file isn't found in the
# 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)
# Find the file in the expected search path
lookupfile = self.find_file_in_search_path(variables, 'files', term)
display.vvvv("File lookup using %s as file" % lookupfile)
try:
if lookupfile:
Expand Down
4 changes: 1 addition & 3 deletions lib/ansible/plugins/lookup/fileglob.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ class LookupModule(LookupBase):

def run(self, terms, variables=None, **kwargs):

basedir = self.get_basedir(variables)

ret = []
for term in terms:
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))
ret.extend(g for g in globbed if os.path.isfile(g))
return ret
30 changes: 10 additions & 20 deletions lib/ansible/plugins/lookup/first_found.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,18 @@
# - ../files/baz
# ignore_errors: true


import os

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.utils.boolean import boolean

class LookupModule(LookupBase):

def run(self, terms, variables, **kwargs):

result = None
anydict = False
skip = False

Expand Down Expand Up @@ -173,28 +171,20 @@ def run(self, terms, variables, **kwargs):
else:
total_search = self._flatten(terms)

roledir = variables.get('roledir')
for fn in total_search:
try:
fn = self._templar.template(fn)
except (AnsibleUndefinedVariable, UndefinedError) as e:
except (AnsibleUndefinedVariable, UndefinedError):
continue

if os.path.isabs(fn) and os.path.exists(fn):
return [fn]
else:
if roledir is not None:
# check the templates and vars directories too,if they exist
for subdir in ('templates', 'vars', 'files'):
path = self._loader.path_dwim_relative(roledir, subdir, fn)
if os.path.exists(path):
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]
# get subdir if set by task executor, default to files otherwise
subdir = getattr(self, '_subdir', 'files')
path = None
try:
path = self.find_file_in_search_path(variables, subdir, fn)
return [path]
except AnsibleFileNotFound:
continue
else:
if skip:
return []
Expand Down
2 changes: 1 addition & 1 deletion lib/ansible/plugins/lookup/ini.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def run(self, terms, variables=None, **kwargs):
except (ValueError, AssertionError) as 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":
var = self.read_properties(path, key, paramvals['default'], paramvals['re'])
else:
Expand Down
28 changes: 9 additions & 19 deletions lib/ansible/plugins/lookup/shelvefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
__metaclass__ = type

import shelve
import os

from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase
Expand All @@ -43,9 +42,6 @@ def run(self, terms, variables=None, **kwargs):
ret = []

for term in terms:
playbook_path = None
relative_path = None

paramvals = {"file": None, "key": None}
params = term.split()

Expand All @@ -59,24 +55,18 @@ def run(self, terms, variables=None, **kwargs):
# In case "file" or "key" are not present
raise AnsibleError(e)

file = paramvals['file']
key = paramvals['key']
basedir_path = self._loader.path_dwim(file)

# Search also in the role/files directory and in the playbook directory
if 'role_path' in variables:
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 path and os.path.exists(path):
res = self.read_shelve(path, key)
if res is None:
raise AnsibleError("Key %s not found in shelve file %s" % (key, file))
# Convert the value read to string
ret.append(str(res))
break
shelvefile = self.find_file_in_search_path(variables, 'files', paramvals['file'])

if shelvefile:
res = self.read_shelve(shelvefile, key)
if res is None:
raise AnsibleError("Key %s not found in shelve file %s" % (key, file))
# Convert the value read to string
ret.append(str(res))
break
else:
raise AnsibleError("Could not locate shelve file in lookup: %s" % file)

Expand Down
20 changes: 9 additions & 11 deletions lib/ansible/plugins/lookup/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import os

from ansible import constants as C
from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase
from ansible.utils.unicode import to_unicode
Expand All @@ -36,26 +35,25 @@ class LookupModule(LookupBase):
def run(self, terms, variables, **kwargs):

convert_data_p = kwargs.get('convert_data', True)
basedir = self.get_basedir(variables)

ret = []

for term in terms:
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)
if lookupfile and os.path.exists(lookupfile):
if lookupfile:
with open(lookupfile, 'r') as f:
template_data = to_unicode(f.read())

searchpath = [self._loader._basedir, os.path.dirname(lookupfile)]
if 'role_path' in variables:
if C.DEFAULT_ROLES_PATH:
searchpath[:0] = C.DEFAULT_ROLES_PATH
searchpath.insert(1, variables['role_path'])

# set jinja2 internal search path for includes
if 'ansible_search_path' in variables:
searchpath = variables['ansible_search_path']
else:
searchpath = [self._loader._basedir, os.path.dirname(lookupfile)]
self._templar.environment.loader.searchpath = searchpath

# do the templating
res = self._templar.template(template_data, preserve_trailing_newlines=True,convert_data=convert_data_p)
ret.append(res)
else:
Expand Down