Rewrite AutoScalingGroup adjustment tests as unit tests

Change-Id: I1c752243ef981a19ff1572071f43e5eaebe3b0dc
part of blueprint decouple-nested
This commit is contained in:
Angus Salkeld 2014-10-02 15:40:09 +10:00
parent 90b8c3a69b
commit e0a94ce2b2
2 changed files with 96 additions and 291 deletions

View File

@ -17,8 +17,6 @@ import six
from heat.common import exception from heat.common import exception
from heat.common import template_format from heat.common import template_format
from heat.engine.resources import autoscaling as asc
from heat.engine import rsrc_defn
from heat.engine import scheduler from heat.engine import scheduler
from heat.tests.autoscaling import inline_templates from heat.tests.autoscaling import inline_templates
from heat.tests import common from heat.tests import common
@ -137,29 +135,106 @@ class TestAutoScalingGroupValidation(common.HeatTestCase):
self.assertEqual(expected_msg, six.text_type(e)) self.assertEqual(expected_msg, six.text_type(e))
self.m.VerifyAll() self.m.VerifyAll()
def test_child_template_uses_min_size(self):
class TestInitialGroupSize(common.HeatTestCase):
scenarios = [
('000', dict(mins=0, maxs=0, desired=0, expected=0)),
('040', dict(mins=0, maxs=4, desired=0, expected=0)),
('253', dict(mins=2, maxs=5, desired=3, expected=3)),
('14n', dict(mins=1, maxs=4, desired=None, expected=1)),
]
def setUp(self):
super(TestInitialGroupSize, self).setUp()
cfg.CONF.set_default('heat_waitcondition_server_url',
'http://server.test:8000/v1/waitcondition')
self.stub_keystoneclient()
def test_initial_size(self):
t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties']
properties['MinSize'] = self.mins
properties['MaxSize'] = self.maxs
properties['DesiredCapacity'] = self.desired
stack = utils.parse_stack(t, params=inline_templates.as_params)
group = stack['WebServerGroup']
with mock.patch.object(group, '_create_template') as mock_cre_temp:
group.child_template()
mock_cre_temp.assert_called_once_with(self.expected)
class TestGroupAdjust(common.HeatTestCase):
def setUp(self):
super(TestGroupAdjust, self).setUp()
cfg.CONF.set_default('heat_waitcondition_server_url',
'http://server.test:8000/v1/waitcondition')
self.stub_keystoneclient()
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = utils.parse_stack(t, params=inline_templates.as_params) stack = utils.parse_stack(t, params=inline_templates.as_params)
defn = rsrc_defn.ResourceDefinition( self.group = stack['WebServerGroup']
'asg', 'AWS::AutoScaling::AutoScalingGroup', self.assertIsNone(self.group.validate())
{'MinSize': 2, 'MaxSize': 5, 'LaunchConfigurationName': 'foo'})
rsrc = asc.AutoScalingGroup('asg', defn, stack)
rsrc._create_template = mock.Mock(return_value='tpl') def test_scaling_policy_cooldown_toosoon(self):
"""If _cooldown_inprogress() returns True don't progress."""
self.assertEqual('tpl', rsrc.child_template()) dont_call = self.patchobject(self.group, 'get_instances')
rsrc._create_template.assert_called_once_with(2) with mock.patch.object(self.group, '_cooldown_inprogress',
return_value=True):
self.group.adjust(1)
self.assertEqual([], dont_call.call_args_list)
def test_child_template_uses_desired_capacity(self): def test_scaling_policy_cooldown_ok(self):
t = template_format.parse(as_template) self.patchobject(self.group, 'get_instances', return_value=[])
stack = utils.parse_stack(t, params=inline_templates.as_params) resize = self.patchobject(self.group, 'resize')
defn = rsrc_defn.ResourceDefinition( cd_stamp = self.patchobject(self.group, '_cooldown_timestamp')
'asg', 'AWS::AutoScaling::AutoScalingGroup', notify = self.patch('heat.engine.notification.autoscaling.send')
{'MinSize': 2, 'MaxSize': 5, 'DesiredCapacity': 3, self.patchobject(self.group, '_cooldown_inprogress',
'LaunchConfigurationName': 'foo'}) return_value=False)
rsrc = asc.AutoScalingGroup('asg', defn, stack) self.group.adjust(1)
rsrc._create_template = mock.Mock(return_value='tpl') expected_notifies = [
mock.call(
capacity=0, suffix='start', adjustment_type='ChangeInCapacity',
groupname=u'WebServerGroup',
message=u'Start resizing the group WebServerGroup',
adjustment=1,
stack=self.group.stack),
mock.call(
capacity=1, suffix='end',
adjustment_type='ChangeInCapacity',
groupname=u'WebServerGroup',
message=u'End resizing the group WebServerGroup',
adjustment=1,
stack=self.group.stack)]
self.assertEqual('tpl', rsrc.child_template()) self.assertEqual(expected_notifies, notify.call_args_list)
rsrc._create_template.assert_called_once_with(3) resize.assert_called_once_with(1)
cd_stamp.assert_called_once_with('ChangeInCapacity : 1')
def test_scaling_policy_resize_fail(self):
self.patchobject(self.group, 'get_instances', return_value=[])
self.patchobject(self.group, 'resize',
side_effect=ValueError('test error'))
notify = self.patch('heat.engine.notification.autoscaling.send')
self.patchobject(self.group, '_cooldown_inprogress',
return_value=False)
self.assertRaises(ValueError, self.group.adjust, 1)
expected_notifies = [
mock.call(
capacity=0, suffix='start',
adjustment_type='ChangeInCapacity',
groupname=u'WebServerGroup',
message=u'Start resizing the group WebServerGroup',
adjustment=1,
stack=self.group.stack),
mock.call(
capacity=0, suffix='error',
adjustment_type='ChangeInCapacity',
groupname=u'WebServerGroup',
message=u'test error',
adjustment=1,
stack=self.group.stack)]
self.assertEqual(expected_notifies, notify.call_args_list)

