diff --git a/doc/source/using-sessions.rst b/doc/source/using-sessions.rst index 1daddaf5..ffd140f1 100644 --- a/doc/source/using-sessions.rst +++ b/doc/source/using-sessions.rst @@ -375,14 +375,64 @@ the ``microversion`` parameter of the `request` method on the to pass the appropriate header to the service informing the service of the microversion the user wants. +.. code-block:: python + + resp = session.get('/volumes', + microversion='3.15', + endpoint_filter={'service_type': 'volume', + 'interface': 'public', + 'min_version': '3', + 'max_version': 'latest'}) + If the user is using a :class:`keystoneauth1.adapter.Adapter`, the `service_type`, which is a part of the data sent in the microversion header, will be taken from the Adapter's `service_type`. +.. code-block:: python + + adapter = keystoneauth1.adapter.Adapter( + session=session, + service_type='compute', + interface='public', + min_version='2.1') + response = adapter.get('/servers', microversion='2.38') + +The user can also provide a ``default_microversion`` parameter to the Adapter +constructor which will be used on all requests where an explicit microversion +is not requested. + +.. code-block:: python + + adapter = keystoneauth1.adapter.Adapter( + session=session, + service_type='compute', + interface='public', + min_version='2.1', + default_microversion='2.38') + response = adapter.get('/servers') + If the user is using a :class:`keystoneauth1.session.Session`, the -`service_type` will be taken from the `service_type` in `endpoint_filter` -or alternately from the parameter `microversion_service_type` in case there -is no `service_type` in `endpoint_filter` for some reason. +`service_type` will be taken from the `service_type` in `endpoint_filter`. + +If the `service_type` is the incorrect value to use for the microversion header +for the service in question, the parameter `microversion_service_type` can be +given. For instance, although keystoneauth already knows about Cinder, the +`service_type` for Cinder is ``block-storage`` but the microversion header +expects ``volume``. + +.. code-block:: python + + # Interactions with cinder do not need to explicitly override the + # microversion_service_type - it is only being used as an example for the + # use of the parameter. + resp = session.get('/volumes', + microversion='3.15', + microversion_service_type='volume', + endpoint_filter={'service_type': 'block-storage', + 'interface': 'public', + 'min_version': '3', + 'max_version': 'latest'}) + .. _API-WG Specs: http://specs.openstack.org/openstack/api-wg/ .. _Consuming the Catalog: http://specs.openstack.org/openstack/api-wg/guidelines/consuming-catalog.html diff --git a/keystoneauth1/session.py b/keystoneauth1/session.py index bef5d566..c35182d1 100644 --- a/keystoneauth1/session.py +++ b/keystoneauth1/session.py @@ -444,7 +444,7 @@ class Session(object): " service_type information is available. Either provide a" " service_type in endpoint_filter or pass" " microversion_service_type as an argument.".format( - microversion=discover.version_to_string(microversion))) + microversion=microversion)) # TODO(mordred) cinder uses volume in its microversion header. This # logic should be handled in the future by os-service-types but for @@ -452,17 +452,13 @@ class Session(object): if (service_type.startswith('volume') or service_type == 'block-storage'): service_type = 'volume' - # TODO(mordred) Fix this as part of the service-types generalized - # fix. Ironic does not yet support the new version header - if service_type != 'baremetal': - headers.setdefault('OpenStack-API-Version', - '{service_type} {microversion}'.format( - service_type=service_type, - microversion=microversion)) + headers.setdefault('OpenStack-API-Version', + '{service_type} {microversion}'.format( + service_type=service_type, + microversion=microversion)) header_names = _mv_legacy_headers_for_service(service_type) for h in header_names: headers.setdefault(h, microversion) - return headers @positional() def request(self, url, method, json=None, original_ip=None, @@ -546,10 +542,10 @@ class Session(object): :param str microversion_service_type: The service_type to be sent in the microversion header, if a microversion is given. Defaults to the value of service_type from - endpoint_filter if one exists. If endpoint_filter - does not have a service_type, microversion is given and - microversion_service_type is not provided, an exception - will be raised. + endpoint_filter if one exists. If endpoint_filter is not + provided or does not have a service_type, microversion + is given and microversion_service_type is not provided, + an exception will be raised. :param kwargs: any other parameter that can be passed to :meth:`requests.Session.request` (such as `headers`). Except: diff --git a/keystoneauth1/tests/unit/test_session.py b/keystoneauth1/tests/unit/test_session.py index 1a6a9577..cba898bf 100644 --- a/keystoneauth1/tests/unit/test_session.py +++ b/keystoneauth1/tests/unit/test_session.py @@ -127,8 +127,9 @@ class SessionTests(utils.TestCase): headers = {} client_session.Session._set_microversion_headers( headers, '2.30', 'baremetal', None) + self.assertEqual(headers['OpenStack-API-Version'], 'baremetal 2.30') self.assertEqual(headers['X-OpenStack-Ironic-API-Version'], '2.30') - self.assertEqual(len(headers.keys()), 1) + self.assertEqual(len(headers.keys()), 2) # volumev2 service-type - volume microversion headers = {} @@ -183,6 +184,7 @@ class SessionTests(utils.TestCase): self.assertTrue(resp.ok) self.assertRequestHeaderEqual('OpenStack-API-Version', 'compute 2.30') + self.assertRequestHeaderEqual('X-OpenStack-Nova-API-Version', '2.30') def test_user_agent(self): session = client_session.Session() diff --git a/releasenotes/notes/microversion-header-support-901acd820a21d788.yaml b/releasenotes/notes/microversion-header-support-901acd820a21d788.yaml new file mode 100644 index 00000000..3f841f36 --- /dev/null +++ b/releasenotes/notes/microversion-header-support-901acd820a21d788.yaml @@ -0,0 +1,6 @@ +--- +features: + - Added support for specifying a microversion to use on + a given REST request. The microversion can be specified + on session request calls and a default can be set on + Adapter construction.