Refactor identity v3 rbac_base to use classmethods.

Currently, identity v3 rbac_base uses self.addCleanup to do cleanup
for the resources it creates. But this locks the tests into using
only test-level resources. This is inefficient. Instead,
class-level resources should be used wherever possible.

This patch changes the identity v3 rbac_base to create class-level
resources, that are then set up in resource_setup and cleaned up
in resource_cleanup.

This patch also refactors test_roles_rbac in identity v3 to work
with these changes.

Change-Id: I80f56464a9391e0e41548b266e9b748bf961e1b6
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/rbac_base.py b/patrole_tempest_plugin/tests/api/identity/v3/rbac_base.py
index 127ed3e..5c1acce 100644
--- a/patrole_tempest_plugin/tests/api/identity/v3/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/identity/v3/rbac_base.py
@@ -53,138 +53,190 @@
         cls.services_client = cls.os.identity_services_v3_client
         cls.users_client = cls.os.users_v3_client
 
-    def setup_test_credential(self, user=None):
-        """Creates a user, project, and credential for test."""
+    @classmethod
+    def resource_setup(cls):
+        super(BaseIdentityV3RbacAdminTest, cls).resource_setup()
+        cls.credentials = []
+        cls.domains = []
+        cls.endpoints = []
+        cls.groups = []
+        cls.policies = []
+        cls.projects = []
+        cls.regions = []
+        cls.roles = []
+        cls.services = []
+        cls.users = []
+
+    @classmethod
+    def resource_cleanup(cls):
+        for credential in cls.credentials:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.creds_client.delete_credential, credential['id'])
+
+        # Delete each domain at the end of the test, but each domain must be
+        # disabled first.
+        for domain in cls.domains:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.domains_client.update_domain, domain['id'], enabled=False)
+            test_utils.call_and_ignore_notfound_exc(
+                cls.domains_client.delete_domain, domain['id'])
+
+        for endpoint in cls.endpoints:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.endpoints_client.delete_endpoint, endpoint['id'])
+
+        for group in cls.groups:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.groups_client.delete_group, group['id'])
+
+        for policy in cls.policies:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.policies_client.delete_policy, policy['id'])
+
+        for project in cls.projects:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.projects_client.delete_project, project['id'])
+
+        for region in cls.regions:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.regions_client.delete_region, region['id'])
+
+        for role in cls.roles:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.roles_client.delete_role, role['id'])
+
+        for service in cls.services:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.services_client.delete_service, service['id'])
+
+        for user in cls.users:
+            test_utils.call_and_ignore_notfound_exc(
+                cls.users_client.delete_user, user['id'])
+
+        super(BaseIdentityV3RbacAdminTest, cls).resource_cleanup()
+
+    @classmethod
+    def setup_test_credential(cls, user=None):
+        """Creates a credential for test."""
         keys = [data_utils.rand_uuid_hex(),
                 data_utils.rand_uuid_hex()]
         blob = '{"access": "%s", "secret": "%s"}' % (keys[0], keys[1])
-        credential = self.creds_client.create_credential(
+
+        credential = cls.creds_client.create_credential(
             user_id=user['id'],
             project_id=user['project_id'],
             blob=blob,
             type='ec2')['credential']
-
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.creds_client.delete_credential,
-                        credential['id'])
+        cls.credentials.append(credential)
 
         return credential
 
-    def setup_test_domain(self):
+    @classmethod
+    def setup_test_domain(cls):
         """Set up a test domain."""
-        domain = self.domains_client.create_domain(
+        domain = cls.domains_client.create_domain(
             name=data_utils.rand_name('test_domain'),
             description=data_utils.rand_name('desc'))['domain']
-        # Delete the domain at the end of the test, but the domain must be
-        # disabled first (cleanup called in reverse order)
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.domains_client.delete_domain,
-                        domain['id'])
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.domains_client.update_domain,
-                        domain['id'],
-                        enabled=False)
+        cls.domains.append(domain)
+
         return domain
 
-    def setup_test_endpoint(self, service=None):
+    @classmethod
+    def setup_test_endpoint(cls, service=None):
         """Creates a service and an endpoint for test."""
         interface = 'public'
         url = data_utils.rand_url()
         # Endpoint creation requires a service
         if service is None:
