Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,22 @@ def sync_users(project_id, allocation, allocator, apply):

return failed_validation

@staticmethod
def sync_openshift_project_labels(project_id, allocator, apply):
cloud_namespace_obj = allocator._openshift_get_namespace(project_id)
cloud_namespace_obj_labels = cloud_namespace_obj["metadata"]["labels"]
if missing_or_incorrect_labels := [
label_items[0] for label_items in openshift.PROJECT_DEFAULT_LABELS.items() if
label_items not in cloud_namespace_obj_labels.items()
]:
logger.warning(
f"Openshift project {project_id} is missing default labels: {', '.join(missing_or_incorrect_labels)}"
)
cloud_namespace_obj_labels.update(openshift.PROJECT_DEFAULT_LABELS)
if apply:
allocator.patch_project(project_id, cloud_namespace_obj)
logger.warning(f"Labels updated for Openshift project {project_id}: {', '.join(missing_or_incorrect_labels)}")

def check_institution_specific_code(self, allocation, apply):
attr = attributes.ALLOCATION_INSTITUTION_SPECIFIC_CODE
isc = allocation.get_attribute(attr)
Expand Down Expand Up @@ -183,6 +199,7 @@ def handle(self, *args, **options):
quota = allocator.get_quota(project_id)

failed_validation = Command.sync_users(project_id, allocation, allocator, options["apply"])
Command.sync_openshift_project_labels(project_id, allocator, options["apply"])

for attr in tasks.get_expected_attributes(allocator):
key_with_lambda = allocator.QUOTA_KEY_MAPPING.get(attr, None)
Expand Down
26 changes: 21 additions & 5 deletions src/coldfront_plugin_cloud/openshift.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@
"uid",
]


PROJECT_DEFAULT_LABELS = {
'opendatahub.io/dashboard': "true",
'modelmesh-enabled': "true",
'nerc.mghpcc.org/allow-unencrypted-routes': "true"
}


def clean_openshift_metadata(obj):
if "metadata" in obj:
for attr in IGNORED_ATTRIBUTES:
Expand Down Expand Up @@ -146,6 +154,9 @@ def create_project(self, suggested_project_name):
self._create_project(project_name, project_id)
return self.Project(project_name, project_id)

def patch_project(self, project_id, new_project_spec):
self._openshift_patch_namespace(project_id, new_project_spec)

def delete_moc_quotas(self, project_id):
"""deletes all resourcequotas from an openshift project"""
resourcequotas = self._openshift_get_resourcequotas(project_id)
Expand Down Expand Up @@ -238,14 +249,10 @@ def _create_project(self, project_name, project_id):
headers = {"Content-type": "application/json"}
annotations = {"cf_project_id": str(self.allocation.project_id),
"cf_pi": self.allocation.project.pi.username}
labels = {
'opendatahub.io/dashboard': "true",
'modelmesh-enabled': "true",
}

payload = {"displayName": project_name,
"annotations": annotations,
"labels": labels}
"labels": PROJECT_DEFAULT_LABELS}
r = self.session.put(url, data=json.dumps(payload), headers=headers)
self.check_response(r)

Expand Down Expand Up @@ -323,6 +330,15 @@ def _openshift_useridentitymapping_exists(self, user_name, id_user):
def _openshift_get_project(self, project_name):
api = self.get_resource_api(API_PROJECT, "Project")
return clean_openshift_metadata(api.get(name=project_name).to_dict())

def _openshift_get_namespace(self, namespace_name):
api = self.get_resource_api(API_CORE, "Namespace")
return clean_openshift_metadata(api.get(name=namespace_name).to_dict())

def _openshift_patch_namespace(self, project_name, new_project_spec):
# During testing, apparently we can't patch Projects, but we can do so with Namespaces
api = self.get_resource_api(API_CORE, "Namespace")
res = api.patch(name=project_name, body=new_project_spec)

def _openshift_get_resourcequotas(self, project_id):
"""Returns a list of resourcequota objects in namespace with name `project_id`"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,35 @@ def test_reactivate_allocation(self):
})

allocator._get_role(user.username, project_id)

def test_project_default_labels(self):
user = self.new_user()
project = self.new_project(pi=user)
allocation = self.new_allocation(project, self.resource, 1)
allocator = openshift.OpenShiftResourceAllocator(self.resource,
allocation)

tasks.activate_allocation(allocation.pk)
allocation.refresh_from_db()

project_id = allocation.get_attribute(attributes.ALLOCATION_PROJECT_ID)

# Check project labels
namespace_dict_labels = allocator._openshift_get_namespace(project_id)["metadata"]["labels"]
self.assertTrue(namespace_dict_labels.items() > openshift.PROJECT_DEFAULT_LABELS.items())

# What if we have a new custom label, or changed value?
openshift.PROJECT_DEFAULT_LABELS["test"] = "test"
call_command('validate_allocations', apply=True)

namespace_dict_labels = allocator._openshift_get_namespace(project_id)["metadata"]["labels"]
self.assertTrue(namespace_dict_labels.items() > openshift.PROJECT_DEFAULT_LABELS.items())

# What if a deafult label is removed (or cloud label
# already has other unrelated labels)? Cloud label should still remain
del openshift.PROJECT_DEFAULT_LABELS["test"]
call_command('validate_allocations', apply=True)
namespace_dict_labels = allocator._openshift_get_namespace(project_id)["metadata"]["labels"]
self.assertFalse(openshift.PROJECT_DEFAULT_LABELS.items() > {"test": "test"}.items())
self.assertTrue(namespace_dict_labels.items() > {"test": "test"}.items())
self.assertTrue(namespace_dict_labels.items() > openshift.PROJECT_DEFAULT_LABELS.items())