2019-10-08 23:01:40 -04:00
/ *
Copyright 2019 The Kubernetes Authors .
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
package noderesources
import (
2019-08-28 07:12:02 -04:00
"context"
2020-02-03 16:36:50 -05:00
"fmt"
2019-10-08 23:01:40 -04:00
"reflect"
"testing"
2023-02-04 23:58:42 -05:00
"github.com/google/go-cmp/cmp"
2019-08-28 07:12:02 -04:00
v1 "k8s.io/api/core/v1"
2019-10-08 23:01:40 -04:00
"k8s.io/apimachinery/pkg/api/resource"
2023-05-15 06:36:17 -04:00
"k8s.io/klog/v2/ktesting"
2020-03-05 01:41:18 -05:00
"k8s.io/kubernetes/pkg/scheduler/apis/config"
2020-10-09 10:41:44 -04:00
"k8s.io/kubernetes/pkg/scheduler/framework"
2021-01-29 16:35:38 -05:00
plfeature "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature"
2022-12-09 13:11:27 -05:00
plugintesting "k8s.io/kubernetes/pkg/scheduler/framework/plugins/testing"
2021-05-07 06:15:18 -04:00
"k8s.io/kubernetes/pkg/scheduler/framework/runtime"
"k8s.io/kubernetes/pkg/scheduler/internal/cache"
2021-11-02 12:52:23 -04:00
st "k8s.io/kubernetes/pkg/scheduler/testing"
2019-10-08 23:01:40 -04:00
)
var (
extendedResourceA = v1 . ResourceName ( "example.com/aaa" )
extendedResourceB = v1 . ResourceName ( "example.com/bbb" )
kubernetesIOResourceA = v1 . ResourceName ( "kubernetes.io/something" )
kubernetesIOResourceB = v1 . ResourceName ( "subdomain.kubernetes.io/something" )
2021-04-25 12:39:00 -04:00
hugePageResourceA = v1 . ResourceName ( v1 . ResourceHugePagesPrefix + "2Mi" )
2019-10-08 23:01:40 -04:00
)
func makeResources ( milliCPU , memory , pods , extendedA , storage , hugePageA int64 ) v1 . NodeResources {
return v1 . NodeResources {
Capacity : v1 . ResourceList {
v1 . ResourceCPU : * resource . NewMilliQuantity ( milliCPU , resource . DecimalSI ) ,
v1 . ResourceMemory : * resource . NewQuantity ( memory , resource . BinarySI ) ,
v1 . ResourcePods : * resource . NewQuantity ( pods , resource . DecimalSI ) ,
extendedResourceA : * resource . NewQuantity ( extendedA , resource . DecimalSI ) ,
v1 . ResourceEphemeralStorage : * resource . NewQuantity ( storage , resource . BinarySI ) ,
hugePageResourceA : * resource . NewQuantity ( hugePageA , resource . BinarySI ) ,
} ,
}
}
func makeAllocatableResources ( milliCPU , memory , pods , extendedA , storage , hugePageA int64 ) v1 . ResourceList {
return v1 . ResourceList {
v1 . ResourceCPU : * resource . NewMilliQuantity ( milliCPU , resource . DecimalSI ) ,
v1 . ResourceMemory : * resource . NewQuantity ( memory , resource . BinarySI ) ,
v1 . ResourcePods : * resource . NewQuantity ( pods , resource . DecimalSI ) ,
extendedResourceA : * resource . NewQuantity ( extendedA , resource . DecimalSI ) ,
v1 . ResourceEphemeralStorage : * resource . NewQuantity ( storage , resource . BinarySI ) ,
hugePageResourceA : * resource . NewQuantity ( hugePageA , resource . BinarySI ) ,
}
}
2020-04-06 21:40:15 -04:00
func newResourcePod ( usage ... framework . Resource ) * v1 . Pod {
2020-11-02 00:56:26 -05:00
var containers [ ] v1 . Container
2019-10-08 23:01:40 -04:00
for _ , req := range usage {
2021-04-25 12:39:00 -04:00
rl := v1 . ResourceList {
v1 . ResourceCPU : * resource . NewMilliQuantity ( req . MilliCPU , resource . DecimalSI ) ,
v1 . ResourceMemory : * resource . NewQuantity ( req . Memory , resource . BinarySI ) ,
v1 . ResourcePods : * resource . NewQuantity ( int64 ( req . AllowedPodNumber ) , resource . BinarySI ) ,
v1 . ResourceEphemeralStorage : * resource . NewQuantity ( req . EphemeralStorage , resource . BinarySI ) ,
}
for rName , rQuant := range req . ScalarResources {
if rName == hugePageResourceA {
rl [ rName ] = * resource . NewQuantity ( rQuant , resource . BinarySI )
} else {
rl [ rName ] = * resource . NewQuantity ( rQuant , resource . DecimalSI )
}
}
2019-10-08 23:01:40 -04:00
containers = append ( containers , v1 . Container {
2021-04-25 12:39:00 -04:00
Resources : v1 . ResourceRequirements { Requests : rl } ,
2019-10-08 23:01:40 -04:00
} )
}
return & v1 . Pod {
Spec : v1 . PodSpec {
Containers : containers ,
} ,
}
}
2020-04-06 21:40:15 -04:00
func newResourceInitPod ( pod * v1 . Pod , usage ... framework . Resource ) * v1 . Pod {
2019-10-08 23:01:40 -04:00
pod . Spec . InitContainers = newResourcePod ( usage ... ) . Spec . Containers
return pod
}
func newResourceOverheadPod ( pod * v1 . Pod , overhead v1 . ResourceList ) * v1 . Pod {
pod . Spec . Overhead = overhead
return pod
}
2020-01-13 13:02:19 -05:00
2020-02-03 16:36:50 -05:00
func getErrReason ( rn v1 . ResourceName ) string {
return fmt . Sprintf ( "Insufficient %v" , rn )
}
2021-05-07 06:15:18 -04:00
var defaultScoringStrategy = & config . ScoringStrategy {
Type : config . LeastAllocated ,
Resources : [ ] config . ResourceSpec {
{ Name : "cpu" , Weight : 1 } ,
{ Name : "memory" , Weight : 1 } ,
} ,
}
2020-01-13 13:02:19 -05:00
func TestEnoughRequests ( t * testing . T ) {
2019-10-08 23:01:40 -04:00
enoughPodsTests := [ ] struct {
2020-01-13 13:02:19 -05:00
pod * v1 . Pod
2020-04-06 21:40:15 -04:00
nodeInfo * framework . NodeInfo
2020-01-13 13:02:19 -05:00
name string
2020-04-15 13:37:56 -04:00
args config . NodeResourcesFitArgs
2020-01-13 13:02:19 -05:00
wantInsufficientResources [ ] InsufficientResource
wantStatus * framework . Status
2019-10-08 23:01:40 -04:00
} {
{
pod : & v1 . Pod { } ,
2020-04-06 21:40:15 -04:00
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 10 , Memory : 20 } ) ) ,
2020-02-03 16:36:50 -05:00
name : "no resources requested always fits" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 10 , Memory : 20 } ) ) ,
2021-11-24 21:34:43 -05:00
name : "too many resources fails" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( v1 . ResourceCPU ) , getErrReason ( v1 . ResourceMemory ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : v1 . ResourceCPU , Reason : getErrReason ( v1 . ResourceCPU ) , Requested : 1 , Used : 10 , Capacity : 10 } ,
{ ResourceName : v1 . ResourceMemory , Reason : getErrReason ( v1 . ResourceMemory ) , Requested : 1 , Used : 20 , Capacity : 20 } ,
} ,
2019-12-12 22:20:02 -05:00
} ,
2019-10-08 23:01:40 -04:00
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 1 } ) , framework . Resource { MilliCPU : 3 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 8 , Memory : 19 } ) ) ,
2021-11-24 21:34:43 -05:00
name : "too many resources fails due to init container cpu" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( v1 . ResourceCPU ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : v1 . ResourceCPU , Reason : getErrReason ( v1 . ResourceCPU ) , Requested : 3 , Used : 8 , Capacity : 10 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 1 } ) , framework . Resource { MilliCPU : 3 , Memory : 1 } , framework . Resource { MilliCPU : 2 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 8 , Memory : 19 } ) ) ,
2021-11-24 21:34:43 -05:00
name : "too many resources fails due to highest init container cpu" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( v1 . ResourceCPU ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : v1 . ResourceCPU , Reason : getErrReason ( v1 . ResourceCPU ) , Requested : 3 , Used : 8 , Capacity : 10 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 1 } ) , framework . Resource { MilliCPU : 1 , Memory : 3 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 9 , Memory : 19 } ) ) ,
2021-11-24 21:34:43 -05:00
name : "too many resources fails due to init container memory" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( v1 . ResourceMemory ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : v1 . ResourceMemory , Reason : getErrReason ( v1 . ResourceMemory ) , Requested : 3 , Used : 19 , Capacity : 20 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 1 } ) , framework . Resource { MilliCPU : 1 , Memory : 3 } , framework . Resource { MilliCPU : 1 , Memory : 2 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 9 , Memory : 19 } ) ) ,
2021-11-24 21:34:43 -05:00
name : "too many resources fails due to highest init container memory" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( v1 . ResourceMemory ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : v1 . ResourceMemory , Reason : getErrReason ( v1 . ResourceMemory ) , Requested : 3 , Used : 19 , Capacity : 20 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 1 } ) , framework . Resource { MilliCPU : 1 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 9 , Memory : 19 } ) ) ,
2020-02-03 16:36:50 -05:00
name : "init container fits because it's the max, not sum, of containers and init containers" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 1 } ) , framework . Resource { MilliCPU : 1 , Memory : 1 } , framework . Resource { MilliCPU : 1 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 9 , Memory : 19 } ) ) ,
2020-02-03 16:36:50 -05:00
name : "multiple init containers fit because it's the max, not sum, of containers and init containers" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 5 , Memory : 5 } ) ) ,
2020-02-03 16:36:50 -05:00
name : "both resources fit" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourcePod ( framework . Resource { MilliCPU : 2 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 9 , Memory : 5 } ) ) ,
2021-11-24 21:34:43 -05:00
name : "one resource memory fits" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( v1 . ResourceCPU ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : v1 . ResourceCPU , Reason : getErrReason ( v1 . ResourceCPU ) , Requested : 2 , Used : 9 , Capacity : 10 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 2 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 5 , Memory : 19 } ) ) ,
2021-11-24 21:34:43 -05:00
name : "one resource cpu fits" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( v1 . ResourceMemory ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : v1 . ResourceMemory , Reason : getErrReason ( v1 . ResourceMemory ) , Requested : 2 , Used : 19 , Capacity : 20 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourcePod ( framework . Resource { MilliCPU : 5 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 5 , Memory : 19 } ) ) ,
2020-02-03 16:36:50 -05:00
name : "equal edge case" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { MilliCPU : 4 , Memory : 1 } ) , framework . Resource { MilliCPU : 5 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 5 , Memory : 19 } ) ) ,
2020-02-03 16:36:50 -05:00
name : "equal edge case for init container" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourcePod ( framework . Resource { ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 1 } } ) ,
nodeInfo : framework . NewNodeInfo ( newResourcePod ( framework . Resource { } ) ) ,
2020-02-03 16:36:50 -05:00
name : "extended resource fits" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { } ) , framework . Resource { ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 1 } } ) ,
nodeInfo : framework . NewNodeInfo ( newResourcePod ( framework . Resource { } ) ) ,
2020-02-03 16:36:50 -05:00
name : "extended resource fits for init container" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
2019-10-08 23:01:40 -04:00
} ,
{
pod : newResourcePod (
2020-04-06 21:40:15 -04:00
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 10 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 0 } } ) ) ,
2021-11-24 21:34:43 -05:00
name : "extended resource capacity enforced" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( extendedResourceA ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : extendedResourceA , Reason : getErrReason ( extendedResourceA ) , Requested : 10 , Used : 0 , Capacity : 5 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { } ) ,
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 10 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 0 } } ) ) ,
2021-11-24 21:34:43 -05:00
name : "extended resource capacity enforced for init container" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( extendedResourceA ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : extendedResourceA , Reason : getErrReason ( extendedResourceA ) , Requested : 10 , Used : 0 , Capacity : 5 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
pod : newResourcePod (
2020-04-06 21:40:15 -04:00
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 1 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 5 } } ) ) ,
2021-11-24 21:34:43 -05:00
name : "extended resource allocatable enforced" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( extendedResourceA ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : extendedResourceA , Reason : getErrReason ( extendedResourceA ) , Requested : 1 , Used : 5 , Capacity : 5 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { } ) ,
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 1 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 5 } } ) ) ,
2021-11-24 21:34:43 -05:00
name : "extended resource allocatable enforced for init container" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( extendedResourceA ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : extendedResourceA , Reason : getErrReason ( extendedResourceA ) , Requested : 1 , Used : 5 , Capacity : 5 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
pod : newResourcePod (
2020-04-06 21:40:15 -04:00
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 3 } } ,
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 3 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 2 } } ) ) ,
2021-11-24 21:34:43 -05:00
name : "extended resource allocatable enforced for multiple containers" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( extendedResourceA ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : extendedResourceA , Reason : getErrReason ( extendedResourceA ) , Requested : 6 , Used : 2 , Capacity : 5 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { } ) ,
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 3 } } ,
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 3 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 2 } } ) ) ,
2020-02-03 16:36:50 -05:00
name : "extended resource allocatable admits multiple init containers" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { } ) ,
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 6 } } ,
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 3 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 2 } } ) ) ,
2021-11-24 21:34:43 -05:00
name : "extended resource allocatable enforced for multiple init containers" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( extendedResourceA ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : extendedResourceA , Reason : getErrReason ( extendedResourceA ) , Requested : 6 , Used : 2 , Capacity : 5 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
pod : newResourcePod (
2020-04-06 21:40:15 -04:00
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceB : 1 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 } ) ) ,
2021-11-24 21:34:43 -05:00
name : "extended resource allocatable enforced for unknown resource" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( extendedResourceB ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : extendedResourceB , Reason : getErrReason ( extendedResourceB ) , Requested : 1 , Used : 0 , Capacity : 0 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { } ) ,
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceB : 1 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 } ) ) ,
2021-11-24 21:34:43 -05:00
name : "extended resource allocatable enforced for unknown resource for init container" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( extendedResourceB ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : extendedResourceB , Reason : getErrReason ( extendedResourceB ) , Requested : 1 , Used : 0 , Capacity : 0 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
pod : newResourcePod (
2020-04-06 21:40:15 -04:00
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { kubernetesIOResourceA : 10 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 } ) ) ,
2021-11-24 21:34:43 -05:00
name : "kubernetes.io resource capacity enforced" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( kubernetesIOResourceA ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : kubernetesIOResourceA , Reason : getErrReason ( kubernetesIOResourceA ) , Requested : 10 , Used : 0 , Capacity : 0 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { } ) ,
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { kubernetesIOResourceB : 10 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 } ) ) ,
2021-11-24 21:34:43 -05:00
name : "kubernetes.io resource capacity enforced for init container" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( kubernetesIOResourceB ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : kubernetesIOResourceB , Reason : getErrReason ( kubernetesIOResourceB ) , Requested : 10 , Used : 0 , Capacity : 0 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
pod : newResourcePod (
2020-04-06 21:40:15 -04:00
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { hugePageResourceA : 10 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 , ScalarResources : map [ v1 . ResourceName ] int64 { hugePageResourceA : 0 } } ) ) ,
2021-11-24 21:34:43 -05:00
name : "hugepages resource capacity enforced" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( hugePageResourceA ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : hugePageResourceA , Reason : getErrReason ( hugePageResourceA ) , Requested : 10 , Used : 0 , Capacity : 5 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { } ) ,
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { hugePageResourceA : 10 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 , ScalarResources : map [ v1 . ResourceName ] int64 { hugePageResourceA : 0 } } ) ) ,
2021-11-24 21:34:43 -05:00
name : "hugepages resource capacity enforced for init container" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( hugePageResourceA ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : hugePageResourceA , Reason : getErrReason ( hugePageResourceA ) , Requested : 10 , Used : 0 , Capacity : 5 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
pod : newResourcePod (
2020-04-06 21:40:15 -04:00
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { hugePageResourceA : 3 } } ,
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { hugePageResourceA : 3 } } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 , ScalarResources : map [ v1 . ResourceName ] int64 { hugePageResourceA : 2 } } ) ) ,
2021-11-24 21:34:43 -05:00
name : "hugepages resource allocatable enforced for multiple containers" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( hugePageResourceA ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : hugePageResourceA , Reason : getErrReason ( hugePageResourceA ) , Requested : 6 , Used : 2 , Capacity : 5 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
{
pod : newResourcePod (
2020-04-06 21:40:15 -04:00
framework . Resource { MilliCPU : 1 , Memory : 1 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceB : 1 } } ) ,
2020-04-15 13:37:56 -04:00
nodeInfo : framework . NewNodeInfo ( newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 } ) ) ,
args : config . NodeResourcesFitArgs {
IgnoredResources : [ ] string { "example.com/bbb" } ,
} ,
2020-02-03 16:36:50 -05:00
name : "skip checking ignored extended resource" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
2019-10-08 23:01:40 -04:00
} ,
{
pod : newResourceOverheadPod (
2020-04-06 21:40:15 -04:00
newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 1 } ) ,
2019-10-08 23:01:40 -04:00
v1 . ResourceList { v1 . ResourceCPU : resource . MustParse ( "3m" ) , v1 . ResourceMemory : resource . MustParse ( "13" ) } ,
) ,
2020-04-06 21:40:15 -04:00
nodeInfo : framework . NewNodeInfo ( newResourcePod ( framework . Resource { MilliCPU : 5 , Memory : 5 } ) ) ,
2020-02-03 16:36:50 -05:00
name : "resources + pod overhead fits" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
2019-10-08 23:01:40 -04:00
} ,
{
pod : newResourceOverheadPod (
2020-04-06 21:40:15 -04:00
newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 1 } ) ,
2019-10-08 23:01:40 -04:00
v1 . ResourceList { v1 . ResourceCPU : resource . MustParse ( "1m" ) , v1 . ResourceMemory : resource . MustParse ( "15" ) } ,
) ,
2021-11-24 21:34:43 -05:00
nodeInfo : framework . NewNodeInfo ( newResourcePod ( framework . Resource { MilliCPU : 5 , Memory : 5 } ) ) ,
name : "requests + overhead does not fit for memory" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( v1 . ResourceMemory ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{ ResourceName : v1 . ResourceMemory , Reason : getErrReason ( v1 . ResourceMemory ) , Requested : 16 , Used : 5 , Capacity : 20 } ,
} ,
2019-10-08 23:01:40 -04:00
} ,
2020-03-05 01:41:18 -05:00
{
pod : newResourcePod (
framework . Resource {
MilliCPU : 1 ,
Memory : 1 ,
ScalarResources : map [ v1 . ResourceName ] int64 {
extendedResourceB : 1 ,
kubernetesIOResourceA : 1 ,
} } ) ,
nodeInfo : framework . NewNodeInfo ( newResourcePod ( framework . Resource { MilliCPU : 0 , Memory : 0 } ) ) ,
args : config . NodeResourcesFitArgs {
IgnoredResourceGroups : [ ] string { "example.com" } ,
} ,
name : "skip checking ignored extended resource via resource groups" ,
wantStatus : framework . NewStatus ( framework . Unschedulable , fmt . Sprintf ( "Insufficient %v" , kubernetesIOResourceA ) ) ,
wantInsufficientResources : [ ] InsufficientResource {
{
ResourceName : kubernetesIOResourceA ,
Reason : fmt . Sprintf ( "Insufficient %v" , kubernetesIOResourceA ) ,
Requested : 1 ,
Used : 0 ,
Capacity : 0 ,
} ,
} ,
} ,
2022-07-29 11:23:25 -04:00
{
pod : newResourcePod (
framework . Resource {
MilliCPU : 1 ,
Memory : 1 ,
ScalarResources : map [ v1 . ResourceName ] int64 {
extendedResourceA : 0 ,
} } ) ,
nodeInfo : framework . NewNodeInfo ( newResourcePod ( framework . Resource {
MilliCPU : 0 , Memory : 0 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 6 } } ) ) ,
name : "skip checking extended resource request with quantity zero via resource groups" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
} ,
2023-03-09 04:05:11 -05:00
{
pod : newResourcePod (
framework . Resource {
ScalarResources : map [ v1 . ResourceName ] int64 {
extendedResourceA : 1 ,
} } ) ,
nodeInfo : framework . NewNodeInfo ( newResourcePod ( framework . Resource {
MilliCPU : 20 , Memory : 30 , ScalarResources : map [ v1 . ResourceName ] int64 { extendedResourceA : 1 } } ) ) ,
name : "skip checking resource request with quantity zero" ,
wantInsufficientResources : [ ] InsufficientResource { } ,
} ,
2019-10-08 23:01:40 -04:00
}
for _ , test := range enoughPodsTests {
t . Run ( test . name , func ( t * testing . T ) {
node := v1 . Node { Status : v1 . NodeStatus { Capacity : makeResources ( 10 , 20 , 32 , 5 , 20 , 5 ) . Capacity , Allocatable : makeAllocatableResources ( 10 , 20 , 32 , 5 , 20 , 5 ) } }
test . nodeInfo . SetNode ( & node )
2021-05-07 06:15:18 -04:00
if test . args . ScoringStrategy == nil {
test . args . ScoringStrategy = defaultScoringStrategy
}
2023-09-05 23:55:33 -04:00
_ , ctx := ktesting . NewTestContext ( t )
ctx , cancel := context . WithCancel ( ctx )
defer cancel ( )
p , err := NewFit ( ctx , & test . args , nil , plfeature . Features { } )
2020-04-15 13:37:56 -04:00
if err != nil {
t . Fatal ( err )
}
2019-12-12 22:20:02 -05:00
cycleState := framework . NewCycleState ( )
2023-09-05 23:55:33 -04:00
_ , preFilterStatus := p . ( framework . PreFilterPlugin ) . PreFilter ( ctx , cycleState , test . pod )
2020-01-13 13:02:19 -05:00
if ! preFilterStatus . IsSuccess ( ) {
t . Errorf ( "prefilter failed with status: %v" , preFilterStatus )
}
2023-09-05 23:55:33 -04:00
gotStatus := p . ( framework . FilterPlugin ) . Filter ( ctx , cycleState , test . pod , test . nodeInfo )
2020-01-13 13:02:19 -05:00
if ! reflect . DeepEqual ( gotStatus , test . wantStatus ) {
t . Errorf ( "status does not match: %v, want: %v" , gotStatus , test . wantStatus )
}
2022-03-15 02:50:27 -04:00
gotInsufficientResources := fitsRequest ( computePodResourceRequest ( test . pod ) , test . nodeInfo , p . ( * Fit ) . ignoredResources , p . ( * Fit ) . ignoredResourceGroups )
2020-01-13 13:02:19 -05:00
if ! reflect . DeepEqual ( gotInsufficientResources , test . wantInsufficientResources ) {
2020-03-05 01:41:18 -05:00
t . Errorf ( "insufficient resources do not match: %+v, want: %v" , gotInsufficientResources , test . wantInsufficientResources )
2020-01-13 13:02:19 -05:00
}
2019-10-08 23:01:40 -04:00
} )
}
2020-01-13 13:02:19 -05:00
}
2019-10-08 23:01:40 -04:00
2020-02-11 03:51:21 -05:00
func TestPreFilterDisabled ( t * testing . T ) {
2023-09-05 23:55:33 -04:00
_ , ctx := ktesting . NewTestContext ( t )
ctx , cancel := context . WithCancel ( ctx )
defer cancel ( )
2020-02-11 03:51:21 -05:00
pod := & v1 . Pod { }
2020-04-06 21:40:15 -04:00
nodeInfo := framework . NewNodeInfo ( )
2020-02-11 03:51:21 -05:00
node := v1 . Node { }
nodeInfo . SetNode ( & node )
2023-09-05 23:55:33 -04:00
p , err := NewFit ( ctx , & config . NodeResourcesFitArgs { ScoringStrategy : defaultScoringStrategy } , nil , plfeature . Features { } )
2020-04-30 18:11:37 -04:00
if err != nil {
t . Fatal ( err )
}
2020-02-11 03:51:21 -05:00
cycleState := framework . NewCycleState ( )
2023-09-05 23:55:33 -04:00
gotStatus := p . ( framework . FilterPlugin ) . Filter ( ctx , cycleState , pod , nodeInfo )
2021-02-23 20:57:28 -05:00
wantStatus := framework . AsStatus ( fmt . Errorf ( ` error reading "PreFilterNodeResourcesFit" from cycleState: %w ` , framework . ErrNotFound ) )
2020-02-11 03:51:21 -05:00
if ! reflect . DeepEqual ( gotStatus , wantStatus ) {
t . Errorf ( "status does not match: %v, want: %v" , gotStatus , wantStatus )
}
}
2020-01-13 13:02:19 -05:00
func TestNotEnoughRequests ( t * testing . T ) {
2019-10-08 23:01:40 -04:00
notEnoughPodsTests := [ ] struct {
pod * v1 . Pod
2020-04-06 21:40:15 -04:00
nodeInfo * framework . NodeInfo
2019-10-08 23:01:40 -04:00
fits bool
name string
wantStatus * framework . Status
} {
{
2020-01-13 13:02:19 -05:00
pod : & v1 . Pod { } ,
2020-04-06 21:40:15 -04:00
nodeInfo : framework . NewNodeInfo ( newResourcePod ( framework . Resource { MilliCPU : 10 , Memory : 20 } ) ) ,
2023-02-25 23:53:04 -05:00
name : "even without specified resources, predicate fails when there's no space for additional pod" ,
2020-02-03 16:36:50 -05:00
wantStatus : framework . NewStatus ( framework . Unschedulable , "Too many pods" ) ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo ( newResourcePod ( framework . Resource { MilliCPU : 5 , Memory : 5 } ) ) ,
2023-02-25 23:53:04 -05:00
name : "even if both resources fit, predicate fails when there's no space for additional pod" ,
2020-02-03 16:36:50 -05:00
wantStatus : framework . NewStatus ( framework . Unschedulable , "Too many pods" ) ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourcePod ( framework . Resource { MilliCPU : 5 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo ( newResourcePod ( framework . Resource { MilliCPU : 5 , Memory : 19 } ) ) ,
2023-02-25 23:53:04 -05:00
name : "even for equal edge case, predicate fails when there's no space for additional pod" ,
2020-02-03 16:36:50 -05:00
wantStatus : framework . NewStatus ( framework . Unschedulable , "Too many pods" ) ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { MilliCPU : 5 , Memory : 1 } ) , framework . Resource { MilliCPU : 5 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo ( newResourcePod ( framework . Resource { MilliCPU : 5 , Memory : 19 } ) ) ,
2023-02-25 23:53:04 -05:00
name : "even for equal edge case, predicate fails when there's no space for additional pod due to init container" ,
2020-02-03 16:36:50 -05:00
wantStatus : framework . NewStatus ( framework . Unschedulable , "Too many pods" ) ,
2019-10-08 23:01:40 -04:00
} ,
}
for _ , test := range notEnoughPodsTests {
t . Run ( test . name , func ( t * testing . T ) {
2023-09-05 23:55:33 -04:00
_ , ctx := ktesting . NewTestContext ( t )
ctx , cancel := context . WithCancel ( ctx )
defer cancel ( )
2019-10-08 23:01:40 -04:00
node := v1 . Node { Status : v1 . NodeStatus { Capacity : v1 . ResourceList { } , Allocatable : makeAllocatableResources ( 10 , 20 , 1 , 0 , 0 , 0 ) } }
test . nodeInfo . SetNode ( & node )
2023-09-05 23:55:33 -04:00
p , err := NewFit ( ctx , & config . NodeResourcesFitArgs { ScoringStrategy : defaultScoringStrategy } , nil , plfeature . Features { } )
2020-04-30 18:11:37 -04:00
if err != nil {
t . Fatal ( err )
}
2019-12-12 22:20:02 -05:00
cycleState := framework . NewCycleState ( )
2023-09-05 23:55:33 -04:00
_ , preFilterStatus := p . ( framework . PreFilterPlugin ) . PreFilter ( ctx , cycleState , test . pod )
2019-12-12 22:20:02 -05:00
if ! preFilterStatus . IsSuccess ( ) {
t . Errorf ( "prefilter failed with status: %v" , preFilterStatus )
}
2023-09-05 23:55:33 -04:00
gotStatus := p . ( framework . FilterPlugin ) . Filter ( ctx , cycleState , test . pod , test . nodeInfo )
2019-10-08 23:01:40 -04:00
if ! reflect . DeepEqual ( gotStatus , test . wantStatus ) {
t . Errorf ( "status does not match: %v, want: %v" , gotStatus , test . wantStatus )
}
} )
}
2020-01-13 13:02:19 -05:00
}
func TestStorageRequests ( t * testing . T ) {
2019-10-08 23:01:40 -04:00
storagePodsTests := [ ] struct {
pod * v1 . Pod
2020-04-06 21:40:15 -04:00
nodeInfo * framework . NodeInfo
2019-10-08 23:01:40 -04:00
name string
wantStatus * framework . Status
} {
{
2020-04-06 21:40:15 -04:00
pod : newResourcePod ( framework . Resource { MilliCPU : 1 , Memory : 1 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 2 , Memory : 10 } ) ) ,
2023-02-25 23:53:04 -05:00
name : "empty storage requested, and pod fits" ,
2019-10-08 23:01:40 -04:00
} ,
{
2020-04-06 21:40:15 -04:00
pod : newResourcePod ( framework . Resource { EphemeralStorage : 25 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 2 , Memory : 2 } ) ) ,
2019-10-08 23:01:40 -04:00
name : "storage ephemeral local storage request exceeds allocatable" ,
2020-01-13 13:02:19 -05:00
wantStatus : framework . NewStatus ( framework . Unschedulable , getErrReason ( v1 . ResourceEphemeralStorage ) ) ,
2019-10-08 23:01:40 -04:00
} ,
2020-11-02 00:56:26 -05:00
{
2022-07-28 11:03:20 -04:00
pod : newResourceInitPod ( newResourcePod ( framework . Resource { EphemeralStorage : 5 } ) ) ,
2020-11-02 00:56:26 -05:00
nodeInfo : framework . NewNodeInfo (
2022-07-28 11:03:20 -04:00
newResourcePod ( framework . Resource { MilliCPU : 2 , Memory : 2 , EphemeralStorage : 10 } ) ) ,
name : "ephemeral local storage is sufficient" ,
2020-11-02 00:56:26 -05:00
} ,
2019-10-08 23:01:40 -04:00
{
2020-04-06 21:40:15 -04:00
pod : newResourcePod ( framework . Resource { EphemeralStorage : 10 } ) ,
nodeInfo : framework . NewNodeInfo (
newResourcePod ( framework . Resource { MilliCPU : 2 , Memory : 2 } ) ) ,
2019-10-08 23:01:40 -04:00
name : "pod fits" ,
} ,
}
for _ , test := range storagePodsTests {
t . Run ( test . name , func ( t * testing . T ) {
2023-09-05 23:55:33 -04:00
_ , ctx := ktesting . NewTestContext ( t )
ctx , cancel := context . WithCancel ( ctx )
defer cancel ( )
2019-10-08 23:01:40 -04:00
node := v1 . Node { Status : v1 . NodeStatus { Capacity : makeResources ( 10 , 20 , 32 , 5 , 20 , 5 ) . Capacity , Allocatable : makeAllocatableResources ( 10 , 20 , 32 , 5 , 20 , 5 ) } }
test . nodeInfo . SetNode ( & node )
2023-09-05 23:55:33 -04:00
p , err := NewFit ( ctx , & config . NodeResourcesFitArgs { ScoringStrategy : defaultScoringStrategy } , nil , plfeature . Features { } )
2020-04-30 18:11:37 -04:00
if err != nil {
t . Fatal ( err )
}
2019-12-12 22:20:02 -05:00
cycleState := framework . NewCycleState ( )
2023-09-05 23:55:33 -04:00
_ , preFilterStatus := p . ( framework . PreFilterPlugin ) . PreFilter ( ctx , cycleState , test . pod )
2019-12-12 22:20:02 -05:00
if ! preFilterStatus . IsSuccess ( ) {
t . Errorf ( "prefilter failed with status: %v" , preFilterStatus )
}
2023-09-05 23:55:33 -04:00
gotStatus := p . ( framework . FilterPlugin ) . Filter ( ctx , cycleState , test . pod , test . nodeInfo )
2019-10-08 23:01:40 -04:00
if ! reflect . DeepEqual ( gotStatus , test . wantStatus ) {
t . Errorf ( "status does not match: %v, want: %v" , gotStatus , test . wantStatus )
}
} )
}
}
2021-05-07 06:15:18 -04:00
2023-05-16 10:41:53 -04:00
func TestRestartableInitContainers ( t * testing . T ) {
newPod := func ( ) * v1 . Pod {
return & v1 . Pod {
Spec : v1 . PodSpec {
Containers : [ ] v1 . Container {
{ Name : "regular" } ,
} ,
} ,
}
}
newPodWithRestartableInitContainers := func ( ) * v1 . Pod {
restartPolicyAlways := v1 . ContainerRestartPolicyAlways
return & v1 . Pod {
Spec : v1 . PodSpec {
Containers : [ ] v1 . Container {
{ Name : "regular" } ,
} ,
InitContainers : [ ] v1 . Container {
{
Name : "restartable-init" ,
RestartPolicy : & restartPolicyAlways ,
} ,
} ,
} ,
}
}
testCases := [ ] struct {
name string
pod * v1 . Pod
enableSidecarContainers bool
wantStatus * framework . Status
} {
{
name : "allow pod without restartable init containers if sidecar containers is disabled" ,
pod : newPod ( ) ,
} ,
{
name : "not allow pod with restartable init containers if sidecar containers is disabled" ,
pod : newPodWithRestartableInitContainers ( ) ,
wantStatus : framework . NewStatus ( framework . UnschedulableAndUnresolvable , "Pod has a restartable init container and the SidecarContainers feature is disabled" ) ,
} ,
{
name : "allow pod without restartable init containers if sidecar containers is enabled" ,
enableSidecarContainers : true ,
pod : newPod ( ) ,
} ,
{
name : "allow pod with restartable init containers if sidecar containers is enabled" ,
enableSidecarContainers : true ,
pod : newPodWithRestartableInitContainers ( ) ,
} ,
}
for _ , test := range testCases {
t . Run ( test . name , func ( t * testing . T ) {
2023-09-05 23:55:33 -04:00
_ , ctx := ktesting . NewTestContext ( t )
ctx , cancel := context . WithCancel ( ctx )
defer cancel ( )
2023-05-16 10:41:53 -04:00
node := v1 . Node { Status : v1 . NodeStatus { Capacity : v1 . ResourceList { } , Allocatable : makeAllocatableResources ( 0 , 0 , 1 , 0 , 0 , 0 ) } }
nodeInfo := framework . NewNodeInfo ( )
nodeInfo . SetNode ( & node )
2023-09-05 23:55:33 -04:00
p , err := NewFit ( ctx , & config . NodeResourcesFitArgs { ScoringStrategy : defaultScoringStrategy } , nil , plfeature . Features { EnableSidecarContainers : test . enableSidecarContainers } )
2023-05-16 10:41:53 -04:00
if err != nil {
t . Fatal ( err )
}
cycleState := framework . NewCycleState ( )
_ , preFilterStatus := p . ( framework . PreFilterPlugin ) . PreFilter ( context . Background ( ) , cycleState , test . pod )
if ! preFilterStatus . IsSuccess ( ) {
t . Errorf ( "prefilter failed with status: %v" , preFilterStatus )
}
gotStatus := p . ( framework . FilterPlugin ) . Filter ( context . Background ( ) , cycleState , test . pod , nodeInfo )
if diff := cmp . Diff ( gotStatus , test . wantStatus ) ; diff != "" {
t . Errorf ( "status does not match: %v, want: %v" , gotStatus , test . wantStatus )
}
} )
}
}
2021-05-07 06:15:18 -04:00
func TestFitScore ( t * testing . T ) {
2021-11-02 12:52:23 -04:00
tests := [ ] struct {
2021-05-07 06:15:18 -04:00
name string
requestedPod * v1 . Pod
nodes [ ] * v1 . Node
2021-11-02 12:52:23 -04:00
existingPods [ ] * v1 . Pod
2021-05-07 06:15:18 -04:00
expectedPriorities framework . NodeScoreList
nodeResourcesFitArgs config . NodeResourcesFitArgs
2023-03-10 10:44:53 -05:00
runPreScore bool
2021-11-02 12:52:23 -04:00
} {
2021-05-07 06:15:18 -04:00
{
2021-11-02 12:52:23 -04:00
name : "test case for ScoringStrategy RequestedToCapacityRatio case1" ,
requestedPod : st . MakePod ( ) .
Req ( map [ v1 . ResourceName ] string { "cpu" : "3000" , "memory" : "5000" } ) .
Obj ( ) ,
nodes : [ ] * v1 . Node {
st . MakeNode ( ) . Name ( "node1" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "4000" , "memory" : "10000" } ) . Obj ( ) ,
st . MakeNode ( ) . Name ( "node2" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "6000" , "memory" : "10000" } ) . Obj ( ) ,
} ,
existingPods : [ ] * v1 . Pod {
st . MakePod ( ) . Node ( "node1" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "2000" , "memory" : "4000" } ) . Obj ( ) ,
st . MakePod ( ) . Node ( "node2" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "1000" , "memory" : "2000" } ) . Obj ( ) ,
} ,
2021-05-07 06:15:18 -04:00
expectedPriorities : [ ] framework . NodeScore { { Name : "node1" , Score : 10 } , { Name : "node2" , Score : 32 } } ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
2021-11-02 12:52:23 -04:00
Type : config . RequestedToCapacityRatio ,
Resources : defaultResources ,
2021-05-07 06:15:18 -04:00
RequestedToCapacityRatio : & config . RequestedToCapacityRatioParam {
Shape : [ ] config . UtilizationShapePoint {
{ Utilization : 0 , Score : 10 } ,
{ Utilization : 100 , Score : 0 } ,
} ,
} ,
} ,
} ,
2023-03-10 10:44:53 -05:00
runPreScore : true ,
2021-05-07 06:15:18 -04:00
} ,
{
2021-11-02 12:52:23 -04:00
name : "test case for ScoringStrategy RequestedToCapacityRatio case2" ,
requestedPod : st . MakePod ( ) .
Req ( map [ v1 . ResourceName ] string { "cpu" : "3000" , "memory" : "5000" } ) .
Obj ( ) ,
nodes : [ ] * v1 . Node {
st . MakeNode ( ) . Name ( "node1" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "4000" , "memory" : "10000" } ) . Obj ( ) ,
st . MakeNode ( ) . Name ( "node2" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "6000" , "memory" : "10000" } ) . Obj ( ) ,
} ,
existingPods : [ ] * v1 . Pod {
st . MakePod ( ) . Node ( "node1" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "2000" , "memory" : "4000" } ) . Obj ( ) ,
st . MakePod ( ) . Node ( "node2" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "1000" , "memory" : "2000" } ) . Obj ( ) ,
} ,
2021-05-07 06:15:18 -04:00
expectedPriorities : [ ] framework . NodeScore { { Name : "node1" , Score : 95 } , { Name : "node2" , Score : 68 } } ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
2021-11-02 12:52:23 -04:00
Type : config . RequestedToCapacityRatio ,
Resources : defaultResources ,
2021-05-07 06:15:18 -04:00
RequestedToCapacityRatio : & config . RequestedToCapacityRatioParam {
Shape : [ ] config . UtilizationShapePoint {
{ Utilization : 0 , Score : 0 } ,
{ Utilization : 100 , Score : 10 } ,
} ,
} ,
} ,
} ,
2023-03-10 10:44:53 -05:00
runPreScore : true ,
2021-05-07 06:15:18 -04:00
} ,
{
2021-11-02 12:52:23 -04:00
name : "test case for ScoringStrategy MostAllocated" ,
requestedPod : st . MakePod ( ) .
Req ( map [ v1 . ResourceName ] string { "cpu" : "1000" , "memory" : "2000" } ) .
Obj ( ) ,
nodes : [ ] * v1 . Node {
st . MakeNode ( ) . Name ( "node1" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "4000" , "memory" : "10000" } ) . Obj ( ) ,
st . MakeNode ( ) . Name ( "node2" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "6000" , "memory" : "10000" } ) . Obj ( ) ,
} ,
existingPods : [ ] * v1 . Pod {
st . MakePod ( ) . Node ( "node1" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "2000" , "memory" : "4000" } ) . Obj ( ) ,
st . MakePod ( ) . Node ( "node2" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "1000" , "memory" : "2000" } ) . Obj ( ) ,
} ,
2021-05-07 06:15:18 -04:00
expectedPriorities : [ ] framework . NodeScore { { Name : "node1" , Score : 67 } , { Name : "node2" , Score : 36 } } ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
2021-11-02 12:52:23 -04:00
Type : config . MostAllocated ,
Resources : defaultResources ,
2021-05-07 06:15:18 -04:00
} ,
} ,
2023-03-10 10:44:53 -05:00
runPreScore : true ,
2021-05-07 06:15:18 -04:00
} ,
{
2021-11-02 12:52:23 -04:00
name : "test case for ScoringStrategy LeastAllocated" ,
requestedPod : st . MakePod ( ) .
Req ( map [ v1 . ResourceName ] string { "cpu" : "1000" , "memory" : "2000" } ) .
Obj ( ) ,
nodes : [ ] * v1 . Node {
st . MakeNode ( ) . Name ( "node1" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "4000" , "memory" : "10000" } ) . Obj ( ) ,
st . MakeNode ( ) . Name ( "node2" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "6000" , "memory" : "10000" } ) . Obj ( ) ,
} ,
existingPods : [ ] * v1 . Pod {
st . MakePod ( ) . Node ( "node1" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "2000" , "memory" : "4000" } ) . Obj ( ) ,
st . MakePod ( ) . Node ( "node2" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "1000" , "memory" : "2000" } ) . Obj ( ) ,
} ,
2021-05-07 06:15:18 -04:00
expectedPriorities : [ ] framework . NodeScore { { Name : "node1" , Score : 32 } , { Name : "node2" , Score : 63 } } ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
2021-11-02 12:52:23 -04:00
Type : config . LeastAllocated ,
Resources : defaultResources ,
2021-05-07 06:15:18 -04:00
} ,
} ,
2023-03-10 10:44:53 -05:00
runPreScore : true ,
} ,
{
name : "test case for ScoringStrategy RequestedToCapacityRatio case1 if PreScore is not called" ,
requestedPod : st . MakePod ( ) .
Req ( map [ v1 . ResourceName ] string { "cpu" : "3000" , "memory" : "5000" } ) .
Obj ( ) ,
nodes : [ ] * v1 . Node {
st . MakeNode ( ) . Name ( "node1" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "4000" , "memory" : "10000" } ) . Obj ( ) ,
st . MakeNode ( ) . Name ( "node2" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "6000" , "memory" : "10000" } ) . Obj ( ) ,
} ,
existingPods : [ ] * v1 . Pod {
st . MakePod ( ) . Node ( "node1" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "2000" , "memory" : "4000" } ) . Obj ( ) ,
st . MakePod ( ) . Node ( "node2" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "1000" , "memory" : "2000" } ) . Obj ( ) ,
} ,
expectedPriorities : [ ] framework . NodeScore { { Name : "node1" , Score : 10 } , { Name : "node2" , Score : 32 } } ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
Type : config . RequestedToCapacityRatio ,
Resources : defaultResources ,
RequestedToCapacityRatio : & config . RequestedToCapacityRatioParam {
Shape : [ ] config . UtilizationShapePoint {
{ Utilization : 0 , Score : 10 } ,
{ Utilization : 100 , Score : 0 } ,
} ,
} ,
} ,
} ,
runPreScore : false ,
} ,
{
name : "test case for ScoringStrategy MostAllocated if PreScore is not called" ,
requestedPod : st . MakePod ( ) .
Req ( map [ v1 . ResourceName ] string { "cpu" : "1000" , "memory" : "2000" } ) .
Obj ( ) ,
nodes : [ ] * v1 . Node {
st . MakeNode ( ) . Name ( "node1" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "4000" , "memory" : "10000" } ) . Obj ( ) ,
st . MakeNode ( ) . Name ( "node2" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "6000" , "memory" : "10000" } ) . Obj ( ) ,
} ,
existingPods : [ ] * v1 . Pod {
st . MakePod ( ) . Node ( "node1" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "2000" , "memory" : "4000" } ) . Obj ( ) ,
st . MakePod ( ) . Node ( "node2" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "1000" , "memory" : "2000" } ) . Obj ( ) ,
} ,
expectedPriorities : [ ] framework . NodeScore { { Name : "node1" , Score : 67 } , { Name : "node2" , Score : 36 } } ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
Type : config . MostAllocated ,
Resources : defaultResources ,
} ,
} ,
runPreScore : false ,
} ,
{
name : "test case for ScoringStrategy LeastAllocated if PreScore is not called" ,
requestedPod : st . MakePod ( ) .
Req ( map [ v1 . ResourceName ] string { "cpu" : "1000" , "memory" : "2000" } ) .
Obj ( ) ,
nodes : [ ] * v1 . Node {
st . MakeNode ( ) . Name ( "node1" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "4000" , "memory" : "10000" } ) . Obj ( ) ,
st . MakeNode ( ) . Name ( "node2" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "6000" , "memory" : "10000" } ) . Obj ( ) ,
} ,
existingPods : [ ] * v1 . Pod {
st . MakePod ( ) . Node ( "node1" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "2000" , "memory" : "4000" } ) . Obj ( ) ,
st . MakePod ( ) . Node ( "node2" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "1000" , "memory" : "2000" } ) . Obj ( ) ,
} ,
expectedPriorities : [ ] framework . NodeScore { { Name : "node1" , Score : 32 } , { Name : "node2" , Score : 63 } } ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
Type : config . LeastAllocated ,
Resources : defaultResources ,
} ,
} ,
runPreScore : false ,
2021-05-07 06:15:18 -04:00
} ,
}
for _ , test := range tests {
t . Run ( test . name , func ( t * testing . T ) {
2023-05-15 06:36:17 -04:00
_ , ctx := ktesting . NewTestContext ( t )
ctx , cancel := context . WithCancel ( ctx )
2022-08-05 12:05:22 -04:00
defer cancel ( )
2021-05-07 06:15:18 -04:00
state := framework . NewCycleState ( )
2021-11-02 12:52:23 -04:00
snapshot := cache . NewSnapshot ( test . existingPods , test . nodes )
2023-05-15 06:36:17 -04:00
fh , _ := runtime . NewFramework ( ctx , nil , nil , runtime . WithSnapshotSharedLister ( snapshot ) )
2021-05-07 06:15:18 -04:00
args := test . nodeResourcesFitArgs
2023-09-05 23:55:33 -04:00
p , err := NewFit ( ctx , & args , fh , plfeature . Features { } )
2021-05-07 06:15:18 -04:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
var gotPriorities framework . NodeScoreList
for _ , n := range test . nodes {
2023-03-12 03:06:26 -04:00
if test . runPreScore {
2023-03-10 10:44:53 -05:00
status := p . ( framework . PreScorePlugin ) . PreScore ( ctx , state , test . requestedPod , test . nodes )
if ! status . IsSuccess ( ) {
t . Errorf ( "PreScore is expected to return success, but didn't. Got status: %v" , status )
}
}
2022-08-05 12:05:22 -04:00
score , status := p . ( framework . ScorePlugin ) . Score ( ctx , state , test . requestedPod , n . Name )
2021-05-07 06:15:18 -04:00
if ! status . IsSuccess ( ) {
2023-03-10 10:44:53 -05:00
t . Errorf ( "Score is expected to return success, but didn't. Got status: %v" , status )
2021-05-07 06:15:18 -04:00
}
gotPriorities = append ( gotPriorities , framework . NodeScore { Name : n . Name , Score : score } )
}
if ! reflect . DeepEqual ( test . expectedPriorities , gotPriorities ) {
t . Errorf ( "expected:\n\t%+v,\ngot:\n\t%+v" , test . expectedPriorities , gotPriorities )
}
} )
}
}
2022-12-09 13:11:27 -05:00
var benchmarkResourceSet = [ ] config . ResourceSpec {
{ Name : string ( v1 . ResourceCPU ) , Weight : 1 } ,
{ Name : string ( v1 . ResourceMemory ) , Weight : 1 } ,
{ Name : string ( v1 . ResourcePods ) , Weight : 1 } ,
{ Name : string ( v1 . ResourceStorage ) , Weight : 1 } ,
{ Name : string ( v1 . ResourceEphemeralStorage ) , Weight : 1 } ,
{ Name : string ( extendedResourceA ) , Weight : 1 } ,
{ Name : string ( extendedResourceB ) , Weight : 1 } ,
{ Name : string ( kubernetesIOResourceA ) , Weight : 1 } ,
{ Name : string ( kubernetesIOResourceB ) , Weight : 1 } ,
{ Name : string ( hugePageResourceA ) , Weight : 1 } ,
}
func BenchmarkTestFitScore ( b * testing . B ) {
tests := [ ] struct {
name string
nodeResourcesFitArgs config . NodeResourcesFitArgs
} {
{
name : "RequestedToCapacityRatio with defaultResources" ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
Type : config . RequestedToCapacityRatio ,
Resources : defaultResources ,
RequestedToCapacityRatio : & config . RequestedToCapacityRatioParam {
Shape : [ ] config . UtilizationShapePoint {
{ Utilization : 0 , Score : 10 } ,
{ Utilization : 100 , Score : 0 } ,
} ,
} ,
} ,
} ,
} ,
{
name : "RequestedToCapacityRatio with 10 resources" ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
Type : config . RequestedToCapacityRatio ,
Resources : benchmarkResourceSet ,
RequestedToCapacityRatio : & config . RequestedToCapacityRatioParam {
Shape : [ ] config . UtilizationShapePoint {
{ Utilization : 0 , Score : 10 } ,
{ Utilization : 100 , Score : 0 } ,
} ,
} ,
} ,
} ,
} ,
{
name : "MostAllocated with defaultResources" ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
Type : config . MostAllocated ,
Resources : defaultResources ,
} ,
} ,
} ,
{
name : "MostAllocated with 10 resources" ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
Type : config . MostAllocated ,
Resources : benchmarkResourceSet ,
} ,
} ,
} ,
{
name : "LeastAllocated with defaultResources" ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
Type : config . LeastAllocated ,
Resources : defaultResources ,
} ,
} ,
} ,
{
name : "LeastAllocated with 10 resources" ,
nodeResourcesFitArgs : config . NodeResourcesFitArgs {
ScoringStrategy : & config . ScoringStrategy {
Type : config . LeastAllocated ,
Resources : benchmarkResourceSet ,
} ,
} ,
} ,
}
for _ , test := range tests {
b . Run ( test . name , func ( b * testing . B ) {
2023-05-15 06:36:17 -04:00
_ , ctx := ktesting . NewTestContext ( b )
ctx , cancel := context . WithCancel ( ctx )
defer cancel ( )
2022-12-09 13:11:27 -05:00
existingPods := [ ] * v1 . Pod {
st . MakePod ( ) . Node ( "node1" ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "2000" , "memory" : "4000" } ) . Obj ( ) ,
}
nodes := [ ] * v1 . Node {
st . MakeNode ( ) . Name ( "node1" ) . Capacity ( map [ v1 . ResourceName ] string { "cpu" : "4000" , "memory" : "10000" } ) . Obj ( ) ,
}
state := framework . NewCycleState ( )
var nodeResourcesFunc = runtime . FactoryAdapter ( plfeature . Features { } , NewFit )
2023-05-15 06:36:17 -04:00
pl := plugintesting . SetupPlugin ( ctx , b , nodeResourcesFunc , & test . nodeResourcesFitArgs , cache . NewSnapshot ( existingPods , nodes ) )
2022-12-09 13:11:27 -05:00
p := pl . ( * Fit )
b . ResetTimer ( )
requestedPod := st . MakePod ( ) . Req ( map [ v1 . ResourceName ] string { "cpu" : "1000" , "memory" : "2000" } ) . Obj ( )
for i := 0 ; i < b . N ; i ++ {
2023-05-15 06:36:17 -04:00
_ , status := p . Score ( ctx , state , requestedPod , nodes [ 0 ] . Name )
2022-12-09 13:11:27 -05:00
if ! status . IsSuccess ( ) {
b . Errorf ( "unexpected status: %v" , status )
}
}
} )
}
}
2023-02-04 23:58:42 -05:00
func TestEventsToRegister ( t * testing . T ) {
tests := [ ] struct {
name string
inPlacePodVerticalScalingEnabled bool
2023-06-08 00:54:30 -04:00
expectedClusterEvents [ ] framework . ClusterEventWithHint
2023-02-04 23:58:42 -05:00
} {
{
"Register events with InPlacePodVerticalScaling feature enabled" ,
true ,
2023-06-08 00:54:30 -04:00
[ ] framework . ClusterEventWithHint {
{ Event : framework . ClusterEvent { Resource : "Pod" , ActionType : framework . Update | framework . Delete } } ,
{ Event : framework . ClusterEvent { Resource : "Node" , ActionType : framework . Add | framework . Update } } ,
2023-02-04 23:58:42 -05:00
} ,
} ,
{
"Register events with InPlacePodVerticalScaling feature disabled" ,
false ,
2023-06-08 00:54:30 -04:00
[ ] framework . ClusterEventWithHint {
{ Event : framework . ClusterEvent { Resource : "Pod" , ActionType : framework . Delete } } ,
{ Event : framework . ClusterEvent { Resource : "Node" , ActionType : framework . Add | framework . Update } } ,
2023-02-04 23:58:42 -05:00
} ,
} ,
}
for _ , test := range tests {
t . Run ( test . name , func ( t * testing . T ) {
fp := & Fit { enableInPlacePodVerticalScaling : test . inPlacePodVerticalScalingEnabled }
actualClusterEvents := fp . EventsToRegister ( )
if diff := cmp . Diff ( test . expectedClusterEvents , actualClusterEvents ) ; diff != "" {
t . Error ( "Cluster Events doesn't match extected events (-expected +actual):\n" , diff )
}
} )
}
}