Skip to content

Commit b61a1d9

Browse files
committed
Merge remote-tracking branch 'upstream/main'
2 parents 49d1fbc + a7c5ffc commit b61a1d9

35 files changed

Lines changed: 5292 additions & 201 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,6 @@ flymd.*
2727

2828
# Ignore version-specific values files
2929
charts/rhai-on-xks-chart/values-rhoai-*.yaml
30+
31+
# graphify output
32+
graphify-out/

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ RHAI on XKS Helm chart for non-OLM installation on non-OpenShift Kubernetes serv
4444
| azure.kubernetesEngine.spec.dependencies.lws.managementPolicy | string | `"Unmanaged"` | |
4545
| azure.kubernetesEngine.spec.dependencies.sailOperator.configuration.namespace | string | `"istio-system"` | |
4646
| azure.kubernetesEngine.spec.dependencies.sailOperator.managementPolicy | string | `"Managed"` | |
47+
| components.aigateway.enabled | bool | `false` | |
48+
| components.aigateway.modelsAsAService.gateway.allowedRoutes.namespaces.from | string | `"Same"` | |
49+
| components.aigateway.modelsAsAService.gateway.create | bool | `true` | |
50+
| components.aigateway.modelsAsAService.gateway.gatewayClassName | string | `"istio"` | |
51+
| components.aigateway.modelsAsAService.gateway.name | string | `"maas-default-gateway"` | |
52+
| components.aigateway.modelsAsAService.gateway.namespace | string | `""` | |
53+
| components.aigateway.spec.modelsAsAService.managementState | string | `"Managed"` | |
4754
| components.kserve.enabled | bool | `true` | |
4855
| components.kserve.gateway.allowedRoutes.namespaces.from | string | `"Same"` | |
4956
| components.kserve.gateway.create | bool | `true` | |

