Merge "Add API microversion support"
This commit is contained in:
@@ -186,6 +186,14 @@ class Profile(object):
|
||||
"""
|
||||
self._get_filter(service).version = version
|
||||
|
||||
def set_api_version(self, service, api_version):
|
||||
"""Set the desired API micro-version for the specified service.
|
||||
|
||||
:param str service: Service type.
|
||||
:param str api_version: Desired service API micro-version.
|
||||
"""
|
||||
self._setter(service, "api_version", api_version)
|
||||
|
||||
def set_interface(self, service, interface):
|
||||
"""Set the desired interface for the specified service.
|
||||
|
||||
|
@@ -72,7 +72,7 @@ class ServiceFilter(dict):
|
||||
valid_versions = []
|
||||
|
||||
def __init__(self, service_type, interface=PUBLIC, region=None,
|
||||
service_name=None, version=None):
|
||||
service_name=None, version=None, api_version=None):
|
||||
"""Create a service identifier.
|
||||
|
||||
:param string service_type: The desired type of service.
|
||||
@@ -81,12 +81,14 @@ class ServiceFilter(dict):
|
||||
:param string region: The desired region (optional).
|
||||
:param string service_name: Name of the service
|
||||
:param string version: Version of service to use.
|
||||
:param string api_version: Microversion of service supported.
|
||||
"""
|
||||
self['service_type'] = service_type.lower()
|
||||
self['interface'] = interface
|
||||
self['region_name'] = region
|
||||
self['service_name'] = service_name
|
||||
self['version'] = version
|
||||
self['api_version'] = api_version
|
||||
|
||||
@property
|
||||
def service_type(self):
|
||||
@@ -124,6 +126,14 @@ class ServiceFilter(dict):
|
||||
def version(self, value):
|
||||
self['version'] = value
|
||||
|
||||
@property
|
||||
def api_version(self):
|
||||
return self['api_version']
|
||||
|
||||
@api_version.setter
|
||||
def api_version(self, value):
|
||||
self['api_version'] = value
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
return self['path']
|
||||
|
@@ -28,6 +28,7 @@ from six.moves.urllib import parse
|
||||
|
||||
DEFAULT_USER_AGENT = "openstacksdk/%s" % openstack_version.__version__
|
||||
VERSION_PATTERN = re.compile('/v\d[\d.]*')
|
||||
API_REQUEST_HEADER = "openstack-api-version"
|
||||
|
||||
|
||||
def parse_url(filt, url):
|
||||
@@ -89,9 +90,33 @@ class Session(_session.Session):
|
||||
self.user_agent = "%s %s" % (user_agent, DEFAULT_USER_AGENT)
|
||||
else:
|
||||
self.user_agent = DEFAULT_USER_AGENT
|
||||
super(Session, self).__init__(user_agent=self.user_agent, **kwargs)
|
||||
|
||||
self.profile = profile
|
||||
api_version_header = self._get_api_requests()
|
||||
super(Session, self).__init__(user_agent=self.user_agent,
|
||||
additional_headers=api_version_header,
|
||||
**kwargs)
|
||||
|
||||
def _get_api_requests(self):
|
||||
"""Get API micro-version requests.
|
||||
|
||||
:param profile: A profile object that contains customizations about
|
||||
service name, region, version, interface or
|
||||
api_version.
|
||||
:return: A standard header string if there is any specialization in
|
||||
API microversion, or None if no such request exists.
|
||||
"""
|
||||
if self.profile is None:
|
||||
return None
|
||||
|
||||
req = []
|
||||
for svc in self.profile.get_services():
|
||||
if svc.service_type and svc.api_version:
|
||||
req.append(" ".join([svc.service_type, svc.api_version]))
|
||||
if req:
|
||||
return {API_REQUEST_HEADER: ",".join(req)}
|
||||
|
||||
return None
|
||||
|
||||
def get_endpoint(self, auth=None, interface=None, **kwargs):
|
||||
"""Override get endpoint to automate endpoint filtering"""
|
||||
|
@@ -60,6 +60,16 @@ class TestProfile(base.TestCase):
|
||||
self.assertRaises(exceptions.SDKException, prof.set_version, 'bogus',
|
||||
'v2')
|
||||
|
||||
def test_set_api_version(self):
|
||||
# This tests that api_version is effective after explicit setting, or
|
||||
# else it defaults to None.
|
||||
prof = profile.Profile()
|
||||
prof.set_api_version('clustering', '1.2')
|
||||
svc = prof.get_filter('clustering')
|
||||
self.assertEqual('1.2', svc.api_version)
|
||||
svc = prof.get_filter('compute')
|
||||
self.assertIsNone(svc.api_version)
|
||||
|
||||
def test_set_all(self):
|
||||
prof = profile.Profile()
|
||||
prof.set_name(prof.ALL, 'fee')
|
||||
|
@@ -24,6 +24,16 @@ class TestValidVersion(testtools.TestCase):
|
||||
|
||||
|
||||
class TestServiceFilter(testtools.TestCase):
|
||||
def test_init(self):
|
||||
sot = service_filter.ServiceFilter(
|
||||
'ServiceType', region='REGION1', service_name='ServiceName',
|
||||
version='1', api_version='1.23')
|
||||
self.assertEqual('servicetype', sot.service_type)
|
||||
self.assertEqual('REGION1', sot.region)
|
||||
self.assertEqual('ServiceName', sot.service_name)
|
||||
self.assertEqual('1', sot.version)
|
||||
self.assertEqual('1.23', sot.api_version)
|
||||
|
||||
def test_get_module(self):
|
||||
sot = identity_service.IdentityService()
|
||||
self.assertEqual('openstack.identity.v3', sot.get_module())
|
||||
|
@@ -17,6 +17,7 @@ from keystoneauth1 import exceptions as _exceptions
|
||||
|
||||
from openstack import exceptions
|
||||
from openstack.image import image_service
|
||||
from openstack import profile
|
||||
from openstack import session
|
||||
|
||||
|
||||
@@ -41,14 +42,43 @@ class TestSession(testtools.TestCase):
|
||||
"http://127.0.0.1:9292/wot/v1/mytenant",
|
||||
session.parse_url(filt, "http://127.0.0.1:9292/wot/v2.0/mytenant"))
|
||||
|
||||
def test_user_agent_none(self):
|
||||
def test_init_user_agent_none(self):
|
||||
sot = session.Session(None)
|
||||
self.assertTrue(sot.user_agent.startswith("openstacksdk"))
|
||||
|
||||
def test_user_agent_set(self):
|
||||
def test_init_user_agent_set(self):
|
||||
sot = session.Session(None, user_agent="testing/123")
|
||||
self.assertTrue(sot.user_agent.startswith("testing/123 openstacksdk"))
|
||||
|
||||
def test_init_with_single_api_request(self):
|
||||
prof = profile.Profile()
|
||||
prof.set_api_version('clustering', '1.2')
|
||||
|
||||
sot = session.Session(prof)
|
||||
|
||||
# The assertion acutally tests the property assigned in parent class
|
||||
self.assertEqual({'openstack-api-version': 'clustering 1.2'},
|
||||
sot.additional_headers)
|
||||
|
||||
def test_init_with_multi_api_requests(self):
|
||||
prof = profile.Profile()
|
||||
prof.set_api_version('clustering', '1.2')
|
||||
prof.set_api_version('compute', '2.15')
|
||||
|
||||
sot = session.Session(prof)
|
||||
|
||||
versions = sot.additional_headers['openstack-api-version']
|
||||
requests = [req.strip() for req in versions.split(',')]
|
||||
self.assertIn('clustering 1.2', requests)
|
||||
self.assertIn('compute 2.15', requests)
|
||||
|
||||
def test_init_with_no_api_requests(self):
|
||||
prof = profile.Profile()
|
||||
|
||||
sot = session.Session(prof)
|
||||
|
||||
self.assertEqual({}, sot.additional_headers)
|
||||
|
||||
def test_map_exceptions_not_found_exception(self):
|
||||
ksa_exc = _exceptions.HttpError(message="test", http_status=404)
|
||||
func = mock.Mock(side_effect=ksa_exc)
|
||||
|
Reference in New Issue
Block a user