-            service = self.setup_test_service()
-        endpoint = self.endpoints_client.create_endpoint(
+            service = cls.setup_test_service()
+
+        endpoint = cls.endpoints_client.create_endpoint(
             service_id=service['id'],
             interface=interface,
             url=url)['endpoint']
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.endpoints_client.delete_endpoint,
-                        endpoint['id'])
+        cls.endpoints.append(endpoint)
+
         return endpoint
 
-    def setup_test_group(self):
+    @classmethod
+    def setup_test_group(cls):
         """Creates a group for test."""
         name = data_utils.rand_name('test_group')
-        group = self.groups_client.create_group(name=name)['group']
-        # Delete the group at the end of the test
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.groups_client.delete_group,
-                        group['id'])
+        group = cls.groups_client.create_group(name=name)['group']
+        cls.groups.append(group)
+
         return group
 
-    def setup_test_policy(self):
+    @classmethod
+    def setup_test_policy(cls):
         """Creates a policy for test."""
         blob = data_utils.rand_name('test_blob')
-        policy_type = data_utils.rand_name('PolicyType')
-        policy = self.policies_client.create_policy(
+        policy_type = data_utils.rand_name('policy_type')
+
+        policy = cls.policies_client.create_policy(
             blob=blob,
             policy=policy_type,
             type="application/json")['policy']
+        cls.policies.append(policy)
 
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.policies_client.delete_policy,
-                        policy['id'])
         return policy
 
-    def setup_test_project(self):
+    @classmethod
+    def setup_test_project(cls):
         """Set up a test project."""
-        project = self.projects_client.create_project(
+        project = cls.projects_client.create_project(
             name=data_utils.rand_name('test_project'),
             description=data_utils.rand_name('desc'))['project']
-        # Delete the project at the end of the test
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.projects_client.delete_project,
-                        project['id'])
+        cls.projects.append(project)
+
         return project
 
-    def setup_test_region(self):
+    @classmethod
+    def setup_test_region(cls):
         """Creates a region for test."""
         description = data_utils.rand_name('test_region_desc')
 
-        region = self.regions_client.create_region(
+        region = cls.regions_client.create_region(
             description=description)['region']
+        cls.regions.append(region)
 
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.regions_client.delete_region,
-                        region['id'])
         return region
 
-    def setup_test_role(self):
+    @classmethod
+    def setup_test_role(cls):
         """Set up a test role."""
         name = data_utils.rand_name('test_role')
-        role = self.roles_client.create_role(name=name)['role']
-        # Delete the role at the end of the test
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.roles_client.delete_role,
-                        role['id'])
+        role = cls.roles_client.create_role(name=name)['role']
+        cls.roles.append(role)
+
         return role
 
-    def setup_test_service(self):
+    @classmethod
+    def setup_test_service(cls):
         """Setup a test service."""
         name = data_utils.rand_name('service')
         serv_type = data_utils.rand_name('type')
         desc = data_utils.rand_name('description')
-        service = self.services_client.create_service(
+
+        service = cls.services_client.create_service(
             name=name,
             type=serv_type,
             description=desc)['service']
-        # Delete the service at the end of the test
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.services_client.delete_service,
-                        service['id'])
+        cls.services.append(service)
+
         return service
 
-    def setup_test_user(self, password=None, **kwargs):
+    @classmethod
+    def setup_test_user(cls, password=None, **kwargs):
         """Set up a test user."""
         username = data_utils.rand_name('test_user')
         email = username + '@testmail.tm'
-        user = self.users_client.create_user(
+
+        user = cls.users_client.create_user(
             name=username,
             email=email,
             password=password,
             **kwargs)['user']
-        # Delete the user at the end of the test
-        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
-                        self.users_client.delete_user,
-                        user['id'])
+        cls.users.append(user)
+
         return user
diff --git a/patrole_tempest_plugin/tests/api/identity/v3/test_roles_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_roles_rbac.py
index e3eebfc..4708b3f 100644
--- a/patrole_tempest_plugin/tests/api/identity/v3/test_roles_rbac.py
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_roles_rbac.py
@@ -23,6 +23,15 @@
 
 class IdentityRolesV3AdminRbacTest(rbac_base.BaseIdentityV3RbacAdminTest):
 
