Skip to content

Commit 82e1f6b

Browse files
committed
redpanda: correct Role and ClusterRole naming
In 5d72f8a, the Names for `Role`s generated by the chart were mistakenly changed from `Fullname` to `Name`. This regression went by unnoticed as we did not have any tests that installed multiple instances of the chart into a single namespace. This commit corrects the regression and updates the naming of `ClusterRole`s to include the release namespace. This allows: - Installing multiple instances of the chart into a single namespace. - Installing multiple instances of the chart with the same release name into different namespaces. (cherry picked from commit d7ad813)
1 parent ea8b8c6 commit 82e1f6b

File tree

12 files changed

+733
-616
lines changed

12 files changed

+733
-616
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: Corrected naming of `Role`s to use Fullname instead of Name, which ensures they are unique within their namespace.
4+
time: 2025-06-19T11:33:17.161135-04:00
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: Updated naming of `ClusterRole`s to include the release namespace. This ensures that they are unique per release and permits installing the chart with the same name across different namespaces.
4+
time: 2025-06-19T11:35:26.699507-04:00

charts/redpanda/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ of `enterprise.license` and `enterprise.licenseSecretRef`, respectively.
133133
now respect `listeners.kafka.tls.trustStore`, when provided.
134134
See also [helm-chart 1573 issue](https://github.com/redpanda-data/helm-charts/issues/1573).
135135

136+
* Corrected naming of `Role`s to use Fullname instead of Name, which ensures they are unique within their namespace.
137+
* Updated naming of `ClusterRole`s to include the release namespace. This ensures that they are unique per release and permits installing the chart with the same name across different namespaces.
136138

137139
## [v25.1.1-beta3](https://github.com/redpanda-data/redpanda-operator/releases/tag/charts%2Fredpanda%2Fv25.1.1-beta3) - 2025-05-06
138140
### Added

charts/redpanda/chart_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import (
4949
"github.com/redpanda-data/redpanda-operator/pkg/helm"
5050
"github.com/redpanda-data/redpanda-operator/pkg/helm/helmtest"
5151
"github.com/redpanda-data/redpanda-operator/pkg/kube"
52+
"github.com/redpanda-data/redpanda-operator/pkg/kube/kubetest"
5253
"github.com/redpanda-data/redpanda-operator/pkg/testutil"
5354
"github.com/redpanda-data/redpanda-operator/pkg/tlsgeneration"
5455
"github.com/redpanda-data/redpanda-operator/pkg/valuesutil"
@@ -1167,3 +1168,76 @@ func TestGoHelmEquivalence(t *testing.T) {
11671168
})
11681169
}
11691170
}
1171+
1172+
// TestMultiNamespaceInstall verifies that:
1173+
// - Multiple instances of the redpanda chart with different names may be installed in the same instance.
1174+
// - Multiple instances of the redpanda chart with the same name may be installed in different namespaces.
1175+
func TestMultiNamespaceInstall(t *testing.T) {
1176+
ctl := kubetest.NewEnv(t)
1177+
client, err := helm.New(helm.Options{
1178+
KubeConfig: ctl.RestConfig(),
1179+
})
1180+
require.NoError(t, err)
1181+
1182+
values := redpanda.PartialValues{
1183+
// Disable NodePort services to avoid port conflicts.
1184+
External: &redpanda.PartialExternalConfig{
1185+
Type: ptr.To(corev1.ServiceTypeLoadBalancer),
1186+
},
1187+
// Disable cert-manager integration so we don't have to
1188+
// install their CRDs.
1189+
TLS: &redpanda.PartialTLS{
1190+
Certs: redpanda.PartialTLSCertMap{
1191+
"default": redpanda.PartialTLSCert{
1192+
SecretRef: &corev1.LocalObjectReference{
1193+
Name: "default",
1194+
},
1195+
},
1196+
"external": redpanda.PartialTLSCert{
1197+
SecretRef: &corev1.LocalObjectReference{
1198+
Name: "default",
1199+
},
1200+
},
1201+
},
1202+
},
1203+
}
1204+
1205+
for i := 0; i < 2; i++ {
1206+
namespace := fmt.Sprintf("namespace-%d", i)
1207+
1208+
require.NoError(t, ctl.Apply(t.Context(), &corev1.Namespace{
1209+
ObjectMeta: metav1.ObjectMeta{Name: namespace},
1210+
}))
1211+
1212+
for j := 0; j < 2; j++ {
1213+
_, err := client.Install(t.Context(), ".", helm.InstallOptions{
1214+
Name: fmt.Sprintf("redpanda-%d", j),
1215+
Namespace: namespace,
1216+
// Disable all forms of waits / checks. This isn't an actual
1217+
// cluster, were just verifying that the API server and helm
1218+
// don't report naming conflicts.
1219+
NoHooks: true,
1220+
NoWait: true,
1221+
NoWaitForJobs: true,
1222+
Timeout: ptr.To(5 * time.Second),
1223+
Values: values,
1224+
})
1225+
require.NoError(t, err)
1226+
}
1227+
1228+
// One final check to show that conflicting names will result in an error.
1229+
_, err := client.Install(t.Context(), ".", helm.InstallOptions{
1230+
Name: "redpanda-0",
1231+
Namespace: namespace,
1232+
// Disable all forms of waits / checks. This isn't an actual
1233+
// cluster, were just verifying that the API server and helm
1234+
// don't report naming conflicts.
1235+
NoHooks: true,
1236+
NoWait: true,
1237+
NoWaitForJobs: true,
1238+
Timeout: ptr.To(5 * time.Second),
1239+
Values: values,
1240+
})
1241+
require.Error(t, err)
1242+
}
1243+
}

