mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
rebase: update K8s packages to v0.32.1
Update K8s packages in go.mod to v0.32.1 Signed-off-by: Praveen M <m.praveen@ibm.com>
This commit is contained in:
4
vendor/k8s.io/component-base/cli/flag/flags.go
generated
vendored
4
vendor/k8s.io/component-base/cli/flag/flags.go
generated
vendored
@ -24,7 +24,7 @@ import (
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
var underscoreWarnings = make(map[string]bool)
|
||||
var underscoreWarnings = make(map[string]struct{})
|
||||
|
||||
// WordSepNormalizeFunc changes all flags that contain "_" separators
|
||||
func WordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
@ -40,7 +40,7 @@ func WarnWordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedNam
|
||||
nname := strings.Replace(name, "_", "-", -1)
|
||||
if _, alreadyWarned := underscoreWarnings[name]; !alreadyWarned {
|
||||
klog.Warningf("using an underscore in a flag name is not supported. %s has been converted to %s.", name, nname)
|
||||
underscoreWarnings[name] = true
|
||||
underscoreWarnings[name] = struct{}{}
|
||||
}
|
||||
|
||||
return pflag.NormalizedName(nname)
|
||||
|
3
vendor/k8s.io/component-base/config/options/leaderelectionconfig.go
generated
vendored
3
vendor/k8s.io/component-base/config/options/leaderelectionconfig.go
generated
vendored
@ -42,8 +42,7 @@ func BindLeaderElectionFlags(l *config.LeaderElectionConfiguration, fs *pflag.Fl
|
||||
"of a leadership. This is only applicable if leader election is enabled.")
|
||||
fs.StringVar(&l.ResourceLock, "leader-elect-resource-lock", l.ResourceLock, ""+
|
||||
"The type of resource object that is used for locking during "+
|
||||
"leader election. Supported options are 'leases', 'endpointsleases' "+
|
||||
"and 'configmapsleases'.")
|
||||
"leader election. Supported options are 'leases'.")
|
||||
fs.StringVar(&l.ResourceName, "leader-elect-resource-name", l.ResourceName, ""+
|
||||
"The name of resource object that is used for locking during "+
|
||||
"leader election.")
|
||||
|
61
vendor/k8s.io/component-base/config/validation/validation.go
generated
vendored
Normal file
61
vendor/k8s.io/component-base/config/validation/validation.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright 2018 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 validation
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/component-base/config"
|
||||
)
|
||||
|
||||
// ValidateClientConnectionConfiguration ensures validation of the ClientConnectionConfiguration struct
|
||||
func ValidateClientConnectionConfiguration(cc *config.ClientConnectionConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if cc.Burst < 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("burst"), cc.Burst, "must be non-negative"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateLeaderElectionConfiguration ensures validation of the LeaderElectionConfiguration struct
|
||||
func ValidateLeaderElectionConfiguration(cc *config.LeaderElectionConfiguration, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if !cc.LeaderElect {
|
||||
return allErrs
|
||||
}
|
||||
if cc.LeaseDuration.Duration <= 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("leaseDuration"), cc.LeaseDuration, "must be greater than zero"))
|
||||
}
|
||||
if cc.RenewDeadline.Duration <= 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("renewDeadline"), cc.RenewDeadline, "must be greater than zero"))
|
||||
}
|
||||
if cc.RetryPeriod.Duration <= 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("retryPeriod"), cc.RetryPeriod, "must be greater than zero"))
|
||||
}
|
||||
if cc.LeaseDuration.Duration <= cc.RenewDeadline.Duration {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("leaseDuration"), cc.RenewDeadline, "LeaseDuration must be greater than RenewDeadline"))
|
||||
}
|
||||
if len(cc.ResourceLock) == 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("resourceLock"), cc.ResourceLock, "resourceLock is required"))
|
||||
}
|
||||
if len(cc.ResourceNamespace) == 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("resourceNamespace"), cc.ResourceNamespace, "resourceNamespace is required"))
|
||||
}
|
||||
if len(cc.ResourceName) == 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("resourceName"), cc.ResourceName, "resourceName is required"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
454
vendor/k8s.io/component-base/featuregate/registry.go
generated
vendored
Normal file
454
vendor/k8s.io/component-base/featuregate/registry.go
generated
vendored
Normal file
@ -0,0 +1,454 @@
|
||||
/*
|
||||
Copyright 2024 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 featuregate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
baseversion "k8s.io/component-base/version"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// DefaultComponentGlobalsRegistry is the global var to store the effective versions and feature gates for all components for easy access.
|
||||
// Example usage:
|
||||
// // register the component effective version and feature gate first
|
||||
// _, _ = utilversion.DefaultComponentGlobalsRegistry.ComponentGlobalsOrRegister(utilversion.DefaultKubeComponent, utilversion.DefaultKubeEffectiveVersion(), utilfeature.DefaultMutableFeatureGate)
|
||||
// wardleEffectiveVersion := utilversion.NewEffectiveVersion("1.2")
|
||||
// wardleFeatureGate := featuregate.NewFeatureGate()
|
||||
// utilruntime.Must(utilversion.DefaultComponentGlobalsRegistry.Register(apiserver.WardleComponentName, wardleEffectiveVersion, wardleFeatureGate, false))
|
||||
//
|
||||
// cmd := &cobra.Command{
|
||||
// ...
|
||||
// // call DefaultComponentGlobalsRegistry.Set() in PersistentPreRunE
|
||||
// PersistentPreRunE: func(*cobra.Command, []string) error {
|
||||
// if err := utilversion.DefaultComponentGlobalsRegistry.Set(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// ...
|
||||
// },
|
||||
// RunE: func(c *cobra.Command, args []string) error {
|
||||
// // call utilversion.DefaultComponentGlobalsRegistry.Validate() somewhere
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// flags := cmd.Flags()
|
||||
// // add flags
|
||||
// utilversion.DefaultComponentGlobalsRegistry.AddFlags(flags)
|
||||
var DefaultComponentGlobalsRegistry ComponentGlobalsRegistry = NewComponentGlobalsRegistry()
|
||||
|
||||
const (
|
||||
DefaultKubeComponent = "kube"
|
||||
|
||||
klogLevel = 2
|
||||
)
|
||||
|
||||
type VersionMapping func(from *version.Version) *version.Version
|
||||
|
||||
// ComponentGlobals stores the global variables for a component for easy access.
|
||||
type ComponentGlobals struct {
|
||||
effectiveVersion baseversion.MutableEffectiveVersion
|
||||
featureGate MutableVersionedFeatureGate
|
||||
|
||||
// emulationVersionMapping contains the mapping from the emulation version of this component
|
||||
// to the emulation version of another component.
|
||||
emulationVersionMapping map[string]VersionMapping
|
||||
// dependentEmulationVersion stores whether or not this component's EmulationVersion is dependent through mapping on another component.
|
||||
// If true, the emulation version cannot be set from the flag, or version mapping from another component.
|
||||
dependentEmulationVersion bool
|
||||
// minCompatibilityVersionMapping contains the mapping from the min compatibility version of this component
|
||||
// to the min compatibility version of another component.
|
||||
minCompatibilityVersionMapping map[string]VersionMapping
|
||||
// dependentMinCompatibilityVersion stores whether or not this component's MinCompatibilityVersion is dependent through mapping on another component
|
||||
// If true, the min compatibility version cannot be set from the flag, or version mapping from another component.
|
||||
dependentMinCompatibilityVersion bool
|
||||
}
|
||||
|
||||
type ComponentGlobalsRegistry interface {
|
||||
// EffectiveVersionFor returns the EffectiveVersion registered under the component.
|
||||
// Returns nil if the component is not registered.
|
||||
EffectiveVersionFor(component string) baseversion.EffectiveVersion
|
||||
// FeatureGateFor returns the FeatureGate registered under the component.
|
||||
// Returns nil if the component is not registered.
|
||||
FeatureGateFor(component string) FeatureGate
|
||||
// Register registers the EffectiveVersion and FeatureGate for a component.
|
||||
// returns error if the component is already registered.
|
||||
Register(component string, effectiveVersion baseversion.MutableEffectiveVersion, featureGate MutableVersionedFeatureGate) error
|
||||
// ComponentGlobalsOrRegister would return the registered global variables for the component if it already exists in the registry.
|
||||
// Otherwise, the provided variables would be registered under the component, and the same variables would be returned.
|
||||
ComponentGlobalsOrRegister(component string, effectiveVersion baseversion.MutableEffectiveVersion, featureGate MutableVersionedFeatureGate) (baseversion.MutableEffectiveVersion, MutableVersionedFeatureGate)
|
||||
// AddFlags adds flags of "--emulated-version" and "--feature-gates"
|
||||
AddFlags(fs *pflag.FlagSet)
|
||||
// Set sets the flags for all global variables for all components registered.
|
||||
Set() error
|
||||
// SetFallback calls Set() if it has never been called.
|
||||
SetFallback() error
|
||||
// Validate calls the Validate() function for all the global variables for all components registered.
|
||||
Validate() []error
|
||||
// Reset removes all stored ComponentGlobals, configurations, and version mappings.
|
||||
Reset()
|
||||
// SetEmulationVersionMapping sets the mapping from the emulation version of one component
|
||||
// to the emulation version of another component.
|
||||
// Once set, the emulation version of the toComponent will be determined by the emulation version of the fromComponent,
|
||||
// and cannot be set from cmd flags anymore.
|
||||
// For a given component, its emulation version can only depend on one other component, no multiple dependency is allowed.
|
||||
SetEmulationVersionMapping(fromComponent, toComponent string, f VersionMapping) error
|
||||
}
|
||||
|
||||
type componentGlobalsRegistry struct {
|
||||
componentGlobals map[string]*ComponentGlobals
|
||||
mutex sync.RWMutex
|
||||
// list of component name to emulation version set from the flag.
|
||||
emulationVersionConfig []string
|
||||
// map of component name to the list of feature gates set from the flag.
|
||||
featureGatesConfig map[string][]string
|
||||
// set stores if the Set() function for the registry is already called.
|
||||
set bool
|
||||
}
|
||||
|
||||
func NewComponentGlobalsRegistry() *componentGlobalsRegistry {
|
||||
return &componentGlobalsRegistry{
|
||||
componentGlobals: make(map[string]*ComponentGlobals),
|
||||
emulationVersionConfig: nil,
|
||||
featureGatesConfig: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) Reset() {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
r.componentGlobals = make(map[string]*ComponentGlobals)
|
||||
r.emulationVersionConfig = nil
|
||||
r.featureGatesConfig = nil
|
||||
r.set = false
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) EffectiveVersionFor(component string) baseversion.EffectiveVersion {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
globals, ok := r.componentGlobals[component]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return globals.effectiveVersion
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) FeatureGateFor(component string) FeatureGate {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
globals, ok := r.componentGlobals[component]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return globals.featureGate
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) unsafeRegister(component string, effectiveVersion baseversion.MutableEffectiveVersion, featureGate MutableVersionedFeatureGate) error {
|
||||
if _, ok := r.componentGlobals[component]; ok {
|
||||
return fmt.Errorf("component globals of %s already registered", component)
|
||||
}
|
||||
if featureGate != nil {
|
||||
if err := featureGate.SetEmulationVersion(effectiveVersion.EmulationVersion()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
c := ComponentGlobals{
|
||||
effectiveVersion: effectiveVersion,
|
||||
featureGate: featureGate,
|
||||
emulationVersionMapping: make(map[string]VersionMapping),
|
||||
minCompatibilityVersionMapping: make(map[string]VersionMapping),
|
||||
}
|
||||
r.componentGlobals[component] = &c
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) Register(component string, effectiveVersion baseversion.MutableEffectiveVersion, featureGate MutableVersionedFeatureGate) error {
|
||||
if effectiveVersion == nil {
|
||||
return fmt.Errorf("cannot register nil effectiveVersion")
|
||||
}
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
return r.unsafeRegister(component, effectiveVersion, featureGate)
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) ComponentGlobalsOrRegister(component string, effectiveVersion baseversion.MutableEffectiveVersion, featureGate MutableVersionedFeatureGate) (baseversion.MutableEffectiveVersion, MutableVersionedFeatureGate) {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
globals, ok := r.componentGlobals[component]
|
||||
if ok {
|
||||
return globals.effectiveVersion, globals.featureGate
|
||||
}
|
||||
utilruntime.Must(r.unsafeRegister(component, effectiveVersion, featureGate))
|
||||
return effectiveVersion, featureGate
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) unsafeKnownFeatures() []string {
|
||||
var known []string
|
||||
for component, globals := range r.componentGlobals {
|
||||
if globals.featureGate == nil {
|
||||
continue
|
||||
}
|
||||
for _, f := range globals.featureGate.KnownFeatures() {
|
||||
known = append(known, component+":"+f)
|
||||
}
|
||||
}
|
||||
sort.Strings(known)
|
||||
return known
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) unsafeVersionFlagOptions(isEmulation bool) []string {
|
||||
var vs []string
|
||||
for component, globals := range r.componentGlobals {
|
||||
binaryVer := globals.effectiveVersion.BinaryVersion()
|
||||
if isEmulation {
|
||||
if globals.dependentEmulationVersion {
|
||||
continue
|
||||
}
|
||||
// emulated version could be between binaryMajor.{binaryMinor} and binaryMajor.{binaryMinor}
|
||||
// TODO: change to binaryMajor.{binaryMinor-1} and binaryMajor.{binaryMinor} in 1.32
|
||||
vs = append(vs, fmt.Sprintf("%s=%s..%s (default=%s)", component,
|
||||
binaryVer.SubtractMinor(0).String(), binaryVer.String(), globals.effectiveVersion.EmulationVersion().String()))
|
||||
} else {
|
||||
if globals.dependentMinCompatibilityVersion {
|
||||
continue
|
||||
}
|
||||
// min compatibility version could be between binaryMajor.{binaryMinor-1} and binaryMajor.{binaryMinor}
|
||||
vs = append(vs, fmt.Sprintf("%s=%s..%s (default=%s)", component,
|
||||
binaryVer.SubtractMinor(1).String(), binaryVer.String(), globals.effectiveVersion.MinCompatibilityVersion().String()))
|
||||
}
|
||||
}
|
||||
sort.Strings(vs)
|
||||
return vs
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) AddFlags(fs *pflag.FlagSet) {
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
for _, globals := range r.componentGlobals {
|
||||
if globals.featureGate != nil {
|
||||
globals.featureGate.Close()
|
||||
}
|
||||
}
|
||||
if r.emulationVersionConfig != nil || r.featureGatesConfig != nil {
|
||||
klog.Warning("calling componentGlobalsRegistry.AddFlags more than once, the registry will be set by the latest flags")
|
||||
}
|
||||
r.emulationVersionConfig = []string{}
|
||||
r.featureGatesConfig = make(map[string][]string)
|
||||
|
||||
fs.StringSliceVar(&r.emulationVersionConfig, "emulated-version", r.emulationVersionConfig, ""+
|
||||
"The versions different components emulate their capabilities (APIs, features, ...) of.\n"+
|
||||
"If set, the component will emulate the behavior of this version instead of the underlying binary version.\n"+
|
||||
"Version format could only be major.minor, for example: '--emulated-version=wardle=1.2,kube=1.31'. Options are:\n"+strings.Join(r.unsafeVersionFlagOptions(true), "\n")+
|
||||
"If the component is not specified, defaults to \"kube\"")
|
||||
|
||||
fs.Var(cliflag.NewColonSeparatedMultimapStringStringAllowDefaultEmptyKey(&r.featureGatesConfig), "feature-gates", "Comma-separated list of component:key=value pairs that describe feature gates for alpha/experimental features of different components.\n"+
|
||||
"If the component is not specified, defaults to \"kube\". This flag can be repeatedly invoked. For example: --feature-gates 'wardle:featureA=true,wardle:featureB=false' --feature-gates 'kube:featureC=true'"+
|
||||
"Options are:\n"+strings.Join(r.unsafeKnownFeatures(), "\n"))
|
||||
}
|
||||
|
||||
type componentVersion struct {
|
||||
component string
|
||||
ver *version.Version
|
||||
}
|
||||
|
||||
// getFullEmulationVersionConfig expands the given version config with version registered version mapping,
|
||||
// and returns the map of component to Version.
|
||||
func (r *componentGlobalsRegistry) getFullEmulationVersionConfig(
|
||||
versionConfigMap map[string]*version.Version) (map[string]*version.Version, error) {
|
||||
result := map[string]*version.Version{}
|
||||
setQueue := []componentVersion{}
|
||||
for comp, ver := range versionConfigMap {
|
||||
if _, ok := r.componentGlobals[comp]; !ok {
|
||||
return result, fmt.Errorf("component not registered: %s", comp)
|
||||
}
|
||||
klog.V(klogLevel).Infof("setting version %s=%s", comp, ver.String())
|
||||
setQueue = append(setQueue, componentVersion{comp, ver})
|
||||
}
|
||||
for len(setQueue) > 0 {
|
||||
cv := setQueue[0]
|
||||
if _, visited := result[cv.component]; visited {
|
||||
return result, fmt.Errorf("setting version of %s more than once, probably version mapping loop", cv.component)
|
||||
}
|
||||
setQueue = setQueue[1:]
|
||||
result[cv.component] = cv.ver
|
||||
for toComp, f := range r.componentGlobals[cv.component].emulationVersionMapping {
|
||||
toVer := f(cv.ver)
|
||||
if toVer == nil {
|
||||
return result, fmt.Errorf("got nil version from mapping of %s=%s to component:%s", cv.component, cv.ver.String(), toComp)
|
||||
}
|
||||
klog.V(klogLevel).Infof("setting version %s=%s from version mapping of %s=%s", toComp, toVer.String(), cv.component, cv.ver.String())
|
||||
setQueue = append(setQueue, componentVersion{toComp, toVer})
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func toVersionMap(versionConfig []string) (map[string]*version.Version, error) {
|
||||
m := map[string]*version.Version{}
|
||||
for _, compVer := range versionConfig {
|
||||
// default to "kube" of component is not specified
|
||||
k := "kube"
|
||||
v := compVer
|
||||
if strings.Contains(compVer, "=") {
|
||||
arr := strings.SplitN(compVer, "=", 2)
|
||||
if len(arr) != 2 {
|
||||
return m, fmt.Errorf("malformed pair, expect string=string")
|
||||
}
|
||||
k = strings.TrimSpace(arr[0])
|
||||
v = strings.TrimSpace(arr[1])
|
||||
}
|
||||
ver, err := version.Parse(v)
|
||||
if err != nil {
|
||||
return m, err
|
||||
}
|
||||
if ver.Patch() != 0 {
|
||||
return m, fmt.Errorf("patch version not allowed, got: %s=%s", k, ver.String())
|
||||
}
|
||||
if existingVer, ok := m[k]; ok {
|
||||
return m, fmt.Errorf("duplicate version flag, %s=%s and %s=%s", k, existingVer.String(), k, ver.String())
|
||||
}
|
||||
m[k] = ver
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) SetFallback() error {
|
||||
r.mutex.Lock()
|
||||
set := r.set
|
||||
r.mutex.Unlock()
|
||||
if set {
|
||||
return nil
|
||||
}
|
||||
klog.Warning("setting componentGlobalsRegistry in SetFallback. We recommend calling componentGlobalsRegistry.Set()" +
|
||||
" right after parsing flags to avoid using feature gates before their final values are set by the flags.")
|
||||
return r.Set()
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) Set() error {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
r.set = true
|
||||
emulationVersionConfigMap, err := toVersionMap(r.emulationVersionConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for comp := range emulationVersionConfigMap {
|
||||
if _, ok := r.componentGlobals[comp]; !ok {
|
||||
return fmt.Errorf("component not registered: %s", comp)
|
||||
}
|
||||
// only components without any dependencies can be set from the flag.
|
||||
if r.componentGlobals[comp].dependentEmulationVersion {
|
||||
return fmt.Errorf("EmulationVersion of %s is set by mapping, cannot set it by flag", comp)
|
||||
}
|
||||
}
|
||||
if emulationVersions, err := r.getFullEmulationVersionConfig(emulationVersionConfigMap); err != nil {
|
||||
return err
|
||||
} else {
|
||||
for comp, ver := range emulationVersions {
|
||||
r.componentGlobals[comp].effectiveVersion.SetEmulationVersion(ver)
|
||||
}
|
||||
}
|
||||
// Set feature gate emulation version before setting feature gate flag values.
|
||||
for comp, globals := range r.componentGlobals {
|
||||
if globals.featureGate == nil {
|
||||
continue
|
||||
}
|
||||
klog.V(klogLevel).Infof("setting %s:feature gate emulation version to %s", comp, globals.effectiveVersion.EmulationVersion().String())
|
||||
if err := globals.featureGate.SetEmulationVersion(globals.effectiveVersion.EmulationVersion()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for comp, fg := range r.featureGatesConfig {
|
||||
if comp == "" {
|
||||
if _, ok := r.featureGatesConfig[DefaultKubeComponent]; ok {
|
||||
return fmt.Errorf("set kube feature gates with default empty prefix or kube: prefix consistently, do not mix use")
|
||||
}
|
||||
comp = DefaultKubeComponent
|
||||
}
|
||||
if _, ok := r.componentGlobals[comp]; !ok {
|
||||
return fmt.Errorf("component not registered: %s", comp)
|
||||
}
|
||||
featureGate := r.componentGlobals[comp].featureGate
|
||||
if featureGate == nil {
|
||||
return fmt.Errorf("component featureGate not registered: %s", comp)
|
||||
}
|
||||
flagVal := strings.Join(fg, ",")
|
||||
klog.V(klogLevel).Infof("setting %s:feature-gates=%s", comp, flagVal)
|
||||
if err := featureGate.Set(flagVal); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) Validate() []error {
|
||||
var errs []error
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
for _, globals := range r.componentGlobals {
|
||||
errs = append(errs, globals.effectiveVersion.Validate()...)
|
||||
if globals.featureGate != nil {
|
||||
errs = append(errs, globals.featureGate.Validate()...)
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
func (r *componentGlobalsRegistry) SetEmulationVersionMapping(fromComponent, toComponent string, f VersionMapping) error {
|
||||
if f == nil {
|
||||
return nil
|
||||
}
|
||||
klog.V(klogLevel).Infof("setting EmulationVersion mapping from %s to %s", fromComponent, toComponent)
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
if _, ok := r.componentGlobals[fromComponent]; !ok {
|
||||
return fmt.Errorf("component not registered: %s", fromComponent)
|
||||
}
|
||||
if _, ok := r.componentGlobals[toComponent]; !ok {
|
||||
return fmt.Errorf("component not registered: %s", toComponent)
|
||||
}
|
||||
// check multiple dependency
|
||||
if r.componentGlobals[toComponent].dependentEmulationVersion {
|
||||
return fmt.Errorf("mapping of %s already exists from another component", toComponent)
|
||||
}
|
||||
r.componentGlobals[toComponent].dependentEmulationVersion = true
|
||||
|
||||
versionMapping := r.componentGlobals[fromComponent].emulationVersionMapping
|
||||
if _, ok := versionMapping[toComponent]; ok {
|
||||
return fmt.Errorf("EmulationVersion from %s to %s already exists", fromComponent, toComponent)
|
||||
}
|
||||
versionMapping[toComponent] = f
|
||||
klog.V(klogLevel).Infof("setting the default EmulationVersion of %s based on mapping from the default EmulationVersion of %s", fromComponent, toComponent)
|
||||
defaultFromVersion := r.componentGlobals[fromComponent].effectiveVersion.EmulationVersion()
|
||||
emulationVersions, err := r.getFullEmulationVersionConfig(map[string]*version.Version{fromComponent: defaultFromVersion})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for comp, ver := range emulationVersions {
|
||||
r.componentGlobals[comp].effectiveVersion.SetEmulationVersion(ver)
|
||||
}
|
||||
return nil
|
||||
}
|
78
vendor/k8s.io/component-base/logs/logreduction/logreduction.go
generated
vendored
Normal file
78
vendor/k8s.io/component-base/logs/logreduction/logreduction.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright 2018 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 logreduction
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var nowfunc = func() time.Time { return time.Now() }
|
||||
|
||||
// LogReduction provides a filter for consecutive identical log messages;
|
||||
// a message will be printed no more than once per interval.
|
||||
// If a string of messages is interrupted by a different message,
|
||||
// the interval timer will be reset.
|
||||
type LogReduction struct {
|
||||
lastError map[string]string
|
||||
errorPrinted map[string]time.Time
|
||||
errorMapLock sync.Mutex
|
||||
identicalErrorDelay time.Duration
|
||||
}
|
||||
|
||||
// NewLogReduction returns an initialized LogReduction
|
||||
func NewLogReduction(identicalErrorDelay time.Duration) *LogReduction {
|
||||
l := new(LogReduction)
|
||||
l.lastError = make(map[string]string)
|
||||
l.errorPrinted = make(map[string]time.Time)
|
||||
l.identicalErrorDelay = identicalErrorDelay
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *LogReduction) cleanupErrorTimeouts() {
|
||||
for name, timeout := range l.errorPrinted {
|
||||
if nowfunc().Sub(timeout) >= l.identicalErrorDelay {
|
||||
delete(l.errorPrinted, name)
|
||||
delete(l.lastError, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ShouldMessageBePrinted determines whether a message should be printed based
|
||||
// on how long ago this particular message was last printed
|
||||
func (l *LogReduction) ShouldMessageBePrinted(message string, parentID string) bool {
|
||||
l.errorMapLock.Lock()
|
||||
defer l.errorMapLock.Unlock()
|
||||
l.cleanupErrorTimeouts()
|
||||
lastMsg, ok := l.lastError[parentID]
|
||||
lastPrinted, ok1 := l.errorPrinted[parentID]
|
||||
if !ok || !ok1 || message != lastMsg || nowfunc().Sub(lastPrinted) >= l.identicalErrorDelay {
|
||||
l.errorPrinted[parentID] = nowfunc()
|
||||
l.lastError[parentID] = message
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ClearID clears out log reduction records pertaining to a particular parent
|
||||
// (e. g. container ID)
|
||||
func (l *LogReduction) ClearID(parentID string) {
|
||||
l.errorMapLock.Lock()
|
||||
defer l.errorMapLock.Unlock()
|
||||
delete(l.lastError, parentID)
|
||||
delete(l.errorPrinted, parentID)
|
||||
}
|
76
vendor/k8s.io/component-base/metrics/counter.go
generated
vendored
76
vendor/k8s.io/component-base/metrics/counter.go
generated
vendored
@ -18,15 +18,19 @@ package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
|
||||
// Counter is our internal representation for our wrapping struct around prometheus
|
||||
// counters. Counter implements both kubeCollector and CounterMetric.
|
||||
type Counter struct {
|
||||
ctx context.Context
|
||||
CounterMetric
|
||||
*CounterOpts
|
||||
lazyMetric
|
||||
@ -36,6 +40,14 @@ type Counter struct {
|
||||
// The implementation of the Metric interface is expected by testutil.GetCounterMetricValue.
|
||||
var _ Metric = &Counter{}
|
||||
|
||||
// All supported exemplar metric types implement the metricWithExemplar interface.
|
||||
var _ metricWithExemplar = &Counter{}
|
||||
|
||||
// exemplarCounterMetric holds a context to extract exemplar labels from, and a counter metric to attach them to. It implements the metricWithExemplar interface.
|
||||
type exemplarCounterMetric struct {
|
||||
*Counter
|
||||
}
|
||||
|
||||
// NewCounter returns an object which satisfies the kubeCollector and CounterMetric interfaces.
|
||||
// However, the object returned will not measure anything unless the collector is first
|
||||
// registered, since the metric is lazily instantiated.
|
||||
@ -93,11 +105,42 @@ func (c *Counter) initializeDeprecatedMetric() {
|
||||
c.initializeMetric()
|
||||
}
|
||||
|
||||
// WithContext allows the normal Counter metric to pass in context. The context is no-op now.
|
||||
// WithContext allows the normal Counter metric to pass in context.
|
||||
func (c *Counter) WithContext(ctx context.Context) CounterMetric {
|
||||
c.ctx = ctx
|
||||
return c.CounterMetric
|
||||
}
|
||||
|
||||
// withExemplar initializes the exemplarMetric object and sets the exemplar value.
|
||||
func (c *Counter) withExemplar(v float64) {
|
||||
(&exemplarCounterMetric{c}).withExemplar(v)
|
||||
}
|
||||
|
||||
func (c *Counter) Add(v float64) {
|
||||
c.withExemplar(v)
|
||||
}
|
||||
|
||||
func (c *Counter) Inc() {
|
||||
c.withExemplar(1)
|
||||
}
|
||||
|
||||
// withExemplar attaches an exemplar to the metric.
|
||||
func (e *exemplarCounterMetric) withExemplar(v float64) {
|
||||
if m, ok := e.CounterMetric.(prometheus.ExemplarAdder); ok {
|
||||
maybeSpanCtx := trace.SpanContextFromContext(e.ctx)
|
||||
if maybeSpanCtx.IsValid() && maybeSpanCtx.IsSampled() {
|
||||
exemplarLabels := prometheus.Labels{
|
||||
"trace_id": maybeSpanCtx.TraceID().String(),
|
||||
"span_id": maybeSpanCtx.SpanID().String(),
|
||||
}
|
||||
m.AddWithExemplar(v, exemplarLabels)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
e.CounterMetric.Add(v)
|
||||
}
|
||||
|
||||
// CounterVec is the internal representation of our wrapping struct around prometheus
|
||||
// counterVecs. CounterVec implements both kubeCollector and CounterVecMetric.
|
||||
type CounterVec struct {
|
||||
@ -119,11 +162,6 @@ func NewCounterVec(opts *CounterOpts, labels []string) *CounterVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[fqName]; ok {
|
||||
opts.LabelValueAllowLists = allowList
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
|
||||
cv := &CounterVec{
|
||||
CounterVec: noopCounterVec,
|
||||
@ -176,7 +214,17 @@ func (v *CounterVec) WithLabelValues(lvs ...string) CounterMetric {
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
|
||||
return v.CounterVec.WithLabelValues(lvs...)
|
||||
}
|
||||
|
||||
@ -190,6 +238,15 @@ func (v *CounterVec) With(labels map[string]string) CounterMetric {
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainLabelMap(labels)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
return v.CounterVec.With(labels)
|
||||
}
|
||||
@ -217,6 +274,13 @@ func (v *CounterVec) Reset() {
|
||||
v.CounterVec.Reset()
|
||||
}
|
||||
|
||||
// ResetLabelAllowLists resets the label allow list for the CounterVec.
|
||||
// NOTE: This should only be used in test.
|
||||
func (v *CounterVec) ResetLabelAllowLists() {
|
||||
v.initializeLabelAllowListsOnce = sync.Once{}
|
||||
v.LabelValueAllowLists = nil
|
||||
}
|
||||
|
||||
// WithContext returns wrapped CounterVec with context
|
||||
func (v *CounterVec) WithContext(ctx context.Context) *CounterVecWithContext {
|
||||
return &CounterVecWithContext{
|
||||
|
18
vendor/k8s.io/component-base/metrics/features/kube_features.go
generated
vendored
18
vendor/k8s.io/component-base/metrics/features/kube_features.go
generated
vendored
@ -17,23 +17,29 @@ limitations under the License.
|
||||
package features
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
"k8s.io/component-base/featuregate"
|
||||
)
|
||||
|
||||
const (
|
||||
// owner: @logicalhan
|
||||
// kep: https://kep.k8s.io/3466
|
||||
// alpha: v1.26
|
||||
ComponentSLIs featuregate.Feature = "ComponentSLIs"
|
||||
)
|
||||
|
||||
func featureGates() map[featuregate.Feature]featuregate.FeatureSpec {
|
||||
return map[featuregate.Feature]featuregate.FeatureSpec{
|
||||
ComponentSLIs: {Default: true, PreRelease: featuregate.Beta},
|
||||
func featureGates() map[featuregate.Feature]featuregate.VersionedSpecs {
|
||||
return map[featuregate.Feature]featuregate.VersionedSpecs{
|
||||
ComponentSLIs: {
|
||||
{Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha},
|
||||
{Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta},
|
||||
// ComponentSLIs officially graduated to GA in v1.29 but the gate was not updated until v1.32.
|
||||
// To support emulated versions, keep the gate until v1.35.
|
||||
{Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// AddFeatureGates adds all feature gates used by this package.
|
||||
func AddFeatureGates(mutableFeatureGate featuregate.MutableFeatureGate) error {
|
||||
return mutableFeatureGate.Add(featureGates())
|
||||
func AddFeatureGates(mutableFeatureGate featuregate.MutableVersionedFeatureGate) error {
|
||||
return mutableFeatureGate.AddVersioned(featureGates())
|
||||
}
|
||||
|
31
vendor/k8s.io/component-base/metrics/gauge.go
generated
vendored
31
vendor/k8s.io/component-base/metrics/gauge.go
generated
vendored
@ -18,6 +18,7 @@ package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -105,11 +106,6 @@ func NewGaugeVec(opts *GaugeOpts, labels []string) *GaugeVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[fqName]; ok {
|
||||
opts.LabelValueAllowLists = allowList
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
|
||||
cv := &GaugeVec{
|
||||
GaugeVec: noopGaugeVec,
|
||||
@ -149,6 +145,15 @@ func (v *GaugeVec) WithLabelValuesChecked(lvs ...string) (GaugeMetric, error) {
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
elt, err := v.GaugeVec.GetMetricWithLabelValues(lvs...)
|
||||
return elt, err
|
||||
@ -186,6 +191,15 @@ func (v *GaugeVec) WithChecked(labels map[string]string) (GaugeMetric, error) {
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainLabelMap(labels)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
elt, err := v.GaugeVec.GetMetricWith(labels)
|
||||
return elt, err
|
||||
@ -226,6 +240,13 @@ func (v *GaugeVec) Reset() {
|
||||
v.GaugeVec.Reset()
|
||||
}
|
||||
|
||||
// ResetLabelAllowLists resets the label allow list for the GaugeVec.
|
||||
// NOTE: This should only be used in test.
|
||||
func (v *GaugeVec) ResetLabelAllowLists() {
|
||||
v.initializeLabelAllowListsOnce = sync.Once{}
|
||||
v.LabelValueAllowLists = nil
|
||||
}
|
||||
|
||||
func newGaugeFunc(opts *GaugeOpts, function func() float64, v semver.Version) GaugeFunc {
|
||||
g := NewGauge(opts)
|
||||
|
||||
|
103
vendor/k8s.io/component-base/metrics/histogram.go
generated
vendored
103
vendor/k8s.io/component-base/metrics/histogram.go
generated
vendored
@ -18,20 +18,59 @@ package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Histogram is our internal representation for our wrapping struct around prometheus
|
||||
// histograms. Summary implements both kubeCollector and ObserverMetric
|
||||
type Histogram struct {
|
||||
ctx context.Context
|
||||
ObserverMetric
|
||||
*HistogramOpts
|
||||
lazyMetric
|
||||
selfCollector
|
||||
}
|
||||
|
||||
// exemplarHistogramMetric holds a context to extract exemplar labels from, and a historgram metric to attach them to. It implements the metricWithExemplar interface.
|
||||
type exemplarHistogramMetric struct {
|
||||
*Histogram
|
||||
}
|
||||
|
||||
type exemplarHistogramVec struct {
|
||||
*HistogramVecWithContext
|
||||
observer prometheus.Observer
|
||||
}
|
||||
|
||||
func (h *Histogram) Observe(v float64) {
|
||||
h.withExemplar(v)
|
||||
}
|
||||
|
||||
// withExemplar initializes the exemplarMetric object and sets the exemplar value.
|
||||
func (h *Histogram) withExemplar(v float64) {
|
||||
(&exemplarHistogramMetric{h}).withExemplar(v)
|
||||
}
|
||||
|
||||
// withExemplar attaches an exemplar to the metric.
|
||||
func (e *exemplarHistogramMetric) withExemplar(v float64) {
|
||||
if m, ok := e.Histogram.ObserverMetric.(prometheus.ExemplarObserver); ok {
|
||||
maybeSpanCtx := trace.SpanContextFromContext(e.ctx)
|
||||
if maybeSpanCtx.IsValid() && maybeSpanCtx.IsSampled() {
|
||||
exemplarLabels := prometheus.Labels{
|
||||
"trace_id": maybeSpanCtx.TraceID().String(),
|
||||
"span_id": maybeSpanCtx.SpanID().String(),
|
||||
}
|
||||
m.ObserveWithExemplar(v, exemplarLabels)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
e.ObserverMetric.Observe(v)
|
||||
}
|
||||
|
||||
// NewHistogram returns an object which is Histogram-like. However, nothing
|
||||
// will be measured until the histogram is registered somewhere.
|
||||
func NewHistogram(opts *HistogramOpts) *Histogram {
|
||||
@ -74,6 +113,7 @@ func (h *Histogram) initializeDeprecatedMetric() {
|
||||
|
||||
// WithContext allows the normal Histogram metric to pass in context. The context is no-op now.
|
||||
func (h *Histogram) WithContext(ctx context.Context) ObserverMetric {
|
||||
h.ctx = ctx
|
||||
return h.ObserverMetric
|
||||
}
|
||||
|
||||
@ -96,11 +136,6 @@ func NewHistogramVec(opts *HistogramOpts, labels []string) *HistogramVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[fqName]; ok {
|
||||
opts.LabelValueAllowLists = allowList
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
|
||||
v := &HistogramVec{
|
||||
HistogramVec: noopHistogramVec,
|
||||
@ -148,6 +183,15 @@ func (v *HistogramVec) WithLabelValues(lvs ...string) ObserverMetric {
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
return v.HistogramVec.WithLabelValues(lvs...)
|
||||
}
|
||||
@ -162,6 +206,15 @@ func (v *HistogramVec) With(labels map[string]string) ObserverMetric {
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainLabelMap(labels)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
return v.HistogramVec.With(labels)
|
||||
}
|
||||
@ -189,6 +242,13 @@ func (v *HistogramVec) Reset() {
|
||||
v.HistogramVec.Reset()
|
||||
}
|
||||
|
||||
// ResetLabelAllowLists resets the label allow list for the HistogramVec.
|
||||
// NOTE: This should only be used in test.
|
||||
func (v *HistogramVec) ResetLabelAllowLists() {
|
||||
v.initializeLabelAllowListsOnce = sync.Once{}
|
||||
v.LabelValueAllowLists = nil
|
||||
}
|
||||
|
||||
// WithContext returns wrapped HistogramVec with context
|
||||
func (v *HistogramVec) WithContext(ctx context.Context) *HistogramVecWithContext {
|
||||
return &HistogramVecWithContext{
|
||||
@ -203,12 +263,37 @@ type HistogramVecWithContext struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (h *exemplarHistogramVec) Observe(v float64) {
|
||||
h.withExemplar(v)
|
||||
}
|
||||
|
||||
func (h *exemplarHistogramVec) withExemplar(v float64) {
|
||||
if m, ok := h.observer.(prometheus.ExemplarObserver); ok {
|
||||
maybeSpanCtx := trace.SpanContextFromContext(h.HistogramVecWithContext.ctx)
|
||||
if maybeSpanCtx.IsValid() && maybeSpanCtx.IsSampled() {
|
||||
m.ObserveWithExemplar(v, prometheus.Labels{
|
||||
"trace_id": maybeSpanCtx.TraceID().String(),
|
||||
"span_id": maybeSpanCtx.SpanID().String(),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
h.observer.Observe(v)
|
||||
}
|
||||
|
||||
// WithLabelValues is the wrapper of HistogramVec.WithLabelValues.
|
||||
func (vc *HistogramVecWithContext) WithLabelValues(lvs ...string) ObserverMetric {
|
||||
return vc.HistogramVec.WithLabelValues(lvs...)
|
||||
func (vc *HistogramVecWithContext) WithLabelValues(lvs ...string) *exemplarHistogramVec {
|
||||
return &exemplarHistogramVec{
|
||||
HistogramVecWithContext: vc,
|
||||
observer: vc.HistogramVec.WithLabelValues(lvs...),
|
||||
}
|
||||
}
|
||||
|
||||
// With is the wrapper of HistogramVec.With.
|
||||
func (vc *HistogramVecWithContext) With(labels map[string]string) ObserverMetric {
|
||||
return vc.HistogramVec.With(labels)
|
||||
func (vc *HistogramVecWithContext) With(labels map[string]string) *exemplarHistogramVec {
|
||||
return &exemplarHistogramVec{
|
||||
HistogramVecWithContext: vc,
|
||||
observer: vc.HistogramVec.With(labels),
|
||||
}
|
||||
}
|
||||
|
7
vendor/k8s.io/component-base/metrics/metric.go
generated
vendored
7
vendor/k8s.io/component-base/metrics/metric.go
generated
vendored
@ -22,8 +22,8 @@ import (
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
promext "k8s.io/component-base/metrics/prometheusextension"
|
||||
|
||||
promext "k8s.io/component-base/metrics/prometheusextension"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
@ -210,6 +210,11 @@ func (c *selfCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
ch <- c.metric
|
||||
}
|
||||
|
||||
// metricWithExemplar is an interface that knows how to attach an exemplar to certain supported metric types.
|
||||
type metricWithExemplar interface {
|
||||
withExemplar(v float64)
|
||||
}
|
||||
|
||||
// no-op vecs for convenience
|
||||
var noopCounterVec = &prometheus.CounterVec{}
|
||||
var noopHistogramVec = &prometheus.HistogramVec{}
|
||||
|
2
vendor/k8s.io/component-base/metrics/options.go
generated
vendored
2
vendor/k8s.io/component-base/metrics/options.go
generated
vendored
@ -129,7 +129,7 @@ func validateAllowMetricLabel(allowListMapping map[string]string) error {
|
||||
for k := range allowListMapping {
|
||||
reg := regexp.MustCompile(metricNameRegex + `,` + labelRegex)
|
||||
if reg.FindString(k) != k {
|
||||
return fmt.Errorf("--allow-metric-labels must have a list of kv pair with format `metricName:labelName=labelValue, labelValue,...`")
|
||||
return fmt.Errorf("--allow-metric-labels must have a list of kv pair with format `metricName,labelName=labelValue, labelValue,...`")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
116
vendor/k8s.io/component-base/metrics/opts.go
generated
vendored
116
vendor/k8s.io/component-base/metrics/opts.go
generated
vendored
@ -25,11 +25,11 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
promext "k8s.io/component-base/metrics/prometheusextension"
|
||||
"k8s.io/klog/v2"
|
||||
yaml "sigs.k8s.io/yaml/goyaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -37,6 +37,14 @@ var (
|
||||
allowListLock sync.RWMutex
|
||||
)
|
||||
|
||||
// ResetLabelValueAllowLists resets the allow lists for label values.
|
||||
// NOTE: This should only be used in test.
|
||||
func ResetLabelValueAllowLists() {
|
||||
allowListLock.Lock()
|
||||
defer allowListLock.Unlock()
|
||||
labelValueAllowLists = map[string]*MetricLabelAllowList{}
|
||||
}
|
||||
|
||||
// KubeOpts is superset struct for prometheus.Opts. The prometheus Opts structure
|
||||
// is purposefully not embedded here because that would change struct initialization
|
||||
// in the manner which people are currently accustomed.
|
||||
@ -44,16 +52,17 @@ var (
|
||||
// Name must be set to a non-empty string. DeprecatedVersion is defined only
|
||||
// if the metric for which this options applies is, in fact, deprecated.
|
||||
type KubeOpts struct {
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
initializeLabelAllowListsOnce sync.Once
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
}
|
||||
|
||||
// BuildFQName joins the given three name components by "_". Empty name
|
||||
@ -160,17 +169,18 @@ func (o *GaugeOpts) toPromGaugeOpts() prometheus.GaugeOpts {
|
||||
// and can safely be left at their zero value, although it is strongly
|
||||
// encouraged to set a Help string.
|
||||
type HistogramOpts struct {
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
Buckets []float64
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
Buckets []float64
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
initializeLabelAllowListsOnce sync.Once
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
}
|
||||
|
||||
// Modify help description on the metric description.
|
||||
@ -206,18 +216,19 @@ func (o *HistogramOpts) toPromHistogramOpts() prometheus.HistogramOpts {
|
||||
// and can safely be left at their zero value, although it is strongly
|
||||
// encouraged to set a Help string.
|
||||
type TimingHistogramOpts struct {
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
Buckets []float64
|
||||
InitialValue float64
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
Buckets []float64
|
||||
InitialValue float64
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
initializeLabelAllowListsOnce sync.Once
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
}
|
||||
|
||||
// Modify help description on the metric description.
|
||||
@ -255,20 +266,21 @@ func (o *TimingHistogramOpts) toPromHistogramOpts() promext.TimingHistogramOpts
|
||||
// a help string and to explicitly set the Objectives field to the desired value
|
||||
// as the default value will change in the upcoming v0.10 of the library.
|
||||
type SummaryOpts struct {
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
Objectives map[float64]float64
|
||||
MaxAge time.Duration
|
||||
AgeBuckets uint32
|
||||
BufCap uint32
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
Namespace string
|
||||
Subsystem string
|
||||
Name string
|
||||
Help string
|
||||
ConstLabels map[string]string
|
||||
Objectives map[float64]float64
|
||||
MaxAge time.Duration
|
||||
AgeBuckets uint32
|
||||
BufCap uint32
|
||||
DeprecatedVersion string
|
||||
deprecateOnce sync.Once
|
||||
annotateOnce sync.Once
|
||||
StabilityLevel StabilityLevel
|
||||
initializeLabelAllowListsOnce sync.Once
|
||||
LabelValueAllowLists *MetricLabelAllowList
|
||||
}
|
||||
|
||||
// Modify help description on the metric description.
|
||||
@ -315,7 +327,7 @@ func (o *SummaryOpts) toPromSummaryOpts() prometheus.SummaryOpts {
|
||||
}
|
||||
|
||||
type MetricLabelAllowList struct {
|
||||
labelToAllowList map[string]sets.String
|
||||
labelToAllowList map[string]sets.Set[string]
|
||||
}
|
||||
|
||||
func (allowList *MetricLabelAllowList) ConstrainToAllowedList(labelNameList, labelValueList []string) {
|
||||
@ -347,13 +359,13 @@ func SetLabelAllowListFromCLI(allowListMapping map[string]string) {
|
||||
for metricLabelName, labelValues := range allowListMapping {
|
||||
metricName := strings.Split(metricLabelName, ",")[0]
|
||||
labelName := strings.Split(metricLabelName, ",")[1]
|
||||
valueSet := sets.NewString(strings.Split(labelValues, ",")...)
|
||||
valueSet := sets.New[string](strings.Split(labelValues, ",")...)
|
||||
|
||||
allowList, ok := labelValueAllowLists[metricName]
|
||||
if ok {
|
||||
allowList.labelToAllowList[labelName] = valueSet
|
||||
} else {
|
||||
labelToAllowList := make(map[string]sets.String)
|
||||
labelToAllowList := make(map[string]sets.Set[string])
|
||||
labelToAllowList[labelName] = valueSet
|
||||
labelValueAllowLists[metricName] = &MetricLabelAllowList{
|
||||
labelToAllowList,
|
||||
@ -363,8 +375,6 @@ func SetLabelAllowListFromCLI(allowListMapping map[string]string) {
|
||||
}
|
||||
|
||||
func SetLabelAllowListFromManifest(manifest string) {
|
||||
allowListLock.Lock()
|
||||
defer allowListLock.Unlock()
|
||||
allowListMapping := make(map[string]string)
|
||||
data, err := os.ReadFile(filepath.Clean(manifest))
|
||||
if err != nil {
|
||||
|
2
vendor/k8s.io/component-base/metrics/processstarttime.go
generated
vendored
2
vendor/k8s.io/component-base/metrics/processstarttime.go
generated
vendored
@ -35,7 +35,7 @@ var processStartTime = NewGaugeVec(
|
||||
// a prometheus registry. This metric needs to be included to ensure counter
|
||||
// data fidelity.
|
||||
func RegisterProcessStartTime(registrationFunc func(Registerable) error) error {
|
||||
start, err := getProcessStart()
|
||||
start, err := GetProcessStart()
|
||||
if err != nil {
|
||||
klog.Errorf("Could not get process start time, %v", err)
|
||||
start = float64(time.Now().Unix())
|
||||
|
2
vendor/k8s.io/component-base/metrics/processstarttime_others.go
generated
vendored
2
vendor/k8s.io/component-base/metrics/processstarttime_others.go
generated
vendored
@ -25,7 +25,7 @@ import (
|
||||
"github.com/prometheus/procfs"
|
||||
)
|
||||
|
||||
func getProcessStart() (float64, error) {
|
||||
func GetProcessStart() (float64, error) {
|
||||
pid := os.Getpid()
|
||||
p, err := procfs.NewProc(pid)
|
||||
if err != nil {
|
||||
|
2
vendor/k8s.io/component-base/metrics/processstarttime_windows.go
generated
vendored
2
vendor/k8s.io/component-base/metrics/processstarttime_windows.go
generated
vendored
@ -23,7 +23,7 @@ import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func getProcessStart() (float64, error) {
|
||||
func GetProcessStart() (float64, error) {
|
||||
processHandle := windows.CurrentProcess()
|
||||
|
||||
var creationTime, exitTime, kernelTime, userTime windows.Filetime
|
||||
|
4
vendor/k8s.io/component-base/metrics/prometheus/slis/routes.go
generated
vendored
4
vendor/k8s.io/component-base/metrics/prometheus/slis/routes.go
generated
vendored
@ -38,8 +38,8 @@ type SLIMetrics struct{}
|
||||
func (s SLIMetrics) Install(m mux) {
|
||||
installOnce.Do(func() {
|
||||
Register(Registry)
|
||||
m.Handle("/metrics/slis", metrics.HandlerFor(Registry, metrics.HandlerOpts{}))
|
||||
})
|
||||
m.Handle("/metrics/slis", metrics.HandlerFor(Registry, metrics.HandlerOpts{}))
|
||||
}
|
||||
|
||||
type SLIMetricsWithReset struct{}
|
||||
@ -48,6 +48,6 @@ type SLIMetricsWithReset struct{}
|
||||
func (s SLIMetricsWithReset) Install(m mux) {
|
||||
installWithResetOnce.Do(func() {
|
||||
Register(Registry)
|
||||
m.Handle("/metrics/slis", metrics.HandlerWithReset(Registry, metrics.HandlerOpts{}))
|
||||
})
|
||||
m.Handle("/metrics/slis", metrics.HandlerWithReset(Registry, metrics.HandlerOpts{}))
|
||||
}
|
||||
|
31
vendor/k8s.io/component-base/metrics/summary.go
generated
vendored
31
vendor/k8s.io/component-base/metrics/summary.go
generated
vendored
@ -18,6 +18,7 @@ package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -109,11 +110,6 @@ func NewSummaryVec(opts *SummaryOpts, labels []string) *SummaryVec {
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[fqName]; ok {
|
||||
opts.LabelValueAllowLists = allowList
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
|
||||
v := &SummaryVec{
|
||||
SummaryOpts: opts,
|
||||
@ -160,6 +156,15 @@ func (v *SummaryVec) WithLabelValues(lvs ...string) ObserverMetric {
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
return v.SummaryVec.WithLabelValues(lvs...)
|
||||
}
|
||||
@ -174,6 +179,15 @@ func (v *SummaryVec) With(labels map[string]string) ObserverMetric {
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainLabelMap(labels)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
return v.SummaryVec.With(labels)
|
||||
}
|
||||
@ -201,6 +215,13 @@ func (v *SummaryVec) Reset() {
|
||||
v.SummaryVec.Reset()
|
||||
}
|
||||
|
||||
// ResetLabelAllowLists resets the label allow list for the SummaryVec.
|
||||
// NOTE: This should only be used in test.
|
||||
func (v *SummaryVec) ResetLabelAllowLists() {
|
||||
v.initializeLabelAllowListsOnce = sync.Once{}
|
||||
v.LabelValueAllowLists = nil
|
||||
}
|
||||
|
||||
// WithContext returns wrapped SummaryVec with context
|
||||
func (v *SummaryVec) WithContext(ctx context.Context) *SummaryVecWithContext {
|
||||
return &SummaryVecWithContext{
|
||||
|
52
vendor/k8s.io/component-base/metrics/testutil/metrics.go
generated
vendored
52
vendor/k8s.io/component-base/metrics/testutil/metrics.go
generated
vendored
@ -258,12 +258,8 @@ func GetHistogramVecFromGatherer(gatherer metrics.Gatherer, metricName string, l
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, mFamily := range m {
|
||||
if mFamily.GetName() == metricName {
|
||||
metricFamily = mFamily
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
metricFamily = findMetricFamily(m, metricName)
|
||||
|
||||
if metricFamily == nil {
|
||||
return nil, fmt.Errorf("metric %q not found", metricName)
|
||||
@ -433,3 +429,47 @@ func LabelsMatch(metric *dto.Metric, labelFilter map[string]string) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// GetCounterVecFromGatherer collects a counter that matches the given name
|
||||
// from a gatherer implementing k8s.io/component-base/metrics.Gatherer interface.
|
||||
// It returns all counter values that had a label with a certain name in a map
|
||||
// that uses the label value as keys.
|
||||
//
|
||||
// Used only for testing purposes where we need to gather metrics directly from a running binary (without metrics endpoint).
|
||||
func GetCounterValuesFromGatherer(gatherer metrics.Gatherer, metricName string, lvMap map[string]string, labelName string) (map[string]float64, error) {
|
||||
m, err := gatherer.Gather()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
metricFamily := findMetricFamily(m, metricName)
|
||||
if metricFamily == nil {
|
||||
return nil, fmt.Errorf("metric %q not found", metricName)
|
||||
}
|
||||
if len(metricFamily.GetMetric()) == 0 {
|
||||
return nil, fmt.Errorf("metric %q is empty", metricName)
|
||||
}
|
||||
|
||||
values := make(map[string]float64)
|
||||
for _, metric := range metricFamily.GetMetric() {
|
||||
if LabelsMatch(metric, lvMap) {
|
||||
if counter := metric.GetCounter(); counter != nil {
|
||||
for _, labelPair := range metric.Label {
|
||||
if labelPair.GetName() == labelName {
|
||||
values[labelPair.GetValue()] = counter.GetValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
func findMetricFamily(metricFamilies []*dto.MetricFamily, metricName string) *dto.MetricFamily {
|
||||
for _, mFamily := range metricFamilies {
|
||||
if mFamily.GetName() == metricName {
|
||||
return mFamily
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
31
vendor/k8s.io/component-base/metrics/timing_histogram.go
generated
vendored
31
vendor/k8s.io/component-base/metrics/timing_histogram.go
generated
vendored
@ -18,6 +18,7 @@ package metrics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
@ -125,11 +126,6 @@ func NewTestableTimingHistogramVec(nowFunc func() time.Time, opts *TimingHistogr
|
||||
opts.StabilityLevel.setDefaults()
|
||||
|
||||
fqName := BuildFQName(opts.Namespace, opts.Subsystem, opts.Name)
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[fqName]; ok {
|
||||
opts.LabelValueAllowLists = allowList
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
|
||||
v := &TimingHistogramVec{
|
||||
TimingHistogramVec: noopTimingHistogramVec,
|
||||
@ -175,6 +171,15 @@ func (v *TimingHistogramVec) WithLabelValuesChecked(lvs ...string) (GaugeMetric,
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainToAllowedList(v.originalLabels, lvs)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
ops, err := v.TimingHistogramVec.GetMetricWithLabelValues(lvs...)
|
||||
if err != nil {
|
||||
@ -214,6 +219,15 @@ func (v *TimingHistogramVec) WithChecked(labels map[string]string) (GaugeMetric,
|
||||
}
|
||||
if v.LabelValueAllowLists != nil {
|
||||
v.LabelValueAllowLists.ConstrainLabelMap(labels)
|
||||
} else {
|
||||
v.initializeLabelAllowListsOnce.Do(func() {
|
||||
allowListLock.RLock()
|
||||
if allowList, ok := labelValueAllowLists[v.FQName()]; ok {
|
||||
v.LabelValueAllowLists = allowList
|
||||
allowList.ConstrainLabelMap(labels)
|
||||
}
|
||||
allowListLock.RUnlock()
|
||||
})
|
||||
}
|
||||
ops, err := v.TimingHistogramVec.GetMetricWith(labels)
|
||||
return ops.(GaugeMetric), err
|
||||
@ -254,6 +268,13 @@ func (v *TimingHistogramVec) Reset() {
|
||||
v.TimingHistogramVec.Reset()
|
||||
}
|
||||
|
||||
// ResetLabelAllowLists resets the label allow list for the TimingHistogramVec.
|
||||
// NOTE: This should only be used in test.
|
||||
func (v *TimingHistogramVec) ResetLabelAllowLists() {
|
||||
v.initializeLabelAllowListsOnce = sync.Once{}
|
||||
v.LabelValueAllowLists = nil
|
||||
}
|
||||
|
||||
// WithContext returns wrapped TimingHistogramVec with context
|
||||
func (v *TimingHistogramVec) InterfaceWithContext(ctx context.Context) GaugeVecMetric {
|
||||
return &TimingHistogramVecWithContext{
|
||||
|
2
vendor/k8s.io/component-base/version/base.go
generated
vendored
2
vendor/k8s.io/component-base/version/base.go
generated
vendored
@ -66,5 +66,5 @@ const (
|
||||
// DefaultKubeBinaryVersion is the hard coded k8 binary version based on the latest K8s release.
|
||||
// It is supposed to be consistent with gitMajor and gitMinor, except for local tests, where gitMajor and gitMinor are "".
|
||||
// Should update for each minor release!
|
||||
DefaultKubeBinaryVersion = "1.31"
|
||||
DefaultKubeBinaryVersion = "1.32"
|
||||
)
|
||||
|
157
vendor/k8s.io/component-base/version/version.go
generated
vendored
157
vendor/k8s.io/component-base/version/version.go
generated
vendored
@ -19,10 +19,41 @@ package version
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||
)
|
||||
|
||||
type EffectiveVersion interface {
|
||||
BinaryVersion() *version.Version
|
||||
EmulationVersion() *version.Version
|
||||
MinCompatibilityVersion() *version.Version
|
||||
EqualTo(other EffectiveVersion) bool
|
||||
String() string
|
||||
Validate() []error
|
||||
}
|
||||
|
||||
type MutableEffectiveVersion interface {
|
||||
EffectiveVersion
|
||||
Set(binaryVersion, emulationVersion, minCompatibilityVersion *version.Version)
|
||||
SetEmulationVersion(emulationVersion *version.Version)
|
||||
SetMinCompatibilityVersion(minCompatibilityVersion *version.Version)
|
||||
}
|
||||
|
||||
type effectiveVersion struct {
|
||||
// When true, BinaryVersion() returns the current binary version
|
||||
useDefaultBuildBinaryVersion atomic.Bool
|
||||
// Holds the last binary version stored in Set()
|
||||
binaryVersion atomic.Pointer[version.Version]
|
||||
// If the emulationVersion is set by the users, it could only contain major and minor versions.
|
||||
// In tests, emulationVersion could be the same as the binary version, or set directly,
|
||||
// which can have "alpha" as pre-release to continue serving expired apis while we clean up the test.
|
||||
emulationVersion atomic.Pointer[version.Version]
|
||||
// minCompatibilityVersion could only contain major and minor versions.
|
||||
minCompatibilityVersion atomic.Pointer[version.Version]
|
||||
}
|
||||
|
||||
// Get returns the overall codebase version. It's for detecting
|
||||
// what code a binary was built from.
|
||||
func Get() apimachineryversion.Info {
|
||||
@ -40,3 +71,129 @@ func Get() apimachineryversion.Info {
|
||||
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *effectiveVersion) BinaryVersion() *version.Version {
|
||||
if m.useDefaultBuildBinaryVersion.Load() {
|
||||
return defaultBuildBinaryVersion()
|
||||
}
|
||||
return m.binaryVersion.Load()
|
||||
}
|
||||
|
||||
func (m *effectiveVersion) EmulationVersion() *version.Version {
|
||||
ver := m.emulationVersion.Load()
|
||||
if ver != nil {
|
||||
// Emulation version can have "alpha" as pre-release to continue serving expired apis while we clean up the test.
|
||||
// The pre-release should not be accessible to the users.
|
||||
return ver.WithPreRelease(m.BinaryVersion().PreRelease())
|
||||
}
|
||||
return ver
|
||||
}
|
||||
|
||||
func (m *effectiveVersion) MinCompatibilityVersion() *version.Version {
|
||||
return m.minCompatibilityVersion.Load()
|
||||
}
|
||||
|
||||
func (m *effectiveVersion) EqualTo(other EffectiveVersion) bool {
|
||||
return m.BinaryVersion().EqualTo(other.BinaryVersion()) && m.EmulationVersion().EqualTo(other.EmulationVersion()) && m.MinCompatibilityVersion().EqualTo(other.MinCompatibilityVersion())
|
||||
}
|
||||
|
||||
func (m *effectiveVersion) String() string {
|
||||
if m == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("{BinaryVersion: %s, EmulationVersion: %s, MinCompatibilityVersion: %s}",
|
||||
m.BinaryVersion().String(), m.EmulationVersion().String(), m.MinCompatibilityVersion().String())
|
||||
}
|
||||
|
||||
func majorMinor(ver *version.Version) *version.Version {
|
||||
if ver == nil {
|
||||
return ver
|
||||
}
|
||||
return version.MajorMinor(ver.Major(), ver.Minor())
|
||||
}
|
||||
|
||||
func (m *effectiveVersion) Set(binaryVersion, emulationVersion, minCompatibilityVersion *version.Version) {
|
||||
m.binaryVersion.Store(binaryVersion)
|
||||
m.useDefaultBuildBinaryVersion.Store(false)
|
||||
m.emulationVersion.Store(majorMinor(emulationVersion))
|
||||
m.minCompatibilityVersion.Store(majorMinor(minCompatibilityVersion))
|
||||
}
|
||||
|
||||
func (m *effectiveVersion) SetEmulationVersion(emulationVersion *version.Version) {
|
||||
m.emulationVersion.Store(majorMinor(emulationVersion))
|
||||
}
|
||||
|
||||
func (m *effectiveVersion) SetMinCompatibilityVersion(minCompatibilityVersion *version.Version) {
|
||||
m.minCompatibilityVersion.Store(majorMinor(minCompatibilityVersion))
|
||||
}
|
||||
|
||||
func (m *effectiveVersion) Validate() []error {
|
||||
var errs []error
|
||||
// Validate only checks the major and minor versions.
|
||||
binaryVersion := m.BinaryVersion().WithPatch(0)
|
||||
emulationVersion := m.emulationVersion.Load()
|
||||
minCompatibilityVersion := m.minCompatibilityVersion.Load()
|
||||
|
||||
// emulationVersion can only be 1.{binaryMinor-1}...1.{binaryMinor}.
|
||||
maxEmuVer := binaryVersion
|
||||
minEmuVer := binaryVersion.SubtractMinor(1)
|
||||
if emulationVersion.GreaterThan(maxEmuVer) || emulationVersion.LessThan(minEmuVer) {
|
||||
errs = append(errs, fmt.Errorf("emulation version %s is not between [%s, %s]", emulationVersion.String(), minEmuVer.String(), maxEmuVer.String()))
|
||||
}
|
||||
// minCompatibilityVersion can only be 1.{binaryMinor-1} for alpha.
|
||||
maxCompVer := binaryVersion.SubtractMinor(1)
|
||||
minCompVer := binaryVersion.SubtractMinor(1)
|
||||
if minCompatibilityVersion.GreaterThan(maxCompVer) || minCompatibilityVersion.LessThan(minCompVer) {
|
||||
errs = append(errs, fmt.Errorf("minCompatibilityVersion version %s is not between [%s, %s]", minCompatibilityVersion.String(), minCompVer.String(), maxCompVer.String()))
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
func newEffectiveVersion(binaryVersion *version.Version, useDefaultBuildBinaryVersion bool) MutableEffectiveVersion {
|
||||
effective := &effectiveVersion{}
|
||||
compatVersion := binaryVersion.SubtractMinor(1)
|
||||
effective.Set(binaryVersion, binaryVersion, compatVersion)
|
||||
effective.useDefaultBuildBinaryVersion.Store(useDefaultBuildBinaryVersion)
|
||||
return effective
|
||||
}
|
||||
|
||||
func NewEffectiveVersion(binaryVer string) MutableEffectiveVersion {
|
||||
if binaryVer == "" {
|
||||
return &effectiveVersion{}
|
||||
}
|
||||
binaryVersion := version.MustParse(binaryVer)
|
||||
return newEffectiveVersion(binaryVersion, false)
|
||||
}
|
||||
|
||||
func defaultBuildBinaryVersion() *version.Version {
|
||||
verInfo := Get()
|
||||
return version.MustParse(verInfo.String()).WithInfo(verInfo)
|
||||
}
|
||||
|
||||
// DefaultBuildEffectiveVersion returns the MutableEffectiveVersion based on the
|
||||
// current build information.
|
||||
func DefaultBuildEffectiveVersion() MutableEffectiveVersion {
|
||||
binaryVersion := defaultBuildBinaryVersion()
|
||||
if binaryVersion.Major() == 0 && binaryVersion.Minor() == 0 {
|
||||
return DefaultKubeEffectiveVersion()
|
||||
}
|
||||
return newEffectiveVersion(binaryVersion, true)
|
||||
}
|
||||
|
||||
// DefaultKubeEffectiveVersion returns the MutableEffectiveVersion based on the
|
||||
// latest K8s release.
|
||||
func DefaultKubeEffectiveVersion() MutableEffectiveVersion {
|
||||
binaryVersion := version.MustParse(DefaultKubeBinaryVersion).WithInfo(Get())
|
||||
return newEffectiveVersion(binaryVersion, false)
|
||||
}
|
||||
|
||||
// ValidateKubeEffectiveVersion validates the EmulationVersion is equal to the binary version at 1.31 for kube components.
|
||||
// emulationVersion is introduced in 1.31, so it is only allowed to be equal to the binary version at 1.31.
|
||||
func ValidateKubeEffectiveVersion(effectiveVersion EffectiveVersion) error {
|
||||
binaryVersion := version.MajorMinor(effectiveVersion.BinaryVersion().Major(), effectiveVersion.BinaryVersion().Minor())
|
||||
if binaryVersion.EqualTo(version.MajorMinor(1, 31)) && !effectiveVersion.EmulationVersion().EqualTo(binaryVersion) {
|
||||
return fmt.Errorf("emulation version needs to be equal to binary version(%s) in compatibility-version alpha, got %s",
|
||||
binaryVersion.String(), effectiveVersion.EmulationVersion().String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
22
vendor/k8s.io/component-base/zpages/features/doc.go
generated
vendored
Normal file
22
vendor/k8s.io/component-base/zpages/features/doc.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright 2024 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 features contains a separate feature set specifically designed for
|
||||
// managing zpages related features. These feature gates control the
|
||||
// availability and behavior of various zpages within Kubernetes components.
|
||||
// New zpages added to Kubernetes components should utilize this feature set
|
||||
// to ensure proper management of their availability.
|
||||
package features
|
52
vendor/k8s.io/component-base/zpages/features/kube_features.go
generated
vendored
Normal file
52
vendor/k8s.io/component-base/zpages/features/kube_features.go
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright 2024 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 features
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
"k8s.io/component-base/featuregate"
|
||||
)
|
||||
|
||||
const (
|
||||
// owner: @richabanker
|
||||
// kep: https://kep.k8s.io/4828
|
||||
ComponentFlagz featuregate.Feature = "ComponentFlagz"
|
||||
|
||||
// owner: @richabanker
|
||||
// kep: https://kep.k8s.io/4827
|
||||
// alpha: v1.32
|
||||
//
|
||||
// Enables /statusz endpoint for a component making it accessible to
|
||||
// users with the system:monitoring cluster role.
|
||||
ComponentStatusz featuregate.Feature = "ComponentStatusz"
|
||||
)
|
||||
|
||||
func featureGates() map[featuregate.Feature]featuregate.VersionedSpecs {
|
||||
return map[featuregate.Feature]featuregate.VersionedSpecs{
|
||||
ComponentFlagz: {
|
||||
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
|
||||
},
|
||||
ComponentStatusz: {
|
||||
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// AddFeatureGates adds all feature gates used by this package.
|
||||
func AddFeatureGates(mutableFeatureGate featuregate.MutableVersionedFeatureGate) error {
|
||||
return mutableFeatureGate.AddVersioned(featureGates())
|
||||
}
|
52
vendor/k8s.io/component-base/zpages/flagz/flagreader.go
generated
vendored
Normal file
52
vendor/k8s.io/component-base/zpages/flagz/flagreader.go
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright 2024 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 flagz
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
)
|
||||
|
||||
type Reader interface {
|
||||
GetFlagz() map[string]string
|
||||
}
|
||||
|
||||
// NamedFlagSetsGetter implements Reader for cliflag.NamedFlagSets
|
||||
type NamedFlagSetsReader struct {
|
||||
FlagSets cliflag.NamedFlagSets
|
||||
}
|
||||
|
||||
func (n NamedFlagSetsReader) GetFlagz() map[string]string {
|
||||
return convertNamedFlagSetToFlags(&n.FlagSets)
|
||||
}
|
||||
|
||||
func convertNamedFlagSetToFlags(flagSets *cliflag.NamedFlagSets) map[string]string {
|
||||
flags := make(map[string]string)
|
||||
for _, fs := range flagSets.FlagSets {
|
||||
fs.VisitAll(func(flag *pflag.Flag) {
|
||||
if flag.Value != nil {
|
||||
value := flag.Value.String()
|
||||
if set, ok := flag.Annotations["classified"]; ok && len(set) > 0 {
|
||||
value = "CLASSIFIED"
|
||||
}
|
||||
flags[flag.Name] = value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return flags
|
||||
}
|
126
vendor/k8s.io/component-base/zpages/flagz/flagz.go
generated
vendored
Normal file
126
vendor/k8s.io/component-base/zpages/flagz/flagz.go
generated
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
Copyright 2024 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 flagz
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/munnerz/goautoneg"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
flagzHeaderFmt = `
|
||||
%s flags
|
||||
Warning: This endpoint is not meant to be machine parseable, has no formatting compatibility guarantees and is for debugging purposes only.
|
||||
|
||||
`
|
||||
)
|
||||
|
||||
var (
|
||||
flagzSeparators = []string{":", ": ", "=", " "}
|
||||
errUnsupportedMediaType = fmt.Errorf("media type not acceptable, must be: text/plain")
|
||||
)
|
||||
|
||||
type registry struct {
|
||||
response bytes.Buffer
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
type mux interface {
|
||||
Handle(path string, handler http.Handler)
|
||||
}
|
||||
|
||||
func Install(m mux, componentName string, flagReader Reader) {
|
||||
var reg registry
|
||||
reg.installHandler(m, componentName, flagReader)
|
||||
}
|
||||
|
||||
func (reg *registry) installHandler(m mux, componentName string, flagReader Reader) {
|
||||
m.Handle("/flagz", reg.handleFlags(componentName, flagReader))
|
||||
}
|
||||
|
||||
func (reg *registry) handleFlags(componentName string, flagReader Reader) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if !acceptableMediaType(r) {
|
||||
http.Error(w, errUnsupportedMediaType.Error(), http.StatusNotAcceptable)
|
||||
return
|
||||
}
|
||||
|
||||
reg.once.Do(func() {
|
||||
fmt.Fprintf(®.response, flagzHeaderFmt, componentName)
|
||||
if flagReader == nil {
|
||||
klog.Error("received nil flagReader")
|
||||
return
|
||||
}
|
||||
|
||||
randomIndex := rand.Intn(len(flagzSeparators))
|
||||
separator := flagzSeparators[randomIndex]
|
||||
// Randomize the delimiter for printing to prevent scraping of the response.
|
||||
printSortedFlags(®.response, flagReader.GetFlagz(), separator)
|
||||
})
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
_, err := w.Write(reg.response.Bytes())
|
||||
if err != nil {
|
||||
klog.Errorf("error writing response: %v", err)
|
||||
http.Error(w, "error writing response", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func acceptableMediaType(r *http.Request) bool {
|
||||
accepts := goautoneg.ParseAccept(r.Header.Get("Accept"))
|
||||
for _, accept := range accepts {
|
||||
if !mediaTypeMatches(accept) {
|
||||
continue
|
||||
}
|
||||
if len(accept.Params) == 0 {
|
||||
return true
|
||||
}
|
||||
if len(accept.Params) == 1 {
|
||||
if charset, ok := accept.Params["charset"]; ok && strings.EqualFold(charset, "utf-8") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func mediaTypeMatches(a goautoneg.Accept) bool {
|
||||
return (a.Type == "text" || a.Type == "*") &&
|
||||
(a.SubType == "plain" || a.SubType == "*")
|
||||
}
|
||||
|
||||
func printSortedFlags(w io.Writer, flags map[string]string, separator string) {
|
||||
var sortedKeys []string
|
||||
for key := range flags {
|
||||
sortedKeys = append(sortedKeys, key)
|
||||
}
|
||||
|
||||
sort.Strings(sortedKeys)
|
||||
for _, key := range sortedKeys {
|
||||
fmt.Fprintf(w, "%s%s%s\n", key, separator, flags[key])
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user