Skip to content

Commit 3019421

Browse files
committed
Rabbitmq vhost and user support
Add new messagingBus and notificationsBus interfaces to hold cluster, user and vhost names for optional usage. The controller adds these values to the TransportURL create request when present. Additionally, we migrate RabbitMQ cluster name to RabbitMq config struct using DefaultRabbitMqConfig from infra-operator to automatically populate the new Cluster field from legacy RabbitMqClusterName. Example usage: spec: messagingBus: cluster: rpc-rabbitmq user: rpc-user vhost: rpc-vhost notificationsBus: cluster: notifications-rabbitmq user: notifications-user vhost: notifications-vhost Finally, we add the rabbitmquser crs to the secret so they can be stored for dataplane finalizers management and do auto cleanup of orphaned users after credential rotations. Jira: https://issues.redhat.com/browse/OSPRH-22697
1 parent 964875f commit 3019421

File tree

21 files changed

+617
-97
lines changed

21 files changed

+617
-97
lines changed

api/bases/nova.openstack.org_nova.yaml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,23 @@ spec:
540540
MemcachedInstance is the name of the Memcached CR that the services in the cell will use.
541541
If defined then this takes precedence over Nova.Spec.MemcachedInstance for this cel
542542
type: string
543+
messagingBus:
544+
description: MessagingBus configuration (username, vhost, and
545+
cluster)
546+
properties:
547+
cluster:
548+
description: Name of the cluster
549+
minLength: 1
550+
type: string
551+
user:
552+
description: User - RabbitMQ username
553+
type: string
554+
vhost:
555+
description: Vhost - RabbitMQ vhost name
556+
type: string
557+
required:
558+
- cluster
559+
type: object
543560
metadataServiceTemplate:
544561
description: |-
545562
MetadataServiceTemplate - defines the metadata service dedicated for the
@@ -1340,6 +1357,22 @@ spec:
13401357
description: MemcachedInstance is the name of the Memcached CR that
13411358
all nova service will use.
13421359
type: string
1360+
messagingBus:
1361+
description: MessagingBus configuration (username, vhost, and cluster)
1362+
properties:
1363+
cluster:
1364+
description: Name of the cluster
1365+
minLength: 1
1366+
type: string
1367+
user:
1368+
description: User - RabbitMQ username
1369+
type: string
1370+
vhost:
1371+
description: Vhost - RabbitMQ vhost name
1372+
type: string
1373+
required:
1374+
- cluster
1375+
type: object
13431376
metadataContainerImageURL:
13441377
description: MetadataContainerImageURL
13451378
type: string
@@ -1648,6 +1681,23 @@ spec:
16481681
NodeSelector here acts as a default value and can be overridden by service
16491682
specific NodeSelector Settings.
16501683
type: object
1684+
notificationsBus:
1685+
description: NotificationsBus configuration (username, vhost, and
1686+
cluster) for notifications
1687+
properties:
1688+
cluster:
1689+
description: Name of the cluster
1690+
minLength: 1
1691+
type: string
1692+
user:
1693+
description: User - RabbitMQ username
1694+
type: string
1695+
vhost:
1696+
description: Vhost - RabbitMQ vhost name
1697+
type: string
1698+
required:
1699+
- cluster
1700+
type: object
16511701
notificationsBusInstance:
16521702
description: |-
16531703
NotificationsBusInstance is the name of the RabbitMqCluster CR to select

api/go.mod

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ go 1.24.4
44