charts/redpanda/helpers.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,22 @@ func ChartLabel(dot *helmette.Dot) string {
4646
return cleanForK8s(strings.ReplaceAll(fmt.Sprintf("%s-%s", dot.Chart.Name, dot.Chart.Version), "+", "_"))
4747
}
4848

49-
// Expand the name of the chart
49+
// Name returns the name of this chart as specified in Chart.yaml, unless
50+
// explicitly overridden.
51+
// Name is effectively static and should not be used for naming of resources.
52+
// Name is truncated at 63 characters to satisfy Kubernetes field limits
53+
// and DNS limits.
5054
func Name(dot *helmette.Dot) string {
5155
if override, ok := dot.Values["nameOverride"].(string); ok && override != "" {
5256
return cleanForK8s(override)
5357
}
5458
return cleanForK8s(dot.Chart.Name)
5559
}
5660

57-
// Create a default fully qualified app name.
58-
// We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
61+
// Fullname returns the name of this helm release, unless explicitly
62+
// overridden.
63+
// Fullname is truncated at 63 characters to satisfy Kubernetes field limits
64+
// and DNS limits.
5965
func Fullname(dot *helmette.Dot) string {
6066
if override, ok := dot.Values["fullnameOverride"].(string); ok && override != "" {
6167
return cleanForK8s(override)

charts/redpanda/rbac.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func Roles(dot *helmette.Dot) []*rbacv1.Role {
3939
role := helmette.FromYaml[rbacv1.Role](dot.Files.Get(file))
4040

4141
// Populated all chart values on the loaded static Role.
42-
role.ObjectMeta.Name = fmt.Sprintf("%s-%s", Name(dot), role.ObjectMeta.Name)
42+
role.ObjectMeta.Name = fmt.Sprintf("%s-%s", Fullname(dot), role.ObjectMeta.Name)
4343
role.ObjectMeta.Namespace = dot.Release.Namespace
4444
role.ObjectMeta.Labels = FullLabels(dot)
4545
role.ObjectMeta.Annotations = helmette.Merge(
@@ -73,7 +73,10 @@ func ClusterRoles(dot *helmette.Dot) []*rbacv1.ClusterRole {
7373
role := helmette.FromYaml[rbacv1.ClusterRole](dot.Files.Get(file))
7474

7575
// Populated all chart values on the loaded static Role.
76-
role.ObjectMeta.Name = fmt.Sprintf("%s-%s", Fullname(dot), role.ObjectMeta.Name)
76+
// For ClusterScoped resources, we include the Namespace to permit
77+
// installing multiple releases with the same names into the same
78+
// cluster.
79+
role.ObjectMeta.Name = cleanForK8s(fmt.Sprintf("%s-%s-%s", Fullname(dot), dot.Release.Namespace, role.ObjectMeta.Name))
7780
role.ObjectMeta.Labels = FullLabels(dot)
7881
role.ObjectMeta.Annotations = helmette.Merge(
7982
map[string]string{},

charts/redpanda/templates/_helpers.go.tpl

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
{{- $dot := (index .a 0) -}}
1515
{{- range $_ := (list 1) -}}
1616
{{- $_is_returning := false -}}
17-
{{- $_51_override_1_ok_2 := (get (fromJson (include "_shims.typetest" (dict "a" (list "string" (index $dot.Values "nameOverride") "")))) "r") -}}
18-
{{- $override_1 := (index $_51_override_1_ok_2 0) -}}
19-
{{- $ok_2 := (index $_51_override_1_ok_2 1) -}}
17+
{{- $_55_override_1_ok_2 := (get (fromJson (include "_shims.typetest" (dict "a" (list "string" (index $dot.Values "nameOverride") "")))) "r") -}}
18+
{{- $override_1 := (index $_55_override_1_ok_2 0) -}}
19+
{{- $ok_2 := (index $_55_override_1_ok_2 1) -}}
2020
{{- if (and $ok_2 (ne $override_1 "")) -}}
2121
{{- $_is_returning = true -}}
2222
{{- (dict "r" (get (fromJson (include "redpanda.cleanForK8s" (dict "a" (list $override_1)))) "r")) | toJson -}}
@@ -32,9 +32,9 @@
3232
{{- $dot := (index .a 0) -}}
3333
{{- range $_ := (list 1) -}}
3434
{{- $_is_returning := false -}}
35-
{{- $_61_override_3_ok_4 := (get (fromJson (include "_shims.typetest" (dict "a" (list "string" (index $dot.Values "fullnameOverride") "")))) "r") -}}
36-
{{- $override_3 := (index $_61_override_3_ok_4 0) -}}
37-
{{- $ok_4 := (index $_61_override_3_ok_4 1) -}}
35+
{{- $_67_override_3_ok_4 := (get (fromJson (include "_shims.typetest" (dict "a" (list "string" (index $dot.Values "fullnameOverride") "")))) "r") -}}
36+
{{- $override_3 := (index $_67_override_3_ok_4 0) -}}
37+
{{- $ok_4 := (index $_67_override_3_ok_4 1) -}}
3838
{{- if (and $ok_4 (ne $override_3 "")) -}}
3939
{{- $_is_returning = true -}}
4040
{{- (dict "r" (get (fromJson (include "redpanda.cleanForK8s" (dict "a" (list $override_3)))) "r")) | toJson -}}
@@ -375,9 +375,9 @@
375375
{{- range $_ := (list 1) -}}
376376
{{- $_is_returning := false -}}
377377
{{- $version := (trimPrefix "v" (get (fromJson (include "redpanda.Tag" (dict "a" (list $dot)))) "r")) -}}
378-
{{- $_356_result_err := (list (semverCompare $constraint $version) nil) -}}
379-
{{- $result := (index $_356_result_err 0) -}}
380-
{{- $err := (index $_356_result_err 1) -}}
378+
{{- $_362_result_err := (list (semverCompare $constraint $version) nil) -}}
379+
{{- $result := (index $_362_result_err 0) -}}
380+
{{- $err := (index $_362_result_err 1) -}}
381381
{{- if (ne (toJson $err) "null") -}}
382382
{{- $_ := (fail $err) -}}
383383
{{- end -}}
@@ -498,9 +498,9 @@
498498
{{- $originalKeys := (dict) -}}
499499
{{- $overrideByKey := (dict) -}}
500500
{{- range $_, $el := $override -}}
501-
{{- $_493_key_ok := (get (fromJson (include "_shims.get" (dict "a" (list $el $mergeKey)))) "r") -}}
502-
{{- $key := (index $_493_key_ok 0) -}}
503-
{{- $ok := (index $_493_key_ok 1) -}}
501+
{{- $_499_key_ok := (get (fromJson (include "_shims.get" (dict "a" (list $el $mergeKey)))) "r") -}}
502+
{{- $key := (index $_499_key_ok 0) -}}
503+
{{- $ok := (index $_499_key_ok 1) -}}
504504
{{- if (not $ok) -}}
505505
{{- continue -}}
506506
{{- end -}}
@@ -511,13 +511,13 @@
511511
{{- end -}}
512512
{{- $merged := (coalesce nil) -}}
513513
{{- range $_, $el := $original -}}
514-
{{- $_505_key__ := (get (fromJson (include "_shims.get" (dict "a" (list $el $mergeKey)))) "r") -}}
515-
{{- $key := (index $_505_key__ 0) -}}
516-
{{- $_ := (index $_505_key__ 1) -}}
514+
{{- $_511_key__ := (get (fromJson (include "_shims.get" (dict "a" (list $el $mergeKey)))) "r") -}}
515+
{{- $key := (index $_511_key__ 0) -}}
516+
{{- $_ := (index $_511_key__ 1) -}}
517517
{{- $_ := (set $originalKeys $key true) -}}
518-
{{- $_507_elOverride_7_ok_8 := (get (fromJson (include "_shims.dicttest" (dict "a" (list $overrideByKey $key (coalesce nil))))) "r") -}}
519-
{{- $elOverride_7 := (index $_507_elOverride_7_ok_8 0) -}}
520-
{{- $ok_8 := (index $_507_elOverride_7_ok_8 1) -}}
518+
{{- $_513_elOverride_7_ok_8 := (get (fromJson (include "_shims.dicttest" (dict "a" (list $overrideByKey $key (coalesce nil))))) "r") -}}
519+
{{- $elOverride_7 := (index $_513_elOverride_7_ok_8 0) -}}
520+
{{- $ok_8 := (index $_513_elOverride_7_ok_8 1) -}}
521521
{{- if $ok_8 -}}
522522
{{- $merged = (concat (default (list) $merged) (list (get (fromJson (include $mergeFunc (dict "a" (list $el $elOverride_7)))) "r"))) -}}
523523
{{- else -}}
@@ -528,15 +528,15 @@
528528
{{- break -}}
529529
{{- end -}}
530530
{{- range $_, $el := $override -}}
531-
{{- $_517_key_ok := (get (fromJson (include "_shims.get" (dict "a" (list $el $mergeKey)))) "r") -}}
532-
{{- $key := (index $_517_key_ok 0) -}}
533-
{{- $ok := (index $_517_key_ok 1) -}}
531+
{{- $_523_key_ok := (get (fromJson (include "_shims.get" (dict "a" (list $el $mergeKey)))) "r") -}}
532+
{{- $key := (index $_523_key_ok 0) -}}
533+
{{- $ok := (index $_523_key_ok 1) -}}
534534
{{- if (not $ok) -}}
535535
{{- continue -}}
536536
{{- end -}}
537-
{{- $_522___ok_9 := (get (fromJson (include "_shims.dicttest" (dict "a" (list $originalKeys $key false)))) "r") -}}
538-
{{- $_ := (index $_522___ok_9 0) -}}
539-
{{- $ok_9 := (index $_522___ok_9 1) -}}
537+
{{- $_528___ok_9 := (get (fromJson (include "_shims.dicttest" (dict "a" (list $originalKeys $key false)))) "r") -}}
538+
{{- $_ := (index $_528___ok_9 0) -}}
539+
{{- $ok_9 := (index $_528___ok_9 1) -}}
540540
{{- if $ok_9 -}}
541541
{{- continue -}}
542542
{{- end -}}

charts/redpanda/templates/_rbac.go.tpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
{{- continue -}}
1313
{{- end -}}
1414
{{- $role := (get (fromJson (include "_shims.fromYaml" (dict "a" (list ($dot.Files.Get $file))))) "r") -}}
15-
{{- $_ := (set $role.metadata "name" (printf "%s-%s" (get (fromJson (include "redpanda.Name" (dict "a" (list $dot)))) "r") $role.metadata.name)) -}}
15+
{{- $_ := (set $role.metadata "name" (printf "%s-%s" (get (fromJson (include "redpanda.Fullname" (dict "a" (list $dot)))) "r") $role.metadata.name)) -}}
1616
{{- $_ := (set $role.metadata "namespace" $dot.Release.Namespace) -}}
1717
{{- $_ := (set $role.metadata "labels" (get (fromJson (include "redpanda.FullLabels" (dict "a" (list $dot)))) "r")) -}}
1818
{{- $_ := (set $role.metadata "annotations" (merge (dict) (dict) $values.serviceAccount.annotations $values.rbac.annotations)) -}}
@@ -39,7 +39,7 @@
3939
{{- continue -}}
4040
{{- end -}}
4141
{{- $role := (get (fromJson (include "_shims.fromYaml" (dict "a" (list ($dot.Files.Get $file))))) "r") -}}
42-
{{- $_ := (set $role.metadata "name" (printf "%s-%s" (get (fromJson (include "redpanda.Fullname" (dict "a" (list $dot)))) "r") $role.metadata.name)) -}}
42+
{{- $_ := (set $role.metadata "name" (get (fromJson (include "redpanda.cleanForK8s" (dict "a" (list (printf "%s-%s-%s" (get (fromJson (include "redpanda.Fullname" (dict "a" (list $dot)))) "r") $dot.Release.Namespace $role.metadata.name))))) "r")) -}}
4343
{{- $_ := (set $role.metadata "labels" (get (fromJson (include "redpanda.FullLabels" (dict "a" (list $dot)))) "r")) -}}
4444
{{- $_ := (set $role.metadata "annotations" (merge (dict) (dict) $values.serviceAccount.annotations $values.rbac.annotations)) -}}
4545
{{- $clusterRoles = (concat (default (list) $clusterRoles) (list $role)) -}}

0 commit comments

Comments
 (0)