Skip to content

Commit 6e79d28

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 115aa89 commit 6e79d28

File tree

5 files changed

+166
-2
lines changed

5 files changed

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

193295
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)