159 lines
4.9 KiB
Python
159 lines
4.9 KiB
Python
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
|
#
|
|
# 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 six.moves.urllib import parse
|
|
from oslo_config import cfg
|
|
|
|
from designate.objects.adapters import base
|
|
from designate.objects import base as ovoobj_base
|
|
from designate import exceptions
|
|
|
|
|
|
cfg.CONF.import_opt('api_base_uri', 'designate.api', group='service:api')
|
|
cfg.CONF.import_opt('enable_host_header', 'designate.api', group='service:api')
|
|
|
|
|
|
class APIv2Adapter(base.DesignateAdapter):
|
|
|
|
BASE_URI = cfg.CONF['service:api'].api_base_uri.rstrip('/')
|
|
|
|
ADAPTER_FORMAT = 'API_v2'
|
|
|
|
#####################
|
|
# Rendering methods #
|
|
#####################
|
|
|
|
@classmethod
|
|
def _render_list(cls, list_object, *args, **kwargs):
|
|
|
|
r_list = super(APIv2Adapter, cls)._render_list(
|
|
list_object, *args, **kwargs)
|
|
|
|
if cls.MODIFICATIONS['options'].get('links', True)\
|
|
and 'request' in kwargs:
|
|
r_list['links'] = cls._get_collection_links(
|
|
list_object, kwargs['request'])
|
|
# Check if we should include metadata
|
|
if isinstance(list_object, ovoobj_base.PagedListObjectMixin):
|
|
metadata = {}
|
|
if list_object.total_count is not None:
|
|
metadata['total_count'] = list_object.total_count
|
|
r_list['metadata'] = metadata
|
|
|
|
return r_list
|
|
|
|
@classmethod
|
|
def _render_object(cls, object, *args, **kwargs):
|
|
obj = super(APIv2Adapter, cls)._render_object(object, *args, **kwargs)
|
|
|
|
if cls.MODIFICATIONS['options'].get('links', True)\
|
|
and 'request' in kwargs:
|
|
obj['links'] = cls._get_resource_links(object, kwargs['request'])
|
|
|
|
return obj
|
|
|
|
#####################
|
|
# Parsing methods #
|
|
#####################
|
|
|
|
@classmethod
|
|
def parse(cls, values, output_object, *args, **kwargs):
|
|
return super(APIv2Adapter, cls).parse(
|
|
cls.ADAPTER_FORMAT, values, output_object, *args, **kwargs)
|
|
|
|
#####################
|
|
# Link methods #
|
|
#####################
|
|
|
|
@classmethod
|
|
def _get_base_url(cls, request):
|
|
if cfg.CONF['service:api'].enable_host_header:
|
|
try:
|
|
return request.host_url
|
|
except Exception:
|
|
return cls.BASE_URI
|
|
else:
|
|
return cls.BASE_URI
|
|
|
|
@classmethod
|
|
def _get_resource_links(cls, obj, request):
|
|
base_uri = cls._get_base_url(request)
|
|
|
|
path = cls._get_path(request, obj)
|
|
return {'self': '%s%s/%s' % (base_uri, path, obj.id)}
|
|
|
|
@classmethod
|
|
def _get_path(cls, request, *args):
|
|
path = request.path.lstrip('/').split('/')
|
|
item_path = ''
|
|
for part in path:
|
|
if part == cls.MODIFICATIONS['options']['collection_name']:
|
|
item_path += '/' + part
|
|
return item_path
|
|
else:
|
|
item_path += '/' + part
|
|
|
|
@classmethod
|
|
def _get_collection_links(cls, item_list, request):
|
|
|
|
links = {
|
|
'self': cls._get_collection_href(request)
|
|
}
|
|
params = request.GET
|
|
|
|
# defined in etc/designate/designate.conf.sample
|
|
limit = cfg.CONF['service:api'].default_limit_v2
|
|
|
|
if 'limit' in params:
|
|
limit = params['limit']
|
|
if limit.lower() == 'max':
|
|
limit = cfg.CONF['service:api'].max_limit_v2
|
|
else:
|
|
try:
|
|
limit = int(limit)
|
|
except ValueError:
|
|
raise exceptions.ValueError(
|
|
"'limit' should be an integer or 'max'")
|
|
|
|
# Bug: this creates a link to "next" even on the last page if
|
|
# len(item_list) happens to be == limit
|
|
if limit is not None and limit == len(item_list):
|
|
links['next'] = cls._get_next_href(request, item_list)
|
|
|
|
return links
|
|
|
|
@classmethod
|
|
def _get_collection_href(cls, request, extra_params=None):
|
|
params = request.GET
|
|
|
|
if extra_params is not None:
|
|
params.update(extra_params)
|
|
|
|
base_uri = cls._get_base_url(request)
|
|
|
|
href = "%s%s?%s" % (
|
|
base_uri,
|
|
cls._get_path(request),
|
|
parse.urlencode(params))
|
|
|
|
return href.rstrip('?')
|
|
|
|
@classmethod
|
|
def _get_next_href(cls, request, items):
|
|
# Prepare the extra params
|
|
extra_params = {
|
|
'marker': items[-1]['id']
|
|
}
|
|
|
|
return cls._get_collection_href(request, extra_params)
|