blob: ce13029f640b9b9c4b71ea74cbdee754c63b5afc [file] [log] [blame]
Felipe Monteiroffa47e62017-07-05 03:37:55 +01001# Copyright 2017 AT&T Corporation.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16"""Fixtures for Patrole tests."""
17from __future__ import absolute_import
18
19import fixtures
20import mock
21
Felipe Monteiro3e14f472017-08-17 23:02:11 +010022from tempest import clients
23from tempest.common import credentials_factory as credentials
Felipe Monteiroffa47e62017-07-05 03:37:55 +010024from tempest import config
25
26from patrole_tempest_plugin import rbac_utils
27
28
29CONF = config.CONF
30
31
32class ConfPatcher(fixtures.Fixture):
33 """Fixture to patch and restore global CONF. Adopted from Nova.
34
35 This also resets overrides for everything that is patched during
36 its teardown.
37 """
38
39 def __init__(self, **kwargs):
40 """Constructor
41
42 :params group: if specified all config options apply to that group.
43 :params **kwargs: the rest of the kwargs are processed as a
44 set of key/value pairs to be set as configuration override.
45 """
46 super(ConfPatcher, self).__init__()
47 self.group = kwargs.pop('group', None)
48 self.args = kwargs
49
50 def setUp(self):
51 super(ConfPatcher, self).setUp()
52 for k, v in self.args.items():
53 self.addCleanup(CONF.clear_override, k, self.group)
54 CONF.set_override(k, v, self.group)
55
56
57class RbacUtilsFixture(fixtures.Fixture):
Felipe Monteiro2693bf72017-08-12 22:56:47 +010058 """Fixture for `RbacUtils` class."""
Felipe Monteiroffa47e62017-07-05 03:37:55 +010059
60 USER_ID = mock.sentinel.user_id
61 PROJECT_ID = mock.sentinel.project_id
62
Felipe Monteiroffa47e62017-07-05 03:37:55 +010063 def setUp(self):
64 super(RbacUtilsFixture, self).setUp()
65
Felipe Monteirof6eb8622017-08-06 06:08:02 +010066 self.useFixture(ConfPatcher(rbac_test_role='member', group='patrole'))
Felipe Monteiroffa47e62017-07-05 03:37:55 +010067 self.useFixture(ConfPatcher(
68 admin_role='admin', auth_version='v3', group='identity'))
69
70 test_obj_kwargs = {
71 'os_primary.credentials.user_id': self.USER_ID,
72 'os_primary.credentials.tenant_id': self.PROJECT_ID,
73 'os_primary.credentials.project_id': self.PROJECT_ID,
74 'get_identity_version.return_value': 'v3'
75 }
Sean Pryor7f8993f2017-08-14 12:53:17 -040076 self.mock_test_obj = mock.Mock(__name__='foo', **test_obj_kwargs)
Felipe Monteiroffa47e62017-07-05 03:37:55 +010077
Felipe Monteiro3e14f472017-08-17 23:02:11 +010078 # Mock out functionality that can't be used by unit tests.
79 self.mock_time = mock.patch.object(rbac_utils, 'time').start()
80 mock.patch.object(
81 credentials, 'get_configured_admin_credentials').start()
82 mock_admin_mgr = mock.patch.object(clients, 'Manager').start()
83 self.roles_v3_client = mock_admin_mgr.return_value.roles_v3_client
Felipe Monteiroffa47e62017-07-05 03:37:55 +010084
Felipe Monteiro2693bf72017-08-12 22:56:47 +010085 self.set_roles(['admin', 'member'], [])
86
Felipe Monteiroffa47e62017-07-05 03:37:55 +010087 def switch_role(self, *role_toggles):
88 """Instantiate `rbac_utils.RbacUtils` and call `switch_role`.
89
90 Create an instance of `rbac_utils.RbacUtils` and call `switch_role`
91 for each boolean value in `role_toggles`. The number of calls to
Felipe Monteiro2693bf72017-08-12 22:56:47 +010092 `switch_role` is always 1 + len(`role_toggles`) because the
Felipe Monteiroffa47e62017-07-05 03:37:55 +010093 `rbac_utils.RbacUtils` constructor automatically calls `switch_role`.
94
95 :param role_toggles: the list of boolean values iterated over and
96 passed to `switch_role`.
97 """
Felipe Monteiroffa47e62017-07-05 03:37:55 +010098 self.fake_rbac_utils = rbac_utils.RbacUtils(self.mock_test_obj)
Felipe Monteiro2693bf72017-08-12 22:56:47 +010099
Felipe Monteiroffa47e62017-07-05 03:37:55 +0100100 for role_toggle in role_toggles:
101 self.fake_rbac_utils.switch_role(self.mock_test_obj, role_toggle)
Felipe Monteiro2693bf72017-08-12 22:56:47 +0100102 # NOTE(felipemonteiro): Simulate that a role switch has occurred
103 # by updating the user's current role to the new role. This means
104 # that all API actions involved during a role switch -- listing,
105 # deleting and adding roles -- are executed, making it easier to
106 # assert that mock calls were called as expected.
107 new_role = 'member' if role_toggle else 'admin'
108 self.set_roles(['admin', 'member'], [new_role])
Felipe Monteiroffa47e62017-07-05 03:37:55 +0100109
Felipe Monteiro2693bf72017-08-12 22:56:47 +0100110 def set_roles(self, roles, roles_on_project=None):
111 """Set the list of available roles in the system.
112
113 :param roles: List of roles returned by ``list_roles``.
114 :param roles_on_project: List of roles returned by
115 ``list_user_roles_on_project``.
116 :returns: None.
117 """
118 if not roles_on_project:
119 roles_on_project = []
120 if not isinstance(roles, list):
121 roles = [roles]
122 if not isinstance(roles_on_project, list):
123 roles_on_project = [roles_on_project]
124
125 available_roles = {
Felipe Monteiroffa47e62017-07-05 03:37:55 +0100126 'roles': [{'name': role, 'id': '%s_id' % role} for role in roles]
127 }
Felipe Monteiro2693bf72017-08-12 22:56:47 +0100128 available_project_roles = {
129 'roles': [{'name': role, 'id': '%s_id' % role}
130 for role in roles_on_project]
131 }
132
133 self.roles_v3_client.list_roles.return_value = available_roles
134 self.roles_v3_client.list_user_roles_on_project.return_value = (
135 available_project_roles)