From fcf81487080d0c355cd3bd88b2748d48ef03e7c5 Mon Sep 17 00:00:00 2001 From: Dmitrii Golubtsov Date: Wed, 24 Jun 2026 21:22:35 +0300 Subject: [PATCH] Add custom names for orchestrator RBAC resources --- api/v1/perconaservermysql_types.go | 10 +++++- api/v1/perconaservermysql_types_test.go | 29 +++++++++++++++ cmd/example-gen/pkg/defaults/manual.go | 6 ++-- pkg/orchestrator/orchestrator.go | 2 +- pkg/orchestrator/orchestrator_test.go | 47 +++++++++++++++++++++++++ 5 files changed, 89 insertions(+), 5 deletions(-) diff --git a/api/v1/perconaservermysql_types.go b/api/v1/perconaservermysql_types.go index 202ca65d0..7f2b9ed87 100644 --- a/api/v1/perconaservermysql_types.go +++ b/api/v1/perconaservermysql_types.go @@ -1071,6 +1071,14 @@ func (cr *PerconaServerMySQL) DefaultSSLSecretName() string { return cr.Name + "-ssl" } +func (cr *PerconaServerMySQL) DefaultOrchestratorServiceAccountName() string { + if cr.Spec.CRVersion != "" && cr.CompareVersion("1.3.0") >= 0 { + return cr.Name + "-orchestrator" + } + + return "percona-server-mysql-operator-orchestrator" +} + // CheckNSetDefaults validates and sets default values for the PerconaServerMySQL custom resource. func (cr *PerconaServerMySQL) CheckNSetDefaults(_ context.Context, serverVersion *platform.ServerVersion) error { if len(cr.Spec.MySQL.ClusterType) == 0 { @@ -1272,7 +1280,7 @@ func (cr *PerconaServerMySQL) CheckNSetDefaults(_ context.Context, serverVersion } if cr.Spec.Orchestrator.ServiceAccountName == "" { - cr.Spec.Orchestrator.ServiceAccountName = "percona-server-mysql-operator-orchestrator" + cr.Spec.Orchestrator.ServiceAccountName = cr.DefaultOrchestratorServiceAccountName() } var err error diff --git a/api/v1/perconaservermysql_types_test.go b/api/v1/perconaservermysql_types_test.go index 62fba12ac..d8596ad3c 100644 --- a/api/v1/perconaservermysql_types_test.go +++ b/api/v1/perconaservermysql_types_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/percona/percona-server-mysql-operator/pkg/naming" ) @@ -849,3 +850,31 @@ func TestPiTREnabled(t *testing.T) { }) } } + +func TestDefaultOrchestratorServiceAccountName(t *testing.T) { + t.Run("empty crVersion", func(t *testing.T) { + cr := &PerconaServerMySQL{ + ObjectMeta: metav1.ObjectMeta{Name: "cluster-a"}, + } + + assert.Equal(t, "percona-server-mysql-operator-orchestrator", cr.DefaultOrchestratorServiceAccountName()) + }) + + t.Run("before 1.3.0", func(t *testing.T) { + cr := &PerconaServerMySQL{ + ObjectMeta: metav1.ObjectMeta{Name: "cluster-a"}, + Spec: PerconaServerMySQLSpec{CRVersion: "1.2.0"}, + } + + assert.Equal(t, "percona-server-mysql-operator-orchestrator", cr.DefaultOrchestratorServiceAccountName()) + }) + + t.Run("since 1.3.0", func(t *testing.T) { + cr := &PerconaServerMySQL{ + ObjectMeta: metav1.ObjectMeta{Name: "cluster-a"}, + Spec: PerconaServerMySQLSpec{CRVersion: "1.3.0"}, + } + + assert.Equal(t, "cluster-a-orchestrator", cr.DefaultOrchestratorServiceAccountName()) + }) +} diff --git a/cmd/example-gen/pkg/defaults/manual.go b/cmd/example-gen/pkg/defaults/manual.go index dabe579b2..87ffbc399 100644 --- a/cmd/example-gen/pkg/defaults/manual.go +++ b/cmd/example-gen/pkg/defaults/manual.go @@ -24,7 +24,7 @@ func ManualCluster(cr *apiv1.PerconaServerMySQL) { mysqlDefaults(&cr.Spec.MySQL) haproxyDefaults(cr.Spec.Proxy.HAProxy) routerDefaults(cr.Spec.Proxy.Router) - orchestratorDefaults(&cr.Spec.Orchestrator) + orchestratorDefaults(cr, &cr.Spec.Orchestrator) pmmDefaults(cr.Spec.PMM) toolkitDefaults(cr.Spec.Toolkit) backupDefaults(cr.Spec.Backup) @@ -107,12 +107,12 @@ func routerDefaults(spec *apiv1.MySQLRouterSpec) { } } -func orchestratorDefaults(spec *apiv1.OrchestratorSpec) { +func orchestratorDefaults(cr *apiv1.PerconaServerMySQL, spec *apiv1.OrchestratorSpec) { podSpecDefaults(&spec.PodSpec, ImageOrchestrator, resources("128M", "", "256M", ""), "", 30, envList("ORC_ENV", "VALUE"), envFromList("orc-env-secret")) spec.Enabled = false spec.Configuration = `{"FailMasterPromotionOnLagMinutes": 10}` - spec.ServiceAccountName = "percona-server-mysql-operator-orchestrator" + spec.ServiceAccountName = cr.DefaultOrchestratorServiceAccountName() spec.PodSecurityContext = &corev1.PodSecurityContext{ SupplementalGroups: []int64{1001}, } diff --git a/pkg/orchestrator/orchestrator.go b/pkg/orchestrator/orchestrator.go index 6af7d81b5..3f942022d 100644 --- a/pkg/orchestrator/orchestrator.go +++ b/pkg/orchestrator/orchestrator.go @@ -605,7 +605,7 @@ func ConfigMapData(cr *apiv1.PerconaServerMySQL) (string, error) { func RBAC(cr *apiv1.PerconaServerMySQL) (*rbacv1.Role, *rbacv1.RoleBinding, *corev1.ServiceAccount) { meta := metav1.ObjectMeta{ Namespace: cr.Namespace, - Name: "percona-server-mysql-operator-orchestrator", + Name: cr.Spec.Orchestrator.ServiceAccountName, Labels: cr.GlobalLabels(), Annotations: cr.GlobalAnnotations(), } diff --git a/pkg/orchestrator/orchestrator_test.go b/pkg/orchestrator/orchestrator_test.go index 87ab09954..972584193 100644 --- a/pkg/orchestrator/orchestrator_test.go +++ b/pkg/orchestrator/orchestrator_test.go @@ -136,6 +136,53 @@ func TestStatefulSet(t *testing.T) { assert.Equal(t, serviceAccountName, sts.Spec.Template.Spec.ServiceAccountName) }) + t.Run("RBAC", func(t *testing.T) { + cluster := cr.DeepCopy() + cluster.Spec.CRVersion = "1.2.0" + cluster.Spec.Orchestrator.ServiceAccountName = "" + + if err := cluster.CheckNSetDefaults(t.Context(), &platform.ServerVersion{ + Platform: platform.PlatformKubernetes, + }); err != nil { + t.Fatal(err) + } + + role, binding, sa := RBAC(cluster) + const legacyDefaultName = "percona-server-mysql-operator-orchestrator" + assert.Equal(t, legacyDefaultName, sa.Name) + assert.Equal(t, legacyDefaultName, role.Name) + assert.Equal(t, legacyDefaultName, binding.Name) + assert.Equal(t, legacyDefaultName, binding.Subjects[0].Name) + assert.Equal(t, legacyDefaultName, binding.RoleRef.Name) + + cluster.Spec.CRVersion = "1.3.0" + cluster.Spec.Orchestrator.ServiceAccountName = "" + + if err := cluster.CheckNSetDefaults(t.Context(), &platform.ServerVersion{ + Platform: platform.PlatformKubernetes, + }); err != nil { + t.Fatal(err) + } + + role, binding, sa = RBAC(cluster) + const modernDefaultName = "cluster-orchestrator" + assert.Equal(t, modernDefaultName, sa.Name) + assert.Equal(t, modernDefaultName, role.Name) + assert.Equal(t, modernDefaultName, binding.Name) + assert.Equal(t, modernDefaultName, binding.Subjects[0].Name) + assert.Equal(t, modernDefaultName, binding.RoleRef.Name) + + const customName = "custom-orchestrator" + cluster.Spec.Orchestrator.ServiceAccountName = customName + + role, binding, sa = RBAC(cluster) + assert.Equal(t, customName, sa.Name) + assert.Equal(t, customName, role.Name) + assert.Equal(t, customName, binding.Name) + assert.Equal(t, customName, binding.Subjects[0].Name) + assert.Equal(t, customName, binding.RoleRef.Name) + }) + t.Run("tolerations", func(t *testing.T) { cluster := cr.DeepCopy() sts := StatefulSet(cluster, initImage, configHash, tlsHash)