keystoneauth/keystoneauth1/fixture/discovery.py
Morgan Fainberg 335a8cdf03 Remove use of positional decorator
The positional decorator results in poorly maintainable code in
a misguided effort to emulate python3's key-word-arg only notation
and functionality. This patch removes keysteonauth's dependance
on the positional decorator.

Change-Id: I20106345747860365cd0203ba1b33a2900e045b9
2017-08-07 16:37:07 -07:00

364 lines
11 KiB
Python

# 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 keystoneauth1 import _utils as utils
__all__ = ('DiscoveryList',
'V2Discovery',
'V3Discovery',
'VersionDiscovery',
)
_DEFAULT_DAYS_AGO = 30
class DiscoveryBase(dict):
"""The basic version discovery structure.
All version discovery elements should have access to these values.
:param string id: The version id for this version entry.
:param string status: The status of this entry.
:param DateTime updated: When the API was last updated.
"""
def __init__(self, id, status=None, updated=None):
super(DiscoveryBase, self).__init__()
self.id = id
self.status = status or 'stable'
self.updated = updated or utils.before_utcnow(days=_DEFAULT_DAYS_AGO)
@property
def id(self):
return self.get('id')
@id.setter
def id(self, value):
self['id'] = value
@property
def status(self):
return self.get('status')
@status.setter
def status(self, value):
self['status'] = value
@property
def links(self):
return self.setdefault('links', [])
@property
def updated_str(self):
return self.get('updated')
@updated_str.setter
def updated_str(self, value):
self['updated'] = value
@property
def updated(self):
return utils.parse_isotime(self.updated_str)
@updated.setter
def updated(self, value):
self.updated_str = value.isoformat()
def add_link(self, href, rel='self', type=None):
link = {'href': href, 'rel': rel}
if type:
link['type'] = type
self.links.append(link)
return link
@property
def media_types(self):
return self.setdefault('media-types', [])
def add_media_type(self, base, type):
mt = {'base': base, 'type': type}
self.media_types.append(mt)
return mt
class VersionDiscovery(DiscoveryBase):
"""A Version element for non-keystone services without microversions.
Provides some default values and helper methods for creating a microversion
endpoint version structure. Clients should use this instead of creating
their own structures.
:param string href: The url that this entry should point to.
:param string id: The version id that should be reported.
"""
def __init__(self, href, id, **kwargs):
super(VersionDiscovery, self).__init__(id, **kwargs)
self.add_link(href)
class MicroversionDiscovery(DiscoveryBase):
"""A Version element that has microversions.
Provides some default values and helper methods for creating a microversion
endpoint version structure. Clients should use this instead of creating
their own structures.
:param string href: The url that this entry should point to.
:param string id: The version id that should be reported.
:param string min_version: The minimum supported microversion. (optional)
:param string max_version: The maximum supported microversion. (optional)
"""
def __init__(self, href, id, min_version='', max_version='', **kwargs):
super(MicroversionDiscovery, self).__init__(id, **kwargs)
self.add_link(href)
self.min_version = min_version
self.max_version = max_version
@property
def min_version(self):
return self.get('min_version')
@min_version.setter
def min_version(self, value):
self['min_version'] = value
@property
def max_version(self):
return self.get('max_version')
@max_version.setter
def max_version(self, value):
self['max_version'] = value
class NovaMicroversionDiscovery(DiscoveryBase):
"""A Version element with nova-style microversions.
Provides some default values and helper methods for creating a microversion
endpoint version structure. Clients should use this instead of creating
their own structures.
:param href: The url that this entry should point to.
:param string id: The version id that should be reported.
:param string min_version: The minimum microversion supported. (optional)
:param string version: The maximum microversion supported. (optional)
"""
def __init__(self, href, id, min_version=None, version=None, **kwargs):
super(NovaMicroversionDiscovery, self).__init__(id, **kwargs)
self.add_link(href)
self.min_version = min_version
self.version = version
@property
def min_version(self):
return self.get('min_version')
@min_version.setter
def min_version(self, value):
if value:
self['min_version'] = value
@property
def version(self):
return self.get('version')
@version.setter
def version(self, value):
if value:
self['version'] = value
class V2Discovery(DiscoveryBase):
"""A Version element for a V2 identity service endpoint.
Provides some default values and helper methods for creating a v2.0
endpoint version structure. Clients should use this instead of creating
their own structures.
:param string href: The url that this entry should point to.
:param string id: The version id that should be reported. (optional)
Defaults to 'v2.0'.
:param bool html: Add HTML describedby links to the structure.
:param bool pdf: Add PDF describedby links to the structure.
"""
_DESC_URL = 'https://developer.openstack.org/api-ref/identity/v2/'
def __init__(self, href, id=None, html=True, pdf=True, **kwargs):
super(V2Discovery, self).__init__(id or 'v2.0', **kwargs)
self.add_link(href)
if html:
self.add_html_description()
if pdf:
self.add_pdf_description()
def add_html_description(self):
"""Add the HTML described by links.
The standard structure includes a link to a HTML document with the
API specification. Add it to this entry.
"""
self.add_link(href=self._DESC_URL + 'content',
rel='describedby',
type='text/html')
def add_pdf_description(self):
"""Add the PDF described by links.
The standard structure includes a link to a PDF document with the
API specification. Add it to this entry.
"""
self.add_link(href=self._DESC_URL + 'identity-dev-guide-2.0.pdf',
rel='describedby',
type='application/pdf')
class V3Discovery(DiscoveryBase):
"""A Version element for a V3 identity service endpoint.
Provides some default values and helper methods for creating a v3
endpoint version structure. Clients should use this instead of creating
their own structures.
:param href: The url that this entry should point to.
:param string id: The version id that should be reported. (optional)
Defaults to 'v3.0'.
:param bool json: Add JSON media-type elements to the structure.
:param bool xml: Add XML media-type elements to the structure.
"""
def __init__(self, href, id=None, json=True, xml=True, **kwargs):
super(V3Discovery, self).__init__(id or 'v3.0', **kwargs)
self.add_link(href)
if json:
self.add_json_media_type()
if xml:
self.add_xml_media_type()
def add_json_media_type(self):
"""Add the JSON media-type links.
The standard structure includes a list of media-types that the endpoint
supports. Add JSON to the list.
"""
self.add_media_type(base='application/json',
type='application/vnd.openstack.identity-v3+json')
def add_xml_media_type(self):
"""Add the XML media-type links.
The standard structure includes a list of media-types that the endpoint
supports. Add XML to the list.
"""
self.add_media_type(base='application/xml',
type='application/vnd.openstack.identity-v3+xml')
class DiscoveryList(dict):
"""A List of version elements.
Creates a correctly structured list of identity service endpoints for
use in testing with discovery.
:param string href: The url that this should be based at.
:param bool v2: Add a v2 element.
:param bool v3: Add a v3 element.
:param string v2_status: The status to use for the v2 element.
:param DateTime v2_updated: The update time to use for the v2 element.
:param bool v2_html: True to add a html link to the v2 element.
:param bool v2_pdf: True to add a pdf link to the v2 element.
:param string v3_status: The status to use for the v3 element.
:param DateTime v3_updated: The update time to use for the v3 element.
:param bool v3_json: True to add a html link to the v2 element.
:param bool v3_xml: True to add a pdf link to the v2 element.
"""
TEST_URL = 'http://keystone.host:5000/'
def __init__(self, href=None, v2=True, v3=True, v2_id=None, v3_id=None,
v2_status=None, v2_updated=None, v2_html=True, v2_pdf=True,
v3_status=None, v3_updated=None, v3_json=True, v3_xml=True):
super(DiscoveryList, self).__init__(versions={'values': []})
href = href or self.TEST_URL
if v2:
v2_href = href.rstrip('/') + '/v2.0'
self.add_v2(v2_href, id=v2_id, status=v2_status,
updated=v2_updated, html=v2_html, pdf=v2_pdf)
if v3:
v3_href = href.rstrip('/') + '/v3'
self.add_v3(v3_href, id=v3_id, status=v3_status,
updated=v3_updated, json=v3_json, xml=v3_xml)
@property
def versions(self):
return self['versions']['values']
def add_version(self, version):
"""Add a new version structure to the list.
:param dict version: A new version structure to add to the list.
"""
self.versions.append(version)
def add_v2(self, href, **kwargs):
"""Add a v2 version to the list.
The parameters are the same as V2Discovery.
"""
obj = V2Discovery(href, **kwargs)
self.add_version(obj)
return obj
def add_v3(self, href, **kwargs):
"""Add a v3 version to the list.
The parameters are the same as V3Discovery.
"""
obj = V3Discovery(href, **kwargs)
self.add_version(obj)
return obj
def add_microversion(self, href, id, **kwargs):
"""Add a microversion version to the list.
The parameters are the same as MicroversionDiscovery.
"""
obj = MicroversionDiscovery(href=href, id=id, **kwargs)
self.add_version(obj)
return obj
def add_nova_microversion(self, href, id, **kwargs):
"""Add a nova microversion version to the list.
The parameters are the same as NovaMicroversionDiscovery.
"""
obj = NovaMicroversionDiscovery(href=href, id=id, **kwargs)
self.add_version(obj)
return obj