mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 08:58:59 +00:00
Merge remote-tracking branch 'upstream/2014.7' into merge-forward-2015.2
Conflicts: doc/conf.py doc/man/salt-api.1 doc/man/salt-call.1 doc/man/salt-cloud.1 doc/man/salt-cp.1 doc/man/salt-key.1 doc/man/salt-master.1 doc/man/salt-minion.1 doc/man/salt-run.1 doc/man/salt-ssh.1 doc/man/salt-syndic.1 doc/man/salt-unity.1 doc/man/salt.1 doc/man/salt.7 salt/cloud/clouds/linode.py salt/states/composer.py salt/states/win_update.py
This commit is contained in:
commit
ebe7eeafd9
@ -151,7 +151,7 @@ copyright = '2015 SaltStack, Inc.'
|
||||
|
||||
version = salt.version.__version__
|
||||
#release = '.'.join(map(str, salt.version.__version_info__))
|
||||
release = '2015.2'
|
||||
release = '2014.7.2'
|
||||
|
||||
needs_sphinx = '1.3'
|
||||
|
||||
|
@ -1885,7 +1885,7 @@ strategy between different sources. It accepts 3 values:
|
||||
|
||||
* aggregate:
|
||||
|
||||
instructs aggregation of elements between sources that use the #!yamlex rendered.
|
||||
instructs aggregation of elements between sources that use the #!yamlex renderer.
|
||||
|
||||
For example, these two documents:
|
||||
|
||||
|
@ -6,8 +6,28 @@ Linode is a public cloud provider with a focus on Linux instances.
|
||||
|
||||
Dependencies
|
||||
============
|
||||
* linode-python >= 1.1
|
||||
|
||||
OR
|
||||
|
||||
* Libcloud >= 0.13.2
|
||||
|
||||
This driver supports accessing Linode via linode-python or Apache Libcloud.
|
||||
Linode-python is recommended, it is more full-featured than Libcloud. In
|
||||
particular using linode-python enables stopping, starting, and cloning
|
||||
machines.
|
||||
|
||||
Driver selection is automatic. If linode-python is present it will be used.
|
||||
If it is absent, salt-cloud will fall back to Libcloud. If neither are present
|
||||
salt-cloud will abort.
|
||||
|
||||
NOTE: linode-python 1.1 or later is recommended. As of this publication it is
|
||||
not yet on PyPi. Earlier versions of linode-python should work but can leak
|
||||
sensitive information into the debug logs.
|
||||
|
||||
Linode-python can be downloaded from
|
||||
https://github.com/tjfontaine/linode-python.
|
||||
|
||||
Configuration
|
||||
=============
|
||||
Linode requires a single API key, but the default root password for new
|
||||
@ -100,3 +120,34 @@ command:
|
||||
uuid:
|
||||
8457f92eaffc92b7666b6734a96ad7abe1a8a6dd
|
||||
...SNIP...
|
||||
|
||||
|
||||
Cloning
|
||||
=======
|
||||
|
||||
When salt-cloud accesses Linode via linode-python it can clone machines.
|
||||
|
||||
It is safest to clone a stopped machine. To stop a machine run
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-cloud -a stop machine_to_clone
|
||||
|
||||
To create a new machine based on another machine, add an entry to your linode
|
||||
cloud profile that looks like this:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
li-clone:
|
||||
provider: linode
|
||||
clonefrom: machine_to_clone
|
||||
script_args: -C
|
||||
|
||||
Then run salt-cloud as normal, specifying `-p li-clone`. The profile name can
|
||||
be anything--it doesn't have to be `li-clone`.
|
||||
|
||||
`Clonefrom:` is the name of an existing machine in Linode from which to clone.
|
||||
`Script_args: -C` is necessary to avoid re-deploying Salt via salt-bootstrap.
|
||||
`-C` will just re-deploy keys so the new minion will not have a duplicate key
|
||||
or minion_id on the master.
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,10 +6,11 @@ from __future__ import absolute_import
|
||||
|
||||
# Import python libs
|
||||
import logging
|
||||
import os.path
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
from salt.exceptions import CommandExecutionError
|
||||
from salt.exceptions import CommandExecutionError, CommandNotFoundError, SaltInvocationError
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -35,6 +36,162 @@ def _valid_composer(composer):
|
||||
return False
|
||||
|
||||
|
||||
def did_composer_install(dir):
|
||||
'''
|
||||
Test to see if the vendor directory exists in this directory
|
||||
|
||||
dir
|
||||
Directory location of the composer.json file
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' composer.did_composer_install /var/www/application
|
||||
'''
|
||||
lockFile = "{0}/vendor".format(dir)
|
||||
if os.path.exists(lockFile):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _run_composer(action,
|
||||
dir=None,
|
||||
composer=None,
|
||||
php=None,
|
||||
runas=None,
|
||||
prefer_source=None,
|
||||
prefer_dist=None,
|
||||
no_scripts=None,
|
||||
no_plugins=None,
|
||||
optimize=None,
|
||||
no_dev=None,
|
||||
quiet=False,
|
||||
composer_home='/root',
|
||||
extra_flags=None):
|
||||
'''
|
||||
Run PHP's composer with a specific action.
|
||||
|
||||
If composer has not been installed globally making it available in the
|
||||
system PATH & making it executable, the ``composer`` and ``php`` parameters
|
||||
will need to be set to the location of the executables.
|
||||
|
||||
action
|
||||
The action to pass to composer ('install', 'update', 'selfupdate', etc).
|
||||
|
||||
dir
|
||||
Directory location of the composer.json file. Required except when
|
||||
action='selfupdate'
|
||||
|
||||
composer
|
||||
Location of the composer.phar file. If not set composer will
|
||||
just execute "composer" as if it is installed globally.
|
||||
(i.e. /path/to/composer.phar)
|
||||
|
||||
php
|
||||
Location of the php executable to use with composer.
|
||||
(i.e. /usr/bin/php)
|
||||
|
||||
runas
|
||||
Which system user to run composer as.
|
||||
|
||||
prefer_source
|
||||
--prefer-source option of composer.
|
||||
|
||||
prefer_dist
|
||||
--prefer-dist option of composer.
|
||||
|
||||
no_scripts
|
||||
--no-scripts option of composer.
|
||||
|
||||
no_plugins
|
||||
--no-plugins option of composer.
|
||||
|
||||
optimize
|
||||
--optimize-autoloader option of composer. Recommended for production.
|
||||
|
||||
no_dev
|
||||
--no-dev option for composer. Recommended for production.
|
||||
|
||||
quiet
|
||||
--quiet option for composer. Whether or not to return output from composer.
|
||||
|
||||
composer_home
|
||||
$COMPOSER_HOME environment variable
|
||||
|
||||
extra_flags
|
||||
None, or a string containing extra flags to pass to composer.
|
||||
'''
|
||||
if composer is not None:
|
||||
if php is None:
|
||||
php = 'php'
|
||||
else:
|
||||
composer = 'composer'
|
||||
|
||||
# Validate Composer is there
|
||||
if not _valid_composer(composer):
|
||||
raise CommandNotFoundError('\'composer.{0}\' is not available. Couldn\'t find {1!r}.'
|
||||
.format(action, composer))
|
||||
|
||||
# Don't need a dir for the 'selfupdate' action; all other actions do need a dir
|
||||
if dir is None and action != 'selfupdate':
|
||||
raise SaltInvocationError('{0!r} is required for \'composer.{1}\''
|
||||
.format('dir', action))
|
||||
|
||||
if action is None:
|
||||
raise SaltInvocationError('{0!r} is required for {1!r}'
|
||||
.format('action', 'composer._run_composer'))
|
||||
|
||||
# Base Settings
|
||||
cmd = '{0} {1} {2}'.format(composer, action, '--no-interaction --no-ansi')
|
||||
|
||||
if extra_flags is not None:
|
||||
cmd = '{0} {1}'.format(cmd, extra_flags)
|
||||
|
||||
# If php is set, prepend it
|
||||
if php is not None:
|
||||
cmd = php + ' ' + cmd
|
||||
|
||||
# Add Working Dir
|
||||
if dir is not None:
|
||||
cmd += ' --working-dir=' + dir
|
||||
|
||||
# Other Settings
|
||||
if quiet is True:
|
||||
cmd += ' --quiet'
|
||||
|
||||
if no_dev is True:
|
||||
cmd += ' --no-dev'
|
||||
|
||||
if prefer_source is True:
|
||||
cmd += ' --prefer-source'
|
||||
|
||||
if prefer_dist is True:
|
||||
cmd += ' --prefer-dist'
|
||||
|
||||
if no_scripts is True:
|
||||
cmd += ' --no-scripts'
|
||||
|
||||
if no_plugins is True:
|
||||
cmd += ' --no-plugins'
|
||||
|
||||
if optimize is True:
|
||||
cmd += ' --optimize-autoloader'
|
||||
|
||||
result = __salt__['cmd.run_all'](cmd,
|
||||
runas=runas,
|
||||
env={'COMPOSER_HOME': composer_home},
|
||||
python_shell=False)
|
||||
|
||||
if result['retcode'] != 0:
|
||||
raise CommandExecutionError(result['stderr'])
|
||||
|
||||
if quiet is True:
|
||||
return True
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def install(dir,
|
||||
composer=None,
|
||||
php=None,
|
||||
@ -102,60 +259,150 @@ def install(dir,
|
||||
salt '*' composer.install /var/www/application \
|
||||
no_dev=True optimize=True
|
||||
'''
|
||||
if composer is not None:
|
||||
if php is None:
|
||||
php = 'php'
|
||||
else:
|
||||
composer = 'composer'
|
||||
|
||||
# Validate Composer is there
|
||||
if not _valid_composer(composer):
|
||||
return '{0!r} is not available. Couldn\'t find {1!r}.'.format('composer.install', composer)
|
||||
|
||||
if dir is None:
|
||||
return '{0!r} is required for {1!r}'.format('dir', 'composer.install')
|
||||
|
||||
# Base Settings
|
||||
cmd = composer + ' install --no-interaction'
|
||||
|
||||
# If php is set, prepend it
|
||||
if php is not None:
|
||||
cmd = php + ' ' + cmd
|
||||
|
||||
# Add Working Dir
|
||||
cmd += ' --working-dir=' + dir
|
||||
|
||||
# Other Settings
|
||||
if quiet is True:
|
||||
cmd += ' --quiet'
|
||||
|
||||
if no_dev is True:
|
||||
cmd += ' --no-dev'
|
||||
|
||||
if prefer_source is True:
|
||||
cmd += ' --prefer-source'
|
||||
|
||||
if prefer_dist is True:
|
||||
cmd += ' --prefer-dist'
|
||||
|
||||
if no_scripts is True:
|
||||
cmd += ' --no-scripts'
|
||||
|
||||
if no_plugins is True:
|
||||
cmd += ' --no-plugins'
|
||||
|
||||
if optimize is True:
|
||||
cmd += ' --optimize-autoloader'
|
||||
|
||||
result = __salt__['cmd.run_all'](cmd,
|
||||
result = _run_composer('install',
|
||||
dir=dir,
|
||||
composer=composer,
|
||||
php=php,
|
||||
runas=runas,
|
||||
env={'COMPOSER_HOME': composer_home},
|
||||
python_shell=False)
|
||||
prefer_source=prefer_source,
|
||||
prefer_dist=prefer_dist,
|
||||
no_scripts=no_scripts,
|
||||
no_plugins=no_plugins,
|
||||
optimize=optimize,
|
||||
no_dev=no_dev,
|
||||
quiet=quiet,
|
||||
composer_home=composer_home)
|
||||
return result
|
||||
|
||||
if result['retcode'] != 0:
|
||||
raise CommandExecutionError(result['stderr'])
|
||||
|
||||
if quiet is True:
|
||||
return True
|
||||
def update(dir,
|
||||
composer=None,
|
||||
php=None,
|
||||
runas=None,
|
||||
prefer_source=None,
|
||||
prefer_dist=None,
|
||||
no_scripts=None,
|
||||
no_plugins=None,
|
||||
optimize=None,
|
||||
no_dev=None,
|
||||
quiet=False,
|
||||
composer_home='/root'):
|
||||
'''
|
||||
Update composer dependencies for a directory.
|
||||
|
||||
return result['stdout']
|
||||
If `composer install` has not yet been run, this runs `composer install`
|
||||
instead.
|
||||
|
||||
If composer has not been installed globally making it available in the
|
||||
system PATH & making it executable, the ``composer`` and ``php`` parameters
|
||||
will need to be set to the location of the executables.
|
||||
|
||||
dir
|
||||
Directory location of the composer.json file.
|
||||
|
||||
composer
|
||||
Location of the composer.phar file. If not set composer will
|
||||
just execute "composer" as if it is installed globally.
|
||||
(i.e. /path/to/composer.phar)
|
||||
|
||||
php
|
||||
Location of the php executable to use with composer.
|
||||
(i.e. /usr/bin/php)
|
||||
|
||||
runas
|
||||
Which system user to run composer as.
|
||||
|
||||
prefer_source
|
||||
--prefer-source option of composer.
|
||||
|
||||
prefer_dist
|
||||
--prefer-dist option of composer.
|
||||
|
||||
no_scripts
|
||||
--no-scripts option of composer.
|
||||
|
||||
no_plugins
|
||||
--no-plugins option of composer.
|
||||
|
||||
optimize
|
||||
--optimize-autoloader option of composer. Recommended for production.
|
||||
|
||||
no_dev
|
||||
--no-dev option for composer. Recommended for production.
|
||||
|
||||
quiet
|
||||
--quiet option for composer. Whether or not to return output from composer.
|
||||
|
||||
composer_home
|
||||
$COMPOSER_HOME environment variable
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' composer.update /var/www/application
|
||||
|
||||
salt '*' composer.update /var/www/application \
|
||||
no_dev=True optimize=True
|
||||
'''
|
||||
result = _run_composer('update',
|
||||
extra_flags='--no-progress',
|
||||
dir=dir,
|
||||
composer=composer,
|
||||
php=php,
|
||||
runas=runas,
|
||||
prefer_source=prefer_source,
|
||||
prefer_dist=prefer_dist,
|
||||
no_scripts=no_scripts,
|
||||
no_plugins=no_plugins,
|
||||
optimize=optimize,
|
||||
no_dev=no_dev,
|
||||
quiet=quiet,
|
||||
composer_home=composer_home)
|
||||
return result
|
||||
|
||||
|
||||
def selfupdate(composer=None,
|
||||
php=None,
|
||||
runas=None,
|
||||
quiet=False,
|
||||
composer_home='/root'):
|
||||
'''
|
||||
Update composer itself.
|
||||
|
||||
If composer has not been installed globally making it available in the
|
||||
system PATH & making it executable, the ``composer`` and ``php`` parameters
|
||||
will need to be set to the location of the executables.
|
||||
|
||||
composer
|
||||
Location of the composer.phar file. If not set composer will
|
||||
just execute "composer" as if it is installed globally.
|
||||
(i.e. /path/to/composer.phar)
|
||||
|
||||
php
|
||||
Location of the php executable to use with composer.
|
||||
(i.e. /usr/bin/php)
|
||||
|
||||
runas
|
||||
Which system user to run composer as.
|
||||
|
||||
quiet
|
||||
--quiet option for composer. Whether or not to return output from composer.
|
||||
|
||||
composer_home
|
||||
$COMPOSER_HOME environment variable
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' composer.selfupdate
|
||||
'''
|
||||
result = _run_composer('selfupdate',
|
||||
extra_flags='--no-progress',
|
||||
composer=composer,
|
||||
php=php,
|
||||
runas=runas,
|
||||
quiet=quiet,
|
||||
composer_home=composer_home)
|
||||
return result
|
||||
|
@ -303,7 +303,7 @@ def disable(name, **kwargs):
|
||||
|
||||
salt '*' service.disable <service name>
|
||||
'''
|
||||
cmd = ['sc', 'config', name, 'start=', 'demand']
|
||||
cmd = ['sc', 'config', name, 'start=', 'disabled']
|
||||
return not __salt__['cmd.retcode'](cmd, python_shell=False)
|
||||
|
||||
|
||||
|
@ -2804,7 +2804,7 @@ class BaseHighState(object):
|
||||
if state:
|
||||
self.merge_included_states(highstate, state, errors)
|
||||
for i, error in enumerate(errors[:]):
|
||||
if 'is not available on the salt master' in error:
|
||||
if 'is not available' in error:
|
||||
# match SLS foobar in environment
|
||||
this_sls = 'SLS {0} in saltenv'.format(
|
||||
sls_match)
|
||||
|
@ -40,7 +40,7 @@ the location of composer in the state.
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import salt libs
|
||||
from salt.exceptions import CommandExecutionError, CommandNotFoundError
|
||||
from salt.exceptions import SaltException
|
||||
|
||||
|
||||
def __virtual__():
|
||||
@ -60,10 +60,138 @@ def installed(name,
|
||||
no_plugins=None,
|
||||
optimize=None,
|
||||
no_dev=None,
|
||||
quiet=False,
|
||||
composer_home='/root',
|
||||
always_check=True):
|
||||
'''
|
||||
Verify that the correct versions of composer dependencies are present.
|
||||
|
||||
dir
|
||||
Directory location of the composer.json file.
|
||||
|
||||
composer
|
||||
Location of the composer.phar file. If not set composer will
|
||||
just execute "composer" as if it is installed globally.
|
||||
(i.e. /path/to/composer.phar)
|
||||
|
||||
php
|
||||
Location of the php executable to use with composer.
|
||||
(i.e. /usr/bin/php)
|
||||
|
||||
user
|
||||
Which system user to run composer as.
|
||||
|
||||
.. versionadded:: 2014.1.4
|
||||
|
||||
prefer_source
|
||||
--prefer-source option of composer.
|
||||
|
||||
prefer_dist
|
||||
--prefer-dist option of composer.
|
||||
|
||||
no_scripts
|
||||
--no-scripts option of composer.
|
||||
|
||||
no_plugins
|
||||
--no-plugins option of composer.
|
||||
|
||||
optimize
|
||||
--optimize-autoloader option of composer. Recommended for production.
|
||||
|
||||
no_dev
|
||||
--no-dev option for composer. Recommended for production.
|
||||
|
||||
quiet
|
||||
--quiet option for composer. Whether or not to return output from composer.
|
||||
|
||||
composer_home
|
||||
$COMPOSER_HOME environment variable
|
||||
|
||||
always_check
|
||||
If True, _always_ run `composer install` in the directory. This is the
|
||||
default behavior. If False, only run `composer install` if there is no
|
||||
vendor directory present.
|
||||
'''
|
||||
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
|
||||
|
||||
did_install = __salt__['composer.did_composer_install'](name)
|
||||
|
||||
# Check if composer.lock exists, if so we already ran `composer install`
|
||||
# and we don't need to do it again
|
||||
if always_check is False and did_install:
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'Composer already installed this directory'
|
||||
return ret
|
||||
|
||||
# The state of the system does need to be changed. Check if we're running
|
||||
# in ``test=true`` mode.
|
||||
if __opts__['test'] is True:
|
||||
|
||||
if did_install is True:
|
||||
install_status = ""
|
||||
else:
|
||||
install_status = "not "
|
||||
|
||||
ret['comment'] = 'The state of "{0}" will be changed.'.format(name)
|
||||
ret['changes'] = {
|
||||
'old': 'composer install has {0}been run in {1}'.format(install_status, name),
|
||||
'new': 'composer install will be run in {0}'.format(name)
|
||||
}
|
||||
ret['result'] = None
|
||||
return ret
|
||||
|
||||
try:
|
||||
call = __salt__['composer.install'](
|
||||
name,
|
||||
composer=composer,
|
||||
php=php,
|
||||
runas=user,
|
||||
prefer_source=prefer_source,
|
||||
prefer_dist=prefer_dist,
|
||||
no_scripts=no_scripts,
|
||||
no_plugins=no_plugins,
|
||||
optimize=optimize,
|
||||
no_dev=no_dev,
|
||||
quiet=quiet,
|
||||
composer_home=composer_home
|
||||
)
|
||||
except (SaltException) as err:
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Error executing composer in \'{0!r}\': {1!r}'.format(name, err)
|
||||
return ret
|
||||
|
||||
# If composer retcode != 0 then an exception was thrown and we dealt with it.
|
||||
# Any other case is success, regardless of what composer decides to output.
|
||||
|
||||
ret['result'] = True
|
||||
|
||||
if quiet is True:
|
||||
ret['comment'] = 'Composer install completed successfully, output silenced by quiet flag'
|
||||
else:
|
||||
ret['comment'] = 'Composer install completed successfully'
|
||||
ret['changes'] = {
|
||||
'stderr': call['stderr'],
|
||||
'stdout': call['stdout']
|
||||
}
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def update(name,
|
||||
composer=None,
|
||||
php=None,
|
||||
user=None,
|
||||
prefer_source=None,
|
||||
prefer_dist=None,
|
||||
no_scripts=None,
|
||||
no_plugins=None,
|
||||
optimize=None,
|
||||
no_dev=None,
|
||||
quiet=False,
|
||||
composer_home='/root'):
|
||||
'''
|
||||
Verify that composer has installed the latest packages give a
|
||||
``composer.json`` and ``composer.lock`` file in a directory.
|
||||
Composer update the directory to ensure we have the latest versions
|
||||
of all project dependencies.
|
||||
|
||||
dir
|
||||
Directory location of the composer.json file.
|
||||
@ -108,8 +236,26 @@ def installed(name,
|
||||
'''
|
||||
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
|
||||
|
||||
# Check if composer.lock exists, if so we already ran `composer install`
|
||||
is_installed = __salt__['composer.did_composer_install'](name)
|
||||
if is_installed:
|
||||
old_status = "composer install has not yet been run in {0}".format(name)
|
||||
else:
|
||||
old_status = "composer install has been run in {0}".format(name)
|
||||
|
||||
# The state of the system does need to be changed. Check if we're running
|
||||
# in ``test=true`` mode.
|
||||
if __opts__['test'] is True:
|
||||
ret['comment'] = 'The state of "{0}" will be changed.'.format(name)
|
||||
ret['changes'] = {
|
||||
'old': old_status,
|
||||
'new': 'composer install/update will be run in {0}'.format(name)
|
||||
}
|
||||
ret['result'] = None
|
||||
return ret
|
||||
|
||||
try:
|
||||
call = __salt__['composer.install'](
|
||||
call = __salt__['composer.update'](
|
||||
name,
|
||||
composer=composer,
|
||||
php=php,
|
||||
@ -120,22 +266,26 @@ def installed(name,
|
||||
no_plugins=no_plugins,
|
||||
optimize=optimize,
|
||||
no_dev=no_dev,
|
||||
quiet=False,
|
||||
quiet=quiet,
|
||||
composer_home=composer_home
|
||||
)
|
||||
except (CommandNotFoundError, CommandExecutionError) as err:
|
||||
except (SaltException) as err:
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Error executing composer in \'{0!r}\': {1!r}'.format(name, err)
|
||||
return ret
|
||||
|
||||
if call or isinstance(call, list) or isinstance(call, dict):
|
||||
ret['result'] = True
|
||||
if call.find('Nothing to install or update') < 0:
|
||||
ret['changes']['stdout'] = call
|
||||
# If composer retcode != 0 then an exception was thrown and we dealt with it.
|
||||
# Any other case is success, regardless of what composer decides to output.
|
||||
|
||||
ret['comment'] = 'Composer ran, nothing changed in {0!r}'.format(name)
|
||||
ret['result'] = True
|
||||
|
||||
if quiet is True:
|
||||
ret['comment'] = 'Composer update completed successfully, output silenced by quiet flag'
|
||||
else:
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Could not run composer'
|
||||
ret['comment'] = 'Composer update completed successfully'
|
||||
ret['changes'] = {
|
||||
'stderr': call['stderr'],
|
||||
'stdout': call['stdout']
|
||||
}
|
||||
|
||||
return ret
|
||||
|
@ -45,7 +45,7 @@ The following example installs all driver updates that don't require a reboot:
|
||||
.. code-block:: yaml
|
||||
|
||||
gryffindor:
|
||||
win_update.install:
|
||||
win_update.installed:
|
||||
- includes:
|
||||
- driver: True
|
||||
- software: False
|
||||
|
@ -221,7 +221,7 @@ def query(key, keyid, method='GET', params=None, headers=None,
|
||||
if return_url is True:
|
||||
return ret, requesturl
|
||||
else:
|
||||
if method == 'GET' or method == 'HEAD':
|
||||
if result.status_code != requests.codes.ok:
|
||||
return
|
||||
ret = {'headers': []}
|
||||
for header in result.headers:
|
||||
|
@ -11,6 +11,7 @@ import os
|
||||
import re
|
||||
import sys
|
||||
import stat
|
||||
import errno
|
||||
import socket
|
||||
import logging
|
||||
|
||||
@ -162,8 +163,11 @@ def verify_files(files, user):
|
||||
for fn_ in files:
|
||||
dirname = os.path.dirname(fn_)
|
||||
try:
|
||||
if not os.path.isdir(dirname):
|
||||
try:
|
||||
os.makedirs(dirname)
|
||||
except OSError as err:
|
||||
if err.errno != errno.EEXIST:
|
||||
raise
|
||||
if not os.path.isfile(fn_):
|
||||
with salt.utils.fopen(fn_, 'w+') as fp_:
|
||||
fp_.write('')
|
||||
|
172
tests/unit/modules/composer_test.py
Normal file
172
tests/unit/modules/composer_test.py
Normal file
@ -0,0 +1,172 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
:codeauthor: :email:`Rupesh Tare <rupesht@saltstack.com>`
|
||||
'''
|
||||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from salttesting import TestCase, skipIf
|
||||
from salttesting.mock import (
|
||||
MagicMock,
|
||||
patch,
|
||||
NO_MOCK,
|
||||
NO_MOCK_REASON
|
||||
)
|
||||
|
||||
# Import Salt Libs
|
||||
from salt.modules import composer
|
||||
from salt.exceptions import CommandExecutionError, CommandNotFoundError, SaltInvocationError
|
||||
|
||||
|
||||
# Globals
|
||||
composer.__grains__ = {}
|
||||
composer.__salt__ = {}
|
||||
composer.__context__ = {}
|
||||
composer.__opts__ = {}
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class ComposerTestCase(TestCase):
|
||||
'''
|
||||
Test cases for salt.modules.composer
|
||||
'''
|
||||
def test_install(self):
|
||||
'''
|
||||
Test for Install composer dependencies for a directory.
|
||||
'''
|
||||
|
||||
# Test _valid_composer=False throws exception
|
||||
mock = MagicMock(return_value=False)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
self.assertRaises(CommandNotFoundError, composer.install, 'd')
|
||||
|
||||
# Test no directory specified throws exception
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
self.assertRaises(SaltInvocationError, composer.install, None)
|
||||
|
||||
# Test `composer install` exit status != 0 throws exception
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
mock = MagicMock(return_value={'retcode': 1, 'stderr': 'A'})
|
||||
with patch.dict(composer.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertRaises(CommandExecutionError, composer.install, 'd')
|
||||
|
||||
# Test success with quiet=True returns True
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stderr': 'A'})
|
||||
with patch.dict(composer.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertTrue(composer.install('dir', None, None, None, None,
|
||||
None, None, None, None, None,
|
||||
True))
|
||||
|
||||
# Test success with quiet=False returns object
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
rval = {'retcode': 0, 'stderr': 'A', 'stdout': 'B'}
|
||||
mock = MagicMock(return_value=rval)
|
||||
with patch.dict(composer.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertEqual(composer.install('dir'), rval)
|
||||
|
||||
def test_update(self):
|
||||
'''
|
||||
Test for Update composer dependencies for a directory.
|
||||
'''
|
||||
|
||||
# Test _valid_composer=False throws exception
|
||||
mock = MagicMock(return_value=False)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
self.assertRaises(CommandNotFoundError, composer.update, 'd')
|
||||
|
||||
# Test no directory specified throws exception
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, 'did_composer_install', mock):
|
||||
self.assertRaises(SaltInvocationError, composer.update, None)
|
||||
|
||||
# Test update with error exit status throws exception
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, 'did_composer_install', mock):
|
||||
mock = MagicMock(return_value={'retcode': 1, 'stderr': 'A'})
|
||||
with patch.dict(composer.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertRaises(CommandExecutionError, composer.update, 'd')
|
||||
|
||||
# Test update with existing vendor directory and quiet=True
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, 'did_composer_install', mock):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stderr': 'A'})
|
||||
with patch.dict(composer.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertTrue(composer.update('dir', None, None, None, None,
|
||||
None, None, None, None, None,
|
||||
True))
|
||||
|
||||
# Test update with no vendor directory and quiet=True
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
mock = MagicMock(return_value=False)
|
||||
with patch.object(composer, 'did_composer_install', mock):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stderr': 'A'})
|
||||
with patch.dict(composer.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertTrue(composer.update('dir', None, None, None, None,
|
||||
None, None, None, None, None,
|
||||
True))
|
||||
|
||||
# Test update with existing vendor directory
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, 'did_composer_install', mock):
|
||||
rval = {'retcode': 0, 'stderr': 'A', 'stdout': 'B'}
|
||||
mock = MagicMock(return_value=rval)
|
||||
with patch.dict(composer.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertEqual(composer.update('dir'), rval)
|
||||
|
||||
# Test update with no vendor directory
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
mock = MagicMock(return_value=False)
|
||||
with patch.object(composer, 'did_composer_install', mock):
|
||||
rval = {'retcode': 0, 'stderr': 'A', 'stdout': 'B'}
|
||||
mock = MagicMock(return_value=rval)
|
||||
with patch.dict(composer.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertEqual(composer.update('dir'), rval)
|
||||
|
||||
def test_selfupdate(self):
|
||||
'''
|
||||
Test for Composer selfupdate
|
||||
'''
|
||||
mock = MagicMock(return_value=False)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
self.assertRaises(CommandNotFoundError, composer.selfupdate)
|
||||
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
mock = MagicMock(return_value={'retcode': 1, 'stderr': 'A'})
|
||||
with patch.dict(composer.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertRaises(CommandExecutionError, composer.selfupdate)
|
||||
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stderr': 'A'})
|
||||
with patch.dict(composer.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertTrue(composer.selfupdate(quiet=True))
|
||||
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(composer, '_valid_composer', mock):
|
||||
rval = {'retcode': 0, 'stderr': 'A', 'stdout': 'B'}
|
||||
mock = MagicMock(return_value=rval)
|
||||
with patch.dict(composer.__salt__, {'cmd.run_all': mock}):
|
||||
self.assertEqual(composer.selfupdate(), rval)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(ComposerTestCase, needs_daemon=False)
|
Loading…
Reference in New Issue
Block a user