Skip to content

Commit 4fb95d5

Browse files
committed
Merge remote-tracking branch 'upstream/main'
2 parents 6a3d847 + 4dad845 commit 4fb95d5

24 files changed

Lines changed: 14394 additions & 683 deletions

charts/rhai-on-xks-chart/api-docs.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ RHAI on XKS Helm chart for non-OLM installation on non-OpenShift Kubernetes serv
4545
| azure.kubernetesEngine.spec.dependencies.sailOperator.configuration.namespace | string | `"istio-system"` | |
4646
| azure.kubernetesEngine.spec.dependencies.sailOperator.managementPolicy | string | `"Managed"` | |
4747
| components.kserve.enabled | bool | `true` | |
48-
| components.kserve.gateway.allowedRoutes.namespaces.from | string | `"All"` | |
48+
| components.kserve.gateway.allowedRoutes.namespaces.from | string | `"Same"` | |
4949
| components.kserve.gateway.create | bool | `true` | |
5050
| components.kserve.spec | object | `{}` | |
5151
| coreweave.cloudManager.image | string | `"quay.io/opendatahub/opendatahub-operator:latest"` | |
@@ -67,6 +67,11 @@ RHAI on XKS Helm chart for non-OLM installation on non-OpenShift Kubernetes serv
6767
| coreweave.kubernetesEngine.spec.dependencies.sailOperator.configuration.namespace | string | `"istio-system"` | |
6868
| coreweave.kubernetesEngine.spec.dependencies.sailOperator.managementPolicy | string | `"Managed"` | |
6969
| enabled | bool | `true` | |
70+
| gateway.hostname | string | `""` | |
71+
| gateway.tls.additionalSANs | list | `[]` | |
72+
| gateway.tls.enabled | bool | `true` | |
73+
| gateway.tls.issuerRef.kind | string | `"ClusterIssuer"` | |
74+
| gateway.tls.issuerRef.name | string | `"rhai-ca-issuer"` | |
7075
| hooks.cliImage | string | `"registry.redhat.io/openshift4/ose-cli-rhel9:v4.20@sha256:d876c1d98b39d65c00c4261431bb84b90284699f3aef84d8701a25c786fb79a1"` | |
7176
| hooks.postInstallCrs.enabled | bool | `true` | |
7277
| hooks.resources.limits.cpu | string | `"200m"` | |
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
{{- $appNs := .Values.rhaiOperator.applicationsNamespace -}}
2+
{{- $tls := .Values.gateway.tls -}}
3+
{{- $hostname := .Values.gateway.hostname -}}
4+
{{- $internalIssuer := eq $tls.issuerRef.name "rhai-ca-issuer" -}}
5+
{{- /* Internal secret name for the cert: created by Certificate, read by every gateway HTTPS listener. Not user-configurable. */ -}}
6+
{{- $certSecret := "inference-gateway-cert-secret" -}}
7+
set -euo pipefail
8+
TIMEOUT=300
9+
INTERVAL=5
10+
11+
# Quoted once here so untrusted values can never reach the shell unquoted.
12+
APP_NAMESPACE={{ $appNs | quote }}
13+
14+
# general wait function for resource to be ready in the cluster
15+
wait_for() {
16+
local desc="$1"; shift
17+
local elapsed=0
18+
echo "Waiting for ${desc}..."
19+
until "$@" >/dev/null 2>&1; do
20+
if [ "$elapsed" -ge "$TIMEOUT" ]; then
21+
echo "ERROR: Timed out waiting for ${desc} after ${TIMEOUT}s"
22+
exit 1
23+
fi
24+
echo "${desc} not yet available, retrying in ${INTERVAL}s... (${elapsed}/${TIMEOUT}s)"
25+
sleep "$INTERVAL"
26+
elapsed=$((elapsed + INTERVAL))
27+
done
28+
echo "${desc} is available."
29+
}
30+
31+
# Readiness predicates for wait_for (only invoked when TLS is enabled).
32+
# ISSUER_ARGS is built in the TLS step below, before issuer_ready is called.
33+
issuer_ready() {
34+
[ "$(kubectl get "${ISSUER_ARGS[@]}" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null)" = "True" ]
35+
}
36+
# Wait on the Certificate's Ready condition, not just Secret existence.
37+
cert_ready() {
38+
[ "$(kubectl get certificate inference-gateway-cert -n "$APP_NAMESPACE" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null)" = "True" ]
39+
}
40+
41+
echo "Step 1: Gateway API CRDs required by Gateway CR 'inference-gateway'..."
42+
wait_for "Gateway API CRDs" kubectl get crd gateways.gateway.networking.k8s.io
43+
44+
echo "Step 2: cert-manager CA secret required by Gateway CR 'inference-gateway'..."
45+
wait_for "cert-manager CA secret" kubectl get secret rhai-ca -n cert-manager
46+
47+
echo "Step 3: Creating CA bundle ConfigMap for Gateway CR 'inference-gateway'..."
48+
kubectl get secret rhai-ca -n cert-manager -o jsonpath='{.data.ca\.crt}' | base64 -d > /tmp/ca.crt
49+
kubectl create configmap rhai-ca-bundle --from-file=ca.crt=/tmp/ca.crt -n "$APP_NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
50+
echo "CA bundle ConfigMap created."
51+
52+
echo "Step 4: Create ConfigMap used by Gateway CR 'inference-gateway'..."
53+
kubectl apply -f - <<'EOF'
54+
apiVersion: v1
55+
kind: ConfigMap
56+
metadata:
57+
name: inference-gateway-config
58+
namespace: {{ $appNs | quote }}
59+
data:
60+
deployment: |
61+
spec:
62+
template:
63+
spec:
64+
volumes:
65+
- name: rhai-ca-bundle
66+
configMap:
67+
name: rhai-ca-bundle
68+
containers:
69+
- name: istio-proxy
70+
volumeMounts:
71+
- name: rhai-ca-bundle
72+
mountPath: /var/run/secrets/rhai
73+
readOnly: true
74+
{{- if .Values.azure.enabled }}
75+
service: |
76+
metadata:
77+
annotations:
78+
service.beta.kubernetes.io/port_80_health-probe_protocol: tcp
79+
{{- end }}
80+
EOF
81+
echo "ConfigMap used by Gateway CR 'inference-gateway' created."
82+
83+
84+
{{- if $tls.enabled }}
85+
ISSUER_NAME={{ $tls.issuerRef.name | quote }}
86+
ISSUER_KIND={{ $tls.issuerRef.kind | lower | quote }}
87+
ISSUER_ARGS=("$ISSUER_KIND" "$ISSUER_NAME")
88+
{{- if eq $tls.issuerRef.kind "Issuer" }}
89+
ISSUER_ARGS+=(-n "$APP_NAMESPACE")
90+
{{- end }}
91+
wait_for "${ISSUER_KIND} ${ISSUER_NAME} to be Ready" issuer_ready
92+
93+
{{- if and (not $internalIssuer) (not $hostname) (not $tls.additionalSANs) }}
94+
{{- fail "gateway.tls.issuerRef is non-default (external) but neither gateway.hostname nor gateway.tls.additionalSANs is set; the certificate would have no dnsNames" }}
95+
{{- end }}
96+
echo "Step 5: Creating Certificate for Gateway TLS..."
97+
{{- if and $hostname $internalIssuer }}
98+
echo "WARNING: gateway.hostname is set but issuerRef ${ISSUER_NAME} is the internal CA; the certificate is only trusted inside the cluster. Set gateway.tls.issuerRef to a public/enterprise issuer for external clients."
99+
{{- end }}
100+
kubectl apply -f - <<'EOF'
101+
apiVersion: cert-manager.io/v1
102+
kind: Certificate
103+
metadata:
104+
name: inference-gateway-cert
105+
namespace: {{ $appNs | quote }}
106+
spec:
107+
secretName: {{ $certSecret | quote }}
108+
issuerRef:
109+
name: {{ $tls.issuerRef.name | quote }}
110+
kind: {{ $tls.issuerRef.kind | quote }}
111+
group: cert-manager.io
112+
dnsNames:
113+
{{- if $internalIssuer }}
114+
- "*.{{ $appNs }}.svc.cluster.local"
115+
- "*.{{ $appNs }}.svc"
116+
{{- end }}
117+
{{- if $hostname }}
118+
- {{ $hostname | quote }}
119+
{{- if hasPrefix "*." $hostname }}
120+
- {{ $hostname | trimPrefix "*." | quote }}
121+
{{- end }}
122+
{{- end }}
123+
{{- range $tls.additionalSANs }}
124+
- {{ . | quote }}
125+
{{- end }}
126+
EOF
127+
echo "Certificate 'inference-gateway-cert' created."
128+
129+
wait_for "Certificate 'inference-gateway-cert' to be Ready" cert_ready
130+
{{- end }}
131+
132+
echo "Step 6: GatewayClass 'istio' required by Gateway CR 'inference-gateway'..."
133+
wait_for "GatewayClass 'istio'" kubectl get gatewayclass istio
134+
135+
echo "Step 7: Creating Gateway CR 'inference-gateway'..."
136+
kubectl apply -f - <<'EOF'
137+
apiVersion: gateway.networking.k8s.io/v1
138+
kind: Gateway
139+
metadata:
140+
name: inference-gateway
141+
namespace: {{ $appNs | quote }}
142+
spec:
143+
gatewayClassName: istio
144+
listeners:
145+
- name: http
146+
port: 80
147+
protocol: HTTP
148+
{{- if .Values.components.kserve.gateway.allowedRoutes.namespaces.from }}
149+
{{- include "rhai-on-xks-chart.gatewayAllowedRoutes" . | nindent 6 }}
150+
{{- end }}
151+
{{- if $tls.enabled }}
152+
- name: https
153+
port: 443
154+
protocol: HTTPS
155+
{{- if .Values.components.kserve.gateway.allowedRoutes.namespaces.from }}
156+
{{- include "rhai-on-xks-chart.gatewayAllowedRoutes" . | nindent 6 }}
157+
{{- end }}
158+
tls:
159+
certificateRefs:
160+
- group: ''
161+
kind: Secret
162+
name: {{ $certSecret | quote }}
163+
mode: Terminate
164+
{{- end }}
165+
infrastructure:
166+
labels:
167+
serving.kserve.io/gateway: kserve-ingress-gateway
168+
parametersRef:
169+
group: ""
170+
kind: ConfigMap
171+
name: inference-gateway-config
172+
EOF
173+
echo "Gateway CR 'inference-gateway' created successfully."

