Compare commits

...

15 Commits

Author SHA1 Message Date
Kubernetes Publisher b951e7b647 Merge pull request #132675 from dims/bump-sigs-k8s-io-json-no-code-changes
Bump sigs.k8s.io/json to latest - no code changes

Kubernetes-commit: e47ac3eb6faa97874658dc281c72b5623f994801
2025-07-03 01:54:52 +00:00
Kubernetes Publisher 8180eb29f0 Merge pull request #132677 from dims/update-github.com/emicklei/go-restful/v3-to-v3.12.2
Update github.com/emicklei/go-restful/v3 to v3.12.2

Kubernetes-commit: 305c0e06c99ff9df013edd804294217a04e4dd31
2025-07-02 21:51:27 +00:00
Kubernetes Publisher b7d91c8e34 Merge pull request #132676 from dims/bump-go.yaml.in/yaml/v3-to-v3.0.4
Bump go.yaml.in/yaml/v3 to v3.0.4

Kubernetes-commit: 01c03ae9cf7b1371c8bc2bdf12d9244e63e83750
2025-07-02 17:56:33 +00:00
Davanum Srinivas c3447f03d0 Update github.com/emicklei/go-restful/v3 to v3.12.2
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: b44b0fbf1299c6821033076352b91914d2efef67
2025-07-02 08:00:43 -04:00
Davanum Srinivas bf6c6b859a Bump go.yaml.in/yaml/v3 to v3.0.4
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 58e620cc4403d30f9fb6aab245cfb47db17957de
2025-07-02 07:37:06 -04:00
Davanum Srinivas cf6c0db284 Bump sigs.k8s.io/json to latest - no code changes
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 00f8cbae6b8fd3799a1a044abcefdbb572d35b27
2025-07-02 07:32:24 -04:00
Kubernetes Publisher e1eb80f820 Merge pull request #132654 from Jefftree/b-openapi
Bump kube-openapi

Kubernetes-commit: db49c25956df36c777213251c4a47d6d9ee1c5ea
2025-07-01 21:56:08 +00:00
Kubernetes Publisher 95b15852f6 Merge pull request #132087 from ania-borowiec/move_code_and_status
Moving Scheduler interfaces to staging: Move Code and Status from pkg/scheduler/framework to k8s.io/kube-scheduler/framework

Kubernetes-commit: 2ee568260ff50064a5b7e46bc53d216edff2c640
2025-07-01 17:40:20 +00:00
Jefftree ebdc23a6fd Update vendor
Kubernetes-commit: d04ee27c98ba91680ac6c6a8ade9e33d7ee44569
2025-07-01 15:23:58 +00:00
Jefftree f502df2683 pin kube-openapi to v0.0.0-20250628140032-d90c4fd18f59
Kubernetes-commit: b41d375b8881f25ff5fe7775b4dedaba1eaa3f02
2025-07-01 15:21:22 +00:00
Ania Borowiec 34108578d3 Move Code and Status from pkg/scheduler/framework to k8s.io/kube-scheduler/framework
Kubernetes-commit: ee8c265d3508ac96665c86bd1590777c5fb3858d
2025-06-03 22:59:50 +00:00
Ania Borowiec f86d55a8f9 Move ClusterEvent type to staging repo, leaving some functions (that contain logic internal to scheduler) in kubernetes/kubernetes (#132190)
* Move ClusterEvent type to staging repo, leaving some functions (that contain logic internal to scheduler) in kubernetes/kubernetes

apply review comment and fix linter warning

* update-vendor.sh

* update doc comments

* run update-vendor.sh

Kubernetes-commit: 00d375050338df847285c0a12bbd90c328d0e707
2025-06-26 18:01:41 +00:00
Kubernetes Publisher e5f83c4ff2 Merge pull request #132357 from dims/drop-usage-of-forked-copies-of-goyaml.v2-and-goyaml.v3
Drop usage of forked copies of goyaml.v2 and goyaml.v3

Kubernetes-commit: c1afec6a0b15ca1ed853c1321ac2c972488bf5b8
2025-06-25 18:15:54 +00:00
Davanum Srinivas 9fd9552640 switch to latest sigs.k8s.io/yaml v1.5.0 (run update-gofmt.sh as well)
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: c5b4b133ce3252ee19b7167eb69a99d88fdefda8
2025-06-25 08:03:06 -04:00
Davanum Srinivas c1e58612a9 Drop usage of forked copies of goyaml.v2 and goyaml.v3
Signed-off-by: Davanum Srinivas <davanum@gmail.com>

Kubernetes-commit: 3827d3bc4f1c17ac816b37422dbd449c276e9ff0
2025-06-17 11:00:27 -04:00
4 changed files with 496 additions and 15 deletions

235
framework/interface.go Normal file
View File

@ -0,0 +1,235 @@
/*
Copyright 2025 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.
*/
// This file defines the scheduling framework plugin interfaces.
package framework
import (
"errors"
"strings"
"github.com/google/go-cmp/cmp" //nolint:depguard
"github.com/google/go-cmp/cmp/cmpopts" //nolint:depguard
)
// Code is the Status code/type which is returned from plugins.
type Code int
// These are predefined codes used in a Status.
// Note: when you add a new status, you have to add it in `codes` slice below.
const (
// Success means that plugin ran correctly and found pod schedulable.
// NOTE: A nil status is also considered as "Success".
Success Code = iota
// Error is one of the failures, used for internal plugin errors, unexpected input, etc.
// Plugin shouldn't return this code for expected failures, like Unschedulable.
// Since it's the unexpected failure, the scheduling queue registers the pod without unschedulable plugins.
// Meaning, the Pod will be requeued to activeQ/backoffQ soon.
Error
// Unschedulable is one of the failures, used when a plugin finds a pod unschedulable.
// If it's returned from PreFilter or Filter, the scheduler might attempt to
// run other postFilter plugins like preemption to get this pod scheduled.
// Use UnschedulableAndUnresolvable to make the scheduler skipping other postFilter plugins.
// The accompanying status message should explain why the pod is unschedulable.
//
// We regard the backoff as a penalty of wasting the scheduling cycle.
// When the scheduling queue requeues Pods, which was rejected with Unschedulable in the last scheduling,
// the Pod goes through backoff.
Unschedulable
// UnschedulableAndUnresolvable is used when a plugin finds a pod unschedulable and
// other postFilter plugins like preemption would not change anything.
// See the comment on PostFilter interface for more details about how PostFilter should handle this status.
// Plugins should return Unschedulable if it is possible that the pod can get scheduled
// after running other postFilter plugins.
// The accompanying status message should explain why the pod is unschedulable.
//
// We regard the backoff as a penalty of wasting the scheduling cycle.
// When the scheduling queue requeues Pods, which was rejected with UnschedulableAndUnresolvable in the last scheduling,
// the Pod goes through backoff.
UnschedulableAndUnresolvable
// Wait is used when a Permit plugin finds a pod scheduling should wait.
Wait
// Skip is used in the following scenarios:
// - when a Bind plugin chooses to skip binding.
// - when a PreFilter plugin returns Skip so that coupled Filter plugin/PreFilterExtensions() will be skipped.
// - when a PreScore plugin returns Skip so that coupled Score plugin will be skipped.
Skip
// Pending means that the scheduling process is finished successfully,
// but the plugin wants to stop the scheduling cycle/binding cycle here.
//
// For example, if your plugin has to notify the scheduling result to an external component,
// and wait for it to complete something **before** binding.
// It's different from when to return Unschedulable/UnschedulableAndUnresolvable,
// because in this case, the scheduler decides where the Pod can go successfully,
// but we need to wait for the external component to do something based on that scheduling result.
//
// We regard the backoff as a penalty of wasting the scheduling cycle.
// In the case of returning Pending, we cannot say the scheduling cycle is wasted
// because the scheduling result is used to proceed the Pod's scheduling forward,
// that particular scheduling cycle is failed though.
// So, Pods rejected by such reasons don't need to suffer a penalty (backoff).
// When the scheduling queue requeues Pods, which was rejected with Pending in the last scheduling,
// the Pod goes to activeQ directly ignoring backoff.
Pending
)
// This list should be exactly the same as the codes iota defined above in the same order.
var codes = []string{"Success", "Error", "Unschedulable", "UnschedulableAndUnresolvable", "Wait", "Skip", "Pending"}
func (c Code) String() string {
return codes[c]
}
// Status indicates the result of running a plugin. It consists of a code, a
// message, (optionally) an error, and a plugin name it fails by.
// When the status code is not Success, the reasons should explain why.
// And, when code is Success, all the other fields should be empty.
// NOTE: A nil Status is also considered as Success.
type Status struct {
code Code
reasons []string
err error
// plugin is an optional field that records the plugin name causes this status.
// It's set by the framework when code is Unschedulable, UnschedulableAndUnresolvable or Pending.
plugin string
}
func (s *Status) WithError(err error) *Status {
s.err = err
return s
}
// Code returns code of the Status.
func (s *Status) Code() Code {
if s == nil {
return Success
}
return s.code
}
// Message returns a concatenated message on reasons of the Status.
func (s *Status) Message() string {
if s == nil {
return ""
}
return strings.Join(s.Reasons(), ", ")
}
// SetPlugin sets the given plugin name to s.plugin.
func (s *Status) SetPlugin(plugin string) {
s.plugin = plugin
}
// WithPlugin sets the given plugin name to s.plugin,
// and returns the given status object.
func (s *Status) WithPlugin(plugin string) *Status {
s.SetPlugin(plugin)
return s
}
// Plugin returns the plugin name which caused this status.
func (s *Status) Plugin() string {
return s.plugin
}
// Reasons returns reasons of the Status.
func (s *Status) Reasons() []string {
if s.err != nil {
return append([]string{s.err.Error()}, s.reasons...)
}
return s.reasons
}
// AppendReason appends given reason to the Status.
func (s *Status) AppendReason(reason string) {
s.reasons = append(s.reasons, reason)
}
// IsSuccess returns true if and only if "Status" is nil or Code is "Success".
func (s *Status) IsSuccess() bool {
return s.Code() == Success
}
// IsWait returns true if and only if "Status" is non-nil and its Code is "Wait".
func (s *Status) IsWait() bool {
return s.Code() == Wait
}
// IsSkip returns true if and only if "Status" is non-nil and its Code is "Skip".
func (s *Status) IsSkip() bool {
return s.Code() == Skip
}
// IsRejected returns true if "Status" is Unschedulable (Unschedulable, UnschedulableAndUnresolvable, or Pending).
func (s *Status) IsRejected() bool {
code := s.Code()
return code == Unschedulable || code == UnschedulableAndUnresolvable || code == Pending
}
// AsError returns nil if the status is a success, a wait or a skip; otherwise returns an "error" object
// with a concatenated message on reasons of the Status.
func (s *Status) AsError() error {
if s.IsSuccess() || s.IsWait() || s.IsSkip() {
return nil
}
if s.err != nil {
return s.err
}
return errors.New(s.Message())
}
// Equal checks equality of two statuses. This is useful for testing with
// cmp.Equal.
func (s *Status) Equal(x *Status) bool {
if s == nil || x == nil {
return s.IsSuccess() && x.IsSuccess()
}
if s.code != x.code {
return false
}
if !cmp.Equal(s.err, x.err, cmpopts.EquateErrors()) {
return false
}
if !cmp.Equal(s.reasons, x.reasons) {
return false
}
return cmp.Equal(s.plugin, x.plugin)
}
func (s *Status) String() string {
return s.Message()
}
// NewStatus makes a Status out of the given arguments and returns its pointer.
func NewStatus(code Code, reasons ...string) *Status {
s := &Status{
code: code,
reasons: reasons,
}
return s
}
// AsStatus wraps an error in a Status.
func AsStatus(err error) *Status {
if err == nil {
return nil
}
return &Status{
code: Error,
err: err,
}
}

240
framework/types.go Normal file
View File

@ -0,0 +1,240 @@
/*
Copyright 2025 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 framework
import (
"fmt"
v1 "k8s.io/api/core/v1"
"k8s.io/klog/v2"
)
// ActionType is an integer to represent one type of resource change.
// Different ActionTypes can be bit-wised to compose new semantics.
type ActionType int64
// Constants for ActionTypes.
// CAUTION for contributors: When you add a new ActionType, you must update the following:
// - The list of basicActionTypes, podActionTypes, and nodeActionTypes at k/k/pkg/scheduler/framework/types.go
// - String() method.
const (
Add ActionType = 1 << iota
Delete
// UpdateNodeXYZ is only applicable for Node events.
// If you use UpdateNodeXYZ,
// your plugin's QueueingHint is only executed for the specific sub-Update event.
// It's better to narrow down the scope of the event by using them instead of just using Update event
// for better performance in requeueing.
UpdateNodeAllocatable
UpdateNodeLabel
// UpdateNodeTaint is an update for node's taints or node.Spec.Unschedulable.
UpdateNodeTaint
UpdateNodeCondition
UpdateNodeAnnotation
// UpdatePodXYZ is only applicable for Pod events.
// If you use UpdatePodXYZ,
// your plugin's QueueingHint is only executed for the specific sub-Update event.
// It's better to narrow down the scope of the event by using them instead of Update event
// for better performance in requeueing.
UpdatePodLabel
// UpdatePodScaleDown is an update for pod's scale down (i.e., any resource request is reduced).
UpdatePodScaleDown
// UpdatePodToleration is an addition for pod's tolerations.
// (Due to API validation, we can add, but cannot modify or remove tolerations.)
UpdatePodToleration
// UpdatePodSchedulingGatesEliminated is an update for pod's scheduling gates, which eliminates all scheduling gates in the Pod.
UpdatePodSchedulingGatesEliminated
// UpdatePodGeneratedResourceClaim is an update of the list of ResourceClaims generated for the pod.
// Depends on the DynamicResourceAllocation feature gate.
UpdatePodGeneratedResourceClaim
All ActionType = 1<<iota - 1
// Use the general Update type if you don't either know or care the specific sub-Update type to use.
Update = UpdateNodeAllocatable | UpdateNodeLabel | UpdateNodeTaint | UpdateNodeCondition | UpdateNodeAnnotation | UpdatePodLabel | UpdatePodScaleDown | UpdatePodToleration | UpdatePodSchedulingGatesEliminated | UpdatePodGeneratedResourceClaim
// None is a special ActionType that is only used internally.
None ActionType = 0
)
func (a ActionType) String() string {
switch a {
case Add:
return "Add"
case Delete:
return "Delete"
case UpdateNodeAllocatable:
return "UpdateNodeAllocatable"
case UpdateNodeLabel:
return "UpdateNodeLabel"
case UpdateNodeTaint:
return "UpdateNodeTaint"
case UpdateNodeCondition:
return "UpdateNodeCondition"
case UpdateNodeAnnotation:
return "UpdateNodeAnnotation"
case UpdatePodLabel:
return "UpdatePodLabel"
case UpdatePodScaleDown:
return "UpdatePodScaleDown"
case UpdatePodToleration:
return "UpdatePodToleration"
case UpdatePodSchedulingGatesEliminated:
return "UpdatePodSchedulingGatesEliminated"
case UpdatePodGeneratedResourceClaim:
return "UpdatePodGeneratedResourceClaim"
case All:
return "All"
case Update:
return "Update"
}
// Shouldn't reach here.
return ""
}
// EventResource is basically short for group/version/kind, which can uniquely represent a particular API resource.
type EventResource string
// Constants for GVKs.
//
// CAUTION for contributors: When you add a new EventResource, you must register a new one to allResources at k/k/pkg/scheduler/framework/types.go
//
// Note:
// - UpdatePodXYZ or UpdateNodeXYZ: triggered by updating particular parts of a Pod or a Node, e.g. updatePodLabel.
// Use specific events rather than general ones (updatePodLabel vs update) can make the requeueing process more efficient
// and consume less memory as less events will be cached at scheduler.
const (
// There are a couple of notes about how the scheduler notifies the events of Pods:
// - Add: add events could be triggered by either a newly created Pod or an existing Pod that is scheduled to a Node.
// - Delete: delete events could be triggered by:
// - a Pod that is deleted
// - a Pod that was assumed, but gets un-assumed due to some errors in the binding cycle.
// - an existing Pod that was unscheduled but gets scheduled to a Node.
//
// Note that the Pod event type includes the events for the unscheduled Pod itself.
// i.e., when unscheduled Pods are updated, the scheduling queue checks with Pod/Update QueueingHint(s) whether the update may make the pods schedulable,
// and requeues them to activeQ/backoffQ when at least one QueueingHint(s) return Queue.
// Plugins **have to** implement a QueueingHint for Pod/Update event
// if the rejection from them could be resolved by updating unscheduled Pods themselves.
// Example: Pods that require excessive resources may be rejected by the noderesources plugin,
// if this unscheduled pod is updated to require fewer resources,
// the previous rejection from noderesources plugin can be resolved.
// this plugin would implement QueueingHint for Pod/Update event
// that returns Queue when such label changes are made in unscheduled Pods.
Pod EventResource = "Pod"
// A note about NodeAdd event and UpdateNodeTaint event:
// When QHint is disabled, NodeAdd often isn't worked expectedly because of the internal feature called preCheck.
// It's definitely not something expected for plugin developers,
// and registering UpdateNodeTaint event is the only mitigation for now.
// So, kube-scheduler registers UpdateNodeTaint event for plugins that has NodeAdded event, but don't have UpdateNodeTaint event.
// It has a bad impact for the requeuing efficiency though, a lot better than some Pods being stuck in the
// unschedulable pod pool.
// This problematic preCheck feature is disabled when QHint is enabled,
// and eventually will be removed along with QHint graduation.
// See: https://github.com/kubernetes/kubernetes/issues/110175
Node EventResource = "Node"
PersistentVolume EventResource = "PersistentVolume"
PersistentVolumeClaim EventResource = "PersistentVolumeClaim"
CSINode EventResource = "storage.k8s.io/CSINode"
CSIDriver EventResource = "storage.k8s.io/CSIDriver"
VolumeAttachment EventResource = "storage.k8s.io/VolumeAttachment"
CSIStorageCapacity EventResource = "storage.k8s.io/CSIStorageCapacity"
StorageClass EventResource = "storage.k8s.io/StorageClass"
ResourceClaim EventResource = "resource.k8s.io/ResourceClaim"
ResourceSlice EventResource = "resource.k8s.io/ResourceSlice"
DeviceClass EventResource = "resource.k8s.io/DeviceClass"
// WildCard is a special EventResource to match all resources.
// e.g., If you register `{Resource: "*", ActionType: All}` in EventsToRegister,
// all coming clusterEvents will be admitted. Be careful to register it, it will
// increase the computing pressure in requeueing unless you really need it.
//
// Meanwhile, if the coming clusterEvent is a wildcard one, all pods
// will be moved from unschedulablePod pool to activeQ/backoffQ forcibly.
WildCard EventResource = "*"
)
type ClusterEventWithHint struct {
Event ClusterEvent
// QueueingHintFn is executed for the Pod rejected by this plugin when the above Event happens,
// and filters out events to reduce useless retry of Pod's scheduling.
// It's an optional field. If not set,
// the scheduling of Pods will be always retried with backoff when this Event happens.
// (the same as Queue)
QueueingHintFn QueueingHintFn
}
// QueueingHintFn returns a hint that signals whether the event can make a Pod,
// which was rejected by this plugin in the past scheduling cycle, schedulable or not.
// It's called before a Pod gets moved from unschedulableQ to backoffQ or activeQ.
// If it returns an error, we'll take the returned QueueingHint as `Queue` at the caller whatever we returned here so that
// we can prevent the Pod from being stuck in the unschedulable pod pool.
//
// - `pod`: the Pod to be enqueued, which is rejected by this plugin in the past.
// - `oldObj` `newObj`: the object involved in that event.
// - For example, the given event is "Node deleted", the `oldObj` will be that deleted Node.
// - `oldObj` is nil if the event is add event.
// - `newObj` is nil if the event is delete event.
type QueueingHintFn func(logger klog.Logger, pod *v1.Pod, oldObj, newObj interface{}) (QueueingHint, error)
type QueueingHint int
const (
// QueueSkip implies that the cluster event has no impact on
// scheduling of the pod.
QueueSkip QueueingHint = iota
// Queue implies that the Pod may be schedulable by the event.
Queue
)
func (s QueueingHint) String() string {
switch s {
case QueueSkip:
return "QueueSkip"
case Queue:
return "Queue"
}
return ""
}
// ClusterEvent abstracts how a system resource's state gets changed.
// Resource represents the standard API resources such as Pod, Node, etc.
// ActionType denotes the specific change such as Add, Update or Delete.
type ClusterEvent struct {
Resource EventResource
ActionType ActionType
// CustomLabel describes this cluster event.
// It's an optional field to control Label(), which is used in logging and metrics.
// Normally, it's not necessary to set this field; only used for special events like UnschedulableTimeout.
CustomLabel string
}
// Label is used for logging and metrics.
func (ce ClusterEvent) Label() string {
if ce.CustomLabel != "" {
return ce.CustomLabel
}
return fmt.Sprintf("%v%v", ce.Resource, ce.ActionType)
}

13
go.mod
View File

@ -8,10 +8,11 @@ godebug default=go1.24
require (
github.com/google/go-cmp v0.7.0
k8s.io/api v0.0.0-20250625172518-2872eaf4bc66
k8s.io/apimachinery v0.0.0-20250625172235-f3d86859ab8a
k8s.io/component-base v0.0.0-20250625174137-670840c797fd
sigs.k8s.io/yaml v1.4.0
k8s.io/api v0.0.0-20250703010437-9ca4bf8538e0
k8s.io/apimachinery v0.0.0-20250703010150-b86b632271cf
k8s.io/component-base v0.0.0-20250703012258-22a26817cb48
k8s.io/klog/v2 v2.130.1
sigs.k8s.io/yaml v1.5.0
)
require (
@ -23,12 +24,12 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/x448/float16 v0.8.4 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/text v0.23.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
)

23
go.sum
View File

@ -40,6 +40,10 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@ -76,22 +80,23 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.0.0-20250625172518-2872eaf4bc66 h1:aMd+Jbx+lq4jR0Cq9r8q0sSul6VjNeJZ6uBuMOW7lcs=
k8s.io/api v0.0.0-20250625172518-2872eaf4bc66/go.mod h1:1C5ufHfx8/vwdBx/DXW0BQ7SqsdvoyTyd6wy6XlQPJA=
k8s.io/apimachinery v0.0.0-20250625172235-f3d86859ab8a h1:iaRq1UKD/uPXfwZlW5WMGlKwRMNkA87SkgAurlTZk78=
k8s.io/apimachinery v0.0.0-20250625172235-f3d86859ab8a/go.mod h1:HYUvaFuBNToT/JW+lhc2D9BYgqj6xhI5eORJ7BnvKpM=
k8s.io/component-base v0.0.0-20250625174137-670840c797fd h1:DfaOuQ5YTgNT6I+8K//HO3lBQxqYnksXx/d1hDrlN3Q=
k8s.io/component-base v0.0.0-20250625174137-670840c797fd/go.mod h1:8XDN50ASDWy5CdtivLOdvBY0JZeDcFhhftTZxa5dABc=
k8s.io/api v0.0.0-20250703010437-9ca4bf8538e0 h1:iS/S3wfNTxgeC+HNybNhVSLt7y9E1XDkUlzPRXd1c6U=
k8s.io/api v0.0.0-20250703010437-9ca4bf8538e0/go.mod h1:2FUvtol5X8X7D4iFOQdd1W2Q6BoMhvE/DSSRzyWQ2yU=
k8s.io/apimachinery v0.0.0-20250703010150-b86b632271cf h1:5z7lkImscG/qu7KON0TOD0aSsycwXXiWue9mrjDasu4=
k8s.io/apimachinery v0.0.0-20250703010150-b86b632271cf/go.mod h1:Th679JJyaVRDNFk3vKPKY43ypziDeoGnbEiEgBCz8s4=
k8s.io/component-base v0.0.0-20250703012258-22a26817cb48 h1:bgA0NLAleN9Rl3z3oq1qc1pxD3hJRPTIVMqWPCZpMXg=
k8s.io/component-base v0.0.0-20250703012258-22a26817cb48/go.mod h1:t81Uof8wYmumUbjkD/V/shpkjxjPcK+dYKWuJGVI1Lw=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ=
sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4=