charts/rhai-on-xks-chart/files/create-gateway.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,14 @@ spec:
146146
port: 80
147147
protocol: HTTP
148148
{{- if .Values.components.kserve.gateway.allowedRoutes.namespaces.from }}
149-
{{- include "rhai-on-xks-chart.gatewayAllowedRoutes" . | nindent 6 }}
149+
{{- include "rhai-on-xks-chart.gatewayAllowedRoutes" (dict "allowedRoutes" .Values.components.kserve.gateway.allowedRoutes) | nindent 6 }}
150150
{{- end }}
151151
{{- if $tls.enabled }}
152152
- name: https
153153
port: 443
154154
protocol: HTTPS
155155
{{- if .Values.components.kserve.gateway.allowedRoutes.namespaces.from }}
156-
{{- include "rhai-on-xks-chart.gatewayAllowedRoutes" . | nindent 6 }}
156+
{{- include "rhai-on-xks-chart.gatewayAllowedRoutes" (dict "allowedRoutes" .Values.components.kserve.gateway.allowedRoutes) | nindent 6 }}
157157
{{- end }}
158158
tls:
159159
certificateRefs:
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
{{- $appNs := .Values.rhaiOperator.applicationsNamespace -}}
2+
{{- $tls := .Values.gateway.tls -}}
3+
{{- $maasGwNs := .Values.components.aigateway.modelsAsAService.gateway.namespace | default $appNs -}}
4+
{{- $maasGwName := .Values.components.aigateway.modelsAsAService.gateway.name -}}
5+
{{- $maasGwClass := .Values.components.aigateway.modelsAsAService.gateway.gatewayClassName -}}
6+
{{- $certSecret := "maas-gateway-cert-secret" -}}
7+
set -euo pipefail
8+
TIMEOUT=300
9+
INTERVAL=5
10+
11+
APP_NAMESPACE={{ $appNs | quote }}
12+
MAAS_GW_NAMESPACE={{ $maasGwNs | quote }}
13+
14+
wait_for() {
15+
local desc="$1"; shift
16+
local elapsed=0
17+
echo "Waiting for ${desc}..."
18+
until "$@" >/dev/null 2>&1; do
19+
if [ "$elapsed" -ge "$TIMEOUT" ]; then
20+
echo "ERROR: Timed out waiting for ${desc} after ${TIMEOUT}s"
21+
exit 1
22+
fi
23+
echo "${desc} not yet available, retrying in ${INTERVAL}s... (${elapsed}/${TIMEOUT}s)"
24+
sleep "$INTERVAL"
25+
elapsed=$((elapsed + INTERVAL))
26+
done
27+
echo "${desc} is available."
28+
}
29+
30+
maas_gw_cert_ready() {
31+
[ "$(kubectl get certificate maas-gateway-cert -n "$MAAS_GW_NAMESPACE" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null)" = "True" ]
32+
}
33+
34+
echo "=== MaaS Gateway Setup ==="
35+
36+
echo "Step 1: Create MaaS gateway namespace..."
37+
kubectl create namespace "$MAAS_GW_NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
38+
39+
echo "Step 2: Create CA bundle ConfigMaps..."
40+
wait_for "cert-manager CA secret" kubectl get secret rhai-ca -n cert-manager
41+
kubectl get secret rhai-ca -n cert-manager -o jsonpath='{.data.ca\.crt}' | base64 -d > /tmp/ca.crt
42+
kubectl create configmap rhai-ca-bundle --from-file=ca.crt=/tmp/ca.crt -n "$APP_NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
43+
kubectl create configmap rhai-ca-bundle --from-file=ca.crt=/tmp/ca.crt -n "$MAAS_GW_NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
44+
echo "CA bundle ConfigMaps created."
45+
46+
echo "Step 3: Create MaaS gateway config ConfigMap..."
47+
kubectl apply -f - <<'EOF'
48+
apiVersion: v1
49+
kind: ConfigMap
50+
metadata:
51+
name: maas-gateway-config
52+
namespace: {{ $maasGwNs | quote }}
53+
data:
54+
deployment: |
55+
spec:
56+
template:
57+
spec:
58+
volumes:
59+
- name: rhai-ca-bundle
60+
configMap:
61+
name: rhai-ca-bundle
62+
containers:
63+
- name: istio-proxy
64+
volumeMounts:
65+
- name: rhai-ca-bundle
66+
mountPath: /var/run/secrets/opendatahub
67+
readOnly: true
68+
- name: rhai-ca-bundle
69+
mountPath: /var/run/secrets/rhai
70+
readOnly: true
71+
{{- if .Values.azure.enabled }}
72+
service: |
73+
metadata:
74+
annotations:
75+
service.beta.kubernetes.io/port_80_health-probe_protocol: tcp
76+
{{- end }}
77+
EOF
78+
echo "MaaS gateway ConfigMap created."
79+
80+
{{- if $tls.enabled }}
81+
echo "Step 4: Create MaaS gateway TLS Certificate..."
82+
kubectl apply -f - <<'EOF'
83+
apiVersion: cert-manager.io/v1
84+
kind: Certificate
85+
metadata:
86+
name: maas-gateway-cert
87+
namespace: {{ $maasGwNs | quote }}
88+
spec:
89+
secretName: {{ $certSecret | quote }}
90+
issuerRef:
91+
name: {{ $tls.issuerRef.name | quote }}
92+
kind: {{ $tls.issuerRef.kind | quote }}
93+
group: cert-manager.io
94+
dnsNames:
95+
- "*.{{ $maasGwNs }}.svc.cluster.local"
96+
- "*.{{ $maasGwNs }}.svc"
97+
EOF
98+
wait_for "MaaS gateway Certificate to be Ready" maas_gw_cert_ready
99+
{{- end }}
100+
101+
echo "Step 5: Create MaaS API serving Certificate..."
102+
kubectl apply -f - <<'EOF'
103+
apiVersion: cert-manager.io/v1
104+
kind: Certificate
105+
metadata:
106+
name: maas-api-serving-cert
107+
namespace: {{ $appNs | quote }}
108+
spec:
109+
secretName: maas-api-serving-cert
110+
issuerRef:
111+
name: {{ $tls.issuerRef.name | quote }}
112+
kind: {{ $tls.issuerRef.kind | quote }}
113+
group: cert-manager.io
114+
dnsNames:
115+
- "maas-api.{{ $appNs }}.svc"
116+
- "maas-api.{{ $appNs }}.svc.cluster.local"
117+
EOF
118+
119+
echo "Step 6: Create MaaS Gateway..."
120+
kubectl apply -f - <<'EOF'
121+
apiVersion: gateway.networking.k8s.io/v1
122+
kind: Gateway
123+
metadata:
124+
name: {{ $maasGwName | quote }}
125+
namespace: {{ $maasGwNs | quote }}
126+
spec:
127+
gatewayClassName: {{ $maasGwClass | quote }}
128+
listeners:
129+
- name: http
130+
port: 80
131+
protocol: HTTP
132+
{{- if .Values.components.aigateway.modelsAsAService.gateway.allowedRoutes.namespaces.from }}
133+
{{- include "rhai-on-xks-chart.gatewayAllowedRoutes" (dict "allowedRoutes" .Values.components.aigateway.modelsAsAService.gateway.allowedRoutes) | nindent 6 }}
134+
{{- end }}
135+
{{- if $tls.enabled }}
136+
- name: https
137+
port: 443
138+
protocol: HTTPS
139+
{{- if .Values.components.aigateway.modelsAsAService.gateway.allowedRoutes.namespaces.from }}
140+
{{- include "rhai-on-xks-chart.gatewayAllowedRoutes" (dict "allowedRoutes" .Values.components.aigateway.modelsAsAService.gateway.allowedRoutes) | nindent 6 }}
141+
{{- end }}
142+
tls:
143+
certificateRefs:
144+
- group: ''
145+
kind: Secret
146+
name: {{ $certSecret | quote }}
147+
mode: Terminate
148+
{{- end }}
149+
infrastructure:
150+
parametersRef:
151+
group: ""
152+
kind: ConfigMap
153+
name: maas-gateway-config
154+
EOF
155+
echo "MaaS Gateway created successfully."
156+
157+
echo "Step 7: Copy pull secret to MaaS gateway namespace..."
158+
if kubectl get secret rhai-pull-secret -n "$APP_NAMESPACE" >/dev/null 2>&1; then
159+
DOCKER_CONFIG=$(kubectl get secret rhai-pull-secret -n "$APP_NAMESPACE" -o jsonpath='{.data.\.dockerconfigjson}')
160+
kubectl create secret generic rhai-pull-secret \
161+
--from-literal=.dockerconfigjson="$(echo "$DOCKER_CONFIG" | base64 -d)" \
162+
--type=kubernetes.io/dockerconfigjson \
163+
-n "$MAAS_GW_NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
164+
echo "Pull secret copied."
165+
else
166+
echo "No rhai-pull-secret found, skipping."
167+
fi
168+
169+
echo "Step 8: Configure Authorino CA trust for MaaS API callbacks..."
170+
KUADRANT_NS="kuadrant-system"
171+
if kubectl get namespace "$KUADRANT_NS" >/dev/null 2>&1; then
172+
kubectl create configmap rhai-ca-bundle --from-file=ca.crt=/tmp/ca.crt \
173+
-n "$KUADRANT_NS" --dry-run=client -o yaml | kubectl apply -f -
174+
175+
kubectl patch deployment authorino -n "$KUADRANT_NS" --type=json -p='[
176+
{"op":"add","path":"/spec/template/spec/volumes/-","value":{"name":"rhai-ca","configMap":{"name":"rhai-ca-bundle"}}},
177+
{"op":"add","path":"/spec/template/spec/containers/0/volumeMounts/-","value":{"name":"rhai-ca","mountPath":"/etc/pki/tls/custom","readOnly":true}},
178+
{"op":"add","path":"/spec/template/spec/containers/0/env/-","value":{"name":"SSL_CERT_FILE","value":"/etc/pki/tls/custom/ca.crt"}}
179+
]'
180+
echo "Authorino CA trust configured."
181+
else
182+
echo "Kuadrant namespace not found, skipping Authorino CA trust."
183+
fi
184+
185+
echo "=== MaaS Gateway setup complete ==="

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,13 @@ imagePullSecrets:
7070
{{- end -}}
7171

