mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #27485 from lyft/boto-asg-scheduled-actions
Add scheduled actions (like scaleup/scaledown actions) to boto_asg
This commit is contained in:
commit
e103f53b4f
3 changed files with 243 additions and 61 deletions
|
@ -46,12 +46,14 @@ Connection module for Amazon Autoscale Groups
|
|||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
import datetime
|
||||
import logging
|
||||
import json
|
||||
import sys
|
||||
import email.mime.multipart
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
|
||||
|
||||
# Import third party libs
|
||||
import yaml
|
||||
|
@ -163,6 +165,22 @@ def get_config(name, region=None, key=None, keyid=None, profile=None):
|
|||
("cooldown", policy.cooldown)
|
||||
])
|
||||
)
|
||||
# scheduled actions
|
||||
actions = conn.get_all_scheduled_actions(as_group=name)
|
||||
ret['scheduled_actions'] = {}
|
||||
for action in actions:
|
||||
end_time = None
|
||||
if action.end_time:
|
||||
end_time = action.end_time.isoformat()
|
||||
ret['scheduled_actions'][action.name] = dict([
|
||||
("min_size", action.min_size),
|
||||
("max_size", action.max_size),
|
||||
# AWS bug
|
||||
("desired_capacity", int(action.desired_capacity)),
|
||||
("start_time", action.start_time.isoformat()),
|
||||
("end_time", end_time),
|
||||
("recurrence", action.recurrence)
|
||||
])
|
||||
return ret
|
||||
except boto.exception.BotoServerError as e:
|
||||
log.debug(e)
|
||||
|
@ -174,7 +192,7 @@ def create(name, launch_config_name, availability_zones, min_size, max_size,
|
|||
health_check_type=None, health_check_period=None,
|
||||
placement_group=None, vpc_zone_identifier=None, tags=None,
|
||||
termination_policies=None, suspended_processes=None,
|
||||
scaling_policies=None, region=None,
|
||||
scaling_policies=None, scheduled_actions=None, region=None,
|
||||
notification_arn=None, notification_types=None,
|
||||
key=None, keyid=None, profile=None):
|
||||
'''
|
||||
|
@ -215,6 +233,8 @@ def create(name, launch_config_name, availability_zones, min_size, max_size,
|
|||
termination_policies = json.loads(termination_policies)
|
||||
if isinstance(suspended_processes, six.string_types):
|
||||
suspended_processes = json.loads(suspended_processes)
|
||||
if isinstance(scheduled_actions, six.string_types):
|
||||
scheduled_actions = json.loads(scheduled_actions)
|
||||
try:
|
||||
_asg = autoscale.AutoScalingGroup(
|
||||
name=name, launch_config=launch_config_name,
|
||||
|
@ -231,6 +251,8 @@ def create(name, launch_config_name, availability_zones, min_size, max_size,
|
|||
conn.create_auto_scaling_group(_asg)
|
||||
# create scaling policies
|
||||
_create_scaling_policies(conn, name, scaling_policies)
|
||||
# create scheduled actions
|
||||
_create_scheduled_actions(conn, name, scheduled_actions)
|
||||
# create notifications
|
||||
if notification_arn and notification_types:
|
||||
conn.put_notification_configuration(_asg, notification_arn, notification_types)
|
||||
|
@ -248,7 +270,7 @@ def update(name, launch_config_name, availability_zones, min_size, max_size,
|
|||
health_check_type=None, health_check_period=None,
|
||||
placement_group=None, vpc_zone_identifier=None, tags=None,
|
||||
termination_policies=None, suspended_processes=None,
|
||||
scaling_policies=None,
|
||||
scaling_policies=None, scheduled_actions=None,
|
||||
notification_arn=None, notification_types=None,
|
||||
region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
|
@ -292,6 +314,8 @@ def update(name, launch_config_name, availability_zones, min_size, max_size,
|
|||
termination_policies = json.loads(termination_policies)
|
||||
if isinstance(suspended_processes, six.string_types):
|
||||
suspended_processes = json.loads(suspended_processes)
|
||||
if isinstance(scheduled_actions, six.string_types):
|
||||
scheduled_actions = json.loads(scheduled_actions)
|
||||
try:
|
||||
_asg = autoscale.AutoScalingGroup(
|
||||
connection=conn,
|
||||
|
@ -325,6 +349,13 @@ def update(name, launch_config_name, availability_zones, min_size, max_size,
|
|||
for policy in conn.get_all_policies(as_group=name):
|
||||
conn.delete_policy(policy.name, autoscale_group=name)
|
||||
_create_scaling_policies(conn, name, scaling_policies)
|
||||
# ### scheduled actions
|
||||
# delete all scheduled actions, then recreate them
|
||||
for scheduled_action in conn.get_all_scheduled_actions(as_group=name):
|
||||
conn.delete_scheduled_action(
|
||||
scheduled_action.name, autoscale_group=name
|
||||
)
|
||||
_create_scheduled_actions(conn, name, scheduled_actions)
|
||||
return True, ''
|
||||
except boto.exception.BotoServerError as e:
|
||||
log.debug(e)
|
||||
|
@ -347,6 +378,30 @@ def _create_scaling_policies(conn, as_name, scaling_policies):
|
|||
conn.create_scaling_policy(policy)
|
||||
|
||||
|
||||
def _create_scheduled_actions(conn, as_name, scheduled_actions):
|
||||
'''
|
||||
Helper function to create scheduled actions
|
||||
'''
|
||||
if scheduled_actions:
|
||||
for name, action in scheduled_actions.iteritems():
|
||||
if 'start_time' in action and isinstance(action['start_time'], six.string_types):
|
||||
action['start_time'] = datetime.datetime.strptime(
|
||||
action['start_time'], DATE_FORMAT
|
||||
)
|
||||
if 'end_time' in action and isinstance(action['end_time'], six.string_types):
|
||||
action['end_time'] = datetime.datetime.strptime(
|
||||
action['end_time'], DATE_FORMAT
|
||||
)
|
||||
conn.create_scheduled_group_action(as_name, name,
|
||||
desired_capacity=action.get('desired_capacity'),
|
||||
min_size=action.get('min_size'),
|
||||
max_size=action.get('max_size'),
|
||||
start_time=action.get('start_time'),
|
||||
end_time=action.get('end_time'),
|
||||
recurrence=action.get('recurrence')
|
||||
)
|
||||
|
||||
|
||||
def delete(name, force=False, region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
Delete an autoscale group.
|
||||
|
@ -527,14 +582,17 @@ def get_scaling_policy_arn(as_group, scaling_policy_name, region=None,
|
|||
return None
|
||||
|
||||
|
||||
def get_instances(name, lifecycle_state="InService", health_status="Healthy", attribute="private_ip_address", region=None, key=None, keyid=None, profile=None):
|
||||
"""return attribute of all instances in the named autoscale group.
|
||||
def get_instances(name, lifecycle_state="InService", health_status="Healthy",
|
||||
attribute="private_ip_address", region=None, key=None,
|
||||
keyid=None, profile=None):
|
||||
'''
|
||||
return attribute of all instances in the named autoscale group.
|
||||
|
||||
CLI example::
|
||||
|
||||
salt-call boto_asg.get_instances my_autoscale_group_name
|
||||
|
||||
"""
|
||||
'''
|
||||
conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
|
||||
ec2_conn = _get_ec2_conn(region=region, key=key, keyid=keyid, profile=profile)
|
||||
try:
|
||||
|
|
|
@ -197,6 +197,7 @@ Overriding the alarm values on the resource:
|
|||
from __future__ import absolute_import
|
||||
import hashlib
|
||||
import logging
|
||||
import copy
|
||||
|
||||
# Import Salt libs
|
||||
import salt.utils.dictupdate as dictupdate
|
||||
|
@ -233,7 +234,9 @@ def present(
|
|||
termination_policies=None,
|
||||
suspended_processes=None,
|
||||
scaling_policies=None,
|
||||
scaling_policies_from_pillar="boto_asg_scaling_policies",
|
||||
scaling_policies_from_pillar='boto_asg_scaling_policies',
|
||||
scheduled_actions=None,
|
||||
scheduled_actions_from_pillar='boto_asg_scheduled_actions',
|
||||
alarms=None,
|
||||
alarms_from_pillar='boto_asg_alarms',
|
||||
region=None,
|
||||
|
@ -241,9 +244,9 @@ def present(
|
|||
keyid=None,
|
||||
profile=None,
|
||||
notification_arn=None,
|
||||
notification_arn_from_pillar="boto_asg_notification_arn",
|
||||
notification_arn_from_pillar='boto_asg_notification_arn',
|
||||
notification_types=None,
|
||||
notification_types_from_pillar="boto_asg_notification_types"):
|
||||
notification_types_from_pillar='boto_asg_notification_types'):
|
||||
'''
|
||||
Ensure the autoscale group exists.
|
||||
|
||||
|
@ -251,17 +254,17 @@ def present(
|
|||
Name of the autoscale group.
|
||||
|
||||
launch_config_name
|
||||
Name of the launch config to use for the group. Or, if
|
||||
launch_config is specified, this will be the launch config
|
||||
name's prefix. (see below)
|
||||
Name of the launch config to use for the group. Or, if
|
||||
launch_config is specified, this will be the launch config
|
||||
name's prefix. (see below)
|
||||
|
||||
launch_config
|
||||
A dictionary of launch config attributes. If specified, a
|
||||
launch config will be used or created, matching this set
|
||||
of attributes, and the autoscale group will be set to use
|
||||
that launch config. The launch config name will be the
|
||||
launch_config_name followed by a hyphen followed by a hash
|
||||
of the launch_config dict contents.
|
||||
A dictionary of launch config attributes. If specified, a
|
||||
launch config will be used or created, matching this set
|
||||
of attributes, and the autoscale group will be set to use
|
||||
that launch config. The launch config name will be the
|
||||
launch_config_name followed by a hyphen followed by a hash
|
||||
of the launch_config dict contents.
|
||||
|
||||
availability_zones
|
||||
List of availability zones for the group.
|
||||
|
@ -322,11 +325,35 @@ def present(
|
|||
name of pillar dict that contains scaling policy settings. Scaling policies defined for
|
||||
this specific state will override those from pillar.
|
||||
|
||||
scheduled_actions:
|
||||
a dictionary of scheduled actions. Each key is the name of scheduled action and each value
|
||||
is dictionary of options. For example,
|
||||
- scheduled_actions:
|
||||
scale_up_at_10:
|
||||
desired_capacity: 4
|
||||
min_size: 3
|
||||
max_size: 5
|
||||
recurrence: "0 9 * * 1-5"
|
||||
scale_down_at_7:
|
||||
desired_capacity: 1
|
||||
min_size: 1
|
||||
max_size: 1
|
||||
recurrence: "0 19 * * 1-5"
|
||||
|
||||
scheduled_actions_from_pillar:
|
||||
name of pillar dict that contains scheduled_actions settings. Scheduled actions
|
||||
for this specific state will override those from pillar.
|
||||
|
||||
alarms:
|
||||
a dictionary of name->boto_cloudwatch_alarm sections to be associated with this ASG.
|
||||
All attributes should be specified except for dimension which will be
|
||||
automatically set to this ASG.
|
||||
See the boto_cloudwatch_alarm state for information about these attributes.
|
||||
if any alarm actions include ":self:" this will be replaced with the asg name.
|
||||
For example, alarm_actions reading "['scaling_policy:self:ScaleUp']" will
|
||||
map to the arn for this asg's scaling policy named "ScaleUp".
|
||||
In addition, any alarms that have only scaling_policy as actions will be ignored if
|
||||
min_size is equal to max_size for this ASG.
|
||||
|
||||
alarms_from_pillar:
|
||||
name of pillar dict that contains alarm settings. Alarms defined for this specific
|
||||
|
@ -367,7 +394,13 @@ def present(
|
|||
'''
|
||||
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
|
||||
if vpc_zone_identifier:
|
||||
vpc_id = __salt__['boto_vpc.get_subnet_association'](vpc_zone_identifier, region, key, keyid, profile)
|
||||
vpc_id = __salt__['boto_vpc.get_subnet_association'](
|
||||
vpc_zone_identifier,
|
||||
region,
|
||||
key,
|
||||
keyid,
|
||||
profile
|
||||
)
|
||||
log.debug('Auto Scaling Group {0} is associated with VPC ID {1}'
|
||||
.format(name, vpc_id))
|
||||
else:
|
||||
|
@ -405,8 +438,8 @@ def present(
|
|||
)
|
||||
launch_config[sg_index]['security_groups'] = _group_ids
|
||||
|
||||
for cfg in launch_config:
|
||||
args.update(cfg)
|
||||
for d in launch_config:
|
||||
args.update(d)
|
||||
if not __opts__['test']:
|
||||
lc_ret = __states__['boto_lc.present'](**args)
|
||||
if lc_ret['result'] is True and lc_ret['changes']:
|
||||
|
@ -415,6 +448,14 @@ def present(
|
|||
ret['changes']['launch_config'] = lc_ret['changes']
|
||||
|
||||
asg = __salt__['boto_asg.get_config'](name, region, key, keyid, profile)
|
||||
scaling_policies = _determine_scaling_policies(
|
||||
scaling_policies,
|
||||
scaling_policies_from_pillar
|
||||
)
|
||||
scheduled_actions = _determine_scheduled_actions(
|
||||
scheduled_actions,
|
||||
scheduled_actions_from_pillar
|
||||
)
|
||||
if asg is None:
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Failed to check autoscale group existence.'
|
||||
|
@ -430,10 +471,6 @@ def present(
|
|||
notification_types,
|
||||
notification_types_from_pillar
|
||||
)
|
||||
scaling_policies = _determine_scaling_policies(
|
||||
scaling_policies,
|
||||
scaling_policies_from_pillar
|
||||
)
|
||||
created = __salt__['boto_asg.create'](name, launch_config_name,
|
||||
availability_zones, min_size,
|
||||
max_size, desired_capacity,
|
||||
|
@ -444,8 +481,9 @@ def present(
|
|||
vpc_zone_identifier, tags,
|
||||
termination_policies,
|
||||
suspended_processes,
|
||||
scaling_policies, region,
|
||||
notification_arn, notification_types,
|
||||
scaling_policies, scheduled_actions,
|
||||
region, notification_arn,
|
||||
notification_types,
|
||||
key, keyid, profile)
|
||||
if created:
|
||||
ret['changes']['old'] = None
|
||||
|
@ -463,6 +501,10 @@ def present(
|
|||
for policy in scaling_policies:
|
||||
if 'min_adjustment_step' not in policy:
|
||||
policy['min_adjustment_step'] = None
|
||||
if scheduled_actions:
|
||||
for s_name, action in scheduled_actions.iteritems():
|
||||
if 'end_time' not in action:
|
||||
action['end_time'] = None
|
||||
config = {
|
||||
'launch_config_name': launch_config_name,
|
||||
'availability_zones': availability_zones,
|
||||
|
@ -477,13 +519,23 @@ def present(
|
|||
'termination_policies': termination_policies,
|
||||
'suspended_processes': suspended_processes,
|
||||
'scaling_policies': scaling_policies,
|
||||
'scheduled_actions': scheduled_actions
|
||||
}
|
||||
if suspended_processes is None:
|
||||
config['suspended_processes'] = []
|
||||
# ensure that we delete scaling_policies if none are specified
|
||||
if scaling_policies is None:
|
||||
config['scaling_policies'] = []
|
||||
# note: do not loop using 'key, value' - this can modify the value of
|
||||
# ensure that we delete scheduled_actions if none are specified
|
||||
if scheduled_actions is None:
|
||||
config['scheduled_actions'] = {}
|
||||
# allow defaults on start_time
|
||||
for s_name, action in scheduled_actions.iteritems():
|
||||
if 'start_time' not in action:
|
||||
asg_action = asg['scheduled_actions'].get(s_name, {})
|
||||
if 'start_time' in asg_action:
|
||||
del asg_action['start_time']
|
||||
# note: do not loop using "key, value" - this can modify the value of
|
||||
# the aws access key
|
||||
for asg_property, value in six.iteritems(config):
|
||||
# Only modify values being specified; introspection is difficult
|
||||
|
@ -511,10 +563,6 @@ def present(
|
|||
notification_types,
|
||||
notification_types_from_pillar
|
||||
)
|
||||
scaling_policies = _determine_scaling_policies(
|
||||
scaling_policies,
|
||||
scaling_policies_from_pillar
|
||||
)
|
||||
updated, msg = __salt__['boto_asg.update'](
|
||||
name,
|
||||
launch_config_name,
|
||||
|
@ -532,15 +580,23 @@ def present(
|
|||
termination_policies=termination_policies,
|
||||
suspended_processes=suspended_processes,
|
||||
scaling_policies=scaling_policies,
|
||||
scheduled_actions=scheduled_actions,
|
||||
region=region,
|
||||
notification_arn=notification_arn,
|
||||
notification_types=notification_types,
|
||||
region=region,
|
||||
key=key,
|
||||
keyid=keyid,
|
||||
profile=profile)
|
||||
profile=profile
|
||||
)
|
||||
if asg['launch_config_name'] != launch_config_name:
|
||||
# delete the old launch_config_name
|
||||
deleted = __salt__['boto_asg.delete_launch_configuration'](asg['launch_config_name'], region, key, keyid, profile)
|
||||
deleted = __salt__['boto_asg.delete_launch_configuration'](
|
||||
asg['launch_config_name'],
|
||||
region=region,
|
||||
key=key,
|
||||
keyid=keyid,
|
||||
profile=profile
|
||||
)
|
||||
if deleted:
|
||||
if 'launch_config' not in ret['changes']:
|
||||
ret['changes']['launch_config'] = {}
|
||||
|
@ -557,40 +613,69 @@ def present(
|
|||
else:
|
||||
ret['comment'] = 'Autoscale group present.'
|
||||
# add in alarms
|
||||
_ret = _alarms_present(name, alarms, alarms_from_pillar, region, key, keyid, profile)
|
||||
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
|
||||
_ret = _alarms_present(
|
||||
name, min_size == max_size, alarms, alarms_from_pillar, region, key,
|
||||
keyid, profile
|
||||
)
|
||||
if _ret['changes'] != {}:
|
||||
ret['result'] = _ret['result']
|
||||
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
|
||||
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
|
||||
return ret
|
||||
|
||||
|
||||
def _determine_scaling_policies(scaling_policies, scaling_policies_from_pillar):
|
||||
'''helper method for present. ensure that scaling_policies are set'''
|
||||
pillar_scaling_policies = __salt__['config.option'](scaling_policies_from_pillar, {})
|
||||
'''
|
||||
helper method for present. ensure that scaling_policies are set
|
||||
'''
|
||||
pillar_scaling_policies = copy.deepcopy(
|
||||
__salt__['config.option'](scaling_policies_from_pillar, {})
|
||||
)
|
||||
if not scaling_policies and len(pillar_scaling_policies) > 0:
|
||||
scaling_policies = pillar_scaling_policies
|
||||
return scaling_policies
|
||||
|
||||
|
||||
def _determine_notification_info(
|
||||
notification_arn,
|
||||
notification_arn_from_pillar,
|
||||
notification_types,
|
||||
notification_types_from_pillar):
|
||||
'''helper method for present. ensure that notification_configs are set'''
|
||||
pillar_arn_list = __salt__['config.option'](notification_arn_from_pillar, {})
|
||||
def _determine_scheduled_actions(scheduled_actions, scheduled_actions_from_pillar):
|
||||
'''
|
||||
helper method for present, ensure scheduled actions are setup
|
||||
'''
|
||||
tmp = copy.deepcopy(
|
||||
__salt__['config.option'](scheduled_actions_from_pillar, {})
|
||||
)
|
||||
# merge with data from state
|
||||
if scheduled_actions:
|
||||
tmp = dictupdate.update(tmp, scheduled_actions)
|
||||
return tmp
|
||||
|
||||
|
||||
def _determine_notification_info(notification_arn,
|
||||
notification_arn_from_pillar,
|
||||
notification_types,
|
||||
notification_types_from_pillar):
|
||||
'''
|
||||
helper method for present. ensure that notification_configs are set
|
||||
'''
|
||||
pillar_arn_list = copy.deepcopy(
|
||||
__salt__['config.option'](notification_arn_from_pillar, {})
|
||||
)
|
||||
pillar_arn = None
|
||||
if len(pillar_arn_list) > 0:
|
||||
pillar_arn = pillar_arn_list[0]
|
||||
pillar_notification_types = __salt__['config.option'](notification_types_from_pillar, {})
|
||||
pillar_notification_types = copy.deepcopy(
|
||||
__salt__['config.option'](notification_types_from_pillar, {})
|
||||
)
|
||||
arn = notification_arn if notification_arn else pillar_arn
|
||||
types = notification_types if notification_types else pillar_notification_types
|
||||
return (arn, types)
|
||||
|
||||
|
||||
def _alarms_present(name, alarms, alarms_from_pillar, region, key, keyid, profile):
|
||||
'''helper method for present. ensure that cloudwatch_alarms are set'''
|
||||
def _alarms_present(name, min_size_equals_max_size, alarms, alarms_from_pillar, region, key, keyid, profile):
|
||||
'''
|
||||
helper method for present. ensure that cloudwatch_alarms are set
|
||||
'''
|
||||
# load data from alarms_from_pillar
|
||||
tmp = __salt__['config.option'](alarms_from_pillar, {})
|
||||
tmp = copy.deepcopy(__salt__['config.option'](alarms_from_pillar, {}))
|
||||
# merge with data from alarms
|
||||
if alarms:
|
||||
tmp = dictupdate.update(tmp, alarms)
|
||||
|
@ -601,7 +686,23 @@ def _alarms_present(name, alarms, alarms_from_pillar, region, key, keyid, profil
|
|||
info['name'] = name + ' ' + info['name']
|
||||
info['attributes']['description'] = name + ' ' + info['attributes']['description']
|
||||
# add dimension attribute
|
||||
info['attributes']['dimensions'] = {'AutoScalingGroupName': [name]}
|
||||
if 'dimensions' not in info['attributes']:
|
||||
info['attributes']['dimensions'] = {'AutoScalingGroupName': [name]}
|
||||
scaling_policy_actions_only = True
|
||||
# replace ":self:" with our name
|
||||
for action_type in ['alarm_actions', 'insufficient_data_actions', 'ok_actions']:
|
||||
if action_type in info['attributes']:
|
||||
new_actions = []
|
||||
for action in info['attributes'][action_type]:
|
||||
if 'scaling_policy' not in action:
|
||||
scaling_policy_actions_only = False
|
||||
if ':self:' in action:
|
||||
action = action.replace(':self:', ':{0}:'.format(name))
|
||||
new_actions.append(action)
|
||||
info['attributes'][action_type] = new_actions
|
||||
# skip alarms that only have actions for scaling policy, if min_size == max_size for this ASG
|
||||
if scaling_policy_actions_only and min_size_equals_max_size:
|
||||
continue
|
||||
# set alarm
|
||||
kwargs = {
|
||||
'name': info['name'],
|
||||
|
|
|
@ -51,25 +51,48 @@ class BotoAsgTestCase(TestCase):
|
|||
with patch.dict(boto_asg.__opts__, {'test': True}):
|
||||
comt = ('Autoscale group set to be created.')
|
||||
ret.update({'comment': comt})
|
||||
self.assertDictEqual(boto_asg.present(name, launch_config_name,
|
||||
availability_zones,
|
||||
min_size, max_size), ret)
|
||||
with patch.dict(boto_asg.__salt__,
|
||||
{'config.option': MagicMock(return_value={})}):
|
||||
self.assertDictEqual(
|
||||
boto_asg.present(
|
||||
name,
|
||||
launch_config_name,
|
||||
availability_zones,
|
||||
min_size,
|
||||
max_size
|
||||
),
|
||||
ret
|
||||
)
|
||||
|
||||
comt = ('Autoscale group set to be updated.')
|
||||
ret.update({'comment': comt, 'result': None})
|
||||
self.assertDictEqual(boto_asg.present(name, launch_config_name,
|
||||
availability_zones,
|
||||
min_size, max_size), ret)
|
||||
with patch.dict(boto_asg.__salt__,
|
||||
{'config.option': MagicMock(return_value={})}):
|
||||
self.assertDictEqual(
|
||||
boto_asg.present(
|
||||
name,
|
||||
launch_config_name,
|
||||
availability_zones,
|
||||
min_size,
|
||||
max_size
|
||||
),
|
||||
ret
|
||||
)
|
||||
|
||||
with patch.dict(boto_asg.__salt__,
|
||||
{'config.option': MagicMock(return_value={})}):
|
||||
comt = ('Autoscale group present. ')
|
||||
ret.update({'comment': comt, 'result': True})
|
||||
self.assertDictEqual(boto_asg.present(name,
|
||||
launch_config_name,
|
||||
availability_zones,
|
||||
min_size, max_size),
|
||||
ret)
|
||||
self.assertDictEqual(
|
||||
boto_asg.present(
|
||||
name,
|
||||
launch_config_name,
|
||||
availability_zones,
|
||||
min_size,
|
||||
max_size
|
||||
),
|
||||
ret
|
||||
)
|
||||
|
||||
# 'absent' function tests: 1
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue