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 }