Merge "Switch swift tests to use cred_provider with roles"
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 6a025d9..42062e7 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -15,7 +15,6 @@
 
 from tempest_lib import exceptions as lib_exc
 
-from tempest.api.identity import base
 from tempest import clients
 from tempest.common import credentials
 from tempest.common import custom_matchers
@@ -33,6 +32,11 @@
         if not CONF.service_available.swift:
             skip_msg = ("%s skipped as swift is not available" % cls.__name__)
             raise cls.skipException(skip_msg)
+        if not CONF.auth.allow_tenant_isolation and \
+            not CONF.auth.locking_credentials_provider:
+            skip_msg = ("%s skipped because a credential provider able to "
+                        "provide credentials by role is needed" % cls.__name__)
+            raise cls.skipException(skip_msg)
 
     @classmethod
     def setup_credentials(cls):
@@ -42,25 +46,15 @@
         cls.isolated_creds = credentials.get_isolated_credentials(
             cls.__name__, network_resources=cls.network_resources)
         # Get isolated creds for normal user
-        cls.os = clients.Manager(cls.isolated_creds.get_primary_creds())
-        # Get isolated creds for admin user
-        cls.os_admin = clients.Manager(cls.isolated_creds.get_admin_creds())
-        cls.data = SwiftDataGenerator(cls.os_admin.identity_client)
-        # Get isolated creds for alt user
-        cls.os_alt = clients.Manager(cls.isolated_creds.get_alt_creds())
+        cls.os = clients.Manager(cls.isolated_creds.get_creds_by_roles(
+            [CONF.object_storage.operator_role]))
 
     @classmethod
     def setup_clients(cls):
         super(BaseObjectTest, cls).setup_clients()
-
         cls.object_client = cls.os.object_client
         cls.container_client = cls.os.container_client
         cls.account_client = cls.os.account_client
-        cls.token_client = cls.os_admin.token_client
-        cls.identity_admin_client = cls.os_admin.identity_client
-        cls.object_client_alt = cls.os_alt.object_client
-        cls.container_client_alt = cls.os_alt.container_client
-        cls.identity_client_alt = cls.os_alt.identity_client
 
     @classmethod
     def resource_setup(cls):
@@ -70,12 +64,9 @@
         cls.object_client.auth_provider.clear_auth()
         cls.container_client.auth_provider.clear_auth()
         cls.account_client.auth_provider.clear_auth()
-        cls.object_client_alt.auth_provider.clear_auth()
-        cls.container_client_alt.auth_provider.clear_auth()
 
     @classmethod
     def resource_cleanup(cls):
-        cls.data.teardown_all()
         cls.isolated_creds.clear_isolated_creds()
         super(BaseObjectTest, cls).resource_cleanup()
 
@@ -119,28 +110,3 @@
         self.assertThat(resp, custom_matchers.ExistsAllResponseHeaders(
                         target, method))
         self.assertThat(resp, custom_matchers.AreAllWellFormatted())
-
-
-class SwiftDataGenerator(base.DataGenerator):
-
-    def setup_test_user(self, reseller=False):
-        super(SwiftDataGenerator, self).setup_test_user()
-        if reseller:
-            role_name = CONF.object_storage.reseller_admin_role
-        else:
-            role_name = CONF.object_storage.operator_role
-        role_id = self._get_role_id(role_name)
-        self._assign_role(role_id)
-
-    def _get_role_id(self, role_name):
-        try:
-            roles = self.client.list_roles()
-            return next(r['id'] for r in roles if r['name'] == role_name)
-        except StopIteration:
-            msg = "Role name '%s' is not found" % role_name
-            raise lib_exc.NotFound(msg)
-
-    def _assign_role(self, role_id):
-        self.client.assign_user_role(self.tenant['id'],
-                                     self.user['id'],
-                                     role_id)
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index 9b379f4..0c7e991 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -26,8 +26,9 @@
     @classmethod
     def setup_credentials(cls):
         super(AccountQuotasTest, cls).setup_credentials()
