Update OpenStack clients to improve 'lazyness'

Change-Id: If32e99f20c628e0c8c8ab201fc92fa58ebaf4587
This commit is contained in:
Federico Ressi 2019-06-17 08:20:39 +02:00
parent 5996055ab6
commit 8a7b39d050
9 changed files with 137 additions and 83 deletions

View File

@ -28,29 +28,26 @@ class OpenstackClientFixture(tobiko.SharedFixture):
client = None client = None
session = None session = None
session_fixture = None
def __init__(self, session=None): def __init__(self, session=None, client=None):
super(OpenstackClientFixture, self).__init__() super(OpenstackClientFixture, self).__init__()
if session: if session:
if tobiko.is_fixture(session): self.session = session
self.session_fixture = session if client:
else: self.client = client
self.session = session
def setup_fixture(self): def setup_fixture(self):
self.setup_session()
self.setup_client() self.setup_client()
def setup_session(self):
session_fixture = self.session_fixture
if session_fixture:
self.session = tobiko.setup_fixture(session_fixture).session
elif not self.session:
self.session = keystone.get_keystone_session()
def setup_client(self): def setup_client(self):
self.client = self.init_client(session=self.session) client = self.client
if not client:
self.session = session = self.get_session()
self.client = client = self.init_client(session=session)
return client
def get_session(self):
return keystone.keystone_session(self.session)
@abc.abstractmethod @abc.abstractmethod
def init_client(self, session): def init_client(self, session):
@ -59,9 +56,8 @@ class OpenstackClientFixture(tobiko.SharedFixture):
class OpenstackClientManager(object): class OpenstackClientManager(object):
def __init__(self, init_client=None): def __init__(self):
self._clients = {} self.clients = {}
self.init_client = init_client
def get_client(self, session=None, shared=True, init_client=None): def get_client(self, session=None, shared=True, init_client=None):
if shared: if shared:
@ -70,17 +66,19 @@ class OpenstackClientManager(object):
else: else:
key = session key = session
client = self._clients.get(key) client = self.clients.get(key)
if client: if client:
return client return client
session = session or keystone.get_keystone_session() init_client = init_client or self.create_client
init_client = init_client or self.init_client
assert callable(init_client) assert callable(init_client)
LOG.debug('Initialize OpenStack client: %r(session=%r)', LOG.debug('Initialize OpenStack client: %r(session=%r)',
init_client, session) init_client, session)
client = init_client(session=session) client = init_client(session=session)
if shared: if shared:
self._clients[key] = client self.clients[key] = client
return client return client
def create_client(self, session):
raise NotImplementedError

View File

@ -18,7 +18,10 @@ from tobiko.openstack.heat import _template
from tobiko.openstack.heat import _stack from tobiko.openstack.heat import _stack
heat_client = _client.heat_client
default_heat_client = _client.default_heat_client
get_heat_client = _client.get_heat_client get_heat_client = _client.get_heat_client
heat_client = _client.heat_client
HeatClientFixture = _client.HeatClientFixture HeatClientFixture = _client.HeatClientFixture
heat_template = _template.heat_template heat_template = _template.heat_template

View File

@ -13,26 +13,51 @@
# under the License. # under the License.
from __future__ import absolute_import from __future__ import absolute_import
from heatclient import client as heatclient from heatclient.v1 import client as heatclient
import tobiko
from tobiko.openstack import _client from tobiko.openstack import _client
class HeatClientFixture(_client.OpenstackClientFixture): class HeatClientFixture(_client.OpenstackClientFixture):
def init_client(self, session): def init_client(self, session):
return heatclient.Client( return heatclient.Client(session=session,
'1', session=session, endpoint_type='public', endpoint_type='public',
service_type='orchestration') service_type='orchestration')
CLIENTS = _client.OpenstackClientManager(init_client=HeatClientFixture) class HeatClientManager(_client.OpenstackClientManager):
def create_client(self, session):
return HeatClientFixture(session=session)
CLIENTS = HeatClientManager()
def heat_client(obj=None):
if obj is None:
return default_heat_client()
if isinstance(obj, heatclient.Client):
return obj
fixture = tobiko.get_fixture(obj)
if isinstance(fixture, HeatClientFixture):
return tobiko.setup_fixture(fixture).client
message = "Object {!r} is not a NeutronClientFixture".format(obj)
raise TypeError(message)
def default_heat_client():
return get_heat_client()
def get_heat_client(session=None, shared=True, init_client=None, def get_heat_client(session=None, shared=True, init_client=None,
manager=None): manager=None):
manager = manager or CLIENTS manager = manager or CLIENTS
client = manager.get_client(session=session, shared=shared, fixture = manager.get_client(session=session, shared=shared,
init_client=init_client) init_client=init_client)
client.setUp() return tobiko.setup_fixture(fixture).client
return client.client

View File

