From f844bf35119f77a56bdbc6215c961aff64440be9 Mon Sep 17 00:00:00 2001 From: Zane Bitter Date: Wed, 14 Nov 2012 17:51:26 +0100 Subject: [PATCH] ReST API: Add a convenience redirect for resources Since the path stacks/{stack_name}/{stack_id}/resources exists for each valid stack we can safely redirect to it from stacks/{stack_name}/resources without having to perform any further checks in the engine, so we may as well allow it. Change-Id: I0169493479f8c6840de3edad271cf98e8fd5d1da Signed-off-by: Zane Bitter --- docs/api.md | 20 ++++++++++++++ heat/api/openstack/v1/__init__.py | 4 +++ heat/api/openstack/v1/stacks.py | 8 ++++-- heat/tests/test_api_openstack_v1.py | 43 +++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/docs/api.md b/docs/api.md index dc4262e7..385a6d1c 100644 --- a/docs/api.md +++ b/docs/api.md @@ -176,6 +176,26 @@ Parameters: * `stack_name` The name of the stack to look up * `stack_id` The unique identifier of the stack to look up +Find Stack Resources by Name +---------------------------- + +``` +GET /v1/{tenant_id}/stacks/{stack_name}/resources +``` + +Parameters: + +* `stack_name` The name of the stack to look up + +Result: + +``` +HTTP/1.1 302 Found +Location: http://heat.example.com:8004/v1/{tenant_id}/stacks/{stack_name}/{stack_id}/resources +``` + +This is a shortcut to go directly to the list of stack resources when only the stack name is known. + Get Resource ------------ diff --git a/heat/api/openstack/v1/__init__.py b/heat/api/openstack/v1/__init__.py index 4a02ee63..446ac7fb 100644 --- a/heat/api/openstack/v1/__init__.py +++ b/heat/api/openstack/v1/__init__.py @@ -69,6 +69,10 @@ class API(wsgi.Router): stack_mapper.connect("stack_lookup", "/stacks/{stack_name}", action="lookup") + stack_mapper.connect("stack_lookup_subpath", + "/stacks/{stack_name}/{path:resources}", + action="lookup", + conditions={'method': 'GET'}) stack_mapper.connect("stack_show", "/stacks/{stack_name}/{stack_id}", action="show", diff --git a/heat/api/openstack/v1/stacks.py b/heat/api/openstack/v1/stacks.py index fc4b0e5a..ff4e1bf7 100644 --- a/heat/api/openstack/v1/stacks.py +++ b/heat/api/openstack/v1/stacks.py @@ -210,7 +210,7 @@ class StackController(object): raise exc.HTTPCreated(location=util.make_url(req, result)) @util.tenant_local - def lookup(self, req, stack_name, body=None): + def lookup(self, req, stack_name, path='', body=None): """ Redirect to the canonical URL for a stack """ @@ -221,7 +221,11 @@ class StackController(object): except rpc_common.RemoteError as ex: return util.remote_error(ex) - raise exc.HTTPFound(location=util.make_url(req, identity)) + location = util.make_url(req, identity) + if path: + location = '/'.join([location, path]) + + raise exc.HTTPFound(location=location) @util.identified_stack def show(self, req, identity): diff --git a/heat/tests/test_api_openstack_v1.py b/heat/tests/test_api_openstack_v1.py index ae5a2c15..3ce7a842 100644 --- a/heat/tests/test_api_openstack_v1.py +++ b/heat/tests/test_api_openstack_v1.py @@ -433,6 +433,49 @@ class StackControllerTest(ControllerTest, unittest.TestCase): req, tenant_id=self.tenant, stack_name=stack_name) self.m.VerifyAll() + def test_lookup_resource(self): + identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '1') + + req = self._get('/stacks/%(stack_name)s/resources' % identity) + + self.m.StubOutWithMock(rpc, 'call') + rpc.call(req.context, self.topic, + {'method': 'identify_stack', + 'args': {'stack_name': identity.stack_name}, + 'version': self.api_version}, + None).AndReturn(identity) + + self.m.ReplayAll() + + try: + result = self.controller.lookup(req, tenant_id=identity.tenant, + stack_name=identity.stack_name, + path='resources') + except webob.exc.HTTPFound as found: + self.assertEqual(found.location, self._url(identity) + + '/resources') + else: + self.fail('No redirect generated') + self.m.VerifyAll() + + def test_lookup_resource_nonexistant(self): + stack_name = 'wibble' + + req = self._get('/stacks/%(stack_name)s/resources' % locals()) + + self.m.StubOutWithMock(rpc, 'call') + rpc.call(req.context, self.topic, + {'method': 'identify_stack', + 'args': {'stack_name': stack_name}, + 'version': self.api_version}, + None).AndRaise(rpc_common.RemoteError("AttributeError")) + self.m.ReplayAll() + + self.assertRaises(webob.exc.HTTPNotFound, self.controller.lookup, + req, tenant_id=self.tenant, stack_name=stack_name, + path='resources') + self.m.VerifyAll() + def test_show(self): identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '6') -- 2.45.2