From e14754bbdbacaf6943c4061e3488f2580acd26ad Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 26 Jul 2011 17:51:46 -0400 Subject: initial working 300 multiple choice stuff --- nova/api/openstack/__init__.py | 2 +- nova/api/openstack/versions.py | 191 +++++++++++++++++------------- nova/api/openstack/views/versions.py | 8 ++ nova/tests/api/openstack/test_versions.py | 59 ++++++++- 4 files changed, 174 insertions(+), 86 deletions(-) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index c10937bd6..0dfad0ef6 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -118,7 +118,7 @@ class APIRouter(base_wsgi.Router): mapper.connect("versions", "/", controller=versions.create_resource(version), - action="detail") + action='show') mapper.resource("console", "consoles", controller=consoles.create_resource(), diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index f389933b9..4b567957d 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -25,6 +25,80 @@ from nova.api.openstack import wsgi ATOM_XMLNS = "http://www.w3.org/2005/Atom" +VERSIONS = { + "v1.0": { + "version" : { + "id": "v1.0", + "status": "DEPRECATED", + "updated": "2011-01-21T11:33:21Z", + "links": [ + { + "rel": "self", + "href": "http://servers.api.openstack.org/v1.0/" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.0/application.wadl" + }, + ], + "media-types": [ + { + "base" : "application/xml", + "type" : "application/vnd.openstack.compute-v1.0+xml" + }, + { + "base" : "application/json", + "type" : "application/vnd.openstack.compute-v1.0+json" + } + ], + }, + }, + "v1.1": { + "version" : { + "id": "v1.1", + "status": "CURRENT", + "updated": "2011-01-21T11:33:21Z", + "links": [ + { + "rel": "self", + "href": "http://servers.api.openstack.org/v1.1/" + }, + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/cs-devguide-20110125.pdf" + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/application.wadl" + }, + ], + "media-types": [ + { + "base" : "application/xml", + "type" : "application/vnd.openstack.compute-v1.1+xml" + }, + { + "base" : "application/json", + "type" : "application/vnd.openstack.compute-v1.1+json" + } + ], + }, + }, +} + + class Versions(wsgi.Resource): @@ -43,11 +117,15 @@ class Versions(wsgi.Resource): } } + headers_serializer = VersionsHeadersSerializer() + body_serializers = { 'application/atom+xml': VersionsAtomSerializer(metadata=metadata), 'application/xml': VersionsXMLSerializer(metadata=metadata), } - serializer = wsgi.ResponseSerializer(body_serializers) + serializer = wsgi.ResponseSerializer( + body_serializers=body_serializers, + headers_serializer=headers_serializer) supported_content_types = ('application/json', 'application/xml', @@ -93,100 +171,41 @@ class Versions(wsgi.Resource): { "id": "v1.1", "status": "CURRENT", - #TODO(wwolf) get correct value for these - "updated": "2011-07-18T11:30:00Z", + "links": [ + { + "rel": "self", + } + ], + "media-types": VERSIONS['v1.1']['version']['media-types'], }, { "id": "v1.0", "status": "DEPRECATED", - #TODO(wwolf) get correct value for these - "updated": "2010-10-09T11:30:00Z", + "links": [ + { + "rel": "self", + } + ], + "media-types": VERSIONS['v1.0']['version']['media-types'], }, ] builder = nova.api.openstack.views.versions.get_view_builder(request) - versions = [builder.build(version) for version in version_objs] - return dict(versions=versions) + choices = [ + builder.build_choices(version, request) + for version in version_objs] + + return dict(choices=choices) class VersionV10(object): - def detail(self, req): - #TODO - return { - "version" : { - "id": "v1.0", - "status": "DEPRECATED", - "updated": "2011-01-21T11:33:21Z", - "links": [ - { - "rel": "self", - "href": "http://servers.api.openstack.org/v1.0/" - }, - { - "rel": "describedby", - "type": "application/pdf", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" - }, - { - "rel": "describedby", - "type": "application/vnd.sun.wadl+xml", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" - }, - ], - "media-types": [ - { - "base" : "application/xml", - "type" : "application/vnd.openstack.compute-v1.0+xml" - }, - { - "base" : "application/json", - "type" : "application/vnd.openstack.compute-v1.0+json" - } - ], - }, - } + def show(self, req): + return VERSIONS['v1.0'] class VersionV11(object): - def detail(self, req): - return { - "version" : { - "id": "v1.1", - "status": "CURRENT", - "updated": "2011-01-21T11:33:21Z", - "links": [ - { - "rel": "self", - "href": "http://servers.api.openstack.org/v1.1/" - }, - { - "rel": "describedby", - "type": "application/pdf", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" - }, - { - "rel": "describedby", - "type": "application/vnd.sun.wadl+xml", - "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" - }, - ], - "media-types": [ - { - "base" : "application/xml", - "type" : "application/vnd.openstack.compute-v1.1+xml" - }, - { - "base" : "application/json", - "type" : "application/vnd.openstack.compute-v1.1+json" - } - ], - }, - } - + def show(self, req): + return VERSIONS['v1.1'] class VersionsRequestDeserializer(wsgi.RequestDeserializer): def get_action_args(self, request_environment): @@ -259,7 +278,7 @@ class VersionsXMLSerializer(wsgi.XMLDictSerializer): return self.to_xml_string(node) - def detail(self,data): + def show(self,data): self._xml_doc = minidom.Document() node = self._create_version_node(data['version'], True) @@ -404,7 +423,7 @@ class VersionsAtomSerializer(wsgi.XMLDictSerializer): return self.to_xml_string(node) - def detail(self, data): + def show(self, data): self._xml_doc = minidom.Document() node = self._xml_doc.createElementNS(self.xmlns, 'feed') self._create_detail_meta(node, data['version']) @@ -412,6 +431,12 @@ class VersionsAtomSerializer(wsgi.XMLDictSerializer): return self.to_xml_string(node) + +class VersionsHeadersSerializer(wsgi.ResponseHeadersSerializer): + def multi(self, response, data): + response.status_int = 300 + + def create_resource(version='1.0'): controller = { '1.0': VersionV10, diff --git a/nova/api/openstack/views/versions.py b/nova/api/openstack/views/versions.py index 9fa8f49dc..97e35c983 100644 --- a/nova/api/openstack/views/versions.py +++ b/nova/api/openstack/views/versions.py @@ -31,6 +31,11 @@ class ViewBuilder(object): """ self.base_url = base_url + def build_choices(self, version_data, request): + version_data['links'][0]['href'] = self._build_versioned_link(request, + version_data['id']) + return version_data + def build(self, version_data): """Generic method used to generate a version entity.""" version = { @@ -42,6 +47,9 @@ class ViewBuilder(object): return version + def _build_versioned_link(self, req, version): + return '%s://%s/%s%s' % (req.scheme, req.host, version, req.path) + def _build_links(self, version_data): """Generate a container of links that refer to the provided version.""" href = self.generate_href(version_data["id"]) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index d1ec0b84a..f33ef5e6a 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -384,6 +384,61 @@ class VersionsTest(test.TestCase): self.assertEqual(expected, actual) + def test_multi_choice_servers_list(self): + req = webob.Request.blank('/servers/2') + req.accept = "application/json" + res = req.get_response(fakes.wsgi_app()) + print res.body + self.assertEqual(res.status_int, 300) + self.assertEqual(res.content_type, "application/json") + + expected = { + "choices": [ + { + "id": "v1.1", + "status": "CURRENT", + "links": [ + { + "href": "http://localhost:80/v1.1/servers/2", + "rel": "self", + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.1+xml" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.1+json" + }, + ], + }, + { + "id": "v1.0", + "status": "DEPRECATED", + "links": [ + { + "href": "http://localhost:80/v1.0/servers/2", + "rel": "self", + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute-v1.0+xml" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute-v1.0+json" + }, + ], + }, + ],} + + self.assertDictMatch(expected, json.loads(res.body)) + + def test_view_builder(self): base_url = "http://example.org/" @@ -488,7 +543,7 @@ class VersionsTest(test.TestCase): } serializer = versions.VersionsXMLSerializer() - response = serializer.detail(version_data) + response = serializer.show(version_data) root = xml.etree.ElementTree.XML(response) self.assertEqual(root.tag.split('}')[1], "version") @@ -625,7 +680,7 @@ class VersionsTest(test.TestCase): } serializer = versions.VersionsAtomSerializer() - response = serializer.detail(versions_data) + response = serializer.show(versions_data) root = xml.etree.ElementTree.XML(response) self.assertEqual(root.tag.split('}')[1], "feed") -- cgit