Compare commits
15 Commits
kubernetes
...
master
Author | SHA1 | Date |
---|---|---|
|
b951e7b647 | |
|
8180eb29f0 | |
|
b7d91c8e34 | |
|
c3447f03d0 | |
|
bf6c6b859a | |
|
cf6c0db284 | |
|
e1eb80f820 | |
|
95b15852f6 | |
|
ebdc23a6fd | |
|
f502df2683 | |
|
34108578d3 | |
|
f86d55a8f9 | |
|
e5f83c4ff2 | |
|
9fd9552640 | |
|
c1e58612a9 |
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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
13
go.mod
|
@ -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
23
go.sum
|
@ -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=
|
||||
|
|
Loading…
Reference in New Issue