designate/designate/objects/adapters/api_v2/base.py

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)