Skip to content

Commit 9b6de6d

Browse files
committed
test toplevel
1 parent 3455dae commit 9b6de6d

41 files changed

Lines changed: 1636 additions & 150 deletions

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: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7235,7 +7235,6 @@ spec:
72357235
- cluster
72367236
type: object
72377237
rabbitMqClusterName:
7238-
default: rabbitmq
72397238
type: string
72407239
replicas:
72417240
default: 1
@@ -7324,7 +7323,6 @@ spec:
73247323
default: true
73257324
type: boolean
73267325
rabbitMqClusterName:
7327-
default: rabbitmq
73287326
type: string
73297327
rpcTransport:
73307328
type: string
@@ -9308,6 +9306,18 @@ spec:
93089306
type: object
93099307
type: object
93109308
type: object
9309+
messagingBus:
9310+
properties:
9311+
cluster:
9312+
minLength: 1
9313+
type: string
9314+
user:
9315+
type: string
9316+
vhost:
9317+
type: string
9318+
required:
9319+
- cluster
9320+
type: object
93119321
neutron:
93129322
properties:
93139323
apiOverride:
@@ -15022,7 +15032,6 @@ spec:
1502215032
default: false
1502315033
type: boolean
1502415034
rabbitMqClusterName:
15025-
default: rabbitmq
1502615035
type: string
1502715036
secret:
1502815037
default: osp-secret
@@ -15164,7 +15173,6 @@ spec:
1516415173
type: string
1516515174
type: object
1516615175
rabbitMqClusterName:
15167-
default: rabbitmq
1516815176
type: string
1516915177
secret:
1517015178
default: osp-secret