@ -131,8 +131,8 @@ class KeystoneCredentialsFixture(tobiko.SharedFixture):
try: try:
credentials.validate() credentials.validate()
except InvalidKeystoneCredentials as ex: except InvalidKeystoneCredentials as ex:
LOG.info("No such valid credentials from environment: %r", LOG.info("No such valid credentials from %r (%r)",
ex) self, ex)
else: else:
self.addCleanup(self.cleanup_credentials) self.addCleanup(self.cleanup_credentials)
self.credentials = credentials self.credentials = credentials
@ -141,7 +141,7 @@ class KeystoneCredentialsFixture(tobiko.SharedFixture):
del self.credentials del self.credentials
def get_credentials(self): def get_credentials(self):
return None return self.credentials
class EnvironKeystoneCredentialsFixture(KeystoneCredentialsFixture): class EnvironKeystoneCredentialsFixture(KeystoneCredentialsFixture):

View File

@ -27,7 +27,13 @@ class NeutronClientFixture(_client.OpenstackClientFixture):
return neutronclient.Client(session=session) return neutronclient.Client(session=session)
CLIENTS = _client.OpenstackClientManager(init_client=NeutronClientFixture) class NeutronClientManatger(_client.OpenstackClientManager):
def create_client(self, session):
return NeutronClientFixture(session=session)
CLIENTS = NeutronClientManatger()
def neutron_client(obj): def neutron_client(obj):

View File

@ -15,5 +15,6 @@ from __future__ import absolute_import
from tobiko.openstack.nova import _client from tobiko.openstack.nova import _client
nova_client = _client.nova_client
get_nova_client = _client.get_nova_client get_nova_client = _client.get_nova_client
NovaClientFixture = _client.NovaClientFixture NovaClientFixture = _client.NovaClientFixture

View File

