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
97 changes: 94 additions & 3 deletions src/codeflare_sdk/cluster/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, ingress_options={}):
machine_types = (
rc["metadata"]["labels"]["orderedinstance"].split("_")
if "orderedinstance" in rc["metadata"]["labels"]
Expand All @@ -502,6 +502,10 @@ def from_k8_cluster_object(rc, mcad=True):
"volumeMounts"
in rc["spec"]["workerGroupSpecs"][0]["template"]["spec"]["containers"][0]
)
if local_interactive:
ingress_domain = get_ingress_domain_from_client(
rc["metadata"]["name"], rc["metadata"]["namespace"]
)
cluster_config = ClusterConfiguration(
name=rc["metadata"]["name"],
namespace=rc["metadata"]["namespace"],
Expand Down Expand Up @@ -532,6 +536,8 @@ def from_k8_cluster_object(rc, mcad=True):
]["image"],
local_interactive=local_interactive,
mcad=mcad,
ingress_domain=ingress_domain,
ingress_options=ingress_options,
)
return Cluster(cluster_config)

Expand Down Expand Up @@ -685,7 +691,62 @@ 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)
ingress_host = None
ingress_options = {}
for ingress in ingresses.items:
# Search for ingress with AppWrapper name as the owner
if (
"ingress-owner" in ingress.metadata.labels
and ingress.metadata.labels["ingress-owner"] == cluster_name
):
ingress_host = ingress.spec.rules[0].host
if (
"ingress-options" in ingress.metadata.labels
and ingress.metadata.labels["ingress-options"] == "true"
):
ingress_name = ingress.metadata.name
port = (
ingress.spec.rules[0]
.http.paths[0]
.backend.service.port.number
)
annotations = ingress.metadata.annotations
path = ingress.spec.rules[0].http.paths[0].path
ingress_class_name = ingress.spec.ingress_class_name
path_type = ingress.spec.rules[0].http.paths[0].path_type

ingress_options = {
"ingresses": [
{
"ingressName": ingress_name,
"port": port,
"annotations": annotations,
"ingressClassName": ingress_class_name,
"pathType": path_type,
"path": path,
"host": ingress_host,
}
]
}
except Exception as e:
return _kube_api_error_handling(e)
# We gather the ingress domain from the host
if ingress_host is not None and ingress_options == {}:
ingress_domain = ingress_host.split(".", 1)[1]
else:
ingress_domain = None

return Cluster.from_k8_cluster_object(
rc,
mcad=mcad,
ingress_domain=ingress_domain,
ingress_options=ingress_options,
)
raise FileNotFoundError(
f"Cluster {cluster_name} is not found in {namespace} namespace"
)
Expand Down Expand Up @@ -734,7 +795,10 @@ def _get_ingress_domain(self): # pragma: no cover
return _kube_api_error_handling(e)

for route in routes["items"]:
if route["spec"]["port"]["targetPort"] == "client":
if (
route["spec"]["port"]["targetPort"] == "client"
or route["spec"]["port"]["targetPort"] == 10001
):
domain = route["spec"]["host"]
else:
try:
Expand Down Expand Up @@ -921,3 +985,30 @@ def _copy_to_ray(cluster: Cluster) -> RayCluster:
if ray.status == CodeFlareClusterStatus.READY:
ray.status = RayClusterStatus.READY
return ray


def get_ingress_domain_from_client(cluster_name: str, namespace: str = "default"):
if is_openshift_cluster():
try:
config_check()
api_instance = client.CustomObjectsApi(api_config_handler())
route = api_instance.get_namespaced_custom_object(
group="route.openshift.io",
version="v1",
namespace=namespace,
plural="routes",
name=f"rayclient-{cluster_name}",
)
return route["spec"]["host"].split(".", 1)[1]
except Exception as e: # pragma no cover
return _kube_api_error_handling(e)
else:
try:
config_check()
api_instance = client.NetworkingV1Api(api_config_handler())
ingress = api_instance.read_namespaced_ingress(
f"rayclient-{cluster_name}", namespace
)
return ingress.spec.rules[0].host.split(".", 1)[1]
except Exception as e: # pragma no cover
return _kube_api_error_handling(e)
3 changes: 3 additions & 0 deletions src/codeflare_sdk/templates/base-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ spec:
namespace: default
annotations:
annotations-example:annotations-example
labels:
ingress-options: "false"
ingress-owner: appwrapper-name
spec:
ingressClassName: nginx
rules:
Expand Down
30 changes: 24 additions & 6 deletions src/codeflare_sdk/utils/generate_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,28 +129,45 @@ 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
if "annotations" not in ingress_option.keys():
metadata["labels"]["ingress-owner"] = cluster_name
metadata["labels"]["ingress-options"] = "true"
if (
"annotations" not in ingress_option.keys()
or ingress_option["annotations"] is None
):
del metadata["annotations"]
else:
metadata["annotations"] = ingress_option["annotations"]
if "path" not in ingress_option.keys():
if (
"path" not in ingress_option.keys()
or ingress_option["path"] is None
):
del spec["rules"][0]["http"]["paths"][0]["path"]
else:
spec["rules"][0]["http"]["paths"][0]["path"] = ingress_option[
"path"
]
if "pathType" not in ingress_option.keys():
if (
"pathType" not in ingress_option.keys()
or ingress_option["pathType"] is None
):
spec["rules"][0]["http"]["paths"][0][
"pathType"
] = "ImplementationSpecific"
if "host" not in ingress_option.keys():
if (
"host" not in ingress_option.keys()
or ingress_option["host"] is None
):
del spec["rules"][0]["host"]
else:
spec["rules"][0]["host"] = ingress_option["host"]
if "ingressClassName" not in ingress_option.keys():
if (
"ingressClassName" not in ingress_option.keys()
or ingress_option["ingressClassName"] is None
):
del spec["ingressClassName"]
else:
spec["ingressClassName"] = ingress_option["ingressClassName"]
Expand All @@ -161,6 +178,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"
Expand Down
3 changes: 3 additions & 0 deletions tests/test-case-no-mcad.yamls
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ spec:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
labels:
ingress-options: 'false'
ingress-owner: unit-test-cluster-ray
name: ray-dashboard-unit-test-cluster-ray
namespace: ns
spec:
Expand Down
3 changes: 3 additions & 0 deletions tests/test-case-prio.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ spec:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
labels:
ingress-options: 'false'
ingress-owner: prio-test-cluster
name: ray-dashboard-prio-test-cluster
namespace: ns
spec:
Expand Down
3 changes: 3 additions & 0 deletions tests/test-case.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ spec:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
labels:
ingress-options: 'false'
ingress-owner: unit-test-cluster
name: ray-dashboard-unit-test-cluster
namespace: ns
spec:
Expand Down
Loading