diff --git a/src/codeflare_sdk/cluster/cluster.py b/src/codeflare_sdk/cluster/cluster.py index 11cf5fdb9..4f24663da 100644 --- a/src/codeflare_sdk/cluster/cluster.py +++ b/src/codeflare_sdk/cluster/cluster.py @@ -492,7 +492,7 @@ def torchx_config( to_return["requirements"] = requirements return to_return - def from_k8_cluster_object(rc, mcad=True): + def from_k8_cluster_object(rc, mcad=True, ingress_domain=None): machine_types = ( rc["metadata"]["labels"]["orderedinstance"].split("_") if "orderedinstance" in rc["metadata"]["labels"] @@ -532,6 +532,7 @@ def from_k8_cluster_object(rc, mcad=True): ]["image"], local_interactive=local_interactive, mcad=mcad, + ingress_domain=ingress_domain, ) return Cluster(cluster_config) @@ -685,7 +686,29 @@ def get_cluster(cluster_name: str, namespace: str = "default"): for rc in rcs["items"]: if rc["metadata"]["name"] == cluster_name: mcad = _check_aw_exists(cluster_name, namespace) - return Cluster.from_k8_cluster_object(rc, mcad=mcad) + + try: + config_check() + api_instance = client.NetworkingV1Api(api_config_handler()) + ingresses = api_instance.list_namespaced_ingress(namespace) + if mcad == True: + for ingress in ingresses.items: + # Search for ingress with AppWrapper name as the owner + if cluster_name == ingress.metadata.owner_references[0].name: + ingress_host = ingress.spec.rules[0].host + else: + for ingress in ingresses.items: + # Search for the ingress with the ingress-owner label + if ingress.metadata.labels["ingress-owner"] == cluster_name: + ingress_host = ingress.spec.rules[0].host + except Exception as e: + return _kube_api_error_handling(e) + + # We gather the ingress domain from the host + ingress_domain = ingress_host.split(".", 1)[1] + return Cluster.from_k8_cluster_object( + rc, mcad=mcad, ingress_domain=ingress_domain + ) raise FileNotFoundError( f"Cluster {cluster_name} is not found in {namespace} namespace" ) diff --git a/src/codeflare_sdk/templates/base-template.yaml b/src/codeflare_sdk/templates/base-template.yaml index 8e6fd0e9e..0e6ef09cc 100644 --- a/src/codeflare_sdk/templates/base-template.yaml +++ b/src/codeflare_sdk/templates/base-template.yaml @@ -293,6 +293,8 @@ spec: namespace: default annotations: annotations-example:annotations-example + labels: + ingress-owner: appwrapper-name spec: ingressClassName: nginx rules: diff --git a/src/codeflare_sdk/utils/generate_yaml.py b/src/codeflare_sdk/utils/generate_yaml.py index 95c17cc28..af1b9ecea 100755 --- a/src/codeflare_sdk/utils/generate_yaml.py +++ b/src/codeflare_sdk/utils/generate_yaml.py @@ -129,9 +129,10 @@ def update_dashboard_ingress( raise ValueError( f"Error: 'port' is not of type int for ingress item at index {index}" ) - if ingress_option["port"] == 8265: + if ingress_option is not None: metadata["name"] = ingress_option["ingressName"] metadata["namespace"] = namespace + metadata["labels"]["ingress-owner"] = cluster_name if "annotations" not in ingress_option.keys(): del metadata["annotations"] else: @@ -161,6 +162,7 @@ def update_dashboard_ingress( else: spec["ingressClassName"] = "nginx" metadata["name"] = gen_dashboard_ingress_name(cluster_name) + metadata["labels"]["ingress-owner"] = cluster_name metadata["namespace"] = namespace spec["rules"][0]["http"]["paths"][0]["backend"]["service"][ "name" diff --git a/tests/test-case-no-mcad.yamls b/tests/test-case-no-mcad.yamls index 484636bc2..77f90f896 100644 --- a/tests/test-case-no-mcad.yamls +++ b/tests/test-case-no-mcad.yamls @@ -142,6 +142,8 @@ spec: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: + labels: + ingress-owner: unit-test-cluster-ray name: ray-dashboard-unit-test-cluster-ray namespace: ns spec: diff --git a/tests/test-case-prio.yaml b/tests/test-case-prio.yaml index 70b68e971..b6d820ae5 100644 --- a/tests/test-case-prio.yaml +++ b/tests/test-case-prio.yaml @@ -175,6 +175,8 @@ spec: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: + labels: + ingress-owner: prio-test-cluster name: ray-dashboard-prio-test-cluster namespace: ns spec: diff --git a/tests/test-case.yaml b/tests/test-case.yaml index 920459c40..e96fa89ef 100644 --- a/tests/test-case.yaml +++ b/tests/test-case.yaml @@ -172,6 +172,8 @@ spec: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: + labels: + ingress-owner: unit-test-cluster name: ray-dashboard-unit-test-cluster namespace: ns spec: diff --git a/tests/unit_test.py b/tests/unit_test.py index 7ad0d08d7..b217b281b 100644 --- a/tests/unit_test.py +++ b/tests/unit_test.py @@ -397,7 +397,7 @@ def arg_check_apply_effect(group, version, namespace, plural, body, *args): with open(f"{aw_dir}unit-test-cluster-ray.yaml") as f: yamls = yaml.load_all(f, Loader=yaml.FullLoader) for resource in yamls: - if resource["kind"] == "Route": + if resource["kind"] == "Ingress": assert body == resource else: assert 1 == 0 @@ -414,8 +414,8 @@ def arg_check_del_effect(group, version, namespace, plural, name, *args): assert group == "ray.io" assert version == "v1alpha1" assert name == "unit-test-cluster-ray" - elif plural == "routes": - assert group == "route.openshift.io" + elif plural == "ingresses": + assert group == "networking.k8s.io" assert version == "v1" assert name == "ray-dashboard-unit-test-cluster-ray" @@ -623,7 +623,13 @@ def ingress_retrieval(port, annotations=None): serviceName = "dashboard" mock_ingress = client.V1Ingress( metadata=client.V1ObjectMeta( - name=f"ray-{serviceName}-unit-test-cluster", annotations=annotations + name=f"ray-{serviceName}-unit-test-cluster", + annotations=annotations, + owner_references=[ + client.V1OwnerReference( + api_version="v1", kind="Ingress", name="quicktest", uid="unique-id" + ) + ], ), spec=client.V1IngressSpec( rules=[ @@ -1148,6 +1154,11 @@ def get_ray_obj(group, version, namespace, plural, cls=None): return api_obj +def get_named_aw(group, version, namespace, plural, name): + aws = get_aw_obj("workload.codeflare.dev", "v1beta1", "ns", "appwrappers") + return aws["items"][0] + + def get_aw_obj(group, version, namespace, plural): api_obj1 = { "items": [ @@ -1403,21 +1414,34 @@ def get_aw_obj(group, version, namespace, plural): { "allocated": 0, "generictemplate": { - "apiVersion": "route.openshift.io/v1", - "kind": "Route", + "apiVersion": "networking.k8s.io/v1", + "kind": "Ingress", "metadata": { - "labels": { - "odh-ray-cluster-service": "quicktest-head-svc" - }, + "labels": {"ingress-owner": "appwrapper-name"}, "name": "ray-dashboard-quicktest", "namespace": "default", }, "spec": { - "port": {"targetPort": "dashboard"}, - "to": { - "kind": "Service", - "name": "quicktest-head-svc", - }, + "ingressClassName": "nginx", + "rules": [ + { + "http": { + "paths": { + "backend": { + "service": { + "name": "quicktest-head-svc", + "port": { + "number": 8265 + }, + }, + }, + "pathType": "Prefix", + "path": "/", + }, + }, + "host": "quicktest.awsroute.com", + } + ], }, }, "metadata": {}, @@ -1788,10 +1812,14 @@ def test_get_cluster(mocker): side_effect=get_ray_obj, ) mocker.patch( - "codeflare_sdk.utils.generate_yaml.is_openshift_cluster", - return_value=True, + "kubernetes.client.CustomObjectsApi.get_namespaced_custom_object", + side_effect=get_named_aw, + ) + mocker.patch( + "kubernetes.client.NetworkingV1Api.list_namespaced_ingress", + return_value=ingress_retrieval(port=8265), ) - cluster = get_cluster(cluster_name="quicktest") + cluster = get_cluster("quicktest") cluster_config = cluster.config assert cluster_config.name == "quicktest" and cluster_config.namespace == "ns" assert (