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__
|
version = salt.version.__version__
|
||||||
#release = '.'.join(map(str, salt.version.__version_info__))
|
#release = '.'.join(map(str, salt.version.__version_info__))
|
||||||
release = '2015.2'
|
release = '2014.7.2'
|
||||||
|
|
||||||
needs_sphinx = '1.3'
|
needs_sphinx = '1.3'
|
||||||
|
|
||||||
|
@ -1885,7 +1885,7 @@ strategy between different sources. It accepts 3 values:
|
|||||||
|
|
||||||
* aggregate:
|
* 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:
|
For example, these two documents:
|
||||||
|
|
||||||
|
@ -6,8 +6,28 @@ Linode is a public cloud provider with a focus on Linux instances.
|
|||||||
|
|
||||||
Dependencies
|
Dependencies
|
||||||
============
|
============
|
||||||
|
* linode-python >= 1.1
|
||||||
|
|
||||||
|
OR
|
||||||
|
|
||||||
* Libcloud >= 0.13.2
|
* 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
|
Configuration
|
||||||
=============
|
=============
|
||||||
Linode requires a single API key, but the default root password for new
|
Linode requires a single API key, but the default root password for new
|
||||||
@ -100,3 +120,34 @@ command:
|
|||||||
uuid:
|
uuid:
|
||||||
8457f92eaffc92b7666b6734a96ad7abe1a8a6dd
|
8457f92eaffc92b7666b6734a96ad7abe1a8a6dd
|
||||||
...SNIP...
|
...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 python libs
|
||||||
import logging
|
import logging
|
||||||
|
import os.path
|
||||||
|
|
||||||
# Import salt libs
|
# Import salt libs
|
||||||
import salt.utils
|
import salt.utils
|
||||||
from salt.exceptions import CommandExecutionError
|
from salt.exceptions import CommandExecutionError, CommandNotFoundError, SaltInvocationError
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -35,6 +36,162 @@ def _valid_composer(composer):
|
|||||||
return False
|
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,
|
def install(dir,
|
||||||
composer=None,
|
composer=None,
|
||||||
php=None,
|
php=None,
|
||||||
@ -102,60 +259,150 @@ def install(dir,
|
|||||||
salt '*' composer.install /var/www/application \
|
salt '*' composer.install /var/www/application \
|
||||||
no_dev=True optimize=True
|
no_dev=True optimize=True
|
||||||
'''
|
'''
|
||||||
if composer is not None:
|
result = _run_composer('install',
|
||||||
if php is None:
|
dir=dir,
|
||||||
php = 'php'
|
composer=composer,
|
||||||
else:
|
php=php,
|
||||||
composer = 'composer'
|
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
|
||||||
|
|
||||||
# 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:
|
def update(dir,
|
||||||
return '{0!r} is required for {1!r}'.format('dir', 'composer.install')
|
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.
|
||||||
|
|
||||||
# Base Settings
|
If `composer install` has not yet been run, this runs `composer install`
|
||||||
cmd = composer + ' install --no-interaction'
|
instead.
|
||||||
|
|
||||||
# If php is set, prepend it
|
If composer has not been installed globally making it available in the
|
||||||
if php is not None:
|
system PATH & making it executable, the ``composer`` and ``php`` parameters
|
||||||
cmd = php + ' ' + cmd
|
will need to be set to the location of the executables.
|
||||||
|
|
||||||
# Add Working Dir
|
dir
|
||||||
cmd += ' --working-dir=' + dir
|
Directory location of the composer.json file.
|
||||||
|
|
||||||
# Other Settings
|
composer
|
||||||
if quiet is True:
|
Location of the composer.phar file. If not set composer will
|
||||||
cmd += ' --quiet'
|
just execute "composer" as if it is installed globally.
|
||||||
|
(i.e. /path/to/composer.phar)
|
||||||
|
|
||||||
if no_dev is True:
|
php
|
||||||
cmd += ' --no-dev'
|
Location of the php executable to use with composer.
|
||||||
|
(i.e. /usr/bin/php)
|
||||||
|
|
||||||
if prefer_source is True:
|
runas
|
||||||
cmd += ' --prefer-source'
|
Which system user to run composer as.
|
||||||
|
|
||||||
if prefer_dist is True:
|
prefer_source
|
||||||
cmd += ' --prefer-dist'
|
--prefer-source option of composer.
|
||||||
|
|
||||||
if no_scripts is True:
|
prefer_dist
|
||||||
cmd += ' --no-scripts'
|
--prefer-dist option of composer.
|
||||||
|
|
||||||
if no_plugins is True:
|
no_scripts
|
||||||
cmd += ' --no-plugins'
|
--no-scripts option of composer.
|
||||||
|
|
||||||
if optimize is True:
|
no_plugins
|
||||||
cmd += ' --optimize-autoloader'
|
--no-plugins option of composer.
|
||||||
|
|
||||||
result = __salt__['cmd.run_all'](cmd,
|
optimize
|
||||||
runas=runas,
|
--optimize-autoloader option of composer. Recommended for production.
|
||||||
env={'COMPOSER_HOME': composer_home},
|
|
||||||
python_shell=False)
|
|
||||||
|
|
||||||
if result['retcode'] != 0:
|
no_dev
|
||||||
raise CommandExecutionError(result['stderr'])
|
--no-dev option for composer. Recommended for production.
|
||||||
|
|
||||||
if quiet is True:
|
quiet
|
||||||
return True
|
--quiet option for composer. Whether or not to return output from composer.
|
||||||
|
|
||||||
return result['stdout']
|
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>
|
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)
|
return not __salt__['cmd.retcode'](cmd, python_shell=False)
|
||||||
|
|
||||||
|
|
||||||
|
@ -2804,7 +2804,7 @@ class BaseHighState(object):
|
|||||||
if state:
|
if state:
|
||||||
self.merge_included_states(highstate, state, errors)
|
self.merge_included_states(highstate, state, errors)
|
||||||
for i, error in enumerate(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
|
# match SLS foobar in environment
|
||||||
this_sls = 'SLS {0} in saltenv'.format(
|
this_sls = 'SLS {0} in saltenv'.format(
|
||||||
sls_match)
|
sls_match)
|
||||||
|
@ -40,7 +40,7 @@ the location of composer in the state.
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
# Import salt libs
|
# Import salt libs
|
||||||
from salt.exceptions import CommandExecutionError, CommandNotFoundError
|
from salt.exceptions import SaltException
|
||||||
|
|
||||||
|
|
||||||
def __virtual__():
|
def __virtual__():
|
||||||
@ -60,10 +60,138 @@ def installed(name,
|
|||||||
no_plugins=None,
|
no_plugins=None,
|
||||||
optimize=None,
|
optimize=None,
|
||||||
no_dev=None,
|
no_dev=None,
|
||||||
composer_home='/root'):
|
quiet=False,
|
||||||
|
composer_home='/root',
|
||||||
|
always_check=True):
|
||||||
'''
|
'''
|
||||||
Verify that composer has installed the latest packages give a
|
Verify that the correct versions of composer dependencies are present.
|
||||||
``composer.json`` and ``composer.lock`` file in a directory.
|
|
||||||
|
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'):
|
||||||
|
'''
|
||||||
|
Composer update the directory to ensure we have the latest versions
|
||||||
|
of all project dependencies.
|
||||||
|
|
||||||
dir
|
dir
|
||||||
Directory location of the composer.json file.
|
Directory location of the composer.json file.
|
||||||
@ -108,8 +236,26 @@ def installed(name,
|
|||||||
'''
|
'''
|
||||||
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
|
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:
|
try:
|
||||||
call = __salt__['composer.install'](
|
call = __salt__['composer.update'](
|
||||||
name,
|
name,
|
||||||
composer=composer,
|
composer=composer,
|
||||||
php=php,
|
php=php,
|
||||||
@ -120,22 +266,26 @@ def installed(name,
|
|||||||
no_plugins=no_plugins,
|
no_plugins=no_plugins,
|
||||||
optimize=optimize,
|
optimize=optimize,
|
||||||
no_dev=no_dev,
|
no_dev=no_dev,
|
||||||
quiet=False,
|
quiet=quiet,
|
||||||
composer_home=composer_home
|
composer_home=composer_home
|
||||||
)
|
)
|
||||||
except (CommandNotFoundError, CommandExecutionError) as err:
|
except (SaltException) as err:
|
||||||
ret['result'] = False
|
ret['result'] = False
|
||||||
ret['comment'] = 'Error executing composer in \'{0!r}\': {1!r}'.format(name, err)
|
ret['comment'] = 'Error executing composer in \'{0!r}\': {1!r}'.format(name, err)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
if call or isinstance(call, list) or isinstance(call, dict):
|
# If composer retcode != 0 then an exception was thrown and we dealt with it.
|
||||||
ret['result'] = True
|
# Any other case is success, regardless of what composer decides to output.
|
||||||
if call.find('Nothing to install or update') < 0:
|
|
||||||
ret['changes']['stdout'] = call
|
|
||||||
|
|
||||||
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:
|
else:
|
||||||
ret['result'] = False
|
ret['comment'] = 'Composer update completed successfully'
|
||||||
ret['comment'] = 'Could not run composer'
|
ret['changes'] = {
|
||||||
|
'stderr': call['stderr'],
|
||||||
|
'stdout': call['stdout']
|
||||||
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
@ -45,7 +45,7 @@ The following example installs all driver updates that don't require a reboot:
|
|||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
gryffindor:
|
gryffindor:
|
||||||
win_update.install:
|
win_update.installed:
|
||||||
- includes:
|
- includes:
|
||||||
- driver: True
|
- driver: True
|
||||||
- software: False
|
- software: False
|
||||||
|
@ -221,7 +221,7 @@ def query(key, keyid, method='GET', params=None, headers=None,
|
|||||||
if return_url is True:
|
if return_url is True:
|
||||||
return ret, requesturl
|
return ret, requesturl
|
||||||
else:
|
else:
|
||||||
if method == 'GET' or method == 'HEAD':
|
if result.status_code != requests.codes.ok:
|
||||||
return
|
return
|
||||||
ret = {'headers': []}
|
ret = {'headers': []}
|
||||||
for header in result.headers:
|
for header in result.headers:
|
||||||
|
@ -11,6 +11,7 @@ import os
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import stat
|
import stat
|
||||||
|
import errno
|
||||||
import socket
|
import socket
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -162,8 +163,11 @@ def verify_files(files, user):
|
|||||||
for fn_ in files:
|
for fn_ in files:
|
||||||
dirname = os.path.dirname(fn_)
|
dirname = os.path.dirname(fn_)
|
||||||
try:
|
try:
|
||||||
if not os.path.isdir(dirname):
|
try:
|
||||||
os.makedirs(dirname)
|
os.makedirs(dirname)
|
||||||
|
except OSError as err:
|
||||||
|
if err.errno != errno.EEXIST:
|
||||||
|
raise
|
||||||
if not os.path.isfile(fn_):
|
if not os.path.isfile(fn_):
|
||||||
with salt.utils.fopen(fn_, 'w+') as fp_:
|
with salt.utils.fopen(fn_, 'w+') as fp_:
|
||||||
fp_.write('')
|
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