Merge "Identity V3 (ext) Tests - Oauth Consumers"
diff --git a/contrib/post_test_hook.sh b/contrib/post_test_hook.sh
index 2eb494f..085b5b1 100644
--- a/contrib/post_test_hook.sh
+++ b/contrib/post_test_hook.sh
@@ -26,12 +26,9 @@
 
 TEMPEST_CONFIG=$BASE/new/tempest/etc/tempest.conf
 TEMPEST_COMMAND="sudo -H -u tempest tox"
-# TODO(felipemonteiro): This regex does a negative lookahead to exclude slow
-# tests that contain the @test.attr(type='slow') decorator above them. Slower
-# tests will execute those tests in a separate gate, which will require
-# future modification of this script.
-DEVSTACK_FAST_GATE_TEMPEST_REGEX="(?!.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api)"
-DEVSTACK_SLOW_GATE_TEMPEST_REGEX="(?=.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api)"
+
+DEVSTACK_GATE_TEMPEST_REGEX="(?!.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api)"
+DEVSTACK_MULTINODE_GATE_TEMPEST_REGEX="(?=.*\[.*\bslow\b.*\])(^patrole_tempest_plugin\.tests\.api)"
 
 # Import devstack function 'iniset'.
 source $BASE/new/devstack/functions
@@ -49,8 +46,8 @@
     RBAC_ROLE="Member"
 fi
 
-# Second argument is expected to contain value to indicate whether it is
-# a "fast' or "slow test" gate
+# Second argument is expected to contain value indicating whether the
+# environment is "multinode" or not (empty string).
 TYPE=$2
 
 # Set enable_rbac=True under [rbac] section in tempest.conf
@@ -73,11 +70,10 @@
 # cd into Tempest directory before executing tox.
 cd $BASE/new/tempest
 
-# Select Fast Gate if Type is set to 'fast', else use 'slow' gate
-if [[ "$TYPE" == "fast" ]]; then
-    $TEMPEST_COMMAND -eall-plugin -- $DEVSTACK_FAST_GATE_TEMPEST_REGEX --concurrency=$TEMPEST_CONCURRENCY
+if [[ "$TYPE" == "multinode" ]]; then
+    $TEMPEST_COMMAND -eall-plugin -- $DEVSTACK_MULTINODE_GATE_TEMPEST_REGEX --concurrency=$TEMPEST_CONCURRENCY
 else
-    $TEMPEST_COMMAND -eall-plugin -- $DEVSTACK_SLOW_GATE_TEMPEST_REGEX --concurrency=$TEMPEST_CONCURRENCY
+    $TEMPEST_COMMAND -eall-plugin -- $DEVSTACK_GATE_TEMPEST_REGEX --concurrency=$TEMPEST_CONCURRENCY
 fi
 
 sudo -H -u tempest .tox/all-plugin/bin/tempest list-plugins
diff --git a/patrole_tempest_plugin/tests/api/compute/test_deferred_delete_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_deferred_delete_rbac.py
index eceef12..79d2c52 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_deferred_delete_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_deferred_delete_rbac.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.lib import decorators
 from tempest import test
 
 from patrole_tempest_plugin import rbac_rule_validation
@@ -39,6 +40,7 @@
         super(DeferredDeleteRbacTest, cls).resource_setup()
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
+    @decorators.idempotent_id('189bfed4-1e6d-475c-bb8c-d57e60895391')
     @rbac_rule_validation.action(
         service="nova",
         rule="os_compute_api:os-deferred-delete")
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 bc9b61a..44504cf 100644
--- a/patrole_tempest_plugin/tests/api/identity/v3/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/identity/v3/rbac_base.py
@@ -50,142 +50,195 @@
         cls.projects_client = cls.os.projects_client
         cls.policies_client = cls.os.policies_client
         cls.regions_client = cls.os.regions_client
+        cls.role_assignments_client = cls.os.role_assignments_client
         cls.roles_client = cls.os.roles_v3_client
         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_role_assignments_rbac.py b/patrole_tempest_plugin/tests/api/identity/v3/test_role_assignments_rbac.py
new file mode 100644
index 0000000..878edcb
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_role_assignments_rbac.py
@@ -0,0 +1,47 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
+
+
+class IdentityRoleAssignmentsV3AdminRbacTest(
+        rbac_base.BaseIdentityV3RbacAdminTest):
+
+    @classmethod
+    def setup_clients(cls):
+        super(IdentityRoleAssignmentsV3AdminRbacTest, cls).setup_clients()
+        cls.client = cls.role_assignments_client
+
+    @decorators.idempotent_id('afe57adb-1b9c-43d9-84a9-f0cf4c94e416')
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_role_assignments")
+    def test_list_role_assignments(self):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.client.list_role_assignments()['role_assignments']
+
+    @decorators.idempotent_id('36c7a990-857e-415c-8717-38d7200a9894')
+    @rbac_rule_validation.action(
+        service="keystone",
+        rule="identity:list_role_assignments_for_tree")
+    def test_list_role_assignments_for_tree(self):
+        project = self.setup_test_project()
+
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.client.list_role_assignments(
+            include_subtree=True, **{'scope.project.id': project['id']})[
+            'role_assignments']
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
new file mode 100644
index 0000000..4708b3f
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/identity/v3/test_roles_rbac.py
@@ -0,0 +1,269 @@
+# Copyright 2017 AT&T Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.identity.v3 import rbac_base
+
+
+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')
+    def test_create_role(self):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.setup_test_role()
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:update_role")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d905')
+    def test_update_role(self):
+        new_role_name = data_utils.rand_name('test_update_role')
+
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.update_role(self.role['id'],
+                                      name=new_role_name)
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:delete_role")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d906')
+    def test_delete_role(self):
+        role = self.setup_test_role()
+
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.delete_role(role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:get_role")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d907')
+    def test_show_role(self):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.show_role(self.role['id'])
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:list_roles")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d908')
+    def test_list_roles(self):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.list_roles()
+
+    @rbac_rule_validation.action(service="keystone",
+                                 rule="identity:create_grant")
+    @decorators.idempotent_id('0f148510-63bf-11e6-1395-080044d0d909')
+    def test_create_user_role_on_project(self):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.create_user_role_on_project(
+            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,
+                        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):
+        self.roles_client.create_user_role_on_project(
+            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,
+                        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):
+        self.roles_client.create_user_role_on_project(
+            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,
+                        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):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.list_user_roles_on_project(
+            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):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.create_group_role_on_project(
+            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,
+                        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):
+        self.roles_client.create_group_role_on_project(
+            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,
+                        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):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.list_group_roles_on_project(
+            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):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.create_user_role_on_domain(
+            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,
+                        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):
+        self.roles_client.create_user_role_on_domain(
+            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,
+                        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):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.list_user_roles_on_domain(
+            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):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.create_group_role_on_domain(
+            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,
+                        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):
+        self.roles_client.create_group_role_on_domain(
+            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,
+                        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):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.roles_client.list_group_roles_on_domain(
+            self.domain['id'],
+            self.group['id'])
diff --git a/tox.ini b/tox.ini
index 85314b6..e123d64 100644
--- a/tox.ini
+++ b/tox.ini
@@ -19,10 +19,10 @@
 
 [testenv:pep8]
 commands = flake8 {posargs}
-           check-uuid
+           check-uuid --package patrole_tempest_plugin.tests.api
 
 [testenv:uuidgen]
-commands = check-uuid --fix
+commands = check-uuid --package patrole_tempest_plugin.tests.api --fix
 
 [testenv:venv]
 commands = {posargs}