7272
{{/*
73-
Add the allowedRoutes block for a Gateway listener can be used by both HTTP and HTTPS listeners
74-
currently is only for kserve, might need adapt for other components
73+
Add the allowedRoutes block for a Gateway listener (HTTP and HTTPS).
74+
Accepts a dict with key "allowedRoutes" (the gateway.allowedRoutes value block).
75+
Usage:
76+
{{- include "rhai-on-xks-chart.gatewayAllowedRoutes" (dict "allowedRoutes" .Values.components.kserve.gateway.allowedRoutes) | nindent 6 }}
7577
*/}}
7678
{{- define "rhai-on-xks-chart.gatewayAllowedRoutes" -}}
77-
{{- $ns := .Values.components.kserve.gateway.allowedRoutes.namespaces -}}
79+
{{- $ns := .allowedRoutes.namespaces -}}
7880
{{- if and (eq $ns.from "Selector") (not $ns.selector) -}}
7981
{{- fail "allowedRoutes.namespaces.selector is required when from is set to Selector" -}}
8082
{{- end -}}

charts/rhai-on-xks-chart/templates/hooks/_crs-definitions.tpl

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ Returns a YAML map keyed by component name.
2727
To add a new component CR: add an entry here. All templates update automatically.
2828
*/}}
2929
{{- define "rhai-on-xks-chart.componentCRRegistry" -}}
30+
aigateway:
31+
kind: AIGateway
32+
resource: aigateways
33+
resourceSingular: aigateway
34+
crName: default-aigateway
35+
apiGroup: components.platform.opendatahub.io
3036
kserve:
3137
kind: Kserve
3238
resource: kserves
@@ -35,6 +41,82 @@ kserve:
3541
apiGroup: components.platform.opendatahub.io
3642
{{- end -}}
3743

