]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Report StackId in ARN format
authorZane Bitter <zbitter@redhat.com>
Wed, 5 Sep 2012 19:51:25 +0000 (21:51 +0200)
committerZane Bitter <zbitter@redhat.com>
Wed, 5 Sep 2012 19:52:53 +0000 (21:52 +0200)
In the RPC API, return a full stack identifier instead of just the database
ID of a stack. In the AWS API, convert this to an ARN for the user.

Change-Id: I5c3ede4885c4ac5801cfef49e05695f3d13622da
Signed-off-by: Zane Bitter <zbitter@redhat.com>
heat/api/v1/stacks.py
heat/engine/api.py
heat/engine/manager.py
heat/tests/test_api_v1.py
heat/tests/test_engine_manager.py

index 9a2e1441241a441d37c9d8ad05ed752b81fe7553..f692d742952a67dd440048d28c914d3aa1cb9252 100644 (file)
@@ -31,6 +31,7 @@ from heat.common import context
 from heat import utils
 from heat.engine import rpcapi as engine_rpcapi
 import heat.engine.api as engine_api
+from heat.engine import identifier
 
 from heat.openstack.common import rpc
 import heat.openstack.common.rpc.common as rpc_common
@@ -50,16 +51,14 @@ class StackController(object):
         self.options = options
         self.engine_rpcapi = engine_rpcapi.EngineAPI()
 
-    def _stackid_addprefix(self, resp):
+    def _stackid_format(self, resp):
         """
         Add a host:port:stack prefix, this formats the StackId in the response
         more like the AWS spec
         """
         if 'StackId' in resp:
-            hostportprefix = ":".join([socket.gethostname(),
-                str(self.options.bind_port), "stack"])
-            resp['StackId'] = "/".join([hostportprefix, resp['StackName'],
-                                       str(resp['StackId'])])
+            identity = identifier.HeatIdentifier(**resp['StackId'])
+            resp['StackId'] = identity.arn()
         return resp
 
     @staticmethod
@@ -107,7 +106,7 @@ class StackController(object):
             if engine_api.STACK_DELETION_TIME in s:
                 result['DeletionTime'] = s[engine_api.STACK_DELETION_TIME]
 
-            return self._stackid_addprefix(result)
+            return self._stackid_format(result)
 
         con = req.context
         parms = dict(req.params)
@@ -176,7 +175,7 @@ class StackController(object):
                 'ParameterValue':v.get('Default')}
                 for (k, v) in result['Parameters'].items()]
 
-            return self._stackid_addprefix(result)
+            return self._stackid_format(result)
 
         con = req.context
         parms = dict(req.params)
@@ -299,7 +298,8 @@ class StackController(object):
         except rpc_common.RemoteError as ex:
             return exception.map_remote_error(ex)
 
