Skip to content

Commit 897b09b

Browse files
committed
Add OpenShift support to boundary-worker Helm chart
1 parent 3f6bd04 commit 897b09b

11 files changed

Lines changed: 424 additions & 2 deletions

templates/_helpers.tpl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,13 @@ limits:
159159
memory: 256Mi
160160
{{- end }}
161161

162+
{{/*
163+
Get the OpenShift Route name for the worker proxy port
164+
*/}}
165+
{{- define "boundary.worker.route.name" -}}
166+
{{- printf "%s-proxy-route" (include "boundary.fullname" .) }}
167+
{{- end }}
168+
162169
{{/*
163170
Get the service account name for the worker
164171
*/}}

templates/worker-deployment.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ metadata:
1010
{{- include "boundary.labels" . | nindent 4 }}
1111
app.kubernetes.io/component: worker
1212
spec:
13-
replicas: 1 # Workers are not scaled horizontally
13+
replicas: 1
1414
selector:
1515
matchLabels:
1616
{{- include "boundary.worker.selectorLabels" . | nindent 6 }}
@@ -33,13 +33,21 @@ spec:
3333
{{- end }}
3434
terminationGracePeriodSeconds: {{ .Values.worker.terminationGracePeriodSeconds }}
3535
securityContext:
36+
{{- if .Values.openshift.enabled }}
37+
{{- toYaml .Values.openshift.podSecurityContext | nindent 8 }}
38+
{{- else }}
3639
{{- toYaml .Values.podSecurityContext | nindent 8 }}
40+
{{- end }}
3741
containers:
3842
- name: worker
3943
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
4044
imagePullPolicy: {{ .Values.image.pullPolicy }}
4145
securityContext:
46+
{{- if .Values.openshift.enabled }}
47+
{{- toYaml .Values.openshift.containerSecurityContext | nindent 12 }}
48+
{{- else }}
4249
{{- toYaml .Values.containerSecurityContext | nindent 12 }}
50+
{{- end }}
4351
env:
4452
- name: POD_NAME
4553
valueFrom:

templates/worker-pvc.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ metadata:
1414
spec:
1515
accessModes:
1616
- {{ .Values.worker.persistence.recording.accessMode }}
17+
{{- if .Values.worker.persistence.recording.storageClass }}
1718
storageClassName: {{ .Values.worker.persistence.recording.storageClass }}
19+
{{- end }}
1820
resources:
1921
requests:
2022
storage: {{ .Values.worker.persistence.recording.size }}
@@ -37,7 +39,9 @@ metadata:
3739
spec:
3840
accessModes:
3941
- {{ .Values.worker.persistence.authStorage.accessMode }}
42+
{{- if .Values.worker.persistence.authStorage.storageClass }}
4043
storageClassName: {{ .Values.worker.persistence.authStorage.storageClass }}
44+
{{- end }}
4145
resources:
4246
requests:
4347
storage: {{ .Values.worker.persistence.authStorage.size }}

templates/worker-route.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright IBM Corp. 2026
2+
3+
{{- if and .Values.openshift.enabled .Values.openshift.route.proxy.enabled }}
4+
# Boundary Worker OpenShift Route
5+
apiVersion: route.openshift.io/v1
6+
kind: Route
7+
metadata:
8+
name: {{ include "boundary.worker.route.name" . }}
9+
namespace: {{ .Release.Namespace }}
10+
labels:
11+
{{- include "boundary.labels" . | nindent 4 }}
12+
app.kubernetes.io/component: worker
13+
{{- with .Values.openshift.route.proxy.annotations }}
14+
annotations:
15+
{{- toYaml . | nindent 4 }}
16+
{{- end }}
17+
spec:
18+
{{- if .Values.openshift.route.proxy.host }}
19+
host: {{ .Values.openshift.route.proxy.host }}
20+
{{- end }}
21+
to:
22+
kind: Service
23+
name: {{ include "boundary.worker.proxy.serviceName" . }}
24+
port:
25+
targetPort: proxy
26+
tls:
27+
termination: {{ .Values.openshift.route.proxy.tls.termination }}
28+
{{- end }}

templates/worker-service.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ metadata:
1515
{{- . | nindent 4 }}
1616
{{- end }}
1717
spec:
18-
type: {{ .Values.worker.service.proxy.type }}
18+
type: {{ if .Values.openshift.enabled }}ClusterIP{{ else }}{{ .Values.worker.service.proxy.type }}{{ end }}
1919
ports:
2020
- port: {{ .Values.worker.service.proxy.port }}
2121
targetPort: {{ .Values.worker.service.proxy.targetPort }}

