From f3725d9b456a6da831f132f60f0a9a43f4307736 Mon Sep 17 00:00:00 2001 From: deefreak Date: Tue, 12 Dec 2023 15:00:28 +0530 Subject: [PATCH 1/7] added hpa update predicate to reconcile a scaledobject only if hpa spec,label or ownerRefernce is changed Signed-off-by: deefreak --- controllers/keda/scaledobject_controller.go | 8 +++++++- controllers/keda/util/predicate.go | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/controllers/keda/scaledobject_controller.go b/controllers/keda/scaledobject_controller.go index b0420c1e9a3..55b24dea7b2 100755 --- a/controllers/keda/scaledobject_controller.go +++ b/controllers/keda/scaledobject_controller.go @@ -132,7 +132,13 @@ func (r *ScaledObjectReconciler) SetupWithManager(mgr ctrl.Manager, options cont predicate.GenerationChangedPredicate{}, ), )). - Owns(&autoscalingv2.HorizontalPodAutoscaler{}). + // Trigger a reconcile only when the HPA spec,label or ownerReference changes. + // Ignore updates to HPA status + Owns(&autoscalingv2.HorizontalPodAutoscaler{}, builder.WithPredicates( + predicate.Or( + predicate.LabelChangedPredicate{}, + kedacontrollerutil.HPAUpdatePredicate{}, + ))). Complete(r) } diff --git a/controllers/keda/util/predicate.go b/controllers/keda/util/predicate.go index b177ad4f550..42f9050581d 100644 --- a/controllers/keda/util/predicate.go +++ b/controllers/keda/util/predicate.go @@ -1,10 +1,13 @@ package util import ( + "reflect" + "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" kedav1alpha1 "github.com/kedacore/keda/v2/apis/keda/v1alpha1" + autoscalingv2 "k8s.io/api/autoscaling/v2" ) type PausedReplicasPredicate struct { @@ -89,3 +92,14 @@ func (PausedPredicate) Update(e event.UpdateEvent) bool { return newPausedValue != oldPausedValue } + +type HPAUpdatePredicate struct { + predicate.Funcs +} + +func (HPAUpdatePredicate) Update(e event.UpdateEvent) bool { + newObj := e.ObjectNew.(*autoscalingv2.HorizontalPodAutoscaler) + oldObj := e.ObjectOld.(*autoscalingv2.HorizontalPodAutoscaler) + + return !reflect.DeepEqual(newObj.Spec, oldObj.Spec) || !reflect.DeepEqual(newObj.OwnerReferences, oldObj.OwnerReferences) +} From 13cadee631bf089de2fb939501dbe1936e667b77 Mon Sep 17 00:00:00 2001 From: deefreak Date: Tue, 12 Dec 2023 17:18:51 +0530 Subject: [PATCH 2/7] added hpa update predicate to reconcile a scaledobject only if hpa spec,label or annotation is changed Signed-off-by: deefreak --- controllers/keda/scaledobject_controller.go | 3 ++- controllers/keda/util/predicate.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/controllers/keda/scaledobject_controller.go b/controllers/keda/scaledobject_controller.go index 55b24dea7b2..3aa53dad4aa 100755 --- a/controllers/keda/scaledobject_controller.go +++ b/controllers/keda/scaledobject_controller.go @@ -132,11 +132,12 @@ func (r *ScaledObjectReconciler) SetupWithManager(mgr ctrl.Manager, options cont predicate.GenerationChangedPredicate{}, ), )). - // Trigger a reconcile only when the HPA spec,label or ownerReference changes. + // Trigger a reconcile only when the HPA spec,label or annotation changes. // Ignore updates to HPA status Owns(&autoscalingv2.HorizontalPodAutoscaler{}, builder.WithPredicates( predicate.Or( predicate.LabelChangedPredicate{}, + predicate.AnnotationChangedPredicate{}, kedacontrollerutil.HPAUpdatePredicate{}, ))). Complete(r) diff --git a/controllers/keda/util/predicate.go b/controllers/keda/util/predicate.go index 42f9050581d..1e41c35eda6 100644 --- a/controllers/keda/util/predicate.go +++ b/controllers/keda/util/predicate.go @@ -101,5 +101,5 @@ func (HPAUpdatePredicate) Update(e event.UpdateEvent) bool { newObj := e.ObjectNew.(*autoscalingv2.HorizontalPodAutoscaler) oldObj := e.ObjectOld.(*autoscalingv2.HorizontalPodAutoscaler) - return !reflect.DeepEqual(newObj.Spec, oldObj.Spec) || !reflect.DeepEqual(newObj.OwnerReferences, oldObj.OwnerReferences) + return !reflect.DeepEqual(newObj.Spec, oldObj.Spec) } From edad66a20e17dae82f42166ab228b8ab90eedda5 Mon Sep 17 00:00:00 2001 From: deefreak Date: Tue, 12 Dec 2023 19:16:01 +0530 Subject: [PATCH 3/7] added hpa update predicate to reconcile a scaledobject only if hpa spec,label or annotation is changed Signed-off-by: deefreak --- controllers/keda/scaledobject_controller.go | 2 +- controllers/keda/util/predicate.go | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/controllers/keda/scaledobject_controller.go b/controllers/keda/scaledobject_controller.go index 3aa53dad4aa..f5b73ea19e3 100755 --- a/controllers/keda/scaledobject_controller.go +++ b/controllers/keda/scaledobject_controller.go @@ -138,7 +138,7 @@ func (r *ScaledObjectReconciler) SetupWithManager(mgr ctrl.Manager, options cont predicate.Or( predicate.LabelChangedPredicate{}, predicate.AnnotationChangedPredicate{}, - kedacontrollerutil.HPAUpdatePredicate{}, + kedacontrollerutil.HPASpecChangedPredicate{}, ))). Complete(r) } diff --git a/controllers/keda/util/predicate.go b/controllers/keda/util/predicate.go index 1e41c35eda6..f9d477543cd 100644 --- a/controllers/keda/util/predicate.go +++ b/controllers/keda/util/predicate.go @@ -1,13 +1,12 @@ package util import ( - "reflect" - "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" kedav1alpha1 "github.com/kedacore/keda/v2/apis/keda/v1alpha1" autoscalingv2 "k8s.io/api/autoscaling/v2" + "k8s.io/apimachinery/pkg/api/equality" ) type PausedReplicasPredicate struct { @@ -93,13 +92,13 @@ func (PausedPredicate) Update(e event.UpdateEvent) bool { return newPausedValue != oldPausedValue } -type HPAUpdatePredicate struct { +type HPASpecChangedPredicate struct { predicate.Funcs } -func (HPAUpdatePredicate) Update(e event.UpdateEvent) bool { +func (HPASpecChangedPredicate) Update(e event.UpdateEvent) bool { newObj := e.ObjectNew.(*autoscalingv2.HorizontalPodAutoscaler) oldObj := e.ObjectOld.(*autoscalingv2.HorizontalPodAutoscaler) - return !reflect.DeepEqual(newObj.Spec, oldObj.Spec) + return len(newObj.Spec.Metrics) != len(oldObj.Spec.Metrics) || !equality.Semantic.DeepDerivative(newObj.Spec, oldObj.Spec) } From 00193f886f83ad240777e09afff2e5d0b8302bd8 Mon Sep 17 00:00:00 2001 From: deefreak Date: Wed, 13 Dec 2023 13:54:22 +0530 Subject: [PATCH 4/7] added hpa update predicate to reconcile a scaledobject only if hpa spec or label is changed Signed-off-by: deefreak --- controllers/keda/scaledobject_controller.go | 3 +- .../keda/scaledobject_controller_test.go | 131 ++++++++++++++++++ controllers/keda/util/predicate.go | 4 +- 3 files changed, 134 insertions(+), 4 deletions(-) diff --git a/controllers/keda/scaledobject_controller.go b/controllers/keda/scaledobject_controller.go index f5b73ea19e3..1d78a56d8e4 100755 --- a/controllers/keda/scaledobject_controller.go +++ b/controllers/keda/scaledobject_controller.go @@ -132,12 +132,11 @@ func (r *ScaledObjectReconciler) SetupWithManager(mgr ctrl.Manager, options cont predicate.GenerationChangedPredicate{}, ), )). - // Trigger a reconcile only when the HPA spec,label or annotation changes. + // Trigger a reconcile only when the HPA spec,label or annotation changes. // Ignore updates to HPA status Owns(&autoscalingv2.HorizontalPodAutoscaler{}, builder.WithPredicates( predicate.Or( predicate.LabelChangedPredicate{}, - predicate.AnnotationChangedPredicate{}, kedacontrollerutil.HPASpecChangedPredicate{}, ))). Complete(r) diff --git a/controllers/keda/scaledobject_controller_test.go b/controllers/keda/scaledobject_controller_test.go index dc3c37e359f..1cd7ac9a1bd 100644 --- a/controllers/keda/scaledobject_controller_test.go +++ b/controllers/keda/scaledobject_controller_test.go @@ -1028,6 +1028,137 @@ var _ = Describe("ScaledObjectController", func() { return k8sClient.Get(context.Background(), types.NamespacedName{Name: fmt.Sprintf("keda-hpa-%s", soName), Namespace: "default"}, hpa) }).Should(HaveOccurred()) }) + + // Fix issue 5281 + It("reconciles scaledobject when hpa spec is changed", func() { + var ( + deploymentName = "hpa-spec-change" + soName = "so-" + deploymentName + min int32 = 1 + max int32 = 5 + newMin int32 = 2 + newMax int32 = 6 + pollingInterVal int32 = 1 + ) + + err := k8sClient.Create(context.Background(), generateDeployment(deploymentName)) + Expect(err).ToNot(HaveOccurred()) + + // Create the ScaledObject without specifying name. + so := &kedav1alpha1.ScaledObject{ + ObjectMeta: metav1.ObjectMeta{ + Name: soName, + Namespace: "default", + }, + Spec: kedav1alpha1.ScaledObjectSpec{ + ScaleTargetRef: &kedav1alpha1.ScaleTarget{ + Name: deploymentName, + }, + MinReplicaCount: &min, + MaxReplicaCount: &max, + PollingInterval: &pollingInterVal, + Advanced: &kedav1alpha1.AdvancedConfig{ + HorizontalPodAutoscalerConfig: &kedav1alpha1.HorizontalPodAutoscalerConfig{}, + }, + Triggers: []kedav1alpha1.ScaleTriggers{ + { + Type: "cron", + Metadata: map[string]string{ + "timezone": "UTC", + "start": "0 * * * *", + "end": "1 * * * *", + "desiredReplicas": "1", + }, + }, + }, + }, + } + err = k8sClient.Create(context.Background(), so) + Expect(err).ToNot(HaveOccurred()) + + // And validate that hpa is created. + hpa := &autoscalingv2.HorizontalPodAutoscaler{} + Eventually(func() error { + return k8sClient.Get(context.Background(), types.NamespacedName{Name: fmt.Sprintf("keda-hpa-%s", soName), Namespace: "default"}, hpa) + }).ShouldNot(HaveOccurred()) + + // Change hpa spec and update + hpa.Spec.MinReplicas = &newMin + hpa.Spec.MaxReplicas = newMax + err = k8sClient.Update(context.Background(), hpa) + Expect(err).ToNot(HaveOccurred()) + + // scaledobject should be reconciled and hpa spec should match with scaledobject spec + Eventually(func() bool { + err = k8sClient.Get(context.Background(), types.NamespacedName{Name: fmt.Sprintf("keda-hpa-%s", soName), Namespace: "default"}, hpa) + if err != nil { + return false + } + return *hpa.Spec.MinReplicas == min && hpa.Spec.MaxReplicas == max + }).Should(BeTrue()) + }) + + It("reconciles scaledobject and creates hpa when child hpa is deleted", func() { + var ( + deploymentName = "hpa-deleted" + soName = "so-" + deploymentName + min int32 = 1 + max int32 = 5 + pollingInterVal int32 = 1 + ) + + err := k8sClient.Create(context.Background(), generateDeployment(deploymentName)) + Expect(err).ToNot(HaveOccurred()) + + // Create the ScaledObject without specifying name. + so := &kedav1alpha1.ScaledObject{ + ObjectMeta: metav1.ObjectMeta{ + Name: soName, + Namespace: "default", + }, + Spec: kedav1alpha1.ScaledObjectSpec{ + ScaleTargetRef: &kedav1alpha1.ScaleTarget{ + Name: deploymentName, + }, + MinReplicaCount: &min, + MaxReplicaCount: &max, + PollingInterval: &pollingInterVal, + Advanced: &kedav1alpha1.AdvancedConfig{ + HorizontalPodAutoscalerConfig: &kedav1alpha1.HorizontalPodAutoscalerConfig{}, + }, + Triggers: []kedav1alpha1.ScaleTriggers{ + { + Type: "cron", + Metadata: map[string]string{ + "timezone": "UTC", + "start": "0 * * * *", + "end": "1 * * * *", + "desiredReplicas": "1", + }, + }, + }, + }, + } + err = k8sClient.Create(context.Background(), so) + Expect(err).ToNot(HaveOccurred()) + + // And validate that hpa is created. + hpa := &autoscalingv2.HorizontalPodAutoscaler{} + Eventually(func() error { + return k8sClient.Get(context.Background(), types.NamespacedName{Name: fmt.Sprintf("keda-hpa-%s", soName), Namespace: "default"}, hpa) + }).ShouldNot(HaveOccurred()) + + // Delete the child hpa + err = k8sClient.Delete(context.Background(), hpa) + Expect(err).ToNot(HaveOccurred()) + + // scaledobject should be reconciled and again the corresponding hpa should be created + Eventually(func() error { + return k8sClient.Get(context.Background(), types.NamespacedName{Name: fmt.Sprintf("keda-hpa-%s", soName), Namespace: "default"}, hpa) + + }).Should(BeNil()) + }) + }) func generateDeployment(name string) *appsv1.Deployment { diff --git a/controllers/keda/util/predicate.go b/controllers/keda/util/predicate.go index f9d477543cd..1ecc114d3ed 100644 --- a/controllers/keda/util/predicate.go +++ b/controllers/keda/util/predicate.go @@ -1,12 +1,12 @@ package util import ( + autoscalingv2 "k8s.io/api/autoscaling/v2" + "k8s.io/apimachinery/pkg/api/equality" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" kedav1alpha1 "github.com/kedacore/keda/v2/apis/keda/v1alpha1" - autoscalingv2 "k8s.io/api/autoscaling/v2" - "k8s.io/apimachinery/pkg/api/equality" ) type PausedReplicasPredicate struct { From e6cef7e1e368a09a9ab117244873644c75f40773 Mon Sep 17 00:00:00 2001 From: deefreak Date: Wed, 13 Dec 2023 15:21:31 +0530 Subject: [PATCH 5/7] added hpa update predicate to reconcile a scaledobject only if hpa spec,label or annotation is changed Signed-off-by: deefreak --- controllers/keda/hpa.go | 10 ++++++++++ controllers/keda/scaledobject_controller.go | 1 + 2 files changed, 11 insertions(+) diff --git a/controllers/keda/hpa.go b/controllers/keda/hpa.go index 4dc9d3d08d9..cbfaa910ed8 100644 --- a/controllers/keda/hpa.go +++ b/controllers/keda/hpa.go @@ -180,6 +180,16 @@ func (r *ScaledObjectReconciler) updateHPAIfNeeded(ctx context.Context, logger l logger.Info("Updated HPA according to ScaledObject", "HPA.Namespace", foundHpa.Namespace, "HPA.Name", foundHpa.Name) } + if !equality.Semantic.DeepDerivative(hpa.ObjectMeta.Annotations, foundHpa.ObjectMeta.Annotations) { + logger.V(1).Info("Found difference in the HPA annotations according to ScaledObject", "currentHPA", foundHpa.ObjectMeta.Annotations, "newHPA", hpa.ObjectMeta.Annotations) + if err = r.Client.Update(ctx, hpa); err != nil { + foundHpa.ObjectMeta.Annotations = hpa.ObjectMeta.Annotations + logger.Error(err, "Failed to update HPA", "HPA.Namespace", foundHpa.Namespace, "HPA.Name", foundHpa.Name) + return err + } + logger.Info("Updated HPA according to ScaledObject", "HPA.Namespace", foundHpa.Namespace, "HPA.Name", foundHpa.Name) + } + return nil } diff --git a/controllers/keda/scaledobject_controller.go b/controllers/keda/scaledobject_controller.go index 1d78a56d8e4..e615ce99529 100755 --- a/controllers/keda/scaledobject_controller.go +++ b/controllers/keda/scaledobject_controller.go @@ -137,6 +137,7 @@ func (r *ScaledObjectReconciler) SetupWithManager(mgr ctrl.Manager, options cont Owns(&autoscalingv2.HorizontalPodAutoscaler{}, builder.WithPredicates( predicate.Or( predicate.LabelChangedPredicate{}, + predicate.AnnotationChangedPredicate{}, kedacontrollerutil.HPASpecChangedPredicate{}, ))). Complete(r) From 048cbbc47906135c2d03d6c0cd5d0cd2123b00f4 Mon Sep 17 00:00:00 2001 From: deefreak Date: Thu, 14 Dec 2023 13:34:02 +0530 Subject: [PATCH 6/7] added hpa update predicate to reconcile a scaledobject only if hpa spec,label or annotation is changed Signed-off-by: deefreak --- controllers/keda/hpa.go | 3 +- .../keda/scaledobject_controller_test.go | 126 ++++++++++++++++++ 2 files changed, 128 insertions(+), 1 deletion(-) diff --git a/controllers/keda/hpa.go b/controllers/keda/hpa.go index cbfaa910ed8..37adf148f41 100644 --- a/controllers/keda/hpa.go +++ b/controllers/keda/hpa.go @@ -180,7 +180,8 @@ func (r *ScaledObjectReconciler) updateHPAIfNeeded(ctx context.Context, logger l logger.Info("Updated HPA according to ScaledObject", "HPA.Namespace", foundHpa.Namespace, "HPA.Name", foundHpa.Name) } - if !equality.Semantic.DeepDerivative(hpa.ObjectMeta.Annotations, foundHpa.ObjectMeta.Annotations) { + if (hpa.ObjectMeta.Annotations == nil && foundHpa.ObjectMeta.Annotations != nil) || + !equality.Semantic.DeepDerivative(hpa.ObjectMeta.Annotations, foundHpa.ObjectMeta.Annotations) { logger.V(1).Info("Found difference in the HPA annotations according to ScaledObject", "currentHPA", foundHpa.ObjectMeta.Annotations, "newHPA", hpa.ObjectMeta.Annotations) if err = r.Client.Update(ctx, hpa); err != nil { foundHpa.ObjectMeta.Annotations = hpa.ObjectMeta.Annotations diff --git a/controllers/keda/scaledobject_controller_test.go b/controllers/keda/scaledobject_controller_test.go index 1cd7ac9a1bd..75ca7f16bed 100644 --- a/controllers/keda/scaledobject_controller_test.go +++ b/controllers/keda/scaledobject_controller_test.go @@ -1098,6 +1098,132 @@ var _ = Describe("ScaledObjectController", func() { }).Should(BeTrue()) }) + It("reconciles scaledobject when hpa label is changed", func() { + var ( + deploymentName = "hpa-label-change" + soName = "so-" + deploymentName + ) + + err := k8sClient.Create(context.Background(), generateDeployment(deploymentName)) + Expect(err).ToNot(HaveOccurred()) + + // Create the ScaledObject without specifying name. + so := &kedav1alpha1.ScaledObject{ + ObjectMeta: metav1.ObjectMeta{ + Name: soName, + Namespace: "default", + }, + Spec: kedav1alpha1.ScaledObjectSpec{ + ScaleTargetRef: &kedav1alpha1.ScaleTarget{ + Name: deploymentName, + }, + Advanced: &kedav1alpha1.AdvancedConfig{ + HorizontalPodAutoscalerConfig: &kedav1alpha1.HorizontalPodAutoscalerConfig{}, + }, + Triggers: []kedav1alpha1.ScaleTriggers{ + { + Type: "cron", + Metadata: map[string]string{ + "timezone": "UTC", + "start": "0 * * * *", + "end": "1 * * * *", + "desiredReplicas": "1", + }, + }, + }, + }, + } + err = k8sClient.Create(context.Background(), so) + Expect(err).ToNot(HaveOccurred()) + + // And validate that hpa is created. + hpa := &autoscalingv2.HorizontalPodAutoscaler{} + Eventually(func() error { + return k8sClient.Get(context.Background(), types.NamespacedName{Name: fmt.Sprintf("keda-hpa-%s", soName), Namespace: "default"}, hpa) + }).ShouldNot(HaveOccurred()) + + // Add a new label to the hpa and update + hpa.ObjectMeta.Labels = map[string]string{"new-label": "new-label-value"} + err = k8sClient.Update(context.Background(), hpa) + Expect(err).ToNot(HaveOccurred()) + + // scaledobject should be reconciled and hpa should not contain this manually added label + Eventually(func() bool { + err = k8sClient.Get(context.Background(), types.NamespacedName{Name: fmt.Sprintf("keda-hpa-%s", soName), Namespace: "default"}, hpa) + if err != nil { + return false + } + // Check if the label is not present + if _, ok := hpa.ObjectMeta.Labels["new-label"]; !ok { + return true + } + return false + }).Should(BeTrue()) + }) + + It("reconciles scaledobject when hpa annotation is changed", func() { + var ( + deploymentName = "hpa-annotation-change" + soName = "so-" + deploymentName + ) + + err := k8sClient.Create(context.Background(), generateDeployment(deploymentName)) + Expect(err).ToNot(HaveOccurred()) + + // Create the ScaledObject without specifying name. + so := &kedav1alpha1.ScaledObject{ + ObjectMeta: metav1.ObjectMeta{ + Name: soName, + Namespace: "default", + }, + Spec: kedav1alpha1.ScaledObjectSpec{ + ScaleTargetRef: &kedav1alpha1.ScaleTarget{ + Name: deploymentName, + }, + Advanced: &kedav1alpha1.AdvancedConfig{ + HorizontalPodAutoscalerConfig: &kedav1alpha1.HorizontalPodAutoscalerConfig{}, + }, + Triggers: []kedav1alpha1.ScaleTriggers{ + { + Type: "cron", + Metadata: map[string]string{ + "timezone": "UTC", + "start": "0 * * * *", + "end": "1 * * * *", + "desiredReplicas": "1", + }, + }, + }, + }, + } + err = k8sClient.Create(context.Background(), so) + Expect(err).ToNot(HaveOccurred()) + + // And validate that hpa is created. + hpa := &autoscalingv2.HorizontalPodAutoscaler{} + Eventually(func() error { + return k8sClient.Get(context.Background(), types.NamespacedName{Name: fmt.Sprintf("keda-hpa-%s", soName), Namespace: "default"}, hpa) + }).ShouldNot(HaveOccurred()) + + // Add a new annotation to the hpa and update + hpa.ObjectMeta.Annotations = map[string]string{"new-annotation": "new-annotation-value"} + err = k8sClient.Update(context.Background(), hpa) + Expect(err).ToNot(HaveOccurred()) + + // scaledobject should be reconciled and hpa should not contain this manually added annotation + Eventually(func() bool { + err = k8sClient.Get(context.Background(), types.NamespacedName{Name: fmt.Sprintf("keda-hpa-%s", soName), Namespace: "default"}, hpa) + if err != nil { + return false + } + // Check if the annotation is not present + if _, ok := hpa.ObjectMeta.Annotations["new-annotation"]; !ok { + return true + } + return false + }, 5*time.Second).Should(BeTrue()) + }) + It("reconciles scaledobject and creates hpa when child hpa is deleted", func() { var ( deploymentName = "hpa-deleted" From 74bb882517a9f1b1b102a4a1c3f95aaacce126c7 Mon Sep 17 00:00:00 2001 From: deefreak Date: Thu, 14 Dec 2023 14:12:13 +0530 Subject: [PATCH 7/7] added hpa update predicate to reconcile a scaledobject only if hpa spec,label or annotation is changed Signed-off-by: deefreak --- controllers/keda/scaledobject_controller_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/controllers/keda/scaledobject_controller_test.go b/controllers/keda/scaledobject_controller_test.go index 75ca7f16bed..c346b59f724 100644 --- a/controllers/keda/scaledobject_controller_test.go +++ b/controllers/keda/scaledobject_controller_test.go @@ -1224,6 +1224,7 @@ var _ = Describe("ScaledObjectController", func() { }, 5*time.Second).Should(BeTrue()) }) + // Fix issue 5281 It("reconciles scaledobject and creates hpa when child hpa is deleted", func() { var ( deploymentName = "hpa-deleted"