add cyborg-api v1 & hooks
add these for further expansion: 1. give an initial version of v1 to api service, 2. add Config and PublicUrl hook to app. 3. add resource endpoint in response body. Change-Id: I2b84508a07bbbf0f5133c828a8217a23398564db
This commit is contained in:
parent
005273fce4
commit
2dd193ae5c
|
@ -16,6 +16,7 @@
|
|||
import pecan
|
||||
|
||||
from cyborg.api import config
|
||||
from cyborg.api import hooks
|
||||
from cyborg.api import middleware
|
||||
|
||||
|
||||
|
@ -26,7 +27,8 @@ def get_pecan_config():
|
|||
|
||||
|
||||
def setup_app(pecan_config=None, extra_hooks=None):
|
||||
app_hooks = []
|
||||
app_hooks = [hooks.ConfigHook(),
|
||||
hooks.PublicUrlHook()]
|
||||
if extra_hooks:
|
||||
app_hooks.extend(extra_hooks)
|
||||
|
||||
|
@ -45,3 +47,12 @@ def setup_app(pecan_config=None, extra_hooks=None):
|
|||
)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
class VersionSelectorApplication(object):
|
||||
def __init__(self):
|
||||
pc = get_pecan_config()
|
||||
self.v1 = setup_app(pecan_config=pc)
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
return self.v1(environ, start_response)
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
# Copyright 2017 Huawei Technologies Co.,LTD.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 pecan
|
||||
from wsme import types as wtypes
|
||||
|
||||
from cyborg.api.controllers import base
|
||||
|
||||
|
||||
def build_url(resource, resource_args, bookmark=False, base_url=None):
|
||||
if base_url is None:
|
||||
base_url = pecan.request.public_url
|
||||
|
||||
template = '%(url)s/%(res)s' if bookmark else '%(url)s/v1/%(res)s'
|
||||
template += '%(args)s' if resource_args.startswith('?') else '/%(args)s'
|
||||
return template % {'url': base_url, 'res': resource, 'args': resource_args}
|
||||
|
||||
|
||||
class Link(base.APIBase):
|
||||
"""A link representation."""
|
||||
|
||||
href = wtypes.text
|
||||
"""The url of a link."""
|
||||
|
||||
rel = wtypes.text
|
||||
"""The name of a link."""
|
||||
|
||||
type = wtypes.text
|
||||
"""Indicates the type of document/link."""
|
||||
|
||||
@staticmethod
|
||||
def make_link(rel_name, url, resource, resource_args,
|
||||
bookmark=False, type=wtypes.Unset):
|
||||
href = build_url(resource, resource_args,
|
||||
bookmark=bookmark, base_url=url)
|
||||
return Link(href=href, rel=rel_name, type=type)
|
|
@ -13,13 +13,18 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
from wsme import types as wtypes
|
||||
|
||||
from cyborg.api.controllers import base
|
||||
from cyborg.api.controllers import v1
|
||||
from cyborg.api import expose
|
||||
|
||||
|
||||
VERSION1 = 'v1'
|
||||
|
||||
|
||||
class Root(base.APIBase):
|
||||
name = wtypes.text
|
||||
"""The name of the API"""
|
||||
|
@ -42,6 +47,26 @@ class Root(base.APIBase):
|
|||
|
||||
|
||||
class RootController(rest.RestController):
|
||||
_versions = [VERSION1]
|
||||
"""All supported API versions"""
|
||||
|
||||
_default_version = VERSION1
|
||||
"""The default API version"""
|
||||
|
||||
v1 = v1.Controller()
|
||||
|
||||
@expose.expose(Root)
|
||||
def get(self):
|
||||
return Root.convert()
|
||||
|
||||
@pecan.expose()
|
||||
def _route(self, args, request=None):
|
||||
"""Overrides the default routing behavior.
|
||||
|
||||
It redirects the request to the default version of the cyborg API
|
||||
if the version number is not specified in the url.
|
||||
"""
|
||||
|
||||
if args[0] and args[0] not in self._versions:
|
||||
args = [self._default_version] + args
|
||||
return super(RootController, self)._route(args)
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
# Copyright 2017 Huawei Technologies Co.,LTD.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Version 1 of the Cyborg API"""
|
||||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
from wsme import types as wtypes
|
||||
|
||||
from cyborg.api.controllers import base
|
||||
from cyborg.api.controllers import link
|
||||
from cyborg.api import expose
|
||||
|
||||
|
||||
class V1(base.APIBase):
|
||||
"""The representation of the version 1 of the API."""
|
||||
|
||||
id = wtypes.text
|
||||
"""The ID of the version"""
|
||||
|
||||
accelerator = [link.Link]
|
||||
"""Links to the accelerator resource"""
|
||||
|
||||
@staticmethod
|
||||
def convert():
|
||||
v1 = V1()
|
||||
v1.id = 'v1'
|
||||
v1.accelerator = [
|
||||
link.Link.make_link('self', pecan.request.public_url,
|
||||
'accelerator', ''),
|
||||
link.Link.make_link('bookmark', pecan.request.public_url,
|
||||
'accelerator', '', bookmark=True)
|
||||
]
|
||||
return v1
|
||||
|
||||
|
||||
class Controller(rest.RestController):
|
||||
"""Version 1 API controller root"""
|
||||
|
||||
@expose.expose(V1)
|
||||
def get(self):
|
||||
return V1.convert()
|
||||
|
||||
|
||||
__all__ = ('Controller',)
|
|
@ -0,0 +1,36 @@
|
|||
# Copyright 2017 Huawei Technologies Co.,LTD.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 oslo_config import cfg
|
||||
from pecan import hooks
|
||||
|
||||
|
||||
class ConfigHook(hooks.PecanHook):
|
||||
"""Attach the config object to the request so controllers can get to it."""
|
||||
|
||||
def before(self, state):
|
||||
state.request.cfg = cfg.CONF
|
||||
|
||||
|
||||
class PublicUrlHook(hooks.PecanHook):
|
||||
"""Attach the right public_url to the request.
|
||||
|
||||
Attach the right public_url to the request so resources can create
|
||||
links even when the API service is behind a proxy or SSL terminator.
|
||||
"""
|
||||
|
||||
def before(self, state):
|
||||
state.request.public_url = (
|
||||
cfg.CONF.api.public_endpoint or state.request.host_url)
|
|
@ -56,7 +56,7 @@ class WSGIService(service.ServiceBase):
|
|||
:returns: None
|
||||
"""
|
||||
self.name = name
|
||||
self.app = app.setup_app()
|
||||
self.app = app.VersionSelectorApplication()
|
||||
self.workers = (CONF.api.api_workers or
|
||||
processutils.get_worker_count())
|
||||
if self.workers and self.workers < 1:
|
||||
|
|
|
@ -38,6 +38,13 @@ opts = [
|
|||
"the service, this option should be False; note, you "
|
||||
"will want to change public API endpoint to represent "
|
||||
"SSL termination URL with 'public_endpoint' option.")),
|
||||
cfg.StrOpt('public_endpoint',
|
||||
help=_("Public URL to use when building the links to the API "
|
||||
"resources (for example, \"https://cyborg.rocks:6666\")."
|
||||
" If None the links will be built using the request's "
|
||||
"host URL. If the API is operating behind a proxy, you "
|
||||
"will want to change this to represent the proxy's URL. "
|
||||
"Defaults to None.")),
|
||||
]
|
||||
|
||||
opt_group = cfg.OptGroup(name='api',
|
||||
|
|
Loading…
Reference in New Issue