diff --git a/novaclient/api_versions.py b/novaclient/api_versions.py index 5ff52b8f5..59b8c1cbc 100644 --- a/novaclient/api_versions.py +++ b/novaclient/api_versions.py @@ -14,7 +14,6 @@ import functools import logging import os -import pkgutil import re import traceback import warnings @@ -195,35 +194,59 @@ class VersionedMethod(object): def get_available_major_versions(): - # NOTE(andreykurilin): available clients version should not be - # hardcoded, so let's discover them. - matcher = re.compile(r"v[0-9]*$") - submodules = pkgutil.iter_modules([os.path.dirname(__file__)]) - available_versions = [name[1:] for loader, name, ispkg in submodules - if matcher.search(name)] - - return available_versions + return ['2'] def check_major_version(api_version): """Checks major part of ``APIVersion`` obj is supported. :raises novaclient.exceptions.UnsupportedVersion: if major part is not - supported + supported """ - available_versions = get_available_major_versions() - if (not api_version.is_null() and - str(api_version.ver_major) not in available_versions): - if len(available_versions) == 1: - msg = _("Invalid client version '%(version)s'. " - "Major part should be '%(major)s'") % { - "version": api_version.get_string(), - "major": available_versions[0]} - else: - msg = _("Invalid client version '%(version)s'. " - "Major part must be one of: '%(major)s'") % { - "version": api_version.get_string(), - "major": ", ".join(available_versions)} + if api_version.is_null(): + return + + if api_version.ver_major == 2: + return + + msg = _( + "Invalid client version '%(version)s'. Major part should be '2'" + ) % {"version": api_version.get_string()} + raise exceptions.UnsupportedVersion(msg) + + +def check_version(api_version): + """Checks if version of ``APIVersion`` is supported. + + Provided as an alternative to :func:`check_major_version` to avoid changing + the behavior of that function. + + :raises novaclient.exceptions.UnsupportedVersion: if major part is not + supported + """ + if api_version.is_null(): + return + + # we can't use API_MIN_VERSION since we do support 2.0 (which is 2.1 but + # less strict) + if api_version < APIVersion('2.0'): + msg = _( + "Invalid client version '%(version)s'. " + "Min version supported is '%(min_version)s'" + ) % { + "version": api_version.get_string(), + "min_version": novaclient.API_MIN_VERSION, + } + raise exceptions.UnsupportedVersion(msg) + + if api_version > novaclient.API_MAX_VERSION: + msg = _( + "Invalid client version '%(version)s'. " + "Max version supported is '%(max_version)s'" + ) % { + "version": api_version.get_string(), + "max_version": novaclient.API_MAX_VERSION, + } raise exceptions.UnsupportedVersion(msg) diff --git a/novaclient/client.py b/novaclient/client.py index 6c15f04d1..369d8d08e 100644 --- a/novaclient/client.py +++ b/novaclient/client.py @@ -51,6 +51,12 @@ class SessionClient(adapter.LegacyJsonAdapter): self.timings = kwargs.pop('timings', False) self.api_version = kwargs.pop('api_version', None) self.api_version = self.api_version or api_versions.APIVersion() + + if isinstance(self.api_version, str): + self.api_version = api_versions.APIVersion(self.api_version) + + api_versions.check_version(self.api_version) + super(SessionClient, self).__init__(*args, **kwargs) def request(self, url, method, **kwargs): diff --git a/novaclient/tests/unit/test_api_versions.py b/novaclient/tests/unit/test_api_versions.py index 6969718f8..a5c8cb1c2 100644 --- a/novaclient/tests/unit/test_api_versions.py +++ b/novaclient/tests/unit/test_api_versions.py @@ -343,6 +343,27 @@ class WrapsTestCase(utils.TestCase): self.assertEqual(expected_name, fake_func.__id__) +class CheckVersionTestCase(utils.TestCase): + def test_version_unsupported(self): + for version in ('1.0', '1.5', '1.100'): + with self.subTest('version too old', version=version): + self.assertRaises( + exceptions.UnsupportedVersion, + api_versions.check_version, + api_versions.APIVersion(version)) + + for version in ('2.97', '2.101', '3.0'): + with self.subTest('version too new', version=version): + self.assertRaises( + exceptions.UnsupportedVersion, + api_versions.check_version, + api_versions.APIVersion(version)) + + for version in ('2.1', '2.57', '2.96'): + with self.subTest('version just right', version=version): + api_versions.check_version(api_versions.APIVersion(version)) + + class DiscoverVersionTestCase(utils.TestCase): def setUp(self): super(DiscoverVersionTestCase, self).setUp()