Add support for next_min_version and not_before
The API-WG just approved the spec for version discovery documents to optionally provide "next_min_version" and "not_before" information. http://specs.openstack.org/openstack/api-wg/guidelines/microversion_specification.html#version-discovery The intended use of these is to communicate that at a point in the future the service plans to raise the minimum microversion. It can't say when that will happen, as a service does not know when deployers will decide to upgrade their services. But it can communicate the earliest date it's possible to happen, which would be the first date the service itself would raise the minimum. This can be used to emit warnings to users who are using a microversion less than the next_min_version and to tell them how long they have to think about it. Currently keystoneauth will not consume these for that purpose. This patch is merely about collecting the information from the discovery document if it is there so a consumer can take action on it if they wish. Change-Id: Ibc404ef55eeae721a0d1d16e4e3e51ad77b5a75c
This commit is contained in:
parent
de41fec992
commit
24b09f4088
|
@ -170,6 +170,9 @@ The overall transaction then has three parts:
|
|||
Major API of a given service, as well as reporting the available microversion
|
||||
ranges that endpoint supports, if any.
|
||||
|
||||
More information is available in the `API-WG Specs`_ on the topics of
|
||||
`Microversions`_ and `Consuming the Catalog`_.
|
||||
|
||||
Authentication
|
||||
--------------
|
||||
|
||||
|
@ -349,7 +352,11 @@ of ranges, lists of input values or ``latest`` version.
|
|||
|
||||
It can also be used to determine the `min_microversion` and `max_microversion`
|
||||
supported by the API. If an API does not support microversions, the values for
|
||||
both will be ``None``.
|
||||
both will be ``None``. It will also contain values for `next_min_version` and
|
||||
`not_before` if they exist for the endpoint, or ``None`` if they do not. The
|
||||
:class:`keystoneauth1.discovery.EndpointData` object will always contain
|
||||
microversion related attributes regardless of whether the REST document does
|
||||
or not.
|
||||
|
||||
``get_endpoint_data`` makes use of the same cache as the rest of the discovery
|
||||
process, so calling it should incur no undue expense. By default it will make
|
||||
|
@ -357,3 +364,8 @@ at least one version discovery call so that it can fetch microversion metadata.
|
|||
If the user knows a service does not support microversions and is merely
|
||||
curious as to which major version was discovered, `discover_versions` can be
|
||||
set to `False` to prevent fetching microversion metadata.
|
||||
|
||||
.. _API-WG Specs: http://specs.openstack.org/openstack/api-wg/
|
||||
.. _Consuming the Catalog: http://specs.openstack.org/openstack/api-wg/guidelines/consuming-catalog.html
|
||||
.. _Microversions: http://specs.openstack.org/openstack/api-wg/guidelines/microversion_specification.html#version-discovery
|
||||
|
||||
|
|
|
@ -390,6 +390,10 @@ class Discover(object):
|
|||
max_microversion = v.get('version') or None
|
||||
if max_microversion:
|
||||
max_microversion = normalize_version_number(max_microversion)
|
||||
next_min_version = v.get('next_min_version') or None
|
||||
if next_min_version:
|
||||
next_min_version = normalize_version_number(next_min_version)
|
||||
not_before = v.get('not_before') or None
|
||||
|
||||
self_url = None
|
||||
collection_url = None
|
||||
|
@ -416,6 +420,8 @@ class Discover(object):
|
|||
'collection': collection_url,
|
||||
'min_microversion': min_microversion,
|
||||
'max_microversion': max_microversion,
|
||||
'next_min_version': next_min_version,
|
||||
'not_before': not_before,
|
||||
'raw_status': v['status']})
|
||||
|
||||
versions.sort(key=lambda v: v['version'], reverse=reverse)
|
||||
|
@ -581,7 +587,9 @@ class EndpointData(object):
|
|||
api_version=None,
|
||||
major_version=None,
|
||||
min_microversion=None,
|
||||
max_microversion=None):
|
||||
max_microversion=None,
|
||||
next_min_version=None,
|
||||
not_before=None):
|
||||
self.catalog_url = catalog_url
|
||||
self.service_url = service_url
|
||||
self.service_type = service_type
|
||||
|
@ -595,6 +603,8 @@ class EndpointData(object):
|
|||
self.major_version = major_version
|
||||
self.min_microversion = min_microversion
|
||||
self.max_microversion = max_microversion
|
||||
self.next_min_version = next_min_version
|
||||
self.not_before = not_before
|
||||
self._saved_project_id = None
|
||||
self._catalog_matches_version = False
|
||||
self._catalog_matches_exactly = False
|
||||
|
@ -615,7 +625,9 @@ class EndpointData(object):
|
|||
api_version=self.api_version,
|
||||
major_version=self.major_version,
|
||||
min_microversion=self.min_microversion,
|
||||
max_microversion=self.max_microversion)
|
||||
max_microversion=self.max_microversion,
|
||||
next_min_version=self.next_min_version,
|
||||
not_before=self.not_before)
|
||||
# Save cached discovery object - but we don't want to
|
||||
# actually provide a constructor argument
|
||||
new_data._disc = self._disc
|
||||
|
@ -752,6 +764,8 @@ class EndpointData(object):
|
|||
|
||||
self.min_microversion = discovered_data['min_microversion']
|
||||
self.max_microversion = discovered_data['max_microversion']
|
||||
self.next_min_version = discovered_data['next_min_version']
|
||||
self.not_before = discovered_data['not_before']
|
||||
|
||||
# TODO(mordred): these next two things should be done by Discover
|
||||
# in versioned_data_for.
|
||||
|
|
|
@ -157,6 +157,8 @@ CINDER_EXAMPLES = {
|
|||
"id": "v3.0",
|
||||
"version": "3.27",
|
||||
"min_version": "3.0",
|
||||
"next_min_version": "3.4",
|
||||
"not_before": "2019-12-31",
|
||||
"links": [
|
||||
{
|
||||
"href": BASE_URL,
|
||||
|
@ -415,21 +417,31 @@ class VersionDataTests(utils.TestCase):
|
|||
|
||||
# no version info in input
|
||||
test_ok({},
|
||||
{'min_microversion': None, 'max_microversion': None})
|
||||
{'min_microversion': None, 'max_microversion': None,
|
||||
'next_min_version': None, 'not_before': None})
|
||||
|
||||
# version => max_microversion
|
||||
test_ok({'version': '2.2'},
|
||||
{'min_microversion': None, 'max_microversion': (2, 2)})
|
||||
{'min_microversion': None, 'max_microversion': (2, 2),
|
||||
'next_min_version': None, 'not_before': None})
|
||||
|
||||
# max_version supersedes version (even if malformed). min_version &
|
||||
# normalization.
|
||||
test_ok({'min_version': '2', 'version': 'foo', 'max_version': '2.2'},
|
||||
{'min_microversion': (2, 0), 'max_microversion': (2, 2)})
|
||||
{'min_microversion': (2, 0), 'max_microversion': (2, 2),
|
||||
'next_min_version': None, 'not_before': None})
|
||||
|
||||
# Edge case: min/max_version ignored if present but "empty"; version
|
||||
# used for max_microversion.
|
||||
test_ok({'min_version': '', 'version': '2.1', 'max_version': ''},
|
||||
{'min_microversion': None, 'max_microversion': (2, 1)})
|
||||
{'min_microversion': None, 'max_microversion': (2, 1),
|
||||
'next_min_version': None, 'not_before': None})
|
||||
|
||||
# next_min_version set
|
||||
test_ok({'min_version': '2', 'max_version': '2.2',
|
||||
'next_min_version': '2.1', 'not_before': '2019-07-01'},
|
||||
{'min_microversion': (2, 0), 'max_microversion': (2, 2),
|
||||
'next_min_version': (2, 1), 'not_before': '2019-07-01'})
|
||||
|
||||
# Badly-formatted min_version
|
||||
test_exc({'min_version': 'foo', 'max_version': '2.1'})
|
||||
|
@ -440,6 +452,9 @@ class VersionDataTests(utils.TestCase):
|
|||
# Badly-formatted version (when max_version omitted)
|
||||
test_exc({'min_version': '2.1', 'version': 'foo'})
|
||||
|
||||
# Badly-formatted next_min_version
|
||||
test_exc({'next_min_version': 'bogus', 'not_before': '2019-07-01'})
|
||||
|
||||
def test_data_for_url(self):
|
||||
mock = self.requests_mock.get(V3_URL,
|
||||
status_code=200,
|
||||
|
@ -542,6 +557,8 @@ class VersionDataTests(utils.TestCase):
|
|||
'collection': None,
|
||||
'max_microversion': None,
|
||||
'min_microversion': None,
|
||||
'next_min_version': None,
|
||||
'not_before': None,
|
||||
'version': (1, 0),
|
||||
'url': v1_url,
|
||||
'raw_status': 'CURRENT',
|
||||
|
@ -550,6 +567,8 @@ class VersionDataTests(utils.TestCase):
|
|||
'collection': None,
|
||||
'max_microversion': None,
|
||||
'min_microversion': None,
|
||||
'next_min_version': None,
|
||||
'not_before': None,
|
||||
'version': (2, 0),
|
||||
'url': v2_url,
|
||||
'raw_status': 'CURRENT',
|
||||
|
@ -558,6 +577,8 @@ class VersionDataTests(utils.TestCase):
|
|||
'collection': BASE_URL,
|
||||
'max_microversion': (3, 27),
|
||||
'min_microversion': (3, 0),
|
||||
'next_min_version': (3, 4),
|
||||
'not_before': u'2019-12-31',
|
||||
'version': (3, 0),
|
||||
'url': v3_url,
|
||||
'raw_status': 'CURRENT',
|
||||
|
@ -610,6 +631,8 @@ class VersionDataTests(utils.TestCase):
|
|||
'collection': None,
|
||||
'max_microversion': None,
|
||||
'min_microversion': None,
|
||||
'next_min_version': None,
|
||||
'not_before': None,
|
||||
'version': (1, 0),
|
||||
'url': v1_url,
|
||||
'raw_status': 'SUPPORTED',
|
||||
|
@ -618,6 +641,8 @@ class VersionDataTests(utils.TestCase):
|
|||
'collection': None,
|
||||
'max_microversion': None,
|
||||
'min_microversion': None,
|
||||
'next_min_version': None,
|
||||
'not_before': None,
|
||||
'version': (1, 1),
|
||||
'url': v1_url,
|
||||
'raw_status': 'CURRENT',
|
||||
|
@ -626,6 +651,8 @@ class VersionDataTests(utils.TestCase):
|
|||
'collection': None,
|
||||
'max_microversion': None,
|
||||
'min_microversion': None,
|
||||
'next_min_version': None,
|
||||
'not_before': None,
|
||||
'version': (2, 0),
|
||||
'url': v2_url,
|
||||
'raw_status': 'SUPPORTED',
|
||||
|
@ -634,6 +661,8 @@ class VersionDataTests(utils.TestCase):
|
|||
'collection': None,
|
||||
'max_microversion': None,
|
||||
'min_microversion': None,
|
||||
'next_min_version': None,
|
||||
'not_before': None,
|
||||
'version': (2, 1),
|
||||
'url': v2_url,
|
||||
'raw_status': 'SUPPORTED',
|
||||
|
@ -642,6 +671,8 @@ class VersionDataTests(utils.TestCase):
|
|||
'collection': None,
|
||||
'max_microversion': None,
|
||||
'min_microversion': None,
|
||||
'next_min_version': None,
|
||||
'not_before': None,
|
||||
'version': (2, 2),
|
||||
'url': v2_url,
|
||||
'raw_status': 'CURRENT',
|
||||
|
|
Loading…
Reference in New Issue