blob: e2309bf29ae28512770cafc24f4a6af9d7341519 [file] [log] [blame]
Jamie Lennox15350172015-08-17 10:54:25 +10001# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
13import abc
14
15from oslo_log import log as logging
16import six
Andrea Frittoli (andreaf)278463c2015-10-08 15:04:09 +010017from tempest_lib import auth
Jamie Lennox15350172015-08-17 10:54:25 +100018from tempest_lib import exceptions as lib_exc
19
Jamie Lennox15350172015-08-17 10:54:25 +100020from tempest.services.identity.v2.json import identity_client as v2_identity
21
Jamie Lennox15350172015-08-17 10:54:25 +100022LOG = logging.getLogger(__name__)
23
24
25@six.add_metaclass(abc.ABCMeta)
26class CredsClient(object):
Ken'ichi Ohmichicb67d2d2015-11-19 08:23:22 +000027 """This class is a wrapper around the identity clients
28
29 to provide a single interface for managing credentials in both v2 and v3
30 cases. It's not bound to created credentials, only to a specific set of
31 admin credentials used for generating credentials.
Jamie Lennox15350172015-08-17 10:54:25 +100032 """
33
Yaroslav Lobankov47a93ab2016-02-07 16:32:49 -060034 def __init__(self, identity_client, projects_client,
Daniel Mellado82c83a52015-12-09 15:16:49 +000035 roles_client=None, users_client=None):
Jamie Lennox15350172015-08-17 10:54:25 +100036 # The client implies version and credentials
37 self.identity_client = identity_client
Yaroslav Lobankov47a93ab2016-02-07 16:32:49 -060038 self.projects_client = projects_client
39 # this is temporary until v3 roles client and v3 users client are
40 # separated, then these clients will become mandatory
Daniel Mellado6b16b922015-12-07 12:43:08 +000041 self.roles_client = roles_client or identity_client
Daniel Mellado82c83a52015-12-09 15:16:49 +000042 self.users_client = users_client or identity_client
Jamie Lennox15350172015-08-17 10:54:25 +100043
44 def create_user(self, username, password, project, email):
Daniel Mellado82c83a52015-12-09 15:16:49 +000045 user = self.users_client.create_user(
Jamie Lennox15350172015-08-17 10:54:25 +100046 username, password, project['id'], email)
47 if 'user' in user:
48 user = user['user']
49 return user
50
Yaroslav Lobankov47a93ab2016-02-07 16:32:49 -060051 def delete_user(self, user_id):
52 self.users_client.delete_user(user_id)
53
Jamie Lennox15350172015-08-17 10:54:25 +100054 @abc.abstractmethod
55 def create_project(self, name, description):
56 pass
57
58 def _check_role_exists(self, role_name):
59 try:
60 roles = self._list_roles()
61 role = next(r for r in roles if r['name'] == role_name)
62 except StopIteration:
63 return None
64 return role
65
66 def create_user_role(self, role_name):
67 if not self._check_role_exists(role_name):
piyush110786afaaf262015-12-11 18:54:05 +053068 self.roles_client.create_role(name=role_name)
Jamie Lennox15350172015-08-17 10:54:25 +100069
70 def assign_user_role(self, user, project, role_name):
71 role = self._check_role_exists(role_name)
72 if not role:
73 msg = 'No "%s" role found' % role_name
74 raise lib_exc.NotFound(msg)
75 try:
Daniel Mellado6b16b922015-12-07 12:43:08 +000076 self.roles_client.assign_user_role(project['id'], user['id'],
77 role['id'])
Jamie Lennox15350172015-08-17 10:54:25 +100078 except lib_exc.Conflict:
79 LOG.debug("Role %s already assigned on project %s for user %s" % (
80 role['id'], project['id'], user['id']))
81
82 @abc.abstractmethod
83 def get_credentials(self, user, project, password):
Andrea Frittoli (andreaf)278463c2015-10-08 15:04:09 +010084 """Produces a Credentials object from the details provided
85
86 :param user: a user dict
87 :param project: a project dict
88 :param password: the password as a string
89 :return: a Credentials object with all the available credential details
90 """
Jamie Lennox15350172015-08-17 10:54:25 +100091 pass
92
Jamie Lennox15350172015-08-17 10:54:25 +100093 def _list_roles(self):
Daniel Mellado6b16b922015-12-07 12:43:08 +000094 roles = self.roles_client.list_roles()['roles']
Jamie Lennox15350172015-08-17 10:54:25 +100095 return roles
96
97
98class V2CredsClient(CredsClient):
99
Daniel Mellado82c83a52015-12-09 15:16:49 +0000100 def __init__(self, identity_client, projects_client, roles_client,
101 users_client):
Daniel Mellado6b16b922015-12-07 12:43:08 +0000102 super(V2CredsClient, self).__init__(identity_client,
103 projects_client,
Daniel Mellado82c83a52015-12-09 15:16:49 +0000104 roles_client,
105 users_client)
Daniel Melladob04da902015-11-20 17:43:12 +0100106
Jamie Lennox15350172015-08-17 10:54:25 +1000107 def create_project(self, name, description):
Daniel Melladob04da902015-11-20 17:43:12 +0100108 tenant = self.projects_client.create_tenant(
Anusha Ramineni0cfb4612015-08-24 08:49:10 +0530109 name=name, description=description)['tenant']
Jamie Lennox15350172015-08-17 10:54:25 +1000110 return tenant
111
Yaroslav Lobankov47a93ab2016-02-07 16:32:49 -0600112 def delete_project(self, project_id):
113 self.projects_client.delete_tenant(project_id)
114
Jamie Lennox15350172015-08-17 10:54:25 +1000115 def get_credentials(self, user, project, password):
Andrea Frittoli (andreaf)278463c2015-10-08 15:04:09 +0100116 # User and project already include both ID and name here,
117 # so there's no need to use the fill_in mode
118 return auth.get_credentials(
119 auth_url=None,
120 fill_in=False,
Jamie Lennox15350172015-08-17 10:54:25 +1000121 identity_version='v2',
122 username=user['name'], user_id=user['id'],
123 tenant_name=project['name'], tenant_id=project['id'],
124 password=password)
125
Jamie Lennox15350172015-08-17 10:54:25 +1000126
127class V3CredsClient(CredsClient):
128
Yaroslav Lobankov47a93ab2016-02-07 16:32:49 -0600129 def __init__(self, identity_client, projects_client, domain_name):
130 super(V3CredsClient, self).__init__(identity_client, projects_client)
Jamie Lennox15350172015-08-17 10:54:25 +1000131 try:
132 # Domain names must be unique, in any case a list is returned,
133 # selecting the first (and only) element
134 self.creds_domain = self.identity_client.list_domains(
135 params={'name': domain_name})['domains'][0]
136 except lib_exc.NotFound:
137 # TODO(andrea) we could probably create the domain on the fly
Andrea Frittoli (andreaf)278463c2015-10-08 15:04:09 +0100138 msg = "Requested domain %s could not be found" % domain_name
139 raise lib_exc.InvalidCredentials(msg)
Jamie Lennox15350172015-08-17 10:54:25 +1000140
141 def create_project(self, name, description):
Yaroslav Lobankov47a93ab2016-02-07 16:32:49 -0600142 project = self.projects_client.create_project(
Jamie Lennox15350172015-08-17 10:54:25 +1000143 name=name, description=description,
144 domain_id=self.creds_domain['id'])['project']
145 return project
146
Yaroslav Lobankov47a93ab2016-02-07 16:32:49 -0600147 def delete_project(self, project_id):
148 self.projects_client.delete_project(project_id)
149
Jamie Lennox15350172015-08-17 10:54:25 +1000150 def get_credentials(self, user, project, password):
Andrea Frittoli (andreaf)278463c2015-10-08 15:04:09 +0100151 # User, project and domain already include both ID and name here,
152 # so there's no need to use the fill_in mode.
153 return auth.get_credentials(
154 auth_url=None,
155 fill_in=False,
Jamie Lennox15350172015-08-17 10:54:25 +1000156 identity_version='v3',
157 username=user['name'], user_id=user['id'],
158 project_name=project['name'], project_id=project['id'],
159 password=password,
Andrea Frittoli (andreaf)278463c2015-10-08 15:04:09 +0100160 project_domain_id=self.creds_domain['id'],
Jamie Lennox15350172015-08-17 10:54:25 +1000161 project_domain_name=self.creds_domain['name'])
162
Jamie Lennox15350172015-08-17 10:54:25 +1000163 def _list_roles(self):
164 roles = self.identity_client.list_roles()['roles']
165 return roles
166
167
Daniel Melladob04da902015-11-20 17:43:12 +0100168def get_creds_client(identity_client,
Yaroslav Lobankov47a93ab2016-02-07 16:32:49 -0600169 projects_client,
Daniel Mellado6b16b922015-12-07 12:43:08 +0000170 roles_client=None,
Daniel Mellado82c83a52015-12-09 15:16:49 +0000171 users_client=None,
Daniel Melladob04da902015-11-20 17:43:12 +0100172 project_domain_name=None):
Jamie Lennox15350172015-08-17 10:54:25 +1000173 if isinstance(identity_client, v2_identity.IdentityClient):
Daniel Mellado82c83a52015-12-09 15:16:49 +0000174 return V2CredsClient(identity_client, projects_client, roles_client,
175 users_client)
Jamie Lennox15350172015-08-17 10:54:25 +1000176 else:
Yaroslav Lobankov47a93ab2016-02-07 16:32:49 -0600177 return V3CredsClient(identity_client,
178 projects_client, project_domain_name)