55
require (
66
github.com/google/go-cmp v0.7.0
7-
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260123105816-865d02e287a9
8-
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251230215914-6ba873b49a35
7+
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260126091827-7758173fbb09
8+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260126081203-efc2df9207eb
99
github.com/robfig/cron/v3 v3.0.1
1010
k8s.io/api v0.31.14
1111
k8s.io/apimachinery v0.31.14
@@ -18,7 +18,6 @@ require (
1818
github.com/cespare/xxhash/v2 v2.3.0 // indirect
1919
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
2020
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
21-
github.com/evanphx/json-patch v5.9.11+incompatible // indirect
2221
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
2322
github.com/fsnotify/fsnotify v1.9.0 // indirect
2423
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
@@ -40,12 +39,12 @@ require (
4039
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
4140
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
4241
github.com/onsi/ginkgo/v2 v2.27.4 // indirect
43-
github.com/onsi/gomega v1.39.0 // indirect
4442
github.com/pkg/errors v0.9.1 // indirect
4543
github.com/prometheus/client_golang v1.22.0 // indirect
4644
github.com/prometheus/client_model v0.6.2 // indirect
4745
github.com/prometheus/common v0.65.0 // indirect
4846
github.com/prometheus/procfs v0.16.1 // indirect
47+
github.com/rabbitmq/cluster-operator/v2 v2.16.0 // indirect
4948
github.com/spf13/pflag v1.0.7 // indirect
5049
github.com/x448/float16 v0.8.4 // indirect
5150
go.yaml.in/yaml/v2 v2.4.2 // indirect

api/go.sum

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
12
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
23
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
34
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -78,10 +79,12 @@ github.com/onsi/ginkgo/v2 v2.27.4 h1:fcEcQW/A++6aZAZQNUmNjvA9PSOzefMJBerHJ4t8v8Y
7879
github.com/onsi/ginkgo/v2 v2.27.4/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
7980
github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q=
8081
github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4=
81-
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260123105816-865d02e287a9 h1:tD6nnTRcyUCXdVMWPHLApk12tzQlQni5eoxvQ8XdbP8=
82-
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260123105816-865d02e287a9/go.mod h1:ZXwFlspJCdZEUjMbmaf61t5AMB4u2vMyAMMoe/vJroE=
83-
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251230215914-6ba873b49a35 h1:pF3mJ3nwq6r4qwom+rEWZNquZpcQW/iftHlJ1KPIDsk=
84-
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251230215914-6ba873b49a35/go.mod h1:kycZyoe7OZdW1HUghr2nI3N7wSJtNahXf6b/ypD14f4=
82+
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260126091827-7758173fbb09 h1:vhAGLKZitJIffj7ONiPpKmOX7Tmt/LGJpaY0Z2LeyfQ=
83+
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260126091827-7758173fbb09/go.mod h1:ZXwFlspJCdZEUjMbmaf61t5AMB4u2vMyAMMoe/vJroE=
84+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260126081203-efc2df9207eb h1:S7tnYO/E1f1KQfcp7N5bam8+ax/ExDTOhZ1WqG4Bfu0=
85+
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260126081203-efc2df9207eb/go.mod h1:ndqfy1KbVorHH6+zlUFPIrCRhMSxO3ImYJUGaooE0x0=
86+
github.com/openstack-k8s-operators/rabbitmq-cluster-operator/v2 v2.6.1-0.20250929174222-a0d328fa4dec h1:saovr368HPAKHN0aRPh8h8n9s9dn3d8Frmfua0UYRlc=
87+
github.com/openstack-k8s-operators/rabbitmq-cluster-operator/v2 v2.6.1-0.20250929174222-a0d328fa4dec/go.mod h1:Nh2NEePLjovUQof2krTAg4JaAoLacqtPTZQXK6izNfg=
8588
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
8689
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
8790
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

api/v1beta1/common_webhook.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"path/filepath"
2222
"strings"
2323

24+
common_webhook "github.com/openstack-k8s-operators/lib-common/modules/common/webhook"
2425
"k8s.io/apimachinery/pkg/util/validation/field"
2526
)
2627

@@ -58,3 +59,128 @@ func matchAny(requested string, allowed []string) bool {
5859
}
5960
return false
6061
}
62+
63+
// getDeprecatedFields returns the centralized list of deprecated fields for NovaSpecCore
64+
func (spec *NovaSpecCore) getDeprecatedFields(old *NovaSpecCore) []common_webhook.DeprecatedFieldUpdate {
65+
// Get new field value (handle nil NotificationsBus)
66+
var newNotifBusCluster *string
67+
if spec.NotificationsBus != nil {
68+
newNotifBusCluster = &spec.NotificationsBus.Cluster
69+
}
70+
71+
deprecatedFields := []common_webhook.DeprecatedFieldUpdate{
72+
{
73+
DeprecatedFieldName: "apiMessageBusInstance",
74+
NewFieldPath: []string{"messagingBus", "cluster"},
75+
NewDeprecatedValue: &spec.APIMessageBusInstance,
76+
NewValue: &spec.MessagingBus.Cluster,
77+
},
78+
{
79+
DeprecatedFieldName: "notificationsBusInstance",
80+
NewFieldPath: []string{"notificationsBus", "cluster"},
81+
NewDeprecatedValue: spec.NotificationsBusInstance,
82+
NewValue: newNotifBusCluster,
83+
},
84+
}
85+
86+
// If old spec is provided (UPDATE operation), add old values
87+
if old != nil {
88+
deprecatedFields[0].OldDeprecatedValue = &old.APIMessageBusInstance
89+
deprecatedFields[1].OldDeprecatedValue = old.NotificationsBusInstance
90+
}
91+
92+
return deprecatedFields
93+
}
94+
95+
// validateDeprecatedFieldsCreate validates deprecated fields during CREATE operations
96+
func (spec *NovaSpecCore) validateDeprecatedFieldsCreate(basePath *field.Path) ([]string, field.ErrorList) {
97+
// Get deprecated fields list (without old values for CREATE)
98+
deprecatedFieldsUpdate := spec.getDeprecatedFields(nil)
99+
100+
// Convert to DeprecatedField list for CREATE validation
101+
deprecatedFields := make([]common_webhook.DeprecatedField, len(deprecatedFieldsUpdate))
102+
for i, df := range deprecatedFieldsUpdate {
103+
deprecatedFields[i] = common_webhook.DeprecatedField{
104+
DeprecatedFieldName: df.DeprecatedFieldName,
105+
NewFieldPath: df.NewFieldPath,
106+
DeprecatedValue: df.NewDeprecatedValue,
107+
NewValue: df.NewValue,
108+
}
109+
}
110+
111+
// Validate top-level NovaSpecCore fields
112+
warnings := common_webhook.ValidateDeprecatedFieldsCreate(deprecatedFields, basePath)
113+
114+
// Validate deprecated fields in cell templates
115+
for cellName, cellTemplate := range spec.CellTemplates {
116+
cellPath := basePath.Child("cellTemplates").Key(cellName)
117+
cellWarnings := cellTemplate.validateDeprecatedFieldsCreate(cellPath)
118+
warnings = append(warnings, cellWarnings...)
119+
}
120+
121+
return warnings, nil
122+
}
123+
124+
// validateDeprecatedFieldsUpdate validates deprecated fields during UPDATE operations
125+
func (spec *NovaSpecCore) validateDeprecatedFieldsUpdate(old NovaSpecCore, basePath *field.Path) ([]string, field.ErrorList) {
126+
// Get deprecated fields list with old values
127+
deprecatedFields := spec.getDeprecatedFields(&old)
128+
warnings, errors := common_webhook.ValidateDeprecatedFieldsUpdate(deprecatedFields, basePath)
129+
130+
// Validate deprecated fields in cell templates
131+
for cellName, cellTemplate := range spec.CellTemplates {
132+
if oldCell, exists := old.CellTemplates[cellName]; exists {
133+
cellPath := basePath.Child("cellTemplates").Key(cellName)
134+
cellWarnings, cellErrors := cellTemplate.validateDeprecatedFieldsUpdate(oldCell, cellPath)
135+
warnings = append(warnings, cellWarnings...)
136+
errors = append(errors, cellErrors...)
137+
}
138+
}
139+
140+
return warnings, errors
141+
}
142+
143+
// getDeprecatedFields returns the centralized list of deprecated fields for NovaCellTemplate
144+
func (spec *NovaCellTemplate) getDeprecatedFields(old *NovaCellTemplate) []common_webhook.DeprecatedFieldUpdate {
145+
deprecatedFields := []common_webhook.DeprecatedFieldUpdate{
146+
{
147+
DeprecatedFieldName: "cellMessageBusInstance",
148+
NewFieldPath: []string{"messagingBus", "cluster"},
149+
NewDeprecatedValue: &spec.CellMessageBusInstance,
150+
NewValue: &spec.MessagingBus.Cluster,
151+
},
152+
}
153+
154+
// If old spec is provided (UPDATE operation), add old values
155+
if old != nil {
156+
deprecatedFields[0].OldDeprecatedValue = &old.CellMessageBusInstance
157+
}
158+
159+
return deprecatedFields
160+
}
161+
162+
// validateDeprecatedFieldsCreate validates deprecated fields during CREATE operations for NovaCellTemplate
163+
func (spec *NovaCellTemplate) validateDeprecatedFieldsCreate(basePath *field.Path) []string {
164+
// Get deprecated fields list (without old values for CREATE)
165+
deprecatedFieldsUpdate := spec.getDeprecatedFields(nil)
166+
167+
// Convert to DeprecatedField list for CREATE validation
168+
deprecatedFields := make([]common_webhook.DeprecatedField, len(deprecatedFieldsUpdate))
169+
for i, df := range deprecatedFieldsUpdate {
170+
deprecatedFields[i] = common_webhook.DeprecatedField{
171+
DeprecatedFieldName: df.DeprecatedFieldName,
172+
NewFieldPath: df.NewFieldPath,
173+
DeprecatedValue: df.NewDeprecatedValue,
174+
NewValue: df.NewValue,
175+
}
176+
}
177+
178+
return common_webhook.ValidateDeprecatedFieldsCreate(deprecatedFields, basePath)
179+
}
180+
181+
// validateDeprecatedFieldsUpdate validates deprecated fields during UPDATE operations for NovaCellTemplate
182+
func (spec *NovaCellTemplate) validateDeprecatedFieldsUpdate(old NovaCellTemplate, basePath *field.Path) ([]string, field.ErrorList) {
183+
// Get deprecated fields list with old values
184+
deprecatedFields := spec.getDeprecatedFields(&old)
185+
return common_webhook.ValidateDeprecatedFieldsUpdate(deprecatedFields, basePath)
186+
}

api/v1beta1/nova_types.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package v1beta1
1818

1919
import (
20+
rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1"
2021
topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
2122
condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition"
2223
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -47,7 +48,11 @@ type NovaSpecCore struct {
4748
// APIMessageBusInstance is the name of the RabbitMqCluster CR to select
4849
// the Message Bus Service instance used by the Nova top level services to
4950
// communicate.
50-
APIMessageBusInstance string `json:"apiMessageBusInstance"`
51+
APIMessageBusInstance string `json:"apiMessageBusInstance" deprecated:"true" deprecatedNew:"messagingBus.cluster"`
52+
53+
// +kubebuilder:validation:Optional
54+
// MessagingBus configuration (username, vhost, and cluster)
55+
MessagingBus rabbitmqv1.RabbitMqConfig `json:"messagingBus,omitempty"`
5156

5257
// +kubebuilder:validation:Optional
5358
// +kubebuilder:default={cell0: {cellDatabaseAccount: nova-cell0, hasAPIAccess: true}, cell1: {cellDatabaseAccount: nova-cell1, cellDatabaseInstance: openstack-cell1, cellMessageBusInstance: rabbitmq-cell1, hasAPIAccess: true}}
@@ -130,7 +135,11 @@ type NovaSpecCore struct {
130135
// An empty value "" leaves the notification drivers unconfigured and emitting no notifications at all.
131136
// Avoid colocating it with RabbitMqClusterName, APIMessageBusInstance or CellMessageBusInstance used for RPC.
132137
// For particular Nova cells, notifications cannot be disabled, nor configured differently.
133-
NotificationsBusInstance *string `json:"notificationsBusInstance,omitempty"`
138+
NotificationsBusInstance *string `json:"notificationsBusInstance,omitempty" deprecated:"true" deprecatedNew:"notificationsBus.cluster"`
139+
140+
// +kubebuilder:validation:Optional
141+
// NotificationsBus configuration (username, vhost, and cluster) for notifications
142+
NotificationsBus *rabbitmqv1.RabbitMqConfig `json:"notificationsBus,omitempty"`
134143
}
135144

136145
// NovaSpec defines the desired state of Nova

0 commit comments

Comments
 (0)