-        cls.data.setup_test_user(reseller=True)
-        cls.os_reselleradmin = clients.Manager(cls.data.test_credentials)
+        cls.os_reselleradmin = clients.Manager(
+            cls.isolated_creds.get_creds_by_roles(
+                roles=[CONF.object_storage.reseller_admin_role]))
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index 7d4008c..dbb46a9 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -29,8 +29,9 @@
     @classmethod
     def setup_credentials(cls):
         super(AccountQuotasNegativeTest, cls).setup_credentials()
-        cls.data.setup_test_user(reseller=True)
-        cls.os_reselleradmin = clients.Manager(cls.data.test_credentials)
+        cls.os_reselleradmin = clients.Manager(
+            cls.isolated_creds.get_creds_by_roles(
+                roles=[CONF.object_storage.reseller_admin_role]))
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 63d0425..14ccc12 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -32,6 +32,13 @@
     containers = []
 
     @classmethod
+    def setup_credentials(cls):
+        super(AccountTest, cls).setup_credentials()
+        cls.os_operator = clients.Manager(
+            cls.isolated_creds.get_creds_by_roles(
+                roles=[CONF.object_storage.operator_role], force_new=True))
+
+    @classmethod
     def resource_setup(cls):
         super(AccountTest, cls).resource_setup()
         for i in moves.xrange(ord('a'), ord('f') + 1):
@@ -63,12 +70,9 @@
 
         # To test listing no containers, create new user other than
         # the base user of this instance.
-        self.data.setup_test_user()
-
-        os_test_user = clients.Manager(self.data.test_credentials)
 
         resp, container_list = \
-            os_test_user.account_client.list_account_containers()
+            self.os_operator.account_client.list_account_containers()
 
         # When sending a request to an account which has not received a PUT
         # container request, the response does not contain 'accept-ranges'
diff --git a/tempest/api/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index f329675..baec616 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -16,20 +16,27 @@
 
 from tempest.api.object_storage import base
 from tempest import clients
+from tempest import config
 from tempest import test
 
+CONF = config.CONF
+
 
 class AccountNegativeTest(base.BaseObjectTest):
 
+    @classmethod
+    def setup_credentials(cls):
+        super(AccountNegativeTest, cls).setup_credentials()
+        cls.os_operator = clients.Manager(
+            cls.isolated_creds.get_creds_by_roles(
+                roles=[CONF.object_storage.operator_role], force_new=True))
+
     @test.attr(type=['negative', 'gate'])
     @test.idempotent_id('070e6aca-6152-4867-868d-1118d68fb38c')
     def test_list_containers_with_non_authorized_user(self):
         # list containers using non-authorized user
 
-        # create user
-        self.data.setup_test_user()
-        test_os = clients.Manager(self.data.test_credentials)
-        test_auth_provider = test_os.auth_provider
+        test_auth_provider = self.os_operator.auth_provider
         # Get auth for the test user
         test_auth_provider.auth_data
 
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index 6368bec..2c00022 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -16,21 +16,25 @@
 from tempest.api.object_storage import base
 from tempest import clients
 from tempest.common.utils import data_utils
+from tempest import config
 from tempest import test
 
+CONF = config.CONF
+
 
 class ObjectTestACLs(base.BaseObjectTest):
 
     @classmethod
     def setup_credentials(cls):
         super(ObjectTestACLs, cls).setup_credentials()
-        cls.data.setup_test_user()
-        cls.test_os = clients.Manager(cls.data.test_credentials)
+        cls.os_operator = clients.Manager(
+            cls.isolated_creds.get_creds_by_roles(
+                roles=[CONF.object_storage.operator_role], force_new=True))
 
     @classmethod
     def resource_setup(cls):
         super(ObjectTestACLs, cls).resource_setup()
-        cls.test_auth_data = cls.test_os.auth_provider.auth_data
+        cls.test_auth_data = cls.os_operator.auth_provider.auth_data
 
     def setUp(self):
         super(ObjectTestACLs, self).setUp()
@@ -46,8 +50,9 @@
     def test_read_object_with_rights(self):
         # attempt to read object using authorized user
         # update X-Container-Read metadata ACL
-        cont_headers = {'X-Container-Read':
-                        self.data.test_tenant + ':' + self.data.test_user}
+        tenant_name = self.os_operator.credentials.tenant_name
+        username = self.os_operator.credentials.username
+        cont_headers = {'X-Container-Read': tenant_name + ':' + username}
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
@@ -71,8 +76,9 @@
     def test_write_object_with_rights(self):
         # attempt to write object using authorized user
         # update X-Container-Write metadata ACL
