Merge "Raise minimum API version to 1.1"
This commit is contained in:
commit
5b9f1ca53a
@ -84,8 +84,10 @@ class Version(object):
|
|||||||
:raises: webob.HTTPNotAcceptable
|
:raises: webob.HTTPNotAcceptable
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
# default to the minimum supported version, but don't actually
|
||||||
|
# import v1.__init__ here because that would be circular...
|
||||||
version = tuple(int(i) for i in headers.get(
|
version = tuple(int(i) for i in headers.get(
|
||||||
Version.string, '1.0').split('.'))
|
Version.string, '1.1').split('.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
version = ()
|
version = ()
|
||||||
if len(version) != 2:
|
if len(version) != 2:
|
||||||
@ -103,3 +105,13 @@ class Version(object):
|
|||||||
"""
|
"""
|
||||||
self.min = min
|
self.min = min
|
||||||
self.max = max
|
self.max = max
|
||||||
|
|
||||||
|
def __lt__(a, b):
|
||||||
|
if (a.major == b.major and a.minor < b.minor):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __gt__(a, b):
|
||||||
|
if (a.major == b.major and a.minor > b.minor):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
@ -36,9 +36,29 @@ from ironic.api.controllers.v1 import node
|
|||||||
from ironic.api.controllers.v1 import port
|
from ironic.api.controllers.v1 import port
|
||||||
from ironic.common.i18n import _
|
from ironic.common.i18n import _
|
||||||
|
|
||||||
|
BASE_VERSION = 1
|
||||||
|
|
||||||
MIN_VER = 0
|
# NOTE(deva): v1.0 is reserved to indicate Juno's API, but is not presently
|
||||||
MAX_VER = 2
|
# supported by the API service. All changes between Juno and the
|
||||||
|
# point where we added microversioning are considered backwards-
|
||||||
|
# compatible, but are not specifically discoverable at this time.
|
||||||
|
#
|
||||||
|
# The v1.1 version indicates this "initial" version as being
|
||||||
|
# different from Juno (v1.0), and includes the following changes:
|
||||||
|
#
|
||||||
|
# 827db7fe: Add Node.maintenance_reason
|
||||||
|
# 68eed82b: Add API endpoint to set/unset the node maintenance mode
|
||||||
|
# bc973889: Add sync and async support for passthru methods
|
||||||
|
# e03f443b: Vendor endpoints to support different HTTP methods
|
||||||
|
# e69e5309: Make vendor methods discoverable via the Ironic API
|
||||||
|
# edf532db: Add logic to store the config drive passed by Nova
|
||||||
|
|
||||||
|
# v1.1: API at the point in time when microversioning support was added
|
||||||
|
MIN_VER = base.Version({base.Version.string: "1.1"})
|
||||||
|
|
||||||
|
# v1.2: Renamed NOSTATE ("None") to AVAILABLE ("available")
|
||||||
|
# v1.3: Add node.driver_internal_info
|
||||||
|
MAX_VER = base.Version({base.Version.string: "1.3"})
|
||||||
|
|
||||||
|
|
||||||
class MediaType(base.APIBase):
|
class MediaType(base.APIBase):
|
||||||
@ -138,13 +158,13 @@ class Controller(rest.RestController):
|
|||||||
|
|
||||||
def _check_version(self, version):
|
def _check_version(self, version):
|
||||||
# ensure that major version in the URL matches the header
|
# ensure that major version in the URL matches the header
|
||||||
if version.major != 1:
|
if version.major != BASE_VERSION:
|
||||||
raise exc.HTTPNotAcceptable(_(
|
raise exc.HTTPNotAcceptable(_(
|
||||||
"Mutually exclusive versions requested. Version %(ver)s "
|
"Mutually exclusive versions requested. Version %(ver)s "
|
||||||
"requested but not supported by this service.")
|
"requested but not supported by this service.")
|
||||||
% {'ver': version})
|
% {'ver': version})
|
||||||
# ensure the minor version is within the supported range
|
# ensure the minor version is within the supported range
|
||||||
if version.minor < MIN_VER or version.minor > MAX_VER:
|
if version < MIN_VER or version > MAX_VER:
|
||||||
raise exc.HTTPNotAcceptable(_(
|
raise exc.HTTPNotAcceptable(_(
|
||||||
"Unsupported minor version requested. This API service "
|
"Unsupported minor version requested. This API service "
|
||||||
"supports the following version range: "
|
"supports the following version range: "
|
||||||
|
@ -56,15 +56,15 @@ _VENDOR_METHODS = {}
|
|||||||
|
|
||||||
|
|
||||||
def assert_juno_provision_state_name(obj):
|
def assert_juno_provision_state_name(obj):
|
||||||
# if requested version is < 1.1, convert AVAILABLE to the old NOSTATE
|
# if requested version is < 1.2, convert AVAILABLE to the old NOSTATE
|
||||||
if (pecan.request.version.minor < 1 and
|
if (pecan.request.version.minor < 2 and
|
||||||
obj.provision_state == ir_states.AVAILABLE):
|
obj.provision_state == ir_states.AVAILABLE):
|
||||||
obj.provision_state = ir_states.NOSTATE
|
obj.provision_state = ir_states.NOSTATE
|
||||||
|
|
||||||
|
|
||||||
def hide_driver_internal_info(obj):
|
def hide_driver_internal_info(obj):
|
||||||
# if requested version is < 1.2, hide driver_internal_info
|
# if requested version is < 1.3, hide driver_internal_info
|
||||||
if pecan.request.version.minor < 2:
|
if pecan.request.version.minor < 3:
|
||||||
obj.driver_internal_info = wsme.Unset
|
obj.driver_internal_info = wsme.Unset
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,6 +75,6 @@ class TestVersion(base.FunctionalTest):
|
|||||||
{cbase.Version.string: '1.2.3'})
|
{cbase.Version.string: '1.2.3'})
|
||||||
|
|
||||||
def test_parse_no_header(self):
|
def test_parse_no_header(self):
|
||||||
# this asserts that the minimum version string of "1.0" is applied
|
# this asserts that the minimum version string of "1.1" is applied
|
||||||
version = cbase.Version.parse_headers({})
|
version = cbase.Version.parse_headers({})
|
||||||
self.assertEqual((1, 0), version)
|
self.assertEqual((1, 1), version)
|
||||||
|
@ -26,6 +26,7 @@ from testtools.matchers import HasLength
|
|||||||
from wsme import types as wtypes
|
from wsme import types as wtypes
|
||||||
|
|
||||||
from ironic.api.controllers import base as api_base
|
from ironic.api.controllers import base as api_base
|
||||||
|
from ironic.api.controllers import v1 as api_v1
|
||||||
from ironic.api.controllers.v1 import node as api_node
|
from ironic.api.controllers.v1 import node as api_node
|
||||||
from ironic.common import boot_devices
|
from ironic.common import boot_devices
|
||||||
from ironic.common import exception
|
from ironic.common import exception
|
||||||
@ -94,7 +95,7 @@ class TestListNodes(test_api_base.FunctionalTest):
|
|||||||
def test_one(self):
|
def test_one(self):
|
||||||
node = obj_utils.create_test_node(self.context)
|
node = obj_utils.create_test_node(self.context)
|
||||||
data = self.get_json('/nodes',
|
data = self.get_json('/nodes',
|
||||||
headers={api_base.Version.string: "1.2"})
|
headers={api_base.Version.string: str(api_v1.MAX_VER)})
|
||||||
self.assertIn('instance_uuid', data['nodes'][0])
|
self.assertIn('instance_uuid', data['nodes'][0])
|
||||||
self.assertIn('maintenance', data['nodes'][0])
|
self.assertIn('maintenance', data['nodes'][0])
|
||||||
self.assertIn('power_state', data['nodes'][0])
|
self.assertIn('power_state', data['nodes'][0])
|
||||||
@ -119,7 +120,7 @@ class TestListNodes(test_api_base.FunctionalTest):
|
|||||||
def test_get_one(self):
|
def test_get_one(self):
|
||||||
node = obj_utils.create_test_node(self.context)
|
node = obj_utils.create_test_node(self.context)
|
||||||
data = self.get_json('/nodes/%s' % node['uuid'],
|
data = self.get_json('/nodes/%s' % node['uuid'],
|
||||||
headers={api_base.Version.string: "1.2"})
|
headers={api_base.Version.string: str(api_v1.MAX_VER)})
|
||||||
self.assertEqual(node.uuid, data['uuid'])
|
self.assertEqual(node.uuid, data['uuid'])
|
||||||
self.assertIn('driver', data)
|
self.assertIn('driver', data)
|
||||||
self.assertIn('driver_info', data)
|
self.assertIn('driver_info', data)
|
||||||
@ -163,22 +164,22 @@ class TestListNodes(test_api_base.FunctionalTest):
|
|||||||
provision_state=states.AVAILABLE)
|
provision_state=states.AVAILABLE)
|
||||||
|
|
||||||
data = self.get_json('/nodes/%s' % node['uuid'],
|
data = self.get_json('/nodes/%s' % node['uuid'],
|
||||||
headers={api_base.Version.string: "1.0"})
|
headers={api_base.Version.string: str(api_v1.MIN_VER)})
|
||||||
self.assertEqual(states.NOSTATE, data['provision_state'])
|
self.assertEqual(states.NOSTATE, data['provision_state'])
|
||||||
|
|
||||||
data = self.get_json('/nodes/%s' % node['uuid'],
|
data = self.get_json('/nodes/%s' % node['uuid'],
|
||||||
headers={api_base.Version.string: "1.1"})
|
headers={api_base.Version.string: "1.2"})
|
||||||
self.assertEqual(states.AVAILABLE, data['provision_state'])
|
self.assertEqual(states.AVAILABLE, data['provision_state'])
|
||||||
|
|
||||||
def test_hide_driver_internal_info(self):
|
def test_hide_driver_internal_info(self):
|
||||||
node = obj_utils.create_test_node(self.context,
|
node = obj_utils.create_test_node(self.context,
|
||||||
driver_internal_info={"foo": "bar"})
|
driver_internal_info={"foo": "bar"})
|
||||||
data = self.get_json('/nodes/%s' % node['uuid'],
|
data = self.get_json('/nodes/%s' % node['uuid'],
|
||||||
headers={api_base.Version.string: "1.0"})
|
headers={api_base.Version.string: str(api_v1.MIN_VER)})
|
||||||
self.assertNotIn('driver_internal_info', data)
|
self.assertNotIn('driver_internal_info', data)
|
||||||
|
|
||||||
data = self.get_json('/nodes/%s' % node['uuid'],
|
data = self.get_json('/nodes/%s' % node['uuid'],
|
||||||
headers={api_base.Version.string: "1.2"})
|
headers={api_base.Version.string: "1.3"})
|
||||||
self.assertEqual({"foo": "bar"}, data['driver_internal_info'])
|
self.assertEqual({"foo": "bar"}, data['driver_internal_info'])
|
||||||
|
|
||||||
def test_many(self):
|
def test_many(self):
|
||||||
|
@ -44,31 +44,31 @@ class TestCheckVersions(test_base.TestCase):
|
|||||||
self.version = ver()
|
self.version = ver()
|
||||||
|
|
||||||
def test_check_version_invalid_major_version(self):
|
def test_check_version_invalid_major_version(self):
|
||||||
self.version.major = 2
|
self.version.major = v1_api.BASE_VERSION + 1
|
||||||
self.version.minor = v1_api.MIN_VER
|
self.version.minor = v1_api.MIN_VER.minor
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
webob_exc.HTTPNotAcceptable,
|
webob_exc.HTTPNotAcceptable,
|
||||||
v1_api.Controller()._check_version,
|
v1_api.Controller()._check_version,
|
||||||
self.version)
|
self.version)
|
||||||
|
|
||||||
def test_check_version_too_low(self):
|
def test_check_version_too_low(self):
|
||||||
self.version.major = 1
|
self.version.major = v1_api.BASE_VERSION
|
||||||
self.version.minor = v1_api.MIN_VER - 1
|
self.version.minor = v1_api.MIN_VER.minor - 1
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
webob_exc.HTTPNotAcceptable,
|
webob_exc.HTTPNotAcceptable,
|
||||||
v1_api.Controller()._check_version,
|
v1_api.Controller()._check_version,
|
||||||
self.version)
|
self.version)
|
||||||
|
|
||||||
def test_check_version_too_high(self):
|
def test_check_version_too_high(self):
|
||||||
self.version.major = 1
|
self.version.major = v1_api.BASE_VERSION
|
||||||
self.version.minor = v1_api.MAX_VER + 1
|
self.version.minor = v1_api.MAX_VER.minor + 1
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
webob_exc.HTTPNotAcceptable,
|
webob_exc.HTTPNotAcceptable,
|
||||||
v1_api.Controller()._check_version,
|
v1_api.Controller()._check_version,
|
||||||
self.version)
|
self.version)
|
||||||
|
|
||||||
def test_check_version_ok(self):
|
def test_check_version_ok(self):
|
||||||
self.version.major = 1
|
self.version.major = v1_api.BASE_VERSION
|
||||||
self.version.minor = v1_api.MIN_VER
|
self.version.minor = v1_api.MIN_VER.minor
|
||||||
v1_api.Controller()._check_version(self.version)
|
v1_api.Controller()._check_version(self.version)
|
||||||
self.assertEqual(1, self.version.set_min_max.call_count)
|
self.assertEqual(1, self.version.set_min_max.call_count)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user