Skip to content

Commit d0bba95

Browse files
lmicciniclaude
andcommitted
Implement messaging bus configuration with migration from deprecated fields
Add top-level MessagingBus and NotificationsBus configuration to OpenstackControlPlane API to replace service-specific RabbitMQ settings. This provides a centralized way to configure messaging infrastructure while maintaining backward compatibility. API changes: - Add MessagingBus field for RPC communication configuration (username, vhost, cluster) - Add NotificationsBus field for notifications configuration - Deprecate NotificationsBusInstance in favor of NotificationsBus.Cluster - Remove default values for deprecated rabbitMqClusterName fields across all service CRDs to enable proper migration Webhook changes: - Update ValidateCreate and ValidateUpdate to return warnings in addition to errors - Add centralized validation for deprecated fields with warning messages - Add ValidateMessagingBusConfig validation - Update service validation calls to capture warnings from downstream operators Controller changes: - Add migration logic to automatically populate NotificationsBus.Cluster from deprecated NotificationsBusInstance field during reconciliation - Migration occurs before service reconciliation to ensure services inherit migrated values Service integration: - Update all service templates (barbican, cinder, designate, glance, heat, ironic, keystone, manila, neutron, nova, octavia, swift, telemetry, watcher) to support new messaging bus fields - Services inherit top-level configuration but can override with service-specific settings Testing: - Add comprehensive migration tests for deprecated field handling - Add RabbitMQ cascading configuration tests - Update functional tests for new configuration structure Additional fixes: - Fix pin-bundle-images.sh to handle operators with replace directives by forcing quay.io for replaced operators and adding fallback logic when bundles are not available in custom registries Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent dd4c370 commit d0bba95

74 files changed

Lines changed: 5117 additions & 397 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/bases/core.openstack.org_openstackcontrolplanes.yaml

Lines changed: 449 additions & 28 deletions
Large diffs are not rendered by default.

