Skip to content

Commit 7f6fd46

Browse files
committed
Fix: Use additionalConfig for default user creds
The RabbitMQ operator now respects `default_user` and `default_pass` values provided in the `additionalConfig` field of the `RabbitmqCluster` manifest when creating the default user secret. Previously, the operator would generate random credentials, leading to mismatches and confusion. This change modifies the `Build` function in `internal/resource/default_user_secret.go` to parse the `additionalConfig` string. If `default_user` and `default_pass` are present, their values are used. Otherwise, random credentials are generated, maintaining backward compatibility. Unit tests in `internal/resource/default_user_secret_test.go` and integration tests in `controllers/rabbitmqcluster_controller_test.go` have been added to verify this behavior.
1 parent 535a681 commit 7f6fd46

File tree

3 files changed

+76
-7
lines changed

3 files changed

+76
-7
lines changed

controllers/rabbitmqcluster_controller_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,33 @@ var _ = Describe("RabbitmqClusterController", func() {
175175
})
176176
})
177177

178+
Context("default user from additionalConfig", func() {
179+
BeforeEach(func() {
180+
cluster = &rabbitmqv1beta1.RabbitmqCluster{
181+
ObjectMeta: metav1.ObjectMeta{
182+
Name: "rabbitmq-default-user-from-config",
183+
Namespace: defaultNamespace,
184+
},
185+
Spec: rabbitmqv1beta1.RabbitmqClusterSpec{
186+
Rabbitmq: rabbitmqv1beta1.RabbitmqClusterConfigurationSpec{
187+
AdditionalConfig: "default_user = my-user\ndefault_pass = my-password",
188+
},
189+
},
190+
}
191+
192+
Expect(client.Create(ctx, cluster)).To(Succeed())
193+
waitForClusterCreation(ctx, cluster, client)
194+
})
195+
196+
It("should use the credentials from additionalConfig in the default-user secret", func() {
197+
secretName := cluster.ChildResourceName("default-user")
198+
secret, err := clientSet.CoreV1().Secrets(cluster.Namespace).Get(ctx, secretName, metav1.GetOptions{})
199+
Expect(err).NotTo(HaveOccurred())
200+
Expect(string(secret.Data["username"])).To(Equal("my-user"))
201+
Expect(string(secret.Data["password"])).To(Equal("my-password"))
202+
})
203+
})
204+
178205
Context("Annotations set on the instance", func() {
179206
BeforeEach(func() {
180207
cluster = &rabbitmqv1beta1.RabbitmqCluster{

internal/resource/default_user_secret.go

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ import (
2222
corev1 "k8s.io/api/core/v1"
2323
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2424

25-
"github.com/rabbitmq/cluster-operator/v2/api/v1beta1"
2625
"slices"
26+
27+
"github.com/rabbitmq/cluster-operator/v2/api/v1beta1"
2728
)
2829

2930
const (
@@ -42,14 +43,36 @@ func (builder *RabbitmqResourceBuilder) DefaultUserSecret() *DefaultUserSecretBu
4243
}
4344

4445
func (builder *DefaultUserSecretBuilder) Build() (client.Object, error) {
45-
username, err := generateUsername(24)
46-
if err != nil {
47-
return nil, err
46+
var username, password string
47+
additionalConfig := builder.Instance.Spec.Rabbitmq.AdditionalConfig
48+
if additionalConfig != "" {
49+
cfg, err := ini.Load([]byte(additionalConfig))
50+
if err != nil {
51+
return nil, fmt.Errorf("failed to parse additionalConfig: %w", err)
52+
}
53+
defaultSection := cfg.Section("")
54+
if defaultSection.HasKey("default_user") {
55+
username = defaultSection.Key("default_user").String()
56+
}
57+
if defaultSection.HasKey("default_pass") {
58+
password = defaultSection.Key("default_pass").String()
59+
}
4860
}
4961

50-
password, err := randomEncodedString(24)
51-
if err != nil {
52-
return nil, err
62+
if username == "" {
63+
generatedUsername, err := generateUsername(24)
64+
if err != nil {
65+
return nil, err
66+
}
67+
username = generatedUsername
68+
}
69+
70+
if password == "" {
71+
generatedPassword, err := randomEncodedString(24)
72+
if err != nil {
73+
return nil, err
74+
}
75+
password = generatedPassword
5376
}
5477

5578
defaultUserConf, err := generateDefaultUserConf(username, password)

internal/resource/default_user_secret_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ package resource_test
1212
import (
1313
b64 "encoding/base64"
1414
"fmt"
15+
1516
. "github.com/onsi/ginkgo/v2"
1617
. "github.com/onsi/gomega"
1718
rabbitmqv1beta1 "github.com/rabbitmq/cluster-operator/v2/api/v1beta1"
@@ -138,6 +139,24 @@ var _ = Describe("DefaultUserSecret", func() {
138139
})
139140
})
140141

142+
Context("Build with additionalConfig", func() {
143+
It("should use the default_user and default_pass from additionalConfig", func() {
144+
instance.Spec.Rabbitmq.AdditionalConfig = "default_user = my-user\ndefault_pass = my-password"
145+
obj, err := defaultUserSecretBuilder.Build()
146+
Expect(err).NotTo(HaveOccurred())
147+
secret = obj.(*corev1.Secret)
148+
Expect(string(secret.Data["username"])).To(Equal("my-user"))
149+
Expect(string(secret.Data["password"])).To(Equal("my-password"))
150+
151+
defaultUserConf, ok := secret.Data["default_user.conf"]
152+
Expect(ok).To(BeTrue(), "Failed to find a key \"default_user.conf\" in the generated Secret")
153+
cfg, err := ini.Load(defaultUserConf)
154+
Expect(err).NotTo(HaveOccurred())
155+
Expect(cfg.Section("").Key("default_user").Value()).To(Equal("my-user"))
156+
Expect(cfg.Section("").Key("default_pass").Value()).To(Equal("my-password"))
157+
})
158+
})
159+
141160
Context("when MQTT, STOMP, streams, WebMQTT, and WebSTOMP are enabled", func() {
142161
It("adds the MQTT, STOMP, stream, WebMQTT, and WebSTOMP ports to the user secret", func() {
143162
var port []byte

0 commit comments

Comments
 (0)