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.
This commit is contained in:
Erik Johnson 2016-12-07 11:36:45 -06:00
parent 1bb31bbebd
commit 71e0bd023f
3 changed files with 28 additions and 12 deletions

View File

@ -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,

View File

@ -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'])

View File

@ -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