charts/rhai-on-xks-chart/scripts/helmtemplate-config.yaml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
11
# helmtemplate-generator configuration for RHAI operator chart
22

3-
filter:
4-
include:
5-
- kinds:
6-
- CustomResourceDefinition
7-
names:
8-
- "kserves.components.platform.opendatahub.io"
9-
103
rules:
114
# Replace namespace references with Helm template
125
- match:

charts/rhai-on-xks-chart/templates/NOTES.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,26 @@ Cloud provider: CoreWeave
88
Cloud provider: AWS
99
{{- end }}
1010

11+
{{- $tls := .Values.gateway.tls }}
12+
{{- $hostname := .Values.gateway.hostname }}
13+
{{- $internalIssuer := eq $tls.issuerRef.name "rhai-ca-issuer" }}
14+
{{- if or (not $tls.enabled) (and $hostname $internalIssuer) }}
15+
16+
== Gateway TLS ==
17+
{{- if not $tls.enabled }}
18+
19+
TLS is disabled (gateway.tls.enabled=false). Gateways serve HTTP only on
20+
port 80; no Certificate is created and the HTTPS listener is omitted. Set
21+
gateway.tls.enabled=true to terminate TLS at the gateway.
22+
{{- else if and $hostname $internalIssuer }}
23+
24+
WARNING: gateway.hostname is set ("{{ $hostname }}") but gateway.tls.issuerRef
25+
is the internal CA ("{{ $tls.issuerRef.name }}"); the certificate is only
26+
trusted inside the cluster. Set gateway.tls.issuerRef to a public/enterprise
27+
issuer for external clients to trust it.
28+
{{- end }}
29+
{{- end }}
30+
1131
== Custom Resources ==
1232

