From: Zane Bitter Date: Tue, 15 Jan 2013 12:42:56 +0000 (+0100) Subject: Move abstract nested stack class to separate file X-Git-Tag: 2014.1~1006 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=9cc80fc737f01a61e3d1553b145ab6a432f36b54;p=openstack-build%2Fheat-build.git Move abstract nested stack class to separate file The class heat.engine.resources.stack.Stack is intended to be an abstract class which resources that are implemented as nested stacks may inherit from. Rename it to StackResource and move it to the heat.engine.stack_resource module, so that other resource modules (including plugins) may include it without having to also import the NestedStack class (which implements the AWS::CloudFormation::Stack resource type). Change-Id: Ie7c05ec64e1c9632c7a24d96b5d790c9e50b691f Signed-off-by: Zane Bitter --- diff --git a/heat/engine/resources/stack.py b/heat/engine/resources/stack.py index db99b438..c18ef612 100644 --- a/heat/engine/resources/stack.py +++ b/heat/engine/resources/stack.py @@ -14,9 +14,9 @@ # under the License. from heat.common import exception -from heat.common import template_format -from heat.engine import resource from heat.engine import parser +from heat.engine import stack_resource +from heat.common import template_format from heat.common import urlfetch from heat.openstack.common import log as logging @@ -29,61 +29,11 @@ logger = logging.getLogger(__name__) PROP_PARAMETERS) = ('TemplateURL', 'TimeoutInMinutes', 'Parameters') -class Stack(resource.Resource): - def __init__(self, name, json_snippet, stack): - super(Stack, self).__init__(name, json_snippet, stack) - self._nested = None - - def nested(self): - if self._nested is None and self.resource_id is not None: - self._nested = parser.Stack.load(self.context, - self.resource_id) - - if self._nested is None: - raise exception.NotFound('Nested stack not found in DB') - - return self._nested - - def create_with_template(self, child_template, user_params): - ''' - Handle the creation of the nested stack from a given JSON template. - ''' - template = parser.Template(child_template) - params = parser.Parameters(self.physical_resource_name(), template, - user_params) - - self._nested = parser.Stack(self.context, - self.physical_resource_name(), - template, - params) - - nested_id = self._nested.store(self.stack) - self.resource_id_set(nested_id) - self._nested.create() - if self._nested.state != self._nested.CREATE_COMPLETE: - raise exception.Error(self._nested.state_description) - - def delete_nested(self): - try: - stack = self.nested() - except exception.NotFound: - logger.info("Stack not found to delete") - else: - if stack is not None: - stack.delete() - - def get_output(self, op): - stack = self.nested() - if not stack: - return None - if op not in stack.outputs: - raise exception.InvalidTemplateAttribute( - resource=self.physical_resource_name(), key=key) - - return stack.output(op) - +class NestedStack(stack_resource.StackResource): + ''' + A Resource representing a child stack to allow composition of templates. + ''' -class NestedStack(Stack): properties_schema = {PROP_TEMPLATE_URL: {'Type': 'String', 'Required': True}, PROP_TIMEOUT_MINS: {'Type': 'Number'}, diff --git a/heat/engine/stack_resource.py b/heat/engine/stack_resource.py new file mode 100644 index 00000000..f392abb6 --- /dev/null +++ b/heat/engine/stack_resource.py @@ -0,0 +1,93 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from heat.common import exception +from heat.engine import resource +from heat.engine import parser + +from heat.openstack.common import log as logging + +logger = logging.getLogger(__name__) + + +class StackResource(resource.Resource): + ''' + An abstract Resource subclass that allows the management of an entire Stack + as a resource in a parent stack. + ''' + + def __init__(self, name, json_snippet, stack): + super(StackResource, self).__init__(name, json_snippet, stack) + self._nested = None + + def nested(self): + ''' + Return a Stack object representing the nested (child) stack. + ''' + if self._nested is None and self.resource_id is not None: + self._nested = parser.Stack.load(self.context, + self.resource_id) + + if self._nested is None: + raise exception.NotFound('Nested stack not found in DB') + + return self._nested + + def create_with_template(self, child_template, user_params): + ''' + Handle the creation of the nested stack from a given JSON template. + ''' + template = parser.Template(child_template) + params = parser.Parameters(self.physical_resource_name(), template, + user_params) + + self._nested = parser.Stack(self.context, + self.physical_resource_name(), + template, + params) + + nested_id = self._nested.store(self.stack) + self.resource_id_set(nested_id) + self._nested.create() + if self._nested.state != self._nested.CREATE_COMPLETE: + raise exception.Error(self._nested.state_description) + + def delete_nested(self): + ''' + Delete the nested stack. + ''' + try: + stack = self.nested() + except exception.NotFound: + logger.info("Stack not found to delete") + else: + if stack is not None: + stack.delete() + + def get_output(self, op): + ''' + Return the specified Output value from the nested stack. + + If the output key does not exist, raise an InvalidTemplateAttribute + exception. + ''' + stack = self.nested() + if not stack: + return None + if op not in stack.outputs: + raise exception.InvalidTemplateAttribute( + resource=self.physical_resource_name(), key=key) + + return stack.output(op) diff --git a/heat/tests/test_dbinstance.py b/heat/tests/test_dbinstance.py index 498e7df4..f99b8115 100644 --- a/heat/tests/test_dbinstance.py +++ b/heat/tests/test_dbinstance.py @@ -24,7 +24,6 @@ from heat.common import context from heat.common import exception from heat.common import template_format from heat.engine import parser -from heat.engine.resources import stack from heat.engine.resources import dbinstance as dbi @@ -33,7 +32,7 @@ from heat.engine.resources import dbinstance as dbi class DBInstanceTest(unittest.TestCase): def setUp(self): self.m = mox.Mox() - self.m.StubOutWithMock(stack.Stack, 'create_with_template') + self.m.StubOutWithMock(dbi.DBInstance, 'create_with_template') self.m.StubOutWithMock(dbi.DBInstance, 'nested') def tearDown(self): @@ -90,8 +89,8 @@ class DBInstanceTest(unittest.TestCase): 'Port': '3306' } - stack.Stack.create_with_template(mox.IgnoreArg(), - params).AndReturn(None) + dbi.DBInstance.create_with_template(mox.IgnoreArg(), + params).AndReturn(None) fn = FakeNested()