Switch swift tests to use cred_provider with roles

The swift tests were using a DataGenerator class to have users with
special roles for performing certain swift operations. This class never
really took into account the cred_provider mechanism and just brute
forced things with admin. This commit address this by removing the
swift data generator and changing all it's uses to get_creds_by_roles()
where needed.

As part of this cleanup many of the tests were also relying on an
implicit assignment of the operator role with tenant isolation. As part
of making role requirements explicit in this patch that had to be
removed.

Change-Id: I07fa785ef0bad9677885488f3155df7d47f8c846
Partially-implements: bp test-accounts-continued
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 29f314d..f224408 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -28,8 +28,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 548c619..4a7de1c 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -31,8 +31,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 a913bd7..b330637 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -18,20 +18,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 644c3b1..4968eb9 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -19,21 +19,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()
@@ -176,8 +180,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,
@@ -199,8 +205,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 968c8ca..783f74d 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 2427f0f..c3b8e54 100644
--- a/tempest/scenario/test_swift_telemetry_middleware.py
+++ b/tempest/scenario/test_swift_telemetry_middleware.py
@@ -55,7 +55,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 80ec193..da6effa 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -155,7 +155,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')
@@ -181,9 +180,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')