-        return api_utils.format_response(action, self._stackid_addprefix(res))
+        identity = identifier.HeatIdentifier(**res)
+        return api_utils.format_response(action, {'StackId': identity.arn()})
 
     def get_template(self, req):
         """
@@ -411,7 +411,7 @@ class StackController(object):
 
             result = api_utils.reformat_dict_keys(keymap, e)
 
-            return self._stackid_addprefix(result)
+            return self._stackid_format(result)
 
         con = req.context
         parms = dict(req.params)
@@ -456,7 +456,7 @@ class StackController(object):
 
             result = api_utils.reformat_dict_keys(keymap, r)
 
-            return self._stackid_addprefix(result)
+            return self._stackid_format(result)
 
         con = req.context
 
@@ -508,7 +508,7 @@ class StackController(object):
 
             result = api_utils.reformat_dict_keys(keymap, r)
 
-            return self._stackid_addprefix(result)
+            return self._stackid_format(result)
 
         con = req.context
         stack_name = req.params.get('StackName')
index 05c3aaabdb5116ded76d16034739ebfc72ff0bad..5c25e72c2110499fb2f15fdcc7b075dfd18c5f24 100644 (file)
@@ -50,7 +50,7 @@ STACK_KEYS = (
     STACK_STATUS, STACK_STATUS_DATA, STACK_CAPABILITIES,
     STACK_DISABLE_ROLLBACK, STACK_TIMEOUT,
 ) = (
-    'stack_name', 'stack_id',
+    'stack_name', 'stack_identity',
     'creation_time', 'updated_time', 'deletion_time',
     'notification_topics',
     'description', 'template_description',
@@ -89,7 +89,7 @@ def format_stack(stack):
     '''
     info = {
         STACK_NAME: stack.name,
-        STACK_ID: stack.id,
+        STACK_ID: dict(stack.identifier()),
         STACK_CREATION_TIME: heat_utils.strtime(stack.created_time),
         STACK_UPDATED_TIME: heat_utils.strtime(stack.updated_time),
         STACK_NOTIFICATION_TOPICS: [],  # TODO Not implemented yet
@@ -138,7 +138,7 @@ def format_stack_resource(resource):
         RES_STATUS: resource.state,
         RES_STATUS_DATA: resource.state_description,
         RES_TYPE: resource.t['Type'],
-        RES_STACK_ID: resource.stack.id,
+        RES_STACK_ID: dict(resource.stack.identifier()),
         RES_STACK_NAME: resource.stack.name,
     }
 
@@ -162,12 +162,12 @@ EVENT_KEYS = (
 )
 
 
-def format_event(event):
-    s = event.stack
+def format_event(context, event):
+    stack = parser.Stack.load(context, event.stack.id)
     result = {
         EVENT_ID: event.id,
-        EVENT_STACK_ID: s.id,
-        EVENT_STACK_NAME: s.name,
+        EVENT_STACK_ID: dict(stack.identifier()),
+        EVENT_STACK_NAME: stack.name,
         EVENT_TIMESTAMP: heat_utils.strtime(event.created_at),
         EVENT_RES_NAME: event.logical_resource_id,
         EVENT_RES_PHYSICAL_ID: event.physical_resource_id,
index bf16842bf22e8e8dd4afd2daf8752cf7c0ebf1ad..a69564a1a55c0c8eff8d7e7a8190b89298708bf6 100644 (file)
@@ -120,7 +120,7 @@ class EngineManager(manager.Manager):
         stack_id = stack.store()
         greenpool.spawn_n(stack.create)
 
-        return {'StackName': stack.name, 'StackId': stack.id}
+        return dict(stack.identifier())
 
     def update_stack(self, context, stack_name, template, params, args):
         """
@@ -160,7 +160,7 @@ class EngineManager(manager.Manager):
 
         greenpool.spawn_n(current_stack.update, updated_stack)
 
