Skip to content

Commit 6771783

Browse files
committed
Fixed integration with Openshift API
It was discovered that Openshift integration did not function because the Openshift allocation would use the same url to make calls to both the account manager and the Openshift API. This resulted in the Openshift API never actually being called. Due to poor error handling by the integration code (more details below), this big went undetected by the functional tests. Appropriate fixes have been added tests, and the Openshift resource type now requires two URLs, one for the account manager, and one for the Openshift API. Regarding the poor error handling, none of the functional Openshift test cases actually checked if the call to `get_federated_user()` returned the expected output. The `get_federated_user()` function itself only emits a log message if the user is not found. This meant that even though `get_federated_user()` never called the Openshift API and would therefore never find the user, the test cases still passed. Additionally, while `_openshift_user_exists()`, the function which was supposed to call the Openshift API, does catch the `kexc.NotFoundError`, this error is not specific enough, as it could be caused by a 404 response made by ANY server (in the case of our tests, the account manager).
1 parent 2ad835f commit 6771783

File tree

6 files changed

+39
-12
lines changed

6 files changed

+39
-12
lines changed

ci/run_functional_tests_openshift.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ fi
1717
export DJANGO_SETTINGS_MODULE="local_settings"
1818
export FUNCTIONAL_TESTS="True"
1919
export OS_AUTH_URL="https://onboarding-onboarding.cluster.local"
20+
export OS_API_URL="https://onboarding-onboarding.cluster.local:6443"
21+
2022

2123
coverage run --source="." -m django test coldfront_plugin_cloud.tests.functional.openshift
2224
coverage report

src/coldfront_plugin_cloud/attributes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class CloudAllocationAttribute:
1818
is_changeable: bool = True
1919

2020

21+
RESOURCE_API_URL = 'OpenShift API Endpoint URL'
2122
RESOURCE_AUTH_URL = 'Identity Endpoint URL'
2223
RESOURCE_IDENTITY_NAME = 'OpenShift Identity Provider Name'
2324
RESOURCE_ROLE = 'Role for User in Project'
@@ -32,6 +33,7 @@ class CloudAllocationAttribute:
3233
RESOURCE_EULA_URL = "EULA URL"
3334

3435
RESOURCE_ATTRIBUTES = [
36+
CloudResourceAttribute(name=RESOURCE_API_URL),
3537
CloudResourceAttribute(name=RESOURCE_AUTH_URL),
3638
CloudResourceAttribute(name=RESOURCE_IDENTITY_NAME),
3739
CloudResourceAttribute(name=RESOURCE_FEDERATION_PROTOCOL),

src/coldfront_plugin_cloud/management/commands/add_openshift_resource.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ def add_arguments(self, parser):
1717
help='Name of OpenShift resource')
1818
parser.add_argument('--auth-url', type=str, required=True,
1919
help='URL of the openshift-acct-mgt endpoint')
20+
parser.add_argument('--api-url', type=str, required=True,
21+
help='API URL of the openshift cluster')
2022
parser.add_argument('--role', type=str, default='edit',
2123
help='Role for user when added to project (default: edit)')
2224

