]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Split nested stack implementation into abstract and concrete
authorZane Bitter <zbitter@redhat.com>
Wed, 19 Dec 2012 18:31:32 +0000 (19:31 +0100)
committerZane Bitter <zbitter@redhat.com>
Wed, 19 Dec 2012 18:51:09 +0000 (19:51 +0100)
Split the Stack resource class into an abstract part from which other
resource types inherit and a concrete implementation of the
AWS::CloudFormation::Stack resource type.

Change-Id: Ie7600b94e17ec31b55bae5c4d9501d3f0cbca97c
Signed-off-by: Zane Bitter <zbitter@redhat.com>
heat/engine/resources/dbinstance.py
heat/engine/resources/loadbalancer.py
heat/engine/resources/stack.py
heat/tests/test_dbinstance.py

index e2c1ea33318755f55a3788f6f7164daff9a6f6d8..ea6a8633b6175202ef145db16ce284ca549487c3 100644 (file)
@@ -220,7 +220,7 @@ class DBInstance(stack.Stack):
 
     def handle_create(self):
         templ = template_format.parse(mysql_template)
-        self.create_with_template(templ)
+        self.create_with_template(templ, self._params())
 
     def FnGetAtt(self, key):
         '''
index 19ea37c68c24926f125831df189de939fd2a5638..bcb3cae1589173400b7452a6c3a264f1a61b4f99 100644 (file)
@@ -200,12 +200,6 @@ class LoadBalancer(stack.Stack):
                     'Implemented': False}
     }
 
-    def _params(self):
-        # total hack - probably need an admin key here.
-        params = {'KeyName': {'Ref': 'KeyName'}}
-        p = self.stack.resolve_static_data(params)
-        return p
-
     def _instance_to_ipaddress(self, inst):
         '''
         Return the server's IP address, fetching it from Nova
@@ -291,7 +285,10 @@ class LoadBalancer(stack.Stack):
             cfg = self._haproxy_config(templ, self.properties['Instances'])
             files['/etc/haproxy/haproxy.cfg']['content'] = cfg
 
-        self.create_with_template(templ)
+        # total hack - probably need an admin key here.
+        param = self.stack.resolve_static_data({'KeyName': {'Ref': 'KeyName'}})
+
+        self.create_with_template(templ, param)
 
     def validate(self):
         '''
@@ -343,7 +340,7 @@ class LoadBalancer(stack.Stack):
                                                      key=key)
 
         if key == 'DNSName':
-            return stack.Stack.FnGetAtt(self, 'Outputs.PublicIp')
+            return self.get_output('PublicIp')
         else:
             return ''
 
index e66e5b37a5c179c5be867f4d1a0b20ebd49cd13a..6d912eb751dd11d7c962f042fdcf8c2a2b7d19f8 100644 (file)
@@ -30,19 +30,10 @@ logger = logging.getLogger(__name__)
 
 
 class Stack(resource.Resource):
-    properties_schema = {PROP_TEMPLATE_URL: {'Type': 'String',
-                                             'Required': True},
-                         PROP_TIMEOUT_MINS: {'Type': 'Number'},
-                         PROP_PARAMETERS: {'Type': 'Map'}}
-
     def __init__(self, name, json_snippet, stack):
         super(Stack, self).__init__(name, json_snippet, stack)
         self._nested = None
 
-    def _params(self):
-        p = self.stack.resolve_runtime_data(self.properties[PROP_PARAMETERS])
-        return p
-
     def nested(self):
         if self._nested is None and self.resource_id is not None:
             self._nested = parser.Stack.load(self.context,
@@ -53,13 +44,13 @@ class Stack(resource.Resource):
 
         return self._nested
 
-    def create_with_template(self, child_template):
+    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,
-                                   self._params())
+                                   user_params)
 
         self._nested = parser.Stack(self.context,
                                     self.physical_resource_name(),
@@ -72,11 +63,26 @@ class Stack(resource.Resource):
         if self._nested.state != self._nested.CREATE_COMPLETE:
             raise exception.Error(self._nested.state_description)
 
+    def get_output(self, op):
+        stack = self.nested()
+        if op not in stack.outputs:
+            raise exception.InvalidTemplateAttribute(
+                        resource=self.physical_resource_name(), key=key)
+
+        return stack.output(op)
+
+
+class NestedStack(Stack):
+    properties_schema = {PROP_TEMPLATE_URL: {'Type': 'String',
+                                             'Required': True},
+                         PROP_TIMEOUT_MINS: {'Type': 'Number'},
+                         PROP_PARAMETERS: {'Type': 'Map'}}
+
     def handle_create(self):
         template_data = urlfetch.get(self.properties[PROP_TEMPLATE_URL])
         template = template_format.parse(template_data)
 
-        self.create_with_template(template)
+        self.create_with_template(template, self.properties[PROP_PARAMETERS])
 
     def handle_update(self):
         return self.UPDATE_REPLACE
@@ -96,18 +102,10 @@ class Stack(resource.Resource):
                         resource=self.physical_resource_name(), key=key)
 
         prefix, dot, op = key.partition('.')
-        stack = self.nested()
-        if stack is None:
-            # This seems like a hack, to get past validation
-            return ''
-        if op not in stack.outputs:
-            raise exception.InvalidTemplateAttribute(
-                        resource=self.physical_resource_name(), key=key)
-
-        return stack.output(op)
+        return self.get_output(op)
 
 
 def resource_mapping():
     return {
-        'AWS::CloudFormation::Stack': Stack,
+        'AWS::CloudFormation::Stack': NestedStack,
     }
index 99d3c368a78f9fd68ea382d234ce5e1df2fd9d4e..6aca59cdf2e08dd13a4f6ab0e0c796ad96f7342b 100644 (file)
@@ -79,7 +79,19 @@ class DBInstanceTest(unittest.TestCase):
         class FakeNested:
             resources = {'DatabaseInstance': FakeDatabaseInstance()}
 
-        stack.Stack.create_with_template(mox.IgnoreArg()).AndReturn(None)
+        params = {
+            'AllocatedStorage': u'5',
+            'DBInstanceClass': u'db.m1.small',
+            'DBName': u'wordpress',
+            'DBSecurityGroups': [],
+            'KeyName': 'test',
+            'MasterUserPassword': u'admin',
+            'MasterUsername': u'admin',
+            'Port': '3306'
+        }
+
+        stack.Stack.create_with_template(mox.IgnoreArg(),
+                                         params).AndReturn(None)
 
         fn = FakeNested()
 
@@ -91,15 +103,6 @@ class DBInstanceTest(unittest.TestCase):
         s = self.parse_stack(t)
         resource = self.create_dbinstance(t, s, 'DatabaseServer')
 
-        self.assertEqual({'AllocatedStorage': u'5',
-            'DBInstanceClass': u'db.m1.small',
-            'DBName': u'wordpress',
-            'DBSecurityGroups': [],
-            'KeyName': 'test',
-            'MasterUserPassword': u'admin',
-            'MasterUsername': u'admin',
-            'Port': '3306'}, resource._params())
-
         self.assertEqual('0.0.0.0', resource.FnGetAtt('Endpoint.Address'))
         self.assertEqual('10.0.0.1', resource.FnGetAtt('Endpoint.Address'))
         self.assertEqual('3306', resource.FnGetAtt('Endpoint.Port'))