api/core/v1beta1/openstackcontrolplane_types.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ 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.
@@ -136,7 +142,10 @@ type OpenStackControlPlaneSpec struct {
136142
NotificationsBusInstance *string `json:"notificationsBusInstance,omitempty"`
137143

138144
// +kubebuilder:validation:Optional
139-
// NotificationsBus configuration (username, vhost, and cluster) for notifications
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.
140149
NotificationsBus *rabbitmqv1.RabbitMqConfig `json:"notificationsBus,omitempty"`
141150

142151
// +kubebuilder:validation:Optional

api/core/v1beta1/openstackcontrolplane_webhook.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ func (r *OpenStackControlPlane) ValidateCreate(ctx context.Context, c client.Cli
123123
allErrs = append(allErrs, err)
124124
}
125125

126+
if errs := r.ValidateMessagingBusConfig(basePath); len(errs) != 0 {
127+
allErrs = append(allErrs, errs...)
128+
}
129+
126130
if len(allErrs) != 0 {
127131
return allWarn, apierrors.NewInvalid(
128132
schema.GroupKind{Group: "core.openstack.org", Kind: "OpenStackControlPlane"},
@@ -162,6 +166,10 @@ func (r *OpenStackControlPlane) ValidateUpdate(ctx context.Context, old runtime.
162166
allErrs = append(allErrs, err)
163167
}
164168

169+
if errs := r.ValidateMessagingBusConfig(basePath); len(errs) != 0 {
170+
allErrs = append(allErrs, errs...)
171+
}
172+
165173
if len(allErrs) != 0 {
166174
return nil, apierrors.NewInvalid(
167175
schema.GroupKind{Group: "core.openstack.org", Kind: "OpenStackControlPlane"},
@@ -1273,6 +1281,39 @@ func (r *OpenStackControlPlane) ValidateTopology(basePath *field.Path) *field.Er
12731281
return nil
12741282
}
12751283

1284+
// ValidateMessagingBusConfig validates that the User field is not set in top-level
1285+
// messagingBus and notificationsBus configurations. Setting a shared username would
1286+
// cause webhook validation failures in infra-operator when multiple services try to
1287+
// create RabbitMQUser resources with the same username. The Cluster and Vhost fields
1288+
// are allowed at the top level since they can be safely shared across services.
1289+
func (r *OpenStackControlPlane) ValidateMessagingBusConfig(basePath *field.Path) field.ErrorList {
1290+
var allErrs field.ErrorList
1291+
1292+
// Validate messagingBus
1293+
if r.Spec.MessagingBus != nil {
1294+
messagingBusPath := basePath.Child("messagingBus")
1295+
if r.Spec.MessagingBus.User != "" {
1296+
allErrs = append(allErrs, field.Forbidden(
1297+
messagingBusPath.Child("user"),
1298+
"user field is not allowed at the top level. Each service operator creates its own TransportURL with a unique user. Set user in individual service templates if needed.",
1299+
))
1300+
}
1301+
}
1302+
1303+
// Validate notificationsBus
1304+
if r.Spec.NotificationsBus != nil {
1305+
notificationsBusPath := basePath.Child("notificationsBus")
1306+
if r.Spec.NotificationsBus.User != "" {
1307+
allErrs = append(allErrs, field.Forbidden(
1308+
notificationsBusPath.Child("user"),
1309+
"user field is not allowed at the top level. Each service operator creates its own TransportURL with a unique user. Set user in individual service templates if needed.",
1310+
))
1311+
}
1312+
}
1313+
1314+
return allErrs
1315+
}
1316+
12761317
// ValidateNotificationsBusInstance - returns an error if the notificationsBusInstance
12771318
// parameter is not valid.
12781319
// - nil or empty string must be raised as an error
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: 5 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: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -144,30 +144,30 @@ 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
146146

147-
replace github.com/openstack-k8s-operators/barbican-operator/api => github.com/lmiccini/barbican-operator/api v0.0.0-20260129115901-ec49646f454d
147+
replace github.com/openstack-k8s-operators/barbican-operator/api => github.com/lmiccini/barbican-operator/api v0.0.0-20260129195435-4c4763914238
148148

149-
replace github.com/openstack-k8s-operators/cinder-operator/api => github.com/lmiccini/cinder-operator/api v0.0.0-20260129115434-72599ec8b0eb
149+
replace github.com/openstack-k8s-operators/cinder-operator/api => github.com/lmiccini/cinder-operator/api v0.0.0-20260129195511-0d2903ecac75
150150

151-
replace github.com/openstack-k8s-operators/designate-operator/api => github.com/lmiccini/designate-operator/api v0.0.0-20260129120125-f724aa20f57f
151+
replace github.com/openstack-k8s-operators/designate-operator/api => github.com/lmiccini/designate-operator/api v0.0.0-20260129195526-07a2bbdbbbc6
152152

153-
replace github.com/openstack-k8s-operators/glance-operator/api => github.com/lmiccini/glance-operator/api v0.0.0-20260129121109-7acdaf900d61
153+
replace github.com/openstack-k8s-operators/glance-operator/api => github.com/lmiccini/glance-operator/api v0.0.0-20260129195538-5b3c2fe872f7
154154

155-
replace github.com/openstack-k8s-operators/heat-operator/api => github.com/lmiccini/heat-operator/api v0.0.0-20260129120621-5a1c0c25f66d
155+
replace github.com/openstack-k8s-operators/heat-operator/api => github.com/lmiccini/heat-operator/api v0.0.0-20260129195640-f1137d273619
156156

157-
replace github.com/openstack-k8s-operators/ironic-operator/api => github.com/lmiccini/ironic-operator/api v0.0.0-20260129120750-2bcbec3adfa7
157+
replace github.com/openstack-k8s-operators/ironic-operator/api => github.com/lmiccini/ironic-operator/api v0.0.0-20260130070940-668bd2fa4901
158158

159-
replace github.com/openstack-k8s-operators/keystone-operator/api => github.com/lmiccini/keystone-operator/api v0.0.0-20260129142446-160e481fd139
159+
replace github.com/openstack-k8s-operators/keystone-operator/api => github.com/lmiccini/keystone-operator/api v0.0.0-20260129195740-1b691198bdd0
160160

161-
replace github.com/openstack-k8s-operators/manila-operator/api => github.com/lmiccini/manila-operator/api v0.0.0-20260129125945-e216361521f4
161+
replace github.com/openstack-k8s-operators/manila-operator/api => github.com/lmiccini/manila-operator/api v0.0.0-20260129195800-215a1bb9e623
162162

163-
replace github.com/openstack-k8s-operators/neutron-operator/api => github.com/lmiccini/neutron-operator/api v0.0.0-20260129121503-0aa4d06499c1
163+
replace github.com/openstack-k8s-operators/neutron-operator/api => github.com/lmiccini/neutron-operator/api v0.0.0-20260129195824-46964feaebad
164164

165-
replace github.com/openstack-k8s-operators/nova-operator/api => github.com/lmiccini/nova-operator/api v0.0.0-20260129134601-7c1ae7633f35
165+
replace github.com/openstack-k8s-operators/nova-operator/api => github.com/lmiccini/nova-operator/api v0.0.0-20260129195845-8130899633b5
166166

167-
replace github.com/openstack-k8s-operators/octavia-operator/api => github.com/lmiccini/octavia-operator/api v0.0.0-20260129123115-7d5093f00dca
167+
replace github.com/openstack-k8s-operators/octavia-operator/api => github.com/lmiccini/octavia-operator/api v0.0.0-20260129195900-f6bf3a78a669
168168

169-
replace github.com/openstack-k8s-operators/swift-operator/api => github.com/lmiccini/swift-operator/api v0.0.0-20260129111939-21099018aab1
169+
replace github.com/openstack-k8s-operators/swift-operator/api => github.com/lmiccini/swift-operator/api v0.0.0-20260130064124-cdb5cb2d15d0
170170

171-
replace github.com/openstack-k8s-operators/telemetry-operator/api => github.com/lmiccini/telemetry-operator/api v0.0.0-20260129121935-22f0adde14e4
171+
replace github.com/openstack-k8s-operators/telemetry-operator/api => github.com/lmiccini/telemetry-operator/api v0.0.0-20260130070733-39cf42d1afac
172172

173-
replace github.com/openstack-k8s-operators/watcher-operator/api => github.com/lmiccini/watcher-operator/api v0.0.0-20260129123402-744760956f20
173+
replace github.com/openstack-k8s-operators/watcher-operator/api => github.com/lmiccini/watcher-operator/api v0.0.0-20260129200055-041ac0b5cc0e

0 commit comments

Comments
 (0)