Merge "Optional setting service client on factory"
diff --git a/tempest/service_clients.py b/tempest/service_clients.py
index a5bc86e..136ad65 100644
--- a/tempest/service_clients.py
+++ b/tempest/service_clients.py
@@ -149,14 +149,34 @@
             setattr(self, class_name, self._get_partial_class(
                 klass, auth_provider, final_kwargs))
 
-    @classmethod
-    def _get_partial_class(cls, klass, auth_provider, kwargs):
+    def _get_partial_class(self, klass, auth_provider, kwargs):
 
         # Define a function that returns a new class instance by
         # combining default kwargs with extra ones
-        def partial_class(**later_kwargs):
+        def partial_class(alias=None, **later_kwargs):
+            """Returns a callable the initialises a service client
+
+            Builds a callable that accepts kwargs, which are passed through
+            to the __init__ of the service client, along with a set of defaults
+            set in factory at factory __init__ time.
+            Original args in the service client can only be passed as kwargs.
+
+            It accepts one extra parameter 'alias' compared to the original
+            service client. When alias is provided, the returned callable will
+            also set an attribute called with a name defined in 'alias', which
+            contains the instance of the service client.
+
+            :param alias: str Name of the attribute set on the factory once
+                the callable is invoked which contains the initialised
+                service client. If None, no attribute is set.
+            :param later_kwargs: kwargs passed through to the service client
+                __init__ on top of defaults set at factory level.
+            """
             kwargs.update(later_kwargs)
-            return klass(auth_provider=auth_provider, **kwargs)
+            _client = klass(auth_provider=auth_provider, **kwargs)
+            if alias:
+                setattr(self, alias, _client)
+            return _client
 
         return partial_class
 
diff --git a/tempest/tests/test_service_clients.py b/tempest/tests/test_service_clients.py
index 3d8b360..b0aa456 100644
--- a/tempest/tests/test_service_clients.py
+++ b/tempest/tests/test_service_clients.py
@@ -160,6 +160,28 @@
         klass_mock.assert_called_once_with(auth_provider=auth_provider,
                                            **params)
 
+    def test__get_partial_class_with_alias(self):
+        expected_fake_client = 'not_really_a_client'
+        client_alias = 'fake_client'
+        self._setup_fake_module(class_names=[])
+        auth_provider = fake_auth_provider.FakeAuthProvider()
+        params = {'k1': 'v1', 'k2': 'v2'}
+        later_params = {'k2': 'v4', 'k3': 'v3'}
+        factory = service_clients.ClientsFactory(
+            'fake_path', [], auth_provider, **params)
+        klass_mock = mock.Mock(return_value=expected_fake_client)
+        partial = factory._get_partial_class(klass_mock, auth_provider, params)
+        # Class has not be initialised yet
+        klass_mock.assert_not_called()
+        # Use partial and assert on parameters
+        client = partial(alias=client_alias, **later_params)
+        params.update(later_params)
+        self.assertEqual(expected_fake_client, client)
+        klass_mock.assert_called_once_with(auth_provider=auth_provider,
+                                           **params)
+        self.assertThat(factory, has_attribute(client_alias))
+        self.assertEqual(expected_fake_client, getattr(factory, client_alias))
+
 
 class TestServiceClients(base.TestCase):