Skip to content
Open
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
2 changes: 1 addition & 1 deletion internal/openstack/barbican.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ func ReconcileBarbican(ctx context.Context, instance *corev1beta1.OpenStackContr
instance.Spec.Barbican.Template.BarbicanAPI.TLS.API.Internal.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointInternal)
}

if instance.Spec.Barbican.Template.NodeSelector == nil {
if instance.Spec.Barbican.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Barbican.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/cinder.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func ReconcileCinder(ctx context.Context, instance *corev1beta1.OpenStackControl
instance.Spec.Cinder.Template.CinderAPI.TLS.API.Internal.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointInternal)
}

if instance.Spec.Cinder.Template.NodeSelector == nil {
if instance.Spec.Cinder.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Cinder.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/designate.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func ReconcileDesignate(ctx context.Context, instance *corev1beta1.OpenStackCont
instance.Spec.Designate.Template.DesignateAPI.TLS.API.Internal.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointInternal)
}

if instance.Spec.Designate.Template.NodeSelector == nil {
if instance.Spec.Designate.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Designate.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/dnsmasq.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func ReconcileDNSMasqs(ctx context.Context, instance *corev1beta1.OpenStackContr
instance.Spec.DNS.Template = &networkv1.DNSMasqSpecCore{}
}

if instance.Spec.DNS.Template.NodeSelector == nil {
if instance.Spec.DNS.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.DNS.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/galera.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ func reconcileGalera(
return galeraReady, galera, nil
}

if spec.NodeSelector == nil {
if spec.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
spec.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/glance.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func ReconcileGlance(ctx context.Context, instance *corev1beta1.OpenStackControl
instance.Spec.Glance.Template.NotificationBusInstance = nil
}

if instance.Spec.Glance.Template.NodeSelector == nil {
if instance.Spec.Glance.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Glance.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/heat.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func ReconcileHeat(ctx context.Context, instance *corev1beta1.OpenStackControlPl
// Note: Migration from rabbitMqClusterName to messagingBus.cluster is handled by the webhook
// via annotation-based triggers. No direct spec mutation here to avoid GitOps conflicts.

if instance.Spec.Heat.Template.NodeSelector == nil {
if instance.Spec.Heat.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Heat.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/horizon.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func ReconcileHorizon(ctx context.Context, instance *corev1beta1.OpenStackContro
instance.Spec.Horizon.Template = &horizonv1.HorizonSpecCore{}
}

if instance.Spec.Horizon.Template.NodeSelector == nil {
if instance.Spec.Horizon.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Horizon.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/ironic.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func ReconcileIronic(ctx context.Context, instance *corev1beta1.OpenStackControl
// via annotation-based triggers. No direct spec mutation here to avoid GitOps conflicts.
// This applies to both Ironic main template and IronicNeutronAgent.

if instance.Spec.Ironic.Template.NodeSelector == nil {
if instance.Spec.Ironic.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Ironic.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/keystone.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func ReconcileKeystoneAPI(ctx context.Context, instance *corev1beta1.OpenStackCo
instance.Spec.Keystone.Template.TLS.API.Internal.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointInternal)
}

if instance.Spec.Keystone.Template.NodeSelector == nil {
if instance.Spec.Keystone.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Keystone.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/manila.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func ReconcileManila(ctx context.Context, instance *corev1beta1.OpenStackControl
instance.Spec.Manila.Template.ManilaAPI.TLS.API.Internal.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointInternal)
}

if instance.Spec.Manila.Template.NodeSelector == nil {
if instance.Spec.Manila.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Manila.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/memcached.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ func reconcileMemcached(
}
}

if spec.NodeSelector == nil {
if spec.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
spec.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/neutron.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ func ReconcileNeutron(ctx context.Context, instance *corev1beta1.OpenStackContro
instance.Spec.Neutron.Template.TLS.API.Internal.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointInternal)
}

if instance.Spec.Neutron.Template.NodeSelector == nil {
if instance.Spec.Neutron.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Neutron.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/nova.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func ReconcileNova(ctx context.Context, instance *corev1beta1.OpenStackControlPl
// Note: Migration from apiMessageBusInstance and cellMessageBusInstance to messagingBus.cluster
// is handled by the webhook via annotation-based triggers. No direct spec mutation here to avoid GitOps conflicts.

if instance.Spec.Nova.Template.NodeSelector == nil {
if instance.Spec.Nova.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Nova.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/octavia.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func ReconcileOctavia(ctx context.Context, instance *corev1beta1.OpenStackContro
// Note: Migration from rabbitMqClusterName to messagingBus.cluster is handled by the webhook
// via annotation-based triggers. No direct spec mutation here to avoid GitOps conflicts.

if instance.Spec.Octavia.Template.NodeSelector == nil {
if instance.Spec.Octavia.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Octavia.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/openstackclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func ReconcileOpenStackClient(ctx context.Context, instance *corev1.OpenStackCon
return ctrl.Result{}, nil
}

if instance.Spec.OpenStackClient.Template.NodeSelector == nil {
if instance.Spec.OpenStackClient.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.OpenStackClient.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
6 changes: 3 additions & 3 deletions internal/openstack/ovn.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ func ReconcileOVNDbClusters(ctx context.Context, instance *corev1beta1.OpenStack
dbcluster.MetricsTLS.CaBundleSecretName = instance.Status.TLS.CaBundleSecretName
}

if dbcluster.NodeSelector == nil {
if dbcluster.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
dbcluster.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down Expand Up @@ -349,7 +349,7 @@ func ReconcileOVNNorthd(ctx context.Context, instance *corev1beta1.OpenStackCont
ovnNorthdSpec.MetricsTLS.CaBundleSecretName = instance.Status.TLS.CaBundleSecretName
}

if ovnNorthdSpec.NodeSelector == nil {
if ovnNorthdSpec.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
ovnNorthdSpec.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down Expand Up @@ -493,7 +493,7 @@ func ReconcileOVNController(ctx context.Context, instance *corev1beta1.OpenStack
ovnControllerSpec.MetricsTLS.CaBundleSecretName = instance.Status.TLS.CaBundleSecretName
}

if ovnControllerSpec.NodeSelector == nil {
if ovnControllerSpec.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
ovnControllerSpec.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/placement.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func ReconcilePlacementAPI(ctx context.Context, instance *corev1beta1.OpenStackC
instance.Spec.Placement.Template = &placementv1.PlacementAPISpecCore{}
}

if instance.Spec.Placement.Template.NodeSelector == nil {
if instance.Spec.Placement.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Placement.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/rabbitmq.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ func reconcileRabbitMQ(
tlsCert = certSecret.Name
}

if spec.NodeSelector == nil {
if spec.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
spec.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ func reconcileRedis(
tlsCert = certSecret.Name
}

if spec.NodeSelector == nil {
if spec.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
spec.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/swift.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func ReconcileSwift(ctx context.Context, instance *corev1beta1.OpenStackControlP
instance.Spec.Swift.Template.SwiftProxy.RabbitMqClusterName = ""
}

if instance.Spec.Swift.Template.NodeSelector == nil {
if instance.Spec.Swift.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Swift.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func ReconcileTelemetry(ctx context.Context, instance *corev1beta1.OpenStackCont
// notificationsBus.cluster (Aodh, Ceilometer) is handled by the webhook via annotation-based triggers.
// No direct spec mutation here to avoid GitOps conflicts.

if instance.Spec.Telemetry.Template.NodeSelector == nil {
if instance.Spec.Telemetry.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Telemetry.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
2 changes: 1 addition & 1 deletion internal/openstack/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func ReconcileWatcher(ctx context.Context, instance *corev1beta1.OpenStackContro
instance.Spec.Watcher.Template.APIServiceTemplate.TLS.API.Internal.SecretName = endpointDetails.GetEndptCertSecret(service.EndpointInternal)
}

if instance.Spec.Watcher.Template.NodeSelector == nil {
if instance.Spec.Watcher.Template.NodeSelector == nil && len(instance.Spec.NodeSelector) > 0 {
instance.Spec.Watcher.Template.NodeSelector = &instance.Spec.NodeSelector
}

Expand Down
76 changes: 76 additions & 0 deletions test/functional/ctlplane/openstackoperator_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2681,6 +2681,82 @@ var _ = Describe("OpenStackOperator controller", func() {
})
})

When("An OpenStackControlplane instance is created without nodeSelector", func() {
BeforeEach(func() {
spec := GetDefaultOpenStackControlPlaneSpec()
spec["tls"] = GetTLSPublicSpec()
// Intentionally do NOT set spec["nodeSelector"]
DeferCleanup(
th.DeleteInstance,
CreateOpenStackControlPlane(names.OpenStackControlplaneName, spec),
)

Eventually(func(g Gomega) {
keystoneAPI := keystone.GetKeystoneAPI(names.KeystoneAPIName)
g.Expect(keystoneAPI).Should(Not(BeNil()))
}, timeout, interval).Should(Succeed())
keystone.SimulateKeystoneAPIReady(names.KeystoneAPIName)

Eventually(func(g Gomega) {
osversion := GetOpenStackVersion(names.OpenStackControlplaneName)
g.Expect(osversion).Should(Not(BeNil()))

th.ExpectCondition(
names.OpenStackVersionName,
ConditionGetterFunc(OpenStackVersionConditionGetter),
corev1.OpenStackVersionInitialized,
k8s_corev1.ConditionTrue,
)
}, timeout, interval).Should(Succeed())

th.CreateSecret(types.NamespacedName{Name: "openstack-config-secret", Namespace: namespace}, map[string][]byte{"secure.yaml": []byte("foo")})
th.CreateConfigMap(types.NamespacedName{Name: "openstack-config", Namespace: namespace}, map[string]interface{}{"clouds.yaml": string("foo"), "OS_CLOUD": "default"})
})

It("does not set nodeSelector on sub-CRs", func() {
Eventually(func(g Gomega) {
db := mariadb.GetGalera(names.DBName)
g.Expect(db.Spec.NodeSelector).To(BeNil())
}, timeout, interval).Should(Succeed())
Eventually(func(g Gomega) {
rmq := GetRabbitMQCluster(names.RabbitMQName)
g.Expect(rmq.Spec.NodeSelector).To(BeNil())
}, timeout, interval).Should(Succeed())
Eventually(func(g Gomega) {
mc := infra.GetMemcached(names.MemcachedName)
g.Expect(mc.Spec.NodeSelector).To(BeNil())
}, timeout, interval).Should(Succeed())
})

It("does not cause spurious updates on sub-CRs when nodeSelector is unset", func() {
// Wait for initial reconciliation to settle
Eventually(func(g Gomega) {
mc := infra.GetMemcached(names.MemcachedName)
g.Expect(mc).ShouldNot(BeNil())
}, timeout, interval).Should(Succeed())

// Record the current generation of each sub-CR
mcGen := infra.GetMemcached(names.MemcachedName).Generation
dbGen := mariadb.GetGalera(names.DBName).Generation
rmqGen := GetRabbitMQCluster(names.RabbitMQName).Generation

// Verify generation stays stable over multiple reconcile cycles.
// Before the fix, the nil-vs-pointer-to-nil-map mismatch in
// NodeSelector caused CreateOrPatch to detect a spurious diff and
// bump the generation on every reconcile (~1/second).
Consistently(func(g Gomega) {
mc := infra.GetMemcached(names.MemcachedName)
g.Expect(mc.Generation).To(Equal(mcGen))

db := mariadb.GetGalera(names.DBName)
g.Expect(db.Generation).To(Equal(dbGen))

rmq := GetRabbitMQCluster(names.RabbitMQName)
g.Expect(rmq.Generation).To(Equal(rmqGen))
}, time.Second*5, interval).Should(Succeed())
})
})

When("An OpenStackControlplane instance references a wrong topology", func() {
BeforeEach(func() {
spec := GetDefaultOpenStackControlPlaneSpec()
Expand Down
Loading