Merge pull request #8230 from s0undt3ch/issues/8196-environments

Properly pass `__env__` to states.
This commit is contained in:
Thomas S Hatch 2013-11-06 14:23:26 -08:00
commit a343e69d02
30 changed files with 648 additions and 142 deletions

View File

@ -682,11 +682,18 @@ class RemoteClient(Client):
hash_server = self.hash_file(path, env)
if hash_local == hash_server:
log.info(
'Fetching file ** skipped **, '
'latest already in cache \'{0}\''.format(path))
'Fetching file from env {0!r}, ** skipped ** '
'latest already in cache {1!r}'.format(
env, path
)
)
return dest2check
log.debug('Fetching file ** attempting ** \'{0}\''.format(path))
log.debug(
'Fetching file from env {0!r}, ** attempting ** {1!r}'.format(
env, path
)
)
d_tries = 0
path = self._check_proto(path)
load = {'path': path,
@ -751,7 +758,11 @@ class RemoteClient(Client):
fn_.write(data)
if fn_:
fn_.close()
log.info('Fetching file ** done ** \'{0}\''.format(path))
log.info(
'Fetching file from env {0!r}, ** done ** {1!r}'.format(
env, path
)
)
return dest
def file_list(self, env='base', prefix=''):

View File

@ -114,7 +114,7 @@ def _chugid_and_umask(runas, umask):
os.umask(umask)
def _render_cmd(cmd, cwd, template):
def _render_cmd(cmd, cwd, template, saltenv='base'):
'''
If template is a valid template engine, process the cmd and cwd through
that engine.
@ -134,7 +134,7 @@ def _render_cmd(cmd, cwd, template):
kwargs['pillar'] = __pillar__
kwargs['grains'] = __grains__
kwargs['opts'] = __opts__
kwargs['env'] = 'base'
kwargs['env'] = saltenv
def _render(contents):
# write out path to temp file
@ -178,7 +178,8 @@ def _run(cmd,
umask=None,
timeout=None,
with_communicate=True,
reset_system_locale=True):
reset_system_locale=True,
saltenv='base'):
'''
Do the DRY thing and only call subprocess.Popen() once
'''
@ -221,7 +222,7 @@ def _run(cmd,
cmd = 'Powershell ' + cmd
# munge the cmd and cwd through the template
(cmd, cwd) = _render_cmd(cmd, cwd, template)
(cmd, cwd) = _render_cmd(cmd, cwd, template, saltenv)
ret = {}
@ -248,8 +249,9 @@ def _run(cmd,
try:
pwd.getpwnam(runas)
except KeyError:
msg = 'User \'{0}\' is not available'.format(runas)
raise CommandExecutionError(msg)
raise CommandExecutionError(
'User {0!r} is not available'.format(runas)
)
try:
# Getting the environment for the runas user
# There must be a better way to do this.
@ -276,8 +278,11 @@ def _run(cmd,
env_runas.update(env)
env = env_runas
except ValueError:
msg = 'Environment could not be retrieved for User \'{0}\''.format(runas)
raise CommandExecutionError(msg)
raise CommandExecutionError(
'Environment could not be retrieved for User {0!r}'.format(
runas
)
)
if not salt.utils.is_true(quiet):
# Put the most common case first
@ -388,7 +393,8 @@ def _run_quiet(cmd,
template=None,
umask=None,
timeout=None,
reset_system_locale=True):
reset_system_locale=True,
saltenv='base'):
'''
Helper for running commands quietly for minion startup
'''
@ -404,7 +410,8 @@ def _run_quiet(cmd,
template=template,
umask=umask,
timeout=timeout,
reset_system_locale=reset_system_locale)['stdout']
reset_system_locale=reset_system_locale,
saltenv=saltenv)['stdout']
def _run_all_quiet(cmd,
@ -417,7 +424,8 @@ def _run_all_quiet(cmd,
template=None,
umask=None,
timeout=None,
reset_system_locale=True):
reset_system_locale=True,
saltenv='base'):
'''
Helper for running commands quietly for minion startup.
Returns a dict of return data
@ -433,7 +441,8 @@ def _run_all_quiet(cmd,
template=template,
umask=umask,
timeout=timeout,
reset_system_locale=reset_system_locale)
reset_system_locale=reset_system_locale,
saltenv=saltenv)
def run(cmd,
@ -450,6 +459,7 @@ def run(cmd,
quiet=False,
timeout=None,
reset_system_locale=True,
saltenv='base',
**kwargs):
'''
Execute the passed command and return the output as a string
@ -499,7 +509,8 @@ def run(cmd,
umask=umask,
quiet=quiet,
timeout=timeout,
reset_system_locale=reset_system_locale)['stdout']
reset_system_locale=reset_system_locale,
saltenv=saltenv)['stdout']
if not quiet:
log.debug('output: {0}'.format(out))
return out
@ -519,6 +530,7 @@ def run_stdout(cmd,
quiet=False,
timeout=None,
reset_system_locale=True,
saltenv='base',
**kwargs):
'''
Execute a command, and only return the standard out
@ -561,7 +573,8 @@ def run_stdout(cmd,
umask=umask,
quiet=quiet,
timeout=timeout,
reset_system_locale=reset_system_locale)["stdout"]
reset_system_locale=reset_system_locale,
saltenv=saltenv)['stdout']
if not quiet:
log.debug('stdout: {0}'.format(stdout))
return stdout
@ -581,6 +594,7 @@ def run_stderr(cmd,
quiet=False,
timeout=None,
reset_system_locale=True,
saltenv='base',
**kwargs):
'''
Execute a command and only return the standard error
@ -623,7 +637,8 @@ def run_stderr(cmd,
umask=umask,
quiet=quiet,
timeout=timeout,
reset_system_locale=reset_system_locale)["stderr"]
reset_system_locale=reset_system_locale,
saltenv=saltenv)['stderr']
if not quiet:
log.debug('stderr: {0}'.format(stderr))
return stderr
@ -643,6 +658,7 @@ def run_all(cmd,
quiet=False,
timeout=None,
reset_system_locale=True,
saltenv='base',
**kwargs):
'''
Execute the passed command and return a dict of return data
@ -685,13 +701,15 @@ def run_all(cmd,
umask=umask,
quiet=quiet,
timeout=timeout,
reset_system_locale=reset_system_locale)
reset_system_locale=reset_system_locale,
saltenv=saltenv)
if not quiet:
if ret['retcode'] != 0:
rcode = ret['retcode']
msg = 'Command \'{0}\' failed with return code: {1}'
log.error(msg.format(cmd, rcode))
log.error(
'Command {0!r} failed with return code: {1}'.format(cmd, rcode)
)
# Don't log a blank line if there is no stderr or stdout
if ret['stdout']:
log.error('stdout: {0}'.format(ret['stdout']))
@ -719,6 +737,7 @@ def retcode(cmd,
quiet=False,
timeout=None,
reset_system_locale=True,
saltenv='base',
**kwargs):
'''
Execute a shell command and return the command's return code.
@ -761,7 +780,8 @@ def retcode(cmd,
quiet=quiet,
timeout=timeout,
with_communicate=False,
reset_system_locale=reset_system_locale)['retcode']
reset_system_locale=reset_system_locale,
saltenv=saltenv)['retcode']
def script(source,
@ -776,7 +796,8 @@ def script(source,
umask=None,
timeout=None,
reset_system_locale=True,
__env__='base',
__env__=None,
saltenv='base',
**kwargs):
'''
Download a script from a remote location and execute the script locally.
@ -812,19 +833,19 @@ def script(source,
log.error('cmd.script: Unable to clean tempfile {0!r}: {1}'
.format(path, exc))
if isinstance(env, string_types):
if isinstance(__env__, string_types):
salt.utils.warn_until(
'Helium',
'Passing a salt environment should be done using \'__env__\' not '
'\'env\'. This functionality will be removed in Salt {version}.'
'Passing a salt environment should be done using \'saltenv\' not '
'\'__env__\'. This functionality will be removed in Salt Helium.'
)
# Backwards compatibility
__env__ = env
saltenv = __env__
if not salt.utils.is_windows():
path = salt.utils.mkstemp(dir=cwd)
else:
path = __salt__['cp.cache_file'](source, __env__)
path = __salt__['cp.cache_file'](source, saltenv)
if not path:
_cleanup_tempfile(path)
return {'pid': 0,
@ -837,7 +858,7 @@ def script(source,
fn_ = __salt__['cp.get_template'](source,
path,
template,
__env__,
saltenv,
**kwargs)
if not fn_:
_cleanup_tempfile(path)
@ -848,7 +869,7 @@ def script(source,
'cache_error': True}
else:
if not salt.utils.is_windows():
fn_ = __salt__['cp.cache_file'](source, __env__)
fn_ = __salt__['cp.cache_file'](source, saltenv)
if not fn_:
_cleanup_tempfile(path)
return {'pid': 0,
@ -869,7 +890,8 @@ def script(source,
python_shell=python_shell,
umask=umask,
timeout=timeout,
reset_system_locale=reset_system_locale)
reset_system_locale=reset_system_locale,
saltenv=saltenv)
_cleanup_tempfile(path)
return ret
@ -885,7 +907,8 @@ def script_retcode(source,
umask=None,
timeout=None,
reset_system_locale=True,
__env__='base',
__env__=None,
saltenv='base'
**kwargs):
'''
Download a script from a remote location and execute the script locally.
@ -913,6 +936,15 @@ def script_retcode(source,
salt '*' cmd.script_retcode salt://scripts/runme.sh stdin='one\\ntwo\\nthree\\nfour\\nfive\\n'
'''
if isinstance(__env__, string_types):
salt.utils.warn_until(
'Helium',
'Passing a salt environment should be done using \'saltenv\' not '
'\'env\'. This functionality will be removed in Salt Helium.'
)
# Backwards compatibility
saltenv = __env__
return script(source=source,
cwd=cwd,
stdin=stdin,
@ -924,6 +956,7 @@ def script_retcode(source,
umask=umask,
timeout=timeout,
reset_system_locale=reset_system_locale,
saltenv=saltenv,
**kwargs)['retcode']

View File

@ -134,7 +134,7 @@ def set_(package, question, type, value, *extra):
return True
def set_file(path, **kwargs):
def set_file(path, saltenv='base', **kwargs):
'''
Set answers to debconf questions from a file.
@ -144,7 +144,15 @@ def set_file(path, **kwargs):
salt '*' debconf.set_file salt://pathto/pkg.selections
'''
path = __salt__['cp.cache_file'](path, kwargs.get('__env__', 'base'))
if '__env__' in kwargs:
salt.utils.warn_until(
'Helium',
'Passing a salt environment should be done using \'saltenv\' not '
'\'__env__\'. This functionality will be removed in Salt Helium.'
)
# Backwards compatibility
saltenv = kwargs['__env__']
path = __salt__['cp.cache_file'](path, saltenv)
if path:
_set_file(path)
return True

View File

@ -1966,34 +1966,37 @@ def _script(status,
stdin=None,
runas=None,
shell=cmdmod.DEFAULT_SHELL,
env=(),
env=None,
template='jinja',
umask=None,
timeout=None,
reset_system_locale=True,
__env__='base',
run_func_=None,
no_clean=False,
saltenv='base',
**kwargs):
try:
if not run_func_:
run_func_ = run_all
rpath = get_container_root(container)
tpath = os.path.join(rpath, 'tmp')
if isinstance(env, string_types):
salt.utils.warn_until(
'Helium',
'Passing a salt environment should be done using \'__env__\' '
'not \'env\'.'
'Passing a salt environment should be done using \'saltenv\' '
'not \'env\'. This functionality will be removed in Salt '
'Helium.'
)
# Backwards compatibility
__env__ = env
saltenv = env
path = salt.utils.mkstemp(dir=tpath)
if template:
__salt__['cp.get_template'](
source, path, template, __env__, **kwargs)
source, path, template, saltenv, **kwargs)
else:
fn_ = __salt__['cp.cache_file'](source, __env__)
fn_ = __salt__['cp.cache_file'](source, saltenv)
if not fn_:
return {'pid': 0,
'retcode': 1,
@ -2028,13 +2031,13 @@ def script(container,
stdin=None,
runas=None,
shell=cmdmod.DEFAULT_SHELL,
env=(),
env=None,
template='jinja',
umask=None,
timeout=None,
reset_system_locale=True,
__env__='base',
no_clean=False,
saltenv='base'
*nargs,
**kwargs):
'''
@ -2057,6 +2060,17 @@ def script(container,
salt '*' docker.script <container id> salt://docker_script.py
'''
status = base_status.copy()
if isinstance(env, string_types):
salt.utils.warn_until(
'Helium',
'Passing a salt environment should be done using \'saltenv\' '
'not \'env\'. This functionality will be removed in Salt '
'Helium.'
)
# Backwards compatibility
saltenv = env
return _script(status,
container,
source,
@ -2065,13 +2079,12 @@ def script(container,
stdin=stdin,
runas=runas,
shell=shell,
env=env,
template=template,
umask=umask,
timeout=timeout,
reset_system_locale=reset_system_locale,
__env__=__env__,
no_clean=no_clean,
saltenv=saltenv,
**kwargs)
@ -2081,13 +2094,13 @@ def script_retcode(container,
stdin=None,
runas=None,
shell=cmdmod.DEFAULT_SHELL,
env=(),
env=None,
template='jinja',
umask=None,
timeout=None,
reset_system_locale=True,
__env__='base',
no_clean=False,
saltenv='base',
*args,
**kwargs):
'''
@ -2109,17 +2122,28 @@ def script_retcode(container,
salt '*' docker.script_retcode <container id> salt://docker_script.py
'''
if isinstance(env, string_types):
salt.utils.warn_until(
'Helium',
'Passing a salt environment should be done using \'saltenv\' '
'not \'env\'. This functionality will be removed in Salt '
'Helium.'
)
# Backwards compatibility
saltenv = env
return _script(container,
source=source,
cwd=cwd,
stdin=stdin,
runas=runas,
shell=shell,
env=env,
template=template,
umask=umask,
timeout=timeout,
reset_system_locale=reset_system_locale,
run_func_=retcode,
no_clean=no_clean,
saltenv=saltenv,
**kwargs)

View File

@ -52,21 +52,21 @@ def _get_pip_bin(bin_env):
return bin_env
def _get_cached_requirements(requirements, __env__):
def _get_cached_requirements(requirements, saltenv):
'''Get the location of a cached requirements file; caching if necessary.'''
cached_requirements = __salt__['cp.is_cached'](
requirements, __env__
requirements, saltenv
)
if not cached_requirements:
# It's not cached, let's cache it.
cached_requirements = __salt__['cp.cache_file'](
requirements, __env__
requirements, saltenv
)
# Check if the master version has changed.
if __salt__['cp.hash_file'](requirements, __env__) != \
__salt__['cp.hash_file'](cached_requirements, __env__):
if __salt__['cp.hash_file'](requirements, saltenv) != \
__salt__['cp.hash_file'](cached_requirements, saltenv):
cached_requirements = __salt__['cp.cache_file'](
requirements, __env__
requirements, saltenv
)
return cached_requirements
@ -120,7 +120,8 @@ def install(pkgs=None,
cwd=None,
activate=False,
pre_releases=False,
__env__='base'):
__env__=None,
saltenv='base'):
'''
Install packages with pip
@ -245,6 +246,16 @@ def install(pkgs=None,
if env and not bin_env:
bin_env = env
if isinstance(__env__, string_types):
salt.utils.warn_until(
'Helium',
'Passing a salt environment should be done using \'saltenv\' '
'not \'__env__\'. This functionality will be removed in Salt '
'Helium.'
)
# Backwards compatibility
saltenv = __env__
if runas is not None:
# The user is using a deprecated argument, warn!
salt.utils.warn_until(
@ -279,7 +290,7 @@ def install(pkgs=None,
treq = None
if requirement.startswith('salt://'):
cached_requirements = _get_cached_requirements(
requirement, __env__
requirement, saltenv
)
if not cached_requirements:
return {
@ -481,7 +492,7 @@ def install(pkgs=None,
cmd.append('--editable={0}'.format(entry))
try:
cmd_kwargs = dict(runas=user, cwd=cwd)
cmd_kwargs = dict(runas=user, cwd=cwd, saltenv=saltenv)
if bin_env and os.path.isdir(bin_env):
cmd_kwargs['env'] = {'VIRTUAL_ENV': bin_env}
return __salt__['cmd.run_all'](' '.join(cmd), **cmd_kwargs)
@ -503,7 +514,8 @@ def uninstall(pkgs=None,
runas=None,
no_chown=False,
cwd=None,
__env__='base'):
__env__=None,
saltenv='base'):
'''
Uninstall packages with pip
@ -556,6 +568,16 @@ def uninstall(pkgs=None,
'''
cmd = [_get_pip_bin(bin_env), 'uninstall', '-y']
if isinstance(__env__, string_types):
salt.utils.warn_until(
'Helium',
'Passing a salt environment should be done using \'saltenv\' '
'not \'__env__\'. This functionality will be removed in Salt '
'Helium.'
)
# Backwards compatibility
saltenv = __env__
if runas is not None:
# The user is using a deprecated argument, warn!
salt.utils.warn_until(
@ -584,7 +606,7 @@ def uninstall(pkgs=None,
treq = None
if requirement.startswith('salt://'):
cached_requirements = _get_cached_requirements(
requirement, __env__
requirement, saltenv
)
if not cached_requirements:
return {
@ -636,7 +658,7 @@ def uninstall(pkgs=None,
pkgs = [p.strip() for p in pkgs.split(',')]
cmd.extend(pkgs)
cmd_kwargs = dict(runas=user, cwd=cwd)
cmd_kwargs = dict(runas=user, cwd=cwd, saltenv=saltenv)
if bin_env and os.path.isdir(bin_env):
cmd_kwargs['env'] = {'VIRTUAL_ENV': bin_env}

View File

@ -191,7 +191,11 @@ def _verify_binary_pkg(srcinfo):
return problems
def parse_targets(name=None, pkgs=None, sources=None, **kwargs):
def parse_targets(name=None,
pkgs=None,
sources=None,
saltenv='base',
**kwargs):
'''
Parses the input to pkg.install and returns back the package(s) to be
installed. Returns a list of packages, as well as a string noting whether
@ -203,6 +207,16 @@ def parse_targets(name=None, pkgs=None, sources=None, **kwargs):
salt '*' pkg_resource.parse_targets
'''
if '__env__' in kwargs:
salt.utils.warn_until(
'Helium',
'Passing a salt environment should be done using \'saltenv\' '
'not \'__env__\'. This functionality will be removed in Salt '
'Helium.'
)
# Backwards compatibility
saltenv = kwargs['__env__']
if __grains__['os'] == 'MacOS' and sources:
log.warning('Parameter "sources" ignored on MacOS hosts.')
@ -228,9 +242,7 @@ def parse_targets(name=None, pkgs=None, sources=None, **kwargs):
# Cache package from remote source (salt master, HTTP, FTP)
srcinfo.append((pkg_name,
pkg_src,
__salt__['cp.cache_file'](pkg_src,
kwargs.get('__env__',
'base')),
__salt__['cp.cache_file'](pkg_src, saltenv),
'remote'))
else:
# Package file local to the minion

View File

@ -30,6 +30,7 @@ import salt.pillar
import salt.fileclient
import salt.utils.event
import salt.syspaths as syspaths
from salt.utils import context
from salt._compat import string_types
from salt.template import compile_template, compile_template_str
from salt.exceptions import SaltReqTimeoutError, SaltException
@ -1260,12 +1261,31 @@ class State(object):
test = sys.modules[self.states[cdata['full']].__module__].__opts__['test']
sys.modules[self.states[cdata['full']].__module__].__opts__['test'] = True
try:
if 'kwargs' in cdata:
ret = self.states[cdata['full']](
*cdata['args'], **cdata['kwargs'])
# Let's get a reference to the salt environment to use within this
# state call.
#
# If the state function accepts an 'env' keyword argument, it
# allows the state to be overridden(we look for that in cdata). If
# that's not found in cdata, we look for what we're being passed in
# the original data, namely, the special dunder __env__. If that's
# not found we default to 'base'
if cdata['kwargs'].get('env', None) is not None:
# User is using a deprecated env setting which was parsed by
# format_call
env = cdata['kwargs']['env']
elif '__env__' in data:
# The user is passing an alternative environement using the
# proper keyword argument
env = data['__env__']
else:
ret = self.states[cdata['full']](*cdata['args'])
self.verify_ret(ret)
# Let's use the default environment
env = 'base'
with context.state_call_context(self.states[cdata['full']],
__env__=env):
ret = self.states[cdata['full']](*cdata['args'],
**cdata['kwargs'])
self.verify_ret(ret)
except Exception:
trb = traceback.format_exc()
ret = {

View File

@ -561,7 +561,6 @@ def script(name,
stateful=False,
umask=None,
timeout=None,
__env__='base',
**kwargs):
'''
Download a script from a remote source and execute it. The name can be the
@ -621,11 +620,6 @@ def script(name,
args
String of command line args to pass to the script. Only used if no
args are specified as part of the `name` argument.
__env__
The root directory of the environment for the referencing script. The
environments are defined in the master config file.
'''
ret = {'changes': {},
'comment': '',
@ -638,15 +632,15 @@ def script(name,
if isinstance(env, string_types):
msg = (
'Passing a salt environment should be done using \'__env__\' not '
'\'env\'. This warning will go away in Salt {version} and this '
'Passing a salt environment should be done using \'saltenv\' not '
'\'env\'. This warning will go away in Salt Helium and this '
'will be the default and expected behaviour. Please update your '
'state files.'
)
salt.utils.warn_until('Helium', msg)
ret.setdefault('warnings', []).append(msg)
# Backwards compatibility
__env__ = env
# No need to set __env__ = env since that's done in function
# globals injection machinery
if HAS_GRP:
pgid = os.getegid()

View File

@ -63,7 +63,8 @@ keyword will not modify it.
import os
# Import salt libs
from salt.utils import mkstemp, fopen
import salt._compat
import salt.utils
from salt.modules.cron import _needs_change
@ -311,8 +312,8 @@ def file(name,
mode = __salt__['config.manage_mode'](600)
owner, group, crontab_dir = _get_cron_info()
cron_path = mkstemp()
with fopen(cron_path, 'w+') as fp_:
cron_path = salt.utils.mkstemp()
with salt.utils.fopen(cron_path, 'w+') as fp_:
fp_.write(__salt__['cron.raw_cron'](user))
ret = {'changes': {},
@ -321,11 +322,19 @@ def file(name,
'result': True}
# Avoid variable naming confusion in below module calls, since ID
# delclaration for this state will be a source URI.
# declaration for this state will be a source URI.
source = name
if env is None:
env = kwargs.get('__env__', 'base')
if isinstance(env, salt._compat.string_types):
msg = (
'Passing a salt environment should be done using \'saltenv\' not '
'\'env\'. This warning will go away in Salt Helium and this '
'will be the default and expected behaviour. Please update your '
'state files.'
)
salt.utils.warn_until('Helium', msg)
ret.setdefault('warnings', []).append(msg)
# No need to set __env__ = env since that's done in the state machinery
if not replace and os.stat(cron_path).st_size > 0:
ret['comment'] = 'User {0} already has a crontab. No changes ' \
@ -344,7 +353,7 @@ def file(name,
False, # makedirs = False
context,
defaults,
env,
__env__,
**kwargs
)
ret['result'], ret['comment'] = fcm

View File

@ -640,7 +640,6 @@ def _get_template_texts(source_list=None,
template='jinja',
defaults=None,
context=None,
env='base',
**kwargs):
'''
Iterate a list of sources and process them as templates.
@ -665,7 +664,7 @@ def _get_template_texts(source_list=None,
if context:
tmpctx.update(context)
rndrd_templ_fn = __salt__['cp.get_template'](source, '',
template=template, env=env,
template=template, env=__env__,
context=tmpctx, **kwargs)
msg = 'cp.get_template returned {0} (Called with: {1})'
log.debug(msg.format(rndrd_templ_fn, source))
@ -1057,8 +1056,17 @@ def managed(name,
if not os.path.isabs(name):
return _error(
ret, 'Specified file {0} is not an absolute path'.format(name))
if env is None:
env = kwargs.get('__env__', 'base')
if isinstance(env, salt._compat.string_types):
msg = (
'Passing a salt environment should be done using \'saltenv\' not '
'\'env\'. This warning will go away in Salt Helium and this '
'will be the default and expected behaviour. Please update your '
'state files.'
)
salt.utils.warn_until('Helium', msg)
ret.setdefault('warnings', []).append(msg)
# No need to set __env__ = env since that's done in the state machinery
if os.path.isdir(name):
ret['comment'] = 'Specified target {0} is a directory'.format(name)
@ -1113,7 +1121,7 @@ def managed(name,
makedirs,
context,
defaults,
env,
__env__,
contents,
**kwargs
)
@ -1123,7 +1131,7 @@ def managed(name,
source, source_hash = __salt__['file.source_list'](
source,
source_hash,
env
__env__
)
# Gather the source file from the server
@ -1135,7 +1143,7 @@ def managed(name,
user,
group,
mode,
env,
__env__,
context,
defaults,
**kwargs
@ -1151,7 +1159,7 @@ def managed(name,
user,
group,
mode,
env,
__env__,
backup,
template,
show_diff,
@ -1513,15 +1521,24 @@ def recurse(name,
if not os.path.isabs(name):
return _error(
ret, 'Specified file {0} is not an absolute path'.format(name))
if env is None:
env = kwargs.get('__env__', 'base')
if isinstance(env, salt._compat.string_types):
msg = (
'Passing a salt environment should be done using \'saltenv\' not '
'\'env\'. This warning will go away in Salt Helium and this '
'will be the default and expected behaviour. Please update your '
'state files.'
)
salt.utils.warn_until('Helium', msg)
ret.setdefault('warnings', []).append(msg)
# No need to set __env__ = env since that's done in the state machinery
# Verify the source exists.
_src_proto, _src_path = source.split('://', 1)
if not _src_path:
pass
elif _src_path.strip('/') not in __salt__['cp.list_master_dirs'](env):
elif _src_path.strip('/') not in __salt__['cp.list_master_dirs'](__env__):
ret['result'] = False
ret['comment'] = (
'The source: {0} does not exist on the master'.format(source)
@ -1591,7 +1608,6 @@ def recurse(name,
context=context,
replace=True,
defaults=defaults,
env=env,
backup=backup,
**pass_kwargs)
merge_ret(path, _ret)
@ -1663,7 +1679,7 @@ def recurse(name,
keep.add(os.path.join(name, srelpath))
return filenames
# If source is a list, find which in the list actually exists
source, source_hash = __salt__['file.source_list'](source, '', env)
source, source_hash = __salt__['file.source_list'](source, '', __env__)
keep = set()
vdir = set()
@ -1672,11 +1688,11 @@ def recurse(name,
#we're searching for things that start with this *directory*.
# use '/' since #master only runs on POSIX
srcpath = srcpath + '/'
fns_ = __salt__['cp.list_master'](env, srcpath)
fns_ = __salt__['cp.list_master'](__env__, srcpath)
# If we are instructed to keep symlinks, then process them.
if keep_symlinks:
# Make this global so that emptydirs can use it if needed.
symlinks = __salt__['cp.list_master_symlinks'](env, srcpath)
symlinks = __salt__['cp.list_master_symlinks'](__env__, srcpath)
fns_ = process_symlinks(fns_, symlinks)
for fn_ in fns_:
if not fn_.strip():
@ -1718,7 +1734,7 @@ def recurse(name,
manage_file(dest, src)
if include_empty:
mdirs = __salt__['cp.list_master_dirs'](env, srcpath)
mdirs = __salt__['cp.list_master_dirs'](__env__, srcpath)
for mdir in mdirs:
if not _check_include_exclude(os.path.relpath(mdir, srcpath),
include_pat,
@ -1729,7 +1745,8 @@ def recurse(name,
if keep_symlinks:
for link in symlinks:
if mdir.startswith(link, 0):
log.debug('** skipping empty dir ** {0}, it intersects a symlink'.format(mdir))
log.debug('** skipping empty dir ** {0}, it intersects'
' a symlink'.format(mdir))
continue
manage_directory(mdest)
keep.add(mdest)
@ -2220,7 +2237,6 @@ def append(name,
makedirs=False,
source=None,
source_hash=None,
__env__='base',
template='jinja',
sources=None,
source_hashes=None,
@ -2302,8 +2318,7 @@ def append(name,
tmpret = _get_template_texts(source_list=sl_,
template=template,
defaults=defaults,
context=context,
env=__env__)
context=context)
if not tmpret['result']:
return tmpret
text = tmpret['data']
@ -2415,10 +2430,19 @@ def patch(name,
ret.update(result=True, comment='Patch is already applied')
return ret
if isinstance(env, salt._compat.string_types):
msg = (
'Passing a salt environment should be done using \'saltenv\' not '
'\'env\'. This warning will go away in Salt Helium and this '
'will be the default and expected behaviour. Please update your '
'state files.'
)
salt.utils.warn_until('Helium', msg)
ret.setdefault('warnings', []).append(msg)
# No need to set __env__ = env since that's done in the state machinery
# get cached file or copy it to cache
if env is None:
env = kwargs.get('__env__', 'base')
cached_source_path = __salt__['cp.cache_file'](source, env)
cached_source_path = __salt__['cp.cache_file'](source, __env__)
log.debug(
'State patch.applied cached source {0} -> {1}'.format(
source, cached_source_path
@ -2821,6 +2845,17 @@ def serialize(name,
'name': name,
'result': True}
if isinstance(env, salt._compat.string_types):
msg = (
'Passing a salt environment should be done using \'saltenv\' not '
'\'env\'. This warning will go away in Salt Helium and this '
'will be the default and expected behaviour. Please update your '
'state files.'
)
salt.utils.warn_until('Helium', msg)
ret.setdefault('warnings', []).append(msg)
# No need to set __env__ = env since that's done in the state machinery
if not create:
if not os.path.isfile(name):
# Don't create a file that is not already present
@ -2854,7 +2889,7 @@ def serialize(name,
user=user,
group=group,
mode=mode,
env=env,
env=__env__,
backup=backup,
template=None,
show_diff=show_diff,

View File

@ -112,8 +112,7 @@ def installed(name,
no_chown=False,
cwd=None,
activate=False,
pre_releases=False,
__env__='base'):
pre_releases=False):
'''
Make sure the package is installed
@ -336,7 +335,6 @@ def installed(name,
cwd=cwd,
activate=activate,
pre_releases=pre_releases,
__env__=__env__
)
if pip_install_call and (pip_install_call.get('retcode', 1) == 0):
@ -409,8 +407,7 @@ def removed(name,
timeout=None,
user=None,
runas=None,
cwd=None,
__env__='base'):
cwd=None):
'''
Make sure that a package is not installed.
@ -468,8 +465,7 @@ def removed(name,
proxy=proxy,
timeout=timeout,
user=user,
cwd=cwd,
__env__='base'):
cwd=cwd):
ret['result'] = True
ret['changes'][name] = 'Removed'
ret['comment'] = 'Package was successfully removed.'

View File

@ -54,7 +54,7 @@ import re
import sys
def _present_test(user, name, enc, comment, options, source, config, env):
def _present_test(user, name, enc, comment, options, source, config):
'''
Run checks for "present"
'''
@ -64,7 +64,7 @@ def _present_test(user, name, enc, comment, options, source, config, env):
user,
source,
config,
env)
__env__)
if keys:
comment = ''
for key, status in keys.items():
@ -168,7 +168,6 @@ def present(
options or [],
source,
config,
kwargs.get('__env__', 'base')
)
return ret
@ -176,8 +175,7 @@ def present(
data = __salt__['ssh.set_auth_key_from_file'](
user,
source,
config,
kwargs.get('__env__', 'base'))
config)
else:
# check if this is of form {options} {enc} {key} {comment}
sshre = re.compile(r'^(.*?)\s?((?:ssh\-|ecds)[\w-]+\s.+)$')

View File

@ -51,8 +51,10 @@ def __virtual__():
# Functions
def war_deployed(name, war, url='http://localhost:8080/manager',
__env__='base', timeout=180):
def war_deployed(name,
war,
url='http://localhost:8080/manager',
timeout=180):
'''
Enforce that the WAR will be deployed and started in the context path
it will make use of WAR versions
@ -137,8 +139,12 @@ def war_deployed(name, war, url='http://localhost:8080/manager',
return ret
# Deploy
deploy_res = __salt__['tomcat.deploy_war'](war, name, 'yes', url, __env__,
timeout)
deploy_res = __salt__['tomcat.deploy_war'](war,
name,
'yes',
url,
__env__,
timeout)
# Return
if deploy_res.startswith('OK'):

View File

@ -34,7 +34,6 @@ def managed(name,
extra_search_dir=None,
never_download=None,
prompt=None,
__env__='base',
user=None,
runas=None,
no_chown=False,
@ -181,7 +180,6 @@ def managed(name,
index_url=index_url,
extra_index_url=extra_index_url,
no_chown=no_chown,
__env__=__env__,
pre_releases=pre_releases
)
ret['result'] &= _ret['retcode'] == 0

52
salt/utils/context.py Normal file
View File

@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
:copyright: © 2013 by the SaltStack Team, see AUTHORS for more details.
:license: Apache 2.0, see LICENSE for more details.
salt.utils.context
~~~~~~~~~~~~~~~~~~
Context managers used throughout Salt's source code.
'''
# Import python libs
from contextlib import contextmanager
@contextmanager
def state_call_context(func, **overrides):
'''
Override specific variable within a state call context.
'''
# recognize methods
if hasattr(func, "im_func"):
func = func.im_func
# Get a reference to the function globals dictionary
func_globals = func.func_globals
# Save the current function globals dictionary state values for the
# overridden objects
injected_func_globals = []
overridden_func_globals = {}
for override in overrides:
if override in func_globals:
overridden_func_globals[override] = func_globals[override]
else:
injected_func_globals.append(override)
# Override the function globals with what's passed in the above overrides
func_globals.update(overrides)
# The context is now ready to be used
yield
# We're now done with the context
# Restore the overwritten function globals
func_globals.update(overridden_func_globals)
# Remove any entry injected in the function globals
for injected in injected_func_globals:
del func_globals[injected]

View File

@ -55,10 +55,11 @@ import yaml
SYS_TMP_DIR = os.environ.get('TMPDIR', tempfile.gettempdir())
TMP = os.path.join(SYS_TMP_DIR, 'salt-tests-tmpdir')
FILES = os.path.join(INTEGRATION_TEST_DIR, 'files')
PYEXEC = 'python{0}.{1}'.format(sys.version_info[0], sys.version_info[1])
PYEXEC = 'python{0}.{1}'.format(*sys.version_info)
MOCKBIN = os.path.join(INTEGRATION_TEST_DIR, 'mockbin')
SCRIPT_DIR = os.path.join(CODE_DIR, 'scripts')
TMP_STATE_TREE = os.path.join(SYS_TMP_DIR, 'salt-temp-state-tree')
TMP_PRODENV_STATE_TREE = os.path.join(SYS_TMP_DIR, 'salt-temp-prodenv-state-tree')
TMP_CONF_DIR = os.path.join(TMP, 'config')
log = logging.getLogger(__name__)
@ -165,6 +166,11 @@ class TestDaemon(object):
# Let's support runtime created files that can be used like:
# salt://my-temp-file.txt
TMP_STATE_TREE
],
# Alternate root to test __env__ choices
'prod': [
os.path.join(FILES, 'file', 'prod'),
TMP_PRODENV_STATE_TREE
]
}
self.master_opts['ext_pillar'].append(
@ -175,7 +181,11 @@ class TestDaemon(object):
)
)}
)
self.master_opts['extension_modules'] = os.path.join(INTEGRATION_TEST_DIR, 'files', 'extension_modules')
self.master_opts['extension_modules'] = os.path.join(
INTEGRATION_TEST_DIR, 'files', 'extension_modules'
)
# clean up the old files
self._clean()
@ -206,7 +216,8 @@ class TestDaemon(object):
self.sub_minion_opts['sock_dir'],
self.minion_opts['sock_dir'],
TMP_STATE_TREE,
TMP
TMP_PRODENV_STATE_TREE,
TMP,
],
running_tests_user)
@ -410,8 +421,10 @@ class TestDaemon(object):
shutil.rmtree(self.master_opts['root_dir'])
if os.path.isdir(self.smaster_opts['root_dir']):
shutil.rmtree(self.smaster_opts['root_dir'])
if os.path.isdir(TMP):
shutil.rmtree(TMP)
for dirname in (TMP, TMP_STATE_TREE, TMP_PRODENV_STATE_TREE):
if os.path.isdir(dirname):
shutil.rmtree(dirname)
def wait_for_jid(self, targets, jid, timeout=120):
time.sleep(1) # Allow some time for minions to accept jobs

View File

@ -1,4 +1,4 @@
/testfile:
{{ salt['runtests_helpers.get_sys_temp_dir_for_path']('testfile') }}:
file:
- managed
- source: salt://testfile

View File

@ -0,0 +1 @@
I could just fancy some cheese, Gromit. What do you say? Cheddar? Comte?

View File

@ -0,0 +1,58 @@
Scene 32
ARTHUR: Knights! Forward!
[boom boom boom boom BOOM boom boom boom boom]
What manner of man are you that can summon up fire without flint
or tinder?
TIM: I... am an enchanter.
ARTHUR: By what name are you known?
TIM: There are some who call me... Tim?
ARTHUR: Greetings, Tim the Enchanter.
TIM: Greetings, King Arthur!
ARTHUR: You know my name?
TIM: I do.
[zoosh]
You seek the Holy Grail!
ARTHUR: That is our quest. You know much that is hidden, O Tim.
TIM: Quite.
[pweeng boom]
[clap clap clap]
ARTHUR: Yes, we're, we're looking for the Grail. Our quest is to find
the Holy Grail.
KNIGHTS: It is, yes, yup, yes, yeah.
ARTHUR: And so we're, we're, we're, we're looking for it.
KNIGHTS: Yes we are we are.
BEDEMIR: We have been for some time.
ROBIN: Ages.
ARTHUR: Uh, so, uh, anything you can do to, uh, to help, would be...
very... helpful...
GALAHAD: Look, can you tell us wh-
[boom]
ARTHUR: Fine, um, I don't want to waste anymore of your time, but, uh
I don't suppose you could, uh, tell us where we might find a, um,
find a, uh, a, um, a uh--
TIM: A what...?
ARTHUR: A g--, a g--
TIM: A Grail?!
ARTHUR: Yes, I think so.
KNIGHTS: Yes, that's it. Yes.
TIM: Yes!
KNIGHTS: Oh, thank you, splendid, fine.
[boom pweeng boom boom]
ARTHUR: Look, you're a busy man, uh--
TIM: Yes, I can help you find the Holy Grail.
KNIGHTS: Oh, thank you.
TIM: To the north there lies a cave -- the cave of Kyre Banorg --
wherein, carved in mystic runes upon the very living rock, the last
words of Ulfin Bedweer of Regett [boom] proclaim the last resting
place of the most Holy Grail.
ARTHUR: Where could we find this cave, O Tim?
TIM: Follow! But! follow only if ye be men of valor, for the entrance
to this cave is guarded by a creature so foul, so cruel that no man
yet has fought with it and lived! Bones of four fifty men lie strewn
about its lair. So, brave knights, if you do doubt your courage or
your strength, come no further, for death awaits you all with nasty
big pointy teeth.
ARTHUR: What an eccentric performance.

View File

@ -0,0 +1,52 @@
Scene 34
KNIGHT: There! Look!
LAUNCELOT: What does it say?
GALAHAD: What language is that?
ARTHUR: Brother Maynard, you're our scholar!
MAYNARD: It's Aramaic!
GALAHAD: Of course! Joseph of Aramathea!
LAUNCELOT: Course!
KNIGHT: What does it say?
MAYNARD: It reads, 'Here may be found the last words of Joseph of
Aramathea. He who is valiant and pure of spirit may find the Holy Grail
in the Castle of uuggggggh'.
ARTHUR: What?
MAYNARD: '... the Castle of uuggggggh'.
BEDEMIR: What is that?
MAYNARD: He must have died while carving it.
LAUNCELOT: Oh, come on!
MAYNARD: Well, that's what it says.
ARTHUR: Look, if he was dying, he wouldn't bother to carve 'aaggggh'.
He'd just say it!
MAYNARD: Well, that's what's carved in the rock!
GALAHAD: Perhaps he was dictating.
ARTHUR: Oh, shut up. Well, does it say anything else?
MAYNARD: No. Just, 'uuggggggh'.
LAUNCELOT: Aauuggghhh.
KNIGHT: Aaauggh.
BEDEMIR: You don't suppose he meant the Camauuuugh?
KNIGHT: Where's that?
BEDEMIR: France, I think.
LAUNCELOT: Isn't there a Saint Aauuuves in Cornwall?
ARTHUR: No, that's Saint Ives.
LAUNCELOT: Oh, yes. Saint Iiiives.
SEVERAL: Iiiiives.
BEDEMIR: Oooohoohohooo!
LAUNCELOT: No, no, aauuuuugh, at the back of the throat. Aauuugh.
BEDEMIR: No, no, no, oooooooh, in surprise and alarm.
LAUNCELOT: Oh, you mean sort of a aaaagh!
BEDEMIR: Yes, but I-- Aaaaagh!
KNIGHT: Oooh!
KNIGHT: Oh, no!
[roar]
MAYNARD: It's the legendary Black Beast of aaauuugh!
ARTHUR: Run away!
ALL: Run away! Run away!
[roar]
NARRATOR: As the horrendous Black Beast lunged forward, escape
for Arthur and his knights seemed hopeless. When, suddenly, the
animator suffered a fatal heart attack. [ulk] The cartoon peril
was no more. The Quest for the Holy Grail could continue.

View File

@ -0,0 +1,3 @@
{{ salt['runtests_helpers.get_sys_temp_dir_for_path']('prod-cheese-file') }}:
file.managed:
- source: salt://cheese

View File

@ -0,0 +1,4 @@
prod:
'G@role:sub':
- match: compound
- issue-8196

View File

@ -277,6 +277,31 @@ class CPModuleTest(integration.ModuleCase):
hashlib.md5(fn_.read()).hexdigest()
)
def test_get_file_from_env_predifined(self):
'''
cp.get_file
'''
tgt = os.path.join(integration.TMP, 'cheese')
try:
self.run_function('cp.get_file', ['salt://cheese', tgt])
with salt.utils.fopen(tgt, 'r') as cheese:
data = cheese.read()
self.assertIn('Gromit', data)
self.assertNotIn('Comte', data)
finally:
os.unlink(tgt)
def test_get_file_from_env_in_url(self):
tgt = os.path.join(integration.TMP, 'cheese')
try:
self.run_function('cp.get_file', ['salt://cheese?env=prod', tgt])
with salt.utils.fopen(tgt, 'r') as cheese:
data = cheese.read()
self.assertIn('Gromit', data)
self.assertIn('Comte', data)
finally:
os.unlink(tgt)
if __name__ == '__main__':
from integration import run_tests

View File

@ -24,9 +24,10 @@ class StateModuleTest(integration.ModuleCase,
state.show_highstate
'''
high = self.run_function('state.show_highstate')
destpath = os.path.join(integration.SYS_TMP_DIR, 'testfile')
self.assertTrue(isinstance(high, dict))
self.assertTrue('/testfile' in high)
self.assertEqual(high['/testfile']['__env__'], 'base')
self.assertTrue(destpath in high)
self.assertEqual(high[destpath]['__env__'], 'base')
def test_show_lowstate(self):
'''
@ -362,6 +363,21 @@ fi
'The state "C" in sls syntax.badlist2 is not formed as a list'
])
def test_get_file_from_env_in_top_match(self):
tgt = os.path.join(integration.SYS_TMP_DIR, 'prod-cheese-file')
try:
ret = self.run_function(
'state.highstate', minion_tgt='sub_minion'
)
self.assertSaltTrueReturn(ret)
self.assertTrue(os.path.isfile(tgt))
with salt.utils.fopen(tgt, 'r') as cheese:
data = cheese.read()
self.assertIn('Gromit', data)
self.assertIn('Comte', data)
finally:
os.unlink(tgt)
if __name__ == '__main__':
from integration import run_tests

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
'''
Tests for the salt-run command
'''

View File

@ -267,6 +267,22 @@ class FileTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
if os.path.isdir(name):
shutil.rmtree(name, ignore_errors=True)
def test_recurse_specific_env(self):
'''
file.recurse passing __env__
'''
name = os.path.join(integration.TMP, 'recurse_dir_prod_env')
ret = self.run_state('file.recurse',
name=name,
source='salt://holy',
__env__='prod')
try:
self.assertSaltTrueReturn(ret)
self.assertTrue(os.path.isfile(os.path.join(name, '32', 'scene')))
finally:
if os.path.isdir(name):
shutil.rmtree(name, ignore_errors=True)
def test_test_recurse(self):
'''
file.recurse test interface
@ -279,6 +295,21 @@ class FileTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
self.assertFalse(os.path.isfile(os.path.join(name, '36', 'scene')))
self.assertFalse(os.path.exists(name))
def test_test_recurse_specific_env(self):
'''
file.recurse test interface
'''
name = os.path.join(integration.TMP, 'recurse_test_dir_prod_env')
ret = self.run_state('file.recurse',
test=True,
name=name,
source='salt://holy',
__env__='prod'
)
self.assertSaltNoneReturn(ret)
self.assertFalse(os.path.isfile(os.path.join(name, '32', 'scene')))
self.assertFalse(os.path.exists(name))
def test_recurse_template(self):
'''
file.recurse with jinja template enabled
@ -320,6 +351,33 @@ class FileTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
finally:
shutil.rmtree(name, ignore_errors=True)
def test_recurse_clean_specific_env(self):
'''
file.recurse with clean=True and __env__=prod
'''
name = os.path.join(integration.TMP, 'recurse_clean_dir_prod_env')
if not os.path.isdir(name):
os.makedirs(name)
strayfile = os.path.join(name, 'strayfile')
salt.utils.fopen(strayfile, 'w').close()
# Corner cases: replacing file with a directory and vice versa
salt.utils.fopen(os.path.join(name, '32'), 'w').close()
os.makedirs(os.path.join(name, 'scene34'))
ret = self.run_state('file.recurse',
name=name,
source='salt://holy',
clean=True,
__env__='prod')
try:
self.assertSaltTrueReturn(ret)
self.assertFalse(os.path.exists(strayfile))
self.assertTrue(os.path.isfile(os.path.join(name, '32', 'scene')))
self.assertTrue(os.path.isfile(os.path.join(name, 'scene34')))
finally:
shutil.rmtree(name, ignore_errors=True)
def test_replace(self):
'''
file.replace

View File

@ -26,6 +26,7 @@ ensure_in_syspath('../../')
# Import salt libs
import integration
import salt.utils
class PipStateTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
@ -192,7 +193,7 @@ class PipStateTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
if venv_create['retcode'] > 0:
self.skipTest(
'Failed to create testcase virtual environment: {0}'.format(
ret
venv_create
)
)
@ -228,8 +229,8 @@ class PipStateTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
req_filename = os.path.join(
integration.TMP_STATE_TREE, 'issue-6912-requirements.txt'
)
with open(req_filename, 'wb') as f:
f.write('pep8')
with salt.utils.fopen(req_filename, 'wb') as reqf:
reqf.write('pep8')
try:
ret = self.run_state(
@ -295,8 +296,8 @@ class PipStateTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
req_filename = os.path.join(
integration.TMP_STATE_TREE, 'issue-6912-requirements.txt'
)
with open(req_filename, 'wb') as f:
f.write('pep8')
with salt.utils.fopen(req_filename, 'wb') as reqf:
reqf.write('pep8')
try:
ret = self.run_state(
@ -381,6 +382,60 @@ class PipStateTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
if os.path.isdir(venv_dir):
shutil.rmtree(venv_dir)
def test_pip_installed_specific_env(self):
# Create the testing virtualenv
venv_dir = os.path.join(
integration.TMP, 'pip-installed-specific-env'
)
# Let's write a requirements file
requirements_file = os.path.join(
integration.TMP_PRODENV_STATE_TREE, 'prod-env-requirements.txt'
)
with salt.utils.fopen(requirements_file, 'wb') as reqf:
reqf.write('pep8\n')
try:
ret = self.run_function('virtualenv.create', [venv_dir])
# The requirements file should not be found the base environment
ret = self.run_state(
'pip.installed', name='', bin_env=venv_dir,
requirements='salt://prod-env-requirements.txt'
)
self.assertSaltFalseReturn(ret)
self.assertInSaltComment(
"'salt://prod-env-requirements.txt' not found", ret
)
# The requirements file must be found in the prod environment
ret = self.run_state(
'pip.installed', name='', bin_env=venv_dir, __env__='prod',
requirements='salt://prod-env-requirements.txt'
)
self.assertSaltTrueReturn(ret)
self.assertInSaltComment(
'Successfully processed requirements file '
'salt://prod-env-requirements.txt', ret
)
# We're using the base environment but we're passing the prod
# environment as an url arg to salt://
ret = self.run_state(
'pip.installed', name='', bin_env=venv_dir,
requirements='salt://prod-env-requirements.txt?env=prod'
)
self.assertSaltTrueReturn(ret)
self.assertInSaltComment(
'Successfully processed requirements file '
'salt://prod-env-requirements.txt', ret
)
finally:
if os.path.isdir(venv_dir):
shutil.rmtree(venv_dir)
if os.path.isfile(requirements_file):
os.unlink(requirements_file)
if __name__ == '__main__':
from integration import run_tests

View File

@ -14,6 +14,7 @@ import yaml
# Import salt libs
import salt.states.file as filestate
filestate.__env__ = 'base'
filestate.__salt__ = {'file.manage_file': False}
filestate.__opts__ = {'test': False}

View File

@ -26,6 +26,7 @@ from salt.exceptions import CommandExecutionError
# Import 3rd-party libs
import pip
pip_state.__env__ = 'base'
pip_state.__opts__ = {'test': False}
pip_state.__salt__ = {'cmd.which_bin': lambda _: 'pip'}