k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/scheduler/apis/config/v1/defaults_test.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1
    18  
    19  import (
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/google/go-cmp/cmp"
    24  
    25  	v1 "k8s.io/api/core/v1"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apimachinery/pkg/runtime"
    28  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    29  	"k8s.io/apiserver/pkg/util/feature"
    30  	componentbaseconfig "k8s.io/component-base/config/v1alpha1"
    31  	"k8s.io/component-base/featuregate"
    32  	featuregatetesting "k8s.io/component-base/featuregate/testing"
    33  	configv1 "k8s.io/kube-scheduler/config/v1"
    34  	"k8s.io/kubernetes/pkg/features"
    35  	"k8s.io/kubernetes/pkg/scheduler/apis/config"
    36  	"k8s.io/kubernetes/pkg/scheduler/framework/plugins/names"
    37  	"k8s.io/utils/ptr"
    38  )
    39  
    40  var pluginConfigs = []configv1.PluginConfig{
    41  	{
    42  		Name: "DefaultPreemption",
    43  		Args: runtime.RawExtension{
    44  			Object: &configv1.DefaultPreemptionArgs{
    45  				TypeMeta: metav1.TypeMeta{
    46  					Kind:       "DefaultPreemptionArgs",
    47  					APIVersion: "kubescheduler.config.k8s.io/v1",
    48  				},
    49  				MinCandidateNodesPercentage: ptr.To[int32](10),
    50  				MinCandidateNodesAbsolute:   ptr.To[int32](100),
    51  			}},
    52  	},
    53  	{
    54  		Name: "InterPodAffinity",
    55  		Args: runtime.RawExtension{
    56  			Object: &configv1.InterPodAffinityArgs{
    57  				TypeMeta: metav1.TypeMeta{
    58  					Kind:       "InterPodAffinityArgs",
    59  					APIVersion: "kubescheduler.config.k8s.io/v1",
    60  				},
    61  				HardPodAffinityWeight: ptr.To[int32](1),
    62  			}},
    63  	},
    64  	{
    65  		Name: "NodeAffinity",
    66  		Args: runtime.RawExtension{Object: &configv1.NodeAffinityArgs{
    67  			TypeMeta: metav1.TypeMeta{
    68  				Kind:       "NodeAffinityArgs",
    69  				APIVersion: "kubescheduler.config.k8s.io/v1",
    70  			},
    71  		}},
    72  	},
    73  	{
    74  		Name: "NodeResourcesBalancedAllocation",
    75  		Args: runtime.RawExtension{Object: &configv1.NodeResourcesBalancedAllocationArgs{
    76  			TypeMeta: metav1.TypeMeta{
    77  				Kind:       "NodeResourcesBalancedAllocationArgs",
    78  				APIVersion: "kubescheduler.config.k8s.io/v1",
    79  			},
    80  			Resources: []configv1.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}},
    81  		}},
    82  	},
    83  	{
    84  		Name: "NodeResourcesFit",
    85  		Args: runtime.RawExtension{Object: &configv1.NodeResourcesFitArgs{
    86  			TypeMeta: metav1.TypeMeta{
    87  				Kind:       "NodeResourcesFitArgs",
    88  				APIVersion: "kubescheduler.config.k8s.io/v1",
    89  			},
    90  			ScoringStrategy: &configv1.ScoringStrategy{
    91  				Type:      configv1.LeastAllocated,
    92  				Resources: []configv1.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}},
    93  			},
    94  		}},
    95  	},
    96  	{
    97  		Name: "PodTopologySpread",
    98  		Args: runtime.RawExtension{Object: &configv1.PodTopologySpreadArgs{
    99  			TypeMeta: metav1.TypeMeta{
   100  				Kind:       "PodTopologySpreadArgs",
   101  				APIVersion: "kubescheduler.config.k8s.io/v1",
   102  			},
   103  			DefaultingType: configv1.SystemDefaulting,
   104  		}},
   105  	},
   106  	{
   107  		Name: "VolumeBinding",
   108  		Args: runtime.RawExtension{Object: &configv1.VolumeBindingArgs{
   109  			TypeMeta: metav1.TypeMeta{
   110  				Kind:       "VolumeBindingArgs",
   111  				APIVersion: "kubescheduler.config.k8s.io/v1",
   112  			},
   113  			BindTimeoutSeconds: ptr.To[int64](600),
   114  		}},
   115  	},
   116  }
   117  
   118  func TestSchedulerDefaults(t *testing.T) {
   119  	enable := true
   120  	unknownPluginConfigs := append([]configv1.PluginConfig{}, pluginConfigs...)
   121  	unknownPluginConfigs[0].Args = runtime.RawExtension{Object: &runtime.Unknown{}}
   122  
   123  	tests := []struct {
   124  		name     string
   125  		config   *configv1.KubeSchedulerConfiguration
   126  		expected *configv1.KubeSchedulerConfiguration
   127  	}{
   128  		{
   129  			name:   "empty config",
   130  			config: &configv1.KubeSchedulerConfiguration{},
   131  			expected: &configv1.KubeSchedulerConfiguration{
   132  				Parallelism: ptr.To[int32](16),
   133  				DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
   134  					EnableProfiling:           &enable,
   135  					EnableContentionProfiling: &enable,
   136  				},
   137  				LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
   138  					LeaderElect:       ptr.To(true),
   139  					LeaseDuration:     metav1.Duration{Duration: 15 * time.Second},
   140  					RenewDeadline:     metav1.Duration{Duration: 10 * time.Second},
   141  					RetryPeriod:       metav1.Duration{Duration: 2 * time.Second},
   142  					ResourceLock:      "leases",
   143  					ResourceNamespace: "kube-system",
   144  					ResourceName:      "kube-scheduler",
   145  				},
   146  				ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
   147  					QPS:         50,
   148  					Burst:       100,
   149  					ContentType: "application/vnd.kubernetes.protobuf",
   150  				},
   151  				PercentageOfNodesToScore: ptr.To[int32](config.DefaultPercentageOfNodesToScore),
   152  				PodInitialBackoffSeconds: ptr.To[int64](1),
   153  				PodMaxBackoffSeconds:     ptr.To[int64](10),
   154  				Profiles: []configv1.KubeSchedulerProfile{
   155  					{
   156  						Plugins:       getDefaultPlugins(),
   157  						PluginConfig:  pluginConfigs,
   158  						SchedulerName: ptr.To("default-scheduler"),
   159  					},
   160  				},
   161  			},
   162  		},
   163  		{
   164  			name: "no scheduler name",
   165  			config: &configv1.KubeSchedulerConfiguration{
   166  				Profiles: []configv1.KubeSchedulerProfile{{}},
   167  			},
   168  			expected: &configv1.KubeSchedulerConfiguration{
   169  				Parallelism: ptr.To[int32](16),
   170  				DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
   171  					EnableProfiling:           &enable,
   172  					EnableContentionProfiling: &enable,
   173  				},
   174  				LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
   175  					LeaderElect:       ptr.To(true),
   176  					LeaseDuration:     metav1.Duration{Duration: 15 * time.Second},
   177  					RenewDeadline:     metav1.Duration{Duration: 10 * time.Second},
   178  					RetryPeriod:       metav1.Duration{Duration: 2 * time.Second},
   179  					ResourceLock:      "leases",
   180  					ResourceNamespace: "kube-system",
   181  					ResourceName:      "kube-scheduler",
   182  				},
   183  				ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
   184  					QPS:         50,
   185  					Burst:       100,
   186  					ContentType: "application/vnd.kubernetes.protobuf",
   187  				},
   188  				PercentageOfNodesToScore: ptr.To[int32](config.DefaultPercentageOfNodesToScore),
   189  				PodInitialBackoffSeconds: ptr.To[int64](1),
   190  				PodMaxBackoffSeconds:     ptr.To[int64](10),
   191  				Profiles: []configv1.KubeSchedulerProfile{
   192  					{
   193  						SchedulerName: ptr.To("default-scheduler"),
   194  						Plugins:       getDefaultPlugins(),
   195  						PluginConfig:  pluginConfigs},
   196  				},
   197  			},
   198  		},
   199  		{
   200  			name: "two profiles",
   201  			config: &configv1.KubeSchedulerConfiguration{
   202  				Parallelism: ptr.To[int32](16),
   203  				Profiles: []configv1.KubeSchedulerProfile{
   204  					{
   205  						PluginConfig: []configv1.PluginConfig{
   206  							{Name: "FooPlugin"},
   207  						},
   208  					},
   209  					{
   210  						SchedulerName: ptr.To("custom-scheduler"),
   211  						Plugins: &configv1.Plugins{
   212  							Bind: configv1.PluginSet{
   213  								Enabled: []configv1.Plugin{
   214  									{Name: "BarPlugin"},
   215  								},
   216  								Disabled: []configv1.Plugin{
   217  									{Name: names.DefaultBinder},
   218  								},
   219  							},
   220  						},
   221  					},
   222  				},
   223  			},
   224  			expected: &configv1.KubeSchedulerConfiguration{
   225  				Parallelism: ptr.To[int32](16),
   226  				DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
   227  					EnableProfiling:           &enable,
   228  					EnableContentionProfiling: &enable,
   229  				},
   230  				LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
   231  					LeaderElect:       ptr.To(true),
   232  					LeaseDuration:     metav1.Duration{Duration: 15 * time.Second},
   233  					RenewDeadline:     metav1.Duration{Duration: 10 * time.Second},
   234  					RetryPeriod:       metav1.Duration{Duration: 2 * time.Second},
   235  					ResourceLock:      "leases",
   236  					ResourceNamespace: "kube-system",
   237  					ResourceName:      "kube-scheduler",
   238  				},
   239  				ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
   240  					QPS:         50,
   241  					Burst:       100,
   242  					ContentType: "application/vnd.kubernetes.protobuf",
   243  				},
   244  				PercentageOfNodesToScore: ptr.To[int32](config.DefaultPercentageOfNodesToScore),
   245  				PodInitialBackoffSeconds: ptr.To[int64](1),
   246  				PodMaxBackoffSeconds:     ptr.To[int64](10),
   247  				Profiles: []configv1.KubeSchedulerProfile{
   248  					{
   249  						Plugins: getDefaultPlugins(),
   250  						PluginConfig: []configv1.PluginConfig{
   251  							{Name: "FooPlugin"},
   252  							{
   253  								Name: "DefaultPreemption",
   254  								Args: runtime.RawExtension{
   255  									Object: &configv1.DefaultPreemptionArgs{
   256  										TypeMeta: metav1.TypeMeta{
   257  											Kind:       "DefaultPreemptionArgs",
   258  											APIVersion: "kubescheduler.config.k8s.io/v1",
   259  										},
   260  										MinCandidateNodesPercentage: ptr.To[int32](10),
   261  										MinCandidateNodesAbsolute:   ptr.To[int32](100),
   262  									}},
   263  							},
   264  							{
   265  								Name: "InterPodAffinity",
   266  								Args: runtime.RawExtension{
   267  									Object: &configv1.InterPodAffinityArgs{
   268  										TypeMeta: metav1.TypeMeta{
   269  											Kind:       "InterPodAffinityArgs",
   270  											APIVersion: "kubescheduler.config.k8s.io/v1",
   271  										},
   272  										HardPodAffinityWeight: ptr.To[int32](1),
   273  									}},
   274  							},
   275  							{
   276  								Name: "NodeAffinity",
   277  								Args: runtime.RawExtension{Object: &configv1.NodeAffinityArgs{
   278  									TypeMeta: metav1.TypeMeta{
   279  										Kind:       "NodeAffinityArgs",
   280  										APIVersion: "kubescheduler.config.k8s.io/v1",
   281  									},
   282  								}},
   283  							},
   284  							{
   285  								Name: "NodeResourcesBalancedAllocation",
   286  								Args: runtime.RawExtension{Object: &configv1.NodeResourcesBalancedAllocationArgs{
   287  									TypeMeta: metav1.TypeMeta{
   288  										Kind:       "NodeResourcesBalancedAllocationArgs",
   289  										APIVersion: "kubescheduler.config.k8s.io/v1",
   290  									},
   291  									Resources: []configv1.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}},
   292  								}},
   293  							},
   294  							{
   295  								Name: "NodeResourcesFit",
   296  								Args: runtime.RawExtension{Object: &configv1.NodeResourcesFitArgs{
   297  									TypeMeta: metav1.TypeMeta{
   298  										Kind:       "NodeResourcesFitArgs",
   299  										APIVersion: "kubescheduler.config.k8s.io/v1",
   300  									},
   301  									ScoringStrategy: &configv1.ScoringStrategy{
   302  										Type:      configv1.LeastAllocated,
   303  										Resources: []configv1.ResourceSpec{{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1}},
   304  									},
   305  								}},
   306  							},
   307  							{
   308  								Name: "PodTopologySpread",
   309  								Args: runtime.RawExtension{Object: &configv1.PodTopologySpreadArgs{
   310  									TypeMeta: metav1.TypeMeta{
   311  										Kind:       "PodTopologySpreadArgs",
   312  										APIVersion: "kubescheduler.config.k8s.io/v1",
   313  									},
   314  									DefaultingType: configv1.SystemDefaulting,
   315  								}},
   316  							},
   317  							{
   318  								Name: "VolumeBinding",
   319  								Args: runtime.RawExtension{Object: &configv1.VolumeBindingArgs{
   320  									TypeMeta: metav1.TypeMeta{
   321  										Kind:       "VolumeBindingArgs",
   322  										APIVersion: "kubescheduler.config.k8s.io/v1",
   323  									},
   324  									BindTimeoutSeconds: ptr.To[int64](600),
   325  								}},
   326  							},
   327  						},
   328  					},
   329  					{
   330  						SchedulerName: ptr.To("custom-scheduler"),
   331  						Plugins: &configv1.Plugins{
   332  							MultiPoint: configv1.PluginSet{
   333  								Enabled: []configv1.Plugin{
   334  									{Name: names.SchedulingGates},
   335  									{Name: names.PrioritySort},
   336  									{Name: names.NodeUnschedulable},
   337  									{Name: names.NodeName},
   338  									{Name: names.TaintToleration, Weight: ptr.To[int32](3)},
   339  									{Name: names.NodeAffinity, Weight: ptr.To[int32](2)},
   340  									{Name: names.NodePorts},
   341  									{Name: names.NodeResourcesFit, Weight: ptr.To[int32](1)},
   342  									{Name: names.VolumeRestrictions},
   343  									{Name: names.NodeVolumeLimits},
   344  									{Name: names.VolumeBinding},
   345  									{Name: names.VolumeZone},
   346  									{Name: names.PodTopologySpread, Weight: ptr.To[int32](2)},
   347  									{Name: names.InterPodAffinity, Weight: ptr.To[int32](2)},
   348  									{Name: names.DefaultPreemption},
   349  									{Name: names.NodeResourcesBalancedAllocation, Weight: ptr.To[int32](1)},
   350  									{Name: names.ImageLocality, Weight: ptr.To[int32](1)},
   351  									{Name: names.DefaultBinder},
   352  								},
   353  							},
   354  							Bind: configv1.PluginSet{
   355  								Enabled: []configv1.Plugin{
   356  									{Name: "BarPlugin"},
   357  								},
   358  								Disabled: []configv1.Plugin{
   359  									{Name: names.DefaultBinder},
   360  								},
   361  							},
   362  						},
   363  						PluginConfig: pluginConfigs,
   364  					},
   365  				},
   366  			},
   367  		},
   368  		{
   369  			name: "Prallelism with no port",
   370  			config: &configv1.KubeSchedulerConfiguration{
   371  				Parallelism: ptr.To[int32](16),
   372  			},
   373  			expected: &configv1.KubeSchedulerConfiguration{
   374  				Parallelism: ptr.To[int32](16),
   375  				DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
   376  					EnableProfiling:           &enable,
   377  					EnableContentionProfiling: &enable,
   378  				},
   379  				LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
   380  					LeaderElect:       ptr.To(true),
   381  					LeaseDuration:     metav1.Duration{Duration: 15 * time.Second},
   382  					RenewDeadline:     metav1.Duration{Duration: 10 * time.Second},
   383  					RetryPeriod:       metav1.Duration{Duration: 2 * time.Second},
   384  					ResourceLock:      "leases",
   385  					ResourceNamespace: "kube-system",
   386  					ResourceName:      "kube-scheduler",
   387  				},
   388  				ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
   389  					QPS:         50,
   390  					Burst:       100,
   391  					ContentType: "application/vnd.kubernetes.protobuf",
   392  				},
   393  				PercentageOfNodesToScore: ptr.To[int32](config.DefaultPercentageOfNodesToScore),
   394  				PodInitialBackoffSeconds: ptr.To[int64](1),
   395  				PodMaxBackoffSeconds:     ptr.To[int64](10),
   396  				Profiles: []configv1.KubeSchedulerProfile{
   397  					{
   398  						Plugins:       getDefaultPlugins(),
   399  						PluginConfig:  pluginConfigs,
   400  						SchedulerName: ptr.To("default-scheduler"),
   401  					},
   402  				},
   403  			},
   404  		},
   405  		{
   406  			name: "set non default parallelism",
   407  			config: &configv1.KubeSchedulerConfiguration{
   408  				Parallelism: ptr.To[int32](8),
   409  			},
   410  			expected: &configv1.KubeSchedulerConfiguration{
   411  				Parallelism: ptr.To[int32](8),
   412  				DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
   413  					EnableProfiling:           &enable,
   414  					EnableContentionProfiling: &enable,
   415  				},
   416  				LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
   417  					LeaderElect:       ptr.To(true),
   418  					LeaseDuration:     metav1.Duration{Duration: 15 * time.Second},
   419  					RenewDeadline:     metav1.Duration{Duration: 10 * time.Second},
   420  					RetryPeriod:       metav1.Duration{Duration: 2 * time.Second},
   421  					ResourceLock:      "leases",
   422  					ResourceNamespace: "kube-system",
   423  					ResourceName:      "kube-scheduler",
   424  				},
   425  				ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
   426  					QPS:         50,
   427  					Burst:       100,
   428  					ContentType: "application/vnd.kubernetes.protobuf",
   429  				},
   430  				PercentageOfNodesToScore: ptr.To[int32](config.DefaultPercentageOfNodesToScore),
   431  				PodInitialBackoffSeconds: ptr.To[int64](1),
   432  				PodMaxBackoffSeconds:     ptr.To[int64](10),
   433  				Profiles: []configv1.KubeSchedulerProfile{
   434  					{
   435  						Plugins:       getDefaultPlugins(),
   436  						PluginConfig:  pluginConfigs,
   437  						SchedulerName: ptr.To("default-scheduler"),
   438  					},
   439  				},
   440  			},
   441  		},
   442  		{
   443  			name: "set non default delayCacheUntilActive",
   444  			config: &configv1.KubeSchedulerConfiguration{
   445  				DelayCacheUntilActive: true,
   446  			},
   447  			expected: &configv1.KubeSchedulerConfiguration{
   448  				Parallelism:           ptr.To[int32](16),
   449  				DelayCacheUntilActive: true,
   450  				DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
   451  					EnableProfiling:           &enable,
   452  					EnableContentionProfiling: &enable,
   453  				},
   454  				LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
   455  					LeaderElect:       ptr.To(true),
   456  					LeaseDuration:     metav1.Duration{Duration: 15 * time.Second},
   457  					RenewDeadline:     metav1.Duration{Duration: 10 * time.Second},
   458  					RetryPeriod:       metav1.Duration{Duration: 2 * time.Second},
   459  					ResourceLock:      "leases",
   460  					ResourceNamespace: "kube-system",
   461  					ResourceName:      "kube-scheduler",
   462  				},
   463  				ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
   464  					QPS:         50,
   465  					Burst:       100,
   466  					ContentType: "application/vnd.kubernetes.protobuf",
   467  				},
   468  				PercentageOfNodesToScore: ptr.To[int32](config.DefaultPercentageOfNodesToScore),
   469  				PodInitialBackoffSeconds: ptr.To[int64](1),
   470  				PodMaxBackoffSeconds:     ptr.To[int64](10),
   471  				Profiles: []configv1.KubeSchedulerProfile{
   472  					{
   473  						Plugins:       getDefaultPlugins(),
   474  						PluginConfig:  pluginConfigs,
   475  						SchedulerName: ptr.To("default-scheduler"),
   476  					},
   477  				},
   478  			},
   479  		},
   480  		{
   481  			name: "set non default global percentageOfNodesToScore",
   482  			config: &configv1.KubeSchedulerConfiguration{
   483  				PercentageOfNodesToScore: ptr.To[int32](50),
   484  			},
   485  			expected: &configv1.KubeSchedulerConfiguration{
   486  				Parallelism: ptr.To[int32](16),
   487  				DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
   488  					EnableProfiling:           &enable,
   489  					EnableContentionProfiling: &enable,
   490  				},
   491  				LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
   492  					LeaderElect:       ptr.To(true),
   493  					LeaseDuration:     metav1.Duration{Duration: 15 * time.Second},
   494  					RenewDeadline:     metav1.Duration{Duration: 10 * time.Second},
   495  					RetryPeriod:       metav1.Duration{Duration: 2 * time.Second},
   496  					ResourceLock:      "leases",
   497  					ResourceNamespace: "kube-system",
   498  					ResourceName:      "kube-scheduler",
   499  				},
   500  				ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
   501  					QPS:         50,
   502  					Burst:       100,
   503  					ContentType: "application/vnd.kubernetes.protobuf",
   504  				},
   505  				PercentageOfNodesToScore: ptr.To[int32](50),
   506  				PodInitialBackoffSeconds: ptr.To[int64](1),
   507  				PodMaxBackoffSeconds:     ptr.To[int64](10),
   508  				Profiles: []configv1.KubeSchedulerProfile{
   509  					{
   510  						Plugins:       getDefaultPlugins(),
   511  						PluginConfig:  pluginConfigs,
   512  						SchedulerName: ptr.To("default-scheduler"),
   513  					},
   514  				},
   515  			},
   516  		},
   517  		{
   518  			name: "set non default profile percentageOfNodesToScore",
   519  			config: &configv1.KubeSchedulerConfiguration{
   520  				Profiles: []configv1.KubeSchedulerProfile{
   521  					{
   522  						PercentageOfNodesToScore: ptr.To[int32](50),
   523  					},
   524  				},
   525  			},
   526  			expected: &configv1.KubeSchedulerConfiguration{
   527  				Parallelism: ptr.To[int32](16),
   528  				DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
   529  					EnableProfiling:           &enable,
   530  					EnableContentionProfiling: &enable,
   531  				},
   532  				LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
   533  					LeaderElect:       ptr.To(true),
   534  					LeaseDuration:     metav1.Duration{Duration: 15 * time.Second},
   535  					RenewDeadline:     metav1.Duration{Duration: 10 * time.Second},
   536  					RetryPeriod:       metav1.Duration{Duration: 2 * time.Second},
   537  					ResourceLock:      "leases",
   538  					ResourceNamespace: "kube-system",
   539  					ResourceName:      "kube-scheduler",
   540  				},
   541  				ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
   542  					QPS:         50,
   543  					Burst:       100,
   544  					ContentType: "application/vnd.kubernetes.protobuf",
   545  				},
   546  				PercentageOfNodesToScore: ptr.To[int32](config.DefaultPercentageOfNodesToScore),
   547  				PodInitialBackoffSeconds: ptr.To[int64](1),
   548  				PodMaxBackoffSeconds:     ptr.To[int64](10),
   549  				Profiles: []configv1.KubeSchedulerProfile{
   550  					{
   551  						Plugins:                  getDefaultPlugins(),
   552  						PluginConfig:             pluginConfigs,
   553  						SchedulerName:            ptr.To("default-scheduler"),
   554  						PercentageOfNodesToScore: ptr.To[int32](50),
   555  					},
   556  				},
   557  			},
   558  		},
   559  		{
   560  			name: "set non default global and profile percentageOfNodesToScore",
   561  			config: &configv1.KubeSchedulerConfiguration{
   562  				PercentageOfNodesToScore: ptr.To[int32](10),
   563  				Profiles: []configv1.KubeSchedulerProfile{
   564  					{
   565  						PercentageOfNodesToScore: ptr.To[int32](50),
   566  					},
   567  				},
   568  			},
   569  			expected: &configv1.KubeSchedulerConfiguration{
   570  				Parallelism: ptr.To[int32](16),
   571  				DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
   572  					EnableProfiling:           &enable,
   573  					EnableContentionProfiling: &enable,
   574  				},
   575  				LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
   576  					LeaderElect:       ptr.To(true),
   577  					LeaseDuration:     metav1.Duration{Duration: 15 * time.Second},
   578  					RenewDeadline:     metav1.Duration{Duration: 10 * time.Second},
   579  					RetryPeriod:       metav1.Duration{Duration: 2 * time.Second},
   580  					ResourceLock:      "leases",
   581  					ResourceNamespace: "kube-system",
   582  					ResourceName:      "kube-scheduler",
   583  				},
   584  				ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
   585  					QPS:         50,
   586  					Burst:       100,
   587  					ContentType: "application/vnd.kubernetes.protobuf",
   588  				},
   589  				PercentageOfNodesToScore: ptr.To[int32](10),
   590  				PodInitialBackoffSeconds: ptr.To[int64](1),
   591  				PodMaxBackoffSeconds:     ptr.To[int64](10),
   592  				Profiles: []configv1.KubeSchedulerProfile{
   593  					{
   594  						Plugins:                  getDefaultPlugins(),
   595  						PluginConfig:             pluginConfigs,
   596  						SchedulerName:            ptr.To("default-scheduler"),
   597  						PercentageOfNodesToScore: ptr.To[int32](50),
   598  					},
   599  				},
   600  			},
   601  		},
   602  		{
   603  			name: "unknown plugin config",
   604  			config: &configv1.KubeSchedulerConfiguration{
   605  				Profiles: []configv1.KubeSchedulerProfile{
   606  					{
   607  						PluginConfig: unknownPluginConfigs,
   608  					},
   609  				},
   610  			},
   611  			expected: &configv1.KubeSchedulerConfiguration{
   612  				Parallelism: ptr.To[int32](16),
   613  				DebuggingConfiguration: componentbaseconfig.DebuggingConfiguration{
   614  					EnableProfiling:           &enable,
   615  					EnableContentionProfiling: &enable,
   616  				},
   617  				LeaderElection: componentbaseconfig.LeaderElectionConfiguration{
   618  					LeaderElect:       ptr.To(true),
   619  					LeaseDuration:     metav1.Duration{Duration: 15 * time.Second},
   620  					RenewDeadline:     metav1.Duration{Duration: 10 * time.Second},
   621  					RetryPeriod:       metav1.Duration{Duration: 2 * time.Second},
   622  					ResourceLock:      "leases",
   623  					ResourceNamespace: "kube-system",
   624  					ResourceName:      "kube-scheduler",
   625  				},
   626  				ClientConnection: componentbaseconfig.ClientConnectionConfiguration{
   627  					QPS:         50,
   628  					Burst:       100,
   629  					ContentType: "application/vnd.kubernetes.protobuf",
   630  				},
   631  				PercentageOfNodesToScore: ptr.To[int32](config.DefaultPercentageOfNodesToScore),
   632  				PodInitialBackoffSeconds: ptr.To[int64](1),
   633  				PodMaxBackoffSeconds:     ptr.To[int64](10),
   634  				Profiles: []configv1.KubeSchedulerProfile{
   635  					{
   636  						Plugins:       getDefaultPlugins(),
   637  						PluginConfig:  unknownPluginConfigs,
   638  						SchedulerName: ptr.To("default-scheduler"),
   639  					},
   640  				},
   641  			},
   642  		},
   643  	}
   644  
   645  	for _, tc := range tests {
   646  		t.Run(tc.name, func(t *testing.T) {
   647  			SetDefaults_KubeSchedulerConfiguration(tc.config)
   648  			if diff := cmp.Diff(tc.expected, tc.config); diff != "" {
   649  				t.Errorf("Got unexpected defaults (-want, +got):\n%s", diff)
   650  			}
   651  		})
   652  	}
   653  }
   654  
   655  func TestPluginArgsDefaults(t *testing.T) {
   656  	tests := []struct {
   657  		name     string
   658  		features map[featuregate.Feature]bool
   659  		in       runtime.Object
   660  		want     runtime.Object
   661  	}{
   662  		{
   663  			name: "DefaultPreemptionArgs empty",
   664  			in:   &configv1.DefaultPreemptionArgs{},
   665  			want: &configv1.DefaultPreemptionArgs{
   666  				MinCandidateNodesPercentage: ptr.To[int32](10),
   667  				MinCandidateNodesAbsolute:   ptr.To[int32](100),
   668  			},
   669  		},
   670  		{
   671  			name: "DefaultPreemptionArgs with value",
   672  			in: &configv1.DefaultPreemptionArgs{
   673  				MinCandidateNodesPercentage: ptr.To[int32](50),
   674  			},
   675  			want: &configv1.DefaultPreemptionArgs{
   676  				MinCandidateNodesPercentage: ptr.To[int32](50),
   677  				MinCandidateNodesAbsolute:   ptr.To[int32](100),
   678  			},
   679  		},
   680  		{
   681  			name: "InterPodAffinityArgs empty",
   682  			in:   &configv1.InterPodAffinityArgs{},
   683  			want: &configv1.InterPodAffinityArgs{
   684  				HardPodAffinityWeight: ptr.To[int32](1),
   685  			},
   686  		},
   687  		{
   688  			name: "InterPodAffinityArgs explicit 0",
   689  			in: &configv1.InterPodAffinityArgs{
   690  				HardPodAffinityWeight: ptr.To[int32](0),
   691  			},
   692  			want: &configv1.InterPodAffinityArgs{
   693  				HardPodAffinityWeight: ptr.To[int32](0),
   694  			},
   695  		},
   696  		{
   697  			name: "InterPodAffinityArgs with value",
   698  			in: &configv1.InterPodAffinityArgs{
   699  				HardPodAffinityWeight: ptr.To[int32](5),
   700  			},
   701  			want: &configv1.InterPodAffinityArgs{
   702  				HardPodAffinityWeight: ptr.To[int32](5),
   703  			},
   704  		},
   705  		{
   706  			name: "NodeResourcesBalancedAllocationArgs resources empty",
   707  			in:   &configv1.NodeResourcesBalancedAllocationArgs{},
   708  			want: &configv1.NodeResourcesBalancedAllocationArgs{
   709  				Resources: []configv1.ResourceSpec{
   710  					{Name: "cpu", Weight: 1}, {Name: "memory", Weight: 1},
   711  				},
   712  			},
   713  		},
   714  		{
   715  			name: "NodeResourcesBalancedAllocationArgs with scalar resource",
   716  			in: &configv1.NodeResourcesBalancedAllocationArgs{
   717  				Resources: []configv1.ResourceSpec{
   718  					{Name: "scalar.io/scalar1", Weight: 1},
   719  				},
   720  			},
   721  			want: &configv1.NodeResourcesBalancedAllocationArgs{
   722  				Resources: []configv1.ResourceSpec{
   723  					{Name: "scalar.io/scalar1", Weight: 1},
   724  				},
   725  			},
   726  		},
   727  		{
   728  			name: "NodeResourcesBalancedAllocationArgs with mixed resources",
   729  			in: &configv1.NodeResourcesBalancedAllocationArgs{
   730  				Resources: []configv1.ResourceSpec{
   731  					{Name: string(v1.ResourceCPU), Weight: 1},
   732  					{Name: "scalar.io/scalar1", Weight: 1},
   733  				},
   734  			},
   735  			want: &configv1.NodeResourcesBalancedAllocationArgs{
   736  				Resources: []configv1.ResourceSpec{
   737  					{Name: string(v1.ResourceCPU), Weight: 1},
   738  					{Name: "scalar.io/scalar1", Weight: 1},
   739  				},
   740  			},
   741  		},
   742  		{
   743  			name: "NodeResourcesBalancedAllocationArgs have resource no weight",
   744  			in: &configv1.NodeResourcesBalancedAllocationArgs{
   745  				Resources: []configv1.ResourceSpec{
   746  					{Name: string(v1.ResourceCPU)},
   747  					{Name: "scalar.io/scalar0"},
   748  					{Name: "scalar.io/scalar1", Weight: 1},
   749  				},
   750  			},
   751  			want: &configv1.NodeResourcesBalancedAllocationArgs{
   752  				Resources: []configv1.ResourceSpec{
   753  					{Name: string(v1.ResourceCPU), Weight: 1},
   754  					{Name: "scalar.io/scalar0", Weight: 1},
   755  					{Name: "scalar.io/scalar1", Weight: 1},
   756  				},
   757  			},
   758  		},
   759  		{
   760  			name: "PodTopologySpreadArgs resources empty",
   761  			in:   &configv1.PodTopologySpreadArgs{},
   762  			want: &configv1.PodTopologySpreadArgs{
   763  				DefaultingType: configv1.SystemDefaulting,
   764  			},
   765  		},
   766  		{
   767  			name: "PodTopologySpreadArgs resources with value",
   768  			in: &configv1.PodTopologySpreadArgs{
   769  				DefaultConstraints: []v1.TopologySpreadConstraint{
   770  					{
   771  						TopologyKey:       "planet",
   772  						WhenUnsatisfiable: v1.DoNotSchedule,
   773  						MaxSkew:           2,
   774  					},
   775  				},
   776  			},
   777  			want: &configv1.PodTopologySpreadArgs{
   778  				DefaultConstraints: []v1.TopologySpreadConstraint{
   779  					{
   780  						TopologyKey:       "planet",
   781  						WhenUnsatisfiable: v1.DoNotSchedule,
   782  						MaxSkew:           2,
   783  					},
   784  				},
   785  				DefaultingType: configv1.SystemDefaulting,
   786  			},
   787  		},
   788  		{
   789  			name: "NodeResourcesFitArgs not set",
   790  			in:   &configv1.NodeResourcesFitArgs{},
   791  			want: &configv1.NodeResourcesFitArgs{
   792  				ScoringStrategy: &configv1.ScoringStrategy{
   793  					Type:      configv1.LeastAllocated,
   794  					Resources: defaultResourceSpec,
   795  				},
   796  			},
   797  		},
   798  		{
   799  			name: "NodeResourcesFitArgs Resources empty",
   800  			in: &configv1.NodeResourcesFitArgs{
   801  				ScoringStrategy: &configv1.ScoringStrategy{
   802  					Type: configv1.MostAllocated,
   803  				},
   804  			},
   805  			want: &configv1.NodeResourcesFitArgs{
   806  				ScoringStrategy: &configv1.ScoringStrategy{
   807  					Type:      configv1.MostAllocated,
   808  					Resources: defaultResourceSpec,
   809  				},
   810  			},
   811  		},
   812  		{
   813  			name: "VolumeBindingArgs empty, VolumeCapacityPriority disabled",
   814  			features: map[featuregate.Feature]bool{
   815  				features.VolumeCapacityPriority: false,
   816  			},
   817  			in: &configv1.VolumeBindingArgs{},
   818  			want: &configv1.VolumeBindingArgs{
   819  				BindTimeoutSeconds: ptr.To[int64](600),
   820  			},
   821  		},
   822  		{
   823  			name: "VolumeBindingArgs empty, VolumeCapacityPriority enabled",
   824  			features: map[featuregate.Feature]bool{
   825  				features.VolumeCapacityPriority: true,
   826  			},
   827  			in: &configv1.VolumeBindingArgs{},
   828  			want: &configv1.VolumeBindingArgs{
   829  				BindTimeoutSeconds: ptr.To[int64](600),
   830  				Shape: []configv1.UtilizationShapePoint{
   831  					{Utilization: 0, Score: 0},
   832  					{Utilization: 100, Score: 10},
   833  				},
   834  			},
   835  		},
   836  	}
   837  	for _, tc := range tests {
   838  		scheme := runtime.NewScheme()
   839  		utilruntime.Must(AddToScheme(scheme))
   840  		t.Run(tc.name, func(t *testing.T) {
   841  			for k, v := range tc.features {
   842  				featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, k, v)
   843  			}
   844  			scheme.Default(tc.in)
   845  			if diff := cmp.Diff(tc.want, tc.in); diff != "" {
   846  				t.Errorf("Got unexpected defaults (-want, +got):\n%s", diff)
   847  			}
   848  		})
   849  	}
   850  }