From 71e0bd023f480ab635ea1186e5dae3a8e0ed26ff Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Wed, 7 Dec 2016 11:36:45 -0600 Subject: [PATCH] Fix edge case in creation of trans tar for salt-thin Using a simple ``str.find()`` on paths cached within the minion's salt-thin cachedir causes problems when the dir being cached is found in the minion ID itself. For example, assume that the master is prepping a salt-ssh state package for a minion named ``foo.bar.baz``, and one of the paths being cached is ``salt://foo``. As we iterate over the cached paths to write them to the trans tar, ``salt://foo/bar.sh`` would have been cached to a path like ``/var/cache/salt/master/salt-ssh/foo.bar.baz/files/base/foo/baz.sh``, and our str.find() would find the first ``foo`` in the minion ID instead of where we want (after the saltenv ``base``). This commit resolves this issue by ditching ``str.find()`` in favor of deriving the actual path we are looking for, so that when we use a string slice we are removing everything but the ``salt://`` fileserver path (which is what we want). It also makes the minion ID a required parameter, as A) we pass it everywhere we invoke ``prep_trans_tar()``, and B) not passing it would set its value to ``None``, resulting in an AttributeError when we try to join a ``None`` to the cachedir. --- salt/client/ssh/state.py | 19 ++++++++++++++----- salt/client/ssh/wrapper/state.py | 18 ++++++++++++------ salt/modules/dockerng.py | 3 ++- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/salt/client/ssh/state.py b/salt/client/ssh/state.py index d643b1bd63..1f11c82140 100644 --- a/salt/client/ssh/state.py +++ b/salt/client/ssh/state.py @@ -122,7 +122,7 @@ def salt_refs(data, ret=None): return ret -def prep_trans_tar(file_client, chunks, file_refs, pillar=None, id_=None): +def prep_trans_tar(opts, file_client, chunks, file_refs, pillar=None, id_=None): ''' Generate the execution package from the saltenv file refs and a low state data structure @@ -145,8 +145,18 @@ def prep_trans_tar(file_client, chunks, file_refs, pillar=None, id_=None): if pillar: with salt.utils.fopen(pillarfn, 'w+') as fp_: fp_.write(json.dumps(pillar)) - cachedir = os.path.join('salt-ssh', id_) + + if id_ is None: + id_ = '' + try: + cachedir = os.path.join(opts['cachedir'], 'salt-ssh', id_).rstrip(os.sep) + except AttributeError: + # Minion ID should always be a str, but don't let an int break this + cachedir = os.path.join(opts['cachedir'], 'salt-ssh', str(id_)).rstrip(os.sep) + for saltenv in file_refs: + # Location where files in this saltenv will be cached + cache_dest_root = os.path.join(cachedir, 'files', saltenv) file_refs[saltenv].extend(sync_refs) env_root = os.path.join(gendir, saltenv) if not os.path.isdir(env_root): @@ -154,6 +164,7 @@ def prep_trans_tar(file_client, chunks, file_refs, pillar=None, id_=None): for ref in file_refs[saltenv]: for name in ref: short = salt.utils.url.parse(name)[0] + cache_dest = os.path.join(cache_dest_root, short) try: path = file_client.cache_file(name, saltenv, cachedir=cachedir) except IOError: @@ -171,9 +182,7 @@ def prep_trans_tar(file_client, chunks, file_refs, pillar=None, id_=None): files = '' if files: for filename in files: - fn = filename[filename.find(short) + len(short):] - if fn.startswith('/'): - fn = fn.strip('/') + fn = filename[len(cache_dest):].strip('/') tgt = os.path.join( env_root, short, diff --git a/salt/client/ssh/wrapper/state.py b/salt/client/ssh/wrapper/state.py index 7bf66e9e01..006f7d0c2c 100644 --- a/salt/client/ssh/wrapper/state.py +++ b/salt/client/ssh/wrapper/state.py @@ -87,11 +87,12 @@ def sls(mods, saltenv='base', test=None, exclude=None, **kwargs): ) # Create the tar containing the state pkg and relevant files. trans_tar = salt.client.ssh.state.prep_trans_tar( + __opts__, __context__['fileclient'], chunks, file_refs, __pillar__, - id_=st_kwargs['id_']) + st_kwargs['id_']) trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__['hash_type']) cmd = 'state.pkg {0}/salt_state.tgz test={1} pkg_sum={2} hash_type={3}'.format( __opts__['thin_dir'], @@ -159,11 +160,12 @@ def low(data, **kwargs): ) # Create the tar containing the state pkg and relevant files. trans_tar = salt.client.ssh.state.prep_trans_tar( + __opts__, __context__['fileclient'], chunks, file_refs, __pillar__, - id_=st_kwargs['id_']) + st_kwargs['id_']) trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__['hash_type']) cmd = 'state.pkg {0}/salt_state.tgz pkg_sum={1} hash_type={2}'.format( __opts__['thin_dir'], @@ -226,11 +228,12 @@ def high(data, **kwargs): ) # Create the tar containing the state pkg and relevant files. trans_tar = salt.client.ssh.state.prep_trans_tar( + __opts__, __context__['fileclient'], chunks, file_refs, __pillar__, - id_=st_kwargs['id_']) + st_kwargs['id_']) trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__['hash_type']) cmd = 'state.pkg {0}/salt_state.tgz pkg_sum={1} hash_type={2}'.format( __opts__['thin_dir'], @@ -322,11 +325,12 @@ def highstate(test=None, **kwargs): return chunks # Create the tar containing the state pkg and relevant files. trans_tar = salt.client.ssh.state.prep_trans_tar( + __opts__, __context__['fileclient'], chunks, file_refs, __pillar__, - id_=st_kwargs['id_']) + st_kwargs['id_']) trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__['hash_type']) cmd = 'state.pkg {0}/salt_state.tgz test={1} pkg_sum={2} hash_type={3}'.format( __opts__['thin_dir'], @@ -396,11 +400,12 @@ def top(topfn, test=None, **kwargs): ) # Create the tar containing the state pkg and relevant files. trans_tar = salt.client.ssh.state.prep_trans_tar( + __opts__, __context__['fileclient'], chunks, file_refs, __pillar__, - id_=st_kwargs['id_']) + st_kwargs['id_']) trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__['hash_type']) cmd = 'state.pkg {0}/salt_state.tgz test={1} pkg_sum={2} hash_type={3}'.format( __opts__['thin_dir'], @@ -651,11 +656,12 @@ def single(fun, name, test=None, **kwargs): # Create the tar containing the state pkg and relevant files. trans_tar = salt.client.ssh.state.prep_trans_tar( + __opts__, __context__['fileclient'], chunks, file_refs, __pillar__, - id_=st_kwargs['id_']) + st_kwargs['id_']) # Create a hash so we can verify the tar on the target system trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__['hash_type']) diff --git a/salt/modules/dockerng.py b/salt/modules/dockerng.py index f3db83cdc5..4a86ccedeb 100644 --- a/salt/modules/dockerng.py +++ b/salt/modules/dockerng.py @@ -5670,8 +5670,9 @@ def _prepare_trans_tar(name, mods=None, saltenv='base', pillar=None): refs = salt.client.ssh.state.lowstate_file_refs(chunks) _mk_fileclient() trans_tar = salt.client.ssh.state.prep_trans_tar( + __opts__, __context__['cp.fileclient'], - chunks, refs, pillar=pillar, id_=name) + chunks, refs, pillar, name) return trans_tar