Module codeflare_sdk.utils.openshift_oauth
+
+
++Expand source code +
+from urllib3.util import parse_url
+from .generate_yaml import gen_dashboard_route_name
+from .kube_api_helpers import _get_api_host
+from base64 import b64decode
+
+from ..cluster.auth import config_check, api_config_handler
+
+from kubernetes import client
+
+
+def create_openshift_oauth_objects(cluster_name, namespace):
+ config_check()
+ api_client = api_config_handler() or client.ApiClient()
+ oauth_port = 8443
+ oauth_sa_name = f"{cluster_name}-oauth-proxy"
+ tls_secret_name = _gen_tls_secret_name(cluster_name)
+ service_name = f"{cluster_name}-oauth"
+ port_name = "oauth-proxy"
+ host = _get_api_host(api_client)
+
+ # replace "^api" with the expected host
+ host = f"{gen_dashboard_route_name(cluster_name)}-{namespace}.apps" + host.lstrip(
+ "api"
+ )
+
+ _create_or_replace_oauth_sa(namespace, oauth_sa_name, host)
+ _create_or_replace_oauth_service_obj(
+ cluster_name, namespace, oauth_port, tls_secret_name, service_name, port_name
+ )
+ _create_or_replace_oauth_ingress_object(
+ cluster_name, namespace, service_name, port_name, host
+ )
+ _create_or_replace_oauth_rb(cluster_name, namespace, oauth_sa_name)
+
+
+def _create_or_replace_oauth_sa(namespace, oauth_sa_name, host):
+ api_client = api_config_handler()
+ oauth_sa = client.V1ServiceAccount(
+ api_version="v1",
+ kind="ServiceAccount",
+ metadata=client.V1ObjectMeta(
+ name=oauth_sa_name,
+ namespace=namespace,
+ annotations={
+ "serviceaccounts.openshift.io/oauth-redirecturi.first": f"https://{host}"
+ },
+ ),
+ )
+ try:
+ client.CoreV1Api(api_client).create_namespaced_service_account(
+ namespace=namespace, body=oauth_sa
+ )
+ except client.ApiException as e:
+ if e.reason == "Conflict":
+ client.CoreV1Api(api_client).replace_namespaced_service_account(
+ namespace=namespace,
+ body=oauth_sa,
+ name=oauth_sa_name,
+ )
+ else:
+ raise e
+
+
+def _create_or_replace_oauth_rb(cluster_name, namespace, oauth_sa_name):
+ api_client = api_config_handler()
+ oauth_crb = client.V1ClusterRoleBinding(
+ api_version="rbac.authorization.k8s.io/v1",
+ kind="ClusterRoleBinding",
+ metadata=client.V1ObjectMeta(name=f"{cluster_name}-rb"),
+ role_ref=client.V1RoleRef(
+ api_group="rbac.authorization.k8s.io",
+ kind="ClusterRole",
+ name="system:auth-delegator",
+ ),
+ subjects=[
+ client.V1Subject(
+ kind="ServiceAccount", name=oauth_sa_name, namespace=namespace
+ )
+ ],
+ )
+ try:
+ client.RbacAuthorizationV1Api(api_client).create_cluster_role_binding(
+ body=oauth_crb
+ )
+ except client.ApiException as e:
+ if e.reason == "Conflict":
+ client.RbacAuthorizationV1Api(api_client).replace_cluster_role_binding(
+ body=oauth_crb, name=f"{cluster_name}-rb"
+ )
+ else:
+ raise e
+
+
+def _gen_tls_secret_name(cluster_name):
+ return f"{cluster_name}-proxy-tls-secret"
+
+
+def delete_openshift_oauth_objects(cluster_name, namespace):
+ # NOTE: it might be worth adding error handling here, but shouldn't be necessary because cluster.down(...) checks
+ # for an existing cluster before calling this => the objects should never be deleted twice
+ api_client = api_config_handler()
+ oauth_sa_name = f"{cluster_name}-oauth-proxy"
+ service_name = f"{cluster_name}-oauth"
+ client.CoreV1Api(api_client).delete_namespaced_service_account(
+ name=oauth_sa_name, namespace=namespace
+ )
+ client.CoreV1Api(api_client).delete_namespaced_service(
+ name=service_name, namespace=namespace
+ )
+ client.NetworkingV1Api(api_client).delete_namespaced_ingress(
+ name=f"{cluster_name}-ingress", namespace=namespace
+ )
+ client.RbacAuthorizationV1Api(api_client).delete_cluster_role_binding(
+ name=f"{cluster_name}-rb"
+ )
+
+
+def _create_or_replace_oauth_service_obj(
+ cluster_name: str,
+ namespace: str,
+ oauth_port: int,
+ tls_secret_name: str,
+ service_name: str,
+ port_name: str,
+) -> client.V1Service:
+ api_client = api_config_handler()
+ oauth_service = client.V1Service(
+ api_version="v1",
+ kind="Service",
+ metadata=client.V1ObjectMeta(
+ annotations={
+ "service.beta.openshift.io/serving-cert-secret-name": tls_secret_name
+ },
+ name=service_name,
+ namespace=namespace,
+ ),
+ spec=client.V1ServiceSpec(
+ ports=[
+ client.V1ServicePort(
+ name=port_name,
+ protocol="TCP",
+ port=443,
+ target_port=oauth_port,
+ )
+ ],
+ selector={
+ "app.kubernetes.io/created-by": "kuberay-operator",
+ "app.kubernetes.io/name": "kuberay",
+ "ray.io/cluster": cluster_name,
+ "ray.io/identifier": f"{cluster_name}-head",
+ "ray.io/node-type": "head",
+ },
+ ),
+ )
+ try:
+ client.CoreV1Api(api_client).create_namespaced_service(
+ namespace=namespace, body=oauth_service
+ )
+ except client.ApiException as e:
+ if e.reason == "Conflict":
+ client.CoreV1Api(api_client).replace_namespaced_service(
+ namespace=namespace, body=oauth_service, name=service_name
+ )
+ else:
+ raise e
+
+
+def _create_or_replace_oauth_ingress_object(
+ cluster_name: str,
+ namespace: str,
+ service_name: str,
+ port_name: str,
+ host: str,
+) -> client.V1Ingress:
+ api_client = api_config_handler()
+ ingress = client.V1Ingress(
+ api_version="networking.k8s.io/v1",
+ kind="Ingress",
+ metadata=client.V1ObjectMeta(
+ annotations={"route.openshift.io/termination": "passthrough"},
+ name=f"{cluster_name}-ingress",
+ namespace=namespace,
+ ),
+ spec=client.V1IngressSpec(
+ rules=[
+ client.V1IngressRule(
+ host=host,
+ http=client.V1HTTPIngressRuleValue(
+ paths=[
+ client.V1HTTPIngressPath(
+ backend=client.V1IngressBackend(
+ service=client.V1IngressServiceBackend(
+ name=service_name,
+ port=client.V1ServiceBackendPort(
+ name=port_name
+ ),
+ )
+ ),
+ path_type="ImplementationSpecific",
+ )
+ ]
+ ),
+ )
+ ]
+ ),
+ )
+ try:
+ client.NetworkingV1Api(api_client).create_namespaced_ingress(
+ namespace=namespace, body=ingress
+ )
+ except client.ApiException as e:
+ if e.reason == "Conflict":
+ client.NetworkingV1Api(api_client).replace_namespaced_ingress(
+ namespace=namespace, body=ingress, name=f"{cluster_name}-ingress"
+ )
+ else:
+ raise e
+Functions
+-
+
+def create_openshift_oauth_objects(cluster_name, namespace) +
+-
+
+++
+Expand source code +
+
+def create_openshift_oauth_objects(cluster_name, namespace): + config_check() + api_client = api_config_handler() or client.ApiClient() + oauth_port = 8443 + oauth_sa_name = f"{cluster_name}-oauth-proxy" + tls_secret_name = _gen_tls_secret_name(cluster_name) + service_name = f"{cluster_name}-oauth" + port_name = "oauth-proxy" + host = _get_api_host(api_client) + + # replace "^api" with the expected host + host = f"{gen_dashboard_route_name(cluster_name)}-{namespace}.apps" + host.lstrip( + "api" + ) + + _create_or_replace_oauth_sa(namespace, oauth_sa_name, host) + _create_or_replace_oauth_service_obj( + cluster_name, namespace, oauth_port, tls_secret_name, service_name, port_name + ) + _create_or_replace_oauth_ingress_object( + cluster_name, namespace, service_name, port_name, host + ) + _create_or_replace_oauth_rb(cluster_name, namespace, oauth_sa_name)
+ +def delete_openshift_oauth_objects(cluster_name, namespace) +
+-
+
+++
+Expand source code +
+
+def delete_openshift_oauth_objects(cluster_name, namespace): + # NOTE: it might be worth adding error handling here, but shouldn't be necessary because cluster.down(...) checks + # for an existing cluster before calling this => the objects should never be deleted twice + api_client = api_config_handler() + oauth_sa_name = f"{cluster_name}-oauth-proxy" + service_name = f"{cluster_name}-oauth" + client.CoreV1Api(api_client).delete_namespaced_service_account( + name=oauth_sa_name, namespace=namespace + ) + client.CoreV1Api(api_client).delete_namespaced_service( + name=service_name, namespace=namespace + ) + client.NetworkingV1Api(api_client).delete_namespaced_ingress( + name=f"{cluster_name}-ingress", namespace=namespace + ) + client.RbacAuthorizationV1Api(api_client).delete_cluster_role_binding( + name=f"{cluster_name}-rb" + )
+