From: Zane Bitter Date: Wed, 5 Sep 2012 19:51:25 +0000 (+0200) Subject: Report StackId in ARN format X-Git-Tag: 2014.1~1473 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=e8b464dabfd95c8ce7c90c72cb5132e7140062f7;p=openstack-build%2Fheat-build.git Report StackId in ARN format 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 --- diff --git a/heat/api/v1/stacks.py b/heat/api/v1/stacks.py index 9a2e1441..f692d742 100644 --- a/heat/api/v1/stacks.py +++ b/heat/api/v1/stacks.py @@ -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') diff --git a/heat/engine/api.py b/heat/engine/api.py index 05c3aaab..5c25e72c 100644 --- a/heat/engine/api.py +++ b/heat/engine/api.py @@ -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, diff --git a/heat/engine/manager.py b/heat/engine/manager.py index bf16842b..a69564a1 100644 --- a/heat/engine/manager.py +++ b/heat/engine/manager.py @@ -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): diff --git a/heat/tests/test_api_v1.py b/heat/tests/test_api_v1.py index 6e1a480a..a0b90e4b 100644 --- a/heat/tests/test_api_v1.py +++ b/heat/tests/test_api_v1.py @@ -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', diff --git a/heat/tests/test_engine_manager.py b/heat/tests/test_engine_manager.py index 172ae569..e853f1a0 100644 --- a/heat/tests/test_engine_manager.py +++ b/heat/tests/test_engine_manager.py @@ -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)