From 2cf0806ed92ba18a27768dfb0a0c85b42f5ee35d Mon Sep 17 00:00:00 2001 From: Richard Lee Date: Tue, 11 Feb 2014 16:20:16 -0600 Subject: [PATCH] Add project to unscoped stack list response For an unscoped stack list, stacks will possibly belong to several different projects. As a user who can see all stacks, it is useful to be able to distinguish which stacks belong to which projects. Co-Authored-By: Anderson Mesquita Change-Id: I4148a298ef7a41b815b477c49ff4aaf331845129 Implements: blueprint management-api --- heat/api/openstack/v1/stacks.py | 3 ++- heat/api/openstack/v1/views/stacks_view.py | 10 ++++--- ..._openstack_v1_views_stacks_view_builder.py | 27 ++++++++++++++++++- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/heat/api/openstack/v1/stacks.py b/heat/api/openstack/v1/stacks.py index d1902e656f..503d007fc9 100644 --- a/heat/api/openstack/v1/stacks.py +++ b/heat/api/openstack/v1/stacks.py @@ -181,7 +181,8 @@ class StackController(object): except AttributeError as exc: logger.warning("Old Engine Version: %s" % str(exc)) - return stacks_view.collection(req, stacks=stacks, count=count) + return stacks_view.collection(req, stacks=stacks, count=count, + tenant_safe=tenant_safe) @util.policy_enforce def global_index(self, req): diff --git a/heat/api/openstack/v1/views/stacks_view.py b/heat/api/openstack/v1/views/stacks_view.py index 3d83ca275d..7a11fc7f32 100644 --- a/heat/api/openstack/v1/views/stacks_view.py +++ b/heat/api/openstack/v1/views/stacks_view.py @@ -31,7 +31,7 @@ basic_keys = (engine_api.STACK_ID, engine_api.STACK_UPDATED_TIME) -def format_stack(req, stack, keys=None): +def format_stack(req, stack, keys=None, tenant_safe=True): def transform(key, value): if keys and key not in keys: return @@ -39,6 +39,8 @@ def format_stack(req, stack, keys=None): if key == engine_api.STACK_ID: yield ('id', value['stack_id']) yield ('links', [util.make_link(req, value)]) + if not tenant_safe: + yield ('project', value['tenant']) elif key == engine_api.STACK_ACTION: return elif (key == engine_api.STACK_STATUS and @@ -57,8 +59,10 @@ def format_stack(req, stack, keys=None): transform(k, v) for k, v in stack.items())) -def collection(req, stacks, count=None): - formatted_stacks = [format_stack(req, s, basic_keys) for s in stacks] +def collection(req, stacks, count=None, tenant_safe=True): + keys = basic_keys + formatted_stacks = [format_stack(req, s, keys, tenant_safe) + for s in stacks] result = {'stacks': formatted_stacks} links = views_common.get_collection_links(req, formatted_stacks) diff --git a/heat/tests/test_api_openstack_v1_views_stacks_view_builder.py b/heat/tests/test_api_openstack_v1_views_stacks_view_builder.py index e7a80cba73..1f435278f6 100644 --- a/heat/tests/test_api_openstack_v1_views_stacks_view_builder.py +++ b/heat/tests/test_api_openstack_v1_views_stacks_view_builder.py @@ -58,6 +58,30 @@ class TestFormatStack(HeatTestCase): self.assertIn('links', result) self.assertEqual(['blah'], result['links']) + @mock.patch.object(stacks_view, 'util', new=mock.Mock()) + def test_doesnt_add_project_by_default(self): + stack = {'stack_identity': {'stack_id': 'foo', 'tenant': 'bar'}} + + result = stacks_view.format_stack(self.request, stack, None) + self.assertNotIn('project', result) + + @mock.patch.object(stacks_view, 'util', new=mock.Mock()) + def test_doesnt_add_project_if_tenant_safe(self): + stack = {'stack_identity': {'stack_id': 'foo', 'tenant': 'bar'}} + + result = stacks_view.format_stack(self.request, stack, + None, tenant_safe=True) + self.assertNotIn('project', result) + + @mock.patch.object(stacks_view, 'util', new=mock.Mock()) + def test_adds_project_if_not_tenant_safe(self): + stack = {'stack_identity': {'stack_id': 'foo', 'tenant': 'bar'}} + + result = stacks_view.format_stack(self.request, stack, + None, tenant_safe=False) + self.assertIn('project', result) + self.assertEqual('bar', result['project']) + def test_includes_all_other_keys(self): stack = {'foo': 'bar'} @@ -116,7 +140,8 @@ class TestStacksViewBuilder(HeatTestCase): stacks_view.collection(self.request, stacks) mock_format_stack.assert_called_once_with(self.request, self.stack1, - expected_keys) + expected_keys, + mock.ANY) @mock.patch.object(stacks_view.views_common, 'get_collection_links') def test_append_collection_links(self, mock_get_collection_links):