1333
{{- if .Values.components.kserve.enabled }}

charts/rhai-on-xks-chart/templates/_helpers.tpl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,24 @@ imagePullSecrets:
4848
- name: {{ include "rhai-on-xks-chart.imagePullSecretName" . }}
4949
{{- end -}}
5050

51+
{{/*
52+
Add the allowedRoutes block for a Gateway listener can be used by both HTTP and HTTPS listeners
53+
currently is only for kserve, might need adapt for other components
54+
*/}}
55+
{{- define "rhai-on-xks-chart.gatewayAllowedRoutes" -}}
56+
{{- $ns := .Values.components.kserve.gateway.allowedRoutes.namespaces -}}
57+
{{- if and (eq $ns.from "Selector") (not $ns.selector) -}}
58+
{{- fail "allowedRoutes.namespaces.selector is required when from is set to Selector" -}}
59+
{{- end -}}
60+
allowedRoutes:
61+
namespaces:
62+
from: {{ $ns.from }}
63+
{{- if and (eq $ns.from "Selector") $ns.selector }}
64+
selector:
65+
{{- toYaml $ns.selector | nindent 6 }}
66+
{{- end }}
67+
{{- end -}}
68+
5169
{{/*
5270
Validate that exactly one cloud provider is enabled.
5371
*/}}

