Merge "Cinder tests - Volume types"
diff --git a/contrib/pre_test_hook.sh b/contrib/pre_test_hook.sh
new file mode 100755
index 0000000..65d1801
--- /dev/null
+++ b/contrib/pre_test_hook.sh
@@ -0,0 +1,39 @@
+#!/bin/bash -xe
+#
+# 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.
+
+# This script is executed inside post_test_hook function in devstack gate.
+# First argument ($1) expects 'rbac-role' as value for setting appropriate
+# tempest rbac option 'rbac_test_role'.
+
+sudo chown -R jenkins:stack $BASE/new/tempest
+sudo chown -R jenkins:stack $BASE/data/tempest
+
+# Import devstack function 'iniset'
+source $BASE/new/devstack/functions
+
+export TEMPEST_CONFIG=${TEMPEST_CONFIG:-$BASE/new/tempest/etc/tempest.conf}
+
+# First argument is expected to contain value equal either to 'admin' or
+# 'member' (both lower-case).
+RBAC_ROLE=$1
+
+if [[ "$RBAC_ROLE" == "member" ]]; then
+ $RBAC_ROLE = "Member"
+fi
+
+# Set rbac_flag=True under [rbac] section in tempest.conf
+iniset $TEMPEST_CONFIG rbac rbac_flag True
+
+# Set rbac_test_role=$RBAC_ROLE under [rbac] section in tempest.conf
+iniset $TEMPEST_CONFIG rbac rbac_test_role $RBAC_ROLE
diff --git a/patrole_tempest_plugin/rbac_utils.py b/patrole_tempest_plugin/rbac_utils.py
index d5f1c2b..69c6ccd 100644
--- a/patrole_tempest_plugin/rbac_utils.py
+++ b/patrole_tempest_plugin/rbac_utils.py
@@ -55,32 +55,25 @@
cls.rbac_role_id = item['id']
if item['name'] == 'admin':
cls.admin_role_id = item['id']
- # Check if admin and rbac role exits
- if not cls.admin_role_id or not cls.rbac_role_id:
- msg = ("defined 'rbac_role' or 'admin' role does not exist"
- " in the system.")
- raise rbac_exceptions.RbacResourceSetupFailed(msg)
-
- def clear_user_roles(cls, user_id, tenant_id):
- roles = cls.creds_client.roles_client.list_user_roles_on_project(
- tenant_id, user_id)['roles']
-
- for role in roles:
- cls.creds_client.roles_client.delete_role_from_user_on_project(
- tenant_id, user_id, role['id'])
def switch_role(cls, test_obj, switchToRbacRole=None):
LOG.debug('Switching role to: %s', switchToRbacRole)
+ # Check if admin and rbac roles exist.
+ if not cls.admin_role_id or not cls.rbac_role_id:
+ msg = ("Defined 'rbac_role' or 'admin' role does not exist"
+ " in the system.")
+ raise rbac_exceptions.RbacResourceSetupFailed(msg)
+
if not isinstance(switchToRbacRole, bool):
msg = ("Wrong value for parameter 'switchToRbacRole' is passed."
" It should be either 'True' or 'False'.")
- raise rbac_exceptions.RbacActionFailed(msg)
+ raise rbac_exceptions.RbacResourceSetupFailed(msg)
try:
user_id = test_obj.auth_provider.credentials.user_id
project_id = test_obj.auth_provider.credentials.tenant_id
- cls.clear_user_roles(user_id, project_id)
+ cls._clear_user_roles(user_id, project_id)
if switchToRbacRole:
cls.creds_client.roles_client.create_user_role_on_project(
@@ -100,4 +93,12 @@
time.sleep(1)
test_obj.auth_provider.set_auth()
+ def _clear_user_roles(cls, user_id, tenant_id):
+ roles = cls.creds_client.roles_client.list_user_roles_on_project(
+ tenant_id, user_id)['roles']
+
+ for role in roles:
+ cls.creds_client.roles_client.delete_role_from_user_on_project(
+ tenant_id, user_id, role['id'])
+
rbac_utils = RbacUtils
diff --git a/patrole_tempest_plugin/tests/api/compute/test_keypairs_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_keypairs_rbac.py
new file mode 100644
index 0000000..d4d9306
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/compute/test_keypairs_rbac.py
@@ -0,0 +1,75 @@
+# 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.compute import rbac_base
+
+
+class KeypairsRbacTest(rbac_base.BaseV2ComputeRbacTest):
+
+ @classmethod
+ def setup_clients(cls):
+ super(KeypairsRbacTest, cls).setup_clients()
+ cls.client = cls.keypairs_client
+
+ def tearDown(self):
+ self.rbac_utils.switch_role(self, switchToRbacRole=False)
+ super(KeypairsRbacTest, self).tearDown()
+
+ def _create_keypair(self):
+ key_name = data_utils.rand_name('key')
+ keypair = self.client.create_keypair(name=key_name)
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.client.delete_keypair,
+ key_name)
+ return keypair
+
+ @decorators.idempotent_id('16e0ae81-e05f-48cd-b253-cf31ab0732f0')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-keypairs:create")
+ def test_create_keypair(self):
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self._create_keypair()
+
+ @decorators.idempotent_id('85a5eb99-40ec-4e77-9358-bee2cdf9d7df')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-keypairs:show")
+ def test_show_keypair(self):
+ kp_name = self._create_keypair()['keypair']['name']
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.client.show_keypair(kp_name)
+
+ @decorators.idempotent_id('6bff9f1c-b809-43c1-8d63-61fbd19d49d3')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-keypairs:delete")
+ def test_delete_keypair(self):
+ kp_name = self._create_keypair()['keypair']['name']
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.client.delete_keypair(kp_name)
+
+ @decorators.idempotent_id('6bb31346-ff7f-4b10-978e-170ac5fcfa3e')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-keypairs:index")
+ def test_index_keypair(self):
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.client.list_keypairs()
diff --git a/patrole_tempest_plugin/tests/api/compute/test_server_tags_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_server_tags_rbac.py
new file mode 100644
index 0000000..14f0638
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/compute/test_server_tags_rbac.py
@@ -0,0 +1,105 @@
+# 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 import decorators
+from tempest import test
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.compute import rbac_base
+
+
+class ServerTagsRbacTest(rbac_base.BaseV2ComputeRbacTest):
+
+ min_microversion = '2.26'
+ max_microversion = 'latest'
+
+ @classmethod
+ def skip_checks(cls):
+ super(ServerTagsRbacTest, cls).skip_checks()
+ if not test.is_extension_enabled('os-server-tags', 'compute'):
+ msg = "os-server-tags extension is not enabled."
+ raise cls.skipException(msg)
+
+ @classmethod
+ def setup_clients(cls):
+ super(ServerTagsRbacTest, cls).setup_clients()
+ cls.client = cls.servers_client
+
+ @classmethod
+ def resource_setup(cls):
+ super(ServerTagsRbacTest, cls).resource_setup()
+ cls.server = cls.create_test_server(wait_until='ACTIVE')
+
+ def tearDown(self):
+ self.rbac_utils.switch_role(self, switchToRbacRole=False)
+ super(ServerTagsRbacTest, self).tearDown()
+
+ def _add_tag_to_server(self):
+ tag_name = data_utils.rand_name('tag')
+ self.client.update_tag(self.server['id'], tag_name)
+ self.addCleanup(self.client.delete_all_tags, self.server['id'])
+ return tag_name
+
+ @decorators.idempotent_id('99e73dd3-adec-4044-b46c-84bdded35d09')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-server-tags:index")
+ def test_list_tags(self):
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.client.list_tags(self.server['id'])['tags']
+
+ @decorators.idempotent_id('9297c99e-94eb-429f-93cf-9b1838e33622')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-server-tags:show")
+ def test_check_tag_existence(self):
+ tag_name = self._add_tag_to_server()
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.client.check_tag_existence(self.server['id'], tag_name)
+
+ @decorators.idempotent_id('0d84ee94-d3ca-4635-8edf-b7f67ab8e4a3')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-server-tags:update")
+ def test_update_tag(self):
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self._add_tag_to_server()
+
+ @decorators.idempotent_id('115c2694-00aa-41ee-99f6-9eab4040c182')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-server-tags:delete")
+ def test_delete_tag(self):
+ tag_name = self._add_tag_to_server()
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.client.delete_tag(self.server['id'], tag_name)
+
+ @decorators.idempotent_id('a8e19b87-6580-4bc8-9933-e62561ff667d')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-server-tags:update_all")
+ def test_update_all_tags(self):
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ new_tag_name = data_utils.rand_name('tag')
+ self.client.update_all_tags(self.server['id'], [new_tag_name])['tags']
+
+ @decorators.idempotent_id('89d51936-e333-42f9-a045-132a4865ba1a')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-server-tags:delete_all")
+ def test_delete_all_tags(self):
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.client.delete_all_tags(self.server['id'])
diff --git a/patrole_tempest_plugin/tests/api/network/test_security_groups_rbac.py b/patrole_tempest_plugin/tests/api/network/test_security_groups_rbac.py
new file mode 100644
index 0000000..25f1acf
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/network/test_security_groups_rbac.py
@@ -0,0 +1,191 @@
+# 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 oslo_log import log
+
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions
+
+from patrole_tempest_plugin import rbac_exceptions
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.network import rbac_base as base
+
+LOG = log.getLogger(__name__)
+
+
+class SecGroupRbacTest(base.BaseNetworkRbacTest):
+
+ def tearDown(self):
+ self.rbac_utils.switch_role(self, switchToRbacRole=False)
+ super(SecGroupRbacTest, self).tearDown()
+
+ @classmethod
+ def resource_setup(cls):
+ super(SecGroupRbacTest, cls).resource_setup()
+ secgroup_name = data_utils.rand_name('secgroup')
+ cls.secgroup = cls.security_groups_client.create_security_group(
+ name=secgroup_name)['security_group']
+
+ @classmethod
+ def resource_cleanup(cls):
+ # Clean up security group
+ test_utils.call_and_ignore_notfound_exc(
+ cls.security_groups_client.delete_security_group,
+ cls.secgroup['id'])
+ super(SecGroupRbacTest, cls).resource_cleanup()
+
+ def _create_security_group(self):
+ # Create a security group
+ name = data_utils.rand_name('secgroup')
+ security_group =\
+ self.security_groups_client.create_security_group(
+ name=name)['security_group']
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.security_groups_client.delete_security_group,
+ security_group['id'])
+ return security_group
+
+ def _create_security_group_rule(self):
+ # Create a security group rule
+ sec_group_rule = \
+ self.security_group_rules_client.create_security_group_rule(
+ security_group_id=self.secgroup['id'],
+ direction='ingress',
+ protocol='tcp',
+ port_range_min=99,
+ port_range_max=99)['security_group_rule']
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.security_group_rules_client.delete_security_group_rule,
+ sec_group_rule['id'])
+ return sec_group_rule
+
+ @rbac_rule_validation.action(service="neutron",
+ rule="create_security_group")
+ @decorators.idempotent_id('db7003ce-5717-4e5b-afc7-befa35e8c67f')
+ def test_create_security_group(self):
+
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self._create_security_group()
+
+ @rbac_rule_validation.action(service="neutron",
+ rule="get_security_group")
+ @decorators.idempotent_id('56335e77-aef2-4b54-86c7-7f772034b585')
+ def test_show_security_groups(self):
+
+ try:
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.security_groups_client.show_security_group(
+ self.secgroup['id'])
+ except exceptions.NotFound as e:
+ LOG.info("NotFound exception caught. Exception is thrown when "
+ "role doesn't have access to the endpoint."
+ "This is irregular and should be fixed.")
+ raise rbac_exceptions.RbacActionFailed(e)
+
+ @rbac_rule_validation.action(service="neutron",
+ rule="delete_security_group")
+ @decorators.idempotent_id('0b1330fd-dd28-40f3-ad73-966052e4b3de')
+ def test_delete_security_group(self):
+
+ # Create a security group
+ secgroup_id = self._create_security_group()['id']
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ try:
+ self.security_groups_client.delete_security_group(secgroup_id)
+ except exceptions.NotFound as e:
+ LOG.info("NotFound exception caught. Exception is thrown when "
+ "role doesn't have access to the endpoint."
+ "This is irregular and should be fixed.")
+ raise rbac_exceptions.RbacActionFailed(e)
+
+ @rbac_rule_validation.action(service="neutron",
+ rule="update_security_group")
+ @decorators.idempotent_id('56c5e4dc-f8aa-11e6-bc64-92361f002671')
+ def test_update_security_group(self):
+
+ # Create a security group
+ secgroup_id = self._create_security_group()['id']
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ try:
+ self.security_groups_client.update_security_group(
+ secgroup_id,
+ description="test description")
+ except exceptions.NotFound as e:
+ LOG.info("NotFound exception caught. Exception is thrown when "
+ "role doesn't have access to the endpoint."
+ "This is irregular and should be fixed.")
+ raise rbac_exceptions.RbacActionFailed(e)
+
+ @rbac_rule_validation.action(service="neutron",
+ rule="get_security_groups")
+ @decorators.idempotent_id('fbaf8d96-ed3e-49af-b24c-5fb44f05bbb7')
+ def test_list_security_groups(self):
+
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.security_groups_client.list_security_groups()
+
+ @rbac_rule_validation.action(service="neutron",
+ rule="create_security_group_rule")
+ @decorators.idempotent_id('953d78df-00cd-416f-9cbd-b7cb4ea65772')
+ def test_create_security_group_rule(self):
+
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self._create_security_group_rule()
+
+ @rbac_rule_validation.action(service="neutron",
+ rule="delete_security_group_rule")
+ @decorators.idempotent_id('2262539e-b7d9-438c-acf9-a5ce0613be28')
+ def test_delete_security_group_rule(self):
+
+ sec_group_rule = self._create_security_group_rule()
+
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ try:
+ self.security_group_rules_client.delete_security_group_rule(
+ sec_group_rule['id'])
+ except exceptions.NotFound as e:
+ LOG.info("NotFound exception caught. Exception is thrown when "
+ "role doesn't have access to the endpoint."
+ "This is irregular and should be fixed.")
+ raise rbac_exceptions.RbacActionFailed(e)
+
+ @rbac_rule_validation.action(service="neutron",
+ rule="get_security_group_rule")
+ @decorators.idempotent_id('84b4038c-261e-4a94-90d5-c885739ab0d5')
+ def test_show_security_group_rule(self):
+
+ sec_group_rule = self._create_security_group_rule()
+
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ try:
+ self.security_group_rules_client.show_security_group_rule(
+ sec_group_rule['id'])
+ except exceptions.NotFound as e:
+ LOG.info("NotFound exception caught. Exception is thrown when "
+ "role doesn't have access to the endpoint."
+ "This is irregular and should be fixed.")
+ raise rbac_exceptions.RbacActionFailed(e)
+
+ @rbac_rule_validation.action(service="neutron",
+ rule="get_security_group_rules")
+ @decorators.idempotent_id('05739ab6-fa35-11e6-bc64-92361f002671')
+ def test_list_security_group_rules(self):
+
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.security_group_rules_client.list_security_group_rules()
diff --git a/patrole_tempest_plugin/tests/unit/test_rbac_utils.py b/patrole_tempest_plugin/tests/unit/test_rbac_utils.py
index 9dd5985..add1770 100644
--- a/patrole_tempest_plugin/tests/unit/test_rbac_utils.py
+++ b/patrole_tempest_plugin/tests/unit/test_rbac_utils.py
@@ -15,45 +15,141 @@
import mock
+from tempest import config
from tempest.lib import exceptions as lib_exc
from tempest.tests import base
from patrole_tempest_plugin import rbac_exceptions
from patrole_tempest_plugin import rbac_utils
+CONF = config.CONF
+
class RBACUtilsTest(base.TestCase):
- def setUp(self):
+
+ @mock.patch.object(rbac_utils, 'time', autospec=True)
+ def setUp(self, _):
super(RBACUtilsTest, self).setUp()
- mock_creds_provider = mock.patch.object(
- rbac_utils, 'credentials_factory').start()
- mock_creds_provider.get_credentials_provider.return_value.\
- creds_client.roles_client.list_roles.return_value.\
- __getitem__.return_value = [
+ self.mock_creds_provider = mock.patch.object(
+ rbac_utils, 'credentials_factory', autospec=True).start()
+
+ available_roles = {
+ 'roles': [
{'name': 'admin', 'id': 'admin_id'},
{'name': 'Member', 'id': 'member_id'}
]
+ }
+ self.mock_creds_provider.get_credentials_provider.return_value.\
+ creds_client.roles_client.list_roles.return_value = \
+ available_roles
+ self.addCleanup(mock.patch.stopall)
+
+ CONF.set_override('rbac_test_role', 'Member', group='rbac',
+ enforce_type=True)
+ self.addCleanup(CONF.clear_override, 'rbac_test_role', group='rbac')
+
+ # Because rbac_utils is a singleton, reset all of its role-related
+ # parameters to the correct values for each test run.
self.rbac_utils = rbac_utils.rbac_utils()
+ self.rbac_utils.available_roles = available_roles
+ self.rbac_utils.admin_role_id = 'admin_id'
+ self.rbac_utils.rbac_role_id = 'member_id'
- def test_rbac_utils_switch_roles_none(self):
- self.assertRaises(rbac_exceptions.RbacActionFailed,
- self.rbac_utils.switch_role, None)
+ def test_initialization_with_missing_admin_role(self):
+ self.rbac_utils.admin_role_id = None
+ e = self.assertRaises(rbac_exceptions.RbacResourceSetupFailed,
+ self.rbac_utils.switch_role, None)
+ self.assertIn("Defined 'rbac_role' or 'admin' role does not exist"
+ " in the system.", e.__str__())
- def test_rbac_utils_switch_roles_false(self):
- self.auth_provider = mock.Mock()
- self.auth_provider.credentials.user_id = "user_id"
- self.auth_provider.credentials.tenant_id = "tenant_id"
- self.admin_client = mock.Mock()
- self.admin_client.token = "admin_token"
- self.assertIsNone(self.rbac_utils.switch_role(self, False))
+ def test_initialization_with_missing_rbac_role(self):
+ self.rbac_utils.rbac_role_id = None
+ e = self.assertRaises(rbac_exceptions.RbacResourceSetupFailed,
+ self.rbac_utils.switch_role, None)
+ self.assertIn("Defined 'rbac_role' or 'admin' role does not exist"
+ " in the system.", e.__str__())
- def test_rbac_utils_switch_roles_get_roles_fails(self):
- self.auth_provider = mock.Mock()
- self.auth_provider.credentials.user_id = "user_id"
- self.auth_provider.credentials.tenant_id = "tenant_id"
- self.admin_client = mock.Mock()
- self.admin_client.token = "admin_token"
- self.rbac_utils.creds_client.roles_client.create_user_role_on_project.\
- side_effect = lib_exc.NotFound
- self.assertRaises(lib_exc.NotFound, self.rbac_utils.switch_role, self,
- False)
+ def test_clear_user_roles(self):
+ self.rbac_utils.creds_client = mock.Mock()
+ creds_client = self.rbac_utils.creds_client
+ creds_client.roles_client.list_user_roles_on_project.return_value = {
+ 'roles': [{'id': 'admin_id'}, {'id': 'member_id'}]
+ }
+
+ self.rbac_utils._clear_user_roles(mock.sentinel.user_id,
+ mock.sentinel.project_id)
+
+ creds_client.roles_client.list_user_roles_on_project.\
+ assert_called_once_with(mock.sentinel.project_id,
+ mock.sentinel.user_id)
+ creds_client.roles_client.delete_role_from_user_on_project.\
+ assert_has_calls([
+ mock.call(mock.sentinel.project_id, mock.sentinel.user_id,
+ 'admin_id'),
+ mock.call(mock.sentinel.project_id, mock.sentinel.user_id,
+ 'member_id'),
+ ])
+
+ @mock.patch.object(rbac_utils.rbac_utils, '_clear_user_roles',
+ autospec=True)
+ def test_rbac_utils_switch_role_to_admin(self, mock_clear_user_roles):
+ mock_test_object = mock.Mock()
+ mock_test_object.auth_provider.credentials.user_id = \
+ mock.sentinel.user_id
+ mock_test_object.auth_provider.credentials.tenant_id = \
+ mock.sentinel.project_id
+
+ self.rbac_utils.creds_client = mock.Mock()
+ creds_client = self.rbac_utils.creds_client
+
+ self.rbac_utils.switch_role(mock_test_object, False)
+
+ creds_client.roles_client.create_user_role_on_project.\
+ assert_called_once_with(mock.sentinel.project_id,
+ mock.sentinel.user_id,
+ 'admin_id')
+ mock_clear_user_roles.assert_called_once_with(
+ self.rbac_utils, mock.sentinel.user_id, mock.sentinel.project_id)
+ mock_test_object.auth_provider.clear_auth.assert_called_once_with()
+ mock_test_object.auth_provider.set_auth.assert_called_once_with()
+
+ @mock.patch.object(rbac_utils.rbac_utils, '_clear_user_roles',
+ autospec=True)
+ def test_rbac_utils_switch_role_to_rbac_role(self, mock_clear_user_roles):
+ mock_test_object = mock.Mock()
+ mock_test_object.auth_provider.credentials.user_id = \
+ mock.sentinel.user_id
+ mock_test_object.auth_provider.credentials.tenant_id = \
+ mock.sentinel.project_id
+
+ self.rbac_utils.creds_client = mock.Mock()
+ creds_client = self.rbac_utils.creds_client
+
+ self.rbac_utils.switch_role(mock_test_object, True)
+
+ creds_client.roles_client.create_user_role_on_project.\
+ assert_called_once_with(mock.sentinel.project_id,
+ mock.sentinel.user_id,
+ 'member_id')
+ mock_clear_user_roles.assert_called_once_with(
+ self.rbac_utils, mock.sentinel.user_id, mock.sentinel.project_id)
+ mock_test_object.auth_provider.clear_auth.assert_called_once_with()
+ mock_test_object.auth_provider.set_auth.assert_called_once_with()
+
+ def test_rbac_utils_switch_roles_with_invalid_value(self):
+ e = self.assertRaises(rbac_exceptions.RbacResourceSetupFailed,
+ self.rbac_utils.switch_role, None)
+ self.assertIn("Wrong value for parameter 'switchToRbacRole' is passed."
+ " It should be either 'True' or 'False'.", e.__str__())
+
+ @mock.patch.object(rbac_utils.rbac_utils, '_clear_user_roles',
+ autospec=True)
+ def test_rbac_utils_switch_role_except_exception(self,
+ mock_clear_user_roles):
+ self.rbac_utils.creds_client = mock.Mock()
+ creds_client = self.rbac_utils.creds_client
+ creds_client.roles_client.create_user_role_on_project.side_effect =\
+ lib_exc.NotFound
+
+ self.assertRaises(lib_exc.NotFound, self.rbac_utils.switch_role,
+ mock.Mock(), True)
diff --git a/test-requirements.txt b/test-requirements.txt
index dddb31f..7c97fa7 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -2,12 +2,14 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
hacking>=0.12.0,!=0.13.0,<0.14 # Apache-2.0
-# needed for doc build
+
sphinx>=1.2.1,!=1.3b1,<1.4 # BSD
oslosphinx>=4.7.0 # Apache-2.0
reno>=1.8.0 # Apache-2.0
mock>=2.0 # BSD
coverage>=4.0 # Apache-2.0
+nose # LGPL
+nosexcover # BSD
oslotest>=1.10.0 # Apache-2.0
oslo.policy>=1.17.0 # Apache-2.0
oslo.log>=3.11.0 # Apache-2.0
diff --git a/tox.ini b/tox.ini
index ba00222..b4953e7 100644
--- a/tox.ini
+++ b/tox.ini
@@ -28,7 +28,15 @@
commands = {posargs}
[testenv:cover]
-commands = python setup.py test --coverage --testr-args='{posargs}'
+setenv = VIRTUAL_ENV={envdir}
+ NOSE_WITH_COVERAGE=1
+ NOSE_COVER_BRANCHES=1
+ NOSE_COVER_PACKAGE=patrole_tempest_plugin
+ NOSE_COVER_HTML=1
+ NOSE_COVER_HTML_DIR={toxinidir}/cover
+ NOSE_WHERE=patrole_tempest_plugin/tests/unit
+whitelist_externals = nosetests
+commands = nosetests {posargs}
[testenv:docs]
commands = python setup.py build_sphinx