View File

@ -248,61 +248,6 @@ class AutoScalingTest(common.HeatTestCase):
for x in range(nmeta): for x in range(nmeta):
resource.Resource.metadata_set(expected).AndReturn(None) resource.Resource.metadata_set(expected).AndReturn(None)
def test_scaling_delete_empty(self):
t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties']
properties['MinSize'] = '0'
properties['MaxSize'] = '0'
properties['DesiredCapacity'] = '0'
stack = utils.parse_stack(t, params=self.params)
self._stub_lb_reload(0)
self.stub_ImageConstraint_validate()
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertIsNone(rsrc.FnGetAtt("InstanceList"))
rsrc.delete()
self.m.VerifyAll()
def test_scaling_adjust_down_empty(self):
t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties']
properties['MinSize'] = '1'
properties['MaxSize'] = '1'
stack = utils.parse_stack(t, params=self.params)
self._stub_lb_reload(1)
now = timeutils.utcnow()
self._stub_meta_expected(now, 'ExactCapacity : 1')
self._stub_create(1)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
instance_names = rsrc.get_instance_names()
self.assertEqual(1, len(instance_names))
# Reduce the min size to 0, should complete without adjusting
props = copy.copy(rsrc.properties.data)
props['MinSize'] = '0'
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name,
rsrc.type(),
props)
scheduler.TaskRunner(rsrc.update, update_snippet)()
self.assertEqual(instance_names, rsrc.get_instance_names())
# trigger adjustment to reduce to 0, there should be no more instances
self._stub_lb_reload(0)
self._stub_scale_notification(adjust=-1, groupname=rsrc.FnGetRefId(),
start_capacity=1, end_capacity=0)
self._stub_meta_expected(now, 'ChangeInCapacity : -1')
self._stub_delete(1)
self.m.ReplayAll()
rsrc.adjust(-1)
self.assertEqual([], rsrc.get_instance_names())
rsrc.delete()
self.m.VerifyAll()
def test_scaling_group_update_replace(self): def test_scaling_group_update_replace(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
stack = utils.parse_stack(t, params=self.params) stack = utils.parse_stack(t, params=self.params)
@ -539,192 +484,6 @@ class AutoScalingTest(common.HeatTestCase):
self.m.VerifyAll() self.m.VerifyAll()
def test_scaling_group_update_ok_maxsize(self):
t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties']
properties['MinSize'] = '1'
properties['MaxSize'] = '3'
stack = utils.parse_stack(t, params=self.params)
self._stub_lb_reload(1)
now = timeutils.utcnow()
self._stub_meta_expected(now, 'ExactCapacity : 1')
self._stub_create(1)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual(1, len(rsrc.get_instance_names()))
instance_names = rsrc.get_instance_names()
# Reduce the max size to 2, should complete without adjusting
props = copy.copy(rsrc.properties.data)
props['MaxSize'] = '2'
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name,
rsrc.type(),
props)
scheduler.TaskRunner(rsrc.update, update_snippet)()
self.assertEqual(instance_names, rsrc.get_instance_names())
self.assertEqual(2, rsrc.properties['MaxSize'])
rsrc.delete()
self.m.VerifyAll()
def test_scaling_group_update_ok_minsize(self):
t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties']
properties['MinSize'] = '1'
properties['MaxSize'] = '3'
stack = utils.parse_stack(t, params=self.params)
self._stub_lb_reload(1)
now = timeutils.utcnow()
self._stub_meta_expected(now, 'ExactCapacity : 1')
self._stub_create(1)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual(1, len(rsrc.get_instance_names()))
# Increase min size to 2, should trigger an ExactCapacity adjust
self._stub_lb_reload(2)
self._stub_meta_expected(now, 'ExactCapacity : 1')
self._stub_create(1)
self.m.ReplayAll()
props = copy.copy(rsrc.properties.data)
props['MinSize'] = '2'
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name,
rsrc.type(),
props)
scheduler.TaskRunner(rsrc.update, update_snippet)()
self.assertEqual(2, len(rsrc.get_instance_names()))
self.assertEqual(2, rsrc.properties['MinSize'])
rsrc.delete()
self.m.VerifyAll()
def test_scaling_group_update_ok_desired(self):
t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties']
properties['MinSize'] = '1'
properties['MaxSize'] = '3'
stack = utils.parse_stack(t, params=self.params)
self._stub_lb_reload(1)
now = timeutils.utcnow()
self._stub_meta_expected(now, 'ExactCapacity : 1')
self._stub_create(1)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual(1, len(rsrc.get_instance_names()))
# Increase min size to 2 via DesiredCapacity, should adjust
self._stub_lb_reload(2)
self._stub_meta_expected(now, 'ExactCapacity : 2')
self._stub_create(1)
self.m.ReplayAll()
props = copy.copy(rsrc.properties.data)
props['DesiredCapacity'] = '2'
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name,
rsrc.type(),
props)
scheduler.TaskRunner(rsrc.update, update_snippet)()
self.assertEqual(2, len(rsrc.get_instance_names()))
self.assertEqual(2, rsrc.properties['DesiredCapacity'])
rsrc.delete()
self.m.VerifyAll()
def test_scaling_group_update_ok_desired_zero(self):
t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties']
properties['MinSize'] = '1'
properties['MaxSize'] = '3'
stack = utils.parse_stack(t, params=self.params)
self._stub_lb_reload(1)
now = timeutils.utcnow()
self._stub_meta_expected(now, 'ExactCapacity : 1')
self._stub_create(1)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual(1, len(rsrc.get_instance_names()))
# Increase min size to 2 via DesiredCapacity, should adjust
self._stub_lb_reload(0)
self._stub_meta_expected(now, 'ExactCapacity : 0')
self._stub_delete(1)
self.m.ReplayAll()
props = copy.copy(rsrc.properties.data)
props['MinSize'] = '0'
props['DesiredCapacity'] = '0'
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name,
rsrc.type(),
props)
scheduler.TaskRunner(rsrc.update, update_snippet)()
self.assertEqual(0, len(rsrc.get_instance_names()))
self.assertEqual(0, rsrc.properties['DesiredCapacity'])
rsrc.delete()
self.m.VerifyAll()
def test_scaling_group_update_ok_desired_remove(self):
t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties']
properties['DesiredCapacity'] = '2'
stack = utils.parse_stack(t, params=self.params)
self._stub_lb_reload(2)
now = timeutils.utcnow()
self._stub_meta_expected(now, 'ExactCapacity : 2')
self._stub_create(2)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual(2, len(rsrc.get_instance_names()))
instance_names = rsrc.get_instance_names()
# Remove DesiredCapacity from the updated template, which should
# have no effect, it's an optional parameter
props = copy.copy(rsrc.properties.data)
del props['DesiredCapacity']
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name,
rsrc.type(),
props)
scheduler.TaskRunner(rsrc.update, update_snippet)()
self.assertEqual(instance_names, rsrc.get_instance_names())
self.assertIsNone(rsrc.properties['DesiredCapacity'])
rsrc.delete()
self.m.VerifyAll()
def test_scaling_group_update_ok_cooldown(self):
t = template_format.parse(as_template)
properties = t['Resources']['WebServerGroup']['Properties']
properties['Cooldown'] = '60'
stack = utils.parse_stack(t, params=self.params)
self._stub_lb_reload(1)
now = timeutils.utcnow()
self._stub_meta_expected(now, 'ExactCapacity : 1')
self._stub_create(1)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual(utils.PhysName(stack.name, rsrc.name),
rsrc.FnGetRefId())
self.assertEqual(1, len(rsrc.get_instance_names()))
props = copy.copy(rsrc.properties.data)
props['Cooldown'] = '61'
update_snippet = rsrc_defn.ResourceDefinition(rsrc.name,
rsrc.type(),
props)
scheduler.TaskRunner(rsrc.update, update_snippet)()
self.assertEqual(61, rsrc.properties['Cooldown'])
rsrc.delete()
self.m.VerifyAll()
def test_lb_reload_static_resolve(self): def test_lb_reload_static_resolve(self):
t = template_format.parse(as_template) t = template_format.parse(as_template)
properties = t['Resources']['ElasticLoadBalancer']['Properties'] properties = t['Resources']['ElasticLoadBalancer']['Properties']
@ -829,35 +588,6 @@ class AutoScalingTest(common.HeatTestCase):
self.m.VerifyAll() self.m.VerifyAll()
def test_scaling_group_scale_up_failure(self):
t = template_format.parse(as_template)
stack = utils.parse_stack(t, params=self.params)
# Create initial group
self._stub_lb_reload(1)
now = timeutils.utcnow()
self._stub_meta_expected(now, 'ExactCapacity : 1')
self._stub_create(1)
self.m.ReplayAll()
rsrc = self.create_scaling_group(t, stack, 'WebServerGroup')
self.assertEqual(1, len(rsrc.get_instance_names()))
self.m.VerifyAll()
self.m.UnsetStubs()
# Scale up one 1 instance with resource failure
self._stub_create(1, with_error='Bang')
self._stub_lb_reload(1, unset=False, nochange=True)
self._stub_scale_notification(adjust=1,
groupname=rsrc.FnGetRefId(),
start_capacity=1,
with_error='Bang')
self.m.ReplayAll()
self.assertRaises(exception.Error, rsrc.adjust, 1)
self.assertEqual(1, len(rsrc.get_instance_names()))
self.m.VerifyAll()
def test_scaling_policy_bad_group(self): def test_scaling_policy_bad_group(self):
t = template_format.parse(as_template_bad_group) t = template_format.parse(as_template_bad_group)
stack = utils.parse_stack(t, params=self.params) stack = utils.parse_stack(t, params=self.params)