]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Get rid of Resource.calculate_properties()
authorZane Bitter <zbitter@redhat.com>
Mon, 5 Nov 2012 16:30:57 +0000 (17:30 +0100)
committerZane Bitter <zbitter@redhat.com>
Mon, 5 Nov 2012 16:42:00 +0000 (17:42 +0100)
Use the new Properties class to lazily load property values so that we
always get the latest data, and get rid of the stateful hacks.

Change-Id: I02a1b927606da217d4adab1ca04b659abadda2ce
Signed-off-by: Zane Bitter <zbitter@redhat.com>
heat/engine/checkeddict.py
heat/engine/parser.py
heat/engine/resources/autoscaling.py
heat/engine/resources/instance.py
heat/engine/resources/resource.py
heat/engine/resources/user.py
heat/engine/resources/wait_condition.py
heat/tests/test_engine_service.py
heat/tests/test_loadbalancer.py
heat/tests/test_quantum.py
heat/tests/unit/test_checkeddict.py

index daef65867f109e7437d4956a2b742f14588450c7..f2b3b14cb619a345dcd040064a2f9326cbef9d03 100644 (file)
@@ -95,8 +95,10 @@ class CheckedDict(collections.MutableMapping):
                     raise ValueError('%s: %s Value must be a map' %
                                      (self.name, key))
                 if 'Schema' in self.data[key]:
-                    cdict = Properties(key, self.data[key]['Schema'])
-                    cdict.data = self.data[key]['Schema']
+                    cdict = CheckedDict(key)
+                    schema = self.data[key]['Schema']
+                    for n, s in schema.items():
+                        cdict.addschema(n, s)
                     for k, v in value.items():
                         cdict[k] = v
 
@@ -106,7 +108,10 @@ class CheckedDict(collections.MutableMapping):
                                      (self.name, key, value))
                 if 'Schema' in self.data[key]:
                     for item in value:
-                        cdict = Properties(key, self.data[key]['Schema'])
+                        cdict = CheckedDict(key)
+                        schema = self.data[key]['Schema']
+                        for n, s in schema.items():
+                            cdict.addschema(n, s)
                         for k, v in item.items():
                             cdict[k] = v
 
@@ -152,29 +157,3 @@ class CheckedDict(collections.MutableMapping):
 
     def __delitem__(self, k):
         del self.data[k]
-
-
-class Properties(CheckedDict):
-    def __init__(self, name, schema):
-        CheckedDict.__init__(self, name)
-        self.data = deepcopy(schema)
-
-        # set some defaults
-        for s in self.data:
-            if not 'Implemented' in self.data[s]:
-                self.data[s]['Implemented'] = True
-            if not 'Required' in self.data[s]:
-                self.data[s]['Required'] = False
-
-    def validate(self):
-        for key in self.data:
-            # are there missing required Properties
-            if 'Required' in self.data[key]:
-                if self.data[key]['Required'] \
-                    and not 'Value' in self.data[key]:
-                    return '%s Property must be provided' % key
-
-            # are there unimplemented Properties
-            if not self.data[key]['Implemented'] and 'Value' in self.data[key]:
-                return '%s Property not implemented yet' % key
-        return None
index ecde0ea5fa567ae69cdff455ad2ed84e25d40d3f..2fc045d744bc5e0cf2c673e1a316fe766b3433b3 100644 (file)
@@ -264,9 +264,6 @@ class Stack(object):
         failures = []
         with eventlet.Timeout(self.timeout_mins * 60) as tmo:
             try:
-                for res in self:
-                    res.calculate_properties()
-
                 # First delete any resources which are not in newstack
                 for res in reversed(self):
                     if not res.name in newstack.keys():
