mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 09:23:56 +00:00
Merge pull request #22995 from basepi/merge-forward-develop
Merge forward from 2015.2 to develop
This commit is contained in:
commit
ed6eadceff
@ -188,6 +188,13 @@ class AuthorizationError(SaltException):
|
||||
'''
|
||||
|
||||
|
||||
class SaltDaemonNotRunning(SaltException):
|
||||
'''
|
||||
Throw when a running master/minion/syndic is not running but is needed to
|
||||
perform the requested operation (e.g., eauth).
|
||||
'''
|
||||
|
||||
|
||||
class SaltRunnerError(SaltException):
|
||||
'''
|
||||
Problem in runner
|
||||
|
@ -3124,7 +3124,9 @@ def get_managed(
|
||||
source_sum = {}
|
||||
if template and source:
|
||||
sfn = __salt__['cp.cache_file'](source, saltenv)
|
||||
if not os.path.exists(sfn):
|
||||
# exists doesn't play nice with sfn as bool
|
||||
# but if cache failed, sfn == False
|
||||
if not sfn or not os.path.exists(sfn):
|
||||
return sfn, {}, 'Source file {0} not found'.format(source)
|
||||
if sfn == name:
|
||||
raise SaltInvocationError(
|
||||
|
@ -36,6 +36,8 @@ SCHEDULE_CONF = [
|
||||
'splay',
|
||||
'range',
|
||||
'when',
|
||||
'once',
|
||||
'once_fmt',
|
||||
'returner',
|
||||
'jid_include',
|
||||
'args',
|
||||
@ -263,7 +265,8 @@ def build_schedule_item(name, **kwargs):
|
||||
else:
|
||||
schedule[name]['splay'] = kwargs['splay']
|
||||
|
||||
for item in ['range', 'when', 'cron', 'returner', 'return_config', 'until']:
|
||||
for item in ['range', 'when', 'once', 'once_fmt', 'cron', 'returner',
|
||||
'return_config', 'until']:
|
||||
if item in kwargs:
|
||||
schedule[name][item] = kwargs[item]
|
||||
|
||||
|
@ -16,7 +16,7 @@ import salt.syspaths
|
||||
import salt.wheel
|
||||
import salt.utils
|
||||
import salt.client.ssh.client
|
||||
from salt.exceptions import SaltException, EauthAuthenticationError
|
||||
import salt.exceptions
|
||||
|
||||
|
||||
class NetapiClient(object):
|
||||
@ -31,16 +31,34 @@ class NetapiClient(object):
|
||||
def __init__(self, opts):
|
||||
self.opts = opts
|
||||
|
||||
def _is_master_running(self):
|
||||
'''
|
||||
Perform a lightweight check to see if the master daemon is running
|
||||
|
||||
Note, this will return an invalid success if the master crashed or was
|
||||
not shut down cleanly.
|
||||
'''
|
||||
return os.path.exists(os.path.join(
|
||||
self.opts['sock_dir'],
|
||||
'workers.ipc'))
|
||||
|
||||
def run(self, low):
|
||||
'''
|
||||
Execute the specified function in the specified client by passing the
|
||||
lowstate
|
||||
'''
|
||||
# Eauth currently requires a running daemon and commands run through
|
||||
# this method require eauth so perform a quick check to raise a
|
||||
# more meaningful error.
|
||||
if not self._is_master_running():
|
||||
raise salt.exceptions.SaltDaemonNotRunning(
|
||||
'Salt Master is not available.')
|
||||
|
||||
if 'client' not in low:
|
||||
raise SaltException('No client specified')
|
||||
raise salt.exceptions.SaltException('No client specified')
|
||||
|
||||
if not ('token' in low or 'eauth' in low) and low['client'] != 'ssh':
|
||||
raise EauthAuthenticationError(
|
||||
raise salt.exceptions.EauthAuthenticationError(
|
||||
'No authentication credentials given')
|
||||
|
||||
l_fun = getattr(self, low['client'])
|
||||
|
@ -278,6 +278,41 @@ except ImportError:
|
||||
HAS_WEBSOCKETS = False
|
||||
|
||||
|
||||
def html_override_tool():
|
||||
'''
|
||||
Bypass the normal handler and serve HTML for all URLs
|
||||
|
||||
The ``app_path`` setting must be non-empty and the request must ask for
|
||||
``text/html`` in the ``Accept`` header.
|
||||
'''
|
||||
apiopts = cherrypy.config['apiopts']
|
||||
request = cherrypy.request
|
||||
|
||||
url_blacklist = (
|
||||
apiopts.get('app_path', '/app'),
|
||||
apiopts.get('static_path', '/static'),
|
||||
)
|
||||
|
||||
if 'app' not in cherrypy.config['apiopts']:
|
||||
return
|
||||
|
||||
if request.path_info.startswith(url_blacklist):
|
||||
return
|
||||
|
||||
if request.headers.get('Accept') == '*/*':
|
||||
return
|
||||
|
||||
try:
|
||||
wants_html = cherrypy.lib.cptools.accept('text/html')
|
||||
except cherrypy.HTTPError:
|
||||
return
|
||||
else:
|
||||
if wants_html != 'text/html':
|
||||
return
|
||||
|
||||
raise cherrypy.InternalRedirect(apiopts.get('app_path', '/app'))
|
||||
|
||||
|
||||
def salt_token_tool():
|
||||
'''
|
||||
If the custom authentication header is supplied, put it in the cookie dict
|
||||
@ -398,6 +433,9 @@ def hypermedia_handler(*args, **kwargs):
|
||||
except (salt.exceptions.EauthAuthenticationError,
|
||||
salt.exceptions.TokenAuthenticationError):
|
||||
raise cherrypy.HTTPError(401)
|
||||
except (salt.exceptions.SaltDaemonNotRunning,
|
||||
salt.exceptions.SaltReqTimeoutError) as exc:
|
||||
raise cherrypy.HTTPError(503, exc.strerror)
|
||||
except cherrypy.CherryPyException:
|
||||
raise
|
||||
except Exception as exc:
|
||||
@ -578,6 +616,8 @@ def lowdata_fmt():
|
||||
cherrypy.serving.request.lowstate = data
|
||||
|
||||
|
||||
cherrypy.tools.html_override = cherrypy.Tool('on_start_resource',
|
||||
html_override_tool, priority=53)
|
||||
cherrypy.tools.salt_token = cherrypy.Tool('on_start_resource',
|
||||
salt_token_tool, priority=55)
|
||||
cherrypy.tools.salt_auth = cherrypy.Tool('before_request_body',
|
||||
@ -1365,6 +1405,10 @@ class Login(LowDataAdapter):
|
||||
]
|
||||
}}
|
||||
'''
|
||||
if not self.api._is_master_running():
|
||||
raise salt.exceptions.SaltDaemonNotRunning(
|
||||
'Salt Master is not available.')
|
||||
|
||||
# the urlencoded_processor will wrap this in a list
|
||||
if isinstance(cherrypy.serving.request.lowstate, list):
|
||||
creds = cherrypy.serving.request.lowstate[0]
|
||||
@ -2216,10 +2260,17 @@ class API(object):
|
||||
|
||||
'tools.cpstats.on': self.apiopts.get('collect_stats', False),
|
||||
|
||||
'tools.html_override.on': True,
|
||||
'tools.cors_tool.on': True,
|
||||
},
|
||||
}
|
||||
|
||||
if 'favicon' in self.apiopts:
|
||||
conf['/favicon.ico'] = {
|
||||
'tools.staticfile.on': True,
|
||||
'tools.staticfile.filename': self.apiopts['favicon'],
|
||||
}
|
||||
|
||||
if self.apiopts.get('debug', False) is False:
|
||||
conf['global']['environment'] = 'production'
|
||||
|
||||
|
@ -85,6 +85,18 @@ localtime.
|
||||
- Thursday 3:00pm
|
||||
- Friday 5:00pm
|
||||
|
||||
This will schedule a job to run once on the specified date. The default date
|
||||
format is ISO 8601 but can be overridden by also specifying the ``once_fmt``
|
||||
option.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
schedule:
|
||||
job1:
|
||||
function: test.ping
|
||||
once: 2015-04-22T20:21:00
|
||||
once_fmt: '%Y-%m-%dT%H:%M:%S'
|
||||
|
||||
This will schedule the command: state.sls httpd test=True at 5pm on Monday,
|
||||
Wednesday and Friday, and 3pm on Tuesday and Thursday.
|
||||
|
||||
@ -230,6 +242,7 @@ from __future__ import absolute_import
|
||||
import os
|
||||
import time
|
||||
import datetime
|
||||
import itertools
|
||||
import multiprocessing
|
||||
import threading
|
||||
import sys
|
||||
@ -650,7 +663,6 @@ class Schedule(object):
|
||||
seconds = 0
|
||||
cron = 0
|
||||
now = int(time.time())
|
||||
time_conflict = False
|
||||
|
||||
if 'until' in data:
|
||||
if not _WHEN_SUPPORTED:
|
||||
@ -665,30 +677,54 @@ class Schedule(object):
|
||||
'skipping job: {0}.'.format(data['name']))
|
||||
continue
|
||||
|
||||
for item in ['seconds', 'minutes', 'hours', 'days']:
|
||||
if item in data and 'when' in data:
|
||||
time_conflict = True
|
||||
if item in data and 'cron' in data:
|
||||
time_conflict = True
|
||||
# Used for quick lookups when detecting invalid option combinations.
|
||||
schedule_keys = set(data.keys())
|
||||
|
||||
if time_conflict:
|
||||
log.error('Unable to use "seconds", "minutes",'
|
||||
'"hours", or "days" with '
|
||||
'"when" or "cron" options. Ignoring.')
|
||||
time_elements = ('seconds', 'minutes', 'hours', 'days')
|
||||
scheduling_elements = ('when', 'cron', 'once')
|
||||
|
||||
invalid_sched_combos = [set(i)
|
||||
for i in itertools.combinations(scheduling_elements, 2)]
|
||||
|
||||
if any(i <= schedule_keys for i in invalid_sched_combos):
|
||||
log.error('Unable to use "{0}" options together. Ignoring.'
|
||||
.format('", "'.join(scheduling_elements)))
|
||||
continue
|
||||
|
||||
if 'when' in data and 'cron' in data:
|
||||
log.error('Unable to use "when" and "cron" options together.'
|
||||
'Ignoring.')
|
||||
invalid_time_combos = []
|
||||
for item in scheduling_elements:
|
||||
all_items = itertools.chain([item], time_elements)
|
||||
invalid_time_combos.append(
|
||||
set(itertools.combinations(all_items, 2)))
|
||||
|
||||
if any(set(x) <= schedule_keys for x in invalid_time_combos):
|
||||
log.error('Unable to use "{0}" with "{1}" options. Ignoring'
|
||||
.format('", "'.join(time_elements),
|
||||
'", "'.join(scheduling_elements)))
|
||||
continue
|
||||
|
||||
time_elements = ['seconds', 'minutes', 'hours', 'days']
|
||||
if True in [True for item in time_elements if item in data]:
|
||||
# Add up how many seconds between now and then
|
||||
seconds += int(data.get('seconds', 0))
|
||||
seconds += int(data.get('minutes', 0)) * 60
|
||||
seconds += int(data.get('hours', 0)) * 3600
|
||||
seconds += int(data.get('days', 0)) * 86400
|
||||
elif 'once' in data:
|
||||
once_fmt = data.get('once_fmt', '%Y-%m-%dT%H:%M:%S')
|
||||
|
||||
try:
|
||||
once = datetime.datetime.strptime(data['once'], once_fmt)
|
||||
once = int(time.mktime(once.timetuple()))
|
||||
except (TypeError, ValueError):
|
||||
log.error('Date string could not be parsed: %s, %s',
|
||||
data['once'], once_fmt)
|
||||
continue
|
||||
|
||||
if now != once:
|
||||
continue
|
||||
else:
|
||||
seconds = 1
|
||||
|
||||
elif 'when' in data:
|
||||
if not _WHEN_SUPPORTED:
|
||||
log.error('Missing python-dateutil.'
|
||||
|
61
tests/unit/modules/qemu_img_test.py
Normal file
61
tests/unit/modules/qemu_img_test.py
Normal file
@ -0,0 +1,61 @@
|
||||
# -*- 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
|
||||
)
|
||||
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
|
||||
ensure_in_syspath('../../')
|
||||
|
||||
# Import Salt Libs
|
||||
from salt.modules import qemu_img
|
||||
import os
|
||||
|
||||
# Globals
|
||||
qemu_img.__salt__ = {}
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class QemuimgTestCase(TestCase):
|
||||
'''
|
||||
Test cases for salt.modules.qemu_img
|
||||
'''
|
||||
def test_make_image(self):
|
||||
'''
|
||||
Test for create a blank virtual machine image file
|
||||
of the specified size in megabytes
|
||||
'''
|
||||
with patch.object(os.path, 'isabs',
|
||||
MagicMock(side_effect=[False, True, True, True])):
|
||||
self.assertEqual(qemu_img.make_image('location', 'size', 'fmt'), '')
|
||||
|
||||
with patch.object(os.path, 'isdir',
|
||||
MagicMock(side_effect=[False, True, True])):
|
||||
self.assertEqual(qemu_img.make_image('location', 'size', 'fmt'),
|
||||
'')
|
||||
|
||||
with patch.dict(qemu_img.__salt__,
|
||||
{'cmd.retcode': MagicMock(side_effect=[False,
|
||||
True])}):
|
||||
self.assertEqual(qemu_img.make_image('location', 'size',
|
||||
'fmt'), 'location')
|
||||
|
||||
self.assertEqual(qemu_img.make_image('location', 'size',
|
||||
'fmt'), '')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(QemuimgTestCase, needs_daemon=False)
|
@ -39,28 +39,34 @@ class ApacheTestCase(TestCase):
|
||||
Test to allows for inputting a yaml dictionary into a file
|
||||
for apache configuration files.
|
||||
'''
|
||||
name = 'yaml'
|
||||
name = '/etc/distro/specific/apache.conf'
|
||||
config = 'VirtualHost: this: "*:80"'
|
||||
new_config = 'LiteralHost: that: "*:79"'
|
||||
|
||||
ret = {'name': name,
|
||||
'result': True,
|
||||
'changes': {},
|
||||
'comment': ''}
|
||||
|
||||
mock = MagicMock(side_effect=[config, '', ''])
|
||||
with patch.object(salt.utils, 'fopen', mock_open(read_data=config)):
|
||||
with patch.dict(apache.__salt__,
|
||||
{'apache.config': mock}):
|
||||
mock_config = MagicMock(return_value=config)
|
||||
with patch.dict(apache.__salt__, {'apache.config': mock_config}):
|
||||
ret.update({'comment': 'Configuration is up to date.'})
|
||||
self.assertDictEqual(apache.configfile(name, config), ret)
|
||||
|
||||
with patch.object(salt.utils, 'fopen', mock_open(read_data=config)):
|
||||
mock_config = MagicMock(return_value=new_config)
|
||||
with patch.dict(apache.__salt__, {'apache.config': mock_config}):
|
||||
ret.update({'comment': 'Configuration will update.',
|
||||
'changes': {'new': '',
|
||||
'old': 'VirtualHost: this: "*:80"'},
|
||||
'changes': {'new': new_config,
|
||||
'old': config},
|
||||
'result': None})
|
||||
with patch.dict(apache.__opts__, {'test': True}):
|
||||
self.assertDictEqual(apache.configfile(name, config), ret)
|
||||
self.assertDictEqual(apache.configfile(name, new_config), ret)
|
||||
|
||||
with patch.object(salt.utils, 'fopen', mock_open(read_data=config)):
|
||||
mock_config = MagicMock(return_value=new_config)
|
||||
with patch.dict(apache.__salt__, {'apache.config': mock_config}):
|
||||
ret.update({'comment': 'Successfully created configuration.',
|
||||
'result': True})
|
||||
with patch.dict(apache.__opts__, {'test': False}):
|
||||
|
105
tests/unit/states/boto_elasticache_test.py
Normal file
105
tests/unit/states/boto_elasticache_test.py
Normal file
@ -0,0 +1,105 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
|
||||
'''
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from salttesting import skipIf, TestCase
|
||||
from salttesting.mock import (
|
||||
NO_MOCK,
|
||||
NO_MOCK_REASON,
|
||||
MagicMock,
|
||||
patch)
|
||||
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
|
||||
ensure_in_syspath('../../')
|
||||
|
||||
# Import Salt Libs
|
||||
from salt.states import boto_elasticache
|
||||
|
||||
boto_elasticache.__salt__ = {}
|
||||
boto_elasticache.__opts__ = {}
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class BotoElasticacheTestCase(TestCase):
|
||||
'''
|
||||
Test cases for salt.states.boto_elasticache
|
||||
'''
|
||||
# 'present' function tests: 1
|
||||
|
||||
def test_present(self):
|
||||
'''
|
||||
Test to ensure the cache cluster exists.
|
||||
'''
|
||||
name = 'myelasticache'
|
||||
engine = 'redis'
|
||||
cache_node_type = 'cache.t1.micro'
|
||||
|
||||
ret = {'name': name,
|
||||
'result': None,
|
||||
'changes': {},
|
||||
'comment': ''}
|
||||
|
||||
mock = MagicMock(side_effect=[None, False, False, True])
|
||||
mock_bool = MagicMock(return_value=False)
|
||||
with patch.dict(boto_elasticache.__salt__,
|
||||
{'boto_elasticache.get_config': mock,
|
||||
'boto_elasticache.create': mock_bool}):
|
||||
comt = ('Failed to retrieve cache cluster info from AWS.')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(boto_elasticache.present(name, engine,
|
||||
cache_node_type), ret)
|
||||
|
||||
with patch.dict(boto_elasticache.__opts__, {'test': True}):
|
||||
comt = ('Cache cluster {0} is set to be created.'.format(name))
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(boto_elasticache.present(name, engine,
|
||||
cache_node_type),
|
||||
ret)
|
||||
|
||||
with patch.dict(boto_elasticache.__opts__, {'test': False}):
|
||||
comt = ('Failed to create {0} cache cluster.'.format(name))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
self.assertDictEqual(boto_elasticache.present(name, engine,
|
||||
cache_node_type),
|
||||
ret)
|
||||
|
||||
comt = ('Cache cluster {0} is present.'.format(name))
|
||||
ret.update({'comment': comt, 'result': True})
|
||||
self.assertDictEqual(boto_elasticache.present(name, engine,
|
||||
cache_node_type),
|
||||
ret)
|
||||
|
||||
# 'absent' function tests: 1
|
||||
|
||||
def test_absent(self):
|
||||
'''
|
||||
Test to ensure the named elasticache cluster is deleted.
|
||||
'''
|
||||
name = 'new_table'
|
||||
|
||||
ret = {'name': name,
|
||||
'result': True,
|
||||
'changes': {},
|
||||
'comment': ''}
|
||||
|
||||
mock = MagicMock(side_effect=[False, True])
|
||||
with patch.dict(boto_elasticache.__salt__,
|
||||
{'boto_elasticache.exists': mock}):
|
||||
comt = ('{0} does not exist in None.'.format(name))
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(boto_elasticache.absent(name), ret)
|
||||
|
||||
with patch.dict(boto_elasticache.__opts__, {'test': True}):
|
||||
comt = ('Cache cluster {0} is set to be removed.'.format(name))
|
||||
ret.update({'comment': comt, 'result': None})
|
||||
self.assertDictEqual(boto_elasticache.absent(name), ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(BotoElasticacheTestCase, needs_daemon=False)
|
142
tests/unit/states/boto_elb_test.py
Normal file
142
tests/unit/states/boto_elb_test.py
Normal file
@ -0,0 +1,142 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
|
||||
'''
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
import copy
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from salttesting import skipIf, TestCase
|
||||
from salttesting.mock import (
|
||||
NO_MOCK,
|
||||
NO_MOCK_REASON,
|
||||
MagicMock,
|
||||
patch)
|
||||
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
|
||||
ensure_in_syspath('../../')
|
||||
|
||||
# Import Salt Libs
|
||||
from salt.states import boto_elb
|
||||
|
||||
boto_elb.__salt__ = {}
|
||||
boto_elb.__opts__ = {}
|
||||
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class BotoElbTestCase(TestCase):
|
||||
'''
|
||||
Test cases for salt.states.boto_elb
|
||||
'''
|
||||
# 'present' function tests: 1
|
||||
|
||||
def test_present(self):
|
||||
'''
|
||||
Test to ensure the IAM role exists.
|
||||
'''
|
||||
name = 'myelb'
|
||||
listeners = [{'elb_port': 'ELBPORT', 'instance_port': 'PORT',
|
||||
'elb_protocol': 'HTTPS', 'certificate': 'A'}]
|
||||
attributes = {'alarm_actions': ['arn:aws:sns:us-east-1:12345:myalarm'],
|
||||
'insufficient_data_actions': [],
|
||||
'ok_actions': ['arn:aws:sns:us-east-1:12345:myalarm']}
|
||||
avail_zones = ['us-east-1a', 'us-east-1c', 'us-east-1d']
|
||||
alarms = {'alarm_actions': {'name': name,
|
||||
'attributes': {'description': 'A'}}}
|
||||
|
||||
ret = {'name': name,
|
||||
'result': False,
|
||||
'changes': {},
|
||||
'comment': ''}
|
||||
ret1 = copy.deepcopy(ret)
|
||||
|
||||
mock = MagicMock(return_value={})
|
||||
mock_bool = MagicMock(return_value=False)
|
||||
with patch.dict(boto_elb.__salt__,
|
||||
{'config.option': mock,
|
||||
'boto_elb.exists': mock_bool,
|
||||
'boto_elb.create': mock_bool,
|
||||
'boto_elb.get_attributes': mock}):
|
||||
with patch.dict(boto_elb.__opts__, {'test': False}):
|
||||
comt = (' Failed to create myelb ELB.')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(boto_elb.present
|
||||
(name, listeners, attributes=attributes,
|
||||
availability_zones=avail_zones), ret)
|
||||
|
||||
mock = MagicMock(return_value={})
|
||||
mock_ret = MagicMock(return_value={'result': {'result': False}})
|
||||
comt1 = (' Failed to retrieve health_check for ELB myelb.')
|
||||
with patch.dict(boto_elb.__salt__,
|
||||
{'config.option': mock,
|
||||
'boto_elb.get_attributes': mock,
|
||||
'boto_elb.get_health_check': mock,
|
||||
'boto_elb.get_elb_config': mock,
|
||||
'state.single': mock_ret}):
|
||||
with patch.dict(boto_elb.__opts__, {'test': False}):
|
||||
ret1.update({'result': True})
|
||||
mock_elb_present = MagicMock(return_value=ret1)
|
||||
with patch.object(boto_elb, '_elb_present', mock_elb_present):
|
||||
comt = (' Failed to retrieve attributes for ELB myelb.')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(boto_elb.present
|
||||
(name, listeners), ret)
|
||||
|
||||
with patch.object(boto_elb, '_attributes_present',
|
||||
mock_elb_present):
|
||||
ret.update({'comment': comt1})
|
||||
self.assertDictEqual(boto_elb.present
|
||||
(name, listeners), ret)
|
||||
|
||||
with patch.object(boto_elb, '_health_check_present',
|
||||
mock_elb_present):
|
||||
comt = (' Failed to retrieve ELB myelb.')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(boto_elb.present
|
||||
(name, listeners), ret)
|
||||
|
||||
with patch.object(boto_elb, '_cnames_present',
|
||||
mock_elb_present):
|
||||
comt = (' ')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(boto_elb.present
|
||||
(name, listeners,
|
||||
alarms=alarms), ret)
|
||||
|
||||
with patch.object(boto_elb, '_alarms_present',
|
||||
mock_elb_present):
|
||||
ret.update({'result': True})
|
||||
self.assertDictEqual(boto_elb.present
|
||||
(name, listeners,
|
||||
alarms=alarms), ret)
|
||||
|
||||
# 'absent' function tests: 1
|
||||
|
||||
def test_absent(self):
|
||||
'''
|
||||
Test to ensure the IAM role is deleted.
|
||||
'''
|
||||
name = 'new_table'
|
||||
|
||||
ret = {'name': name,
|
||||
'result': True,
|
||||
'changes': {},
|
||||
'comment': ''}
|
||||
|
||||
mock = MagicMock(side_effect=[False, True])
|
||||
with patch.dict(boto_elb.__salt__, {'boto_elb.exists': mock}):
|
||||
comt = ('{0} ELB does not exist.'.format(name))
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(boto_elb.absent(name), ret)
|
||||
|
||||
with patch.dict(boto_elb.__opts__, {'test': True}):
|
||||
comt = ('ELB {0} is set to be removed.'.format(name))
|
||||
ret.update({'comment': comt, 'result': None})
|
||||
self.assertDictEqual(boto_elb.absent(name), ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(BotoElbTestCase, needs_daemon=False)
|
Loading…
Reference in New Issue
Block a user