Fix client backwards compatibility

Change [1] introduced support of microversions to manilaclient and
changed behaviour of client init that is not compatible with old
approach. Also, not all old modules have deprecated modules in place.

So, first problem description:
- Old client expected string with api version, new one expects
APIVersion class instance. So, add support for both and cover them with
unit tests.

Second problem description:
- Manila UI project imports "manilaclient.v1.contrib.list_extensions"
directly, but this file was moved to another place without keeping in
place deprecated variant. So, add such to fix backward compatibility
and allow to use newest manilaclient with manila-ui project.

[1] I3733fe85424e39566addc070d42609e508259f19

Change-Id: I838631fb38b8ddf1f4f1e06269af122bf51a5155
Closes-Bug: #1518245
This commit is contained in:
Valeriy Ponomaryov 2015-11-20 12:19:50 +02:00
parent f2ebf210dc
commit d4ff416e2d
4 changed files with 97 additions and 1 deletions

View File

@ -22,6 +22,7 @@ OpenStack Client interface. Handles the REST calls and responses.
from oslo_utils import importutils from oslo_utils import importutils
from manilaclient import api_versions
from manilaclient import exceptions from manilaclient import exceptions
@ -41,6 +42,14 @@ def get_client_class(version):
def Client(api_version, *args, **kwargs): def Client(api_version, *args, **kwargs):
if not hasattr(api_version, 'get_major_version'):
if api_version in ('1', '1.0'):
api_version = api_versions.APIVersion(
api_versions.DEPRECATED_VERSION)
elif api_version == '2':
api_version = api_versions.APIVersion(api_versions.MIN_VERSION)
else:
api_version = api_versions.APIVersion(api_version)
client_class = get_client_class(api_version.get_major_version()) client_class = get_client_class(api_version.get_major_version())
kwargs['api_version'] = api_version kwargs['api_version'] = api_version
return client_class(*args, **kwargs) return client_class(*args, **kwargs)

View File

@ -10,11 +10,18 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import manilaclient.client import ddt
import mock
from manilaclient import api_versions
from manilaclient import client
from manilaclient import exceptions
from manilaclient.tests.unit import utils from manilaclient.tests.unit import utils
import manilaclient.v1.client
import manilaclient.v2.client import manilaclient.v2.client
@ddt.ddt
class ClientTest(utils.TestCase): class ClientTest(utils.TestCase):
def test_get_client_class_v2(self): def test_get_client_class_v2(self):
@ -24,3 +31,47 @@ class ClientTest(utils.TestCase):
def test_get_client_class_unknown(self): def test_get_client_class_unknown(self):
self.assertRaises(manilaclient.exceptions.UnsupportedVersion, self.assertRaises(manilaclient.exceptions.UnsupportedVersion,
manilaclient.client.get_client_class, '0') manilaclient.client.get_client_class, '0')
@ddt.data('1', '1.0')
def test_init_client_with_string_v1_version(self, version):
with mock.patch.object(manilaclient.v1.client, 'Client'):
with mock.patch.object(api_versions, 'APIVersion'):
api_instance = api_versions.APIVersion.return_value
api_instance.get_major_version.return_value = '1'
manilaclient.client.Client(version, 'foo', bar='quuz')
manilaclient.v1.client.Client.assert_called_once_with(
'foo', api_version=api_instance, bar='quuz')
api_versions.APIVersion.assert_called_once_with('1.0')
@ddt.data(
('2', '2.0'),
('2.0', '2.0'),
('2.6', '2.6'),
)
@ddt.unpack
def test_init_client_with_string_v2_version(self, provided, expected):
with mock.patch.object(manilaclient.v2.client, 'Client'):
with mock.patch.object(api_versions, 'APIVersion'):
api_instance = api_versions.APIVersion.return_value
api_instance.get_major_version.return_value = '2'
manilaclient.client.Client(provided, 'foo', bar='quuz')
manilaclient.v2.client.Client.assert_called_once_with(
'foo', api_version=api_instance, bar='quuz')
api_versions.APIVersion.assert_called_once_with(expected)
def test_init_client_with_api_version_instance(self):
version = manilaclient.API_MAX_VERSION
with mock.patch.object(manilaclient.v2.client, 'Client'):
manilaclient.client.Client(version, 'foo', bar='quuz')
manilaclient.v2.client.Client.assert_called_once_with(
'foo', api_version=version, bar='quuz')
@ddt.data(None, '', '3', 'v1', 'v2', 'v1.0', 'v2.0')
def test_init_client_with_unsupported_version(self, v):
self.assertRaises(exceptions.UnsupportedVersion, client.Client, v)

View File

View File

@ -0,0 +1,36 @@
# Copyright 2013 OpenStack LLC.
# All Rights Reserved.
#
# 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 sys
import warnings
from manilaclient.v2.contrib import list_extensions
warnings.warn(
"Module manilaclient.v1.contrib.list_extensions is deprecated "
"(taken as a basis for manilaclient.v2.contrib.list_extensions). "
"The preferable way to get a client class or object is to use "
"the manilaclient.client module.")
class MovedModule(object):
def __init__(self, new_module):
self.new_module = new_module
def __getattr__(self, attr):
return getattr(self.new_module, attr)
sys.modules["manilaclient.v1.contrib.list_extensions"] = MovedModule(
list_extensions)