@@ -366,9 +363,6 @@ class Stack(object):
         '''
         self.state_set(self.DELETE_IN_PROGRESS, 'Stack deletion started')
 
-        for res in self:
-            res.calculate_properties()
-
         failures = []
         for res in reversed(self):
             result = res.destroy()
@@ -399,9 +393,6 @@ class Stack(object):
         deps = self.dependencies[self[resource_name]]
         failed = False
 
-        for res in self:
-            res.calculate_properties()
-
         for res in reversed(deps):
             try:
                 res.destroy()
index 774a02f347834bc4dbf3ca450ea7496ed2d5f582..a5161a88c597afc99ad4ca1f21b26b86e305e815 100644 (file)
@@ -77,8 +77,6 @@ class AutoScalingGroup(resource.Resource):
                 inst.destroy()
 
     def adjust(self, adjustment, adjustment_type='ChangeInCapacity'):
-        self.calculate_properties()
-
         inst_list = []
         if self.instance_id is not None:
             inst_list = sorted(self.instance_id.split(','))
@@ -190,7 +188,6 @@ class ScalingPolicy(resource.Resource):
         super(ScalingPolicy, self).__init__(name, json_snippet, stack)
 
     def alarm(self):
-        self.calculate_properties()
         group = self.stack.resources[self.properties['AutoScalingGroupName']]
 
         logger.info('%s Alarm, adjusting Group %s by %s' %
index 076d68145631207adb04425d4bf7716f181f2bfe..c6697a8665186b4df959bad7f488812375ee8278 100644 (file)
@@ -47,7 +47,6 @@ class Restarter(resource.Resource):
         return None
 
     def alarm(self):
-        self.calculate_properties()
         victim = self._find_resource(self.properties['InstanceId'])
 
         if victim is None:
index 28681ceddab1199fbbefd39f77c01601cfc4d631..186f5880121577ebe5153dbeb1745b37bf648fb7 100644 (file)
@@ -37,8 +37,8 @@ except ImportError:
 from heat.common import exception
 from heat.common import config
 from heat.db import api as db_api
-from heat.engine import checkeddict
 from heat.engine import timestamp
+from heat.engine.resources.properties import Properties
 
 from heat.openstack.common import log as logging
 from heat.openstack.common import cfg
@@ -114,7 +114,10 @@ class Resource(object):
         self.context = stack.context
         self.name = name
         self.t = stack.resolve_static_data(json_snippet)
-        self.properties = checkeddict.Properties(name, self.properties_schema)
+        self.properties = Properties(self.properties_schema,
+                                     self.t.get('Properties', {}),
+                                     self.stack.resolve_runtime_data,
+                                     self.name)
 
         resource = db_api.resource_get_by_name_and_stack(self.context,
                                                          name, stack.id)
@@ -321,10 +324,6 @@ class Resource(object):
 
         return self._quantum
 
-    def calculate_properties(self):
-        for p, v in self.parsed_template('Properties').items():
-            self.properties[p] = v
-
     def create(self):
         '''
         Create the resource. Subclasses should provide a handle_create() method
@@ -336,7 +335,6 @@ class Resource(object):
         logger.info('creating %s' % str(self))
 
         try:
-            self.calculate_properties()
             self.properties.validate()
             self.state_set(self.CREATE_IN_PROGRESS)
             if callable(getattr(self, 'handle_create', None)):
@@ -365,9 +363,6 @@ class Resource(object):
         try:
             self.state_set(self.UPDATE_IN_PROGRESS)
             self.t = self.stack.resolve_static_data(json_snippet)
-            self.properties = checkeddict.Properties(self.name,
-                                                     self.properties_schema)
-            self.calculate_properties()
             self.properties.validate()
             if callable(getattr(self, 'handle_update', None)):
                 result = self.handle_update()
@@ -394,10 +389,6 @@ class Resource(object):
     def validate(self):
         logger.info('Validating %s' % str(self))
 
-        try:
-            self.calculate_properties()
-        except ValueError as ex:
-                return str(ex)
         return self.properties.validate()
 
     def delete(self):
@@ -476,7 +467,6 @@ class Resource(object):
 
     def _add_event(self, new_state, reason):
         '''Add a state change event to the database'''
