@@ -7030,11 +7030,12 @@ func TestBuildResizeTarget_OmitsLimitsWhenZero(t *testing.T) {
70307030 MemoryRequest : resource .MustParse ("128Mi" ),
70317031 },
70327032 }
7033- target , _ := buildResizeTarget (rec )
7033+ target , clamped := buildResizeTarget (rec )
70347034 assert .Equal (t , int64 (100 ), target .Requests .Cpu ().MilliValue ())
70357035 wantMem := resource .MustParse ("128Mi" )
70367036 assert .Equal (t , wantMem .Value (), target .Requests .Memory ().Value ())
70377037 assert .Nil (t , target .Limits , "Limits should be nil when recommendation limits are zero" )
7038+ assert .Empty (t , clamped , "nothing should be clamped when no limits present" )
70387039}
70397040
70407041func TestBuildResizeTarget_IncludesLimitsWhenNonZero (t * testing.T ) {
@@ -7047,11 +7048,12 @@ func TestBuildResizeTarget_IncludesLimitsWhenNonZero(t *testing.T) {
70477048 MemoryLimit : resource .MustParse ("256Mi" ),
70487049 },
70497050 }
7050- target , _ := buildResizeTarget (rec )
7051+ target , clamped := buildResizeTarget (rec )
70517052 require .NotNil (t , target .Limits )
70527053 assert .Equal (t , int64 (200 ), target .Limits .Cpu ().MilliValue ())
70537054 wantMemLim := resource .MustParse ("256Mi" )
70547055 assert .Equal (t , wantMemLim .Value (), target .Limits .Memory ().Value ())
7056+ assert .Empty (t , clamped , "nothing should be clamped when requests are below limits" )
70557057}
70567058
70577059func TestBuildResizeTarget_PartialLimits (t * testing.T ) {
@@ -7063,11 +7065,12 @@ func TestBuildResizeTarget_PartialLimits(t *testing.T) {
70637065 MemoryRequest : resource .MustParse ("128Mi" ),
70647066 },
70657067 }
7066- target , _ := buildResizeTarget (rec )
7068+ target , clamped := buildResizeTarget (rec )
70677069 require .NotNil (t , target .Limits , "Limits should be non-nil when any limit is non-zero" )
70687070 assert .Equal (t , int64 (200 ), target .Limits .Cpu ().MilliValue ())
70697071 _ , hasMemLimit := target .Limits [corev1 .ResourceMemory ]
70707072 assert .False (t , hasMemLimit , "Memory limit should not be set when zero in recommendation" )
7073+ assert .Empty (t , clamped , "nothing should be clamped when requests are below limits" )
70717074}
70727075
70737076func TestBuildResizeTarget_ClampsRequestsToLimits (t * testing.T ) {
@@ -7127,6 +7130,78 @@ func TestBuildResizeTarget_PartialClamping(t *testing.T) {
71277130 "only CPU should be reported as clamped" )
71287131}
71297132
7133+ func TestComputeRecommendations_NanInfSamplesMetric (t * testing.T ) {
7134+ policy := newTestPolicy ("test-policy" , "default" )
7135+ deploy := newTestDeployment ("api-server" , "default" , nil )
7136+ reconciler := newReconcilerWithClient ()
7137+
7138+ // Return NaN/Inf samples so BuildProfile yields 0 data points.
7139+ mc := & mockCollector {
7140+ queryRangeGroupedFunc : func (_ context.Context , query string , _ , _ time.Time , _ time.Duration ) (map [string ][]rsmetrics.Sample , error ) {
7141+ return map [string ][]rsmetrics.Sample {
7142+ "main" : {
7143+ {Timestamp : time .Now ().Add (- 1 * time .Hour ), Value : math .NaN ()},
7144+ {Timestamp : time .Now ().Add (- 2 * time .Hour ), Value : math .Inf (1 )},
7145+ {Timestamp : time .Now ().Add (- 3 * time .Hour ), Value : math .Inf (- 1 )},
7146+ },
7147+ }, nil
7148+ },
7149+ }
7150+
7151+ before := promtestutil .ToFloat64 (operatormetrics .NanInfSamplesTotal .WithLabelValues ("default" , "test-policy" , "main" , "cpu" ))
7152+ rec , _ , _ , _ , err := reconciler .computeRecommendations (context .Background (), policy , deploy , mc , nil , nil , nil , nil )
7153+ assert .NoError (t , err )
7154+ assert .Nil (t , rec , "should produce no recommendation when all data is NaN/Inf" )
7155+ after := promtestutil .ToFloat64 (operatormetrics .NanInfSamplesTotal .WithLabelValues ("default" , "test-policy" , "main" , "cpu" ))
7156+ assert .Equal (t , before + 1 , after , "NanInfSamplesTotal should increment for CPU" )
7157+ }
7158+
7159+ func TestExecuteResizes_RequestClampedMetric (t * testing.T ) {
7160+ pod := newResizePod ("api-server" , "600m" , "1Gi" , "500m" , "512Mi" )
7161+ deploy := newTestDeployment ("api-server" , "default" , map [string ]string {"app" : "api-server" })
7162+ policy := newTestPolicy ("test-policy" , "default" )
7163+ policy .Spec .UpdateStrategy .Type = attunev1alpha1 .UpdateTypeAuto
7164+ clientset := kubefake .NewSimpleClientset (pod )
7165+
7166+ reconciler := newReconcilerWithClient (pod , deploy )
7167+ reconciler .Clientset = clientset
7168+
7169+ recommendations := []attunev1alpha1.WorkloadRecommendation {
7170+ {
7171+ Workload : "api-server" ,
7172+ Kind : "Deployment" ,
7173+ Containers : []attunev1alpha1.ContainerRecommendation {
7174+ {
7175+ Name : "main" ,
7176+ Recommended : attunev1alpha1.ResourceValues {
7177+ CPURequest : resource .MustParse ("800m" ), // Will be clamped to 500m limit
7178+ MemoryRequest : resource .MustParse ("2Gi" ), // Will be clamped to 512Mi limit
7179+ CPULimit : resource .MustParse ("500m" ),
7180+ MemoryLimit : resource .MustParse ("512Mi" ),
7181+ },
7182+ Current : attunev1alpha1.ResourceValues {
7183+ CPURequest : resource .MustParse ("600m" ),
7184+ MemoryRequest : resource .MustParse ("1Gi" ),
7185+ CPULimit : resource .MustParse ("500m" ),
7186+ MemoryLimit : resource .MustParse ("512Mi" ),
7187+ },
7188+ },
7189+ },
7190+ },
7191+ }
7192+
7193+ beforeCPU := promtestutil .ToFloat64 (operatormetrics .RequestClampedTotal .WithLabelValues ("default" , "test-policy" , "main" , "cpu" ))
7194+ beforeMem := promtestutil .ToFloat64 (operatormetrics .RequestClampedTotal .WithLabelValues ("default" , "test-policy" , "main" , "memory" ))
7195+
7196+ reconciler .executeResizes (context .Background (), policy , []client.Object {deploy },
7197+ recommendations , podMap ("api-server" , pod ), nil , nil )
7198+
7199+ afterCPU := promtestutil .ToFloat64 (operatormetrics .RequestClampedTotal .WithLabelValues ("default" , "test-policy" , "main" , "cpu" ))
7200+ afterMem := promtestutil .ToFloat64 (operatormetrics .RequestClampedTotal .WithLabelValues ("default" , "test-policy" , "main" , "memory" ))
7201+ assert .Equal (t , beforeCPU + 1 , afterCPU , "RequestClampedTotal should increment for CPU" )
7202+ assert .Equal (t , beforeMem + 1 , afterMem , "RequestClampedTotal should increment for memory" )
7203+ }
7204+
71307205func TestTryEvictionFallback_EvictsWhenMultipleReplicas (t * testing.T ) {
71317206 pod1 := newTestPod ("api-server-abc-1" , "default" , map [string ]string {"app" : "api-server" })
71327207 pod2 := newTestPod ("api-server-abc-2" , "default" , map [string ]string {"app" : "api-server" })
0 commit comments