Merge "Raise minimum API version to 1.1"

This commit is contained in:
Jenkins 2015-02-05 12:13:09 +00:00 committed by Gerrit Code Review
commit 5b9f1ca53a
6 changed files with 58 additions and 25 deletions

View File

@ -84,8 +84,10 @@ class Version(object):
:raises: webob.HTTPNotAcceptable
"""
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.string, '1.0').split('.'))
Version.string, '1.1').split('.'))
except ValueError:
version = ()
if len(version) != 2:
@ -103,3 +105,13 @@ class Version(object):
"""
self.min = min
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

View File

@ -36,9 +36,29 @@ from ironic.api.controllers.v1 import node
from ironic.api.controllers.v1 import port
from ironic.common.i18n import _
BASE_VERSION = 1
MIN_VER = 0
MAX_VER = 2
# NOTE(deva): v1.0 is reserved to indicate Juno's API, but is not presently
# 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):
@ -138,13 +158,13 @@ class Controller(rest.RestController):
def _check_version(self, version):
# ensure that major version in the URL matches the header
if version.major != 1:
if version.major != BASE_VERSION:
raise exc.HTTPNotAcceptable(_(
"Mutually exclusive versions requested. Version %(ver)s "
"requested but not supported by this service.")
% {'ver': version})
# 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(_(
"Unsupported minor version requested. This API service "
"supports the following version range: "

View File

@ -56,15 +56,15 @@ _VENDOR_METHODS = {}
def assert_juno_provision_state_name(obj):
# if requested version is < 1.1, convert AVAILABLE to the old NOSTATE
if (pecan.request.version.minor < 1 and
# if requested version is < 1.2, convert AVAILABLE to the old NOSTATE
if (pecan.request.version.minor < 2 and
obj.provision_state == ir_states.AVAILABLE):
obj.provision_state = ir_states.NOSTATE
def hide_driver_internal_info(obj):
# if requested version is < 1.2, hide driver_internal_info
if pecan.request.version.minor < 2:
# if requested version is < 1.3, hide driver_internal_info
if pecan.request.version.minor < 3:
obj.driver_internal_info = wsme.Unset

View File

@ -75,6 +75,6 @@ class TestVersion(base.FunctionalTest):
{cbase.Version.string: '1.2.3'})
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({})
self.assertEqual((1, 0), version)
self.assertEqual((1, 1), version)

View File

@ -26,6 +26,7 @@ from testtools.matchers import HasLength
from wsme import types as wtypes
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.common import boot_devices
from ironic.common import exception
@ -94,7 +95,7 @@ class TestListNodes(test_api_base.FunctionalTest):
def test_one(self):
node = obj_utils.create_test_node(self.context)
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('maintenance', 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):
node = obj_utils.create_test_node(self.context)
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.assertIn('driver', data)
self.assertIn('driver_info', data)
@ -163,22 +164,22 @@ class TestListNodes(test_api_base.FunctionalTest):
provision_state=states.AVAILABLE)
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'])
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'])
def test_hide_driver_internal_info(self):
node = obj_utils.create_test_node(self.context,
driver_internal_info={"foo": "bar"})
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)
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'])
def test_many(self):

View File

@ -44,31 +44,31 @@ class TestCheckVersions(test_base.TestCase):
self.version = ver()
def test_check_version_invalid_major_version(self):
self.version.major = 2
self.version.minor = v1_api.MIN_VER
self.version.major = v1_api.BASE_VERSION + 1
self.version.minor = v1_api.MIN_VER.minor
self.assertRaises(
webob_exc.HTTPNotAcceptable,
v1_api.Controller()._check_version,
self.version)
def test_check_version_too_low(self):
self.version.major = 1
self.version.minor = v1_api.MIN_VER - 1
self.version.major = v1_api.BASE_VERSION
self.version.minor = v1_api.MIN_VER.minor - 1
self.assertRaises(
webob_exc.HTTPNotAcceptable,
v1_api.Controller()._check_version,
self.version)
def test_check_version_too_high(self):
self.version.major = 1
self.version.minor = v1_api.MAX_VER + 1
self.version.major = v1_api.BASE_VERSION
self.version.minor = v1_api.MAX_VER.minor + 1
self.assertRaises(
webob_exc.HTTPNotAcceptable,
v1_api.Controller()._check_version,
self.version)
def test_check_version_ok(self):
self.version.major = 1
self.version.minor = v1_api.MIN_VER
self.version.major = v1_api.BASE_VERSION
self.version.minor = v1_api.MIN_VER.minor
v1_api.Controller()._check_version(self.version)
self.assertEqual(1, self.version.set_min_max.call_count)