tests/unit/worker-deployment_test.yaml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,3 +468,68 @@ tests:
468468
- equal:
469469
path: spec.selector.matchLabels["app.kubernetes.io/component"]
470470
value: worker
471+
472+
# ============================================================================
473+
# OPENSHIFT SECURITY CONTEXT TESTS
474+
# ============================================================================
475+
476+
- it: should omit runAsUser and fsGroup from pod security context when openshift.enabled is true
477+
template: worker-deployment.yaml
478+
set:
479+
openshift.enabled: true
480+
asserts:
481+
- isNull:
482+
path: spec.template.spec.securityContext.runAsUser
483+
- isNull:
484+
path: spec.template.spec.securityContext.runAsGroup
485+
- isNull:
486+
path: spec.template.spec.securityContext.fsGroup
487+
- equal:
488+
path: spec.template.spec.securityContext.runAsNonRoot
489+
value: true
490+
491+
- it: should retain runAsUser and fsGroup in pod security context when openshift.enabled is false
492+
template: worker-deployment.yaml
493+
set:
494+
openshift.enabled: false
495+
asserts:
496+
- equal:
497+
path: spec.template.spec.securityContext.runAsUser
498+
value: 100
499+
- equal:
500+
path: spec.template.spec.securityContext.runAsGroup
501+
value: 1000
502+
- equal:
503+
path: spec.template.spec.securityContext.fsGroup
504+
value: 1000
505+
506+
- it: should omit runAsUser and runAsGroup from container security context when openshift.enabled is true
507+
template: worker-deployment.yaml
508+
set:
509+
openshift.enabled: true
510+
asserts:
511+
- isNull:
512+
path: spec.template.spec.containers[0].securityContext.runAsUser
513+
- isNull:
514+
path: spec.template.spec.containers[0].securityContext.runAsGroup
515+
- equal:
516+
path: spec.template.spec.containers[0].securityContext.runAsNonRoot
517+
value: true
518+
- equal:
519+
path: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation
520+
value: false
521+
- equal:
522+
path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
523+
value: true
524+
525+
- it: should retain runAsUser in container security context when openshift.enabled is false
526+
template: worker-deployment.yaml
527+
set:
528+
openshift.enabled: false
529+
asserts:
530+
- equal:
531+
path: spec.template.spec.containers[0].securityContext.runAsUser
532+
value: 100
533+
- equal:
534+
path: spec.template.spec.containers[0].securityContext.runAsGroup
535+
value: 1000

tests/unit/worker-pvc_test.yaml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,45 @@ tests:
204204
path: spec.storageClassName
205205
value: local-path
206206
documentIndex: 0
207+
208+
# ============================================================================
209+
# STORAGECLASS CONDITIONAL RENDERING TESTS (OpenShift / default SC)
210+
# ============================================================================
211+
212+
- it: should omit storageClassName from recording PVC when storageClass is empty
213+
set:
214+
worker.persistence.recording.enabled: true
215+
worker.persistence.recording.storageClass: ""
216+
documentIndex: 0
217+
asserts:
218+
- isNull:
219+
path: spec.storageClassName
220+
221+
- it: should set storageClassName on recording PVC when storageClass is provided
222+
set:
223+
worker.persistence.recording.enabled: true
224+
worker.persistence.recording.storageClass: gp3-csi
225+
documentIndex: 0
226+
asserts:
227+
- equal:
228+
path: spec.storageClassName
229+
value: gp3-csi
230+
231+
- it: should omit storageClassName from auth PVC when storageClass is empty
232+
set:
233+
worker.persistence.recording.enabled: false
234+
worker.persistence.authStorage.storageClass: ""
235+
documentIndex: 0
236+
asserts:
237+
- isNull:
238+
path: spec.storageClassName
239+
240+
- it: should set storageClassName on auth PVC when storageClass is provided
241+
set:
242+
worker.persistence.recording.enabled: false
243+
worker.persistence.authStorage.storageClass: thin-csi
244+
documentIndex: 0
245+
asserts:
246+
- equal:
247+
path: spec.storageClassName
248+
value: thin-csi

