Skip to content

Commit 5d72eed

Browse files
committed
charts/redpanda: allow overriding volumes
Previously it wasn't possible to use `podTemplate` to override the `VolumeSource`. Helm prevented explicitly null'ing out values due to the chart's schema and the go implementation has no concept of explicit nulls. This commit copies the precedent set in `mergeEnvVar` and simply elects the override if provided. Additionally this commit adds a test case showcasing how to use `podTemplate` to generate certificates from an initContainer. K8S-683 (cherry picked from commit 1f5dfc9) # Conflicts: # charts/redpanda/helpers_test.go
1 parent 1c00a87 commit 5d72eed

File tree

5 files changed

+171
-2
lines changed

5 files changed

+171
-2
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
project: charts/redpanda
2+
kind: Fixed
3+
body: '`statefulset.podTemplate.spec.volumes` can now be used to override chart generated volumes.'
4+
time: 2025-09-08T17:24:18.8483-04:00

charts/redpanda/helpers.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,9 @@ func mergeEnvVar(original corev1.EnvVar, overrides applycorev1.EnvVarApplyConfig
544544
}
545545

546546
func mergeVolume(original corev1.Volume, override applycorev1.VolumeApplyConfiguration) corev1.Volume {
547-
return helmette.MergeTo[corev1.Volume](override, original)
547+
// Similar to the above, if a volume is being overridden, it's likely to
548+
// change the VolumeSource. Don't merge, just accept the override.
549+
return helmette.MergeTo[corev1.Volume](override)
548550
}
549551

550552
func mergeVolumeMount(original corev1.VolumeMount, override applycorev1.VolumeMountApplyConfiguration) corev1.VolumeMount {

charts/redpanda/helpers_test.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,113 @@ func TestStrategicMergePatch(t *testing.T) {
188188
},
189189
},
190190
},
191+
<<<<<<< HEAD
192+
=======
193+
{
194+
Name: "probes",
195+
Override: redpanda.PodTemplate{
196+
Spec: &applycorev1.PodSpecApplyConfiguration{
197+
Containers: []applycorev1.ContainerApplyConfiguration{
198+
{
199+
Name: ptr.To("redpanda"),
200+
StartupProbe: &applycorev1.ProbeApplyConfiguration{
201+
FailureThreshold: ptr.To[int32](120),
202+
},
203+
},
204+
},
205+
},
206+
},
207+
Original: corev1.PodTemplateSpec{
208+
Spec: corev1.PodSpec{
209+
Containers: []corev1.Container{
210+
{
211+
Name: "redpanda",
212+
StartupProbe: &corev1.Probe{
213+
ProbeHandler: corev1.ProbeHandler{
214+
Exec: &corev1.ExecAction{
215+
Command: []string{"rpk cluster health"},
216+
},
217+
},
218+
},
219+
},
220+
},
221+
},
222+
},
223+
Expected: corev1.PodTemplateSpec{
224+
ObjectMeta: metav1.ObjectMeta{
225+
Labels: map[string]string{},
226+
Annotations: map[string]string{},
227+
},
228+
Spec: corev1.PodSpec{
229+
NodeSelector: map[string]string{},
230+
Tolerations: []corev1.Toleration{},
231+
ImagePullSecrets: []corev1.LocalObjectReference{},
232+
Containers: []corev1.Container{
233+
{
234+
Name: "redpanda",
235+
StartupProbe: &corev1.Probe{
236+
ProbeHandler: corev1.ProbeHandler{
237+
Exec: &corev1.ExecAction{
238+
Command: []string{"rpk cluster health"},
239+
},
240+
},
241+
FailureThreshold: 120,
242+
},
243+
},
244+
},
245+
},
246+
},
247+
},
248+
{
249+
Name: "volumes",
250+
Override: redpanda.PodTemplate{
251+
Spec: &applycorev1.PodSpecApplyConfiguration{
252+
Volumes: []applycorev1.VolumeApplyConfiguration{
253+
{
254+
Name: ptr.To("certs-volume-mount"),
255+
VolumeSourceApplyConfiguration: applycorev1.VolumeSourceApplyConfiguration{
256+
Secret: nil,
257+
EmptyDir: &applycorev1.EmptyDirVolumeSourceApplyConfiguration{},
258+
},
259+
},
260+
},
261+
},
262+
},
263+
Original: corev1.PodTemplateSpec{
264+
Spec: corev1.PodSpec{
265+
Volumes: []corev1.Volume{
266+
{
267+
Name: "certs-volume-mount",
268+
VolumeSource: corev1.VolumeSource{
269+
Secret: &corev1.SecretVolumeSource{
270+
SecretName: "some-secret",
271+
},
272+
},
273+
},
274+
},
275+
},
276+
},
277+
Expected: corev1.PodTemplateSpec{
278+
ObjectMeta: metav1.ObjectMeta{
279+
Labels: map[string]string{},
280+
Annotations: map[string]string{},
281+
},
282+
Spec: corev1.PodSpec{
283+
NodeSelector: map[string]string{},
284+
Tolerations: []corev1.Toleration{},
285+
ImagePullSecrets: []corev1.LocalObjectReference{},
286+
Volumes: []corev1.Volume{
287+
{
288+
Name: "certs-volume-mount",
289+
VolumeSource: corev1.VolumeSource{
290+
EmptyDir: &corev1.EmptyDirVolumeSource{},
291+
},
292+
},
293+
},
294+
},
295+
},
296+
},
297+
>>>>>>> 1f5dfc91 (charts/redpanda: allow overriding volumes)
191298
}
192299