+    @classmethod
+    def resource_setup(cls):
+        super(IdentityRolesV3AdminRbacTest, cls).resource_setup()
+        cls.domain = cls.setup_test_domain()
+        cls.project = cls.setup_test_project()
+        cls.group = cls.setup_test_group()
+        cls.role = cls.setup_test_role()
+        cls.user = cls.setup_test_user()
+
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:create_role")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d904')
@@ -34,11 +43,10 @@
                                  rule="identity:update_role")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d905')
     def test_update_role(self):
-        role = self.setup_test_role()
         new_role_name = data_utils.rand_name('test_update_role')
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.roles_client.update_role(role['id'],
+        self.roles_client.update_role(self.role['id'],
                                       name=new_role_name)
 
     @rbac_rule_validation.action(service="keystone",
@@ -54,9 +62,8 @@
                                  rule="identity:get_role")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d907')
     def test_show_role(self):
-        role = self.setup_test_role()
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.roles_client.show_role(role['id'])
+        self.roles_client.show_role(self.role['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_roles")
@@ -69,224 +76,194 @@
                                  rule="identity:create_grant")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d909')
     def test_create_user_role_on_project(self):
-        project = self.setup_test_project()
-        role = self.setup_test_role()
-        user = self.setup_test_user()
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.create_user_role_on_project(
-            project['id'],
-            user['id'],
-            role['id'])
+            self.project['id'],
+            self.user['id'],
+            self.role['id'])
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.roles_client.delete_role_from_user_on_project,
-                        project['id'],
-                        user['id'],
-                        role['id'])
+                        self.project['id'],
+                        self.user['id'],
+                        self.role['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:check_grant")
     @decorators.idempotent_id('22921b1e-1a33-4026-bff9-f236d6dd149c')
     def test_check_user_role_existence_on_project(self):
-        project = self.setup_test_project()
-        role = self.setup_test_role()
-        user = self.setup_test_user()
         self.roles_client.create_user_role_on_project(
-            project['id'],
-            user['id'],
-            role['id'])
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.roles_client.check_user_role_existence_on_project(
-            project['id'],
-            user['id'],
-            role['id'])
+            self.project['id'],
+            self.user['id'],
+            self.role['id'])
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.roles_client.delete_role_from_user_on_project,
-                        project['id'],
-                        user['id'],
-                        role['id'])
+                        self.project['id'],
+                        self.user['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.check_user_role_existence_on_project(
+            self.project['id'],
+            self.user['id'],
+            self.role['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:revoke_grant")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90a')
     def test_delete_role_from_user_on_project(self):
-        project = self.setup_test_project()
-        role = self.setup_test_role()
-        user = self.setup_test_user()
         self.roles_client.create_user_role_on_project(
-            project['id'],
-            user['id'],
-            role['id'])
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.roles_client.delete_role_from_user_on_project(
-            project['id'],
-            user['id'],
-            role['id'])
+            self.project['id'],
+            self.user['id'],
+            self.role['id'])
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.roles_client.delete_role_from_user_on_project,
-                        project['id'],
-                        user['id'],
-                        role['id'])
+                        self.project['id'],
+                        self.user['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.delete_role_from_user_on_project(
+            self.project['id'],
+            self.user['id'],
+            self.role['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_grants")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90b')
     def test_list_user_roles_on_project(self):
-        project = self.setup_test_project()
-        user = self.setup_test_user()
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.list_user_roles_on_project(
-            project['id'],
-            user['id'])
+            self.project['id'],
+            self.user['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:create_grant")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90c')
     def test_create_group_role_on_project(self):
-        group = self.setup_test_group()
-        project = self.setup_test_project()
-        role = self.setup_test_role()
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.create_group_role_on_project(
-            project['id'],
-            group['id'],
-            role['id'])
+            self.project['id'],
+            self.group['id'],
+            self.role['id'])
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.roles_client.delete_role_from_group_on_project,
-                        project['id'],
-                        group['id'],
-                        role['id'])
+                        self.project['id'],
+                        self.group['id'],
+                        self.role['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:revoke_grant")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90d')
     def test_delete_role_from_group_on_project(self):