-        cont_headers = {'X-Container-Write':
-                        self.data.test_tenant + ':' + self.data.test_user}
+        tenant_name = self.os_operator.credentials.tenant_name
+        username = self.os_operator.credentials.username
+        cont_headers = {'X-Container-Write': tenant_name + ':' + username}
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index 5892340..4ed4d57 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -17,21 +17,25 @@
 from tempest.api.object_storage import base
 from tempest import clients
 from tempest.common.utils import data_utils
+from tempest import config
 from tempest import test
 
+CONF = config.CONF
+
 
 class ObjectACLsNegativeTest(base.BaseObjectTest):
 
     @classmethod
     def setup_credentials(cls):
         super(ObjectACLsNegativeTest, cls).setup_credentials()
-        cls.data.setup_test_user()
-        cls.test_os = clients.Manager(cls.data.test_credentials)
+        cls.os_operator = clients.Manager(
+            cls.isolated_creds.get_creds_by_roles(
+                roles=[CONF.object_storage.operator_role], force_new=True))
 
     @classmethod
     def resource_setup(cls):
         super(ObjectACLsNegativeTest, cls).resource_setup()
-        cls.test_auth_data = cls.test_os.auth_provider.auth_data
+        cls.test_auth_data = cls.os_operator.auth_provider.auth_data
 
     def setUp(self):
         super(ObjectACLsNegativeTest, self).setUp()
@@ -174,8 +178,10 @@
     def test_write_object_without_write_rights(self):
         # attempt to write object using non-authorized user
         # update X-Container-Read and X-Container-Write metadata ACL
+        tenant_name = self.os_operator.credentials.tenant_name
+        username = self.os_operator.credentials.username
         cont_headers = {'X-Container-Read':
-                        self.data.test_tenant + ':' + self.data.test_user,
+                        tenant_name + ':' + username,
                         'X-Container-Write': ''}
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers,
@@ -197,8 +203,10 @@
     def test_delete_object_without_write_rights(self):
         # attempt to delete object using non-authorized user
         # update X-Container-Read and X-Container-Write metadata ACL
+        tenant_name = self.os_operator.credentials.tenant_name
+        username = self.os_operator.credentials.username
         cont_headers = {'X-Container-Read':
-                        self.data.test_tenant + ':' + self.data.test_user,
+                        tenant_name + ':' + username,
                         'X-Container-Write': ''}
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers,
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 71f1275..ae42da6 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -19,6 +19,7 @@
 import urlparse
 
 from tempest.api.object_storage import base
+from tempest import clients
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest import test
@@ -36,6 +37,18 @@
     clients = {}
 
     @classmethod
+    def setup_credentials(cls):
+        super(ContainerSyncTest, cls).setup_credentials()
+        cls.os_alt = clients.Manager(cls.isolated_creds.get_creds_by_roles(
+            [CONF.object_storage.operator_role], force_new=True))
+
+    @classmethod
+    def setup_clients(cls):
+        super(ContainerSyncTest, cls).setup_clients()
+        cls.object_client_alt = cls.os_alt.object_client
+        cls.container_client_alt = cls.os_alt.container_client
+
+    @classmethod
     def resource_setup(cls):
         super(ContainerSyncTest, cls).resource_setup()
         cls.containers = []
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index a4d0377..f9220cf 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -23,12 +23,17 @@
 import six
 
 from tempest.api.object_storage import base
+from tempest import clients
 from tempest.common import custom_matchers
 from tempest.common.utils import data_utils
+from tempest import config
 from tempest import test
 
+CONF = config.CONF
+
 
 class ObjectTest(base.BaseObjectTest):
+
     @classmethod
     def resource_setup(cls):
         super(ObjectTest, cls).resource_setup()
@@ -1016,6 +1021,19 @@
 
 
 class PublicObjectTest(base.BaseObjectTest):
