mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 01:18:58 +00:00
Merge pull request #28155 from basepi/merge-forward-2015.8
[2015.8] Merge forward from 2015.5 to 2015.8
This commit is contained in:
commit
053ad408c7
@ -402,7 +402,8 @@
|
||||
|
||||
# Set the file client. The client defaults to looking on the master server for
|
||||
# files, but can be directed to look at the local file directory setting
|
||||
# defined below by setting it to local.
|
||||
# defined below by setting it to "local". Setting a local file_client runs the
|
||||
# minion in masterless mode.
|
||||
#file_client: remote
|
||||
|
||||
# The file directory works on environments passed to the minion, each environment
|
||||
|
@ -164,7 +164,7 @@ project = 'Salt'
|
||||
copyright = '2015 SaltStack, Inc.'
|
||||
|
||||
version = salt.version.__version__
|
||||
latest_release = '2015.8.1' # latest release
|
||||
latest_release = '2015.8.1' # latest release
|
||||
previous_release = '2015.5.6' # latest release from previous branch
|
||||
previous_release_dir = '2015.5' # path on web server for previous branch
|
||||
build_type = 'latest' # latest, previous, develop, inactive
|
||||
|
@ -307,7 +307,7 @@ https://github.com/saltstack-formulas/salt-formula
|
||||
.. _faq-grain-security:
|
||||
|
||||
Is Targeting using Grain Data Secure?
|
||||
=====================================
|
||||
-------------------------------------
|
||||
|
||||
Because grains can be set by users that have access to the minion configuration
|
||||
files on the local system, grains are considered less secure than other
|
||||
|
@ -85,6 +85,10 @@ by their ``os`` grain:
|
||||
|
||||
company: Foo Industries
|
||||
|
||||
.. important::
|
||||
See :ref:`Is Targeting using Grain Data Secure? <faq-grain-security>` for
|
||||
important security information.
|
||||
|
||||
The above pillar sets two key/value pairs. If a minion is running RedHat, then
|
||||
the ``apache`` key is set to ``httpd`` and the ``git`` key is set to the value
|
||||
of ``git``. If the minion is running Debian, those values are changed to
|
||||
|
@ -22,6 +22,10 @@ to a custom grain, grain data is refreshed.
|
||||
Grains resolve to lowercase letters. For example, ``FOO``, and ``foo``
|
||||
target the same grain.
|
||||
|
||||
.. important::
|
||||
See :ref:`Is Targeting using Grain Data Secure? <faq-grain-security>` for
|
||||
important security information.
|
||||
|
||||
Match all CentOS minions:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -90,6 +90,8 @@ class SaltCloud(parsers.SaltCloudParser):
|
||||
log.info('salt-cloud starting')
|
||||
try:
|
||||
mapper = salt.cloud.Map(self.config)
|
||||
except SaltCloudSystemExit as exc:
|
||||
self.handle_exception(exc.args, exc)
|
||||
except SaltCloudException as exc:
|
||||
msg = 'There was an error generating the mapper.'
|
||||
self.handle_exception(msg, exc)
|
||||
@ -374,7 +376,7 @@ class SaltCloud(parsers.SaltCloudParser):
|
||||
|
||||
def handle_exception(self, msg, exc):
|
||||
if isinstance(exc, SaltCloudException):
|
||||
# It's a know exception an we know own to handle it
|
||||
# It's a known exception and we know how to handle it
|
||||
if isinstance(exc, SaltCloudSystemExit):
|
||||
# This is a salt cloud system exit
|
||||
if exc.exit_code > 0:
|
||||
|
@ -134,19 +134,17 @@ except ImportError:
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
SIZE_MAP = {
|
||||
'Micro Instance': 't1.micro',
|
||||
'Small Instance': 'm1.small',
|
||||
'Medium Instance': 'm1.medium',
|
||||
'Large Instance': 'm1.large',
|
||||
'Extra Large Instance': 'm1.xlarge',
|
||||
'High-CPU Medium Instance': 'c1.medium',
|
||||
'High-CPU Extra Large Instance': 'c1.xlarge',
|
||||
'High-Memory Extra Large Instance': 'm2.xlarge',
|
||||
'High-Memory Double Extra Large Instance': 'm2.2xlarge',
|
||||
'High-Memory Quadruple Extra Large Instance': 'm2.4xlarge',
|
||||
'Cluster GPU Quadruple Extra Large Instance': 'cg1.4xlarge',
|
||||
'Cluster Compute Quadruple Extra Large Instance': 'cc1.4xlarge',
|
||||
'Cluster Compute Eight Extra Large Instance': 'cc2.8xlarge',
|
||||
'Micro Instance': 't2.micro',
|
||||
'Small Instance': 't2.small',
|
||||
'Medium Instance': 'm3.medium',
|
||||
'Large Instance': 'm4.large',
|
||||
'Extra Large Instance': 'm4.xlarge',
|
||||
'High-CPU Medium Instance': 'c4.large',
|
||||
'High-CPU Extra Large Instance': 'c4.xlarge',
|
||||
'High-Memory Extra Large Instance': 'r3.xlarge',
|
||||
'High-Memory Double Extra Large Instance': 'r3.2xlarge',
|
||||
'High-Memory Quadruple Extra Large Instance': 'r3.4xlarge',
|
||||
'Cluster GPU Quadruple Extra Large Instance': 'g2.8xlarge'
|
||||
}
|
||||
|
||||
|
||||
@ -622,57 +620,93 @@ def avail_sizes(call=None):
|
||||
'ram': '22.5 GiB'
|
||||
},
|
||||
},
|
||||
'High CPU': {
|
||||
'c1.xlarge': {
|
||||
'id': 'c1.xlarge',
|
||||
'cores': '8 (with 2.5 ECUs each)',
|
||||
'disk': '1680 GiB (4 x 420 GiB)',
|
||||
'ram': '8 GiB'
|
||||
'Compute Optimized': {
|
||||
'c4.large': {
|
||||
'id': 'c4.large',
|
||||
'cores': '2',
|
||||
'disk': 'EBS - 500 Mbps',
|
||||
'ram': '3.75 GiB'
|
||||
},
|
||||
'c1.medium': {
|
||||
'id': 'c1.medium',
|
||||
'cores': '2 (with 2.5 ECUs each)',
|
||||
'disk': '340 GiB (1 x 340 GiB)',
|
||||
'ram': '1.7 GiB'
|
||||
'c4.xlarge': {
|
||||
'id': 'c4.xlarge',
|
||||
'cores': '4',
|
||||
'disk': 'EBS - 750 Mbps',
|
||||
'ram': '7.5 GiB'
|
||||
},
|
||||
'c4.2xlarge': {
|
||||
'id': 'c4.2xlarge',
|
||||
'cores': '8',
|
||||
'disk': 'EBS - 1000 Mbps',
|
||||
'ram': '15 GiB'
|
||||
},
|
||||
'c4.4xlarge': {
|
||||
'id': 'c4.4xlarge',
|
||||
'cores': '16',
|
||||
'disk': 'EBS - 2000 Mbps',
|
||||
'ram': '30 GiB'
|
||||
},
|
||||
'c4.8xlarge': {
|
||||
'id': 'c4.8xlarge',
|
||||
'cores': '36',
|
||||
'disk': 'EBS - 4000 Mbps',
|
||||
'ram': '60 GiB'
|
||||
},
|
||||
'c3.large': {
|
||||
'id': 'c3.large',
|
||||
'cores': '2 (with 3.5 ECUs each)',
|
||||
'cores': '2',
|
||||
'disk': '32 GiB (2 x 16 GiB SSD)',
|
||||
'ram': '3.75 GiB'
|
||||
},
|
||||
'c3.xlarge': {
|
||||
'id': 'c3.xlarge',
|
||||
'cores': '4 (with 3.5 ECUs each)',
|
||||
'cores': '4',
|
||||
'disk': '80 GiB (2 x 40 GiB SSD)',
|
||||
'ram': '7.5 GiB'
|
||||
},
|
||||
'c3.2xlarge': {
|
||||
'id': 'c3.2xlarge',
|
||||
'cores': '8 (with 3.5 ECUs each)',
|
||||
'cores': '8',
|
||||
'disk': '160 GiB (2 x 80 GiB SSD)',
|
||||
'ram': '15 GiB'
|
||||
},
|
||||
'c3.4xlarge': {
|
||||
'id': 'c3.4xlarge',
|
||||
'cores': '16 (with 3.5 ECUs each)',
|
||||
'disk': '320 GiB (2 x 80 GiB SSD)',
|
||||
'cores': '16',
|
||||
'disk': '320 GiB (2 x 160 GiB SSD)',
|
||||
'ram': '30 GiB'
|
||||
},
|
||||
'c3.8xlarge': {
|
||||
'id': 'c3.8xlarge',
|
||||
'cores': '32 (with 3.5 ECUs each)',
|
||||
'disk': '320 GiB (2 x 160 GiB SSD)',
|
||||
'cores': '32',
|
||||
'disk': '640 GiB (2 x 320 GiB SSD)',
|
||||
'ram': '60 GiB'
|
||||
}
|
||||
},
|
||||
'High I/O': {
|
||||
'hi1.4xlarge': {
|
||||
'id': 'hi1.4xlarge',
|
||||
'cores': '8 (with 4.37 ECUs each)',
|
||||
'disk': '2 TiB',
|
||||
'ram': '60.5 GiB'
|
||||
'i2.xlarge': {
|
||||
'id': 'i2.xlarge',
|
||||
'cores': '4',
|
||||
'disk': 'SSD (1 x 800 GiB)',
|
||||
'ram': '30.5 GiB'
|
||||
},
|
||||
'i2.2xlarge': {
|
||||
'id': 'i2.2xlarge',
|
||||
'cores': '8',
|
||||
'disk': 'SSD (2 x 800 GiB)',
|
||||
'ram': '61 GiB'
|
||||
},
|
||||
'i2.4xlarge': {
|
||||
'id': 'i2.4xlarge',
|
||||
'cores': '16',
|
||||
'disk': 'SSD (4 x 800 GiB)',
|
||||
'ram': '122 GiB'
|
||||
},
|
||||
'i2.8xlarge': {
|
||||
'id': 'i2.8xlarge',
|
||||
'cores': '32',
|
||||
'disk': 'SSD (8 x 800 GiB)',
|
||||
'ram': '244 GiB'
|
||||
}
|
||||
},
|
||||
'High Memory': {
|
||||
'm2.2xlarge': {
|
||||
@ -740,51 +774,85 @@ def avail_sizes(call=None):
|
||||
'ram': '117 GiB'
|
||||
},
|
||||
},
|
||||
'Micro': {
|
||||
't1.micro': {
|
||||
'id': 't1.micro',
|
||||
'General Purpose': {
|
||||
't2.micro': {
|
||||
'id': 't2.micro',
|
||||
'cores': '1',
|
||||
'disk': 'EBS',
|
||||
'ram': '615 MiB'
|
||||
'ram': '1 GiB'
|
||||
},
|
||||
},
|
||||
'Standard': {
|
||||
'm1.xlarge': {
|
||||
'id': 'm1.xlarge',
|
||||
'cores': '4 (with 2 ECUs each)',
|
||||
'disk': '1680 GB (4 x 420 GiB)',
|
||||
'ram': '15 GiB'
|
||||
},
|
||||
'm1.large': {
|
||||
'id': 'm1.large',
|
||||
'cores': '2 (with 2 ECUs each)',
|
||||
'disk': '840 GiB (2 x 420 GiB)',
|
||||
'ram': '7.5 GiB'
|
||||
},
|
||||
'm1.medium': {
|
||||
'id': 'm1.medium',
|
||||
't2.small': {
|
||||
'id': 't2.small',
|
||||
'cores': '1',
|
||||
'disk': '400 GiB',
|
||||
'disk': 'EBS',
|
||||
'ram': '2 GiB'
|
||||
},
|
||||
't2.medium': {
|
||||
'id': 't2.medium',
|
||||
'cores': '2',
|
||||
'disk': 'EBS',
|
||||
'ram': '4 GiB'
|
||||
},
|
||||
't2.large': {
|
||||
'id': 't2.large',
|
||||
'cores': '2',
|
||||
'disk': 'EBS',
|
||||
'ram': '8 GiB'
|
||||
},
|
||||
'm4.large': {
|
||||
'id': 'm4.large',
|
||||
'cores': '2',
|
||||
'disk': 'EBS - 450 Mbps',
|
||||
'ram': '8 GiB'
|
||||
},
|
||||
'm4.xlarge': {
|
||||
'id': 'm4.xlarge',
|
||||
'cores': '4',
|
||||
'disk': 'EBS - 750 Mbps',
|
||||
'ram': '16 GiB'
|
||||
},
|
||||
'm4.2xlarge': {
|
||||
'id': 'm4.2xlarge',
|
||||
'cores': '8',
|
||||
'disk': 'EBS - 1000 Mbps',
|
||||
'ram': '32 GiB'
|
||||
},
|
||||
'm4.4xlarge': {
|
||||
'id': 'm4.4xlarge',
|
||||
'cores': '16',
|
||||
'disk': 'EBS - 2000 Mbps',
|
||||
'ram': '64 GiB'
|
||||
},
|
||||
'm4.10xlarge': {
|
||||
'id': 'm4.10xlarge',
|
||||
'cores': '40',
|
||||
'disk': 'EBS - 4000 Mbps',
|
||||
'ram': '160 GiB'
|
||||
},
|
||||
'm3.medium': {
|
||||
'id': 'm3.medium',
|
||||
'cores': '1',
|
||||
'disk': 'SSD (1 x 4)',
|
||||
'ram': '3.75 GiB'
|
||||
},
|
||||
'm1.small': {
|
||||
'id': 'm1.small',
|
||||
'cores': '1',
|
||||
'disk': '150 GiB',
|
||||
'ram': '1.7 GiB'
|
||||
},
|
||||
'm3.2xlarge': {
|
||||
'id': 'm3.2xlarge',
|
||||
'cores': '8 (with 3.25 ECUs each)',
|
||||
'disk': 'EBS',
|
||||
'ram': '30 GiB'
|
||||
'm3.large': {
|
||||
'id': 'm3.large',
|
||||
'cores': '2',
|
||||
'disk': 'SSD (1 x 32)',
|
||||
'ram': '7.5 GiB'
|
||||
},
|
||||
'm3.xlarge': {
|
||||
'id': 'm3.xlarge',
|
||||
'cores': '4 (with 3.25 ECUs each)',
|
||||
'disk': 'EBS',
|
||||
'cores': '4',
|
||||
'disk': 'SSD (2 x 40)',
|
||||
'ram': '15 GiB'
|
||||
},
|
||||
'm3.2xlarge': {
|
||||
'id': 'm3.2xlarge',
|
||||
'cores': '8',
|
||||
'disk': 'SSD (2 x 80)',
|
||||
'ram': '30 GiB'
|
||||
},
|
||||
}
|
||||
}
|
||||
return sizes
|
||||
|
@ -467,6 +467,18 @@ def create(vm_, call=None):
|
||||
__opts__['internal_lxc_profile'] = __opts__['profile']
|
||||
del __opts__['profile']
|
||||
|
||||
salt.utils.cloud.fire_event(
|
||||
'event',
|
||||
'created instance',
|
||||
'salt/cloud/{0}/created'.format(vm_['name']),
|
||||
{
|
||||
'name': vm_['name'],
|
||||
'profile': vm_['profile'],
|
||||
'provider': vm_['driver'],
|
||||
},
|
||||
transport=__opts__['transport']
|
||||
)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
@ -532,13 +544,10 @@ def get_configured_provider(vm_=None):
|
||||
{}).get(dalias, {}).get(driver, {})
|
||||
# in all cases, verify that the linked saltmaster is alive.
|
||||
if data:
|
||||
try:
|
||||
ret = _salt('test.ping', salt_target=data['target'])
|
||||
if not ret:
|
||||
raise Exception('error')
|
||||
return data
|
||||
except Exception:
|
||||
ret = _salt('test.ping', salt_target=data['target'])
|
||||
if not ret:
|
||||
raise SaltCloudSystemExit(
|
||||
'Configured provider {0} minion: {1} is unreachable'.format(
|
||||
__active_provider_name__, data['target']))
|
||||
return data
|
||||
return False
|
||||
|
@ -123,10 +123,9 @@ def _authenticate():
|
||||
'password', get_configured_provider(), __opts__, search_global=False
|
||||
)
|
||||
verify_ssl = config.get_cloud_config_value(
|
||||
'verify_ssl', get_configured_provider(), __opts__, search_global=False
|
||||
'verify_ssl', get_configured_provider(), __opts__,
|
||||
default=True, search_global=False
|
||||
)
|
||||
if verify_ssl is None:
|
||||
verify_ssl = True
|
||||
|
||||
connect_data = {'username': username, 'password': passwd}
|
||||
full_url = 'https://{0}:8006/api2/json/access/ticket'.format(url)
|
||||
|
@ -10,6 +10,7 @@ import logging
|
||||
import hashlib
|
||||
import os
|
||||
import shutil
|
||||
import ftplib
|
||||
|
||||
# Import salt libs
|
||||
from salt.exceptions import (
|
||||
@ -572,6 +573,15 @@ class Client(object):
|
||||
return dest
|
||||
except Exception:
|
||||
raise MinionError('Could not fetch from {0}'.format(url))
|
||||
if url_data.scheme == 'ftp':
|
||||
try:
|
||||
ftp = ftplib.FTP(url_data.hostname)
|
||||
ftp.login()
|
||||
with salt.utils.fopen(dest, 'wb') as fp_:
|
||||
ftp.retrbinary('RETR {0}'.format(url_data.path), fp_.write)
|
||||
return dest
|
||||
except Exception as exc:
|
||||
raise MinionError('Could not retrieve {0} from FTP server. Exception: {1}'.format(url, exc))
|
||||
|
||||
if url_data.scheme == 'swift':
|
||||
try:
|
||||
|
@ -159,15 +159,15 @@ def set_host(ip, alias):
|
||||
comps = tmpline.split()
|
||||
if comps[0] == ip:
|
||||
if not ovr:
|
||||
lines[ind] = ip + '\t\t' + alias + '\n'
|
||||
lines[ind] = ip + '\t\t' + alias + os.linesep
|
||||
ovr = True
|
||||
else: # remove other entries
|
||||
lines[ind] = ''
|
||||
if not ovr:
|
||||
# make sure there is a newline
|
||||
if lines and not lines[-1].endswith(('\n', '\r')):
|
||||
lines[-1] = '{0}\n'.format(lines[-1])
|
||||
line = ip + '\t\t' + alias + '\n'
|
||||
if lines and not lines[-1].endswith(os.linesep):
|
||||
lines[-1] += os.linesep
|
||||
line = ip + '\t\t' + alias + os.linesep
|
||||
lines.append(line)
|
||||
with salt.utils.fopen(hfn, 'w+') as ofile:
|
||||
ofile.writelines(lines)
|
||||
@ -206,7 +206,7 @@ def rm_host(ip, alias):
|
||||
lines[ind] = ''
|
||||
else:
|
||||
# Only an alias was removed
|
||||
lines[ind] = '{0}\n'.format(newline)
|
||||
lines[ind] = newline + os.linesep
|
||||
with salt.utils.fopen(hfn, 'w+') as ofile:
|
||||
ofile.writelines(lines)
|
||||
return True
|
||||
@ -262,4 +262,4 @@ def _write_hosts(hosts):
|
||||
if line.strip():
|
||||
# /etc/hosts needs to end with EOL so that some utils that read
|
||||
# it do not break
|
||||
ofile.write('{0}\n'.format(line.strip()))
|
||||
ofile.write(line.strip() + os.linesep)
|
||||
|
@ -6,14 +6,16 @@ Author: Anthony Stanton <anthony.stanton@gmail.com>
|
||||
Inspired by the S3 and Nova modules
|
||||
|
||||
:depends: - swiftclient Python module
|
||||
:configuration: This module is not usable until the user, password, tenant, and
|
||||
auth URL are specified either in a pillar or in the minion's config file.
|
||||
:configuration: This module is not usable until the user, tenant, auth URL, and password or auth_key
|
||||
are specified either in a pillar or in the minion's config file.
|
||||
For example::
|
||||
|
||||
keystone.user: admin
|
||||
keystone.password: verybadpass
|
||||
keystone.tenant: admin
|
||||
keystone.auth_url: 'http://127.0.0.1:5000/v2.0/'
|
||||
keystone.password: verybadpass
|
||||
# or
|
||||
keystone.auth_key: 203802934809284k2j34lkj2l3kj43k
|
||||
|
||||
If configuration for multiple OpenStack accounts is required, they can be
|
||||
set up as different configuration profiles:
|
||||
@ -21,21 +23,27 @@ Inspired by the S3 and Nova modules
|
||||
|
||||
openstack1:
|
||||
keystone.user: admin
|
||||
keystone.password: verybadpass
|
||||
keystone.tenant: admin
|
||||
keystone.auth_url: 'http://127.0.0.1:5000/v2.0/'
|
||||
keystone.password: verybadpass
|
||||
# or
|
||||
keystone.auth_key: 203802934809284k2j34lkj2l3kj43k
|
||||
|
||||
openstack2:
|
||||
keystone.user: admin
|
||||
keystone.password: verybadpass
|
||||
keystone.tenant: admin
|
||||
keystone.auth_url: 'http://127.0.0.2:5000/v2.0/'
|
||||
keystone.password: verybadpass
|
||||
# or
|
||||
keystone.auth_key: 303802934809284k2j34lkj2l3kj43k
|
||||
|
||||
With this configuration in place, any of the swift functions can make use of
|
||||
a configuration profile by declaring it explicitly.
|
||||
For example::
|
||||
|
||||
salt '*' swift.get mycontainer myfile /tmp/file profile=openstack1
|
||||
|
||||
NOTE: For Rackspace cloud files setting keystone.auth_version = 1 is recommended.
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
|
||||
@ -67,26 +75,29 @@ def _auth(profile=None):
|
||||
if profile:
|
||||
credentials = __salt__['config.option'](profile)
|
||||
user = credentials['keystone.user']
|
||||
password = credentials['keystone.password']
|
||||
password = credentials.get('keystone.password', None)
|
||||
tenant = credentials['keystone.tenant']
|
||||
auth_url = credentials['keystone.auth_url']
|
||||
auth_version = credentials.get('keystone.auth_version', 2)
|
||||
region_name = credentials.get('keystone.region_name', None)
|
||||
api_key = credentials.get('keystone.api_key', None)
|
||||
os_auth_system = credentials.get('keystone.os_auth_system', None)
|
||||
else:
|
||||
user = __salt__['config.option']('keystone.user')
|
||||
password = __salt__['config.option']('keystone.password')
|
||||
password = __salt__['config.option']('keystone.password', None)
|
||||
tenant = __salt__['config.option']('keystone.tenant')
|
||||
auth_url = __salt__['config.option']('keystone.auth_url')
|
||||
auth_version = __salt__['config.option']('keystone.auth_version', 2)
|
||||
region_name = __salt__['config.option']('keystone.region_name')
|
||||
api_key = __salt__['config.option']('keystone.api_key')
|
||||
os_auth_system = __salt__['config.option']('keystone.os_auth_system')
|
||||
kwargs = {
|
||||
'user': user,
|
||||
'password': password,
|
||||
'api_key': api_key,
|
||||
'key': api_key,
|
||||
'tenant_name': tenant,
|
||||
'auth_url': auth_url,
|
||||
'auth_version': auth_version,
|
||||
'region_name': region_name
|
||||
}
|
||||
|
||||
|
@ -75,11 +75,7 @@ def get_path():
|
||||
'''
|
||||
ret = __salt__['reg.read_value']('HKEY_LOCAL_MACHINE',
|
||||
'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment',
|
||||
'PATH')
|
||||
if isinstance(ret, dict):
|
||||
ret = ret['vdata'].split(';')
|
||||
if isinstance(ret, str):
|
||||
ret = ret.split(';')
|
||||
'PATH')['vdata'].split(';')
|
||||
|
||||
# Trim ending backslash
|
||||
return list(map(_normalize_dir, ret))
|
||||
|
@ -704,7 +704,12 @@ def installed(name,
|
||||
trusted_host=trusted_host
|
||||
)
|
||||
|
||||
if pip_install_call and (pip_install_call.get('retcode', 1) == 0):
|
||||
# Check the retcode for success, but don't fail if using pip1 and the package is
|
||||
# already present. Pip1 returns a retcode of 1 (instead of 0 for pip2) if you run
|
||||
# "pip install" without any arguments. See issue #21845.
|
||||
if pip_install_call and \
|
||||
(pip_install_call.get('retcode', 1) == 0 or pip_install_call.get('stdout', '').startswith(
|
||||
'You must give at least one requirement to install')):
|
||||
ret['result'] = True
|
||||
|
||||
if requirements or editable:
|
||||
|
@ -243,8 +243,12 @@ def state(
|
||||
if mdata.get('failed', False):
|
||||
m_state = False
|
||||
else:
|
||||
m_ret = mdata['ret']
|
||||
m_state = salt.utils.check_state_result(m_ret)
|
||||
try:
|
||||
m_ret = mdata['ret']
|
||||
except KeyError:
|
||||
m_state = False
|
||||
if not m_state:
|
||||
m_state = salt.utils.check_state_result(m_ret)
|
||||
|
||||
if not m_state:
|
||||
if minion not in fail_minions:
|
||||
|
Loading…
Reference in New Issue
Block a user