-        return {'StackName': current_stack.name, 'StackId': current_stack.id}
+        return dict(current_stack.identifier())
 
     def validate_template(self, context, template, params):
         """
@@ -255,7 +255,7 @@ class EngineManager(manager.Manager):
         else:
             events = db_api.event_get_all_by_tenant(context)
 
-        return {'events': [api.format_event(e) for e in events]}
+        return {'events': [api.format_event(context, e) for e in events]}
 
     def event_create(self, context, event):
 
index 6e1a480a39069965c0d9e3b33a3cbd91f3d584fd..a0b90e4ba9dcffd913c8cbe395b0702910780b93 100644 (file)
@@ -61,17 +61,19 @@ class StackControllerTest(unittest.TestCase):
 
     # The tests
     def test_stackid_addprefix(self):
-
-        # Stub socket.gethostname so it returns "ahostname"
-        self.m.StubOutWithMock(socket, 'gethostname')
-        socket.gethostname().AndReturn("ahostname")
-
         self.m.ReplayAll()
 
-        response = self.controller._stackid_addprefix({'StackName': 'Foo',
-                                                       'StackId': str(123)})
+        response = self.controller._stackid_format({
+            'StackName': 'Foo',
+            'StackId': {
+                u'tenant': u't',
+                u'stack_name': u'Foo',
+                u'stack_id': u'123',
+                u'path': u''
+            }
+        })
         expected = {'StackName': 'Foo',
-                    'StackId': 'ahostname:8000:stack/Foo/123'}
+                    'StackId': 'arn:openstack:heat::t:stacks/Foo/123'}
         self.assertEqual(response, expected)
 
     def test_list(self):
@@ -81,7 +83,10 @@ class StackControllerTest(unittest.TestCase):
 
         # Stub out the RPC call to the engine with a pre-canned response
         engine_resp = {u'stacks': [
-                        {u'stack_id': u'1',
+                        {u'stack_identity': {u'tenant': u't',
+                                             u'stack_name': u'wordpress',
+                                             u'stack_id': u'1',
+                                             u'path': u''},
                         u'updated_time': u'2012-07-09T09:13:11Z',
                         u'template_description': u'blah',
                         u'stack_status_reason': u'Stack successfully created',
@@ -95,17 +100,13 @@ class StackControllerTest(unittest.TestCase):
                                     'version': self.api_version}, None
                 ).AndReturn(engine_resp)
 
-        # Stub socket.gethostname so it returns "ahostname"
-        self.m.StubOutWithMock(socket, 'gethostname')
-        socket.gethostname().AndReturn("ahostname")
-
         self.m.ReplayAll()
 
         # Call the list controller function and compare the response
         result = self.controller.list(dummy_req)
         expected = {'ListStacksResponse': {'ListStacksResult':
             {'StackSummaries': [
-            {u'StackId': u'ahostname:8000:stack/wordpress/1',
+            {u'StackId': u'arn:openstack:heat::t:stacks/wordpress/1',
             u'LastUpdatedTime': u'2012-07-09T09:13:11Z',
             u'TemplateDescription': u'blah',
             u'StackStatusReason': u'Stack successfully created',
@@ -162,7 +163,10 @@ class StackControllerTest(unittest.TestCase):
         # Note the engine returns a load of keys we don't actually use
         # so this is a subset of the real response format
         engine_resp = {u'stacks': [
-            {u'stack_id': u'6',
+            {u'stack_identity': {u'tenant': u't',
+                                 u'stack_name': u'wordpress',
+                                 u'stack_id': u'6',
+                                 u'path': u''},
             u'updated_time': u'2012-07-09T09:13:11Z',
             u'parameters':{
             u'DBUsername': {u'Default': u'admin'},
@@ -191,10 +195,6 @@ class StackControllerTest(unittest.TestCase):
                      'params': dict(dummy_req.params)},
             'version': self.api_version}, None).AndReturn(engine_resp)
 
-        # Stub socket.gethostname so it returns "ahostname"
-        self.m.StubOutWithMock(socket, 'gethostname')
-        socket.gethostname().AndReturn("ahostname")
-
         self.m.ReplayAll()
 
         # Call the list controller function and compare the response
@@ -202,7 +202,7 @@ class StackControllerTest(unittest.TestCase):
 
         expected = {'DescribeStacksResponse': {'DescribeStacksResult':
                 {'Stacks':
-                [{'StackId': u'ahostname:8000:stack/wordpress/6',
+                [{'StackId': u'arn:openstack:heat::t:stacks/wordpress/6',
                 'StackStatusReason': u'Stack successfully created',
                 'Description': u'blah',
                 'Parameters':
@@ -278,7 +278,10 @@ class StackControllerTest(unittest.TestCase):
         dummy_req = self._dummy_GET_request(params)
 
         # Stub out the RPC call to the engine with a pre-canned response
-        engine_resp = {u'StackName': u'wordpress', u'StackId': 1}
+        engine_resp = {u'tenant': u't',
+                       u'stack_name': u'wordpress',
+                       u'stack_id': u'1',
+                       u'path': u''}
 
         self.m.StubOutWithMock(rpc, 'call')
         rpc.call(dummy_req.context, self.topic, {'method': 'create_stack',
@@ -289,17 +292,17 @@ class StackControllerTest(unittest.TestCase):
             'args': engine_args},
             'version': self.api_version}, None).AndReturn(engine_resp)
 
-        # Stub socket.gethostname so it returns "ahostname"
-        self.m.StubOutWithMock(socket, 'gethostname')
-        socket.gethostname().AndReturn("ahostname")
-
         self.m.ReplayAll()
 
         response = self.controller.create(dummy_req)
 
-        expected = {'CreateStackResponse': {'CreateStackResult':
-                        {u'StackName': u'wordpress',
-                        u'StackId': u'ahostname:8000:stack/wordpress/1'}}}
+        expected = {
+            'CreateStackResponse': {
+                'CreateStackResult': {
+                    u'StackId': u'arn:openstack:heat::t:stacks/wordpress/1'
+                }
+            }
+        }
 
         self.assertEqual(response, expected)
 
@@ -372,7 +375,10 @@ class StackControllerTest(unittest.TestCase):
         dummy_req = self._dummy_GET_request(params)
 
         # Stub out the RPC call to the engine with a pre-canned response
-        engine_resp = {u'StackName': u'wordpress', u'StackId': 1}
+        engine_resp = {u'tenant': u't',
+                       u'stack_name': u'wordpress',
+                       u'stack_id': u'1',
+                       u'path': u''}
 
         self.m.StubOutWithMock(rpc, 'call')
         rpc.call(dummy_req.context, self.topic, {'method': 'update_stack',
@@ -383,17 +389,17 @@ class StackControllerTest(unittest.TestCase):
             'args': engine_args},
             'version': self.api_version}, None).AndReturn(engine_resp)
 
-        # Stub socket.gethostname so it returns "ahostname"
-        self.m.StubOutWithMock(socket, 'gethostname')
-        socket.gethostname().AndReturn("ahostname")
-
         self.m.ReplayAll()
 
         response = self.controller.update(dummy_req)
 
-        expected = {'UpdateStackResponse': {'UpdateStackResult':
-                        {u'StackName': u'wordpress',
-                        u'StackId': u'ahostname:8000:stack/wordpress/1'}}}
+        expected = {
+            'UpdateStackResponse': {
+                'UpdateStackResult': {
+                    u'StackId': u'arn:openstack:heat::t:stacks/wordpress/1'
+                }
+            }
+        }
 
         self.assertEqual(response, expected)
 
@@ -550,7 +556,10 @@ class StackControllerTest(unittest.TestCase):
         # Stub out the RPC call to the engine with a pre-canned response
         engine_resp = {u'events': [{u'stack_name': u'wordpress',
                         u'event_time': u'2012-07-23T13:05:39Z',
-                        u'stack_id': 6,
+                        u'stack_identity': {u'tenant': u't',
+                                            u'stack_name': u'wordpress',
+                                            u'stack_id': u'6',
+                                            u'path': u''},
                         u'logical_resource_id': u'WikiDatabase',
                         u'resource_status_reason': u'state changed',
                         u'event_id': 42,
@@ -567,10 +576,6 @@ class StackControllerTest(unittest.TestCase):
             'params': dict(dummy_req.params)},
             'version': self.api_version}, None).AndReturn(engine_resp)
 
-        # Stub socket.gethostname so it returns "ahostname"
-        self.m.StubOutWithMock(socket, 'gethostname')
-        socket.gethostname().AndReturn("ahostname")
-
         self.m.ReplayAll()
 
         response = self.controller.events_list(dummy_req)
@@ -579,7 +584,7 @@ class StackControllerTest(unittest.TestCase):
             {'DescribeStackEventsResult':
             {'StackEvents':
                 [{'EventId': 42,
-                'StackId': u'ahostname:8000:stack/wordpress/6',
+                'StackId': u'arn:openstack:heat::t:stacks/wordpress/6',
                 'ResourceStatus': u'IN_PROGRESS',
                 'ResourceType': u'AWS::EC2::Instance',
                 'Timestamp': u'2012-07-23T13:05:39Z',
@@ -626,7 +631,10 @@ class StackControllerTest(unittest.TestCase):
                        u'logical_resource_id': u'WikiDatabase',
                        u'resource_status_reason': None,
                        u'updated_time': u'2012-07-23T13:06:00Z',
-                       u'stack_id': 6,
+                       u'stack_identity': {u'tenant': u't',
+                                           u'stack_name': u'wordpress',
+                                           u'stack_id': u'6',
+                                           u'path': u''},
                        u'resource_status': u'CREATE_COMPLETE',
                        u'physical_resource_id':
                             u'a3455d8c-9f88-404d-a85b-5315293e67de',
@@ -643,10 +651,6 @@ class StackControllerTest(unittest.TestCase):
             'args': args,
             'version': self.api_version}, None).AndReturn(engine_resp)
 
-        # Stub socket.gethostname so it returns "ahostname"
-        self.m.StubOutWithMock(socket, 'gethostname')
-        socket.gethostname().AndReturn("ahostname")
-
         self.m.ReplayAll()
 
         response = self.controller.describe_stack_resource(dummy_req)
@@ -654,7 +658,7 @@ class StackControllerTest(unittest.TestCase):
         expected = {'DescribeStackResourceResponse':
                     {'DescribeStackResourceResult':
                     {'StackResourceDetail':
-                    {'StackId': u'ahostname:8000:stack/wordpress/6',
+                    {'StackId': u'arn:openstack:heat::t:stacks/wordpress/6',
                     'ResourceStatus': u'CREATE_COMPLETE',
                     'Description': u'',
                     'ResourceType': u'AWS::EC2::Instance',
@@ -682,7 +686,10 @@ class StackControllerTest(unittest.TestCase):
                         u'logical_resource_id': u'WikiDatabase',
                         u'resource_status_reason': None,
                         u'updated_time': u'2012-07-23T13:06:00Z',
-                        u'stack_id': 6,
+                        u'stack_identity': {u'tenant': u't',
+                                            u'stack_name': u'wordpress',
+                                            u'stack_id': u'6',
+                                            u'path': u''},
                         u'resource_status': u'CREATE_COMPLETE',
                         u'physical_resource_id':
                             u'a3455d8c-9f88-404d-a85b-5315293e67de',
@@ -700,10 +707,6 @@ class StackControllerTest(unittest.TestCase):
             'args': args,
             'version': self.api_version}, None).AndReturn(engine_resp)
 
-        # Stub socket.gethostname so it returns "ahostname"
-        self.m.StubOutWithMock(socket, 'gethostname')
-        socket.gethostname().AndReturn("ahostname")
-
         self.m.ReplayAll()
 
         response = self.controller.describe_stack_resources(dummy_req)
@@ -711,7 +714,7 @@ class StackControllerTest(unittest.TestCase):
         expected = {'DescribeStackResourcesResponse':
                     {'DescribeStackResourcesResult':
                     {'StackResources':
-                        [{'StackId': u'ahostname:8000:stack/wordpress/6',
+                      [{'StackId': u'arn:openstack:heat::t:stacks/wordpress/6',
                         'ResourceStatus': u'CREATE_COMPLETE',
                         'Description': u'',
                         'ResourceType': u'AWS::EC2::Instance',
@@ -750,7 +753,10 @@ class StackControllerTest(unittest.TestCase):
                         u'logical_resource_id': u'WikiDatabase',
                         u'resource_status_reason': None,
                         u'updated_time': u'2012-07-23T13:06:00Z',
-                        u'stack_id': 6,
+                        u'stack_identity': {u'tenant': u't',
+                                            u'stack_name': u'wordpress',
+                                            u'stack_id': u'6',
+                                            u'path': u''},
                         u'resource_status': u'CREATE_COMPLETE',
                         u'physical_resource_id':
                             u'a3455d8c-9f88-404d-a85b-5315293e67de',
index 172ae56997315f343cdcef564ef4a8af44385593..e853f1a0aab5ea8363cfd5d1e7825a83999ff2ce 100644 (file)
@@ -205,7 +205,7 @@ class stackManagerTest(unittest.TestCase):
             self.assertTrue('resource_type' in ev)
             self.assertEqual(ev['resource_type'], 'AWS::EC2::Instance')
 
-            self.assertTrue('stack_id' in ev)
+            self.assertTrue('stack_identity' in ev)
 
             self.assertTrue('stack_name' in ev)
             self.assertEqual(ev['stack_name'], self.stack_name)
@@ -217,7 +217,7 @@ class stackManagerTest(unittest.TestCase):
 
         self.assertEqual(len(sl['stacks']), 1)
         for s in sl['stacks']:
-            self.assertNotEqual(s['stack_id'], None)
+            self.assertNotEqual(s['stack_identity'], None)
             self.assertNotEqual(s['description'].find('WordPress'), -1)
 
     def test_stack_describe_all_empty(self):
@@ -242,8 +242,8 @@ class stackManagerTest(unittest.TestCase):
         s = sl['stacks'][0]
         self.assertTrue('creation_time' in s)
         self.assertTrue('updated_time' in s)
-        self.assertTrue('stack_id' in s)
-        self.assertNotEqual(s['stack_id'], None)
+        self.assertTrue('stack_identity' in s)
+        self.assertNotEqual(s['stack_identity'], None)
         self.assertTrue('stack_name' in s)
         self.assertEqual(s['stack_name'], self.stack_name)
         self.assertTrue('stack_status' in s)
@@ -258,8 +258,8 @@ class stackManagerTest(unittest.TestCase):
 
         self.assertTrue('description' in r)
         self.assertTrue('updated_time' in r)
-        self.assertTrue('stack_id' in r)
-        self.assertNotEqual(r['stack_id'], None)
+        self.assertTrue('stack_identity' in r)
+        self.assertNotEqual(r['stack_identity'], None)
         self.assertTrue('stack_name' in r)
         self.assertEqual(r['stack_name'], self.stack_name)
         self.assertTrue('metadata' in r)
@@ -289,8 +289,8 @@ class stackManagerTest(unittest.TestCase):
         r = resources[0]
         self.assertTrue('description' in r)
         self.assertTrue('updated_time' in r)
-        self.assertTrue('stack_id' in r)
-        self.assertNotEqual(r['stack_id'], None)
+        self.assertTrue('stack_identity' in r)
+        self.assertNotEqual(r['stack_identity'], None)
         self.assertTrue('stack_name' in r)
         self.assertEqual(r['stack_name'], self.stack_name)
         self.assertTrue('resource_status' in r)