diff --git a/controllers/rabbitmqcluster_controller_test.go b/controllers/rabbitmqcluster_controller_test.go index 087670b8e..499396499 100644 --- a/controllers/rabbitmqcluster_controller_test.go +++ b/controllers/rabbitmqcluster_controller_test.go @@ -175,6 +175,33 @@ var _ = Describe("RabbitmqClusterController", func() { }) }) + Context("default user from additionalConfig", func() { + BeforeEach(func() { + cluster = &rabbitmqv1beta1.RabbitmqCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "rabbitmq-default-user-from-config", + Namespace: defaultNamespace, + }, + Spec: rabbitmqv1beta1.RabbitmqClusterSpec{ + Rabbitmq: rabbitmqv1beta1.RabbitmqClusterConfigurationSpec{ + AdditionalConfig: "default_user = my-user\ndefault_pass = my-password", + }, + }, + } + + Expect(client.Create(ctx, cluster)).To(Succeed()) + waitForClusterCreation(ctx, cluster, client) + }) + + It("should use the credentials from additionalConfig in the default-user secret", func() { + secretName := cluster.ChildResourceName("default-user") + secret, err := clientSet.CoreV1().Secrets(cluster.Namespace).Get(ctx, secretName, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + Expect(string(secret.Data["username"])).To(Equal("my-user")) + Expect(string(secret.Data["password"])).To(Equal("my-password")) + }) + }) + Context("Annotations set on the instance", func() { BeforeEach(func() { cluster = &rabbitmqv1beta1.RabbitmqCluster{ diff --git a/internal/resource/default_user_secret.go b/internal/resource/default_user_secret.go index 0e2f60185..4f5aa575a 100644 --- a/internal/resource/default_user_secret.go +++ b/internal/resource/default_user_secret.go @@ -22,8 +22,9 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/rabbitmq/cluster-operator/v2/api/v1beta1" "slices" + + "github.com/rabbitmq/cluster-operator/v2/api/v1beta1" ) const ( @@ -42,14 +43,36 @@ func (builder *RabbitmqResourceBuilder) DefaultUserSecret() *DefaultUserSecretBu } func (builder *DefaultUserSecretBuilder) Build() (client.Object, error) { - username, err := generateUsername(24) - if err != nil { - return nil, err + var username, password string + additionalConfig := builder.Instance.Spec.Rabbitmq.AdditionalConfig + if additionalConfig != "" { + cfg, err := ini.Load([]byte(additionalConfig)) + if err != nil { + return nil, fmt.Errorf("failed to parse additionalConfig: %w", err) + } + defaultSection := cfg.Section("") + if defaultSection.HasKey("default_user") { + username = defaultSection.Key("default_user").String() + } + if defaultSection.HasKey("default_pass") { + password = defaultSection.Key("default_pass").String() + } } - password, err := randomEncodedString(24) - if err != nil { - return nil, err + if username == "" { + generatedUsername, err := generateUsername(24) + if err != nil { + return nil, err + } + username = generatedUsername + } + + if password == "" { + generatedPassword, err := randomEncodedString(24) + if err != nil { + return nil, err + } + password = generatedPassword } defaultUserConf, err := generateDefaultUserConf(username, password) diff --git a/internal/resource/default_user_secret_test.go b/internal/resource/default_user_secret_test.go index bca19a7f5..835bfbc79 100644 --- a/internal/resource/default_user_secret_test.go +++ b/internal/resource/default_user_secret_test.go @@ -12,6 +12,7 @@ package resource_test import ( b64 "encoding/base64" "fmt" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" rabbitmqv1beta1 "github.com/rabbitmq/cluster-operator/v2/api/v1beta1" @@ -138,6 +139,24 @@ var _ = Describe("DefaultUserSecret", func() { }) }) + Context("Build with additionalConfig", func() { + It("should use the default_user and default_pass from additionalConfig", func() { + instance.Spec.Rabbitmq.AdditionalConfig = "default_user = my-user\ndefault_pass = my-password" + obj, err := defaultUserSecretBuilder.Build() + Expect(err).NotTo(HaveOccurred()) + secret = obj.(*corev1.Secret) + Expect(string(secret.Data["username"])).To(Equal("my-user")) + Expect(string(secret.Data["password"])).To(Equal("my-password")) + + defaultUserConf, ok := secret.Data["default_user.conf"] + Expect(ok).To(BeTrue(), "Failed to find a key \"default_user.conf\" in the generated Secret") + cfg, err := ini.Load(defaultUserConf) + Expect(err).NotTo(HaveOccurred()) + Expect(cfg.Section("").Key("default_user").Value()).To(Equal("my-user")) + Expect(cfg.Section("").Key("default_pass").Value()).To(Equal("my-password")) + }) + }) + Context("when MQTT, STOMP, streams, WebMQTT, and WebSTOMP are enabled", func() { It("adds the MQTT, STOMP, stream, WebMQTT, and WebSTOMP ports to the user secret", func() { var port []byte