api/core/v1beta1/openstackcontrolplane_types.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,27 @@ type OpenStackControlPlaneSpec struct {
127127
// Rabbitmq - Parameters related to the Rabbitmq service
128128
Rabbitmq RabbitmqSection `json:"rabbitmq,omitempty"`
129129

130+
// +kubebuilder:validation:Optional
131+
// MessagingBus configuration (username, vhost, and cluster) for RPC communication.
132+
// This is the default configuration for all services.
133+
// Individual services can override by setting their own Template.MessagingBus.
134+
MessagingBus *rabbitmqv1.RabbitMqConfig `json:"messagingBus,omitempty"`
135+
130136
// +kubebuilder:validation:Optional
131137
// NotificationsBusInstance - the name of RabbitMQ Cluster CR to select a Messaging
132138
// Bus Service instance used by all services that produce or consume notifications.
133139
// Avoid colocating it with RabbitMQ services used for PRC.
134140
// That instance will be pushed down for services, unless overriden in templates.
141+
// Deprecated: Use NotificationsBus.Cluster instead
135142
NotificationsBusInstance *string `json:"notificationsBusInstance,omitempty"`
136143

144+
// +kubebuilder:validation:Optional
145+
// NotificationsBus configuration (username, vhost, and cluster) for notifications.
146+
// This is the default configuration for all services.
147+
// Individual services can override by setting their own Template.NotificationsBus.
148+
// Avoid colocating with MessagingBus used for RPC.
149+
NotificationsBus *rabbitmqv1.RabbitMqConfig `json:"notificationsBus,omitempty"`
150+
137151
// +kubebuilder:validation:Optional
138152
// +operator-sdk:csv:customresourcedefinitions:type=spec
139153
// Memcached - Parameters related to the Memcached service

api/core/v1beta1/openstackcontrolplane_webhook.go

Lines changed: 225 additions & 26 deletions
Large diffs are not rendered by default.
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package v1beta1
2+
3+
import (
4+
. "github.com/onsi/ginkgo/v2"
5+
. "github.com/onsi/gomega"
6+
rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1"
7+
"k8s.io/apimachinery/pkg/util/validation/field"
8+
)
9+
10+
var _ = Describe("OpenStackControlPlane Webhook", func() {
11+
12+
Context("ValidateMessagingBusConfig", func() {
13+
var instance *OpenStackControlPlane
14+
var basePath *field.Path
15+
16+
BeforeEach(func() {
17+
instance = &OpenStackControlPlane{
18+
Spec: OpenStackControlPlaneSpec{},
19+
}
20+
basePath = field.NewPath("spec")
21+
})
22+
23+
It("should allow only Cluster field in messagingBus", func() {
24+
instance.Spec.MessagingBus = &rabbitmqv1.RabbitMqConfig{
25+
Cluster: "rabbitmq",
26+
}
27+
28+
errs := instance.ValidateMessagingBusConfig(basePath)
29+
Expect(errs).To(BeEmpty())
30+
})
31+
32+
It("should allow Cluster and Vhost fields in messagingBus", func() {
33+
instance.Spec.MessagingBus = &rabbitmqv1.RabbitMqConfig{
34+
Cluster: "rabbitmq",
35+
Vhost: "/openstack",
36+
}
37+
38+
errs := instance.ValidateMessagingBusConfig(basePath)
39+
Expect(errs).To(BeEmpty())
40+
})
41+
42+
It("should reject User field in messagingBus", func() {
43+
instance.Spec.MessagingBus = &rabbitmqv1.RabbitMqConfig{
44+
Cluster: "rabbitmq",
45+
User: "shared-user",
46+
}
47+
48+
errs := instance.ValidateMessagingBusConfig(basePath)
49+
Expect(errs).To(HaveLen(1))
50+
Expect(errs[0].Type).To(Equal(field.ErrorTypeForbidden))
51+
Expect(errs[0].Field).To(Equal("spec.messagingBus.user"))
52+
Expect(errs[0].Detail).To(ContainSubstring("user field is not allowed at the top level"))
53+
})
54+
55+
It("should reject User field even with other valid fields in messagingBus", func() {
56+
instance.Spec.MessagingBus = &rabbitmqv1.RabbitMqConfig{
57+
Cluster: "rabbitmq",
58+
Vhost: "/openstack",
59+
User: "shared-user",
60+
}
61+
62+
errs := instance.ValidateMessagingBusConfig(basePath)
63+
Expect(errs).To(HaveLen(1))
64+
Expect(errs[0].Type).To(Equal(field.ErrorTypeForbidden))
65+
Expect(errs[0].Field).To(Equal("spec.messagingBus.user"))
66+
})
67+
68+
It("should allow only Cluster field in notificationsBus", func() {
69+
instance.Spec.NotificationsBus = &rabbitmqv1.RabbitMqConfig{
70+
Cluster: "rabbitmq-notifications",
71+
}
72+
73+
errs := instance.ValidateMessagingBusConfig(basePath)
74+
Expect(errs).To(BeEmpty())
75+
})
76+
77+
It("should allow Cluster and Vhost fields in notificationsBus", func() {
78+
instance.Spec.NotificationsBus = &rabbitmqv1.RabbitMqConfig{
79+
Cluster: "rabbitmq-notifications",
80+
Vhost: "/notifications",
81+
}
82+
83+
errs := instance.ValidateMessagingBusConfig(basePath)
84+
Expect(errs).To(BeEmpty())
85+
})
86+
87+
It("should reject User field in notificationsBus", func() {
88+
instance.Spec.NotificationsBus = &rabbitmqv1.RabbitMqConfig{
89+
Cluster: "rabbitmq-notifications",
90+
User: "shared-user",
91+
}
92+
93+
errs := instance.ValidateMessagingBusConfig(basePath)
94+
Expect(errs).To(HaveLen(1))
95+
Expect(errs[0].Type).To(Equal(field.ErrorTypeForbidden))
96+
Expect(errs[0].Field).To(Equal("spec.notificationsBus.user"))
97+
Expect(errs[0].Detail).To(ContainSubstring("user field is not allowed at the top level"))
98+
})
99+
100+
It("should reject User field in both messagingBus and notificationsBus", func() {
101+
instance.Spec.MessagingBus = &rabbitmqv1.RabbitMqConfig{
102+
Cluster: "rabbitmq",
103+
User: "rpc-user",
104+
}
105+
instance.Spec.NotificationsBus = &rabbitmqv1.RabbitMqConfig{
106+
Cluster: "rabbitmq-notifications",
107+
User: "notif-user",
108+
}
109+
110+
errs := instance.ValidateMessagingBusConfig(basePath)
111+
Expect(errs).To(HaveLen(2))
112+
Expect(errs[0].Field).To(Equal("spec.messagingBus.user"))
113+
Expect(errs[1].Field).To(Equal("spec.notificationsBus.user"))
114+
})
115+
116+
It("should allow nil messagingBus and notificationsBus", func() {
117+
instance.Spec.MessagingBus = nil
118+
instance.Spec.NotificationsBus = nil
119+
120+
errs := instance.ValidateMessagingBusConfig(basePath)
121+
Expect(errs).To(BeEmpty())
122+
})
123+
})
124+
})

api/core/v1beta1/zz_generated.deepcopy.go

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/go.mod

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ go 1.24.4
55
require (
66
github.com/cert-manager/cert-manager v1.16.5
77
github.com/go-playground/validator/v10 v10.30.1
8-
github.com/onsi/ginkgo/v2 v2.27.5
9-
github.com/onsi/gomega v1.39.0
8+
github.com/onsi/ginkgo/v2 v2.28.1
9+
github.com/onsi/gomega v1.39.1
1010
github.com/openstack-k8s-operators/barbican-operator/api v0.6.1-0.20260126155915-bd373daa8e8c
1111
github.com/openstack-k8s-operators/cinder-operator/api v0.6.1-0.20260124150910-c004203b9504
1212
github.com/openstack-k8s-operators/designate-operator/api v0.6.1-0.20260126110625-223581247a61
@@ -16,8 +16,8 @@ require (
1616
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260128074606-03b808364e4a
1717
github.com/openstack-k8s-operators/ironic-operator/api v0.6.1-0.20260126092810-cd39d45b6c0e
1818
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20260126175636-114b4c65a959
19-
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260126081203-efc2df9207eb
20-
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20260126081203-efc2df9207eb
19+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260128142552-e2c25eccae5a
20+
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20260128142552-e2c25eccae5a
2121
github.com/openstack-k8s-operators/manila-operator/api v0.6.1-0.20260124125332-5046d6342e48
2222
github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20260127154438-ff95971883bb
2323
github.com/openstack-k8s-operators/neutron-operator/api v0.6.1-0.20260128083308-da1a0d762151
@@ -34,7 +34,7 @@ require (
3434
go.uber.org/multierr v1.11.0 // indirect
3535
go.uber.org/zap v1.27.1 // indirect
3636
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67
37-
golang.org/x/tools v0.40.0 // indirect
37+
golang.org/x/tools v0.41.0 // indirect
3838
k8s.io/api v0.31.14
3939
k8s.io/apimachinery v0.31.14
4040
k8s.io/client-go v0.31.14
@@ -66,7 +66,7 @@ require (
6666
github.com/google/gnostic-models v0.7.0 // indirect
6767
github.com/google/go-cmp v0.7.0 // indirect
6868
github.com/google/gofuzz v1.2.0 // indirect
69-
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
69+
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect
7070
github.com/google/uuid v1.6.0 // indirect
7171
github.com/gophercloud/gophercloud/v2 v2.8.0 // indirect
7272
github.com/imdario/mergo v0.3.16 // indirect
@@ -80,7 +80,7 @@ require (
8080
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
8181
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
8282
github.com/openshift/api v3.9.0+incompatible // indirect
83-
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20251230215914-6ba873b49a35 // indirect
83+
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20260126081203-efc2df9207eb // indirect
8484
github.com/pkg/errors v0.9.1 // indirect
8585
github.com/prometheus/client_golang v1.22.0 // indirect
8686
github.com/prometheus/client_model v0.6.2 // indirect
@@ -92,9 +92,9 @@ require (
9292
github.com/x448/float16 v0.8.4 // indirect
9393
go.yaml.in/yaml/v2 v2.4.2 // indirect
9494
go.yaml.in/yaml/v3 v3.0.4 // indirect
95-
golang.org/x/crypto v0.46.0 // indirect
96-
golang.org/x/mod v0.31.0 // indirect
97-
golang.org/x/net v0.48.0 // indirect
95+
golang.org/x/crypto v0.47.0 // indirect
96+
golang.org/x/mod v0.32.0 // indirect
97+
golang.org/x/net v0.49.0 // indirect
9898
golang.org/x/oauth2 v0.30.0 // indirect
9999
golang.org/x/sync v0.19.0 // indirect
100100
golang.org/x/sys v0.40.0 // indirect
@@ -143,3 +143,31 @@ replace k8s.io/code-generator => k8s.io/code-generator v0.31.14 //allow-merging
143143
replace k8s.io/component-base => k8s.io/component-base v0.31.14 //allow-merging
144144

145145
replace github.com/cert-manager/cmctl/v2 => github.com/cert-manager/cmctl/v2 v2.1.2-0.20241127223932-88edb96860cf //allow-merging
146+
147+
replace github.com/openstack-k8s-operators/barbican-operator/api => github.com/lmiccini/barbican-operator/api v0.0.0-20260130153748-c0862ee80f6b
148+
149+
replace github.com/openstack-k8s-operators/cinder-operator/api => github.com/lmiccini/cinder-operator/api v0.0.0-20260202135636-cac3f48d9aa2
150+
151+
replace github.com/openstack-k8s-operators/designate-operator/api => github.com/lmiccini/designate-operator/api v0.0.0-20260129195526-07a2bbdbbbc6
152+
153+
replace github.com/openstack-k8s-operators/glance-operator/api => github.com/lmiccini/glance-operator/api v0.0.0-20260204060307-02f38e6051cf
154+
155+
replace github.com/openstack-k8s-operators/heat-operator/api => github.com/lmiccini/heat-operator/api v0.0.0-20260130153836-0162a8fbe588
156+
157+
replace github.com/openstack-k8s-operators/ironic-operator/api => github.com/lmiccini/ironic-operator/api v0.0.0-20260203063324-88bdbd5829f7
158+
159+
replace github.com/openstack-k8s-operators/keystone-operator/api => github.com/lmiccini/keystone-operator/api v0.0.0-20260130154009-73911b575f47
160+
161+
replace github.com/openstack-k8s-operators/manila-operator/api => github.com/lmiccini/manila-operator/api v0.0.0-20260204094838-b0fc51fc62dc
162+
163+
replace github.com/openstack-k8s-operators/neutron-operator/api => github.com/lmiccini/neutron-operator/api v0.0.0-20260130154215-206cdc241686
164+
165+
replace github.com/openstack-k8s-operators/nova-operator/api => github.com/lmiccini/nova-operator/api v0.0.0-20260130154456-145dc1dc3e11
166+
167+
replace github.com/openstack-k8s-operators/octavia-operator/api => github.com/lmiccini/octavia-operator/api v0.0.0-20260131142608-b5b99abd4e39
168+
169+
replace github.com/openstack-k8s-operators/swift-operator/api => github.com/lmiccini/swift-operator/api v0.0.0-20260201083840-dc87b8fbd348
170+
171+
replace github.com/openstack-k8s-operators/telemetry-operator/api => github.com/lmiccini/telemetry-operator/api v0.0.0-20260202133001-8d290e538966
172+
173+
replace github.com/openstack-k8s-operators/watcher-operator/api => github.com/lmiccini/watcher-operator/api v0.0.0-20260130155151-6da48495bd84

0 commit comments

Comments
 (0)