@ -15,6 +15,7 @@ from __future__ import absolute_import
from novaclient import client as novaclient from novaclient import client as novaclient
import tobiko
from tobiko.openstack import _client from tobiko.openstack import _client
@ -24,7 +25,28 @@ class NovaClientFixture(_client.OpenstackClientFixture):
return novaclient.Client('2', session=session) return novaclient.Client('2', session=session)
CLIENTS = _client.OpenstackClientManager(init_client=NovaClientFixture) class NovaClientManager(_client.OpenstackClientManager):
def create_client(self, session):
return NovaClientFixture(session=session)
CLIENTS = NovaClientManager()
def nova_client(obj):
if not obj:
return get_nova_client()
if isinstance(obj, novaclient.Client):
return obj
fixture = tobiko.setup_fixture(obj)
if isinstance(fixture, NovaClientFixture):
return fixture.client
message = "Object {!r} is not a NovaClientFixture".format(obj)
raise TypeError(message)
def get_nova_client(session=None, shared=True, init_client=None, def get_nova_client(session=None, shared=True, init_client=None,
@ -32,5 +54,5 @@ def get_nova_client(session=None, shared=True, init_client=None,
manager = manager or CLIENTS manager = manager or CLIENTS
client = manager.get_client(session=session, shared=shared, client = manager.get_client(session=session, shared=shared,
init_client=init_client) init_client=init_client)
client.setUp() tobiko.setup_fixture(client)
return client.client return client.client

View File

@ -14,6 +14,7 @@
from __future__ import absolute_import from __future__ import absolute_import
from heatclient.v1 import client as heatclient from heatclient.v1 import client as heatclient
import mock
from tobiko.openstack import keystone from tobiko.openstack import keystone
from tobiko.openstack import heat from tobiko.openstack import heat
@ -21,6 +22,9 @@ from tobiko.tests.unit import openstack
from tobiko.tests.unit.openstack import test_client from tobiko.tests.unit.openstack import test_client
MockClient = mock.create_autospec(heatclient.Client)
class HeatClientFixtureTest(test_client.OpenstackClientFixtureTest): class HeatClientFixtureTest(test_client.OpenstackClientFixtureTest):
def create_client(self, session=None): def create_client(self, session=None):
@ -45,3 +49,22 @@ class GetHeatClientTest(openstack.OpenstackTest):
def test_get_heat_client_with_session(self): def test_get_heat_client_with_session(self):
session = keystone.get_keystone_session() session = keystone.get_keystone_session()
self.test_get_heat_client(session=session) self.test_get_heat_client(session=session)
class HeatClientTest(openstack.OpenstackTest):
def test_heat_client(self, obj=None):
client = heat.heat_client(obj)
self.assertIsInstance(client, heatclient.Client)
if obj is None:
self.assertIs(heat.default_heat_client(), client)
elif isinstance(obj, heatclient.Client):
self.assertIs(obj, client)
elif isinstance(obj, heat.HeatClientFixture):
self.assertIs(obj.client, client)
def test_heat_client_with_client(self):
self.test_heat_client(obj=MockClient())
def test_heat_client_with_fixture(self):
self.test_heat_client(obj=heat.HeatClientFixture())

View File

@ -16,6 +16,7 @@ from __future__ import absolute_import
import inspect import inspect
from keystoneauth1 import session as _session
import mock import mock
import tobiko import tobiko
@ -33,17 +34,7 @@ class ClientFixture(_client.OpenstackClientFixture):
return CLIENT return CLIENT
SESSION = object() MockSession = mock.create_autospec(_session.Session)
DEFAULT_SESSION = object()
class SessionFixture(tobiko.SharedFixture):
session = None
def setup_fixture(self):
self.session = SESSION
class OpenstackClientFixtureTest(openstack.OpenstackTest): class OpenstackClientFixtureTest(openstack.OpenstackTest):
@ -53,10 +44,10 @@ class OpenstackClientFixtureTest(openstack.OpenstackTest):
def test_init(self, session=None): def test_init(self, session=None):
client = self.create_client(session=session) client = self.create_client(session=session)
self.check_client_session(client=client, session=session) self.assertIs(session or None, client.session)
def test_init_with_credentials(self): def test_init_with_credentials(self):
self.test_init(session=SESSION) self.test_init(session=MockSession)
def test_init_with_credentials_fixture(self): def test_init_with_credentials_fixture(self):
self.test_init(session=keystone.KeystoneSessionFixture()) self.test_init(session=keystone.KeystoneSessionFixture())
@ -78,25 +69,19 @@ class OpenstackClientFixtureTest(openstack.OpenstackTest):
self.assertIs(keystone.get_keystone_session(), client.session) self.assertIs(keystone.get_keystone_session(), client.session)
def test_setup_with_session(self): def test_setup_with_session(self):
self.test_setup(session=SESSION) self.test_setup(session=MockSession())
def test_setup_with_session_fixture(self): def test_setup_with_session_fixture(self):
self.test_setup(session=SessionFixture()) self.test_setup(session=keystone.KeystoneSessionFixture())
def test_setup_with_session_fixture_type(self): def test_setup_with_session_fixture_type(self):
self.test_setup(session=SessionFixture) self.test_setup(session=keystone.KeystoneSessionFixture)
def check_client_session(self, client, session):
if session: class ClientManager(_client.OpenstackClientManager):
if tobiko.is_fixture(session):
self.assertIsNone(client.session) def create_client(self, session):
self.assertIs(session, client.session_fixture) return ClientFixture(session=session)
else:
self.assertIs(session, client.session)
self.assertIsNone(client.session_fixture)
else:
self.assertIsNone(client.session)
self.assertIsNone(client.session_fixture)
class OpenstackClientManagerTest(openstack.OpenstackTest): class OpenstackClientManagerTest(openstack.OpenstackTest):
@ -104,47 +89,38 @@ class OpenstackClientManagerTest(openstack.OpenstackTest):
def setUp(self): def setUp(self):
super(OpenstackClientManagerTest, self).setUp() super(OpenstackClientManagerTest, self).setUp()
self.patch(keystone, 'get_keystone_session', self.patch(keystone, 'get_keystone_session',
return_value=DEFAULT_SESSION) return_value=MockSession())
def test_init(self, init_client=None): def test_init(self):
manager = _client.OpenstackClientManager(init_client=init_client) manager = ClientManager()
self.assertIs(init_client, manager.init_client) self.assertEqual({}, manager.clients)
def test_init_with_init_client(self):
self.test_init(init_client=ClientFixture)
def test_get_client(self, session=None, shared=True): def test_get_client(self, session=None, shared=True):
default_init_client = mock.MagicMock(side_effect=ClientFixture) manager = ClientManager()
manager = _client.OpenstackClientManager(
init_client=default_init_client)
client1 = manager.get_client(session=session, shared=shared) client1 = manager.get_client(session=session, shared=shared)
client2 = manager.get_client(session=session, shared=shared) client2 = manager.get_client(session=session, shared=shared)
if shared: if shared:
self.assertIs(client1, client2) self.assertIs(client1, client2)
default_init_client.assert_called_once_with(
session=(session or DEFAULT_SESSION))
else: else:
self.assertIsNot(client1, client2) self.assertIsNot(client1, client2)
default_init_client.assert_has_calls(
[mock.call(session=(session or DEFAULT_SESSION))] * 2,
any_order=True)
def test_get_client_with_not_shared(self): def test_get_client_with_not_shared(self):
self.test_get_client(shared=False) self.test_get_client(shared=False)
def test_get_client_with_session(self): def test_get_client_with_session(self):
self.test_get_client(session=SESSION) self.test_get_client(session=MockSession())
def test_get_client_with_session_fixture(self): def test_get_client_with_session_fixture(self):
self.test_get_client(session=SessionFixture()) self.test_get_client(session=keystone.KeystoneSessionFixture())
def test_get_client_with_session_fixture_type(self): def test_get_client_with_session_fixture_type(self):
self.test_get_client(session=SessionFixture) self.test_get_client(session=keystone.KeystoneSessionFixture)
def test_get_client_with_init_client(self): def test_get_client_with_init_client(self):
init_client = mock.MagicMock(return_value=CLIENT) init_client = mock.MagicMock(return_value=CLIENT)
manager = _client.OpenstackClientManager() manager = _client.OpenstackClientManager()
client = manager.get_client(session=SESSION, session = MockSession()
client = manager.get_client(session=session,
init_client=init_client) init_client=init_client)
self.assertIs(CLIENT, client) self.assertIs(CLIENT, client)
init_client.assert_called_once_with(session=SESSION) init_client.assert_called_once_with(session=session)