193300
for _, tc := range cases {

charts/redpanda/templates/_helpers.go.tpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@
567567
{{- range $_ := (list 1) -}}
568568
{{- $_is_returning := false -}}
569569
{{- $_is_returning = true -}}
570-
{{- (dict "r" (merge (dict) $override $original)) | toJson -}}
570+
{{- (dict "r" (merge (dict) $override)) | toJson -}}
571571
{{- break -}}
572572
{{- end -}}
573573
{{- end -}}

charts/redpanda/testdata/template-cases.txtar

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,3 +1584,59 @@ statefulset:
15841584
enabled: false
15851585
pvcUnbinder:
15861586
enabled: false
1587+
1588+
-- jit-certificates --
1589+
# ASSERT-NO-ERROR
1590+
# ASSERT-FIELD-EQUALS ["apps/v1/StatefulSet", "default/redpanda", "{.spec.template.spec.volumes[?(@.name == \"redpanda-external-cert\")]}", {"name": "redpanda-external-cert", "emptyDir": {}}]
1591+
# This case demonstrates how to provide "Just In Time" certificates via an
1592+
# initContainer by using podTemplate to overwrite the auto generated volume.
1593+
tls:
1594+
certs:
1595+
external:
1596+
# Uncomment this block to disable the generation of cert-manager Certificates.
1597+
# secretRef:
1598+
# name: "set-to-disable-cert-manager"
1599+
1600+
# Controls whether or not the chart expects a ca.crt key to
1601+
# exist in the volume we create with the below init
1602+
# container. If set to false, the trustStore feature can
1603+
# continue to be used as is with the strategy.
1604+
caEnabled: true
1605+
1606+
statefulset:
1607+
podTemplate:
1608+
spec:
1609+
initContainers:
1610+
- name: cert-minter
1611+
image: debian:latest
1612+
command:
1613+
- bash
1614+
- -c
1615+
- 'cp -L -r /original/.'
1616+
# Provide the rest of your initContainer implementation here.
1617+
# This runs with the redpanda ServiceAccount.
1618+
volumeMounts:
1619+
# autoMountServiceAccountToken is set to false but we do mount it. To
1620+
# mount it to your init container, specify this volume:
1621+
- name: "kube-api-access"
1622+
readOnly: true
1623+
mountPath: "/var/run/secrets/kubernetes.io/serviceaccount"
1624+
# Mount the empty dir volume that will be used to pass certs through to redpanda.
1625+
- name: "redpanda-external-cert"
1626+
mountPath: "/certs"
1627+
# Unique to this example, we're just stealing the certs from the original.
1628+
- name: "3rd-party-certs"
1629+
mountPath: "/original"
1630+
1631+
volumes:
1632+
# Here's where the "magic" is. We're going to use podTemplate
1633+
# to override the standard certificate mount that the chart
1634+
# generates with an emptyDir. The initContainer will then
1635+
# populate it with a tls.crt, tls.key, and (optionally) ca.crt
1636+
# which makes it look like a standard TLS Secret mount.
1637+
- name: "redpanda-external-cert" # "{{ nameOverride }}-{{ cert }}-cert"
1638+
emptyDir: {}
1639+
# Unique to this example, we're just stealing the certs from the original.
1640+
- name: "3rd-party-certs"
1641+
secret:
1642+
secretName: "redpanda-external-cert"

0 commit comments

Comments
 (0)