From df33f3ef495813f393a1cc9fc18555118463b9a1 Mon Sep 17 00:00:00 2001 From: Alan Bishop <abishop@redhat.com> Date: Fri, 1 Mar 2024 08:33:31 -0800 Subject: [PATCH] Restart services when their NodeSelector changes Add a hash of a service's Spec.NodeSelector to the inputs that determine when the corresponding pod should be recreated. This ensures pods are restarted whenever the NodeSelector is modified. --- controllers/cinderapi_controller.go | 14 ++++++++++++++ controllers/cinderbackup_controller.go | 14 ++++++++++++++ controllers/cinderscheduler_controller.go | 14 ++++++++++++++ controllers/cindervolume_controller.go | 14 ++++++++++++++ pkg/cinder/funcs.go | 11 +++++++++++ 5 files changed, 67 insertions(+) diff --git a/controllers/cinderapi_controller.go b/controllers/cinderapi_controller.go index 5f6688be..9dfa712d 100644 --- a/controllers/cinderapi_controller.go +++ b/controllers/cinderapi_controller.go @@ -706,6 +706,20 @@ func (r *CinderAPIReconciler) reconcileNormal(ctx context.Context, instance *cin // all cert input checks out so report InputReady instance.Status.Conditions.MarkTrue(condition.TLSInputReadyCondition, condition.InputReadyMessage) + // + // Hash the nodeSelector so the pod is recreated when it changes + // + err = cinder.AddNodeSelectorHash(instance.Spec.NodeSelector, &configVars) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.ServiceConfigReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.ServiceConfigReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } + // // Create secrets required as input for the Service and calculate an overall hash of hashes // diff --git a/controllers/cinderbackup_controller.go b/controllers/cinderbackup_controller.go index 0c31c956..505e1ded 100644 --- a/controllers/cinderbackup_controller.go +++ b/controllers/cinderbackup_controller.go @@ -410,6 +410,20 @@ func (r *CinderBackupReconciler) reconcileNormal(ctx context.Context, instance * // all cert input checks out so report InputReady instance.Status.Conditions.MarkTrue(condition.TLSInputReadyCondition, condition.InputReadyMessage) + // + // Hash the nodeSelector so the pod is recreated when it changes + // + err = cinder.AddNodeSelectorHash(instance.Spec.NodeSelector, &configVars) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.ServiceConfigReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.ServiceConfigReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } + // // Create secrets required as input for the Service and calculate an overall hash of hashes // diff --git a/controllers/cinderscheduler_controller.go b/controllers/cinderscheduler_controller.go index ef158015..072ee50d 100644 --- a/controllers/cinderscheduler_controller.go +++ b/controllers/cinderscheduler_controller.go @@ -409,6 +409,20 @@ func (r *CinderSchedulerReconciler) reconcileNormal(ctx context.Context, instanc // all cert input checks out so report InputReady instance.Status.Conditions.MarkTrue(condition.TLSInputReadyCondition, condition.InputReadyMessage) + // + // Hash the nodeSelector so the pod is recreated when it changes + // + err = cinder.AddNodeSelectorHash(instance.Spec.NodeSelector, &configVars) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.ServiceConfigReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.ServiceConfigReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } + // // Create ConfigMaps required as input for the Service and calculate an overall hash of hashes // diff --git a/controllers/cindervolume_controller.go b/controllers/cindervolume_controller.go index b784193c..553c18e0 100644 --- a/controllers/cindervolume_controller.go +++ b/controllers/cindervolume_controller.go @@ -434,6 +434,20 @@ func (r *CinderVolumeReconciler) reconcileNormal(ctx context.Context, instance * return ctrl.Result{}, err } + // + // Hash the nodeSelector so the pod is recreated when it changes + // + err = cinder.AddNodeSelectorHash(instance.Spec.NodeSelector, &configVars) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.ServiceConfigReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.ServiceConfigReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } + // // create hash over all the different input resources to identify if any those changed // and a restart/recreate is required. diff --git a/pkg/cinder/funcs.go b/pkg/cinder/funcs.go index 4e86c067..6b7e39e5 100644 --- a/pkg/cinder/funcs.go +++ b/pkg/cinder/funcs.go @@ -3,6 +3,8 @@ package cinder import ( common "github.com/openstack-k8s-operators/lib-common/modules/common" "github.com/openstack-k8s-operators/lib-common/modules/common/affinity" + "github.com/openstack-k8s-operators/lib-common/modules/common/env" + "github.com/openstack-k8s-operators/lib-common/modules/common/util" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -47,3 +49,12 @@ func GetPodAffinity(componentName string) *corev1.Affinity { corev1.LabelHostname, ) } + +// AddNodeSelectorHash - Adds a hash of a nodeSelector map to the envVars. +func AddNodeSelectorHash(nodeSelector map[string]string, envVars *map[string]env.Setter) error { + hash, err := util.ObjectHash(nodeSelector) + if err != nil { + (*envVars)["NodeSelectorHash"] = env.SetValue(hash) + } + return err +}