From a5e1284138da16e880e74a16f0020bcd130c4d21 Mon Sep 17 00:00:00 2001 From: jiasirui Date: Wed, 23 Dec 2020 18:34:02 +0800 Subject: [PATCH] version request url move to the dir of module Change-Id: If6819e3131144c5630539d76bafd42b101e06a91 --- etc/venus/api-paste.ini | 2 +- venus/api/openstack/__init__.py | 6 +- venus/api/v1/router.py | 2 +- venus/modules/version/__init__.py | 0 venus/{api => modules/version}/versions.py | 487 ++++++++++----------- 5 files changed, 247 insertions(+), 250 deletions(-) create mode 100644 venus/modules/version/__init__.py rename venus/{api => modules/version}/versions.py (96%) diff --git a/etc/venus/api-paste.ini b/etc/venus/api-paste.ini index 6c509ca..6bcb6e3 100644 --- a/etc/venus/api-paste.ini +++ b/etc/venus/api-paste.ini @@ -37,7 +37,7 @@ paste.app_factory = venus.api.v1.router:APIRouter.factory pipeline = faultwrap osvenusversionapp [app:osvenusversionapp] -paste.app_factory = venus.api.versions:Versions.factory +paste.app_factory = venus.modules.version.versions:Versions.factory ########## # Shared # diff --git a/venus/api/openstack/__init__.py b/venus/api/openstack/__init__.py index bdb69d8..3279d0e 100644 --- a/venus/api/openstack/__init__.py +++ b/venus/api/openstack/__init__.py @@ -81,10 +81,10 @@ class APIRouter(base_wsgi.Router): mapper = ProjectMapper() self.resources = {} self._setup_routes(mapper, ext_mgr) - self._setup_ext_routes(mapper, ext_mgr) - self._setup_extensions(ext_mgr) + # self._setup_ext_routes(mapper, ext_mgr) + # self._setup_extensions(ext_mgr) for url in mapper.matchlist: - LOG.debug('URL methid: s% register: %s ', + LOG.debug('URL method: %s register: %s ', url.conditions, url.routepath) super(APIRouter, self).__init__(mapper) diff --git a/venus/api/v1/router.py b/venus/api/v1/router.py index 035e865..c4858a8 100644 --- a/venus/api/v1/router.py +++ b/venus/api/v1/router.py @@ -20,9 +20,9 @@ from oslo_log import log as logging from venus.api import extensions import venus.api.openstack -from venus.api import versions from venus.modules.custom_config import controller as custom_config from venus.modules.search import controller as search +from venus.modules.version import versions LOG = logging.getLogger(__name__) diff --git a/venus/modules/version/__init__.py b/venus/modules/version/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venus/api/versions.py b/venus/modules/version/versions.py similarity index 96% rename from venus/api/versions.py rename to venus/modules/version/versions.py index fc595ed..6c66e15 100644 --- a/venus/api/versions.py +++ b/venus/modules/version/versions.py @@ -1,245 +1,242 @@ -# Copyright 2020 Inspur -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import datetime - -from lxml import etree -from oslo_config import cfg - -from venus.api.openstack import wsgi -from venus.api.v1.views import versions as views_versions -from venus.api import xmlutil - - -CONF = cfg.CONF - - -_KNOWN_VERSIONS = { - "v1.0": { - "id": "v1.0", - "status": "SUPPORTED", - "updated": "2014-06-28T12:20:21Z", - "links": [ - { - "rel": "describedby", - "type": "text/html", - "href": "http://docs.openstack.org/", - }, - ], - "media-types": [ - { - "base": "application/xml", - "type": "application/vnd.openstack.venus+xml;version=1", - }, - { - "base": "application/json", - "type": "application/vnd.openstack.venus+json;version=1", - } - ], - } -} - - -def get_supported_versions(): - versions = {} - - if CONF.enable_v1_api: - versions['v1.0'] = _KNOWN_VERSIONS['v1.0'] - - return versions - - -class MediaTypesTemplateElement(xmlutil.TemplateElement): - def will_render(self, datum): - return 'media-types' in datum - - -def make_version(elem): - elem.set('id') - elem.set('status') - elem.set('updated') - - mts = MediaTypesTemplateElement('media-types') - elem.append(mts) - - mt = xmlutil.sub_template_element(mts, 'media-type', - selector='media-types') - mt.set('base') - mt.set('type') - - xmlutil.make_links(elem, 'links') - - -version_nsmap = {None: xmlutil.XMLNS_COMMON_V10, 'atom': xmlutil.XMLNS_ATOM} - - -class VersionTemplate(xmlutil.TemplateBuilder): - def construct(self): - root = xmlutil.TemplateElement('version', selector='version') - make_version(root) - return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap) - - -class VersionsTemplate(xmlutil.TemplateBuilder): - def construct(self): - root = xmlutil.TemplateElement('versions') - elem = xmlutil.sub_template_element(root, 'version', - selector='versions') - make_version(elem) - return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap) - - -class ChoicesTemplate(xmlutil.TemplateBuilder): - def construct(self): - root = xmlutil.TemplateElement('choices') - elem = xmlutil.sub_template_element(root, 'version', - selector='choices') - make_version(elem) - return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap) - - -class AtomSerializer(wsgi.XMLDictSerializer): - - NSMAP = {None: xmlutil.XMLNS_ATOM} - - def __init__(self, metadata=None, xmlns=None): - super(AtomSerializer, self).__init__(metadata, xmlns) - self.metadata = metadata or {} - if not xmlns: - self.xmlns = wsgi.XML_NS_ATOM - else: - self.xmlns = xmlns - - def _get_most_recent_update(self, versions): - recent = None - for version in versions: - updated = datetime.datetime.strptime(version['updated'], - '%Y-%m-%dT%H:%M:%SZ') - if not recent: - recent = updated - elif updated > recent: - recent = updated - - return recent.strftime('%Y-%m-%dT%H:%M:%SZ') - - def _get_base_url(self, link_href): - # Make sure no trailing / - link_href = link_href.rstrip('/') - return link_href.rsplit('/', 1)[0] + '/' - - def _create_feed(self, versions, feed_title, feed_id): - feed = etree.Element('feed', nsmap=self.NSMAP) - title = etree.SubElement(feed, 'title') - title.set('type', 'text') - title.text = feed_title - - # Set this updated to the most recently updated version - recent = self._get_most_recent_update(versions) - etree.SubElement(feed, 'updated').text = recent - - etree.SubElement(feed, 'id').text = feed_id - - link = etree.SubElement(feed, 'link') - link.set('rel', 'self') - link.set('href', feed_id) - - author = etree.SubElement(feed, 'author') - etree.SubElement(author, 'name').text = 'Rackspace' - etree.SubElement(author, 'uri').text = 'http://www.rackspace.com/' - - for version in versions: - feed.append(self._create_version_entry(version)) - - return feed - - def _create_version_entry(self, version): - entry = etree.Element('entry') - etree.SubElement(entry, 'id').text = version['links'][0]['href'] - title = etree.SubElement(entry, 'title') - title.set('type', 'text') - title.text = 'Version %s' % version['id'] - etree.SubElement(entry, 'updated').text = version['updated'] - - for link in version['links']: - link_elem = etree.SubElement(entry, 'link') - link_elem.set('rel', link['rel']) - link_elem.set('href', link['href']) - if 'type' in link: - link_elem.set('type', link['type']) - - content = etree.SubElement(entry, 'content') - content.set('type', 'text') - content.text = 'Version %s %s (%s)' % (version['id'], - version['status'], - version['updated']) - return entry - - -class VersionsAtomSerializer(AtomSerializer): - def default(self, data): - versions = data['versions'] - feed_id = self._get_base_url(versions[0]['links'][0]['href']) - feed = self._create_feed(versions, 'Available API Versions', feed_id) - return self._to_xml(feed) - - -class VersionAtomSerializer(AtomSerializer): - def default(self, data): - version = data['version'] - feed_id = version['links'][0]['href'] - feed = self._create_feed([version], 'About This Version', feed_id) - return self._to_xml(feed) - - -class Versions(wsgi.Resource): - - def __init__(self): - super(Versions, self).__init__(None) - - @wsgi.serializers(xml=VersionsTemplate, - atom=VersionsAtomSerializer) - def index(self, req): - """Return all versions.""" - builder = views_versions.get_view_builder(req) - return builder.build_versions(get_supported_versions()) - - @wsgi.serializers(xml=ChoicesTemplate) - @wsgi.response(300) - def multi(self, req): - """Return multiple choices.""" - builder = views_versions.get_view_builder(req) - return builder.build_choices(get_supported_versions(), req) - - def get_action_args(self, request_environment): - """Parse dictionary created by routes library.""" - args = {} - if request_environment['PATH_INFO'] == '/': - args['action'] = 'index' - else: - args['action'] = 'multi' - - return args - - -class VenusVersion(object): - @wsgi.serializers(xml=VersionTemplate, - atom=VersionAtomSerializer) - def show(self, req): - builder = views_versions.get_view_builder(req) - if 'v1' in builder.base_url: - return builder.build_version(_KNOWN_VERSIONS['v1.0']) - - -def create_resource(): - return wsgi.Resource(VenusVersion()) +# Copyright 2020 Inspur +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import datetime + +from lxml import etree + +from venus.api.openstack import wsgi +from venus.api.v1.views import versions as views_versions +from venus.api import xmlutil +from venus.conf import CONF + + +_KNOWN_VERSIONS = { + "v1.0": { + "id": "v1.0", + "status": "SUPPORTED", + "updated": "2014-06-28T12:20:21Z", + "links": [ + { + "rel": "describedby", + "type": "text/html", + "href": "http://docs.openstack.org/", + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.venus+xml;version=1", + }, + { + "base": "application/json", + "type": "application/vnd.openstack.venus+json;version=1", + } + ], + } +} + + +def get_supported_versions(): + versions = {} + + if CONF.enable_v1_api: + versions['v1.0'] = _KNOWN_VERSIONS['v1.0'] + + return versions + + +class MediaTypesTemplateElement(xmlutil.TemplateElement): + def will_render(self, datum): + return 'media-types' in datum + + +def make_version(elem): + elem.set('id') + elem.set('status') + elem.set('updated') + + mts = MediaTypesTemplateElement('media-types') + elem.append(mts) + + mt = xmlutil.sub_template_element(mts, 'media-type', + selector='media-types') + mt.set('base') + mt.set('type') + + xmlutil.make_links(elem, 'links') + + +version_nsmap = {None: xmlutil.XMLNS_COMMON_V10, 'atom': xmlutil.XMLNS_ATOM} + + +class VersionTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('version', selector='version') + make_version(root) + return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap) + + +class VersionsTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('versions') + elem = xmlutil.sub_template_element(root, 'version', + selector='versions') + make_version(elem) + return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap) + + +class ChoicesTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('choices') + elem = xmlutil.sub_template_element(root, 'version', + selector='choices') + make_version(elem) + return xmlutil.MasterTemplate(root, 1, nsmap=version_nsmap) + + +class AtomSerializer(wsgi.XMLDictSerializer): + + NSMAP = {None: xmlutil.XMLNS_ATOM} + + def __init__(self, metadata=None, xmlns=None): + super(AtomSerializer, self).__init__(metadata, xmlns) + self.metadata = metadata or {} + if not xmlns: + self.xmlns = wsgi.XML_NS_ATOM + else: + self.xmlns = xmlns + + def _get_most_recent_update(self, versions): + recent = None + for version in versions: + updated = datetime.datetime.strptime(version['updated'], + '%Y-%m-%dT%H:%M:%SZ') + if not recent: + recent = updated + elif updated > recent: + recent = updated + + return recent.strftime('%Y-%m-%dT%H:%M:%SZ') + + def _get_base_url(self, link_href): + # Make sure no trailing / + link_href = link_href.rstrip('/') + return link_href.rsplit('/', 1)[0] + '/' + + def _create_feed(self, versions, feed_title, feed_id): + feed = etree.Element('feed', nsmap=self.NSMAP) + title = etree.SubElement(feed, 'title') + title.set('type', 'text') + title.text = feed_title + + # Set this updated to the most recently updated version + recent = self._get_most_recent_update(versions) + etree.SubElement(feed, 'updated').text = recent + + etree.SubElement(feed, 'id').text = feed_id + + link = etree.SubElement(feed, 'link') + link.set('rel', 'self') + link.set('href', feed_id) + + author = etree.SubElement(feed, 'author') + etree.SubElement(author, 'name').text = 'Rackspace' + etree.SubElement(author, 'uri').text = 'http://www.rackspace.com/' + + for version in versions: + feed.append(self._create_version_entry(version)) + + return feed + + def _create_version_entry(self, version): + entry = etree.Element('entry') + etree.SubElement(entry, 'id').text = version['links'][0]['href'] + title = etree.SubElement(entry, 'title') + title.set('type', 'text') + title.text = 'Version %s' % version['id'] + etree.SubElement(entry, 'updated').text = version['updated'] + + for link in version['links']: + link_elem = etree.SubElement(entry, 'link') + link_elem.set('rel', link['rel']) + link_elem.set('href', link['href']) + if 'type' in link: + link_elem.set('type', link['type']) + + content = etree.SubElement(entry, 'content') + content.set('type', 'text') + content.text = 'Version %s %s (%s)' % (version['id'], + version['status'], + version['updated']) + return entry + + +class VersionsAtomSerializer(AtomSerializer): + def default(self, data): + versions = data['versions'] + feed_id = self._get_base_url(versions[0]['links'][0]['href']) + feed = self._create_feed(versions, 'Available API Versions', feed_id) + return self._to_xml(feed) + + +class VersionAtomSerializer(AtomSerializer): + def default(self, data): + version = data['version'] + feed_id = version['links'][0]['href'] + feed = self._create_feed([version], 'About This Version', feed_id) + return self._to_xml(feed) + + +class Versions(wsgi.Resource): + + def __init__(self): + super(Versions, self).__init__(None) + + @wsgi.serializers(xml=VersionsTemplate, + atom=VersionsAtomSerializer) + def index(self, req): + """Return all versions.""" + builder = views_versions.get_view_builder(req) + return builder.build_versions(get_supported_versions()) + + @wsgi.serializers(xml=ChoicesTemplate) + @wsgi.response(300) + def multi(self, req): + """Return multiple choices.""" + builder = views_versions.get_view_builder(req) + return builder.build_choices(get_supported_versions(), req) + + def get_action_args(self, request_environment): + """Parse dictionary created by routes library.""" + args = {} + if request_environment['PATH_INFO'] == '/': + args['action'] = 'index' + else: + args['action'] = 'multi' + + return args + + +class VenusVersion(object): + @wsgi.serializers(xml=VersionTemplate, + atom=VersionAtomSerializer) + def show(self, req): + builder = views_versions.get_view_builder(req) + if 'v1' in builder.base_url: + return builder.build_version(_KNOWN_VERSIONS['v1.0']) + + +def create_resource(): + return wsgi.Resource(VenusVersion())