mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
Merge pull request #28226 from plastikos/improvement-module_package_collision
Improvement module package collision
This commit is contained in:
commit
05ed7d0bdc
@ -985,7 +985,8 @@ class LazyLoader(salt.utils.lazy.LazyDict):
|
||||
'''
|
||||
# map of suffix to description for imp
|
||||
self.suffix_map = {}
|
||||
suffix_order = [] # local list to determine precedence of extensions
|
||||
suffix_order = [''] # local list to determine precedence of extensions
|
||||
# Prefer packages (directories) over modules (single files)!
|
||||
for (suffix, mode, kind) in SUFFIXES:
|
||||
self.suffix_map[suffix] = (suffix, mode, kind)
|
||||
suffix_order.append(suffix)
|
||||
@ -1014,47 +1015,51 @@ class LazyLoader(salt.utils.lazy.LazyDict):
|
||||
try:
|
||||
files = os.listdir(mod_dir)
|
||||
except OSError:
|
||||
continue
|
||||
continue # Next mod_dir
|
||||
for filename in files:
|
||||
try:
|
||||
if filename.startswith('_'):
|
||||
# skip private modules
|
||||
# log messages omitted for obviousness
|
||||
continue
|
||||
continue # Next filename
|
||||
f_noext, ext = os.path.splitext(filename)
|
||||
# make sure it is a suffix we support
|
||||
if ext not in self.suffix_map:
|
||||
continue
|
||||
continue # Next filename
|
||||
if f_noext in self.disabled:
|
||||
log.trace(
|
||||
'Skipping {0}, it is disabled by configuration'.format(
|
||||
filename
|
||||
)
|
||||
)
|
||||
continue
|
||||
continue # Next filename
|
||||
fpath = os.path.join(mod_dir, filename)
|
||||
# if its a directory, lets allow us to load that
|
||||
if ext == '':
|
||||
# is there something __init__?
|
||||
subfiles = os.listdir(fpath)
|
||||
sub_path = None
|
||||
for suffix in suffix_order:
|
||||
if '' == suffix:
|
||||
continue # Next suffix (__init__ must have a suffix)
|
||||
init_file = '__init__{0}'.format(suffix)
|
||||
if init_file in subfiles:
|
||||
sub_path = os.path.join(fpath, init_file)
|
||||
break
|
||||
if sub_path is not None:
|
||||
self.file_mapping[f_noext] = (fpath, ext)
|
||||
else:
|
||||
continue # Next filename
|
||||
|
||||
# if we don't have it, we want it
|
||||
elif f_noext not in self.file_mapping:
|
||||
self.file_mapping[f_noext] = (fpath, ext)
|
||||
# if we do, we want it if we have a higher precidence ext
|
||||
else:
|
||||
if f_noext in self.file_mapping:
|
||||
curr_ext = self.file_mapping[f_noext][1]
|
||||
#log.debug("****** curr_ext={0} ext={1} suffix_order={2}".format(curr_ext, ext, suffix_order))
|
||||
if curr_ext and suffix_order.index(ext) < suffix_order.index(curr_ext):
|
||||
self.file_mapping[f_noext] = (fpath, ext)
|
||||
if '' in (curr_ext, ext) and curr_ext != ext:
|
||||
log.error('Module/package collision: {0!r} and {1!r}'.format(
|
||||
fpath, self.file_mapping[f_noext][0]
|
||||
))
|
||||
if suffix_order.index(ext) >= suffix_order.index(curr_ext):
|
||||
continue # Next filename
|
||||
|
||||
# Made it this far - add it
|
||||
self.file_mapping[f_noext] = (fpath, ext)
|
||||
|
||||
except OSError:
|
||||
continue
|
||||
for smod in self.static_modules:
|
||||
|
@ -435,6 +435,94 @@ class LazyLoaderSubmodReloadingTest(TestCase):
|
||||
self.assertNotIn(self.module_key, self.loader)
|
||||
|
||||
|
||||
mod_template = '''
|
||||
def test():
|
||||
return ({val})
|
||||
'''
|
||||
|
||||
|
||||
class LazyLoaderModulePackageTest(TestCase):
|
||||
'''
|
||||
Test the loader of salt with changing modules
|
||||
'''
|
||||
module_name = 'loadertestmodpkg'
|
||||
module_key = 'loadertestmodpkg.test'
|
||||
|
||||
def setUp(self):
|
||||
self.opts = _config = minion_config(None)
|
||||
self.opts['grains'] = grains(self.opts)
|
||||
self.tmp_dir = tempfile.mkdtemp(dir=tests.integration.TMP)
|
||||
|
||||
dirs = _module_dirs(self.opts, 'modules', 'module')
|
||||
dirs.append(self.tmp_dir)
|
||||
self.loader = LazyLoader(dirs,
|
||||
self.opts,
|
||||
tag='module')
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tmp_dir)
|
||||
|
||||
def update_pyfile(self, pyfile, contents):
|
||||
dirname = os.path.dirname(pyfile)
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
with open(pyfile, 'wb') as fh:
|
||||
fh.write(contents)
|
||||
fh.flush()
|
||||
os.fsync(fh.fileno()) # flush to disk
|
||||
|
||||
# pyc files don't like it when we change the original quickly
|
||||
# since the header bytes only contain the timestamp (granularity of seconds)
|
||||
# TODO: don't write them? Is *much* slower on re-load (~3x)
|
||||
# https://docs.python.org/2/library/sys.html#sys.dont_write_bytecode
|
||||
try:
|
||||
os.unlink(pyfile + 'c')
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def rm_pyfile(self, pyfile):
|
||||
os.unlink(pyfile)
|
||||
os.unlink(pyfile + 'c')
|
||||
|
||||
def update_module(self, relative_path, contents):
|
||||
self.update_pyfile(os.path.join(self.tmp_dir, relative_path), contents)
|
||||
|
||||
def rm_module(self, relative_path):
|
||||
self.rm_pyfile(os.path.join(self.tmp_dir, relative_path))
|
||||
|
||||
def test_module(self):
|
||||
# ensure it doesn't exist
|
||||
self.assertNotIn('foo', self.loader)
|
||||
self.assertNotIn('foo.test', self.loader)
|
||||
self.update_module('foo.py', mod_template.format(val=1))
|
||||
self.loader.clear()
|
||||
self.assertIn('foo.test', self.loader)
|
||||
self.assertEqual(self.loader['foo.test'](), 1)
|
||||
|
||||
def test_package(self):
|
||||
# ensure it doesn't exist
|
||||
self.assertNotIn('foo', self.loader)
|
||||
self.assertNotIn('foo.test', self.loader)
|
||||
self.update_module('foo/__init__.py', mod_template.format(val=2))
|
||||
self.loader.clear()
|
||||
self.assertIn('foo.test', self.loader)
|
||||
self.assertEqual(self.loader['foo.test'](), 2)
|
||||
|
||||
def test_module_package_collision(self):
|
||||
# ensure it doesn't exist
|
||||
self.assertNotIn('foo', self.loader)
|
||||
self.assertNotIn('foo.test', self.loader)
|
||||
self.update_module('foo.py', mod_template.format(val=3))
|
||||
self.loader.clear()
|
||||
self.assertIn('foo.test', self.loader)
|
||||
self.assertEqual(self.loader['foo.test'](), 3)
|
||||
|
||||
self.update_module('foo/__init__.py', mod_template.format(val=4))
|
||||
self.loader.clear()
|
||||
self.assertIn('foo.test', self.loader)
|
||||
self.assertEqual(self.loader['foo.test'](), 4)
|
||||
|
||||
|
||||
deep_init_base = '''
|
||||
import top_lib
|
||||
import top_lib.mid_lib
|
||||
|
Loading…
Reference in New Issue
Block a user