+
+    @classmethod
+    def setup_credentials(cls):
+        super(PublicObjectTest, cls).setup_credentials()
+        cls.os_alt = clients.Manager(
+            cls.isolated_creds.get_creds_by_roles(
+                roles=[CONF.object_storage.operator_role], force_new=True))
+
+    @classmethod
+    def setup_clients(cls):
+        super(PublicObjectTest, cls).setup_clients()
+        cls.identity_client_alt = cls.os_alt.identity_client
+
     def setUp(self):
         super(PublicObjectTest, self).setUp()
         self.container_name = data_utils.rand_name(name='TestContainer')
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index b0531fd..b36dd46 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -79,8 +79,15 @@
         except StopIteration:
             msg = 'No "%s" role found' % role_name
             raise lib_exc.NotFound(msg)
-        self.identity_admin_client.assign_user_role(tenant['id'], user['id'],
-                                                    role['id'])
+        try:
+            self.identity_admin_client.assign_user_role(tenant['id'],
+                                                        user['id'],
+                                                        role['id'])
+        except lib_exc.Conflict:
+            LOG.warning('Trying to add %s for user %s in tenant %s but they '
+                        ' were already granted that role' % (role_name,
+                                                             user['name'],
+                                                             tenant['name']))
 
     def _delete_user(self, user):
         self.identity_admin_client.delete_user(user)
@@ -114,11 +121,6 @@
         email = data_utils.rand_name(root) + suffix + "@example.com"
         user = self._create_user(username, self.password,
                                  tenant, email)
-        if CONF.service_available.swift:
-            # NOTE(andrey-mp): user needs this role to create containers
-            # in swift
-            swift_operator_role = CONF.object_storage.operator_role
-            self._assign_user_role(tenant, user, swift_operator_role)
         if admin:
             self._assign_user_role(tenant, user, CONF.identity.admin_role)
         # Add roles specified in config file
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index f24a22a..7f0582a 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -1372,10 +1372,13 @@
             raise cls.skipException(skip_msg)
         cls.set_network_resources()
         super(SwiftScenarioTest, cls).resource_setup()
+        cls.os_operator = clients.Manager(
+            cls.isolated_creds.get_creds_by_roles(
+                [CONF.object_storage.operator_role]))
         # Clients for Swift
-        cls.account_client = cls.manager.account_client
-        cls.container_client = cls.manager.container_client
-        cls.object_client = cls.manager.object_client
+        cls.account_client = cls.os_operator.account_client
+        cls.container_client = cls.os_operator.container_client
+        cls.object_client = cls.os_operator.object_client
 
     def get_swift_stat(self):
         """get swift status for our user account."""
diff --git a/tempest/scenario/test_swift_telemetry_middleware.py b/tempest/scenario/test_swift_telemetry_middleware.py
index 8305641..16c3976 100644
--- a/tempest/scenario/test_swift_telemetry_middleware.py
+++ b/tempest/scenario/test_swift_telemetry_middleware.py
@@ -53,7 +53,7 @@
             skip_msg = "Ceilometer feature for fast work mysql is disabled"
             raise cls.skipException(skip_msg)
         super(TestSwiftTelemetry, cls).resource_setup()
-        cls.telemetry_client = cls.manager.telemetry_client
+        cls.telemetry_client = cls.os_operator.telemetry_client
 
     def _confirm_notifications(self, container_name, obj_name):
         """
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index a18ad46..a420a8f 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -156,7 +156,6 @@
                                'assign_user_role') as user_mock:
             admin_creds = iso_creds.get_admin_creds()
         user_mock.assert_has_calls([
-            mock.call('1234', '1234', '1'),
             mock.call('1234', '1234', '1234')])
         self.assertEqual(admin_creds.username, 'fake_admin_user')
         self.assertEqual(admin_creds.tenant_name, 'fake_admin_tenant')
@@ -182,9 +181,8 @@
             role_creds = iso_creds.get_creds_by_roles(roles=['role1', 'role2'])
         calls = user_mock.mock_calls
         # Assert that the role creation is called with the 2 specified roles
-        self.assertEqual(len(calls), 3)
+        self.assertEqual(len(calls), 2)
         args = map(lambda x: x[1], calls)
-        self.assertIn(('1234', '1234', '1'), args)
         self.assertIn(('1234', '1234', '1234'), args)
         self.assertIn(('1234', '1234', '12345'), args)
         self.assertEqual(role_creds.username, 'fake_role_user')