Merge "Clean up rbac_rule_validation unit tests"
diff --git a/patrole_tempest_plugin/rbac_utils.py b/patrole_tempest_plugin/rbac_utils.py
index 81fefb2..9fa3740 100644
--- a/patrole_tempest_plugin/rbac_utils.py
+++ b/patrole_tempest_plugin/rbac_utils.py
@@ -191,25 +191,6 @@
else:
self.switch_role_history[key] = toggle_rbac_role
- def _get_roles(self):
- available_roles = self.admin_roles_client.list_roles()
- admin_role_id = rbac_role_id = None
-
- for role in available_roles['roles']:
- if role['name'] == CONF.patrole.rbac_test_role:
- rbac_role_id = role['id']
- if role['name'] == CONF.identity.admin_role:
- admin_role_id = role['id']
-
- if not admin_role_id or not rbac_role_id:
- msg = "Role with name 'admin' does not exist in the system."\
- if not admin_role_id else "Role defined by rbac_test_role "\
- "does not exist in the system."
- raise rbac_exceptions.RbacResourceSetupFailed(msg)
-
- self.admin_role_id = admin_role_id
- self.rbac_role_id = rbac_role_id
-
def is_admin():
"""Verifies whether the current test role equals the admin role.
diff --git a/patrole_tempest_plugin/tests/api/compute/test_flavor_rxtx_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_flavor_rxtx_rbac.py
index 33b1564..7340689 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_flavor_rxtx_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_flavor_rxtx_rbac.py
@@ -13,12 +13,17 @@
# License for the specific language governing permissions and limitations
# under the License.
+from oslo_config import cfg
+
from tempest.lib import decorators
from tempest import test
+from patrole_tempest_plugin import rbac_exceptions
from patrole_tempest_plugin import rbac_rule_validation
from patrole_tempest_plugin.tests.api.compute import rbac_base
+CONF = cfg.CONF
+
class FlavorRxtxRbacTest(rbac_base.BaseV2ComputeRbacTest):
@@ -29,11 +34,27 @@
msg = "os-flavor-rxtx extension not enabled."
raise cls.skipException(msg)
- @decorators.idempotent_id('0278677c-6e69-4293-a387-b485781e61a1')
+ @decorators.idempotent_id('5e1fd9f0-9a08-485a-ad9c-0fc66e4d64b7')
@rbac_rule_validation.action(
service="nova",
rule="os_compute_api:os-flavor-rxtx")
- def test_create_flavor_rxtx(self):
+ def test_list_flavors_details_rxtx(self):
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
- # Enforces os_compute_api:os-flavor-rxtx.
- self.flavors_client.list_flavors(detail=True)['flavors']
+ # Enforces os_compute_api:os-flavor-rxtx
+ result = self.flavors_client.list_flavors(detail=True)['flavors']
+ if 'rxtx_factor' not in result[0]:
+ raise rbac_exceptions.RbacMalformedResponse(
+ attribute='rxtx_factor')
+
+ @decorators.idempotent_id('70c55a07-c843-4627-a29d-ba78673c1e63')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-flavor-rxtx")
+ def test_get_flavor_rxtx(self):
+ self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+ # Enforces os_compute_api:os-flavor-rxtx
+ result =\
+ self.flavors_client.show_flavor(CONF.compute.flavor_ref)['flavor']
+ if 'rxtx_factor' not in result:
+ raise rbac_exceptions.RbacMalformedResponse(
+ attribute='rxtx_factor')
diff --git a/patrole_tempest_plugin/tests/api/compute/test_security_groups_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_security_groups_rbac.py
index a28ddb9..36d8c2c 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_security_groups_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_security_groups_rbac.py
@@ -61,7 +61,6 @@
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
self.servers_client.list_security_groups_by_server(self.server['id'])
- @decorators.attr(type=["slow"])
@rbac_rule_validation.action(
service="nova",
rule="os_compute_api:os-security-groups")
@@ -75,7 +74,6 @@
self.servers_client.remove_security_group,
self.server['id'], name=sg_name)
- @decorators.attr(type=["slow"])
@rbac_rule_validation.action(
service="nova",
rule="os_compute_api:os-security-groups")
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_misc_policy_actions_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_misc_policy_actions_rbac.py
index 63dee63..654d3f1 100644
--- a/patrole_tempest_plugin/tests/api/compute/test_server_misc_policy_actions_rbac.py
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_misc_policy_actions_rbac.py
@@ -98,7 +98,6 @@
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
self.servers_client.inject_network_info(self.server['id'])
- @decorators.attr(type=['slow'])
@test.requires_ext(extension='os-admin-actions', service='compute')
@rbac_rule_validation.action(
service="nova",
@@ -306,6 +305,29 @@
@rbac_rule_validation.action(
service="nova",
+ rule="os_compute_api:os-keypairs")
+ @decorators.idempotent_id('81e6fa34-c06b-42ca-b195-82bf8699b940')
+ def test_show_server_keypair(self):
+ self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+ result =\
+ self.servers_client.show_server(self.server['id'])['server']
+ if 'key_name' not in result:
+ raise rbac_exceptions.RbacMalformedResponse(
+ attribute='key_name')
+
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-keypairs")
+ @decorators.idempotent_id('41ca4280-ec59-4b80-a9b1-6bc6366faf39')
+ def test_list_servers_keypairs(self):
+ self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+ result = self.servers_client.list_servers(detail=True)['servers']
+ if 'key_name' not in result[0]:
+ raise rbac_exceptions.RbacMalformedResponse(
+ attribute='key_name')
+
+ @rbac_rule_validation.action(
+ service="nova",
rule="os_compute_api:os-lock-server:lock")
@decorators.idempotent_id('b81e10fb-1864-498f-8c1d-5175c6fec5fb')
def test_lock_server(self):
diff --git a/patrole_tempest_plugin/tests/api/image/test_image_resource_types_rbac.py b/patrole_tempest_plugin/tests/api/image/test_image_resource_types_rbac.py
index 6727cc8..456e10b 100644
--- a/patrole_tempest_plugin/tests/api/image/test_image_resource_types_rbac.py
+++ b/patrole_tempest_plugin/tests/api/image/test_image_resource_types_rbac.py
@@ -37,7 +37,7 @@
test_utils.call_and_ignore_notfound_exc(
cls.namespaces_client.delete_namespace,
cls.namespace_name)
- super(ImageResourceTypesRbacTest, cls).resource_setup()
+ super(ImageResourceTypesRbacTest, cls).resource_cleanup()
@rbac_rule_validation.action(service="glance",
rule="list_metadef_resource_types")
diff --git a/patrole_tempest_plugin/tests/api/network/test_subnetpools_rbac.py b/patrole_tempest_plugin/tests/api/network/test_subnetpools_rbac.py
index 8c799b6..44f6be4 100644
--- a/patrole_tempest_plugin/tests/api/network/test_subnetpools_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_subnetpools_rbac.py
@@ -102,8 +102,7 @@
@decorators.idempotent_id('a16f4e5c-0675-415f-b636-00af00638693')
@rbac_rule_validation.action(service="neutron",
- rule="update_subnetpool:is_default",
- expected_error_code=404)
+ rule="update_subnetpool:is_default")
def test_update_subnetpool_is_default(self):
"""Update default subnetpool.
@@ -123,8 +122,7 @@
default_pool['id'], description=original_desc, is_default=True)
@rbac_rule_validation.action(service="neutron",
- rule="delete_subnetpool",
- expected_error_code=404)
+ rule="delete_subnetpool")
@decorators.idempotent_id('50f5944e-43e5-457b-ab50-fb48a73f0d3e')
def test_delete_subnetpool(self):
"""Delete subnetpool.
diff --git a/patrole_tempest_plugin/tests/api/volume/rbac_base.py b/patrole_tempest_plugin/tests/api/volume/rbac_base.py
index c43c552..6db364e 100644
--- a/patrole_tempest_plugin/tests/api/volume/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/volume/rbac_base.py
@@ -35,14 +35,8 @@
super(BaseVolumeRbacTest, cls).setup_clients()
cls.rbac_utils = rbac_utils.RbacUtils(cls)
- version_checker = {
- 2: [cls.os_primary.volume_hosts_v2_client,
- cls.os_primary.volume_types_v2_client],
- 3: [cls.os_primary.volume_hosts_v2_client,
- cls.os_primary.volume_types_v2_client]
- }
- cls.volume_hosts_client, cls.volume_types_client = \
- version_checker[cls._api_version]
+ cls.volume_hosts_client = cls.os_primary.volume_hosts_v2_client
+ cls.volume_types_client = cls.os_primary.volume_types_v2_client
cls.groups_client = cls.os_primary.groups_v3_client
cls.group_types_client = cls.os_primary.group_types_v3_client
diff --git a/patrole_tempest_plugin/tests/api/volume/test_qos_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_qos_rbac.py
index 7d9ec0f..2327de8 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_qos_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_qos_rbac.py
@@ -146,3 +146,7 @@
self.qos_client.disassociate_all_qos(qos['id'])
waiters.wait_for_qos_operations(self.admin_qos_client, qos['id'],
'disassociate-all')
+
+
+class VolumeQOSV3RbacTest(VolumeQOSRbacTest):
+ _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud_rbac.py
index d780de7..3f5227e 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud_rbac.py
@@ -20,11 +20,11 @@
from patrole_tempest_plugin.tests.api.volume import rbac_base
-class VolumesV2BasicCrudRbacTest(rbac_base.BaseVolumeRbacTest):
+class VolumesBasicCrudRbacTest(rbac_base.BaseVolumeRbacTest):
@classmethod
def resource_setup(cls):
- super(VolumesV2BasicCrudRbacTest, cls).resource_setup()
+ super(VolumesBasicCrudRbacTest, cls).resource_setup()
cls.volume = cls.create_volume()
@rbac_rule_validation.action(service="cinder",
@@ -72,5 +72,5 @@
self.volumes_client.list_volumes(detail=True)
-class VolumesV3BasicCrudRbacTest(VolumesV2BasicCrudRbacTest):
+class VolumesBasicCrudV3RbacTest(VolumesBasicCrudRbacTest):
_api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_hosts_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_hosts_rbac.py
index 18a2768..ee0a0be 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_hosts_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_hosts_rbac.py
@@ -27,3 +27,19 @@
def test_list_hosts(self):
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
self.volume_hosts_client.list_hosts()
+
+ @decorators.idempotent_id('9ddf321e-788f-4787-b8cc-dfa59e264143')
+ @rbac_rule_validation.action(service="cinder",
+ rule="volume_extension:hosts")
+ def test_show_host(self):
+ hosts = self.volume_hosts_client.list_hosts()['hosts']
+ host_names = [host['host_name'] for host in hosts]
+ self.assertNotEmpty(host_names, "No available volume host was found, "
+ "all hosts found were: %s" % hosts)
+
+ self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+ self.volume_hosts_client.show_host(host_names[0])
+
+
+class VolumeHostsV3RbacTest(VolumeHostsRbacTest):
+ _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_metadata_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_metadata_rbac.py
index 8c4185b..f9114a8 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_metadata_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_metadata_rbac.py
@@ -103,3 +103,7 @@
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
self.volumes_client.update_volume_image_metadata(
self.volume['id'], image_id=self.image_id)
+
+
+class VolumeMetadataV3RbacTest(VolumeMetadataRbacTest):
+ _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py
index 7eb1cf0..7ca3d9f 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py
@@ -22,6 +22,7 @@
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
@@ -32,10 +33,6 @@
credentials = ['primary', 'admin']
- def setUp(self):
- super(VolumesBackupsRbacTest, self).setUp()
- self.volume = self.create_volume()
-
@classmethod
def skip_checks(cls):
super(VolumesBackupsRbacTest, cls).skip_checks()
@@ -47,6 +44,11 @@
super(VolumesBackupsRbacTest, cls).setup_clients()
cls.admin_backups_client = cls.os_admin.backups_v2_client
+ @classmethod
+ def resource_setup(cls):
+ super(VolumesBackupsRbacTest, cls).resource_setup()
+ cls.volume = cls.create_volume()
+
def _decode_url(self, backup_url):
return json.loads(base64.decode_as_text(backup_url))
@@ -73,6 +75,7 @@
@decorators.idempotent_id('abd92bdd-b0fb-4dc4-9cfc-de9e968f8c8a')
def test_show_backup(self):
backup = self.create_backup(volume_id=self.volume['id'])
+
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
self.backups_client.show_backup(backup['id'])
@@ -96,8 +99,7 @@
service="cinder",
rule="volume_extension:backup_admin_actions:reset_status")
def test_reset_backup_status(self):
- volume = self.create_volume()
- backup = self.create_backup(volume_id=volume['id'])
+ backup = self.create_backup(volume_id=self.volume['id'])
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
self.backups_client.reset_backup_status(backup_id=backup['id'],
@@ -135,7 +137,7 @@
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
self.backups_client.delete_backup(backup['id'])
# Wait for deletion so error isn't thrown during clean up.
- self.backups_client.wait_for_resource_deletion(backup['id'])
+ self.admin_backups_client.wait_for_resource_deletion(backup['id'])
@decorators.attr(type='slow')
@rbac_rule_validation.action(service="cinder",
@@ -143,6 +145,7 @@
@decorators.idempotent_id('e984ec8d-e8eb-485c-98bc-f1856020303c')
def test_export_backup(self):
backup = self.create_backup(volume_id=self.volume['id'])
+
self.rbac_utils.switch_role(self, toggle_rbac_role=True)
self.backups_client.export_backup(backup['id'])['backup-record']
@@ -167,3 +170,34 @@
class VolumesBackupsV3RbacTest(VolumesBackupsRbacTest):
_api_version = 3
+
+
+class VolumesBackupsV318RbacTest(rbac_base.BaseVolumeRbacTest):
+ _api_version = 3
+ # The minimum microversion for showing 'os-backup-project-attr:project_id'
+ # is 3.18.
+ min_microversion = '3.18'
+ max_microversion = 'latest'
+
+ @classmethod
+ def skip_checks(cls):
+ super(VolumesBackupsV318RbacTest, cls).skip_checks()
+ if not CONF.volume_feature_enabled.backup:
+ raise cls.skipException("Cinder backup feature disabled")
+
+ @decorators.idempotent_id('69801485-d5be-4e75-bbb4-168d50b5a8c2')
+ @rbac_rule_validation.action(service="cinder",
+ rule="backup:backup_project_attribute")
+ def test_show_backup_project_attribute(self):
+ volume = self.create_volume()
+ backup = self.create_backup(volume_id=volume['id'])
+ expected_attr = 'os-backup-project-attr:project_id'
+
+ self.rbac_utils.switch_role(self, toggle_rbac_role=True)
+ body = self.backups_client.show_backup(backup['id'])['backup']
+
+ # Show backup API attempts to inject the attribute below into the
+ # response body but only if policy enforcement succeeds.
+ if expected_attr not in body:
+ raise rbac_exceptions.RbacMalformedResponse(
+ attribute=expected_attr)
diff --git a/releasenotes/notes/backup-project-attribute-test-504f053c6ec95b85.yaml b/releasenotes/notes/backup-project-attribute-test-504f053c6ec95b85.yaml
new file mode 100644
index 0000000..01a55cc
--- /dev/null
+++ b/releasenotes/notes/backup-project-attribute-test-504f053c6ec95b85.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Add RBAC test for "backup:backup_project_attribute" which verifies
+ that the "os-backup-project-attr:project_id" attribute appears in
+ the response body once policy enforcement succeeds.
diff --git a/releasenotes/notes/flavor-rxtx-d7aadbb32a9f232c.yaml b/releasenotes/notes/flavor-rxtx-d7aadbb32a9f232c.yaml
new file mode 100644
index 0000000..083d9b0
--- /dev/null
+++ b/releasenotes/notes/flavor-rxtx-d7aadbb32a9f232c.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ test_flavor_rxtx_rbac now offers complete
+ coverage for the os-flavor-rxtx policy.
diff --git a/releasenotes/notes/keypairs-c8355d9496f83f9f.yaml b/releasenotes/notes/keypairs-c8355d9496f83f9f.yaml
new file mode 100644
index 0000000..0580c0e
--- /dev/null
+++ b/releasenotes/notes/keypairs-c8355d9496f83f9f.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ Adds tests to see if key_name is returned in server
+ response to test_server_misc_policy_actions_rbac.
diff --git a/releasenotes/notes/start-of-pike-support-360e27b4d192e3d2.yaml b/releasenotes/notes/start-of-pike-support-360e27b4d192e3d2.yaml
new file mode 100644
index 0000000..50e9159
--- /dev/null
+++ b/releasenotes/notes/start-of-pike-support-360e27b4d192e3d2.yaml
@@ -0,0 +1,10 @@
+---
+prelude: >
+ This release marks the start of support for the Pike release in Patrole.
+other:
+ - OpenStack Releases supported after this release are **Pike**.
+
+ The release under current development of this tag is Queens, meaning
+ that every Patrole commit is also tested against master during the Queens
+ cycle. However, this does not necessarily mean that using Patrole as of
+ this tag will work against a Queens (or future release) cloud.
diff --git a/requirements.txt b/requirements.txt
index 00c7e64..abccb62 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,9 +3,8 @@
# process, which may cause wedges in the gate later.
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
pbr!=2.1.0,>=2.0.0 # Apache-2.0
-urllib3>=1.21.1 # MIT
oslo.log>=3.30.0 # Apache-2.0
-oslo.config!=4.3.0,!=4.4.0,>=4.0.0 # Apache-2.0
+oslo.config>=4.6.0 # Apache-2.0
oslo.policy>=1.23.0 # Apache-2.0
tempest>=16.1.0 # Apache-2.0
stevedore>=1.20.0 # Apache-2.0
diff --git a/test-requirements.txt b/test-requirements.txt
index 0657438..dc2fec9 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -4,13 +4,13 @@
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
sphinx>=1.6.2 # BSD
-openstackdocstheme>=1.16.0 # Apache-2.0
+openstackdocstheme>=1.17.0 # Apache-2.0
reno>=2.5.0 # Apache-2.0
fixtures>=3.0.0 # Apache-2.0/BSD
mock>=2.0.0 # BSD
coverage!=4.4,>=4.0 # Apache-2.0
-nose # LGPL
-nosexcover # BSD
+nose>=1.3.7 # LGPL
+nosexcover>=1.0.10 # BSD
oslotest>=1.10.0 # Apache-2.0
oslo.policy>=1.23.0 # Apache-2.0
oslo.log>=3.30.0 # Apache-2.0