Add version discovery information to the /v1 endpoint
Currently we do not provide enough information for keystoneauth to work on. This makes version discovery impossible e.g. in a standalone case when the versioned endpoint is supplied by a user. This change adds the required versioning information based on the actual keystoneauth implementation and the in-progress API SIG specification: https://review.openstack.org/#/c/459710/ Note that this change is not microversioned, as it is used to discover available microversions for the versioned endpoint. Change-Id: Ibb1e8a1c8973a4742b7ba508dc84de577cb967c9 Story: #2003567 Task: #24859
This commit is contained in:
parent
d42343deea
commit
1f03a57268
@ -19,50 +19,10 @@ from pecan import rest
|
|||||||
from wsme import types as wtypes
|
from wsme import types as wtypes
|
||||||
|
|
||||||
from ironic.api.controllers import base
|
from ironic.api.controllers import base
|
||||||
from ironic.api.controllers import link
|
|
||||||
from ironic.api.controllers import v1
|
from ironic.api.controllers import v1
|
||||||
from ironic.api.controllers.v1 import versions
|
from ironic.api.controllers import version
|
||||||
from ironic.api import expose
|
from ironic.api import expose
|
||||||
|
|
||||||
ID_VERSION1 = 'v1'
|
|
||||||
|
|
||||||
|
|
||||||
class Version(base.APIBase):
|
|
||||||
"""An API version representation.
|
|
||||||
|
|
||||||
This class represents an API version, including the minimum and
|
|
||||||
maximum minor versions that are supported within the major version.
|
|
||||||
"""
|
|
||||||
|
|
||||||
id = wtypes.text
|
|
||||||
"""The ID of the (major) version, also acts as the release number"""
|
|
||||||
|
|
||||||
links = [link.Link]
|
|
||||||
"""A Link that point to a specific version of the API"""
|
|
||||||
|
|
||||||
status = wtypes.text
|
|
||||||
"""Status of the version.
|
|
||||||
|
|
||||||
One of:
|
|
||||||
* CURRENT - the latest version of API,
|
|
||||||
* SUPPORTED - supported, but not latest, version of API,
|
|
||||||
* DEPRECATED - supported, but deprecated, version of API.
|
|
||||||
"""
|
|
||||||
|
|
||||||
version = wtypes.text
|
|
||||||
"""The current, maximum supported (major.minor) version of API."""
|
|
||||||
|
|
||||||
min_version = wtypes.text
|
|
||||||
"""Minimum supported (major.minor) version of API."""
|
|
||||||
|
|
||||||
def __init__(self, id, min_version, version, status='CURRENT'):
|
|
||||||
self.id = id
|
|
||||||
self.links = [link.Link.make_link('self', pecan.request.public_url,
|
|
||||||
self.id, '', bookmark=True)]
|
|
||||||
self.status = status
|
|
||||||
self.version = version
|
|
||||||
self.min_version = min_version
|
|
||||||
|
|
||||||
|
|
||||||
class Root(base.APIBase):
|
class Root(base.APIBase):
|
||||||
|
|
||||||
@ -72,10 +32,10 @@ class Root(base.APIBase):
|
|||||||
description = wtypes.text
|
description = wtypes.text
|
||||||
"""Some information about this API"""
|
"""Some information about this API"""
|
||||||
|
|
||||||
versions = [Version]
|
versions = [version.Version]
|
||||||
"""Links to all the versions available in this API"""
|
"""Links to all the versions available in this API"""
|
||||||
|
|
||||||
default_version = Version
|
default_version = version.Version
|
||||||
"""A link to the default version of the API"""
|
"""A link to the default version of the API"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -84,19 +44,17 @@ class Root(base.APIBase):
|
|||||||
root.name = "OpenStack Ironic API"
|
root.name = "OpenStack Ironic API"
|
||||||
root.description = ("Ironic is an OpenStack project which aims to "
|
root.description = ("Ironic is an OpenStack project which aims to "
|
||||||
"provision baremetal machines.")
|
"provision baremetal machines.")
|
||||||
root.default_version = Version(ID_VERSION1,
|
root.default_version = version.default_version()
|
||||||
versions.min_version_string(),
|
|
||||||
versions.max_version_string())
|
|
||||||
root.versions = [root.default_version]
|
root.versions = [root.default_version]
|
||||||
return root
|
return root
|
||||||
|
|
||||||
|
|
||||||
class RootController(rest.RestController):
|
class RootController(rest.RestController):
|
||||||
|
|
||||||
_versions = [ID_VERSION1]
|
_versions = [version.ID_VERSION1]
|
||||||
"""All supported API versions"""
|
"""All supported API versions"""
|
||||||
|
|
||||||
_default_version = ID_VERSION1
|
_default_version = version.ID_VERSION1
|
||||||
"""The default API version"""
|
"""The default API version"""
|
||||||
|
|
||||||
v1 = v1.Controller()
|
v1 = v1.Controller()
|
||||||
|
@ -34,6 +34,7 @@ from ironic.api.controllers.v1 import ramdisk
|
|||||||
from ironic.api.controllers.v1 import utils
|
from ironic.api.controllers.v1 import utils
|
||||||
from ironic.api.controllers.v1 import versions
|
from ironic.api.controllers.v1 import versions
|
||||||
from ironic.api.controllers.v1 import volume
|
from ironic.api.controllers.v1 import volume
|
||||||
|
from ironic.api.controllers import version
|
||||||
from ironic.api import expose
|
from ironic.api import expose
|
||||||
from ironic.common.i18n import _
|
from ironic.common.i18n import _
|
||||||
|
|
||||||
@ -99,6 +100,9 @@ class V1(base.APIBase):
|
|||||||
heartbeat = [link.Link]
|
heartbeat = [link.Link]
|
||||||
"""Links to the heartbeat resource"""
|
"""Links to the heartbeat resource"""
|
||||||
|
|
||||||
|
version = version.Version
|
||||||
|
"""Version discovery information."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def convert():
|
def convert():
|
||||||
v1 = V1()
|
v1 = V1()
|
||||||
@ -174,6 +178,7 @@ class V1(base.APIBase):
|
|||||||
'heartbeat', '',
|
'heartbeat', '',
|
||||||
bookmark=True)
|
bookmark=True)
|
||||||
]
|
]
|
||||||
|
v1.version = version.default_version()
|
||||||
return v1
|
return v1
|
||||||
|
|
||||||
|
|
||||||
|
65
ironic/api/controllers/version.py
Normal file
65
ironic/api/controllers/version.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
import pecan
|
||||||
|
from wsme import types as wtypes
|
||||||
|
|
||||||
|
from ironic.api.controllers import base
|
||||||
|
from ironic.api.controllers import link
|
||||||
|
|
||||||
|
ID_VERSION1 = 'v1'
|
||||||
|
|
||||||
|
|
||||||
|
class Version(base.APIBase):
|
||||||
|
"""An API version representation.
|
||||||
|
|
||||||
|
This class represents an API version, including the minimum and
|
||||||
|
maximum minor versions that are supported within the major version.
|
||||||
|
"""
|
||||||
|
|
||||||
|
id = wtypes.text
|
||||||
|
"""The ID of the (major) version, also acts as the release number"""
|
||||||
|
|
||||||
|
links = [link.Link]
|
||||||
|
"""A Link that point to a specific version of the API"""
|
||||||
|
|
||||||
|
status = wtypes.text
|
||||||
|
"""Status of the version.
|
||||||
|
|
||||||
|
One of:
|
||||||
|
* CURRENT - the latest version of API,
|
||||||
|
* SUPPORTED - supported, but not latest, version of API,
|
||||||
|
* DEPRECATED - supported, but deprecated, version of API.
|
||||||
|
"""
|
||||||
|
|
||||||
|
version = wtypes.text
|
||||||
|
"""The current, maximum supported (major.minor) version of API."""
|
||||||
|
|
||||||
|
min_version = wtypes.text
|
||||||
|
"""Minimum supported (major.minor) version of API."""
|
||||||
|
|
||||||
|
def __init__(self, id, min_version, version, status='CURRENT'):
|
||||||
|
self.id = id
|
||||||
|
self.links = [link.Link.make_link('self', pecan.request.public_url,
|
||||||
|
self.id, '', bookmark=True)]
|
||||||
|
self.status = status
|
||||||
|
self.version = version
|
||||||
|
self.min_version = min_version
|
||||||
|
|
||||||
|
|
||||||
|
def default_version():
|
||||||
|
# NOTE(dtantsur): avoid circular imports
|
||||||
|
from ironic.api.controllers.v1 import versions
|
||||||
|
|
||||||
|
return Version(ID_VERSION1,
|
||||||
|
versions.min_version_string(),
|
||||||
|
versions.max_version_string())
|
@ -49,7 +49,7 @@ class TestV1Root(base.BaseApiTest):
|
|||||||
for f in data:
|
for f in data:
|
||||||
self.assertNotIn(f, ['', []])
|
self.assertNotIn(f, ['', []])
|
||||||
# Check if all known resources are present and there are no extra ones.
|
# Check if all known resources are present and there are no extra ones.
|
||||||
not_resources = ('id', 'links', 'media_types')
|
not_resources = ('id', 'links', 'media_types', 'version')
|
||||||
actual_resources = tuple(set(data) - set(not_resources))
|
actual_resources = tuple(set(data) - set(not_resources))
|
||||||
expected_resources = (['chassis', 'drivers', 'nodes', 'ports']
|
expected_resources = (['chassis', 'drivers', 'nodes', 'ports']
|
||||||
+ additional_expected_resources)
|
+ additional_expected_resources)
|
||||||
@ -57,6 +57,13 @@ class TestV1Root(base.BaseApiTest):
|
|||||||
self.assertIn({'type': 'application/vnd.openstack.ironic.v1+json',
|
self.assertIn({'type': 'application/vnd.openstack.ironic.v1+json',
|
||||||
'base': 'application/json'}, data['media_types'])
|
'base': 'application/json'}, data['media_types'])
|
||||||
|
|
||||||
|
version1 = data['version']
|
||||||
|
self.assertEqual('v1', version1['id'])
|
||||||
|
self.assertEqual('CURRENT', version1['status'])
|
||||||
|
self.assertEqual(versions.min_version_string(),
|
||||||
|
version1['min_version'])
|
||||||
|
self.assertEqual(versions.max_version_string(), version1['version'])
|
||||||
|
|
||||||
def test_get_v1_root(self):
|
def test_get_v1_root(self):
|
||||||
self._test_get_root()
|
self._test_get_root()
|
||||||
|
|
||||||
|
6
releasenotes/notes/v1-discovery-4311398040581fe8.yaml
Normal file
6
releasenotes/notes/v1-discovery-4311398040581fe8.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Adds the version discovery information to the versioned API endpoint
|
||||||
|
(``/v1``). This allows *keystoneauth* version discovery to work on this
|
||||||
|
endpoint.
|
Loading…
Reference in New Issue
Block a user