Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 54 additions & 3 deletions api/bases/nova.openstack.org_nova.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ spec:
Service instance used for the Nova API DB.
type: string
apiMessageBusInstance:
default: rabbitmq
description: |-
APIMessageBusInstance is the name of the RabbitMqCluster CR to select
the Message Bus Service instance used by the Nova top level services to
communicate.
Deprecated: Use MessagingBus.Cluster instead
type: string
apiServiceTemplate:
default:
Expand Down Expand Up @@ -398,11 +398,11 @@ spec:
Service instance used as the DB of this cell.
type: string
cellMessageBusInstance:
default: rabbitmq
description: |-
CellMessageBusInstance is the name of the RabbitMqCluster CR to select
the Message Bus Service instance used by the nova services to
communicate in this cell. For cell0 it is unused.
Deprecated: Use MessagingBus.Cluster instead
type: string
conductorServiceTemplate:
description: ConductorServiceTemplate - defines the cell conductor
Expand Down Expand Up @@ -550,6 +550,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
Expand Down Expand Up @@ -1325,8 +1342,9 @@ spec:
cell1:
cellDatabaseAccount: nova-cell1
cellDatabaseInstance: openstack-cell1
cellMessageBusInstance: rabbitmq-cell1
hasAPIAccess: true
messagingBus:
cluster: rabbitmq-cell1
description: |-
Cells is a mapping of cell names to NovaCellTemplate objects defining
the cells in the deployment. The "cell0" cell is a mandatory cell in
Expand All @@ -1350,6 +1368,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
Expand Down Expand Up @@ -1658,6 +1692,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
Expand Down
7 changes: 3 additions & 4 deletions api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ 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.20260123105816-865d02e287a9
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251230215914-6ba873b49a35
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260126091827-7758173fbb09
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260128142552-e2c25eccae5a
github.com/robfig/cron/v3 v3.0.1
k8s.io/api v0.31.14
k8s.io/apimachinery v0.31.14
Expand All @@ -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
Expand All @@ -40,12 +39,12 @@ require (
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/onsi/ginkgo/v2 v2.27.5 // indirect
github.com/onsi/gomega v1.39.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect
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/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
Expand Down
11 changes: 7 additions & 4 deletions api/go.sum
Original file line number Diff line number Diff line change
@@ -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=
Expand Down Expand Up @@ -78,10 +79,12 @@ github.com/onsi/ginkgo/v2 v2.27.5 h1:ZeVgZMx2PDMdJm/+w5fE/OyG6ILo1Y3e+QX4zSR0zTE
github.com/onsi/ginkgo/v2 v2.27.5/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q=
github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4=
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260123105816-865d02e287a9 h1:tD6nnTRcyUCXdVMWPHLApk12tzQlQni5eoxvQ8XdbP8=
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260123105816-865d02e287a9/go.mod h1:ZXwFlspJCdZEUjMbmaf61t5AMB4u2vMyAMMoe/vJroE=
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251230215914-6ba873b49a35 h1:pF3mJ3nwq6r4qwom+rEWZNquZpcQW/iftHlJ1KPIDsk=
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251230215914-6ba873b49a35/go.mod h1:kycZyoe7OZdW1HUghr2nI3N7wSJtNahXf6b/ypD14f4=
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260126091827-7758173fbb09 h1:vhAGLKZitJIffj7ONiPpKmOX7Tmt/LGJpaY0Z2LeyfQ=
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260126091827-7758173fbb09/go.mod h1:ZXwFlspJCdZEUjMbmaf61t5AMB4u2vMyAMMoe/vJroE=
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260128142552-e2c25eccae5a h1:97OfmmJgoIKTfbED2SfyjoPkivoiMHg4jfbrTuwSGQw=
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260128142552-e2c25eccae5a/go.mod h1:ndqfy1KbVorHH6+zlUFPIrCRhMSxO3ImYJUGaooE0x0=
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=
Expand Down
126 changes: 126 additions & 0 deletions api/v1beta1/common_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"path/filepath"
"strings"

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

Expand Down Expand Up @@ -58,3 +59,128 @@ func matchAny(requested string, allowed []string) bool {
}
return false
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i feel like we could/shoudl move some of these validation function into lib common and just take the field names/paths as inputs to them

we do no need to address this comment now but duplicating this logic in multiple operator is sub optimal so it would be a good thing to consolidate into lib common and reuse later.

to do that you may need ot use generics and im not sure if we have access to thos in our current go so just food for thought.

// getDeprecatedFields returns the centralized list of deprecated fields for NovaSpecCore
func (spec *NovaSpecCore) getDeprecatedFields(old *NovaSpecCore) []common_webhook.DeprecatedFieldUpdate {
// Get new field value (handle nil NotificationsBus)
var newNotifBusCluster *string
if spec.NotificationsBus != nil {
newNotifBusCluster = &spec.NotificationsBus.Cluster
}

deprecatedFields := []common_webhook.DeprecatedFieldUpdate{
{
DeprecatedFieldName: "apiMessageBusInstance",
NewFieldPath: []string{"messagingBus", "cluster"},
NewDeprecatedValue: &spec.APIMessageBusInstance,
NewValue: &spec.MessagingBus.Cluster,
},
{
DeprecatedFieldName: "notificationsBusInstance",
NewFieldPath: []string{"notificationsBus", "cluster"},
NewDeprecatedValue: spec.NotificationsBusInstance,
NewValue: newNotifBusCluster,
},
}

// If old spec is provided (UPDATE operation), add old values
if old != nil {
deprecatedFields[0].OldDeprecatedValue = &old.APIMessageBusInstance
deprecatedFields[1].OldDeprecatedValue = old.NotificationsBusInstance
}

return deprecatedFields
}

// validateDeprecatedFieldsCreate validates deprecated fields during CREATE operations
func (spec *NovaSpecCore) validateDeprecatedFieldsCreate(basePath *field.Path) ([]string, field.ErrorList) {
// Get deprecated fields list (without old values for CREATE)
deprecatedFieldsUpdate := spec.getDeprecatedFields(nil)

// Convert to DeprecatedField list for CREATE validation
deprecatedFields := make([]common_webhook.DeprecatedField, len(deprecatedFieldsUpdate))
for i, df := range deprecatedFieldsUpdate {
deprecatedFields[i] = common_webhook.DeprecatedField{
DeprecatedFieldName: df.DeprecatedFieldName,
NewFieldPath: df.NewFieldPath,
DeprecatedValue: df.NewDeprecatedValue,
NewValue: df.NewValue,
}
}

// Validate top-level NovaSpecCore fields
warnings := common_webhook.ValidateDeprecatedFieldsCreate(deprecatedFields, basePath)

// Validate deprecated fields in cell templates
for cellName, cellTemplate := range spec.CellTemplates {
cellPath := basePath.Child("cellTemplates").Key(cellName)
cellWarnings := cellTemplate.validateDeprecatedFieldsCreate(cellPath)
warnings = append(warnings, cellWarnings...)
}

return warnings, nil
}

// validateDeprecatedFieldsUpdate validates deprecated fields during UPDATE operations
func (spec *NovaSpecCore) validateDeprecatedFieldsUpdate(old NovaSpecCore, basePath *field.Path) ([]string, field.ErrorList) {
// Get deprecated fields list with old values
deprecatedFields := spec.getDeprecatedFields(&old)
warnings, errors := common_webhook.ValidateDeprecatedFieldsUpdate(deprecatedFields, basePath)

// Validate deprecated fields in cell templates
for cellName, cellTemplate := range spec.CellTemplates {
if oldCell, exists := old.CellTemplates[cellName]; exists {
cellPath := basePath.Child("cellTemplates").Key(cellName)
cellWarnings, cellErrors := cellTemplate.validateDeprecatedFieldsUpdate(oldCell, cellPath)
warnings = append(warnings, cellWarnings...)
errors = append(errors, cellErrors...)
}
}

return warnings, errors
}

// getDeprecatedFields returns the centralized list of deprecated fields for NovaCellTemplate
func (spec *NovaCellTemplate) getDeprecatedFields(old *NovaCellTemplate) []common_webhook.DeprecatedFieldUpdate {
deprecatedFields := []common_webhook.DeprecatedFieldUpdate{
{
DeprecatedFieldName: "cellMessageBusInstance",
NewFieldPath: []string{"messagingBus", "cluster"},
NewDeprecatedValue: &spec.CellMessageBusInstance,
NewValue: &spec.MessagingBus.Cluster,
},
}

// If old spec is provided (UPDATE operation), add old values
if old != nil {
deprecatedFields[0].OldDeprecatedValue = &old.CellMessageBusInstance
}

return deprecatedFields
}

// validateDeprecatedFieldsCreate validates deprecated fields during CREATE operations for NovaCellTemplate
func (spec *NovaCellTemplate) validateDeprecatedFieldsCreate(basePath *field.Path) []string {
// Get deprecated fields list (without old values for CREATE)
deprecatedFieldsUpdate := spec.getDeprecatedFields(nil)

// Convert to DeprecatedField list for CREATE validation
deprecatedFields := make([]common_webhook.DeprecatedField, len(deprecatedFieldsUpdate))
for i, df := range deprecatedFieldsUpdate {
deprecatedFields[i] = common_webhook.DeprecatedField{
DeprecatedFieldName: df.DeprecatedFieldName,
NewFieldPath: df.NewFieldPath,
DeprecatedValue: df.NewDeprecatedValue,
NewValue: df.NewValue,
}
}

return common_webhook.ValidateDeprecatedFieldsCreate(deprecatedFields, basePath)
}

// validateDeprecatedFieldsUpdate validates deprecated fields during UPDATE operations for NovaCellTemplate
func (spec *NovaCellTemplate) validateDeprecatedFieldsUpdate(old NovaCellTemplate, basePath *field.Path) ([]string, field.ErrorList) {
// Get deprecated fields list with old values
deprecatedFields := spec.getDeprecatedFields(&old)
return common_webhook.ValidateDeprecatedFieldsUpdate(deprecatedFields, basePath)
}
17 changes: 13 additions & 4 deletions api/v1beta1/nova_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -43,14 +44,18 @@ type NovaSpecCore struct {
APIDatabaseInstance string `json:"apiDatabaseInstance"`

// +kubebuilder:validation:Optional
// +kubebuilder:default=rabbitmq
// APIMessageBusInstance is the name of the RabbitMqCluster CR to select
// the Message Bus Service instance used by the Nova top level services to
// communicate.
APIMessageBusInstance string `json:"apiMessageBusInstance"`
// Deprecated: Use MessagingBus.Cluster instead
APIMessageBusInstance string `json:"apiMessageBusInstance,omitempty"`

// +kubebuilder:validation:Optional
// +kubebuilder:default={cell0: {cellDatabaseAccount: nova-cell0, hasAPIAccess: true}, cell1: {cellDatabaseAccount: nova-cell1, cellDatabaseInstance: openstack-cell1, cellMessageBusInstance: rabbitmq-cell1, hasAPIAccess: true}}
// 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, messagingBus: {cluster: rabbitmq-cell1}, hasAPIAccess: true}}
// Cells is a mapping of cell names to NovaCellTemplate objects defining
// the cells in the deployment. The "cell0" cell is a mandatory cell in
// every deployment. Moreover any real deployment needs at least one
Expand Down Expand Up @@ -130,7 +135,11 @@ type NovaSpecCore struct {
// An empty value "" leaves the notification drivers unconfigured and emitting no notifications at all.
// 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"`
NotificationsBusInstance *string `json:"notificationsBusInstance,omitempty" deprecated:"true" deprecatedNew:"notificationsBus.cluster"`

// +kubebuilder:validation:Optional
// NotificationsBus configuration (username, vhost, and cluster) for notifications
NotificationsBus *rabbitmqv1.RabbitMqConfig `json:"notificationsBus,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so the pre-commit failure is because of this

while NotificationsBus is optional it has requried field internally and that is not sumethign that is supproted by kubebuilder

ERROR: "NoNewRequiredFields": crd/nova.nova.openstack.org version/v1beta1 field/^.spec.cellTemplates[*].messagingBus.cluster is new and may not be required
ERROR: "NoNewRequiredFields": crd/nova.nova.openstack.org version/v1beta1 field/^.spec.messagingBus.cluster is new and may not be required
ERROR: "NoNewRequiredFields": crd/nova.nova.openstack.org version/v1beta1 field/^.spec.notificationsBus.cluster is new and may not be required

to fix that we need to chagne the type definiton for rabbitmqv1.RabbitMqConfig

or we need to alter the pre-commti config for that check


// +kubebuilder:validation:Optional
// +operator-sdk:csv:customresourcedefinitions:type=spec
Expand Down
Loading