Skip to content

Commit 3c35642

Browse files
lmicciniopenshift-merge-bot[bot]
authored andcommitted
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 d785b91 commit 3c35642

21 files changed

Lines changed: 610 additions & 89 deletions

api/bases/nova.openstack.org_nova.yaml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,23 @@ spec:
550550
MemcachedInstance is the name of the Memcached CR that the services in the cell will use.
551551
If defined then this takes precedence over Nova.Spec.MemcachedInstance for this cel
552552
type: string
553+
messagingBus:
554+
description: MessagingBus configuration (username, vhost, and
555+
cluster)
556+
properties:
557+
cluster:
558+
description: Name of the cluster
559+
minLength: 1
560+
type: string
561+
user:
562+
description: User - RabbitMQ username
563+
type: string
564+
vhost:
565+
description: Vhost - RabbitMQ vhost name
566+
type: string
567+
required:
568+
- cluster
569+
type: object
553570
metadataServiceTemplate:
554571
description: |-
555572
MetadataServiceTemplate - defines the metadata service dedicated for the
@@ -1350,6 +1367,22 @@ spec:
13501367
description: MemcachedInstance is the name of the Memcached CR that
13511368
all nova service will use.
13521369
type: string
1370+
messagingBus:
1371+
description: MessagingBus configuration (username, vhost, and cluster)
1372+
properties:
1373+
cluster:
1374+
description: Name of the cluster
1375+
minLength: 1
1376+
type: string
1377+
user:
1378+
description: User - RabbitMQ username
1379+
type: string
1380+
vhost:
1381+
description: Vhost - RabbitMQ vhost name
1382+
type: string
1383+
required:
1384+
- cluster
1385+
type: object
13531386
metadataContainerImageURL:
13541387
description: MetadataContainerImageURL
13551388
type: string
@@ -1658,6 +1691,23 @@ spec:
16581691
NodeSelector here acts as a default value and can be overridden by service
16591692
specific NodeSelector Settings.
16601693
type: object
1694+
notificationsBus:
1695+
description: NotificationsBus configuration (username, vhost, and
1696+
cluster) for notifications
1697+
properties:
1698+
cluster:
1699+
description: Name of the cluster
1700+
minLength: 1
1701+
type: string
1702+
user:
1703+
description: User - RabbitMQ username
1704+
type: string
1705+
vhost:
1706+
description: Vhost - RabbitMQ vhost name
1707+
type: string
1708+
required:
1709+
- cluster
1710+
type: object
16611711
notificationsBusInstance:
16621712
description: |-
16631713
NotificationsBusInstance is the name of the RabbitMqCluster CR to select

api/go.mod

Lines changed: 3 additions & 3 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
@@ -46,6 +45,7 @@ require (
4645
github.com/prometheus/client_model v0.6.2 // indirect
4746
github.com/prometheus/common v0.65.0 // indirect
4847
github.com/prometheus/procfs v0.16.1 // indirect
48+
github.com/rabbitmq/cluster-operator/v2 v2.16.0 // indirect
4949
github.com/spf13/pflag v1.0.7 // indirect
5050
github.com/x448/float16 v0.8.4 // indirect
5151
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.5 h1:ZeVgZMx2PDMdJm/+w5fE/OyG6ILo1Y3e+QX4zSR0zTE
7879
github.com/onsi/ginkgo/v2 v2.27.5/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
// +kubebuilder:validation:Optional
136145
// +operator-sdk:csv:customresourcedefinitions:type=spec

0 commit comments

Comments
 (0)