charts/rhai-on-xks-chart/templates/hooks/post-install-crs-rbac.yaml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
{{- $createCoreweaveKE := and .Values.coreweave.enabled .Values.coreweave.kubernetesEngine.enabled }}
66
{{- $createAwsKE := and .Values.aws.enabled .Values.aws.kubernetesEngine.enabled }}
77
{{- $createGateway := and .Values.components.kserve.enabled .Values.components.kserve.gateway.create }}
8+
{{- $gatewayTls := and $createGateway .Values.gateway.tls.enabled }}
9+
{{- $appNs := .Values.rhaiOperator.applicationsNamespace }}
10+
{{- $issuerName := .Values.gateway.tls.issuerRef.name }}
11+
{{- $issuerKind := .Values.gateway.tls.issuerRef.kind }}
812
{{- if or $createKserve $createAzureKE $createCoreweaveKE $createAwsKE $createGateway }}
913
apiVersion: v1
1014
kind: ServiceAccount
@@ -86,6 +90,18 @@ rules:
8690
- create
8791
- patch
8892
- update
93+
{{- if and $gatewayTls (eq $issuerKind "ClusterIssuer") }}
94+
# ClusterIssuers are cluster-scoped, so the read must live on the ClusterRole,
95+
# but it is restricted to the single issuer the gateway Certificate references.
96+
- apiGroups:
97+
- cert-manager.io
98+
resources:
99+
- clusterissuers
100+
resourceNames:
101+
- {{ $issuerName }}
102+
verbs:
103+
- get
104+
{{- end }}
89105
{{- end }}
90106
---
91107
apiVersion: rbac.authorization.k8s.io/v1
@@ -106,6 +122,61 @@ subjects:
106122
- kind: ServiceAccount
107123
name: rhai-post-install-hook
108124
namespace: {{ .Release.Namespace }}
125+
{{- if $gatewayTls }}
126+
---
127+
# Certificate is namespaced to the applications namespace.
128+
apiVersion: rbac.authorization.k8s.io/v1
129+
kind: Role
130+
metadata:
131+
name: rhai-post-install-hook-cert
132+
namespace: {{ $appNs }}
133+
labels:
134+
{{- include "rhai-on-xks-chart.labels" . | nindent 4 }}
135+
annotations:
136+
helm.sh/hook: post-install,post-upgrade
137+
helm.sh/hook-weight: "0"
138+
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
139+
rules:
140+
- apiGroups:
141+
- cert-manager.io
142+
resources:
143+
- certificates
144+
verbs:
145+
- get
146+
- create
147+
- patch
148+
- update
149+
{{- if eq $issuerKind "Issuer" }}
150+
- apiGroups:
151+
- cert-manager.io
152+
resources:
153+
- issuers
154+
resourceNames:
155+
- {{ $issuerName }}
156+
verbs:
157+
- get
158+
{{- end }}
159+
---
160+
apiVersion: rbac.authorization.k8s.io/v1
161+
kind: RoleBinding
162+
metadata:
163+
name: rhai-post-install-hook-cert
164+
namespace: {{ $appNs }}
165+
labels:
166+
{{- include "rhai-on-xks-chart.labels" . | nindent 4 }}
167+
annotations:
168+
helm.sh/hook: post-install,post-upgrade
169+
helm.sh/hook-weight: "0"
170+
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
171+
roleRef:
172+
apiGroup: rbac.authorization.k8s.io
173+
kind: Role
174+
name: rhai-post-install-hook-cert
175+
subjects:
176+
- kind: ServiceAccount
177+
name: rhai-post-install-hook
178+
namespace: {{ .Release.Namespace }}
179+
{{- end }}
109180
{{- end }}
110181
{{- end }}
111182
{{- end }}

0 commit comments

Comments
 (0)