blob: 13baafb4cbec3f727666c52cd03e9fb49bcd0724 [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
34 def __init__(self, identity_client):
35 # The client implies version and credentials
36 self.identity_client = identity_client
Jamie Lennox15350172015-08-17 10:54:25 +100037
38 def create_user(self, username, password, project, email):
39 user = self.identity_client.create_user(
40 username, password, project['id'], email)
41 if 'user' in user:
42 user = user['user']
43 return user
44
45 @abc.abstractmethod
46 def create_project(self, name, description):
47 pass
48
49 def _check_role_exists(self, role_name):
50 try:
51 roles = self._list_roles()
52 role = next(r for r in roles if r['name'] == role_name)
53 except StopIteration:
54 return None
55 return role
56
57 def create_user_role(self, role_name):
58 if not self._check_role_exists(role_name):
59 self.identity_client.create_role(role_name)
60
61 def assign_user_role(self, user, project, role_name):
62 role = self._check_role_exists(role_name)
63 if not role:
64 msg = 'No "%s" role found' % role_name
65 raise lib_exc.NotFound(msg)
66 try:
67 self.identity_client.assign_user_role(project['id'], user['id'],
68 role['id'])
69 except lib_exc.Conflict:
70 LOG.debug("Role %s already assigned on project %s for user %s" % (
71 role['id'], project['id'], user['id']))
72
73 @abc.abstractmethod
74 def get_credentials(self, user, project, password):
Andrea Frittoli (andreaf)278463c2015-10-08 15:04:09 +010075 """Produces a Credentials object from the details provided
76
77 :param user: a user dict
78 :param project: a project dict
79 :param password: the password as a string
80 :return: a Credentials object with all the available credential details
81 """
Jamie Lennox15350172015-08-17 10:54:25 +100082 pass
83
84 def delete_user(self, user_id):
85 self.identity_client.delete_user(user_id)
86
87 def _list_roles(self):
Anusha Ramineni0cfb4612015-08-24 08:49:10 +053088 roles = self.identity_client.list_roles()['roles']
Jamie Lennox15350172015-08-17 10:54:25 +100089 return roles
90
91
92class V2CredsClient(CredsClient):
93
94 def create_project(self, name, description):
95 tenant = self.identity_client.create_tenant(
Anusha Ramineni0cfb4612015-08-24 08:49:10 +053096 name=name, description=description)['tenant']
Jamie Lennox15350172015-08-17 10:54:25 +100097 return tenant
98
99 def get_credentials(self, user, project, password):
Andrea Frittoli (andreaf)278463c2015-10-08 15:04:09 +0100100 # User and project already include both ID and name here,
101 # so there's no need to use the fill_in mode
102 return auth.get_credentials(
103 auth_url=None,
104 fill_in=False,
Jamie Lennox15350172015-08-17 10:54:25 +1000105 identity_version='v2',
106 username=user['name'], user_id=user['id'],
107 tenant_name=project['name'], tenant_id=project['id'],
108 password=password)
109
110 def delete_project(self, project_id):
111 self.identity_client.delete_tenant(project_id)
112
113
114class V3CredsClient(CredsClient):
115
116 def __init__(self, identity_client, domain_name):
117 super(V3CredsClient, self).__init__(identity_client)
118 try:
119 # Domain names must be unique, in any case a list is returned,
120 # selecting the first (and only) element
121 self.creds_domain = self.identity_client.list_domains(
122 params={'name': domain_name})['domains'][0]
123 except lib_exc.NotFound:
124 # TODO(andrea) we could probably create the domain on the fly
Andrea Frittoli (andreaf)278463c2015-10-08 15:04:09 +0100125 msg = "Requested domain %s could not be found" % domain_name
126 raise lib_exc.InvalidCredentials(msg)
Jamie Lennox15350172015-08-17 10:54:25 +1000127
128 def create_project(self, name, description):
129 project = self.identity_client.create_project(
130 name=name, description=description,
131 domain_id=self.creds_domain['id'])['project']
132 return project
133
134 def get_credentials(self, user, project, password):
Andrea Frittoli (andreaf)278463c2015-10-08 15:04:09 +0100135 # User, project and domain already include both ID and name here,
136 # so there's no need to use the fill_in mode.
137 return auth.get_credentials(
138 auth_url=None,
139 fill_in=False,
Jamie Lennox15350172015-08-17 10:54:25 +1000140 identity_version='v3',
141 username=user['name'], user_id=user['id'],
142 project_name=project['name'], project_id=project['id'],
143 password=password,
Andrea Frittoli (andreaf)278463c2015-10-08 15:04:09 +0100144 project_domain_id=self.creds_domain['id'],
Jamie Lennox15350172015-08-17 10:54:25 +1000145 project_domain_name=self.creds_domain['name'])
146
147 def delete_project(self, project_id):
148 self.identity_client.delete_project(project_id)
149
150 def _list_roles(self):
151 roles = self.identity_client.list_roles()['roles']
152 return roles
153
154
155def get_creds_client(identity_client, project_domain_name=None):
156 if isinstance(identity_client, v2_identity.IdentityClient):
157 return V2CredsClient(identity_client)
158 else:
159 return V3CredsClient(identity_client, project_domain_name)