b974a63660
EXPERIMENTAL Glance v3 API has been removed in favor of standalone API (EXPERIMENTAL Artifacts API of v0.1). This patch introduces a new process entry point to run on a different port (9494 by default), with its own configuration file and a paste config. A controller stub for old /v3 api remains in the glnace.api package for the compatibility with existing paste configuration which may reference it. This stub returns a 301 redirects to glare endpoint if it is present or 410 errors otherwise. To reuse the existing version_negotiation middleware some refactoring has been made. Implements blueprint: move-v3-to-glare Change-Id: I5b7bd4cdcc5f2a40fc4a5f74bcc422fd700c4fb0
99 lines
4.0 KiB
Python
99 lines
4.0 KiB
Python
# Copyright (c) 2015 Mirantis, Inc.
|
|
#
|
|
# 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.
|
|
|
|
from glance.api.glare.v0_1 import glare
|
|
from glance.common import wsgi
|
|
|
|
|
|
UUID_REGEX = (
|
|
R'[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}')
|
|
|
|
|
|
class API(wsgi.Router):
|
|
|
|
def _get_artifacts_resource(self):
|
|
if not self.artifacts_resource:
|
|
self.artifacts_resource = glare.create_resource()
|
|
return self.artifacts_resource
|
|
|
|
def __init__(self, mapper):
|
|
self.artifacts_resource = None
|
|
artifacts_resource = self._get_artifacts_resource()
|
|
reject_method_resource = wsgi.Resource(wsgi.RejectMethodController())
|
|
|
|
def _check_json_content_type(environ, result):
|
|
return "application/json" in environ["CONTENT_TYPE"]
|
|
|
|
def _check_octet_stream_content_type(environ, result):
|
|
return "application/octet-stream" in environ["CONTENT_TYPE"]
|
|
|
|
def connect_routes(m, read_only):
|
|
with m.submapper(resource_name="artifact_operations",
|
|
path_prefix="/{id}",
|
|
requirements={'id': UUID_REGEX}) as art:
|
|
art.show()
|
|
if not read_only:
|
|
art.delete()
|
|
art.action('update', method='PATCH')
|
|
art.link('publish', method='POST')
|
|
|
|
def connect_attr_action(attr):
|
|
if not read_only:
|
|
attr.action("upload", conditions={
|
|
'method': ["POST", "PUT"],
|
|
'function': _check_octet_stream_content_type})
|
|
attr.action("update_property",
|
|
conditions={
|
|
'method': ["POST", "PUT"],
|
|
'function': _check_json_content_type})
|
|
attr.link("download", method="GET")
|
|
|
|
attr_map = art.submapper(resource_name="attr_operations",
|
|
path_prefix="/{attr}", path_left=None)
|
|
attr_items = art.submapper(
|
|
resource_name="attr_item_ops",
|
|
path_prefix="/{attr}/{path_left:.*}")
|
|
connect_attr_action(attr_map)
|
|
connect_attr_action(attr_items)
|
|
|
|
m.connect("", action='list', conditions={'method': 'GET'},
|
|
state='active')
|
|
m.connect("/drafts", action='list', conditions={'method': 'GET'},
|
|
state='creating')
|
|
if not read_only:
|
|
m.connect("/drafts", action='create',
|
|
conditions={'method': 'POST'})
|
|
|
|
mapper.connect('/artifacts',
|
|
controller=artifacts_resource,
|
|
action='list_artifact_types',
|
|
conditions={'method': ['GET']})
|
|
|
|
versioned = mapper.submapper(path_prefix='/artifacts/{type_name}/'
|
|
'v{type_version}',
|
|
controller=artifacts_resource)
|
|
|
|
non_versioned = mapper.submapper(path_prefix='/artifacts/{type_name}',
|
|
type_version=None,
|
|
controller=artifacts_resource)
|
|
connect_routes(versioned, False)
|
|
connect_routes(non_versioned, True)
|
|
|
|
mapper.connect('/artifacts',
|
|
controller=reject_method_resource,
|
|
action='reject',
|
|
allowed_methods='GET')
|
|
|
|
super(API, self).__init__(mapper)
|