RBAC tests for volume v3 groups and group types

This commit adds RBAC tests for volume v3 groups
and group types APIs. Only the APIs currently
implemented by the corresponding Tempest clients
are tested.

Change-Id: I4ccd52f097eb07221fbb8b9158e53d439573fd97
diff --git a/patrole_tempest_plugin/tests/api/volume/rbac_base.py b/patrole_tempest_plugin/tests/api/volume/rbac_base.py
index 1d390b7..953a834 100644
--- a/patrole_tempest_plugin/tests/api/volume/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/volume/rbac_base.py
@@ -47,6 +47,8 @@
         }
         cls.volume_hosts_client, cls.volume_types_client = \
             version_checker[cls._api_version]
+        cls.groups_client = cls.os_primary.groups_v3_client
+        cls.group_types_client = cls.os_primary.group_types_v3_client
 
     @classmethod
     def resource_setup(cls):
@@ -56,6 +58,8 @@
     @classmethod
     def resource_cleanup(cls):
         super(BaseVolumeRbacTest, cls).resource_cleanup()
+        # Allow volumes to be cleared first, so only clear volume types
+        # after super's resource_cleanup.
         cls.clear_volume_types()
 
     @classmethod
@@ -64,15 +68,33 @@
         name = name or data_utils.rand_name(cls.__name__ + '-volume-type')
         volume_type = cls.volume_types_client.create_volume_type(
             name=name, **kwargs)['volume_type']
-        cls.volume_types.append(volume_type['id'])
+        cls.volume_types.append(volume_type)
         return volume_type
 