44+
{{/*
45+
Registry of module CRs managed via the Platform CR (config.opendatahub.io/v1alpha1).
46+
AIGateway is a module, not a component — it is enabled by setting
47+
spec.modules.<platformModuleKey>.managementState: Managed on the Platform CR.
48+
To add a new module: add an entry here. All templates update automatically.
49+
*/}}
50+
{{- define "rhai-on-xks-chart.moduleCRRegistry" -}}
51+
aigateway:
52+
platformModuleKey: aigateway
53+
{{- end -}}
54+
55+
{{/*
56+
Returns a JSON list of enabled module names for guard conditions.
57+
*/}}
58+
{{- define "rhai-on-xks-chart.enabledModuleCRs" -}}
59+
{{- $registry := include "rhai-on-xks-chart.moduleCRRegistry" . | fromYaml }}
60+
{{- $result := list }}
61+
{{- range $name := keys $registry | sortAlpha }}
62+
{{- $modVals := index $.Values.components $name | default dict }}
63+
{{- if $modVals.enabled }}
64+
{{- $result = append $result $name }}
65+
{{- end }}
66+
{{- end }}
67+
{{- $result | toJson }}
68+
{{- end -}}
69+
70+
{{/*
71+
Emit a single kubectl apply for the Platform CR.
72+
The CR is always created (even with an empty modules spec) so it is present
73+
in the cluster for the operator to reconcile. Enabled modules get
74+
spec.modules.<key>.managementState: Managed; if none are enabled the CR is
75+
created with an empty spec.
76+
Include with: {{- include "rhai-on-xks-chart.moduleApplyCommands" . | nindent 14 }}
77+
*/}}
78+
{{- define "rhai-on-xks-chart.moduleApplyCommands" -}}
79+
{{- $root := . }}
80+
{{- $registry := include "rhai-on-xks-chart.moduleCRRegistry" . | fromYaml }}
81+
{{- $modulesSpec := dict }}
82+
{{- range $name := keys $registry | sortAlpha }}
83+
{{- $meta := index $registry $name }}
84+
{{- $modVals := index $.Values.components $name | default dict }}
85+
{{- if $modVals.enabled }}
86+
{{- $key := index $meta "platformModuleKey" }}
87+
{{- $modulesSpec = merge $modulesSpec (dict $key (dict "managementState" "Managed")) }}
88+
{{- end }}
89+
{{- end }}
90+
echo "Waiting for CRD platforms.config.opendatahub.io to be established..."
91+
kubectl wait --for condition=established --timeout=300s crd/platforms.config.opendatahub.io
92+
echo "Creating Platform CR..."
93+
kubectl apply -f - <<'EOF'
94+
apiVersion: config.opendatahub.io/v1alpha1
95+
kind: Platform
96+
metadata:
97+
name: default
98+
labels:
99+
{{- include "rhai-on-xks-chart.labels" $root | nindent 4 }}
100+
{{- if $modulesSpec }}
101+
spec:
102+
modules:
103+
{{- $modulesSpec | toYaml | nindent 4 }}
104+
{{- else }}
105+
spec: {}
106+
{{- end }}
107+
EOF
108+
{{- end -}}
109+
110+
{{/*
111+
Emit kubectl delete for the Platform CR. Always runs on uninstall since the
112+
Platform CR is always created (even with an empty modules spec).
113+
Include with: {{- include "rhai-on-xks-chart.moduleDeleteCommands" . | nindent 14 }}
114+
*/}}
115+
{{- define "rhai-on-xks-chart.moduleDeleteCommands" -}}
116+
echo "Deleting Platform CR 'default'..."
117+
kubectl delete platform default --ignore-not-found --timeout=300s
118+
{{- end -}}
119+
38120
{{/*
39121
Return a YAML dict for the active cloud provider (the one with .enabled=true).
40122
Returns empty string (→ empty map after fromYaml) if none enabled.
@@ -99,6 +181,8 @@ Component CRs are applied before provider KE CRs.
99181
{{- $meta := index $compRegistry $name }}
100182
{{- $compVals := index $.Values.components $name | default dict }}
101183
{{- if $compVals.enabled }}
184+
echo "Waiting for CRD {{ index $meta "resource" }}.{{ index $meta "apiGroup" }} to be established..."
185+
kubectl wait --for condition=established --timeout=300s crd/{{ index $meta "resource" }}.{{ index $meta "apiGroup" }}
102186
echo "Creating {{ index $meta "kind" }} CR..."
103187
kubectl apply -f - <<'EOF'
104188
apiVersion: {{ index $meta "apiGroup" }}/v1alpha1

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
{{- if .Values.enabled }}
22
{{- if .Values.hooks.postInstallCrs.enabled }}
3-
{{- $componentCRs := include "rhai-on-xks-chart.enabledComponentCRs" . | fromJson }}
4-
{{- $providerKECR := include "rhai-on-xks-chart.enabledProviderKECR" . }}
5-
{{- if or $componentCRs $providerKECR }}
63
apiVersion: batch/v1
74
kind: Job
85
metadata:
@@ -46,7 +43,7 @@ spec:
4643
- |
4744
set -euo pipefail
4845
{{- include "rhai-on-xks-chart.crApplyCommands" . | trimPrefix "\n" | nindent 14 }}
46+
{{- include "rhai-on-xks-chart.moduleApplyCommands" . | nindent 14 }}
4947
echo "Done."
5048
{{- end }}
5149
{{- end }}
52-
{{- end }}

0 commit comments

Comments
 (0)