blob: 6b4294964d0a81d001eaf134ac0e72f2a7e23903 [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
22from tempest import config
23
24from patrole_tempest_plugin import rbac_utils
25
26
27CONF = config.CONF
28
29
30class ConfPatcher(fixtures.Fixture):
31 """Fixture to patch and restore global CONF. Adopted from Nova.
32
33 This also resets overrides for everything that is patched during
34 its teardown.
35 """
36
37 def __init__(self, **kwargs):
38 """Constructor
39
40 :params group: if specified all config options apply to that group.
41 :params **kwargs: the rest of the kwargs are processed as a
42 set of key/value pairs to be set as configuration override.
43 """
44 super(ConfPatcher, self).__init__()
45 self.group = kwargs.pop('group', None)
46 self.args = kwargs
47
48 def setUp(self):
49 super(ConfPatcher, self).setUp()
50 for k, v in self.args.items():
51 self.addCleanup(CONF.clear_override, k, self.group)
52 CONF.set_override(k, v, self.group)
53
54
55class RbacUtilsFixture(fixtures.Fixture):
Felipe Monteiro2693bf72017-08-12 22:56:47 +010056 """Fixture for `RbacUtils` class."""
Felipe Monteiroffa47e62017-07-05 03:37:55 +010057
58 USER_ID = mock.sentinel.user_id
59 PROJECT_ID = mock.sentinel.project_id
60
Felipe Monteiroffa47e62017-07-05 03:37:55 +010061 def setUp(self):
62 super(RbacUtilsFixture, self).setUp()
63
Felipe Monteirof6eb8622017-08-06 06:08:02 +010064 self.useFixture(ConfPatcher(rbac_test_role='member', group='patrole'))
Felipe Monteiroffa47e62017-07-05 03:37:55 +010065 self.useFixture(ConfPatcher(
66 admin_role='admin', auth_version='v3', group='identity'))
67
68 test_obj_kwargs = {
69 'os_primary.credentials.user_id': self.USER_ID,
70 'os_primary.credentials.tenant_id': self.PROJECT_ID,
71 'os_primary.credentials.project_id': self.PROJECT_ID,
72 'get_identity_version.return_value': 'v3'
73 }
74 self.mock_test_obj = mock.Mock(**test_obj_kwargs)
75 self.mock_time = mock.patch.object(rbac_utils, 'time').start()
76
77 self.roles_v3_client = (
78 self.mock_test_obj.get_client_manager.return_value.roles_v3_client)
79
Felipe Monteiro2693bf72017-08-12 22:56:47 +010080 self.set_roles(['admin', 'member'], [])
81
Felipe Monteiroffa47e62017-07-05 03:37:55 +010082 def switch_role(self, *role_toggles):
83 """Instantiate `rbac_utils.RbacUtils` and call `switch_role`.
84
85 Create an instance of `rbac_utils.RbacUtils` and call `switch_role`
86 for each boolean value in `role_toggles`. The number of calls to
Felipe Monteiro2693bf72017-08-12 22:56:47 +010087 `switch_role` is always 1 + len(`role_toggles`) because the
Felipe Monteiroffa47e62017-07-05 03:37:55 +010088 `rbac_utils.RbacUtils` constructor automatically calls `switch_role`.
89
90 :param role_toggles: the list of boolean values iterated over and
91 passed to `switch_role`.
92 """
Felipe Monteiroffa47e62017-07-05 03:37:55 +010093 self.fake_rbac_utils = rbac_utils.RbacUtils(self.mock_test_obj)
Felipe Monteiro2693bf72017-08-12 22:56:47 +010094
Felipe Monteiroffa47e62017-07-05 03:37:55 +010095 for role_toggle in role_toggles:
96 self.fake_rbac_utils.switch_role(self.mock_test_obj, role_toggle)
Felipe Monteiro2693bf72017-08-12 22:56:47 +010097 # NOTE(felipemonteiro): Simulate that a role switch has occurred
98 # by updating the user's current role to the new role. This means
99 # that all API actions involved during a role switch -- listing,
100 # deleting and adding roles -- are executed, making it easier to
101 # assert that mock calls were called as expected.
102 new_role = 'member' if role_toggle else 'admin'
103 self.set_roles(['admin', 'member'], [new_role])
Felipe Monteiroffa47e62017-07-05 03:37:55 +0100104
Felipe Monteiro2693bf72017-08-12 22:56:47 +0100105 def set_roles(self, roles, roles_on_project=None):
106 """Set the list of available roles in the system.
107
108 :param roles: List of roles returned by ``list_roles``.
109 :param roles_on_project: List of roles returned by
110 ``list_user_roles_on_project``.
111 :returns: None.
112 """
113 if not roles_on_project:
114 roles_on_project = []
115 if not isinstance(roles, list):
116 roles = [roles]
117 if not isinstance(roles_on_project, list):
118 roles_on_project = [roles_on_project]
119
120 available_roles = {
Felipe Monteiroffa47e62017-07-05 03:37:55 +0100121 'roles': [{'name': role, 'id': '%s_id' % role} for role in roles]
122 }
Felipe Monteiro2693bf72017-08-12 22:56:47 +0100123 available_project_roles = {
124 'roles': [{'name': role, 'id': '%s_id' % role}
125 for role in roles_on_project]
126 }
127
128 self.roles_v3_client.list_roles.return_value = available_roles
129 self.roles_v3_client.list_user_roles_on_project.return_value = (
130 available_project_roles)