@@ -22,6 +22,7 @@ import (
2222	"time" 
2323
2424	"github.com/golang/glog" 
25+ 	apiequality "k8s.io/apimachinery/pkg/api/equality" 
2526	"k8s.io/apimachinery/pkg/api/errors" 
2627	"k8s.io/apimachinery/pkg/api/resource" 
2728	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 
@@ -371,14 +372,20 @@ func (a *HorizontalController) reconcileAutoscaler(hpav1Shared *autoscalingv1.Ho
371372		return  fmt .Errorf ("failed to convert the given HPA to %s: %v" , autoscalingv2 .SchemeGroupVersion .String (), err )
372373	}
373374	hpa  :=  hpaRaw .(* autoscalingv2.HorizontalPodAutoscaler )
375+ 	hpaStatusOriginalRaw , err  :=  api .Scheme .DeepCopy (& hpa .Status )
376+ 	if  err  !=  nil  {
377+ 		a .eventRecorder .Event (hpav1Shared , v1 .EventTypeWarning , "FailedConvertHPA" , err .Error ())
378+ 		return  fmt .Errorf ("failed to deep-copy the HPA status: %v" , err )
379+ 	}
380+ 	hpaStatusOriginal  :=  hpaStatusOriginalRaw .(* autoscalingv2.HorizontalPodAutoscalerStatus )
374381
375382	reference  :=  fmt .Sprintf ("%s/%s/%s" , hpa .Spec .ScaleTargetRef .Kind , hpa .Namespace , hpa .Spec .ScaleTargetRef .Name )
376383
377384	scale , err  :=  a .scaleNamespacer .Scales (hpa .Namespace ).Get (hpa .Spec .ScaleTargetRef .Kind , hpa .Spec .ScaleTargetRef .Name )
378385	if  err  !=  nil  {
379386		a .eventRecorder .Event (hpa , v1 .EventTypeWarning , "FailedGetScale" , err .Error ())
380387		setCondition (hpa , autoscalingv2 .AbleToScale , v1 .ConditionFalse , "FailedGetScale" , "the HPA controller was unable to get the target's current scale: %v" , err )
381- 		a .update ( hpa )
388+ 		a .updateStatusIfNeeded ( hpaStatusOriginal ,  hpa )
382389		return  fmt .Errorf ("failed to query scale subresource for %s: %v" , reference , err )
383390	}
384391	setCondition (hpa , autoscalingv2 .AbleToScale , v1 .ConditionTrue , "SucceededGetScale" , "the HPA controller was able to get the target's current scale" )
@@ -412,7 +419,10 @@ func (a *HorizontalController) reconcileAutoscaler(hpav1Shared *autoscalingv1.Ho
412419	} else  {
413420		metricDesiredReplicas , metricName , metricStatuses , metricTimestamp , err  =  a .computeReplicasForMetrics (hpa , scale , hpa .Spec .Metrics )
414421		if  err  !=  nil  {
415- 			a .updateCurrentReplicasInStatus (hpa , currentReplicas )
422+ 			a .setCurrentReplicasInStatus (hpa , currentReplicas )
423+ 			if  err  :=  a .updateStatusIfNeeded (hpaStatusOriginal , hpa ); err  !=  nil  {
424+ 				utilruntime .HandleError (err )
425+ 			}
416426			a .eventRecorder .Event (hpa , v1 .EventTypeWarning , "FailedComputeMetricsReplicas" , err .Error ())
417427			return  fmt .Errorf ("failed to compute desired number of replicas based on listed metrics for %s: %v" , reference , err )
418428		}
@@ -489,7 +499,10 @@ func (a *HorizontalController) reconcileAutoscaler(hpav1Shared *autoscalingv1.Ho
489499		if  err  !=  nil  {
490500			a .eventRecorder .Eventf (hpa , v1 .EventTypeWarning , "FailedRescale" , "New size: %d; reason: %s; error: %v" , desiredReplicas , rescaleReason , err .Error ())
491501			setCondition (hpa , autoscalingv2 .AbleToScale , v1 .ConditionFalse , "FailedUpdateScale" , "the HPA controller was unable to update the target scale: %v" , err )
492- 			a .updateCurrentReplicasInStatus (hpa , currentReplicas )
502+ 			a .setCurrentReplicasInStatus (hpa , currentReplicas )
503+ 			if  err  :=  a .updateStatusIfNeeded (hpaStatusOriginal , hpa ); err  !=  nil  {
504+ 				utilruntime .HandleError (err )
505+ 			}
493506			return  fmt .Errorf ("failed to rescale %s: %v" , reference , err )
494507		}
495508		setCondition (hpa , autoscalingv2 .AbleToScale , v1 .ConditionTrue , "SucceededRescale" , "the HPA controller was able to update the target scale to %d" , desiredReplicas )
@@ -501,7 +514,8 @@ func (a *HorizontalController) reconcileAutoscaler(hpav1Shared *autoscalingv1.Ho
501514		desiredReplicas  =  currentReplicas 
502515	}
503516
504- 	return  a .updateStatusWithReplicas (hpa , currentReplicas , desiredReplicas , metricStatuses , rescale )
517+ 	a .setStatus (hpa , currentReplicas , desiredReplicas , metricStatuses , rescale )
518+ 	return  a .updateStatusIfNeeded (hpaStatusOriginal , hpa )
505519}
506520
507521func  (a  * HorizontalController ) shouldScale (hpa  * autoscalingv2.HorizontalPodAutoscaler , currentReplicas , desiredReplicas  int32 , timestamp  time.Time ) bool  {
@@ -528,14 +542,14 @@ func (a *HorizontalController) shouldScale(hpa *autoscalingv2.HorizontalPodAutos
528542	return  false 
529543}
530544
531- func  (a  * HorizontalController ) updateCurrentReplicasInStatus (hpa  * autoscalingv2.HorizontalPodAutoscaler , currentReplicas  int32 ) {
532- 	err  :=  a .updateStatusWithReplicas (hpa , currentReplicas , hpa .Status .DesiredReplicas , hpa .Status .CurrentMetrics , false )
533- 	if  err  !=  nil  {
534- 		utilruntime .HandleError (err )
535- 	}
545+ // setCurrentReplicasInStatus sets the current replica count in the status of the HPA. 
546+ func  (a  * HorizontalController ) setCurrentReplicasInStatus (hpa  * autoscalingv2.HorizontalPodAutoscaler , currentReplicas  int32 ) {
547+ 	a .setStatus (hpa , currentReplicas , hpa .Status .DesiredReplicas , hpa .Status .CurrentMetrics , false )
536548}
537549
538- func  (a  * HorizontalController ) updateStatusWithReplicas (hpa  * autoscalingv2.HorizontalPodAutoscaler , currentReplicas , desiredReplicas  int32 , metricStatuses  []autoscalingv2.MetricStatus , rescale  bool ) error  {
550+ // setStatus recreates the status of the given HPA, updating the current and 
551+ // desired replicas, as well as the metric statuses 
552+ func  (a  * HorizontalController ) setStatus (hpa  * autoscalingv2.HorizontalPodAutoscaler , currentReplicas , desiredReplicas  int32 , metricStatuses  []autoscalingv2.MetricStatus , rescale  bool ) {
539553	hpa .Status  =  autoscalingv2.HorizontalPodAutoscalerStatus {
540554		CurrentReplicas : currentReplicas ,
541555		DesiredReplicas : desiredReplicas ,
@@ -548,11 +562,19 @@ func (a *HorizontalController) updateStatusWithReplicas(hpa *autoscalingv2.Horiz
548562		now  :=  metav1 .NewTime (time .Now ())
549563		hpa .Status .LastScaleTime  =  & now 
550564	}
565+ }
551566
552- 	return  a .update (hpa )
567+ // updateStatusIfNeeded calls updateStatus only if the status of the new HPA is not the same as the old status 
568+ func  (a  * HorizontalController ) updateStatusIfNeeded (oldStatus  * autoscalingv2.HorizontalPodAutoscalerStatus , newHPA  * autoscalingv2.HorizontalPodAutoscaler ) error  {
569+ 	// skip a write if we wouldn't need to update 
570+ 	if  apiequality .Semantic .DeepEqual (oldStatus , & newHPA .Status ) {
571+ 		return  nil 
572+ 	}
573+ 	return  a .updateStatus (newHPA )
553574}
554575
555- func  (a  * HorizontalController ) update (hpa  * autoscalingv2.HorizontalPodAutoscaler ) error  {
576+ // updateStatus actually does the update request for the status of the given HPA 
577+ func  (a  * HorizontalController ) updateStatus (hpa  * autoscalingv2.HorizontalPodAutoscaler ) error  {
556578	// convert back to autoscalingv1 
557579	hpaRaw , err  :=  UnsafeConvertToVersionVia (hpa , autoscalingv1 .SchemeGroupVersion )
558580	if  err  !=  nil  {
0 commit comments