tests/unit/worker-route_test.yaml

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Copyright IBM Corp. 2026
2+
3+
suite: Test Worker OpenShift Route Configuration
4+
templates:
5+
- worker-route.yaml
6+
tests:
7+
# ============================================================================
8+
# ROUTE NOT RENDERED ON VANILLA KUBERNETES
9+
# ============================================================================
10+
11+
- it: should not render a Route when openshift.enabled is false
12+
set:
13+
openshift.enabled: false
14+
openshift.route.proxy.enabled: true
15+
asserts:
16+
- hasDocuments:
17+
count: 0
18+
19+
- it: should not render a Route when openshift.route.proxy.enabled is false
20+
set:
21+
openshift.enabled: true
22+
openshift.route.proxy.enabled: false
23+
asserts:
24+
- hasDocuments:
25+
count: 0
26+
27+
- it: should not render a Route when both flags are false
28+
set:
29+
openshift.enabled: false
30+
openshift.route.proxy.enabled: false
31+
asserts:
32+
- hasDocuments:
33+
count: 0
34+
35+
# ============================================================================
36+
# ROUTE RENDERED ON OPENSHIFT
37+
# ============================================================================
38+
39+
- it: should render a Route when openshift.enabled and route.proxy.enabled are true
40+
set:
41+
openshift.enabled: true
42+
openshift.route.proxy.enabled: true
43+
asserts:
44+
- hasDocuments:
45+
count: 1
46+
- isAPIVersion:
47+
of: route.openshift.io/v1
48+
- isKind:
49+
of: Route
50+
51+
- it: should use passthrough TLS termination by default
52+
set:
53+
openshift.enabled: true
54+
openshift.route.proxy.enabled: true
55+
asserts:
56+
- equal:
57+
path: spec.tls.termination
58+
value: passthrough
59+
60+
- it: should allow edge TLS termination override
61+
set:
62+
openshift.enabled: true
63+
openshift.route.proxy.enabled: true
64+
openshift.route.proxy.tls.termination: edge
65+
asserts:
66+
- equal:
67+
path: spec.tls.termination
68+
value: edge
69+
70+
- it: should not set spec.host when host is empty
71+
set:
72+
openshift.enabled: true
73+
openshift.route.proxy.enabled: true
74+
openshift.route.proxy.host: ""
75+
asserts:
76+
- isNull:
77+
path: spec.host
78+
79+
- it: should set spec.host when a custom host is provided
80+
set:
81+
openshift.enabled: true
82+
openshift.route.proxy.enabled: true
83+
openshift.route.proxy.host: "boundary.apps.cluster.example.com"
84+
asserts:
85+
- equal:
86+
path: spec.host
87+
value: "boundary.apps.cluster.example.com"
88+
89+
- it: should target the proxy service
90+
release:
91+
name: my-worker
92+
set:
93+
openshift.enabled: true
94+
openshift.route.proxy.enabled: true
95+
asserts:
96+
- equal:
97+
path: spec.to.kind
98+
value: Service
99+
- equal:
100+
path: spec.to.name
101+
value: my-worker-proxy
102+
- equal:
103+
path: spec.port.targetPort
104+
value: proxy
105+
106+
- it: should apply route annotations when provided
107+
set:
108+
openshift.enabled: true
109+
openshift.route.proxy.enabled: true
110+
openshift.route.proxy.annotations:
111+
haproxy.router.openshift.io/timeout: "2h"
112+
asserts:
113+
- equal:
114+
path: metadata.annotations["haproxy.router.openshift.io/timeout"]
115+
value: "2h"
116+
117+
- it: should use the release namespace
118+
release:
119+
namespace: boundary-prod
120+
set:
121+
openshift.enabled: true
122+
openshift.route.proxy.enabled: true
123+
asserts:
124+
- equal:
125+
path: metadata.namespace
126+
value: boundary-prod
127+
128+
- it: should carry standard labels
129+
set:
130+
openshift.enabled: true
131+
openshift.route.proxy.enabled: true
132+
asserts:
133+
- equal:
134+
path: metadata.labels["app.kubernetes.io/component"]
135+
value: worker
136+
- isNotNull:
137+
path: metadata.labels["helm.sh/chart"]
138+
- isNotNull:
139+
path: metadata.labels["app.kubernetes.io/name"]

tests/unit/worker-service_test.yaml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,41 @@ tests:
181181
path: metadata.namespace
182182
value: custom-namespace
183183
documentIndex: 1
184+
185+
# ============================================================================
186+
# OPENSHIFT SERVICE TESTS
187+
# ============================================================================
188+
189+
- it: should use ClusterIP for proxy service when openshift.enabled is true
190+
set:
191+
worker.service.proxy.enabled: true
192+
worker.service.proxy.type: LoadBalancer
193+
openshift.enabled: true
194+
documentIndex: 0
195+
asserts:
196+
- equal:
197+
path: spec.type
198+
value: ClusterIP
199+
200+
- it: should use configured type for proxy service when openshift.enabled is false
201+
set:
202+
worker.service.proxy.enabled: true
203+
worker.service.proxy.type: LoadBalancer
204+
openshift.enabled: false
205+
documentIndex: 0
206+
asserts:
207+
- equal:
208+
path: spec.type
209+
value: LoadBalancer
210+
211+
- it: should keep ops service type unchanged when openshift.enabled is true
212+
set:
213+
worker.service.proxy.enabled: true
214+
worker.service.ops.enabled: true
215+
worker.service.ops.type: ClusterIP
216+
openshift.enabled: true
217+
documentIndex: 1
218+
asserts:
219+
- equal:
220+
path: spec.type
221+
value: ClusterIP

0 commit comments

Comments
 (0)