From: Clint Byrum Date: Fri, 6 Sep 2013 03:00:56 +0000 (-0700) Subject: Stop stack updates from exceeding resource limit X-Git-Tag: 2014.1~16^2 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=89bb14f49996c7a2bfe76d0067c46823be77b675;p=openstack-build%2Fheat-build.git Stop stack updates from exceeding resource limit Previous patches raise an error when a newly created stack would exceed the limit. This one applies the same logic during an update. Note that nested stack updates will be handled in another patch. Change-Id: Ic5d32501f582640cb77629b902c32c8cb9c20b42 Partial-Bug: #1215100 --- diff --git a/heat/engine/service.py b/heat/engine/service.py index 9241c8d2..f5cddd83 100644 --- a/heat/engine/service.py +++ b/heat/engine/service.py @@ -300,6 +300,8 @@ class EngineService(service.Service): # Now parse the template and any parameters for the updated # stack definition. tmpl = parser.Template(template, files=files) + if len(tmpl[tpl.RESOURCES]) > cfg.CONF.max_resources_per_stack: + raise exception.StackResourceLimitExceeded() stack_name = current_stack.name common_params = api.extract_args(args) env = environment.Environment(params) diff --git a/heat/tests/test_engine_service.py b/heat/tests/test_engine_service.py index 46829da4..f9d8f70d 100644 --- a/heat/tests/test_engine_service.py +++ b/heat/tests/test_engine_service.py @@ -578,6 +578,76 @@ class StackServiceCreateUpdateDeleteTest(HeatTestCase): self.assertTrue(result['stack_id']) self.m.VerifyAll() + def test_stack_update_equals(self): + stack_name = 'test_stack_update_equals_resource_limit' + params = {} + res._register_class('GenericResourceType', + generic_rsrc.GenericResource) + tpl = {'Resources': { + 'A': {'Type': 'GenericResourceType'}, + 'B': {'Type': 'GenericResourceType'}, + 'C': {'Type': 'GenericResourceType'}}} + + template = parser.Template(tpl) + + old_stack = parser.Stack(self.ctx, stack_name, template) + sid = old_stack.store() + s = db_api.stack_get(self.ctx, sid) + + stack = parser.Stack(self.ctx, stack_name, template) + + self.m.StubOutWithMock(parser, 'Stack') + self.m.StubOutWithMock(parser.Stack, 'load') + parser.Stack.load(self.ctx, stack=s).AndReturn(old_stack) + + self.m.StubOutWithMock(parser, 'Template') + self.m.StubOutWithMock(environment, 'Environment') + + parser.Template(template, files=None).AndReturn(stack.t) + environment.Environment(params).AndReturn(stack.env) + parser.Stack(self.ctx, stack.name, + stack.t, stack.env).AndReturn(stack) + + self.m.StubOutWithMock(stack, 'validate') + stack.validate().AndReturn(None) + + self.m.StubOutWithMock(threadgroup, 'ThreadGroup') + threadgroup.ThreadGroup().AndReturn(DummyThreadGroup()) + + self.m.ReplayAll() + + cfg.CONF.set_override('max_resources_per_stack', 3) + + result = self.man.update_stack(self.ctx, old_stack.identifier(), + template, params, None, {}) + self.assertEqual(old_stack.identifier(), result) + self.assertTrue(isinstance(result, dict)) + self.assertTrue(result['stack_id']) + self.assertEquals(3, old_stack.root_stack.total_resources()) + self.m.VerifyAll() + + def test_stack_update_exceeds_resource_limit(self): + stack_name = 'test_stack_update_exceeds_resource_limit' + params = {} + res._register_class('GenericResourceType', + generic_rsrc.GenericResource) + tpl = {'Resources': { + 'A': {'Type': 'GenericResourceType'}, + 'B': {'Type': 'GenericResourceType'}, + 'C': {'Type': 'GenericResourceType'}}} + + template = parser.Template(tpl) + + old_stack = parser.Stack(self.ctx, stack_name, template) + sid = old_stack.store() + s = db_api.stack_get(self.ctx, sid) + + cfg.CONF.set_override('max_resources_per_stack', 2) + + self.assertRaises(exception.StackResourceLimitExceeded, + self.man.update_stack, self.ctx, + old_stack.identifier(), template, params, None, {}) + def test_stack_update_verify_err(self): stack_name = 'service_update_verify_err_test_stack' params = {'foo': 'bar'}