-        self.calculate_properties()
         ev = {'logical_resource_id': self.name,
               'physical_resource_id': self.instance_id,
               'stack_id': self.stack.id,
index 40b8e796618cba4132ed0522f0b6e2988317afce..16a6ac102778b7d0cb4af148f4eee248f9993915 100644 (file)
@@ -199,7 +199,6 @@ class AccessKey(resource.Resource):
     def FnGetAtt(self, key):
         res = None
         log_res = None
-        self.calculate_properties()
         if key == 'UserName':
             res = self.properties['UserName']
             log_res = res
index 20073ddc7bd5602ea8fe8bdbc68bed22ef5f02d1..74d5c7dc00255fdd6a34ff18c5d78ae8f78751b3 100644 (file)
@@ -86,7 +86,6 @@ class WaitCondition(resource.Resource):
 
     def _get_handle_resource_id(self):
         if self.resource_id is None:
-            self.calculate_properties()
             handle_url = self.properties['Handle']
             self.resource_id = handle_url.split('/')[-1]
         return self.resource_id
index c19970a533d26d36919e41389db94bf43afaf2dc..9dde968429cba39b3f00eeec58bafe08b9dd9d83 100644 (file)
@@ -70,7 +70,6 @@ def setup_mocks(mocks, stack):
     instances.Instance.nova().MultipleTimes().AndReturn(fc)
 
     instance = stack.resources['WebServer']
-    instance.calculate_properties()
     server_userdata = instance._build_userdata(instance.properties['UserData'])
     mocks.StubOutWithMock(fc.servers, 'create')
     fc.servers.create(image=744, flavor=3, key_name='test',
index 4c2c22aa3be07976b50fa0d1fc0ecb8d33a118da..5f8f12fb8ec4bd201364f8c743f89d20e1252399 100644 (file)
@@ -105,7 +105,7 @@ class LoadBalancerTest(unittest.TestCase):
             'UnhealthyThreshold': '5',
             'Interval': '30',
             'Timeout': '5'}
-        resource.properties['HealthCheck'] = hc
+        resource.t['Properties']['HealthCheck'] = hc
         self.assertEqual(None, resource.validate())
 
         hc['Timeout'] = 35
index 9091cca696b77700ddd0c918c18440cb5747324f..40776b0309405a420e2c59041e04226341eed055 100644 (file)
@@ -24,7 +24,7 @@ import json
 from nose.plugins.attrib import attr
 
 from heat.common import exception
-from heat.engine import checkeddict
+from heat.engine.resources import properties
 from heat.engine.resources.quantum import net
 from heat.engine.resources.quantum.quantum import QuantumResource as qr
 from heat.engine import parser
@@ -104,12 +104,12 @@ class QuantumTest(unittest.TestCase):
         return resource
 
     def test_validate_properties(self):
-        p = checkeddict.Properties('foo', net.Net.properties_schema)
         vs = {'router:external': True}
-        p.update({
+        data = {
             'admin_state_up': False,
             'value_specs': vs
-        })
+        }
+        p = properties.Properties(net.Net.properties_schema, data)
         self.assertEqual(None, qr.validate_properties(p))
 
         vs['shared'] = True
@@ -131,11 +131,11 @@ class QuantumTest(unittest.TestCase):
         self.assertEqual(None, qr.validate_properties(p))
 
     def test_prepare_properties(self):
-        p = checkeddict.Properties('foo', net.Net.properties_schema)
-        p.update({
+        data = {
             'admin_state_up': False,
             'value_specs': {'router:external': True}
-        })
+        }
+        p = properties.Properties(net.Net.properties_schema, data)
         props = qr.prepare_properties(p, 'resource_name')
         self.assertEqual({
             'name': 'resource_name',
index a00fbd3e2794c3180b97832d452fa8814766c86f..e1ec6a445f3f710bdbf0b49412ab885d71a12694 100644 (file)
@@ -110,7 +110,9 @@ class CheckedDictTest(unittest.TestCase):
                           'Schema': listeners_schema}
         }
 
-        cd = checkeddict.Properties('nested', properties_schema)
+        cd = checkeddict.CheckedDict('nested')
+        for p, s in properties_schema.items():
+            cd.addschema(p, s)
 
         hc = {'HealthyThreshold': 'bla', 'Interval': '45'}
         self.assertRaises(ValueError, cd.__setitem__, 'HealthCheck', hc)