@@ -37,6 +39,12 @@ def handle(self, *args, **options):
3739
resource=openshift,
3840
value=options['auth_url']
3941
)
42+
ResourceAttribute.objects.get_or_create(
43+
resource_attribute_type=ResourceAttributeType.objects.get(
44+
name=attributes.RESOURCE_API_URL),
45+
resource=openshift,
46+
value=options['api_url']
47+
)
4048
ResourceAttribute.objects.get_or_create(
4149
resource_attribute_type=ResourceAttributeType.objects.get(
4250
name=attributes.RESOURCE_ROLE),

src/coldfront_plugin_cloud/openshift.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def __init__(self, resource, allocation):
7777
def k8_client(self):
7878
# Load Endpoint URL and Auth token for new k8 client
7979
openshift_token = os.getenv(f"OPENSHIFT_{self.safe_resource_name}_TOKEN")
80-
openshift_url = self.resource.get_attribute(attributes.RESOURCE_AUTH_URL)
80+
openshift_url = self.resource.get_attribute(attributes.RESOURCE_API_URL)
8181

8282
k8_config = kubernetes.client.Configuration()
8383
k8_config.api_key["authorization"] = openshift_token
@@ -181,7 +181,7 @@ def reactivate_project(self, project_id):
181181
def get_federated_user(self, username):
182182
if (
183183
self._openshift_user_exists(username)
184-
and self._openshift_get_identity(username)
184+
and self._openshift_identity_exists(username)
185185
and self._openshift_useridentitymapping_exists(username, username)
186186
):
187187
return {'username': username}
@@ -264,22 +264,33 @@ def _openshift_get_identity(self, id_user):
264264
def _openshift_user_exists(self, user_name):
265265
try:
266266
self._openshift_get_user(user_name)
267-
except kexc.NotFoundError:
268-
return False
267+
except kexc.NotFoundError as e:
268+
# Ensures error raise because resource not found,
269+
# not because of other reasons, like incorrect url
270+
e_info = json.loads(e.body)
271+
if e_info.get("reason") == "NotFound":
272+
return False
273+
raise e
269274
return True
270275

271276
def _openshift_identity_exists(self, id_user):
272277
try:
273278
self._openshift_get_identity(id_user)
274-
except kexc.NotFoundError:
275-
return False
279+
except kexc.NotFoundError as e:
280+
e_info = json.loads(e.body)
281+
if e_info.get("reason") == "NotFound":
282+
return False
283+
raise e
276284
return True
277285

278286
def _openshift_useridentitymapping_exists(self, user_name, id_user):
279287
try:
280288
user = self._openshift_get_user(user_name)
281-
except kexc.NotFoundError:
282-
return False
289+
except kexc.NotFoundError as e:
290+
e_info = json.loads(e.body)
291+
if e_info.get("reason") == "NotFound":
292+
return False
293+
raise e
283294

284295
return any(
285296
identity == self.qualified_id_user(id_user)

src/coldfront_plugin_cloud/tests/base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,14 @@ def new_openstack_resource(name=None, auth_url=None) -> Resource:
8181
return Resource.objects.get(name=resource_name)
8282

8383
@staticmethod
84-
def new_openshift_resource(name=None, auth_url=None) -> Resource:
84+
def new_openshift_resource(name=None, auth_url=None, api_url=None) -> Resource:
8585
resource_name = name or uuid.uuid4().hex
8686

8787
call_command(
8888
'add_openshift_resource',
8989
name=resource_name,
9090
auth_url=auth_url or 'https://onboarding-onboarding.cluster.local',
91+
api_url=api_url or 'https://onboarding-onboarding.cluster.local:6443',
9192
)
9293
return Resource.objects.get(name=resource_name)
9394

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ def setUp(self) -> None:
1515
super().setUp()
1616
self.resource = self.new_openshift_resource(
1717
name='Microshift',
18-
auth_url=os.getenv('OS_AUTH_URL')
18+
auth_url=os.getenv('OS_AUTH_URL'),
19+
api_url=os.getenv('OS_API_URL'),
1920
)
2021

2122
def test_new_allocation(self):
@@ -36,7 +37,8 @@ def test_new_allocation(self):
3637
allocator._get_project(project_id)
3738

3839
# Check user and roles
39-
allocator.get_federated_user(user.username)
40+
user_info = allocator.get_federated_user(user.username)
41+
self.assertEqual(user_info, {'username': user.username})
4042

4143
allocator._get_role(user.username, project_id)
4244

@@ -73,7 +75,8 @@ def test_add_remove_user(self):
7375
tasks.add_user_to_allocation(allocation_user2.pk)
7476
allocator._get_role(user.username, project_id)
7577

76-
allocator.get_federated_user(user2.username)
78+
user_info = allocator.get_federated_user(user.username)
79+
self.assertEqual(user_info, {'username': user.username})
7780

7881
allocator._get_role(user.username, project_id)
7982
allocator._get_role(user2.username, project_id)

0 commit comments

Comments
 (0)