]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Improve the identifier class for Resources
authorZane Bitter <zbitter@redhat.com>
Thu, 22 Nov 2012 10:06:56 +0000 (11:06 +0100)
committerZane Bitter <zbitter@redhat.com>
Thu, 22 Nov 2012 11:03:30 +0000 (12:03 +0100)
Enable the resource name to be retrieved from an object. Also allow a
ResourceIdentifier to be constructed from only the data passed through the
RPC API. This means we can use a single format for identifiers, but still
be able to extract important information such as the stack identifier and
resource name.

Change-Id: Ie9122cb1a835b30eb8e0713a9d5cdcb4a386eda7
Signed-off-by: Zane Bitter <zbitter@redhat.com>
heat/api/openstack/v1/resources.py
heat/engine/identifier.py
heat/engine/resources/resource.py
heat/tests/test_api_openstack_v1.py
heat/tests/test_identifier.py

index 0cbaab2f6a1710796a0c84dbcaaa8f66b8129e32..3a16809e6fe92a603b2eb91885ec8024b2e3dc42 100644 (file)
@@ -31,7 +31,7 @@ def format_resource(req, stack, keys=[]):
             return
 
         if key == engine_api.RES_ID:
-            identity = identifier.HeatIdentifier(**value)
+            identity = identifier.ResourceIdentifier(**value)
             yield ('links', [util.make_link(req, identity),
                              util.make_link(req, identity.stack(), 'stack')])
         elif (key == engine_api.RES_STACK_NAME or
index 8cf71c1c01644c2ed75424530a3e2678eef08ab3..094fbc023d74fd5dba45a9f92452dab978fe18a8 100644 (file)
@@ -72,12 +72,6 @@ class HeatIdentifier(collections.Mapping):
                    urllib.unquote(path.group(2)),
                    urllib.unquote(path.group(3)))
 
-    def stack(self):
-        '''
-        Return a HeatIdentifier for the top-level stack
-        '''
-        return HeatIdentifier(self.tenant, self.stack_name, self.stack_id)
-
     def arn(self):
         '''
         Return an ARN of the form:
@@ -103,6 +97,10 @@ class HeatIdentifier(collections.Mapping):
                                    urllib.quote(self.stack_id, ''),
                                    urllib.quote(self.path))
 
+    def _path_components(self):
+        '''Return a list of the path components'''
+        return self.path.lstrip('/').split('/')
+
     def __getattr__(self, attr):
         '''
         Return one of the components of the identity when accessed as an
@@ -135,10 +133,37 @@ class HeatIdentifier(collections.Mapping):
 
 
 class ResourceIdentifier(HeatIdentifier):
