Skip to content

Commit df704e8

Browse files
committed
Allow direct communication to Openshift Users API
1 parent fcd7dd1 commit df704e8

File tree

3 files changed

+128
-9
lines changed

3 files changed

+128
-9
lines changed

src/coldfront_plugin_cloud/openshift.py

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,25 @@ def get_federated_user(self, username):
232232
logger.info(f"User ({username}) does not exist")
233233

234234
def create_federated_user(self, unique_id):
235-
url = f"{self.auth_url}/users/{unique_id}"
236-
try:
237-
r = self.session.put(url)
238-
self.check_response(r)
239-
except Conflict:
240-
pass
235+
user_def = {
236+
"metadata": {"name": unique_id},
237+
"fullName": unique_id,
238+
}
239+
240+
identity_def = {
241+
"providerName": self.id_provider,
242+
"providerUserName": unique_id,
243+
}
244+
245+
identity_mapping_def = {
246+
"user": {"name": unique_id},
247+
"identity": {"name": self.qualified_id_user(unique_id)},
248+
}
249+
250+
self._openshift_create_user(user_def)
251+
self._openshift_create_identity(identity_def)
252+
self._openshift_create_useridentitymapping(identity_mapping_def)
253+
logger.info(f"User {unique_id} successfully created")
241254

242255
def assign_role_on_user(self, username, project_id):
243256
# /users/<user_name>/projects/<project>/roles/<role>
@@ -291,9 +304,9 @@ def _get_project(self, project_id):
291304
return self.check_response(r)
292305

293306
def _delete_user(self, username):
294-
url = f"{self.auth_url}/users/{username}"
295-
r = self.session.delete(url)
296-
return self.check_response(r)
307+
self._openshift_delete_user(username)
308+
self._openshift_delete_identity(username)
309+
logger.info(f"User {username} successfully deleted")
297310

298311
def get_users(self, project_id):
299312
url = f"{self.auth_url}/projects/{project_id}/users"
@@ -304,12 +317,43 @@ def _openshift_get_user(self, username):
304317
api = self.get_resource_api(API_USER, "User")
305318
return clean_openshift_metadata(api.get(name=username).to_dict())
306319

320+
def _openshift_create_user(self, user_def):
321+
api = self.get_resource_api(API_USER, "User")
322+
try:
323+
return clean_openshift_metadata(api.create(body=user_def).to_dict())
324+
except kexc.ConflictError:
325+
pass
326+
327+
def _openshift_delete_user(self, username):
328+
api = self.get_resource_api(API_USER, "User")
329+
return clean_openshift_metadata(api.delete(name=username).to_dict())
330+
307331
def _openshift_get_identity(self, id_user):
308332
api = self.get_resource_api(API_USER, "Identity")
309333
return clean_openshift_metadata(
310334
api.get(name=self.qualified_id_user(id_user)).to_dict()
311335
)
312336

337+
def _openshift_create_identity(self, identity_def):
338+
api = self.get_resource_api(API_USER, "Identity")
339+
try:
340+
return clean_openshift_metadata(api.create(body=identity_def).to_dict())
341+
except kexc.ConflictError:
342+
pass
343+
344+
def _openshift_delete_identity(self, username):
345+
api = self.get_resource_api(API_USER, "Identity")
346+
return api.delete(name=self.qualified_id_user(username)).to_dict()
347+
348+
def _openshift_create_useridentitymapping(self, identity_mapping_def):
349+
api = self.get_resource_api(API_USER, "UserIdentityMapping")
350+
try:
351+
return clean_openshift_metadata(
352+
api.create(body=identity_mapping_def).to_dict()
353+
)
354+
except kexc.ConflictError:
355+
pass
356+
313357
def _openshift_user_exists(self, user_name):
314358
try:
315359
self._openshift_get_user(user_name)

src/coldfront_plugin_cloud/tests/functional/openshift/test_allocation.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,3 +286,33 @@ def test_project_default_labels(self):
286286
self.assertTrue(
287287
namespace_dict_labels.items() > openshift.PROJECT_DEFAULT_LABELS.items()
288288
)
289+
290+
def test_create_incomplete(self):
291+
"""Creating a user that only has user, but no identity or mapping should not raise an error."""
292+
user = self.new_user()
293+
project = self.new_project(pi=user)
294+
allocation = self.new_allocation(project, self.resource, 1)
295+
allocator = openshift.OpenShiftResourceAllocator(self.resource, allocation)
296+
user_def = {
297+
"metadata": {"name": user.username},
298+
"fullName": user.username,
299+
}
300+
301+
allocator._openshift_create_user(user_def)
302+
self.assertTrue(allocator._openshift_user_exists(user.username))
303+
self.assertFalse(allocator._openshift_identity_exists(user.username))
304+
self.assertFalse(
305+
allocator._openshift_useridentitymapping_exists(
306+
user.username, user.username
307+
)
308+
)
309+
310+
# Now create identity and mapping, no errors should be raised
311+
allocator.get_or_create_federated_user(user.username)
312+
self.assertTrue(allocator._openshift_user_exists(user.username))
313+
self.assertTrue(allocator._openshift_identity_exists(user.username))
314+
self.assertTrue(
315+
allocator._openshift_useridentitymapping_exists(
316+
user.username, user.username
317+
)
318+
)

src/coldfront_plugin_cloud/tests/unit/openshift/test_user.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,48 @@ def test_get_federated_user_not_exist(self):
3737

3838
output = self.allocator.get_federated_user("fake_user_2")
3939
self.assertEqual(output, None)
40+
41+
def test_create_federated_user(self):
42+
fake_client_output = mock.Mock(spec=["to_dict"])
43+
fake_client_output.to_dict.return_value = {}
44+
self.allocator.k8_client.resources.get.return_value.create.return_value = (
45+
fake_client_output
46+
)
47+
48+
self.allocator.create_federated_user("fake_user_name")
49+
50+
# Assert called to create user
51+
self.allocator.k8_client.resources.get.return_value.create.assert_any_call(
52+
body={"metadata": {"name": "fake_user_name"}, "fullName": "fake_user_name"}
53+
)
54+
55+
# Assert called to add identity
56+
self.allocator.k8_client.resources.get.return_value.create.assert_any_call(
57+
body={
58+
"providerName": "fake_idp",
59+
"providerUserName": "fake_user_name",
60+
}
61+
)
62+
63+
# Assert called to add identity mapping
64+
self.allocator.k8_client.resources.get.return_value.create.assert_any_call(
65+
body={
66+
"user": {"name": "fake_user_name"},
67+
"identity": {"name": "fake_idp:fake_user_name"},
68+
}
69+
)
70+
71+
def test_delete_user(self):
72+
fake_client_output = mock.Mock(spec=["to_dict"])
73+
fake_client_output.to_dict.return_value = {}
74+
self.allocator.k8_client.resources.get.return_value.delete.return_value = (
75+
fake_client_output
76+
)
77+
78+
self.allocator._delete_user("fake_user_name")
79+
self.allocator.k8_client.resources.get.return_value.delete.assert_any_call(
80+
name="fake_user_name"
81+
)
82+
self.allocator.k8_client.resources.get.return_value.delete.assert_any_call(
83+
name="fake_idp:fake_user_name"
84+
)

0 commit comments

Comments
 (0)