+    def create_group_type(self, name=None, ignore_notfound=False, **kwargs):
+        """Create a test group-type"""
+        name = name or data_utils.rand_name(
+            self.__class__.__name__ + '-group-type')
+        group_type = self.group_types_client.create_group_type(
+            name=name, **kwargs)['group_type']
+
+        if ignore_notfound:
+            self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                            self.group_types_client.delete_group_type,
+                            group_type['id'])
+        else:
+            self.addCleanup(self.group_types_client.delete_group_type,
+                            group_type['id'])
+
+        return group_type
+
     @classmethod
     def clear_volume_types(cls):
         for vol_type in cls.volume_types:
             test_utils.call_and_ignore_notfound_exc(
-                cls.volume_types_client.delete_volume_type, vol_type)
+                cls.volume_types_client.delete_volume_type, vol_type['id'])
 
         for vol_type in cls.volume_types:
             test_utils.call_and_ignore_notfound_exc(
-                cls.volume_types_client.wait_for_resource_deletion, vol_type)
+                cls.volume_types_client.wait_for_resource_deletion,
+                vol_type['id'])
diff --git a/patrole_tempest_plugin/tests/api/volume/test_groups_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_groups_rbac.py
new file mode 100644
index 0000000..6b07aaa
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/volume/test_groups_rbac.py
@@ -0,0 +1,143 @@
+# 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.common import waiters
+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_exceptions
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.volume import rbac_base
+
+
+class GroupsV3RbacTest(rbac_base.BaseVolumeRbacTest):
+    _api_version = 3
+    min_microversion = '3.14'
+    max_microversion = 'latest'
+
+    def setUp(self):
+        super(GroupsV3RbacTest, self).setUp()
+        self.volume_type_id = self.create_volume_type()['id']
+        self.group_type_id = self.create_group_type()['id']
+
+    def _create_group(self, name=None, ignore_notfound=False, **kwargs):
+        group_name = name or data_utils.rand_name(
+            self.__class__.__name__ + '-Group')
+        group = self.groups_client.create_group(name=group_name, **kwargs)[
+            'group']
+        waiters.wait_for_volume_resource_status(
+            self.groups_client, group['id'], 'available')
+
+        if ignore_notfound:
+            self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                            self._delete_group, group['id'])
+        else:
+            self.addCleanup(self._delete_group, group['id'])
+
+        return group
+
+    def _delete_group(self, group_id, delete_volumes=True):
+        self.groups_client.delete_group(group_id, delete_volumes)
+        self.groups_client.wait_for_resource_deletion(group_id)
+
+    @decorators.idempotent_id('43235328-66ae-424f-bc7f-f709c0ca268c')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="group:create")
+    def test_create_group(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self._create_group(ignore_notfound=True,
+                           group_type=self.group_type_id,
+                           volume_types=[self.volume_type_id])
+
+    @decorators.idempotent_id('9dc34a62-ae3e-439e-92b6-9389ea4c2863')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="group:get")
+    def test_show_group(self):
+        group = self._create_group(group_type=self.group_type_id,
+                                   volume_types=[self.volume_type_id])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.groups_client.show_group(group['id'])
+
+    @decorators.idempotent_id('db43841b-a173-4317-acfc-f83e4e48e4ee')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="group:get_all")
+    def test_list_groups(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.groups_client.list_groups()['groups']
+
+    @decorators.idempotent_id('5378da93-9c26-4ad4-b039-0555e2b8f668')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="group:get_all")
+    def test_list_groups_with_details(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.groups_client.list_groups(detail=True)['groups']
+
+    @decorators.idempotent_id('66fda391-5774-42a9-a018-80b34e57ab76')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="group:delete")
+    def test_delete_group(self):
+        group = self._create_group(ignore_notfound=True,
+                                   group_type=self.group_type_id,
+                                   volume_types=[self.volume_type_id])
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.groups_client.delete_group(group['id'])
+
+
+class GroupTypesV3RbacTest(rbac_base.BaseVolumeRbacTest):
+    _api_version = 3
+    min_microversion = '3.11'
+    max_microversion = 'latest'
+
+    @decorators.idempotent_id('2820f12c-4681-4c7f-b28d-e6925637dff6')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="group:group_types_manage")
+    def test_create_group_type(self):
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.create_group_type(ignore_notfound=True)
+
+    @decorators.idempotent_id('a5f88c26-df7c-4f21-a3ae-7a4c2d6212b4')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="group:access_group_types_specs")
+    def test_create_group_type_group_specs(self):
+        # TODO(felipemonteiro): Combine with ``test_create_group_type``
+        # once multiple policy testing is supported. This policy is
+        # only enforced after "group:group_types_manage".
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        group_type = self.create_group_type(ignore_notfound=True)
+
+        if 'group_specs' not in group_type:
+            raise rbac_exceptions.RbacActionFailed(
+                'Policy %s does not return %s in response body.' %
+                ('group:access_group_types_specs', 'group_specs'))
+
+    @decorators.idempotent_id('f77f8156-4fc9-4f02-be15-8930f748e10c')
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="group:group_types_manage")
+    def test_delete_group_type(self):
+        goup_type = self.create_group_type(ignore_notfound=True)
+
+        self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+        self.group_types_client.delete_group_type(goup_type['id'])
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py
index 8bb92f4..b666a2d 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py
@@ -155,10 +155,13 @@
     @rbac_rule_validation.action(service="cinder",
                                  rule="volume:retype")
     def test_volume_retype(self):
-        volume = self.create_volume()
         vol_type = self.create_volume_type()['name']
+        volume = self.create_volume()
+
         self.rbac_utils.switch_role(self, toggle_rbac_role=True)
         self.volumes_client.retype_volume(volume['id'], new_type=vol_type)
+        waiters.wait_for_volume_retype(
+            self.os_admin.volumes_client, volume['id'], vol_type)
 
     @rbac_rule_validation.action(
         service="cinder",
diff --git a/releasenotes/notes/volume-v3-groups-rbac-tests-60bddf6fa509545d.yaml b/releasenotes/notes/volume-v3-groups-rbac-tests-60bddf6fa509545d.yaml
new file mode 100644
index 0000000..92b1123
--- /dev/null
+++ b/releasenotes/notes/volume-v3-groups-rbac-tests-60bddf6fa509545d.yaml
@@ -0,0 +1,12 @@
+---
+features:
+  - |
+    Add RBAC tests for the volume v3 groups and group types APIs, providing
+    coverage for the following policy actions:
+
+    * group:create
+    * group:get
+    * group:get_all
+    * group:delete
+    * group:group_types_manage
+    * group:access_group_types_specs