-    def __init__(self, stack_identifier, resource_id):
-        path = (stack_identifier.path.rstrip('/') +
-                '/resources/%s' % resource_id)
-        super(ResourceIdentifier, self).__init__(stack_identifier.tenant,
-                                                 stack_identifier.stack_name,
-                                                 stack_identifier.stack_id,
+    '''An identifier for a resource'''
+
+    RESOURCE_NAME = 'resource_name'
+
+    def __init__(self, tenant, stack_name, stack_id, path,
+                 resource_name=None):
+        '''
+        Return a new Resource identifier based on the identifier components of
+        the owning stack and the resource name.
+        '''
+        if resource_name is not None:
+            path = '/'.join([path.rstrip('/'), 'resources', resource_name])
+        super(ResourceIdentifier, self).__init__(tenant,
+                                                 stack_name,
+                                                 stack_id,
                                                  path)
+
+    def __getattr__(self, attr):
+        '''
+        Return one of the components of the identity when accessed as an
+        attribute.
+        '''
+
+        if attr == self.RESOURCE_NAME:
+            return self._path_components()[-1]
+
+        return HeatIdentifier.__getattr__(self, attr)
+
+    def stack(self):
+        '''
+        Return a HeatIdentifier for the owning stack
+        '''
+        return HeatIdentifier(self.tenant, self.stack_name, self.stack_id,
+                              '/'.join(self._path_components()[:-2]))
index a7ed5315e8ac411652d6c5e1a421eea86a56cba9..bd91540e8bc316157d0c49888323cf3ff43d54b3 100644 (file)
@@ -134,8 +134,8 @@ class Resource(object):
 
     def identifier(self):
         '''Return an identifier for this resource'''
-        return identifier.ResourceIdentifier(self.stack.identifier(),
-                                             self.name)
+        return identifier.ResourceIdentifier(resource_name=self.name,
+                                             **self.stack.identifier())
 
     def parsed_template(self, section=None, default={}):
         '''
index 3ce7a842a67b75264c071fcf890099f8b4ee4940..f94ca97a0b1c4b63ac478a743fae9e51ae32af5a 100644 (file)
@@ -796,8 +796,8 @@ class ResourceControllerTest(ControllerTest, unittest.TestCase):
         res_name = 'WikiDatabase'
         stack_identity = identifier.HeatIdentifier(self.tenant,
                                                    'wordpress', '1')
-        res_identity = identifier.ResourceIdentifier(stack_identity,
-                                                     res_name)
+        res_identity = identifier.ResourceIdentifier(resource_name=res_name,
+                                                     **stack_identity)
 
         req = self._get(stack_identity._tenant_path() + '/resources')
 
@@ -873,8 +873,8 @@ class ResourceControllerTest(ControllerTest, unittest.TestCase):
         res_name = 'WikiDatabase'
         stack_identity = identifier.HeatIdentifier(self.tenant,
                                                    'wordpress', '6')
-        res_identity = identifier.ResourceIdentifier(stack_identity,
-                                                     res_name)
+        res_identity = identifier.ResourceIdentifier(resource_name=res_name,
+                                                     **stack_identity)
 
         req = self._get(stack_identity._tenant_path())
 
@@ -930,8 +930,8 @@ class ResourceControllerTest(ControllerTest, unittest.TestCase):
         res_name = 'WikiDatabase'
         stack_identity = identifier.HeatIdentifier(self.tenant,
                                                    'rubbish', '1')
-        res_identity = identifier.ResourceIdentifier(stack_identity,
-                                                     res_name)
+        res_identity = identifier.ResourceIdentifier(resource_name=res_name,
+                                                     **stack_identity)
 
         req = self._get(res_identity._tenant_path())
 
@@ -956,8 +956,8 @@ class ResourceControllerTest(ControllerTest, unittest.TestCase):
         res_name = 'WikiDatabase'
         stack_identity = identifier.HeatIdentifier(self.tenant,
                                                    'wordpress', '6')
-        res_identity = identifier.ResourceIdentifier(stack_identity,
-                                                     res_name)
+        res_identity = identifier.ResourceIdentifier(resource_name=res_name,
+                                                     **stack_identity)
 
         req = self._get(stack_identity._tenant_path())
 
@@ -998,8 +998,8 @@ class ResourceControllerTest(ControllerTest, unittest.TestCase):
         res_name = 'WikiDatabase'
         stack_identity = identifier.HeatIdentifier(self.tenant,
                                                    'rubbish', '1')
-        res_identity = identifier.ResourceIdentifier(stack_identity,
-                                                     res_name)
+        res_identity = identifier.ResourceIdentifier(resource_name=res_name,
+                                                     **stack_identity)
 
         req = self._get(res_identity._tenant_path() + '/metadata')
 
index 92eefb3ff46d27ebb4470a645e87e4e7b4e2f87c..632acbd31812b7eaa029b0e29a9df14895eb1cfa 100644 (file)
@@ -222,6 +222,10 @@ class IdentifierTest(unittest.TestCase):
                           'stack_name': 's',
                           'stack_id': 'i'} == hi1)
 
+    def test_path_components(self):
+        hi = identifier.HeatIdentifier('t', 's', 'i', 'p1/p2/p3')
+        self.assertEqual(hi._path_components(), ['p1', 'p2', 'p3'])
+
     def test_uuid_match(self):
         uuid = utils.generate_uuid()
         self.assertTrue(identifier.HeatIdentifier.is_uuid(uuid))
@@ -239,15 +243,29 @@ class IdentifierTest(unittest.TestCase):
 class ResourceIdentifierTest(unittest.TestCase):
     def test_resource_init_no_path(self):
         si = identifier.HeatIdentifier('t', 's', 'i')
-        ri = identifier.ResourceIdentifier(si, 'r')
+        ri = identifier.ResourceIdentifier(resource_name='r', **si)
         self.assertEqual(ri.path, '/resources/r')
 
     def test_resource_init_path(self):
         si = identifier.HeatIdentifier('t', 's', 'i')
-        pi = identifier.ResourceIdentifier(si, 'p')
-        ri = identifier.ResourceIdentifier(pi, 'r')
+        pi = identifier.ResourceIdentifier(resource_name='p', **si)
+        ri = identifier.ResourceIdentifier(resource_name='r', **pi)
         self.assertEqual(ri.path, '/resources/p/resources/r')
 
+    def test_resource_init_from_dict(self):
+        hi = identifier.HeatIdentifier('t', 's', 'i', '/resources/r')
+        ri = identifier.ResourceIdentifier(**hi)
+        self.assertEqual(ri, hi)
+
+    def test_resource_stack(self):
+        si = identifier.HeatIdentifier('t', 's', 'i')
+        ri = identifier.ResourceIdentifier(resource_name='r', **si)
+        self.assertEqual(ri.stack(), si)
+
+    def test_resource_id(self):
+        ri = identifier.ResourceIdentifier('t', 's', 'i', '', 'r')
+        self.assertEqual(ri.resource_name, 'r')
+
 
 # allows testing of the test directly, shown below
 if __name__ == '__main__':