Skip to content

Commit ec02437

Browse files
Add unit test for the enable_local_interactive
1 parent cd8bce0 commit ec02437

File tree

1 file changed

+171
-1
lines changed

1 file changed

+171
-1
lines changed

tests/unit_test.py

+171-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,12 @@
8383
)
8484

8585
import codeflare_sdk.utils.kube_api_helpers
86-
from codeflare_sdk.utils.generate_yaml import gen_names, is_openshift_cluster
86+
from codeflare_sdk.utils.generate_yaml import (
87+
gen_names,
88+
is_openshift_cluster,
89+
read_template,
90+
enable_local_interactive,
91+
)
8792

8893
import openshift
8994
from openshift.selector import Selector
@@ -2563,6 +2568,171 @@ def test_export_env():
25632568
)
25642569

25652570

2571+
def test_enable_local_interactive(mocker):
2572+
template = f"{parent}/src/codeflare_sdk/templates/base-template.yaml"
2573+
user_yaml = read_template(template)
2574+
aw_spec = user_yaml.get("spec", None)
2575+
cluster_name = "test-enable-local"
2576+
namespace = "default"
2577+
ingress_domain = "mytest.domain"
2578+
mocker.patch(
2579+
"codeflare_sdk.utils.generate_yaml.is_openshift_cluster", return_value=False
2580+
)
2581+
volume_mounts = [
2582+
{"name": "ca-vol", "mountPath": "/home/ray/workspace/ca", "readOnly": True},
2583+
{
2584+
"name": "server-cert",
2585+
"mountPath": "/home/ray/workspace/tls",
2586+
"readOnly": False,
2587+
},
2588+
]
2589+
volumes = [
2590+
{
2591+
"name": "ca-vol",
2592+
"secret": {"secretName": f"ca-secret-{cluster_name}"},
2593+
"optional": False,
2594+
},
2595+
{"name": "server-cert", "emptyDir": {}},
2596+
]
2597+
tls_env = [
2598+
{"name": "RAY_USE_TLS", "value": "1"},
2599+
{"name": "RAY_TLS_SERVER_CERT", "value": "/home/ray/workspace/tls/server.crt"},
2600+
{"name": "RAY_TLS_SERVER_KEY", "value": "/home/ray/workspace/tls/server.key"},
2601+
{"name": "RAY_TLS_CA_CERT", "value": "/home/ray/workspace/tls/ca.crt"},
2602+
]
2603+
assert aw_spec != None
2604+
enable_local_interactive(aw_spec, cluster_name, namespace, ingress_domain)
2605+
head_group_spec = aw_spec["resources"]["GenericItems"][0]["generictemplate"][
2606+
"spec"
2607+
]["headGroupSpec"]
2608+
worker_group_spec = aw_spec["resources"]["GenericItems"][0]["generictemplate"][
2609+
"spec"
2610+
]["workerGroupSpecs"]
2611+
ca_secret = aw_spec["resources"]["GenericItems"][3]["generictemplate"]
2612+
# At a minimal, make sure the following items are presented in the appwrapper spec.resources.
2613+
# 1. headgroup has the initContainers command to generated TLS cert from the mounted CA cert.
2614+
# Note: In this particular command, the DNS.5 in [alt_name] must match the exposed local_client_url: rayclient-{cluster_name}.{namespace}.{ingress_domain}
2615+
assert (
2616+
head_group_spec["template"]["spec"]["initContainers"][0]["command"][2]
2617+
== f"cd /home/ray/workspace/tls && openssl req -nodes -newkey rsa:2048 -keyout server.key -out server.csr -subj '/CN=ray-head' && printf \"authorityKeyIdentifier=keyid,issuer\\nbasicConstraints=CA:FALSE\\nsubjectAltName = @alt_names\\n[alt_names]\\nDNS.1 = 127.0.0.1\\nDNS.2 = localhost\\nDNS.3 = ${{FQ_RAY_IP}}\\nDNS.4 = $(awk 'END{{print $1}}' /etc/hosts)\\nDNS.5 = rayclient-{cluster_name}-$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).{ingress_domain}\">./domain.ext && cp /home/ray/workspace/ca/* . && openssl x509 -req -CA ca.crt -CAkey ca.key -in server.csr -out server.crt -days 365 -CAcreateserial -extfile domain.ext"
2618+
)
2619+
assert (
2620+
head_group_spec["template"]["spec"]["initContainers"][0]["volumeMounts"]
2621+
== volume_mounts
2622+
)
2623+
assert head_group_spec["template"]["spec"]["volumes"] == volumes
2624+
2625+
# 2. workerGrooupSpec has the initContainers command to generated TLS cert from the mounted CA cert.
2626+
assert (
2627+
worker_group_spec[0]["template"]["spec"]["initContainers"][1]["command"][2]
2628+
== "cd /home/ray/workspace/tls && openssl req -nodes -newkey rsa:2048 -keyout server.key -out server.csr -subj '/CN=ray-head' && printf \"authorityKeyIdentifier=keyid,issuer\\nbasicConstraints=CA:FALSE\\nsubjectAltName = @alt_names\\n[alt_names]\\nDNS.1 = 127.0.0.1\\nDNS.2 = localhost\\nDNS.3 = ${FQ_RAY_IP}\\nDNS.4 = $(awk 'END{print $1}' /etc/hosts)\">./domain.ext && cp /home/ray/workspace/ca/* . && openssl x509 -req -CA ca.crt -CAkey ca.key -in server.csr -out server.crt -days 365 -CAcreateserial -extfile domain.ext"
2629+
)
2630+
assert (
2631+
worker_group_spec[0]["template"]["spec"]["initContainers"][1]["volumeMounts"]
2632+
== volume_mounts
2633+
)
2634+
assert worker_group_spec[0]["template"]["spec"]["volumes"] == volumes
2635+
2636+
# 3. Required Envs to enable TLS encryption between head and workers
2637+
for i in range(len(tls_env)):
2638+
assert (
2639+
head_group_spec["template"]["spec"]["containers"][0]["env"][i + 1]["name"]
2640+
== tls_env[i]["name"]
2641+
)
2642+
assert (
2643+
head_group_spec["template"]["spec"]["containers"][0]["env"][i + 1]["value"]
2644+
== tls_env[i]["value"]
2645+
)
2646+
assert (
2647+
worker_group_spec[0]["template"]["spec"]["containers"][0]["env"][i + 1][
2648+
"name"
2649+
]
2650+
== tls_env[i]["name"]
2651+
)
2652+
assert (
2653+
worker_group_spec[0]["template"]["spec"]["containers"][0]["env"][i + 1][
2654+
"value"
2655+
]
2656+
== tls_env[i]["value"]
2657+
)
2658+
2659+
# 4. Secret with ca.crt and ca.key
2660+
assert ca_secret["kind"] == "Secret"
2661+
assert ca_secret["data"]["ca.crt"] != None
2662+
assert ca_secret["data"]["ca.key"] != None
2663+
assert ca_secret["metadata"]["name"] == f"ca-secret-{cluster_name}"
2664+
assert ca_secret["metadata"]["namespace"] == namespace
2665+
2666+
# 5. Rayclient ingress - Kind
2667+
rayclient_ingress = aw_spec["resources"]["GenericItems"][2]["generictemplate"]
2668+
paths = [
2669+
{
2670+
"backend": {
2671+
"service": {
2672+
"name": f"{cluster_name}-head-svc",
2673+
"port": {"number": 10001},
2674+
}
2675+
},
2676+
"path": "",
2677+
"pathType": "ImplementationSpecific",
2678+
}
2679+
]
2680+
2681+
assert rayclient_ingress["kind"] == "Ingress"
2682+
assert rayclient_ingress["metadata"]["namespace"] == namespace
2683+
assert rayclient_ingress["metadata"]["annotations"] == {
2684+
"nginx.ingress.kubernetes.io/rewrite-target": "/",
2685+
"nginx.ingress.kubernetes.io/ssl-redirect": "true",
2686+
"nginx.ingress.kubernetes.io/ssl-passthrough": "true",
2687+
}
2688+
assert rayclient_ingress["metadata"]["name"] == f"rayclient-{cluster_name}"
2689+
assert rayclient_ingress["spec"]["rules"][0] == {
2690+
"host": f"rayclient-{cluster_name}-{namespace}.{ingress_domain}",
2691+
"http": {"paths": paths},
2692+
}
2693+
# 5.1 Rayclient ingress - OCP
2694+
user_yaml = read_template(template)
2695+
aw_spec = user_yaml.get("spec", None)
2696+
cluster_name = "test-ocp-enable-local"
2697+
namespace = "default"
2698+
ocp_cluster_domain = {"spec": {"domain": "mytest.ocp.domain"}}
2699+
ingress_domain = ocp_cluster_domain["spec"]["domain"]
2700+
mocker.patch(
2701+
"codeflare_sdk.utils.generate_yaml.is_openshift_cluster", return_value=True
2702+
)
2703+
mocker.patch(
2704+
"kubernetes.client.CustomObjectsApi.get_cluster_custom_object",
2705+
return_value=ocp_cluster_domain,
2706+
)
2707+
paths = [
2708+
{
2709+
"backend": {
2710+
"service": {
2711+
"name": f"{cluster_name}-head-svc",
2712+
"port": {"number": 10001},
2713+
}
2714+
},
2715+
"path": "",
2716+
"pathType": "ImplementationSpecific",
2717+
}
2718+
]
2719+
enable_local_interactive(aw_spec, cluster_name, namespace, ingress_domain)
2720+
rayclient_ocp_ingress = aw_spec["resources"]["GenericItems"][2]["generictemplate"]
2721+
assert rayclient_ocp_ingress["kind"] == "Ingress"
2722+
assert rayclient_ocp_ingress["metadata"]["annotations"] == {
2723+
"nginx.ingress.kubernetes.io/rewrite-target": "/",
2724+
"nginx.ingress.kubernetes.io/ssl-redirect": "true",
2725+
"route.openshift.io/termination": "passthrough",
2726+
}
2727+
assert rayclient_ocp_ingress["metadata"]["name"] == f"rayclient-{cluster_name}"
2728+
assert rayclient_ocp_ingress["metadata"]["namespace"] == namespace
2729+
assert rayclient_ocp_ingress["spec"]["ingressClassName"] == "openshift-default"
2730+
assert rayclient_ocp_ingress["spec"]["rules"][0] == {
2731+
"host": f"rayclient-{cluster_name}-{namespace}.{ingress_domain}",
2732+
"http": {"paths": paths},
2733+
}
2734+
2735+
25662736
def test_create_openshift_oauth(mocker: MockerFixture):
25672737
create_namespaced_service_account = MagicMock()
25682738
create_cluster_role_binding = MagicMock()

0 commit comments

Comments
 (0)