diff --git a/api/bases/nova.openstack.org_nova.yaml b/api/bases/nova.openstack.org_nova.yaml index 58303ff6a..1356b378f 100644 --- a/api/bases/nova.openstack.org_nova.yaml +++ b/api/bases/nova.openstack.org_nova.yaml @@ -540,6 +540,23 @@ spec: MemcachedInstance is the name of the Memcached CR that the services in the cell will use. If defined then this takes precedence over Nova.Spec.MemcachedInstance for this cel type: string + messagingBus: + description: MessagingBus configuration (username, vhost, and + cluster) + properties: + cluster: + description: Name of the cluster + minLength: 1 + type: string + user: + description: User - RabbitMQ username + type: string + vhost: + description: Vhost - RabbitMQ vhost name + type: string + required: + - cluster + type: object metadataServiceTemplate: description: |- MetadataServiceTemplate - defines the metadata service dedicated for the @@ -1340,6 +1357,22 @@ spec: description: MemcachedInstance is the name of the Memcached CR that all nova service will use. type: string + messagingBus: + description: MessagingBus configuration (username, vhost, and cluster) + properties: + cluster: + description: Name of the cluster + minLength: 1 + type: string + user: + description: User - RabbitMQ username + type: string + vhost: + description: Vhost - RabbitMQ vhost name + type: string + required: + - cluster + type: object metadataContainerImageURL: description: MetadataContainerImageURL type: string @@ -1648,6 +1681,23 @@ spec: NodeSelector here acts as a default value and can be overridden by service specific NodeSelector Settings. type: object + notificationsBus: + description: NotificationsBus configuration (username, vhost, and + cluster) for notifications + properties: + cluster: + description: Name of the cluster + minLength: 1 + type: string + user: + description: User - RabbitMQ username + type: string + vhost: + description: Vhost - RabbitMQ vhost name + type: string + required: + - cluster + type: object notificationsBusInstance: description: |- NotificationsBusInstance is the name of the RabbitMqCluster CR to select diff --git a/api/go.mod b/api/go.mod index e4d8d717e..cb16c31c1 100644 --- a/api/go.mod +++ b/api/go.mod @@ -4,11 +4,11 @@ go 1.24.4 require ( github.com/google/go-cmp v0.7.0 - github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251030184102-82d2cbaafd35 - github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251027074416-ab5c045dbe00 + github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251217131115-0f117a938d4e + github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251122131503-b76943960b6c github.com/robfig/cron/v3 v3.0.1 - k8s.io/api v0.31.13 - k8s.io/apimachinery v0.31.13 + k8s.io/api v0.31.14 + k8s.io/apimachinery v0.31.14 k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d sigs.k8s.io/controller-runtime v0.19.7 ) @@ -18,7 +18,6 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.2 // indirect - github.com/evanphx/json-patch v5.9.11+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect @@ -44,7 +43,7 @@ require ( github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.65.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/rabbitmq/cluster-operator/v2 v2.16.0 // indirect github.com/spf13/pflag v1.0.7 // indirect github.com/x448/float16 v0.8.4 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect @@ -61,7 +60,7 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.33.2 // indirect - k8s.io/client-go v0.31.13 // indirect + k8s.io/client-go v0.31.14 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250902184714-7fc278399c7f // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect diff --git a/api/go.sum b/api/go.sum index 73864187c..56d246ecc 100644 --- a/api/go.sum +++ b/api/go.sum @@ -1,3 +1,4 @@ +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -74,14 +75,16 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.27.1 h1:0LJC8MpUSQnfnp4n/3W3GdlmJP3ENGF0ZPzjQGLPP7s= -github.com/onsi/ginkgo/v2 v2.27.1/go.mod h1:wmy3vCqiBjirARfVhAqFpYt8uvX0yaFe+GudAqqcCqA= +github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= -github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251030184102-82d2cbaafd35 h1:QFFGu93A+XCvDUxZIgfBE4gB5hEdVQAIw+E8dF1kP/E= -github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251030184102-82d2cbaafd35/go.mod h1:qq8BCRxTEmLRriUsQ4HeDUzqltWg32MQPDTMhgbBGK4= -github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251027074416-ab5c045dbe00 h1:Xih6tYYqiDVllo4fDGHqTPL+M2biO5YLOUmbiTqrW/I= -github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251027074416-ab5c045dbe00/go.mod h1:PMoNILOdQ1Ij7DyrKgljN6RAiq8pFM2AGsUb6mcxe98= +github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251217131115-0f117a938d4e h1:PIjcXzMMwfvBRFgFpaq/W9tqy0t2cYvcWX+kq6uNtTM= +github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251217131115-0f117a938d4e/go.mod h1:ex8ou6/3ms6ovR+CMXD6XhTlNakm1GhB6UZgagVRNW8= +github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251122131503-b76943960b6c h1:wM8qXCB5mQwSosCvtaydzuXitWVVKBHTzH0A2znQ+Jg= +github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251122131503-b76943960b6c/go.mod h1:+Me0raWPPdz8gRi9D4z1khmvUgS9vIKAVC8ckg1yJZU= +github.com/openstack-k8s-operators/rabbitmq-cluster-operator/v2 v2.6.1-0.20250929174222-a0d328fa4dec h1:saovr368HPAKHN0aRPh8h8n9s9dn3d8Frmfua0UYRlc= +github.com/openstack-k8s-operators/rabbitmq-cluster-operator/v2 v2.6.1-0.20250929174222-a0d328fa4dec/go.mod h1:Nh2NEePLjovUQof2krTAg4JaAoLacqtPTZQXK6izNfg= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -109,14 +112,12 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= -go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= diff --git a/api/v1beta1/nova_types.go b/api/v1beta1/nova_types.go index 2f0ad588e..3781aedc9 100644 --- a/api/v1beta1/nova_types.go +++ b/api/v1beta1/nova_types.go @@ -17,6 +17,7 @@ limitations under the License. package v1beta1 import ( + rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1" topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1" condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +50,10 @@ type NovaSpecCore struct { // communicate. APIMessageBusInstance string `json:"apiMessageBusInstance"` + // +kubebuilder:validation:Optional + // MessagingBus configuration (username, vhost, and cluster) + MessagingBus rabbitmqv1.RabbitMqConfig `json:"messagingBus,omitempty"` + // +kubebuilder:validation:Optional // +kubebuilder:default={cell0: {cellDatabaseAccount: nova-cell0, hasAPIAccess: true}, cell1: {cellDatabaseAccount: nova-cell1, cellDatabaseInstance: openstack-cell1, cellMessageBusInstance: rabbitmq-cell1, hasAPIAccess: true}} // Cells is a mapping of cell names to NovaCellTemplate objects defining @@ -131,6 +136,10 @@ type NovaSpecCore struct { // Avoid colocating it with RabbitMqClusterName, APIMessageBusInstance or CellMessageBusInstance used for RPC. // For particular Nova cells, notifications cannot be disabled, nor configured differently. NotificationsBusInstance *string `json:"notificationsBusInstance,omitempty"` + + // +kubebuilder:validation:Optional + // NotificationsBus configuration (username, vhost, and cluster) for notifications + NotificationsBus *rabbitmqv1.RabbitMqConfig `json:"notificationsBus,omitempty"` } // NovaSpec defines the desired state of Nova diff --git a/api/v1beta1/nova_webhook.go b/api/v1beta1/nova_webhook.go index b144b1601..acc979549 100644 --- a/api/v1beta1/nova_webhook.go +++ b/api/v1beta1/nova_webhook.go @@ -26,6 +26,7 @@ import ( "fmt" "github.com/google/go-cmp/cmp" + rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1" service "github.com/openstack-k8s-operators/lib-common/modules/common/service" "github.com/robfig/cron/v3" @@ -88,6 +89,26 @@ func (spec *NovaSpecCore) Default() { spec.APITimeout = novaDefaults.APITimeout } + // Default MessagingBus.Cluster from APIMessageBusInstance if not already set + if spec.MessagingBus.Cluster == "" { + spec.MessagingBus.Cluster = spec.APIMessageBusInstance + } + + // Default NotificationsBus if NotificationsBusInstance is specified + if spec.NotificationsBusInstance != nil && *spec.NotificationsBusInstance != "" { + if spec.NotificationsBus == nil { + // Initialize NotificationsBus with MessagingBus values to inherit user/vhost + spec.NotificationsBus = &rabbitmqv1.RabbitMqConfig{ + User: spec.MessagingBus.User, + Vhost: spec.MessagingBus.Vhost, + } + } + // Default cluster name if not already set + if spec.NotificationsBus.Cluster == "" { + spec.NotificationsBus.Cluster = *spec.NotificationsBusInstance + } + } + for cellName, cellTemplate := range spec.CellTemplates { if cellTemplate.MetadataServiceTemplate.Enabled == nil { @@ -106,6 +127,11 @@ func (spec *NovaSpecCore) Default() { } } + // Default MessagingBus.Cluster from CellMessageBusInstance if not already set + if cellTemplate.MessagingBus.Cluster == "" { + cellTemplate.MessagingBus.Cluster = cellTemplate.CellMessageBusInstance + } + // "cellTemplate" is a by-value copy, so we need to re-inject the updated version of it into the map spec.CellTemplates[cellName] = cellTemplate } @@ -315,7 +341,34 @@ func (spec *NovaSpec) ValidateUpdate(old NovaSpec, basePath *field.Path, namespa // expected to be called by the validation webhook in the higher level meta // operator func (spec *NovaSpecCore) ValidateUpdate(old NovaSpecCore, basePath *field.Path, namespace string) field.ErrorList { - errors := spec.ValidateCellTemplates(basePath, namespace) + var errors field.ErrorList + + // Reject changes to deprecated messagingBusInstance fields - users should use the new messagingBus fields instead + if spec.APIMessageBusInstance != old.APIMessageBusInstance { + errors = append(errors, field.Forbidden( + basePath.Child("apiMessageBusInstance"), + "apiMessageBusInstance is deprecated and cannot be changed. Please use messagingBus.cluster instead")) + } + + if spec.NotificationsBusInstance != nil && old.NotificationsBusInstance != nil && + *spec.NotificationsBusInstance != *old.NotificationsBusInstance { + errors = append(errors, field.Forbidden( + basePath.Child("notificationsBusInstance"), + "notificationsBusInstance is deprecated and cannot be changed. Please use notificationsBus.cluster instead")) + } + + // Check cell template changes + for cellName, cellTemplate := range spec.CellTemplates { + if oldCell, exists := old.CellTemplates[cellName]; exists { + if cellTemplate.CellMessageBusInstance != oldCell.CellMessageBusInstance { + errors = append(errors, field.Forbidden( + basePath.Child("cellTemplates").Key(cellName).Child("cellMessageBusInstance"), + "cellMessageBusInstance is deprecated and cannot be changed. Please use messagingBus.cluster instead")) + } + } + } + + errors = append(errors, spec.ValidateCellTemplates(basePath, namespace)...) // Validate top-level TopologyRef errors = append(errors, topologyv1.ValidateTopologyRef( spec.TopologyRef, *basePath.Child("topologyRef"), namespace)...) diff --git a/api/v1beta1/novacell_types.go b/api/v1beta1/novacell_types.go index 091e60e00..72c128bd7 100644 --- a/api/v1beta1/novacell_types.go +++ b/api/v1beta1/novacell_types.go @@ -17,6 +17,7 @@ limitations under the License. package v1beta1 import ( + rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1" topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1" condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" "github.com/openstack-k8s-operators/lib-common/modules/common/tls" @@ -51,6 +52,10 @@ type NovaCellTemplate struct { // communicate in this cell. For cell0 it is unused. CellMessageBusInstance string `json:"cellMessageBusInstance"` + // +kubebuilder:validation:Optional + // MessagingBus configuration (username, vhost, and cluster) + MessagingBus rabbitmqv1.RabbitMqConfig `json:"messagingBus,omitempty"` + // +kubebuilder:validation:Required // HasAPIAccess defines if this Cell is configured to have access to the // API DB and message bus. diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index e493aca03..026f24def 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -21,6 +21,7 @@ limitations under the License. package v1beta1 import ( + rabbitmqv1beta1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1" topologyv1beta1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" "github.com/openstack-k8s-operators/lib-common/modules/common/service" @@ -505,6 +506,7 @@ func (in *NovaCellStatus) DeepCopy() *NovaCellStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NovaCellTemplate) DeepCopyInto(out *NovaCellTemplate) { *out = *in + out.MessagingBus = in.MessagingBus if in.NodeSelector != nil { in, out := &in.NodeSelector, &out.NodeSelector *out = new(map[string]string) @@ -1659,6 +1661,7 @@ func (in *NovaSpec) DeepCopy() *NovaSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NovaSpecCore) DeepCopyInto(out *NovaSpecCore) { *out = *in + out.MessagingBus = in.MessagingBus if in.CellTemplates != nil { in, out := &in.CellTemplates, &out.CellTemplates *out = make(map[string]NovaCellTemplate, len(*in)) @@ -1691,6 +1694,11 @@ func (in *NovaSpecCore) DeepCopyInto(out *NovaSpecCore) { *out = new(string) **out = **in } + if in.NotificationsBus != nil { + in, out := &in.NotificationsBus, &out.NotificationsBus + *out = new(rabbitmqv1beta1.RabbitMqConfig) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NovaSpecCore. diff --git a/config/crd/bases/nova.openstack.org_nova.yaml b/config/crd/bases/nova.openstack.org_nova.yaml index 58303ff6a..1356b378f 100644 --- a/config/crd/bases/nova.openstack.org_nova.yaml +++ b/config/crd/bases/nova.openstack.org_nova.yaml @@ -540,6 +540,23 @@ spec: MemcachedInstance is the name of the Memcached CR that the services in the cell will use. If defined then this takes precedence over Nova.Spec.MemcachedInstance for this cel type: string + messagingBus: + description: MessagingBus configuration (username, vhost, and + cluster) + properties: + cluster: + description: Name of the cluster + minLength: 1 + type: string + user: + description: User - RabbitMQ username + type: string + vhost: + description: Vhost - RabbitMQ vhost name + type: string + required: + - cluster + type: object metadataServiceTemplate: description: |- MetadataServiceTemplate - defines the metadata service dedicated for the @@ -1340,6 +1357,22 @@ spec: description: MemcachedInstance is the name of the Memcached CR that all nova service will use. type: string + messagingBus: + description: MessagingBus configuration (username, vhost, and cluster) + properties: + cluster: + description: Name of the cluster + minLength: 1 + type: string + user: + description: User - RabbitMQ username + type: string + vhost: + description: Vhost - RabbitMQ vhost name + type: string + required: + - cluster + type: object metadataContainerImageURL: description: MetadataContainerImageURL type: string @@ -1648,6 +1681,23 @@ spec: NodeSelector here acts as a default value and can be overridden by service specific NodeSelector Settings. type: object + notificationsBus: + description: NotificationsBus configuration (username, vhost, and + cluster) for notifications + properties: + cluster: + description: Name of the cluster + minLength: 1 + type: string + user: + description: User - RabbitMQ username + type: string + vhost: + description: Vhost - RabbitMQ vhost name + type: string + required: + - cluster + type: object notificationsBusInstance: description: |- NotificationsBusInstance is the name of the RabbitMqCluster CR to select diff --git a/go.mod b/go.mod index 07230445e..a9cd291d2 100644 --- a/go.mod +++ b/go.mod @@ -8,21 +8,21 @@ require ( github.com/google/uuid v1.6.0 github.com/gophercloud/gophercloud/v2 v2.8.0 github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.7 - github.com/onsi/ginkgo/v2 v2.27.1 + github.com/onsi/ginkgo/v2 v2.27.2 github.com/onsi/gomega v1.38.2 - github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251030184102-82d2cbaafd35 + github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251217131115-0f117a938d4e github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20251027074845-ed8154b20ad1 - github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251027074416-ab5c045dbe00 + github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251122131503-b76943960b6c github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20251027074416-ab5c045dbe00 github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20250929092825-4c2402451077 github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20251015110425-ad0381ce8cd4 github.com/openstack-k8s-operators/nova-operator/api v0.0.0-20221209164002-f9e6b9363961 - go.uber.org/zap v1.27.0 + go.uber.org/zap v1.27.1 golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.31.13 - k8s.io/apimachinery v0.31.13 - k8s.io/client-go v0.31.13 + k8s.io/api v0.31.14 + k8s.io/apimachinery v0.31.14 + k8s.io/client-go v0.31.14 k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d sigs.k8s.io/controller-runtime v0.19.7 ) @@ -85,7 +85,6 @@ require ( go.opentelemetry.io/otel/sdk v1.34.0 // indirect go.opentelemetry.io/otel/trace v1.34.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect - go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect diff --git a/go.sum b/go.sum index d4adef9ee..c13440541 100644 --- a/go.sum +++ b/go.sum @@ -112,18 +112,18 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.27.1 h1:0LJC8MpUSQnfnp4n/3W3GdlmJP3ENGF0ZPzjQGLPP7s= -github.com/onsi/ginkgo/v2 v2.27.1/go.mod h1:wmy3vCqiBjirARfVhAqFpYt8uvX0yaFe+GudAqqcCqA= +github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/openshift/api v0.0.0-20250711200046-c86d80652a9e h1:E1OdwSpqWuDPCedyUt0GEdoAE+r5TXy7YS21yNEo+2U= github.com/openshift/api v0.0.0-20250711200046-c86d80652a9e/go.mod h1:Shkl4HanLwDiiBzakv+con/aMGnVE2MAGvoKp5oyYUo= -github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251030184102-82d2cbaafd35 h1:QFFGu93A+XCvDUxZIgfBE4gB5hEdVQAIw+E8dF1kP/E= -github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251030184102-82d2cbaafd35/go.mod h1:qq8BCRxTEmLRriUsQ4HeDUzqltWg32MQPDTMhgbBGK4= +github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251217131115-0f117a938d4e h1:PIjcXzMMwfvBRFgFpaq/W9tqy0t2cYvcWX+kq6uNtTM= +github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251217131115-0f117a938d4e/go.mod h1:ex8ou6/3ms6ovR+CMXD6XhTlNakm1GhB6UZgagVRNW8= github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20251027074845-ed8154b20ad1 h1:QohvX44nxoV2GwvvOURGXYyDuCn4SCrnwubTKJtzehY= github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20251027074845-ed8154b20ad1/go.mod h1:FMFoO4MjEQ85JpdLtDHxYSZxvJ9KzHua+HdKhpl0KRI= -github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251027074416-ab5c045dbe00 h1:Xih6tYYqiDVllo4fDGHqTPL+M2biO5YLOUmbiTqrW/I= -github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251027074416-ab5c045dbe00/go.mod h1:PMoNILOdQ1Ij7DyrKgljN6RAiq8pFM2AGsUb6mcxe98= +github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251122131503-b76943960b6c h1:wM8qXCB5mQwSosCvtaydzuXitWVVKBHTzH0A2znQ+Jg= +github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251122131503-b76943960b6c/go.mod h1:+Me0raWPPdz8gRi9D4z1khmvUgS9vIKAVC8ckg1yJZU= github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20251027074416-ab5c045dbe00 h1:YwkGrTpeeAq9bk09u9Hp96BEZb8X3XgnMfoyxypelVM= github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20251027074416-ab5c045dbe00/go.mod h1:yf13jWb60XV26eA7A8o86ZCXNWBLNK9dPkTSWFaTPCw= github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20250929092825-4c2402451077 h1:9tpPDBV2RLXMDgt13ec8XR2OatFriItseqg+Oyvx9GA= @@ -139,8 +139,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= @@ -198,14 +196,12 @@ go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= -go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= -go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= diff --git a/internal/controller/nova_controller.go b/internal/controller/nova_controller.go index f59d01c6e..ea85f616f 100644 --- a/internal/controller/nova_controller.go +++ b/internal/controller/nova_controller.go @@ -368,7 +368,7 @@ func (r *NovaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resul // message bus is always the same as the top level API message bus so // we create API MQ separately first apiTransportURL, apiQuorumQueues, apiMQStatus, apiMQError := r.ensureMQ( - ctx, h, instance, instance.Name+"-api-transport", instance.Spec.APIMessageBusInstance) + ctx, h, instance, instance.Name+"-api-transport", instance.Spec.MessagingBus) switch apiMQStatus { case nova.MQFailed: instance.Status.Conditions.Set(condition.FalseCondition( @@ -392,10 +392,17 @@ func (r *NovaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resul return ctrl.Result{}, fmt.Errorf("%w from for the API MQ: %d", util.ErrInvalidStatus, apiMQStatus) } - // nova broadcaster rabbit - notificationBusName := "" - if instance.Spec.NotificationsBusInstance != nil { - notificationBusName = *instance.Spec.NotificationsBusInstance + // Determine if notifications are enabled by checking both old and new API fields + notificationsEnabled := false + + // Check deprecated NotificationsBusInstance field first + if instance.Spec.NotificationsBusInstance != nil && *instance.Spec.NotificationsBusInstance != "" { + notificationsEnabled = true + } + + // Check new NotificationsBus.Cluster field (takes precedence) + if instance.Spec.NotificationsBus != nil && instance.Spec.NotificationsBus.Cluster != "" { + notificationsEnabled = true } var notificationTransportURL string @@ -403,9 +410,14 @@ func (r *NovaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resul var notificationMQError error notificationTransportURLName := instance.Name + "-notification-transport" - if notificationBusName != "" { + if notificationsEnabled { + // Use NotificationsBus if specified, otherwise fall back to main MessagingBus config + notificationsRabbitMqConfig := instance.Spec.MessagingBus + if instance.Spec.NotificationsBus != nil { + notificationsRabbitMqConfig = *instance.Spec.NotificationsBus + } notificationTransportURL, _, notificationMQStatus, notificationMQError = r.ensureMQ( - ctx, h, instance, notificationTransportURLName, notificationBusName) + ctx, h, instance, notificationTransportURLName, notificationsRabbitMqConfig) switch notificationMQStatus { case nova.MQFailed: @@ -470,7 +482,7 @@ func (r *NovaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resul err = apiMQError } else { cellTransportURL, cellQuorumQueues, status, err = r.ensureMQ( - ctx, h, instance, instance.Name+"-"+cellName+"-transport", cellTemplate.CellMessageBusInstance) + ctx, h, instance, instance.Name+"-"+cellName+"-transport", cellTemplate.MessagingBus) } switch status { case nova.MQFailed: @@ -1711,7 +1723,7 @@ func (r *NovaReconciler) ensureMQ( h *helper.Helper, instance *novav1.Nova, transportName string, - messageBusInstanceName string, + rabbitMqConfig rabbitmqv1.RabbitMqConfig, ) (string, bool, nova.MessageBusStatus, error) { Log := r.GetLogger(ctx) transportURL := &rabbitmqv1.TransportURL{ @@ -1722,7 +1734,12 @@ func (r *NovaReconciler) ensureMQ( } op, err := controllerutil.CreateOrPatch(ctx, r.Client, transportURL, func() error { - transportURL.Spec.RabbitmqClusterName = messageBusInstanceName + transportURL.Spec.RabbitmqClusterName = rabbitMqConfig.Cluster + if rabbitMqConfig.User != "" { + transportURL.Spec.Username = rabbitMqConfig.User + } + // Always set Vhost - empty string means use default "/" vhost + transportURL.Spec.Vhost = rabbitMqConfig.Vhost err := controllerutil.SetControllerReference(instance, transportURL, r.Scheme) return err diff --git a/test/functional/nova_controller_test.go b/test/functional/nova_controller_test.go index 59bd0a67f..fe6e455ce 100644 --- a/test/functional/nova_controller_test.go +++ b/test/functional/nova_controller_test.go @@ -28,6 +28,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" + rabbitmqv1 "github.com/openstack-k8s-operators/infra-operator/apis/rabbitmq/v1beta1" topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1" mariadb_test "github.com/openstack-k8s-operators/mariadb-operator/api/test/helpers" mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" @@ -77,13 +78,15 @@ var _ = Describe("Nova controller - notifications", func() { It("notification transport url is set with new rabbit", func() { - // add new-rabbit in Nova CR + // add new-rabbit in Nova CR using the new notificationsBus API notificationsBus := GetNotificationsBusNames(novaNames.NovaName) DeferCleanup(k8sClient.Delete, ctx, CreateNotificationTransportURLSecret(notificationsBus)) Eventually(func(g Gomega) { nova := GetNova(novaNames.NovaName) - nova.Spec.NotificationsBusInstance = ¬ificationsBus.BusName + nova.Spec.NotificationsBus = &rabbitmqv1.RabbitMqConfig{ + Cluster: notificationsBus.BusName, + } g.Expect(k8sClient.Update(ctx, nova)).Should(Succeed()) }, timeout, interval).Should(Succeed()) @@ -123,10 +126,10 @@ var _ = Describe("Nova controller - notifications", func() { configData = string(configDataMap.Data["01-nova.conf"]) AssertHaveNotificationTransportURL(notificationsBus.TransportURLName.Name, configData) - // cleanup notifications transporturl + // cleanup notifications transporturl by clearing the notificationsBus Eventually(func(g Gomega) { nova := GetNova(novaNames.NovaName) - nova.Spec.NotificationsBusInstance = nil + nova.Spec.NotificationsBus = nil g.Expect(k8sClient.Update(ctx, nova)).Should(Succeed()) }, timeout, interval).Should(Succeed()) diff --git a/test/functional/nova_reconfiguration_test.go b/test/functional/nova_reconfiguration_test.go index 29be006a1..442054c62 100644 --- a/test/functional/nova_reconfiguration_test.go +++ b/test/functional/nova_reconfiguration_test.go @@ -689,7 +689,8 @@ var _ = Describe("Nova reconfiguration", func() { nova := GetNova(novaNames.NovaName) cell1 := nova.Spec.CellTemplates["cell1"] - cell1.CellMessageBusInstance = "alternate-mq-for-cell1" + // Use the new messagingBus.cluster field instead of the deprecated cellMessageBusInstance + cell1.MessagingBus.Cluster = "alternate-mq-for-cell1" nova.Spec.CellTemplates["cell1"] = cell1 g.Expect(k8sClient.Update(ctx, nova)).To(Succeed())