-        group = self.setup_test_group()
-        project = self.setup_test_project()
-        role = self.setup_test_role()
         self.roles_client.create_group_role_on_project(
-            project['id'],
-            group['id'],
-            role['id'])
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.roles_client.delete_role_from_group_on_project(
-            project['id'],
-            group['id'],
-            role['id'])
+            self.project['id'],
+            self.group['id'],
+            self.role['id'])
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.roles_client.delete_role_from_group_on_project,
-                        project['id'],
-                        group['id'],
-                        role['id'])
+                        self.project['id'],
+                        self.group['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.delete_role_from_group_on_project(
+            self.project['id'],
+            self.group['id'],
+            self.role['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_grants")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90e')
     def test_list_group_roles_on_project(self):
-        group = self.setup_test_group()
-        project = self.setup_test_project()
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.list_group_roles_on_project(
-            project['id'],
-            group['id'])
+            self.project['id'],
+            self.group['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:create_grant")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d90f')
     def test_create_user_role_on_domain(self):
-        domain = self.setup_test_domain()
-        role = self.setup_test_role()
-        user = self.setup_test_user()
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.create_user_role_on_domain(
-            domain['id'],
-            user['id'],
-            role['id'])
+            self.domain['id'],
+            self.user['id'],
+            self.role['id'])
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.roles_client.delete_role_from_user_on_domain,
-                        domain['id'],
-                        user['id'],
-                        role['id'])
+                        self.domain['id'],
+                        self.user['id'],
+                        self.role['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:revoke_grant")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d910')
     def test_delete_role_from_user_on_domain(self):
-        domain = self.setup_test_domain()
-        role = self.setup_test_role()
-        user = self.setup_test_user()
         self.roles_client.create_user_role_on_domain(
-            domain['id'],
-            user['id'],
-            role['id'])
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.roles_client.delete_role_from_user_on_domain(
-            domain['id'],
-            user['id'],
-            role['id'])
+            self.domain['id'],
+            self.user['id'],
+            self.role['id'])
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.roles_client.delete_role_from_user_on_domain,
-                        domain['id'],
-                        user['id'],
-                        role['id'])
+                        self.domain['id'],
+                        self.user['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.delete_role_from_user_on_domain(
+            self.domain['id'],
+            self.user['id'],
+            self.role['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_grants")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d911')
     def test_list_user_roles_on_domain(self):
-        domain = self.setup_test_domain()
-        user = self.setup_test_user()
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.list_user_roles_on_domain(
-            domain['id'],
-            user['id'])
+            self.domain['id'],
+            self.user['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:create_grant")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d912')
     def test_create_group_role_on_domain(self):
-        domain = self.setup_test_domain()
-        group = self.setup_test_group()
-        role = self.setup_test_role()
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.create_group_role_on_domain(
-            domain['id'],
-            group['id'],
-            role['id'])
+            self.domain['id'],
+            self.group['id'],
+            self.role['id'])
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.roles_client.delete_role_from_group_on_domain,
-                        domain['id'],
-                        group['id'],
-                        role['id'])
+                        self.domain['id'],
+                        self.group['id'],
+                        self.role['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:revoke_grant")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d913')
     def test_delete_role_from_group_on_domain(self):
-        domain = self.setup_test_domain()
-        group = self.setup_test_group()
-        role = self.setup_test_role()
         self.roles_client.create_group_role_on_domain(
-            domain['id'],
-            group['id'],
-            role['id'])
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.roles_client.delete_role_from_group_on_domain(
-            domain['id'],
-            group['id'],
-            role['id'])
+            self.domain['id'],
+            self.group['id'],
+            self.role['id'])
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
                         self.roles_client.delete_role_from_group_on_domain,
-                        domain['id'],
-                        group['id'],
-                        role['id'])
+                        self.domain['id'],
+                        self.group['id'],
+                        self.role['id'])
+
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.delete_role_from_group_on_domain(
+            self.domain['id'],
+            self.group['id'],
+            self.role['id'])
 
     @rbac_rule_validation.action(service="keystone",
                                  rule="identity:list_grants")
     @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d914')
     def test_list_group_roles_on_domain(self):
-        domain = self.setup_test_domain()
-        group = self.setup_test_group()
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.roles_client.list_group_roles_on_domain(
-            domain['id'],
-            group['id'])
+            self.domain['id'],
+            self.group['id'])