mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
build: move e2e dependencies into e2e/go.mod
Several packages are only used while running the e2e suite. These packages are less important to update, as the they can not influence the final executable that is part of the Ceph-CSI container-image. By moving these dependencies out of the main Ceph-CSI go.mod, it is easier to identify if a reported CVE affects Ceph-CSI, or only the testing (like most of the Kubernetes CVEs). Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
committed by
mergify[bot]
parent
15da101b1b
commit
bec6090996
13
vendor/k8s.io/component-base/config/OWNERS
generated
vendored
13
vendor/k8s.io/component-base/config/OWNERS
generated
vendored
@ -1,13 +0,0 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
# Disable inheritance as this is an api owners file
|
||||
options:
|
||||
no_parent_owners: true
|
||||
approvers:
|
||||
- api-approvers
|
||||
reviewers:
|
||||
- api-reviewers
|
||||
labels:
|
||||
- kind/api-change
|
||||
- sig/api-machinery
|
||||
- sig/scheduling
|
19
vendor/k8s.io/component-base/config/doc.go
generated
vendored
19
vendor/k8s.io/component-base/config/doc.go
generated
vendored
@ -1,19 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
|
||||
package config // import "k8s.io/component-base/config"
|
52
vendor/k8s.io/component-base/config/options/leaderelectionconfig.go
generated
vendored
52
vendor/k8s.io/component-base/config/options/leaderelectionconfig.go
generated
vendored
@ -1,52 +0,0 @@
|
||||
/*
|
||||
Copyright 2017 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 options
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/component-base/config"
|
||||
)
|
||||
|
||||
// BindLeaderElectionFlags binds the LeaderElectionConfiguration struct fields to a flagset
|
||||
func BindLeaderElectionFlags(l *config.LeaderElectionConfiguration, fs *pflag.FlagSet) {
|
||||
fs.BoolVar(&l.LeaderElect, "leader-elect", l.LeaderElect, ""+
|
||||
"Start a leader election client and gain leadership before "+
|
||||
"executing the main loop. Enable this when running replicated "+
|
||||
"components for high availability.")
|
||||
fs.DurationVar(&l.LeaseDuration.Duration, "leader-elect-lease-duration", l.LeaseDuration.Duration, ""+
|
||||
"The duration that non-leader candidates will wait after observing a leadership "+
|
||||
"renewal until attempting to acquire leadership of a led but unrenewed leader "+
|
||||
"slot. This is effectively the maximum duration that a leader can be stopped "+
|
||||
"before it is replaced by another candidate. This is only applicable if leader "+
|
||||
"election is enabled.")
|
||||
fs.DurationVar(&l.RenewDeadline.Duration, "leader-elect-renew-deadline", l.RenewDeadline.Duration, ""+
|
||||
"The interval between attempts by the acting master to renew a leadership slot "+
|
||||
"before it stops leading. This must be less than the lease duration. "+
|
||||
"This is only applicable if leader election is enabled.")
|
||||
fs.DurationVar(&l.RetryPeriod.Duration, "leader-elect-retry-period", l.RetryPeriod.Duration, ""+
|
||||
"The duration the clients should wait between attempting acquisition and renewal "+
|
||||
"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'.")
|
||||
fs.StringVar(&l.ResourceName, "leader-elect-resource-name", l.ResourceName, ""+
|
||||
"The name of resource object that is used for locking during "+
|
||||
"leader election.")
|
||||
fs.StringVar(&l.ResourceNamespace, "leader-elect-resource-namespace", l.ResourceNamespace, ""+
|
||||
"The namespace of resource object that is used for locking during "+
|
||||
"leader election.")
|
||||
}
|
80
vendor/k8s.io/component-base/config/types.go
generated
vendored
80
vendor/k8s.io/component-base/config/types.go
generated
vendored
@ -1,80 +0,0 @@
|
||||
/*
|
||||
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 config
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// ClientConnectionConfiguration contains details for constructing a client.
|
||||
type ClientConnectionConfiguration struct {
|
||||
// kubeconfig is the path to a KubeConfig file.
|
||||
Kubeconfig string
|
||||
// acceptContentTypes defines the Accept header sent by clients when connecting to a server, overriding the
|
||||
// default value of 'application/json'. This field will control all connections to the server used by a particular
|
||||
// client.
|
||||
AcceptContentTypes string
|
||||
// contentType is the content type used when sending data to the server from this client.
|
||||
ContentType string
|
||||
// qps controls the number of queries per second allowed for this connection.
|
||||
QPS float32
|
||||
// burst allows extra queries to accumulate when a client is exceeding its rate.
|
||||
Burst int32
|
||||
}
|
||||
|
||||
// LeaderElectionConfiguration defines the configuration of leader election
|
||||
// clients for components that can run with leader election enabled.
|
||||
type LeaderElectionConfiguration struct {
|
||||
// leaderElect enables a leader election client to gain leadership
|
||||
// before executing the main loop. Enable this when running replicated
|
||||
// components for high availability.
|
||||
LeaderElect bool
|
||||
// leaseDuration is the duration that non-leader candidates will wait
|
||||
// after observing a leadership renewal until attempting to acquire
|
||||
// leadership of a led but unrenewed leader slot. This is effectively the
|
||||
// maximum duration that a leader can be stopped before it is replaced
|
||||
// by another candidate. This is only applicable if leader election is
|
||||
// enabled.
|
||||
LeaseDuration metav1.Duration
|
||||
// renewDeadline is the interval between attempts by the acting master to
|
||||
// renew a leadership slot before it stops leading. This must be less
|
||||
// than or equal to the lease duration. This is only applicable if leader
|
||||
// election is enabled.
|
||||
RenewDeadline metav1.Duration
|
||||
// retryPeriod is the duration the clients should wait between attempting
|
||||
// acquisition and renewal of a leadership. This is only applicable if
|
||||
// leader election is enabled.
|
||||
RetryPeriod metav1.Duration
|
||||
// resourceLock indicates the resource object type that will be used to lock
|
||||
// during leader election cycles.
|
||||
ResourceLock string
|
||||
// resourceName indicates the name of resource object that will be used to lock
|
||||
// during leader election cycles.
|
||||
ResourceName string
|
||||
// resourceNamespace indicates the namespace of resource object that will be used to lock
|
||||
// during leader election cycles.
|
||||
ResourceNamespace string
|
||||
}
|
||||
|
||||
// DebuggingConfiguration holds configuration for Debugging related features.
|
||||
type DebuggingConfiguration struct {
|
||||
// enableProfiling enables profiling via web interface host:port/debug/pprof/
|
||||
EnableProfiling bool
|
||||
// enableContentionProfiling enables block profiling, if
|
||||
// enableProfiling is true.
|
||||
EnableContentionProfiling bool
|
||||
}
|
53
vendor/k8s.io/component-base/config/v1alpha1/conversion.go
generated
vendored
53
vendor/k8s.io/component-base/config/v1alpha1/conversion.go
generated
vendored
@ -1,53 +0,0 @@
|
||||
/*
|
||||
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 v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/component-base/config"
|
||||
)
|
||||
|
||||
// Important! The public back-and-forth conversion functions for the types in this generic
|
||||
// package with ComponentConfig types need to be manually exposed like this in order for
|
||||
// other packages that reference this package to be able to call these conversion functions
|
||||
// in an autogenerated manner.
|
||||
// TODO: Fix the bug in conversion-gen so it automatically discovers these Convert_* functions
|
||||
// in autogenerated code as well.
|
||||
|
||||
func Convert_v1alpha1_ClientConnectionConfiguration_To_config_ClientConnectionConfiguration(in *ClientConnectionConfiguration, out *config.ClientConnectionConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_ClientConnectionConfiguration_To_config_ClientConnectionConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func Convert_config_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration(in *config.ClientConnectionConfiguration, out *ClientConnectionConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_config_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func Convert_v1alpha1_DebuggingConfiguration_To_config_DebuggingConfiguration(in *DebuggingConfiguration, out *config.DebuggingConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_DebuggingConfiguration_To_config_DebuggingConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func Convert_config_DebuggingConfiguration_To_v1alpha1_DebuggingConfiguration(in *config.DebuggingConfiguration, out *DebuggingConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_config_DebuggingConfiguration_To_v1alpha1_DebuggingConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func Convert_v1alpha1_LeaderElectionConfiguration_To_config_LeaderElectionConfiguration(in *LeaderElectionConfiguration, out *config.LeaderElectionConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_LeaderElectionConfiguration_To_config_LeaderElectionConfiguration(in, out, s)
|
||||
}
|
||||
|
||||
func Convert_config_LeaderElectionConfiguration_To_v1alpha1_LeaderElectionConfiguration(in *config.LeaderElectionConfiguration, out *LeaderElectionConfiguration, s conversion.Scope) error {
|
||||
return autoConvert_config_LeaderElectionConfiguration_To_v1alpha1_LeaderElectionConfiguration(in, out, s)
|
||||
}
|
98
vendor/k8s.io/component-base/config/v1alpha1/defaults.go
generated
vendored
98
vendor/k8s.io/component-base/config/v1alpha1/defaults.go
generated
vendored
@ -1,98 +0,0 @@
|
||||
/*
|
||||
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 v1alpha1
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
// RecommendedDefaultLeaderElectionConfiguration defaults a pointer to a
|
||||
// LeaderElectionConfiguration struct. This will set the recommended default
|
||||
// values, but they may be subject to change between API versions. This function
|
||||
// is intentionally not registered in the scheme as a "normal" `SetDefaults_Foo`
|
||||
// function to allow consumers of this type to set whatever defaults for their
|
||||
// embedded configs. Forcing consumers to use these defaults would be problematic
|
||||
// as defaulting in the scheme is done as part of the conversion, and there would
|
||||
// be no easy way to opt-out. Instead, if you want to use this defaulting method
|
||||
// run it in your wrapper struct of this type in its `SetDefaults_` method.
|
||||
func RecommendedDefaultLeaderElectionConfiguration(obj *LeaderElectionConfiguration) {
|
||||
zero := metav1.Duration{}
|
||||
if obj.LeaseDuration == zero {
|
||||
obj.LeaseDuration = metav1.Duration{Duration: 15 * time.Second}
|
||||
}
|
||||
if obj.RenewDeadline == zero {
|
||||
obj.RenewDeadline = metav1.Duration{Duration: 10 * time.Second}
|
||||
}
|
||||
if obj.RetryPeriod == zero {
|
||||
obj.RetryPeriod = metav1.Duration{Duration: 2 * time.Second}
|
||||
}
|
||||
if obj.ResourceLock == "" {
|
||||
// TODO(#80289): Figure out how to migrate to LeaseLock at this point.
|
||||
// This will most probably require going through EndpointsLease first.
|
||||
obj.ResourceLock = EndpointsResourceLock
|
||||
}
|
||||
if obj.LeaderElect == nil {
|
||||
obj.LeaderElect = utilpointer.BoolPtr(true)
|
||||
}
|
||||
}
|
||||
|
||||
// RecommendedDefaultClientConnectionConfiguration defaults a pointer to a
|
||||
// ClientConnectionConfiguration struct. This will set the recommended default
|
||||
// values, but they may be subject to change between API versions. This function
|
||||
// is intentionally not registered in the scheme as a "normal" `SetDefaults_Foo`
|
||||
// function to allow consumers of this type to set whatever defaults for their
|
||||
// embedded configs. Forcing consumers to use these defaults would be problematic
|
||||
// as defaulting in the scheme is done as part of the conversion, and there would
|
||||
// be no easy way to opt-out. Instead, if you want to use this defaulting method
|
||||
// run it in your wrapper struct of this type in its `SetDefaults_` method.
|
||||
func RecommendedDefaultClientConnectionConfiguration(obj *ClientConnectionConfiguration) {
|
||||
if len(obj.ContentType) == 0 {
|
||||
obj.ContentType = "application/vnd.kubernetes.protobuf"
|
||||
}
|
||||
if obj.QPS == 0.0 {
|
||||
obj.QPS = 50.0
|
||||
}
|
||||
if obj.Burst == 0 {
|
||||
obj.Burst = 100
|
||||
}
|
||||
}
|
||||
|
||||
// RecommendedDebuggingConfiguration defaults profiling and debugging configuration.
|
||||
// This will set the recommended default
|
||||
// values, but they may be subject to change between API versions. This function
|
||||
// is intentionally not registered in the scheme as a "normal" `SetDefaults_Foo`
|
||||
// function to allow consumers of this type to set whatever defaults for their
|
||||
// embedded configs. Forcing consumers to use these defaults would be problematic
|
||||
// as defaulting in the scheme is done as part of the conversion, and there would
|
||||
// be no easy way to opt-out. Instead, if you want to use this defaulting method
|
||||
// run it in your wrapper struct of this type in its `SetDefaults_` method.
|
||||
func RecommendedDebuggingConfiguration(obj *DebuggingConfiguration) {
|
||||
if obj.EnableProfiling == nil {
|
||||
obj.EnableProfiling = utilpointer.BoolPtr(true) // profile debugging is cheap to have exposed and standard on kube binaries
|
||||
}
|
||||
}
|
||||
|
||||
// NewRecommendedDebuggingConfiguration returns the current recommended DebuggingConfiguration.
|
||||
// This may change between releases as recommendations shift.
|
||||
func NewRecommendedDebuggingConfiguration() *DebuggingConfiguration {
|
||||
ret := &DebuggingConfiguration{}
|
||||
RecommendedDebuggingConfiguration(ret)
|
||||
return ret
|
||||
}
|
20
vendor/k8s.io/component-base/config/v1alpha1/doc.go
generated
vendored
20
vendor/k8s.io/component-base/config/v1alpha1/doc.go
generated
vendored
@ -1,20 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/component-base/config
|
||||
|
||||
package v1alpha1 // import "k8s.io/component-base/config/v1alpha1"
|
31
vendor/k8s.io/component-base/config/v1alpha1/register.go
generated
vendored
31
vendor/k8s.io/component-base/config/v1alpha1/register.go
generated
vendored
@ -1,31 +0,0 @@
|
||||
/*
|
||||
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 v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
// SchemeBuilder is the scheme builder with scheme init functions to run for this API package
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
// localSchemeBuilder extends the SchemeBuilder instance with the external types. In this package,
|
||||
// defaulting and conversion init funcs are registered as well.
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
// AddToScheme is a global function that registers this API group & version to a scheme
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
82
vendor/k8s.io/component-base/config/v1alpha1/types.go
generated
vendored
82
vendor/k8s.io/component-base/config/v1alpha1/types.go
generated
vendored
@ -1,82 +0,0 @@
|
||||
/*
|
||||
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 v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
const EndpointsResourceLock = "endpoints"
|
||||
|
||||
// LeaderElectionConfiguration defines the configuration of leader election
|
||||
// clients for components that can run with leader election enabled.
|
||||
type LeaderElectionConfiguration struct {
|
||||
// leaderElect enables a leader election client to gain leadership
|
||||
// before executing the main loop. Enable this when running replicated
|
||||
// components for high availability.
|
||||
LeaderElect *bool `json:"leaderElect"`
|
||||
// leaseDuration is the duration that non-leader candidates will wait
|
||||
// after observing a leadership renewal until attempting to acquire
|
||||
// leadership of a led but unrenewed leader slot. This is effectively the
|
||||
// maximum duration that a leader can be stopped before it is replaced
|
||||
// by another candidate. This is only applicable if leader election is
|
||||
// enabled.
|
||||
LeaseDuration metav1.Duration `json:"leaseDuration"`
|
||||
// renewDeadline is the interval between attempts by the acting master to
|
||||
// renew a leadership slot before it stops leading. This must be less
|
||||
// than or equal to the lease duration. This is only applicable if leader
|
||||
// election is enabled.
|
||||
RenewDeadline metav1.Duration `json:"renewDeadline"`
|
||||
// retryPeriod is the duration the clients should wait between attempting
|
||||
// acquisition and renewal of a leadership. This is only applicable if
|
||||
// leader election is enabled.
|
||||
RetryPeriod metav1.Duration `json:"retryPeriod"`
|
||||
// resourceLock indicates the resource object type that will be used to lock
|
||||
// during leader election cycles.
|
||||
ResourceLock string `json:"resourceLock"`
|
||||
// resourceName indicates the name of resource object that will be used to lock
|
||||
// during leader election cycles.
|
||||
ResourceName string `json:"resourceName"`
|
||||
// resourceName indicates the namespace of resource object that will be used to lock
|
||||
// during leader election cycles.
|
||||
ResourceNamespace string `json:"resourceNamespace"`
|
||||
}
|
||||
|
||||
// DebuggingConfiguration holds configuration for Debugging related features.
|
||||
type DebuggingConfiguration struct {
|
||||
// enableProfiling enables profiling via web interface host:port/debug/pprof/
|
||||
EnableProfiling *bool `json:"enableProfiling,omitempty"`
|
||||
// enableContentionProfiling enables block profiling, if
|
||||
// enableProfiling is true.
|
||||
EnableContentionProfiling *bool `json:"enableContentionProfiling,omitempty"`
|
||||
}
|
||||
|
||||
// ClientConnectionConfiguration contains details for constructing a client.
|
||||
type ClientConnectionConfiguration struct {
|
||||
// kubeconfig is the path to a KubeConfig file.
|
||||
Kubeconfig string `json:"kubeconfig"`
|
||||
// acceptContentTypes defines the Accept header sent by clients when connecting to a server, overriding the
|
||||
// default value of 'application/json'. This field will control all connections to the server used by a particular
|
||||
// client.
|
||||
AcceptContentTypes string `json:"acceptContentTypes"`
|
||||
// contentType is the content type used when sending data to the server from this client.
|
||||
ContentType string `json:"contentType"`
|
||||
// qps controls the number of queries per second allowed for this connection.
|
||||
QPS float32 `json:"qps"`
|
||||
// burst allows extra queries to accumulate when a client is exceeding its rate.
|
||||
Burst int32 `json:"burst"`
|
||||
}
|
133
vendor/k8s.io/component-base/config/v1alpha1/zz_generated.conversion.go
generated
vendored
133
vendor/k8s.io/component-base/config/v1alpha1/zz_generated.conversion.go
generated
vendored
@ -1,133 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
config "k8s.io/component-base/config"
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(RegisterConversions)
|
||||
}
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddConversionFunc((*config.ClientConnectionConfiguration)(nil), (*ClientConnectionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration(a.(*config.ClientConnectionConfiguration), b.(*ClientConnectionConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*config.DebuggingConfiguration)(nil), (*DebuggingConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_DebuggingConfiguration_To_v1alpha1_DebuggingConfiguration(a.(*config.DebuggingConfiguration), b.(*DebuggingConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*config.LeaderElectionConfiguration)(nil), (*LeaderElectionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_config_LeaderElectionConfiguration_To_v1alpha1_LeaderElectionConfiguration(a.(*config.LeaderElectionConfiguration), b.(*LeaderElectionConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*ClientConnectionConfiguration)(nil), (*config.ClientConnectionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_ClientConnectionConfiguration_To_config_ClientConnectionConfiguration(a.(*ClientConnectionConfiguration), b.(*config.ClientConnectionConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*DebuggingConfiguration)(nil), (*config.DebuggingConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_DebuggingConfiguration_To_config_DebuggingConfiguration(a.(*DebuggingConfiguration), b.(*config.DebuggingConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*LeaderElectionConfiguration)(nil), (*config.LeaderElectionConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_LeaderElectionConfiguration_To_config_LeaderElectionConfiguration(a.(*LeaderElectionConfiguration), b.(*config.LeaderElectionConfiguration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_ClientConnectionConfiguration_To_config_ClientConnectionConfiguration(in *ClientConnectionConfiguration, out *config.ClientConnectionConfiguration, s conversion.Scope) error {
|
||||
out.Kubeconfig = in.Kubeconfig
|
||||
out.AcceptContentTypes = in.AcceptContentTypes
|
||||
out.ContentType = in.ContentType
|
||||
out.QPS = in.QPS
|
||||
out.Burst = in.Burst
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_config_ClientConnectionConfiguration_To_v1alpha1_ClientConnectionConfiguration(in *config.ClientConnectionConfiguration, out *ClientConnectionConfiguration, s conversion.Scope) error {
|
||||
out.Kubeconfig = in.Kubeconfig
|
||||
out.AcceptContentTypes = in.AcceptContentTypes
|
||||
out.ContentType = in.ContentType
|
||||
out.QPS = in.QPS
|
||||
out.Burst = in.Burst
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_DebuggingConfiguration_To_config_DebuggingConfiguration(in *DebuggingConfiguration, out *config.DebuggingConfiguration, s conversion.Scope) error {
|
||||
if err := v1.Convert_Pointer_bool_To_bool(&in.EnableProfiling, &out.EnableProfiling, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := v1.Convert_Pointer_bool_To_bool(&in.EnableContentionProfiling, &out.EnableContentionProfiling, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_config_DebuggingConfiguration_To_v1alpha1_DebuggingConfiguration(in *config.DebuggingConfiguration, out *DebuggingConfiguration, s conversion.Scope) error {
|
||||
if err := v1.Convert_bool_To_Pointer_bool(&in.EnableProfiling, &out.EnableProfiling, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := v1.Convert_bool_To_Pointer_bool(&in.EnableContentionProfiling, &out.EnableContentionProfiling, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_LeaderElectionConfiguration_To_config_LeaderElectionConfiguration(in *LeaderElectionConfiguration, out *config.LeaderElectionConfiguration, s conversion.Scope) error {
|
||||
if err := v1.Convert_Pointer_bool_To_bool(&in.LeaderElect, &out.LeaderElect, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.LeaseDuration = in.LeaseDuration
|
||||
out.RenewDeadline = in.RenewDeadline
|
||||
out.RetryPeriod = in.RetryPeriod
|
||||
out.ResourceLock = in.ResourceLock
|
||||
out.ResourceName = in.ResourceName
|
||||
out.ResourceNamespace = in.ResourceNamespace
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_config_LeaderElectionConfiguration_To_v1alpha1_LeaderElectionConfiguration(in *config.LeaderElectionConfiguration, out *LeaderElectionConfiguration, s conversion.Scope) error {
|
||||
if err := v1.Convert_bool_To_Pointer_bool(&in.LeaderElect, &out.LeaderElect, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.LeaseDuration = in.LeaseDuration
|
||||
out.RenewDeadline = in.RenewDeadline
|
||||
out.RetryPeriod = in.RetryPeriod
|
||||
out.ResourceLock = in.ResourceLock
|
||||
out.ResourceName = in.ResourceName
|
||||
out.ResourceNamespace = in.ResourceNamespace
|
||||
return nil
|
||||
}
|
88
vendor/k8s.io/component-base/config/v1alpha1/zz_generated.deepcopy.go
generated
vendored
88
vendor/k8s.io/component-base/config/v1alpha1/zz_generated.deepcopy.go
generated
vendored
@ -1,88 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ClientConnectionConfiguration) DeepCopyInto(out *ClientConnectionConfiguration) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientConnectionConfiguration.
|
||||
func (in *ClientConnectionConfiguration) DeepCopy() *ClientConnectionConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClientConnectionConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DebuggingConfiguration) DeepCopyInto(out *DebuggingConfiguration) {
|
||||
*out = *in
|
||||
if in.EnableProfiling != nil {
|
||||
in, out := &in.EnableProfiling, &out.EnableProfiling
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.EnableContentionProfiling != nil {
|
||||
in, out := &in.EnableContentionProfiling, &out.EnableContentionProfiling
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DebuggingConfiguration.
|
||||
func (in *DebuggingConfiguration) DeepCopy() *DebuggingConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DebuggingConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *LeaderElectionConfiguration) DeepCopyInto(out *LeaderElectionConfiguration) {
|
||||
*out = *in
|
||||
if in.LeaderElect != nil {
|
||||
in, out := &in.LeaderElect, &out.LeaderElect
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
out.LeaseDuration = in.LeaseDuration
|
||||
out.RenewDeadline = in.RenewDeadline
|
||||
out.RetryPeriod = in.RetryPeriod
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LeaderElectionConfiguration.
|
||||
func (in *LeaderElectionConfiguration) DeepCopy() *LeaderElectionConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(LeaderElectionConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
61
vendor/k8s.io/component-base/config/validation/validation.go
generated
vendored
61
vendor/k8s.io/component-base/config/validation/validation.go
generated
vendored
@ -1,61 +0,0 @@
|
||||
/*
|
||||
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
|
||||
}
|
73
vendor/k8s.io/component-base/config/zz_generated.deepcopy.go
generated
vendored
73
vendor/k8s.io/component-base/config/zz_generated.deepcopy.go
generated
vendored
@ -1,73 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package config
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ClientConnectionConfiguration) DeepCopyInto(out *ClientConnectionConfiguration) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientConnectionConfiguration.
|
||||
func (in *ClientConnectionConfiguration) DeepCopy() *ClientConnectionConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClientConnectionConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DebuggingConfiguration) DeepCopyInto(out *DebuggingConfiguration) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DebuggingConfiguration.
|
||||
func (in *DebuggingConfiguration) DeepCopy() *DebuggingConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DebuggingConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *LeaderElectionConfiguration) DeepCopyInto(out *LeaderElectionConfiguration) {
|
||||
*out = *in
|
||||
out.LeaseDuration = in.LeaseDuration
|
||||
out.RenewDeadline = in.RenewDeadline
|
||||
out.RetryPeriod = in.RetryPeriod
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LeaderElectionConfiguration.
|
||||
func (in *LeaderElectionConfiguration) DeepCopy() *LeaderElectionConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(LeaderElectionConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
12
vendor/k8s.io/component-base/logs/OWNERS
generated
vendored
12
vendor/k8s.io/component-base/logs/OWNERS
generated
vendored
@ -1,12 +0,0 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- sig-instrumentation-approvers
|
||||
- serathius
|
||||
- pohly
|
||||
reviewers:
|
||||
- sig-instrumentation-reviewers
|
||||
- serathius
|
||||
labels:
|
||||
- sig/instrumentation
|
||||
- wg/structured-logging
|
32
vendor/k8s.io/component-base/logs/api/v1/doc.go
generated
vendored
32
vendor/k8s.io/component-base/logs/api/v1/doc.go
generated
vendored
@ -1,32 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 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.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
|
||||
// Package v1 contains the configuration API for logging.
|
||||
//
|
||||
// The intention is to only have a single version of this API, potentially with
|
||||
// new fields added over time in a backwards-compatible manner. Fields for
|
||||
// alpha or beta features are allowed as long as they are defined so that not
|
||||
// changing the defaults leaves those features disabled.
|
||||
//
|
||||
// The "v1" package name is just a reminder that API compatibility rules apply,
|
||||
// not an indication of the stability of all features covered by it.
|
||||
|
||||
// The LoggingAlphaOptions and LoggingBetaOptions feature gates control whether
|
||||
// these unstable features can get enabled. This can be used to ensure that
|
||||
// command invocations do not accidentally rely on unstable features.
|
||||
package v1 // import "k8s.io/component-base/logs/api/v1"
|
72
vendor/k8s.io/component-base/logs/api/v1/kube_features.go
generated
vendored
72
vendor/k8s.io/component-base/logs/api/v1/kube_features.go
generated
vendored
@ -1,72 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 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 v1
|
||||
|
||||
import (
|
||||
"k8s.io/component-base/featuregate"
|
||||
)
|
||||
|
||||
const (
|
||||
// owner: @pohly
|
||||
// kep: https://kep.k8s.io/3077
|
||||
// alpha: v1.24
|
||||
// beta: v1.30
|
||||
//
|
||||
// Enables looking up a logger from a context.Context instead of using
|
||||
// the global fallback logger and manipulating the logger that is
|
||||
// used by a call chain.
|
||||
ContextualLogging featuregate.Feature = "ContextualLogging"
|
||||
|
||||
// contextualLoggingDefault is now true because the feature reached beta
|
||||
// and performance comparisons showed no relevant degradation when
|
||||
// enabling it.
|
||||
contextualLoggingDefault = true
|
||||
|
||||
// Allow fine-tuning of experimental, alpha-quality logging options.
|
||||
//
|
||||
// Per https://groups.google.com/g/kubernetes-sig-architecture/c/Nxsc7pfe5rw/m/vF2djJh0BAAJ
|
||||
// we want to avoid a proliferation of feature gates. This feature gate:
|
||||
// - will guard *a group* of logging options whose quality level is alpha.
|
||||
// - will never graduate to beta or stable.
|
||||
LoggingAlphaOptions featuregate.Feature = "LoggingAlphaOptions"
|
||||
|
||||
// Allow fine-tuning of experimental, beta-quality logging options.
|
||||
//
|
||||
// Per https://groups.google.com/g/kubernetes-sig-architecture/c/Nxsc7pfe5rw/m/vF2djJh0BAAJ
|
||||
// we want to avoid a proliferation of feature gates. This feature gate:
|
||||
// - will guard *a group* of logging options whose quality level is beta.
|
||||
// - is thus *introduced* as beta
|
||||
// - will never graduate to stable.
|
||||
LoggingBetaOptions featuregate.Feature = "LoggingBetaOptions"
|
||||
|
||||
// Stable logging options. Always enabled.
|
||||
LoggingStableOptions featuregate.Feature = "LoggingStableOptions"
|
||||
)
|
||||
|
||||
func featureGates() map[featuregate.Feature]featuregate.FeatureSpec {
|
||||
return map[featuregate.Feature]featuregate.FeatureSpec{
|
||||
ContextualLogging: {Default: contextualLoggingDefault, PreRelease: featuregate.Beta},
|
||||
|
||||
LoggingAlphaOptions: {Default: false, PreRelease: featuregate.Alpha},
|
||||
LoggingBetaOptions: {Default: true, PreRelease: featuregate.Beta},
|
||||
}
|
||||
}
|
||||
|
||||
// AddFeatureGates adds all feature gates used by this package.
|
||||
func AddFeatureGates(mutableFeatureGate featuregate.MutableFeatureGate) error {
|
||||
return mutableFeatureGate.Add(featureGates())
|
||||
}
|
449
vendor/k8s.io/component-base/logs/api/v1/options.go
generated
vendored
449
vendor/k8s.io/component-base/logs/api/v1/options.go
generated
vendored
@ -1,449 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 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 v1
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/klog/v2/textlogger"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
"k8s.io/component-base/featuregate"
|
||||
"k8s.io/component-base/logs/internal/setverbositylevel"
|
||||
"k8s.io/component-base/logs/klogflags"
|
||||
)
|
||||
|
||||
const (
|
||||
// LogFlushFreqDefault is the default for the corresponding command line
|
||||
// parameter.
|
||||
LogFlushFreqDefault = 5 * time.Second
|
||||
)
|
||||
|
||||
const (
|
||||
// LogFlushFreqFlagName is the name of the command line parameter.
|
||||
// Depending on how flags get added, it is either a stand-alone
|
||||
// value (logs.AddFlags) or part of LoggingConfiguration.
|
||||
LogFlushFreqFlagName = "log-flush-frequency"
|
||||
)
|
||||
|
||||
// NewLoggingConfiguration returns a struct holding the default logging configuration.
|
||||
func NewLoggingConfiguration() *LoggingConfiguration {
|
||||
c := LoggingConfiguration{}
|
||||
SetRecommendedLoggingConfiguration(&c)
|
||||
return &c
|
||||
}
|
||||
|
||||
// Applying configurations multiple times is not safe unless it's guaranteed that there
|
||||
// are no goroutines which might call logging functions. The default for ValidateAndApply
|
||||
// and ValidateAndApplyWithOptions is to return an error when called more than once.
|
||||
// Binaries and unit tests can override that behavior.
|
||||
var ReapplyHandling = ReapplyHandlingError
|
||||
|
||||
type ReapplyHandlingType int
|
||||
|
||||
const (
|
||||
// ReapplyHandlingError is the default: calling ValidateAndApply or
|
||||
// ValidateAndApplyWithOptions again returns an error.
|
||||
ReapplyHandlingError ReapplyHandlingType = iota
|
||||
// ReapplyHandlingIgnoreUnchanged silently ignores any additional calls of
|
||||
// ValidateAndApply or ValidateAndApplyWithOptions if the configuration
|
||||
// is unchanged, otherwise they return an error.
|
||||
ReapplyHandlingIgnoreUnchanged
|
||||
)
|
||||
|
||||
// ValidateAndApply combines validation and application of the logging configuration.
|
||||
// This should be invoked as early as possible because then the rest of the program
|
||||
// startup (including validation of other options) will already run with the final
|
||||
// logging configuration.
|
||||
//
|
||||
// The optional FeatureGate controls logging features. If nil, the default for
|
||||
// these features is used.
|
||||
//
|
||||
// Logging options must be applied as early as possible during the program
|
||||
// startup. Some changes are global and cannot be done safely when there are
|
||||
// already goroutines running.
|
||||
func ValidateAndApply(c *LoggingConfiguration, featureGate featuregate.FeatureGate) error {
|
||||
return validateAndApply(c, nil, featureGate, nil)
|
||||
}
|
||||
|
||||
// ValidateAndApplyWithOptions is a variant of ValidateAndApply which accepts
|
||||
// additional options beyond those that can be configured through the API. This
|
||||
// is meant for testing.
|
||||
//
|
||||
// Logging options must be applied as early as possible during the program
|
||||
// startup. Some changes are global and cannot be done safely when there are
|
||||
// already goroutines running.
|
||||
func ValidateAndApplyWithOptions(c *LoggingConfiguration, options *LoggingOptions, featureGate featuregate.FeatureGate) error {
|
||||
return validateAndApply(c, options, featureGate, nil)
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=false
|
||||
|
||||
// LoggingOptions can be used with ValidateAndApplyWithOptions to override
|
||||
// certain global defaults.
|
||||
type LoggingOptions struct {
|
||||
// ErrorStream can be used to override the os.Stderr default.
|
||||
ErrorStream io.Writer
|
||||
|
||||
// InfoStream can be used to override the os.Stdout default.
|
||||
InfoStream io.Writer
|
||||
}
|
||||
|
||||
// ValidateAndApplyAsField is a variant of ValidateAndApply that should be used
|
||||
// when the LoggingConfiguration is embedded in some larger configuration
|
||||
// structure.
|
||||
func ValidateAndApplyAsField(c *LoggingConfiguration, featureGate featuregate.FeatureGate, fldPath *field.Path) error {
|
||||
return validateAndApply(c, nil, featureGate, fldPath)
|
||||
}
|
||||
|
||||
func validateAndApply(c *LoggingConfiguration, options *LoggingOptions, featureGate featuregate.FeatureGate, fldPath *field.Path) error {
|
||||
errs := Validate(c, featureGate, fldPath)
|
||||
if len(errs) > 0 {
|
||||
return errs.ToAggregate()
|
||||
}
|
||||
return apply(c, options, featureGate)
|
||||
}
|
||||
|
||||
// Validate can be used to check for invalid settings without applying them.
|
||||
// Most binaries should validate and apply the logging configuration as soon
|
||||
// as possible via ValidateAndApply. The field path is optional: nil
|
||||
// can be passed when the struct is not embedded in some larger struct.
|
||||
func Validate(c *LoggingConfiguration, featureGate featuregate.FeatureGate, fldPath *field.Path) field.ErrorList {
|
||||
errs := field.ErrorList{}
|
||||
if c.Format != DefaultLogFormat {
|
||||
// WordSepNormalizeFunc is just a guess. Commands should use it,
|
||||
// but we cannot know for sure.
|
||||
allFlags := unsupportedLoggingFlags(cliflag.WordSepNormalizeFunc)
|
||||
for _, f := range allFlags {
|
||||
if f.DefValue != f.Value.String() {
|
||||
errs = append(errs, field.Invalid(fldPath.Child("format"), c.Format, fmt.Sprintf("Non-default format doesn't honor flag: %s", f.Name)))
|
||||
}
|
||||
}
|
||||
}
|
||||
format, err := logRegistry.get(c.Format)
|
||||
if err != nil {
|
||||
errs = append(errs, field.Invalid(fldPath.Child("format"), c.Format, "Unsupported log format"))
|
||||
} else if format != nil {
|
||||
if format.feature != LoggingStableOptions {
|
||||
enabled := featureGates()[format.feature].Default
|
||||
if featureGate != nil {
|
||||
enabled = featureGate.Enabled(format.feature)
|
||||
}
|
||||
if !enabled {
|
||||
errs = append(errs, field.Forbidden(fldPath.Child("format"), fmt.Sprintf("Log format %s is disabled, see %s feature", c.Format, format.feature)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The type in our struct is uint32, but klog only accepts positive int32.
|
||||
if c.Verbosity > math.MaxInt32 {
|
||||
errs = append(errs, field.Invalid(fldPath.Child("verbosity"), c.Verbosity, fmt.Sprintf("Must be <= %d", math.MaxInt32)))
|
||||
}
|
||||
vmoduleFldPath := fldPath.Child("vmodule")
|
||||
if len(c.VModule) > 0 && c.Format != "" && c.Format != "text" {
|
||||
errs = append(errs, field.Forbidden(vmoduleFldPath, "Only supported for text log format"))
|
||||
}
|
||||
for i, item := range c.VModule {
|
||||
if item.FilePattern == "" {
|
||||
errs = append(errs, field.Required(vmoduleFldPath.Index(i), "File pattern must not be empty"))
|
||||
}
|
||||
if strings.ContainsAny(item.FilePattern, "=,") {
|
||||
errs = append(errs, field.Invalid(vmoduleFldPath.Index(i), item.FilePattern, "File pattern must not contain equal sign or comma"))
|
||||
}
|
||||
if item.Verbosity > math.MaxInt32 {
|
||||
errs = append(errs, field.Invalid(vmoduleFldPath.Index(i), item.Verbosity, fmt.Sprintf("Must be <= %d", math.MaxInt32)))
|
||||
}
|
||||
}
|
||||
|
||||
errs = append(errs, validateFormatOptions(c, featureGate, fldPath.Child("options"))...)
|
||||
return errs
|
||||
}
|
||||
|
||||
func validateFormatOptions(c *LoggingConfiguration, featureGate featuregate.FeatureGate, fldPath *field.Path) field.ErrorList {
|
||||
errs := field.ErrorList{}
|
||||
errs = append(errs, validateTextOptions(c, featureGate, fldPath.Child("text"))...)
|
||||
errs = append(errs, validateJSONOptions(c, featureGate, fldPath.Child("json"))...)
|
||||
return errs
|
||||
}
|
||||
|
||||
func validateTextOptions(c *LoggingConfiguration, featureGate featuregate.FeatureGate, fldPath *field.Path) field.ErrorList {
|
||||
errs := field.ErrorList{}
|
||||
if gate := LoggingAlphaOptions; c.Options.Text.SplitStream && !featureEnabled(featureGate, gate) {
|
||||
errs = append(errs, field.Forbidden(fldPath.Child("splitStream"), fmt.Sprintf("Feature %s is disabled", gate)))
|
||||
}
|
||||
if gate := LoggingAlphaOptions; c.Options.Text.InfoBufferSize.Value() != 0 && !featureEnabled(featureGate, gate) {
|
||||
errs = append(errs, field.Forbidden(fldPath.Child("infoBufferSize"), fmt.Sprintf("Feature %s is disabled", gate)))
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
func validateJSONOptions(c *LoggingConfiguration, featureGate featuregate.FeatureGate, fldPath *field.Path) field.ErrorList {
|
||||
errs := field.ErrorList{}
|
||||
if gate := LoggingAlphaOptions; c.Options.JSON.SplitStream && !featureEnabled(featureGate, gate) {
|
||||
errs = append(errs, field.Forbidden(fldPath.Child("splitStream"), fmt.Sprintf("Feature %s is disabled", gate)))
|
||||
}
|
||||
if gate := LoggingAlphaOptions; c.Options.JSON.InfoBufferSize.Value() != 0 && !featureEnabled(featureGate, gate) {
|
||||
errs = append(errs, field.Forbidden(fldPath.Child("infoBufferSize"), fmt.Sprintf("Feature %s is disabled", gate)))
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
func featureEnabled(featureGate featuregate.FeatureGate, feature featuregate.Feature) bool {
|
||||
enabled := false
|
||||
if featureGate != nil {
|
||||
enabled = featureGate.Enabled(feature)
|
||||
}
|
||||
return enabled
|
||||
}
|
||||
|
||||
func apply(c *LoggingConfiguration, options *LoggingOptions, featureGate featuregate.FeatureGate) error {
|
||||
p := ¶meters{
|
||||
C: c,
|
||||
Options: options,
|
||||
ContextualLoggingEnabled: contextualLoggingDefault,
|
||||
}
|
||||
if featureGate != nil {
|
||||
p.ContextualLoggingEnabled = featureGate.Enabled(ContextualLogging)
|
||||
}
|
||||
|
||||
oldP := applyParameters.Load()
|
||||
if oldP != nil {
|
||||
switch ReapplyHandling {
|
||||
case ReapplyHandlingError:
|
||||
return errors.New("logging configuration was already applied earlier, changing it is not allowed")
|
||||
case ReapplyHandlingIgnoreUnchanged:
|
||||
if diff := cmp.Diff(oldP, p); diff != "" {
|
||||
return fmt.Errorf("the logging configuration should not be changed after setting it once (- old setting, + new setting):\n%s", diff)
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("invalid value %d for ReapplyHandling", ReapplyHandling)
|
||||
}
|
||||
}
|
||||
applyParameters.Store(p)
|
||||
|
||||
// if log format not exists, use nil loggr
|
||||
format, _ := logRegistry.get(c.Format)
|
||||
if format.factory == nil {
|
||||
klog.ClearLogger()
|
||||
} else {
|
||||
if options == nil {
|
||||
options = &LoggingOptions{
|
||||
ErrorStream: os.Stderr,
|
||||
InfoStream: os.Stdout,
|
||||
}
|
||||
}
|
||||
log, control := format.factory.Create(*c, *options)
|
||||
if control.SetVerbosityLevel != nil {
|
||||
setverbositylevel.Mutex.Lock()
|
||||
defer setverbositylevel.Mutex.Unlock()
|
||||
setverbositylevel.Callbacks = append(setverbositylevel.Callbacks, control.SetVerbosityLevel)
|
||||
}
|
||||
opts := []klog.LoggerOption{
|
||||
klog.ContextualLogger(p.ContextualLoggingEnabled),
|
||||
klog.FlushLogger(control.Flush),
|
||||
}
|
||||
if writer, ok := log.GetSink().(textlogger.KlogBufferWriter); ok {
|
||||
opts = append(opts, klog.WriteKlogBuffer(writer.WriteKlogBuffer))
|
||||
}
|
||||
klog.SetLoggerWithOptions(log, opts...)
|
||||
}
|
||||
if err := loggingFlags.Lookup("v").Value.Set(VerbosityLevelPflag(&c.Verbosity).String()); err != nil {
|
||||
return fmt.Errorf("internal error while setting klog verbosity: %v", err)
|
||||
}
|
||||
if err := loggingFlags.Lookup("vmodule").Value.Set(VModuleConfigurationPflag(&c.VModule).String()); err != nil {
|
||||
return fmt.Errorf("internal error while setting klog vmodule: %v", err)
|
||||
}
|
||||
setSlogDefaultLogger()
|
||||
klog.StartFlushDaemon(c.FlushFrequency.Duration.Duration)
|
||||
klog.EnableContextualLogging(p.ContextualLoggingEnabled)
|
||||
return nil
|
||||
}
|
||||
|
||||
type parameters struct {
|
||||
C *LoggingConfiguration
|
||||
Options *LoggingOptions
|
||||
ContextualLoggingEnabled bool
|
||||
}
|
||||
|
||||
var applyParameters atomic.Pointer[parameters]
|
||||
|
||||
// ResetForTest restores the default settings. This is not thread-safe and should only
|
||||
// be used when there are no goroutines running. The intended users are unit
|
||||
// tests in other packages.
|
||||
func ResetForTest(featureGate featuregate.FeatureGate) error {
|
||||
oldP := applyParameters.Load()
|
||||
if oldP == nil {
|
||||
// Nothing to do.
|
||||
return nil
|
||||
}
|
||||
|
||||
// This makes it possible to call apply again without triggering errors.
|
||||
applyParameters.Store(nil)
|
||||
|
||||
// Restore defaults. Shouldn't fail, but check anyway.
|
||||
config := NewLoggingConfiguration()
|
||||
if err := ValidateAndApply(config, featureGate); err != nil {
|
||||
return fmt.Errorf("apply default configuration: %v", err)
|
||||
}
|
||||
|
||||
// And again...
|
||||
applyParameters.Store(nil)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddFlags adds command line flags for the configuration.
|
||||
func AddFlags(c *LoggingConfiguration, fs *pflag.FlagSet) {
|
||||
addFlags(c, fs)
|
||||
}
|
||||
|
||||
// AddGoFlags is a variant of AddFlags for a standard FlagSet.
|
||||
func AddGoFlags(c *LoggingConfiguration, fs *flag.FlagSet) {
|
||||
addFlags(c, goFlagSet{FlagSet: fs})
|
||||
}
|
||||
|
||||
// flagSet is the interface implemented by pflag.FlagSet, with
|
||||
// just those methods defined which are needed by addFlags.
|
||||
type flagSet interface {
|
||||
BoolVar(p *bool, name string, value bool, usage string)
|
||||
DurationVar(p *time.Duration, name string, value time.Duration, usage string)
|
||||
StringVar(p *string, name string, value string, usage string)
|
||||
Var(value pflag.Value, name string, usage string)
|
||||
VarP(value pflag.Value, name, shorthand, usage string)
|
||||
}
|
||||
|
||||
// goFlagSet implements flagSet for a stdlib flag.FlagSet.
|
||||
type goFlagSet struct {
|
||||
*flag.FlagSet
|
||||
}
|
||||
|
||||
func (fs goFlagSet) Var(value pflag.Value, name string, usage string) {
|
||||
fs.FlagSet.Var(value, name, usage)
|
||||
}
|
||||
|
||||
func (fs goFlagSet) VarP(value pflag.Value, name, shorthand, usage string) {
|
||||
// Ignore shorthand, it's not needed and not supported.
|
||||
fs.FlagSet.Var(value, name, usage)
|
||||
}
|
||||
|
||||
// addFlags can be used with both flag.FlagSet and pflag.FlagSet. The internal
|
||||
// interface definition avoids duplicating this code.
|
||||
func addFlags(c *LoggingConfiguration, fs flagSet) {
|
||||
formats := logRegistry.list()
|
||||
fs.StringVar(&c.Format, "logging-format", c.Format, fmt.Sprintf("Sets the log format. Permitted formats: %s.", formats))
|
||||
// No new log formats should be added after generation is of flag options
|
||||
logRegistry.freeze()
|
||||
|
||||
fs.DurationVar(&c.FlushFrequency.Duration.Duration, LogFlushFreqFlagName, c.FlushFrequency.Duration.Duration, "Maximum number of seconds between log flushes")
|
||||
fs.VarP(VerbosityLevelPflag(&c.Verbosity), "v", "v", "number for the log level verbosity")
|
||||
fs.Var(VModuleConfigurationPflag(&c.VModule), "vmodule", "comma-separated list of pattern=N settings for file-filtered logging (only works for text log format)")
|
||||
|
||||
fs.BoolVar(&c.Options.Text.SplitStream, "log-text-split-stream", false, "[Alpha] In text format, write error messages to stderr and info messages to stdout. The default is to write a single stream to stdout. Enable the LoggingAlphaOptions feature gate to use this.")
|
||||
fs.Var(&c.Options.Text.InfoBufferSize, "log-text-info-buffer-size", "[Alpha] In text format with split output streams, the info messages can be buffered for a while to increase performance. The default value of zero bytes disables buffering. The size can be specified as number of bytes (512), multiples of 1000 (1K), multiples of 1024 (2Ki), or powers of those (3M, 4G, 5Mi, 6Gi). Enable the LoggingAlphaOptions feature gate to use this.")
|
||||
|
||||
// JSON options. We only register them if "json" is a valid format. The
|
||||
// config file API however always has them.
|
||||
if _, err := logRegistry.get("json"); err == nil {
|
||||
fs.BoolVar(&c.Options.JSON.SplitStream, "log-json-split-stream", false, "[Alpha] In JSON format, write error messages to stderr and info messages to stdout. The default is to write a single stream to stdout. Enable the LoggingAlphaOptions feature gate to use this.")
|
||||
fs.Var(&c.Options.JSON.InfoBufferSize, "log-json-info-buffer-size", "[Alpha] In JSON format with split output streams, the info messages can be buffered for a while to increase performance. The default value of zero bytes disables buffering. The size can be specified as number of bytes (512), multiples of 1000 (1K), multiples of 1024 (2Ki), or powers of those (3M, 4G, 5Mi, 6Gi). Enable the LoggingAlphaOptions feature gate to use this.")
|
||||
}
|
||||
}
|
||||
|
||||
// SetRecommendedLoggingConfiguration sets the default logging configuration
|
||||
// for fields that are unset.
|
||||
//
|
||||
// Consumers who embed LoggingConfiguration in their own configuration structs
|
||||
// may set custom defaults and then should call this function to add the
|
||||
// global defaults.
|
||||
func SetRecommendedLoggingConfiguration(c *LoggingConfiguration) {
|
||||
if c.Format == "" {
|
||||
c.Format = "text"
|
||||
}
|
||||
if c.FlushFrequency.Duration.Duration == 0 {
|
||||
c.FlushFrequency.Duration.Duration = LogFlushFreqDefault
|
||||
c.FlushFrequency.SerializeAsString = true
|
||||
}
|
||||
setRecommendedOutputRouting(&c.Options.Text.OutputRoutingOptions)
|
||||
setRecommendedOutputRouting(&c.Options.JSON.OutputRoutingOptions)
|
||||
}
|
||||
|
||||
func setRecommendedOutputRouting(o *OutputRoutingOptions) {
|
||||
var empty resource.QuantityValue
|
||||
if o.InfoBufferSize == empty {
|
||||
o.InfoBufferSize = resource.QuantityValue{
|
||||
// This is similar, but not quite the same as a default
|
||||
// constructed instance.
|
||||
Quantity: *resource.NewQuantity(0, resource.DecimalSI),
|
||||
}
|
||||
// This sets the unexported Quantity.s which will be compared
|
||||
// by reflect.DeepEqual in some tests.
|
||||
_ = o.InfoBufferSize.String()
|
||||
}
|
||||
}
|
||||
|
||||
// loggingFlags captures the state of the logging flags, in particular their default value
|
||||
// before flag parsing. It is used by unsupportedLoggingFlags.
|
||||
var loggingFlags pflag.FlagSet
|
||||
|
||||
func init() {
|
||||
var fs flag.FlagSet
|
||||
klogflags.Init(&fs)
|
||||
loggingFlags.AddGoFlagSet(&fs)
|
||||
}
|
||||
|
||||
// List of logs (k8s.io/klog + k8s.io/component-base/logs) flags supported by all logging formats
|
||||
var supportedLogsFlags = map[string]struct{}{
|
||||
"v": {},
|
||||
}
|
||||
|
||||
// unsupportedLoggingFlags lists unsupported logging flags. The normalize
|
||||
// function is optional.
|
||||
func unsupportedLoggingFlags(normalizeFunc func(f *pflag.FlagSet, name string) pflag.NormalizedName) []*pflag.Flag {
|
||||
// k8s.io/component-base/logs and klog flags
|
||||
pfs := &pflag.FlagSet{}
|
||||
loggingFlags.VisitAll(func(flag *pflag.Flag) {
|
||||
if _, found := supportedLogsFlags[flag.Name]; !found {
|
||||
// Normalization changes flag.Name, so make a copy.
|
||||
clone := *flag
|
||||
pfs.AddFlag(&clone)
|
||||
}
|
||||
})
|
||||
|
||||
// Apply normalization.
|
||||
pfs.SetNormalizeFunc(normalizeFunc)
|
||||
|
||||
var allFlags []*pflag.Flag
|
||||
pfs.VisitAll(func(flag *pflag.Flag) {
|
||||
allFlags = append(allFlags, flag)
|
||||
})
|
||||
return allFlags
|
||||
}
|
24
vendor/k8s.io/component-base/logs/api/v1/options_no_slog.go
generated
vendored
24
vendor/k8s.io/component-base/logs/api/v1/options_no_slog.go
generated
vendored
@ -1,24 +0,0 @@
|
||||
//go:build !go1.21
|
||||
// +build !go1.21
|
||||
|
||||
/*
|
||||
Copyright 2023 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 v1
|
||||
|
||||
func setSlogDefaultLogger() {
|
||||
// Do nothing when build with Go < 1.21.
|
||||
}
|
37
vendor/k8s.io/component-base/logs/api/v1/options_slog.go
generated
vendored
37
vendor/k8s.io/component-base/logs/api/v1/options_slog.go
generated
vendored
@ -1,37 +0,0 @@
|
||||
//go:build go1.21
|
||||
// +build go1.21
|
||||
|
||||
/*
|
||||
Copyright 2023 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 v1
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// setSlogDefaultLogger sets the global slog default logger to the same default
|
||||
// that klog currently uses.
|
||||
func setSlogDefaultLogger() {
|
||||
// klog.Background() always returns a valid logr.Logger, regardless of
|
||||
// how logging was configured. We just need to turn it into a
|
||||
// slog.Handler. SetDefault then needs a slog.Logger.
|
||||
handler := logr.ToSlogHandler(klog.Background())
|
||||
slog.SetDefault(slog.New(handler))
|
||||
}
|
113
vendor/k8s.io/component-base/logs/api/v1/pflags.go
generated
vendored
113
vendor/k8s.io/component-base/logs/api/v1/pflags.go
generated
vendored
@ -1,113 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 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 v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// VModuleConfigurationPflag implements the pflag.Value interface for a
|
||||
// VModuleConfiguration. The value pointer must not be nil.
|
||||
func VModuleConfigurationPflag(value *VModuleConfiguration) pflag.Value {
|
||||
return vmoduleConfigurationPFlag{value}
|
||||
}
|
||||
|
||||
type vmoduleConfigurationPFlag struct {
|
||||
value *VModuleConfiguration
|
||||
}
|
||||
|
||||
// String returns the -vmodule parameter (comma-separated list of pattern=N).
|
||||
func (wrapper vmoduleConfigurationPFlag) String() string {
|
||||
if wrapper.value == nil {
|
||||
return ""
|
||||
}
|
||||
var patterns []string
|
||||
for _, item := range *wrapper.value {
|
||||
patterns = append(patterns, fmt.Sprintf("%s=%d", item.FilePattern, item.Verbosity))
|
||||
}
|
||||
return strings.Join(patterns, ",")
|
||||
}
|
||||
|
||||
// Set parses the -vmodule parameter (comma-separated list of pattern=N).
|
||||
func (wrapper vmoduleConfigurationPFlag) Set(value string) error {
|
||||
// This code mirrors https://github.com/kubernetes/klog/blob/9ad246211af1ed84621ee94a26fcce0038b69cd1/klog.go#L287-L313
|
||||
|
||||
for _, pat := range strings.Split(value, ",") {
|
||||
if len(pat) == 0 {
|
||||
// Empty strings such as from a trailing comma can be ignored.
|
||||
continue
|
||||
}
|
||||
patLev := strings.Split(pat, "=")
|
||||
if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 {
|
||||
return fmt.Errorf("%q does not have the pattern=N format", pat)
|
||||
}
|
||||
pattern := patLev[0]
|
||||
// 31 instead of 32 to ensure that it also fits into int32.
|
||||
v, err := strconv.ParseUint(patLev[1], 10, 31)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing verbosity in %q: %v", pat, err)
|
||||
}
|
||||
*wrapper.value = append(*wrapper.value, VModuleItem{FilePattern: pattern, Verbosity: VerbosityLevel(v)})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wrapper vmoduleConfigurationPFlag) Type() string {
|
||||
return "pattern=N,..."
|
||||
}
|
||||
|
||||
// VerbosityLevelPflag implements the pflag.Value interface for a verbosity
|
||||
// level value.
|
||||
func VerbosityLevelPflag(value *VerbosityLevel) pflag.Value {
|
||||
return verbosityLevelPflag{value}
|
||||
}
|
||||
|
||||
type verbosityLevelPflag struct {
|
||||
value *VerbosityLevel
|
||||
}
|
||||
|
||||
func (wrapper verbosityLevelPflag) String() string {
|
||||
if wrapper.value == nil {
|
||||
return "0"
|
||||
}
|
||||
return strconv.FormatInt(int64(*wrapper.value), 10)
|
||||
}
|
||||
|
||||
func (wrapper verbosityLevelPflag) Get() interface{} {
|
||||
if wrapper.value == nil {
|
||||
return VerbosityLevel(0)
|
||||
}
|
||||
return *wrapper.value
|
||||
}
|
||||
|
||||
func (wrapper verbosityLevelPflag) Set(value string) error {
|
||||
// Limited to int32 for compatibility with klog.
|
||||
v, err := strconv.ParseUint(value, 10, 31)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*wrapper.value = VerbosityLevel(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wrapper verbosityLevelPflag) Type() string {
|
||||
return "Level"
|
||||
}
|
135
vendor/k8s.io/component-base/logs/api/v1/registry.go
generated
vendored
135
vendor/k8s.io/component-base/logs/api/v1/registry.go
generated
vendored
@ -1,135 +0,0 @@
|
||||
/*
|
||||
Copyright 2020 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 v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
|
||||
"k8s.io/component-base/featuregate"
|
||||
)
|
||||
|
||||
var logRegistry = newLogFormatRegistry()
|
||||
|
||||
// logFormatRegistry stores factories for all supported logging formats.
|
||||
type logFormatRegistry struct {
|
||||
mutex sync.Mutex
|
||||
registry map[string]logFormat
|
||||
frozen bool
|
||||
}
|
||||
|
||||
type logFormat struct {
|
||||
factory LogFormatFactory
|
||||
feature featuregate.Feature
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=false
|
||||
|
||||
// RuntimeControl provides operations that aren't available through the normal
|
||||
// Logger or LogSink API.
|
||||
type RuntimeControl struct {
|
||||
// Flush ensures that all in-memory data is written.
|
||||
// May be nil.
|
||||
Flush func()
|
||||
|
||||
// SetVerbosityLevel changes the level for all Logger instances
|
||||
// derived from the initial one. May be nil.
|
||||
//
|
||||
// The parameter is intentionally a plain uint32 instead of
|
||||
// VerbosityLevel to enable implementations that don't need to import
|
||||
// the API (helps avoid circular dependencies).
|
||||
SetVerbosityLevel func(v uint32) error
|
||||
}
|
||||
|
||||
// LogFormatFactory provides support for a certain additional,
|
||||
// non-default log format.
|
||||
type LogFormatFactory interface {
|
||||
// Create returns a logger with the requested configuration.
|
||||
Create(c LoggingConfiguration, o LoggingOptions) (logr.Logger, RuntimeControl)
|
||||
}
|
||||
|
||||
// RegisterLogFormat registers support for a new logging format. This must be called
|
||||
// before using any of the methods in LoggingConfiguration. The feature must
|
||||
// be one of those defined in this package (typically LoggingAlphaOptions,
|
||||
// LoggingBetaOptions or LoggingStableOptions).
|
||||
func RegisterLogFormat(name string, factory LogFormatFactory, feature featuregate.Feature) error {
|
||||
return logRegistry.register(name, logFormat{factory, feature})
|
||||
}
|
||||
|
||||
func newLogFormatRegistry() *logFormatRegistry {
|
||||
registry := &logFormatRegistry{
|
||||
registry: make(map[string]logFormat),
|
||||
frozen: false,
|
||||
}
|
||||
_ = registry.register(DefaultLogFormat, logFormat{factory: textFactory{}, feature: LoggingStableOptions})
|
||||
return registry
|
||||
}
|
||||
|
||||
// register adds a new log format. It's an error to modify an existing one.
|
||||
func (lfr *logFormatRegistry) register(name string, format logFormat) error {
|
||||
lfr.mutex.Lock()
|
||||
defer lfr.mutex.Unlock()
|
||||
if lfr.frozen {
|
||||
return fmt.Errorf("log format registry is frozen, unable to register log format %s", name)
|
||||
}
|
||||
if _, ok := lfr.registry[name]; ok {
|
||||
return fmt.Errorf("log format: %s already exists", name)
|
||||
}
|
||||
if _, ok := featureGates()[format.feature]; !ok && format.feature != LoggingStableOptions {
|
||||
return fmt.Errorf("log format %s: unsupported feature gate %s", name, format.feature)
|
||||
}
|
||||
lfr.registry[name] = format
|
||||
return nil
|
||||
}
|
||||
|
||||
// get specified log format factory
|
||||
func (lfr *logFormatRegistry) get(name string) (*logFormat, error) {
|
||||
lfr.mutex.Lock()
|
||||
defer lfr.mutex.Unlock()
|
||||
format, ok := lfr.registry[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("log format: %s does not exists", name)
|
||||
}
|
||||
return &format, nil
|
||||
}
|
||||
|
||||
// list names of registered log formats, including feature gates (sorted)
|
||||
func (lfr *logFormatRegistry) list() string {
|
||||
lfr.mutex.Lock()
|
||||
defer lfr.mutex.Unlock()
|
||||
formats := make([]string, 0, len(lfr.registry))
|
||||
for name, format := range lfr.registry {
|
||||
item := fmt.Sprintf(`"%s"`, name)
|
||||
if format.feature != LoggingStableOptions {
|
||||
item += fmt.Sprintf(" (gated by %s)", format.feature)
|
||||
}
|
||||
formats = append(formats, item)
|
||||
}
|
||||
sort.Strings(formats)
|
||||
return strings.Join(formats, ", ")
|
||||
}
|
||||
|
||||
// freeze prevents further modifications of the registered log formats.
|
||||
func (lfr *logFormatRegistry) freeze() {
|
||||
lfr.mutex.Lock()
|
||||
defer lfr.mutex.Unlock()
|
||||
lfr.frozen = true
|
||||
}
|
142
vendor/k8s.io/component-base/logs/api/v1/text.go
generated
vendored
142
vendor/k8s.io/component-base/logs/api/v1/text.go
generated
vendored
@ -1,142 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 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 v1
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
|
||||
"k8s.io/component-base/featuregate"
|
||||
"k8s.io/klog/v2/textlogger"
|
||||
)
|
||||
|
||||
// textFactory produces klog text logger instances.
|
||||
type textFactory struct{}
|
||||
|
||||
var _ LogFormatFactory = textFactory{}
|
||||
|
||||
func (f textFactory) Feature() featuregate.Feature {
|
||||
return LoggingStableOptions
|
||||
}
|
||||
|
||||
func (f textFactory) Create(c LoggingConfiguration, o LoggingOptions) (logr.Logger, RuntimeControl) {
|
||||
output := o.ErrorStream
|
||||
var flush func()
|
||||
if c.Options.Text.SplitStream {
|
||||
r := &klogMsgRouter{
|
||||
info: o.InfoStream,
|
||||
error: o.ErrorStream,
|
||||
}
|
||||
size := c.Options.Text.InfoBufferSize.Value()
|
||||
if size > 0 {
|
||||
// Prevent integer overflow.
|
||||
if size > 2*1024*1024*1024 {
|
||||
size = 2 * 1024 * 1024 * 1024
|
||||
}
|
||||
info := newBufferedWriter(r.info, int(size))
|
||||
flush = info.Flush
|
||||
r.info = info
|
||||
}
|
||||
output = r
|
||||
}
|
||||
|
||||
options := []textlogger.ConfigOption{
|
||||
textlogger.Verbosity(int(c.Verbosity)),
|
||||
textlogger.Output(output),
|
||||
}
|
||||
loggerConfig := textlogger.NewConfig(options...)
|
||||
|
||||
// This should never fail, we produce a valid string here.
|
||||
_ = loggerConfig.VModule().Set(VModuleConfigurationPflag(&c.VModule).String())
|
||||
|
||||
return textlogger.NewLogger(loggerConfig),
|
||||
RuntimeControl{
|
||||
SetVerbosityLevel: func(v uint32) error {
|
||||
return loggerConfig.Verbosity().Set(fmt.Sprintf("%d", v))
|
||||
},
|
||||
Flush: flush,
|
||||
}
|
||||
}
|
||||
|
||||
type klogMsgRouter struct {
|
||||
info, error io.Writer
|
||||
}
|
||||
|
||||
var _ io.Writer = &klogMsgRouter{}
|
||||
|
||||
// Write redirects the message into either the info or error
|
||||
// stream, depending on its type as indicated in text format
|
||||
// by the first byte.
|
||||
func (r *klogMsgRouter) Write(p []byte) (int, error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if p[0] == 'I' {
|
||||
return r.info.Write(p)
|
||||
}
|
||||
return r.error.Write(p)
|
||||
}
|
||||
|
||||
// bufferedWriter is an io.Writer that buffers writes in-memory before
|
||||
// flushing them to a wrapped io.Writer after reaching some limit
|
||||
// or getting flushed.
|
||||
type bufferedWriter struct {
|
||||
mu sync.Mutex
|
||||
writer *bufio.Writer
|
||||
out io.Writer
|
||||
}
|
||||
|
||||
func newBufferedWriter(out io.Writer, size int) *bufferedWriter {
|
||||
return &bufferedWriter{
|
||||
writer: bufio.NewWriterSize(out, size),
|
||||
out: out,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *bufferedWriter) Write(p []byte) (int, error) {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
|
||||
// To avoid partial writes into the underlying writer, we ensure that
|
||||
// the entire new data fits into the buffer or flush first.
|
||||
if len(p) > b.writer.Available() && b.writer.Buffered() > 0 {
|
||||
if err := b.writer.Flush(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
// If it still doesn't fit, then we bypass the now empty buffer
|
||||
// and write directly.
|
||||
if len(p) > b.writer.Available() {
|
||||
return b.out.Write(p)
|
||||
}
|
||||
|
||||
// This goes into the buffer.
|
||||
return b.writer.Write(p)
|
||||
}
|
||||
|
||||
func (b *bufferedWriter) Flush() {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
|
||||
_ = b.writer.Flush()
|
||||
}
|
146
vendor/k8s.io/component-base/logs/api/v1/types.go
generated
vendored
146
vendor/k8s.io/component-base/logs/api/v1/types.go
generated
vendored
@ -1,146 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 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 v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// Supported output formats.
|
||||
const (
|
||||
// DefaultLogFormat is the traditional klog output format.
|
||||
DefaultLogFormat = "text"
|
||||
|
||||
// JSONLogFormat emits each log message as a JSON struct.
|
||||
JSONLogFormat = "json"
|
||||
)
|
||||
|
||||
// The alpha or beta level of structs is the highest stability level of any field
|
||||
// inside it. Feature gates will get checked during LoggingConfiguration.ValidateAndApply.
|
||||
|
||||
// LoggingConfiguration contains logging options.
|
||||
type LoggingConfiguration struct {
|
||||
// Format Flag specifies the structure of log messages.
|
||||
// default value of format is `text`
|
||||
Format string `json:"format,omitempty"`
|
||||
// Maximum time between log flushes.
|
||||
// If a string, parsed as a duration (i.e. "1s")
|
||||
// If an int, the maximum number of nanoseconds (i.e. 1s = 1000000000).
|
||||
// Ignored if the selected logging backend writes log messages without buffering.
|
||||
FlushFrequency TimeOrMetaDuration `json:"flushFrequency"`
|
||||
// Verbosity is the threshold that determines which log messages are
|
||||
// logged. Default is zero which logs only the most important
|
||||
// messages. Higher values enable additional messages. Error messages
|
||||
// are always logged.
|
||||
Verbosity VerbosityLevel `json:"verbosity"`
|
||||
// VModule overrides the verbosity threshold for individual files.
|
||||
// Only supported for "text" log format.
|
||||
VModule VModuleConfiguration `json:"vmodule,omitempty"`
|
||||
// [Alpha] Options holds additional parameters that are specific
|
||||
// to the different logging formats. Only the options for the selected
|
||||
// format get used, but all of them get validated.
|
||||
// Only available when the LoggingAlphaOptions feature gate is enabled.
|
||||
Options FormatOptions `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
// TimeOrMetaDuration is present only for backwards compatibility for the
|
||||
// flushFrequency field, and new fields should use metav1.Duration.
|
||||
type TimeOrMetaDuration struct {
|
||||
// Duration holds the duration
|
||||
Duration metav1.Duration
|
||||
// SerializeAsString controls whether the value is serialized as a string or an integer
|
||||
SerializeAsString bool `json:"-"`
|
||||
}
|
||||
|
||||
func (t TimeOrMetaDuration) MarshalJSON() ([]byte, error) {
|
||||
if t.SerializeAsString {
|
||||
return t.Duration.MarshalJSON()
|
||||
} else {
|
||||
// Marshal as integer for backwards compatibility
|
||||
return json.Marshal(t.Duration.Duration)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TimeOrMetaDuration) UnmarshalJSON(b []byte) error {
|
||||
if len(b) > 0 && b[0] == '"' {
|
||||
// string values unmarshal as metav1.Duration
|
||||
t.SerializeAsString = true
|
||||
return json.Unmarshal(b, &t.Duration)
|
||||
}
|
||||
t.SerializeAsString = false
|
||||
if err := json.Unmarshal(b, &t.Duration.Duration); err != nil {
|
||||
return fmt.Errorf("invalid duration %q: %w", string(b), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FormatOptions contains options for the different logging formats.
|
||||
type FormatOptions struct {
|
||||
// [Alpha] Text contains options for logging format "text".
|
||||
// Only available when the LoggingAlphaOptions feature gate is enabled.
|
||||
Text TextOptions `json:"text,omitempty"`
|
||||
// [Alpha] JSON contains options for logging format "json".
|
||||
// Only available when the LoggingAlphaOptions feature gate is enabled.
|
||||
JSON JSONOptions `json:"json,omitempty"`
|
||||
}
|
||||
|
||||
// TextOptions contains options for logging format "text".
|
||||
type TextOptions struct {
|
||||
OutputRoutingOptions `json:",inline"`
|
||||
}
|
||||
|
||||
// JSONOptions contains options for logging format "json".
|
||||
type JSONOptions struct {
|
||||
OutputRoutingOptions `json:",inline"`
|
||||
}
|
||||
|
||||
// OutputRoutingOptions contains options that are supported by both "text" and "json".
|
||||
type OutputRoutingOptions struct {
|
||||
// [Alpha] SplitStream redirects error messages to stderr while
|
||||
// info messages go to stdout, with buffering. The default is to write
|
||||
// both to stdout, without buffering. Only available when
|
||||
// the LoggingAlphaOptions feature gate is enabled.
|
||||
SplitStream bool `json:"splitStream,omitempty"`
|
||||
// [Alpha] InfoBufferSize sets the size of the info stream when
|
||||
// using split streams. The default is zero, which disables buffering.
|
||||
// Only available when the LoggingAlphaOptions feature gate is enabled.
|
||||
InfoBufferSize resource.QuantityValue `json:"infoBufferSize,omitempty"`
|
||||
}
|
||||
|
||||
// VModuleConfiguration is a collection of individual file names or patterns
|
||||
// and the corresponding verbosity threshold.
|
||||
type VModuleConfiguration []VModuleItem
|
||||
|
||||
// VModuleItem defines verbosity for one or more files which match a certain
|
||||
// glob pattern.
|
||||
type VModuleItem struct {
|
||||
// FilePattern is a base file name (i.e. minus the ".go" suffix and
|
||||
// directory) or a "glob" pattern for such a name. It must not contain
|
||||
// comma and equal signs because those are separators for the
|
||||
// corresponding klog command line argument.
|
||||
FilePattern string `json:"filePattern"`
|
||||
// Verbosity is the threshold for log messages emitted inside files
|
||||
// that match the pattern.
|
||||
Verbosity VerbosityLevel `json:"verbosity"`
|
||||
}
|
||||
|
||||
// VerbosityLevel represents a klog or logr verbosity threshold.
|
||||
type VerbosityLevel uint32
|
167
vendor/k8s.io/component-base/logs/api/v1/zz_generated.deepcopy.go
generated
vendored
167
vendor/k8s.io/component-base/logs/api/v1/zz_generated.deepcopy.go
generated
vendored
@ -1,167 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FormatOptions) DeepCopyInto(out *FormatOptions) {
|
||||
*out = *in
|
||||
in.Text.DeepCopyInto(&out.Text)
|
||||
in.JSON.DeepCopyInto(&out.JSON)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FormatOptions.
|
||||
func (in *FormatOptions) DeepCopy() *FormatOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FormatOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONOptions) DeepCopyInto(out *JSONOptions) {
|
||||
*out = *in
|
||||
in.OutputRoutingOptions.DeepCopyInto(&out.OutputRoutingOptions)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONOptions.
|
||||
func (in *JSONOptions) DeepCopy() *JSONOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *LoggingConfiguration) DeepCopyInto(out *LoggingConfiguration) {
|
||||
*out = *in
|
||||
out.FlushFrequency = in.FlushFrequency
|
||||
if in.VModule != nil {
|
||||
in, out := &in.VModule, &out.VModule
|
||||
*out = make(VModuleConfiguration, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
in.Options.DeepCopyInto(&out.Options)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoggingConfiguration.
|
||||
func (in *LoggingConfiguration) DeepCopy() *LoggingConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(LoggingConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OutputRoutingOptions) DeepCopyInto(out *OutputRoutingOptions) {
|
||||
*out = *in
|
||||
in.InfoBufferSize.DeepCopyInto(&out.InfoBufferSize)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OutputRoutingOptions.
|
||||
func (in *OutputRoutingOptions) DeepCopy() *OutputRoutingOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OutputRoutingOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TextOptions) DeepCopyInto(out *TextOptions) {
|
||||
*out = *in
|
||||
in.OutputRoutingOptions.DeepCopyInto(&out.OutputRoutingOptions)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TextOptions.
|
||||
func (in *TextOptions) DeepCopy() *TextOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TextOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TimeOrMetaDuration) DeepCopyInto(out *TimeOrMetaDuration) {
|
||||
*out = *in
|
||||
out.Duration = in.Duration
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TimeOrMetaDuration.
|
||||
func (in *TimeOrMetaDuration) DeepCopy() *TimeOrMetaDuration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TimeOrMetaDuration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in VModuleConfiguration) DeepCopyInto(out *VModuleConfiguration) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(VModuleConfiguration, len(*in))
|
||||
copy(*out, *in)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VModuleConfiguration.
|
||||
func (in VModuleConfiguration) DeepCopy() VModuleConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(VModuleConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return *out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *VModuleItem) DeepCopyInto(out *VModuleItem) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VModuleItem.
|
||||
func (in *VModuleItem) DeepCopy() *VModuleItem {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(VModuleItem)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
34
vendor/k8s.io/component-base/logs/internal/setverbositylevel/setverbositylevel.go
generated
vendored
34
vendor/k8s.io/component-base/logs/internal/setverbositylevel/setverbositylevel.go
generated
vendored
@ -1,34 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 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 setverbositylevel stores callbacks that will be invoked by logs.GlogLevel.
|
||||
//
|
||||
// This is a separate package to avoid a dependency from
|
||||
// k8s.io/component-base/logs (uses the callbacks) to
|
||||
// k8s.io/component-base/logs/api/v1 (adds them). Not all users of the logs
|
||||
// package also use the API.
|
||||
package setverbositylevel
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
// Mutex controls access to the callbacks.
|
||||
Mutex sync.Mutex
|
||||
|
||||
Callbacks []func(v uint32) error
|
||||
)
|
41
vendor/k8s.io/component-base/logs/klogflags/klogflags.go
generated
vendored
41
vendor/k8s.io/component-base/logs/klogflags/klogflags.go
generated
vendored
@ -1,41 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 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 klogflags
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// Init is a replacement for klog.InitFlags which only adds those flags
|
||||
// that are still supported for Kubernetes components (i.e. -v and -vmodule).
|
||||
// See
|
||||
// https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/2845-deprecate-klog-specific-flags-in-k8s-components.
|
||||
func Init(fs *flag.FlagSet) {
|
||||
var allFlags flag.FlagSet
|
||||
klog.InitFlags(&allFlags)
|
||||
if fs == nil {
|
||||
fs = flag.CommandLine
|
||||
}
|
||||
allFlags.VisitAll(func(f *flag.Flag) {
|
||||
switch f.Name {
|
||||
case "v", "vmodule":
|
||||
fs.Var(f.Value, f.Name, f.Usage)
|
||||
}
|
||||
})
|
||||
}
|
78
vendor/k8s.io/component-base/logs/logreduction/logreduction.go
generated
vendored
78
vendor/k8s.io/component-base/logs/logreduction/logreduction.go
generated
vendored
@ -1,78 +0,0 @@
|
||||
/*
|
||||
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)
|
||||
}
|
209
vendor/k8s.io/component-base/logs/logs.go
generated
vendored
209
vendor/k8s.io/component-base/logs/logs.go
generated
vendored
@ -1,209 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 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 logs contains support for logging options, flags and setup.
|
||||
// Commands must explicitly enable command line flags. They no longer
|
||||
// get added automatically when importing this package.
|
||||
package logs
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
logsapi "k8s.io/component-base/logs/api/v1"
|
||||
"k8s.io/component-base/logs/internal/setverbositylevel"
|
||||
"k8s.io/component-base/logs/klogflags"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
const vmoduleUsage = " (only works for the default text log format)"
|
||||
|
||||
var (
|
||||
packageFlags = flag.NewFlagSet("logging", flag.ContinueOnError)
|
||||
|
||||
// Periodic flushing gets configured either via the global flag
|
||||
// in this file or via LoggingConfiguration.
|
||||
logFlushFreq time.Duration
|
||||
)
|
||||
|
||||
func init() {
|
||||
klogflags.Init(packageFlags)
|
||||
packageFlags.DurationVar(&logFlushFreq, logsapi.LogFlushFreqFlagName, logsapi.LogFlushFreqDefault, "Maximum number of seconds between log flushes")
|
||||
}
|
||||
|
||||
type addFlagsOptions struct {
|
||||
skipLoggingConfigurationFlags bool
|
||||
}
|
||||
|
||||
type Option func(*addFlagsOptions)
|
||||
|
||||
// SkipLoggingConfigurationFlags must be used as option for AddFlags when
|
||||
// the program also uses a LoggingConfiguration struct for configuring
|
||||
// logging. Then only flags not covered by that get added.
|
||||
func SkipLoggingConfigurationFlags() Option {
|
||||
return func(o *addFlagsOptions) {
|
||||
o.skipLoggingConfigurationFlags = true
|
||||
}
|
||||
}
|
||||
|
||||
// Options is an alias for LoggingConfiguration to comply with component-base
|
||||
// conventions.
|
||||
type Options = logsapi.LoggingConfiguration
|
||||
|
||||
// NewOptions is an alias for NewLoggingConfiguration.
|
||||
var NewOptions = logsapi.NewLoggingConfiguration
|
||||
|
||||
// AddFlags registers this package's flags on arbitrary FlagSets. This includes
|
||||
// the klog flags, with the original underscore as separator between. If
|
||||
// commands want hyphens as separators, they can set
|
||||
// k8s.io/component-base/cli/flag/WordSepNormalizeFunc as normalization
|
||||
// function on the flag set before calling AddFlags.
|
||||
//
|
||||
// May be called more than once.
|
||||
func AddFlags(fs *pflag.FlagSet, opts ...Option) {
|
||||
o := addFlagsOptions{}
|
||||
for _, opt := range opts {
|
||||
opt(&o)
|
||||
}
|
||||
|
||||
// Add all supported flags.
|
||||
packageFlags.VisitAll(func(f *flag.Flag) {
|
||||
pf := pflag.PFlagFromGoFlag(f)
|
||||
switch f.Name {
|
||||
case "v", logsapi.LogFlushFreqFlagName:
|
||||
// unchanged, potentially skip it
|
||||
if o.skipLoggingConfigurationFlags {
|
||||
return
|
||||
}
|
||||
case "vmodule":
|
||||
if o.skipLoggingConfigurationFlags {
|
||||
return
|
||||
}
|
||||
pf.Usage += vmoduleUsage
|
||||
}
|
||||
if fs.Lookup(pf.Name) == nil {
|
||||
fs.AddFlag(pf)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// AddGoFlags is a variant of AddFlags for traditional Go flag.FlagSet.
|
||||
// Commands should use pflag whenever possible for the sake of consistency.
|
||||
// Cases where this function is needed include tests (they have to set up flags
|
||||
// in flag.CommandLine) and commands that for historic reasons use Go
|
||||
// flag.Parse and cannot change to pflag because it would break their command
|
||||
// line interface.
|
||||
func AddGoFlags(fs *flag.FlagSet, opts ...Option) {
|
||||
o := addFlagsOptions{}
|
||||
for _, opt := range opts {
|
||||
opt(&o)
|
||||
}
|
||||
|
||||
// Add flags with deprecation remark added to the usage text of
|
||||
// some klog flags.
|
||||
packageFlags.VisitAll(func(f *flag.Flag) {
|
||||
usage := f.Usage
|
||||
switch f.Name {
|
||||
case "v", logsapi.LogFlushFreqFlagName:
|
||||
// unchanged
|
||||
if o.skipLoggingConfigurationFlags {
|
||||
return
|
||||
}
|
||||
case "vmodule":
|
||||
if o.skipLoggingConfigurationFlags {
|
||||
return
|
||||
}
|
||||
usage += vmoduleUsage
|
||||
}
|
||||
fs.Var(f.Value, f.Name, usage)
|
||||
})
|
||||
}
|
||||
|
||||
// KlogWriter serves as a bridge between the standard log package and the glog package.
|
||||
type KlogWriter struct{}
|
||||
|
||||
// Write implements the io.Writer interface.
|
||||
func (writer KlogWriter) Write(data []byte) (n int, err error) {
|
||||
klog.InfoDepth(1, string(data))
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
// InitLogs initializes logs the way we want for Kubernetes.
|
||||
// It should be called after parsing flags. If called before that,
|
||||
// it will use the default log settings.
|
||||
//
|
||||
// InitLogs disables support for contextual logging in klog while
|
||||
// that Kubernetes feature is not considered stable yet. Commands
|
||||
// which want to support contextual logging can:
|
||||
// - call klog.EnableContextualLogging after calling InitLogs,
|
||||
// with a fixed `true` or depending on some command line flag or
|
||||
// a feature gate check
|
||||
// - set up a FeatureGate instance, the advanced logging configuration
|
||||
// with Options and call Options.ValidateAndApply with the FeatureGate;
|
||||
// k8s.io/component-base/logs/example/cmd demonstrates how to do that
|
||||
func InitLogs() {
|
||||
log.SetOutput(KlogWriter{})
|
||||
log.SetFlags(0)
|
||||
|
||||
// Start flushing now. If LoggingConfiguration.ApplyAndValidate is
|
||||
// used, it will restart the daemon with the log flush interval defined
|
||||
// there.
|
||||
klog.StartFlushDaemon(logFlushFreq)
|
||||
|
||||
// This is the default in Kubernetes. Options.ValidateAndApply
|
||||
// will override this with the result of a feature gate check.
|
||||
klog.EnableContextualLogging(false)
|
||||
}
|
||||
|
||||
// FlushLogs flushes logs immediately. This should be called at the end of
|
||||
// the main function via defer to ensure that all pending log messages
|
||||
// are printed before exiting the program.
|
||||
func FlushLogs() {
|
||||
klog.Flush()
|
||||
}
|
||||
|
||||
// NewLogger creates a new log.Logger which sends logs to klog.Info.
|
||||
func NewLogger(prefix string) *log.Logger {
|
||||
return log.New(KlogWriter{}, prefix, 0)
|
||||
}
|
||||
|
||||
// GlogSetter modifies the verbosity threshold for the entire program.
|
||||
// Some components have HTTP-based APIs for invoking this at runtime.
|
||||
func GlogSetter(val string) (string, error) {
|
||||
v, err := strconv.ParseUint(val, 10, 32)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var level klog.Level
|
||||
if err := level.Set(val); err != nil {
|
||||
return "", fmt.Errorf("failed set klog.logging.verbosity %s: %v", val, err)
|
||||
}
|
||||
|
||||
setverbositylevel.Mutex.Lock()
|
||||
defer setverbositylevel.Mutex.Unlock()
|
||||
for _, cb := range setverbositylevel.Callbacks {
|
||||
if err := cb(uint32(v)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf("successfully set klog.logging.verbosity to %s", val), nil
|
||||
}
|
32
vendor/k8s.io/component-base/logs/testinit/testinit.go
generated
vendored
32
vendor/k8s.io/component-base/logs/testinit/testinit.go
generated
vendored
@ -1,32 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 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 testinit adds logging flags to a Ginkgo or Go test program during
|
||||
// initialization, something that the logs package itself no longer does.
|
||||
//
|
||||
// Normal commands should not use this and instead manage logging flags with
|
||||
// logs.Options and/or cli.Run.
|
||||
package testinit
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"k8s.io/component-base/logs"
|
||||
)
|
||||
|
||||
func init() {
|
||||
logs.AddGoFlags(flag.CommandLine)
|
||||
}
|
45
vendor/k8s.io/component-base/metrics/features/kube_features.go
generated
vendored
45
vendor/k8s.io/component-base/metrics/features/kube_features.go
generated
vendored
@ -1,45 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 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: @logicalhan
|
||||
// kep: https://kep.k8s.io/3466
|
||||
ComponentSLIs featuregate.Feature = "ComponentSLIs"
|
||||
)
|
||||
|
||||
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.MutableVersionedFeatureGate) error {
|
||||
return mutableFeatureGate.AddVersioned(featureGates())
|
||||
}
|
75
vendor/k8s.io/component-base/metrics/prometheus/slis/metrics.go
generated
vendored
75
vendor/k8s.io/component-base/metrics/prometheus/slis/metrics.go
generated
vendored
@ -1,75 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 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 slis
|
||||
|
||||
import (
|
||||
"context"
|
||||
k8smetrics "k8s.io/component-base/metrics"
|
||||
)
|
||||
|
||||
type HealthcheckStatus string
|
||||
|
||||
const (
|
||||
Success HealthcheckStatus = "success"
|
||||
Error HealthcheckStatus = "error"
|
||||
)
|
||||
|
||||
var (
|
||||
// healthcheck is a Prometheus Gauge metrics used for recording the results of a k8s healthcheck.
|
||||
healthcheck = k8smetrics.NewGaugeVec(
|
||||
&k8smetrics.GaugeOpts{
|
||||
Namespace: "kubernetes",
|
||||
Name: "healthcheck",
|
||||
Help: "This metric records the result of a single healthcheck.",
|
||||
StabilityLevel: k8smetrics.STABLE,
|
||||
},
|
||||
[]string{"name", "type"},
|
||||
)
|
||||
|
||||
// healthchecksTotal is a Prometheus Counter metrics used for counting the results of a k8s healthcheck.
|
||||
healthchecksTotal = k8smetrics.NewCounterVec(
|
||||
&k8smetrics.CounterOpts{
|
||||
Namespace: "kubernetes",
|
||||
Name: "healthchecks_total",
|
||||
Help: "This metric records the results of all healthcheck.",
|
||||
StabilityLevel: k8smetrics.STABLE,
|
||||
},
|
||||
[]string{"name", "type", "status"},
|
||||
)
|
||||
)
|
||||
|
||||
func Register(registry k8smetrics.KubeRegistry) {
|
||||
registry.Register(healthcheck)
|
||||
registry.Register(healthchecksTotal)
|
||||
_ = k8smetrics.RegisterProcessStartTime(registry.Register)
|
||||
}
|
||||
|
||||
func ResetHealthMetrics() {
|
||||
healthcheck.Reset()
|
||||
healthchecksTotal.Reset()
|
||||
}
|
||||
|
||||
func ObserveHealthcheck(ctx context.Context, name string, healthcheckType string, status HealthcheckStatus) error {
|
||||
if status == Success {
|
||||
healthcheck.WithContext(ctx).WithLabelValues(name, healthcheckType).Set(1)
|
||||
} else {
|
||||
healthcheck.WithContext(ctx).WithLabelValues(name, healthcheckType).Set(0)
|
||||
}
|
||||
|
||||
healthchecksTotal.WithContext(ctx).WithLabelValues(name, healthcheckType, string(status)).Inc()
|
||||
return nil
|
||||
}
|
27
vendor/k8s.io/component-base/metrics/prometheus/slis/registry.go
generated
vendored
27
vendor/k8s.io/component-base/metrics/prometheus/slis/registry.go
generated
vendored
@ -1,27 +0,0 @@
|
||||
/*
|
||||
Copyright 2020 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 slis
|
||||
|
||||
import (
|
||||
"k8s.io/component-base/metrics"
|
||||
)
|
||||
|
||||
var (
|
||||
// Registry exposes the SLI registry so that additional SLIs can be
|
||||
// added on a per-component basis.
|
||||
Registry = metrics.NewKubeRegistry()
|
||||
)
|
53
vendor/k8s.io/component-base/metrics/prometheus/slis/routes.go
generated
vendored
53
vendor/k8s.io/component-base/metrics/prometheus/slis/routes.go
generated
vendored
@ -1,53 +0,0 @@
|
||||
/*
|
||||
Copyright 2020 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 slis
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"k8s.io/component-base/metrics"
|
||||
)
|
||||
|
||||
var (
|
||||
installOnce = sync.Once{}
|
||||
installWithResetOnce = sync.Once{}
|
||||
)
|
||||
|
||||
type mux interface {
|
||||
Handle(path string, handler http.Handler)
|
||||
}
|
||||
|
||||
type SLIMetrics struct{}
|
||||
|
||||
// Install adds the DefaultMetrics handler
|
||||
func (s SLIMetrics) Install(m mux) {
|
||||
installOnce.Do(func() {
|
||||
Register(Registry)
|
||||
})
|
||||
m.Handle("/metrics/slis", metrics.HandlerFor(Registry, metrics.HandlerOpts{}))
|
||||
}
|
||||
|
||||
type SLIMetricsWithReset struct{}
|
||||
|
||||
// Install adds the DefaultMetrics handler
|
||||
func (s SLIMetricsWithReset) Install(m mux) {
|
||||
installWithResetOnce.Do(func() {
|
||||
Register(Registry)
|
||||
})
|
||||
m.Handle("/metrics/slis", metrics.HandlerWithReset(Registry, metrics.HandlerOpts{}))
|
||||
}
|
137
vendor/k8s.io/component-base/metrics/prometheus/workqueue/metrics.go
generated
vendored
137
vendor/k8s.io/component-base/metrics/prometheus/workqueue/metrics.go
generated
vendored
@ -1,137 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 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 workqueue
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
k8smetrics "k8s.io/component-base/metrics"
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
)
|
||||
|
||||
// Package prometheus sets the workqueue DefaultMetricsFactory to produce
|
||||
// prometheus metrics. To use this package, you just have to import it.
|
||||
|
||||
// Metrics subsystem and keys used by the workqueue.
|
||||
const (
|
||||
WorkQueueSubsystem = "workqueue"
|
||||
DepthKey = "depth"
|
||||
AddsKey = "adds_total"
|
||||
QueueLatencyKey = "queue_duration_seconds"
|
||||
WorkDurationKey = "work_duration_seconds"
|
||||
UnfinishedWorkKey = "unfinished_work_seconds"
|
||||
LongestRunningProcessorKey = "longest_running_processor_seconds"
|
||||
RetriesKey = "retries_total"
|
||||
)
|
||||
|
||||
var (
|
||||
depth = k8smetrics.NewGaugeVec(&k8smetrics.GaugeOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: DepthKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "Current depth of workqueue",
|
||||
}, []string{"name"})
|
||||
|
||||
adds = k8smetrics.NewCounterVec(&k8smetrics.CounterOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: AddsKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "Total number of adds handled by workqueue",
|
||||
}, []string{"name"})
|
||||
|
||||
latency = k8smetrics.NewHistogramVec(&k8smetrics.HistogramOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: QueueLatencyKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "How long in seconds an item stays in workqueue before being requested.",
|
||||
Buckets: k8smetrics.ExponentialBuckets(10e-9, 10, 10),
|
||||
}, []string{"name"})
|
||||
|
||||
workDuration = k8smetrics.NewHistogramVec(&k8smetrics.HistogramOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: WorkDurationKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "How long in seconds processing an item from workqueue takes.",
|
||||
Buckets: k8smetrics.ExponentialBuckets(10e-9, 10, 10),
|
||||
}, []string{"name"})
|
||||
|
||||
unfinished = k8smetrics.NewGaugeVec(&k8smetrics.GaugeOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: UnfinishedWorkKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "How many seconds of work has done that " +
|
||||
"is in progress and hasn't been observed by work_duration. Large " +
|
||||
"values indicate stuck threads. One can deduce the number of stuck " +
|
||||
"threads by observing the rate at which this increases.",
|
||||
}, []string{"name"})
|
||||
|
||||
longestRunningProcessor = k8smetrics.NewGaugeVec(&k8smetrics.GaugeOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: LongestRunningProcessorKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "How many seconds has the longest running " +
|
||||
"processor for workqueue been running.",
|
||||
}, []string{"name"})
|
||||
|
||||
retries = k8smetrics.NewCounterVec(&k8smetrics.CounterOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: RetriesKey,
|
||||
StabilityLevel: k8smetrics.ALPHA,
|
||||
Help: "Total number of retries handled by workqueue",
|
||||
}, []string{"name"})
|
||||
|
||||
metrics = []k8smetrics.Registerable{
|
||||
depth, adds, latency, workDuration, unfinished, longestRunningProcessor, retries,
|
||||
}
|
||||
)
|
||||
|
||||
type prometheusMetricsProvider struct {
|
||||
}
|
||||
|
||||
func init() {
|
||||
for _, m := range metrics {
|
||||
legacyregistry.MustRegister(m)
|
||||
}
|
||||
workqueue.SetProvider(prometheusMetricsProvider{})
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewDepthMetric(name string) workqueue.GaugeMetric {
|
||||
return depth.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewAddsMetric(name string) workqueue.CounterMetric {
|
||||
return adds.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewLatencyMetric(name string) workqueue.HistogramMetric {
|
||||
return latency.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewWorkDurationMetric(name string) workqueue.HistogramMetric {
|
||||
return workDuration.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewUnfinishedWorkSecondsMetric(name string) workqueue.SettableGaugeMetric {
|
||||
return unfinished.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewLongestRunningProcessorSecondsMetric(name string) workqueue.SettableGaugeMetric {
|
||||
return longestRunningProcessor.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (prometheusMetricsProvider) NewRetriesMetric(name string) workqueue.CounterMetric {
|
||||
return retries.WithLabelValues(name)
|
||||
}
|
475
vendor/k8s.io/component-base/metrics/testutil/metrics.go
generated
vendored
475
vendor/k8s.io/component-base/metrics/testutil/metrics.go
generated
vendored
@ -1,475 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 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 testutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
"github.com/prometheus/common/expfmt"
|
||||
"github.com/prometheus/common/model"
|
||||
|
||||
"k8s.io/component-base/metrics"
|
||||
)
|
||||
|
||||
var (
|
||||
// MetricNameLabel is label under which model.Sample stores metric name
|
||||
MetricNameLabel model.LabelName = model.MetricNameLabel
|
||||
// QuantileLabel is label under which model.Sample stores latency quantile value
|
||||
QuantileLabel model.LabelName = model.QuantileLabel
|
||||
)
|
||||
|
||||
// Metrics is generic metrics for other specific metrics
|
||||
type Metrics map[string]model.Samples
|
||||
|
||||
// Equal returns true if all metrics are the same as the arguments.
|
||||
func (m *Metrics) Equal(o Metrics) bool {
|
||||
var leftKeySet []string
|
||||
var rightKeySet []string
|
||||
for k := range *m {
|
||||
leftKeySet = append(leftKeySet, k)
|
||||
}
|
||||
for k := range o {
|
||||
rightKeySet = append(rightKeySet, k)
|
||||
}
|
||||
if !reflect.DeepEqual(leftKeySet, rightKeySet) {
|
||||
return false
|
||||
}
|
||||
for _, k := range leftKeySet {
|
||||
if !(*m)[k].Equal(o[k]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// NewMetrics returns new metrics which are initialized.
|
||||
func NewMetrics() Metrics {
|
||||
result := make(Metrics)
|
||||
return result
|
||||
}
|
||||
|
||||
// ParseMetrics parses Metrics from data returned from prometheus endpoint
|
||||
func ParseMetrics(data string, output *Metrics) error {
|
||||
dec := expfmt.NewDecoder(strings.NewReader(data), expfmt.NewFormat(expfmt.TypeTextPlain))
|
||||
decoder := expfmt.SampleDecoder{
|
||||
Dec: dec,
|
||||
Opts: &expfmt.DecodeOptions{},
|
||||
}
|
||||
|
||||
for {
|
||||
var v model.Vector
|
||||
if err := decoder.Decode(&v); err != nil {
|
||||
if err == io.EOF {
|
||||
// Expected loop termination condition.
|
||||
return nil
|
||||
}
|
||||
continue
|
||||
}
|
||||
for _, metric := range v {
|
||||
name := string(metric.Metric[MetricNameLabel])
|
||||
(*output)[name] = append((*output)[name], metric)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TextToMetricFamilies reads 'in' as the simple and flat text-based exchange
|
||||
// format and creates MetricFamily proto messages. It returns the MetricFamily
|
||||
// proto messages in a map where the metric names are the keys, along with any
|
||||
// error encountered.
|
||||
func TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricFamily, error) {
|
||||
var textParser expfmt.TextParser
|
||||
return textParser.TextToMetricFamilies(in)
|
||||
}
|
||||
|
||||
// PrintSample returns formatted representation of metric Sample
|
||||
func PrintSample(sample *model.Sample) string {
|
||||
buf := make([]string, 0)
|
||||
// Id is a VERY special label. For 'normal' container it's useless, but it's necessary
|
||||
// for 'system' containers (e.g. /docker-daemon, /kubelet, etc.). We know if that's the
|
||||
// case by checking if there's a label "kubernetes_container_name" present. It's hacky
|
||||
// but it works...
|
||||
_, normalContainer := sample.Metric["kubernetes_container_name"]
|
||||
for k, v := range sample.Metric {
|
||||
if strings.HasPrefix(string(k), "__") {
|
||||
continue
|
||||
}
|
||||
|
||||
if string(k) == "id" && normalContainer {
|
||||
continue
|
||||
}
|
||||
buf = append(buf, fmt.Sprintf("%v=%v", string(k), v))
|
||||
}
|
||||
return fmt.Sprintf("[%v] = %v", strings.Join(buf, ","), sample.Value)
|
||||
}
|
||||
|
||||
// ComputeHistogramDelta computes the change in histogram metric for a selected label.
|
||||
// Results are stored in after samples
|
||||
func ComputeHistogramDelta(before, after model.Samples, label model.LabelName) {
|
||||
beforeSamplesMap := make(map[string]*model.Sample)
|
||||
for _, bSample := range before {
|
||||
beforeSamplesMap[makeKey(bSample.Metric[label], bSample.Metric["le"])] = bSample
|
||||
}
|
||||
for _, aSample := range after {
|
||||
if bSample, found := beforeSamplesMap[makeKey(aSample.Metric[label], aSample.Metric["le"])]; found {
|
||||
aSample.Value = aSample.Value - bSample.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeKey(a, b model.LabelValue) string {
|
||||
return string(a) + "___" + string(b)
|
||||
}
|
||||
|
||||
// GetMetricValuesForLabel returns value of metric for a given dimension
|
||||
func GetMetricValuesForLabel(ms Metrics, metricName, label string) map[string]int64 {
|
||||
samples, found := ms[metricName]
|
||||
result := make(map[string]int64, len(samples))
|
||||
if !found {
|
||||
return result
|
||||
}
|
||||
for _, sample := range samples {
|
||||
count := int64(sample.Value)
|
||||
dimensionName := string(sample.Metric[model.LabelName(label)])
|
||||
result[dimensionName] = count
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ValidateMetrics verifies if every sample of metric has all expected labels
|
||||
func ValidateMetrics(metrics Metrics, metricName string, expectedLabels ...string) error {
|
||||
samples, ok := metrics[metricName]
|
||||
if !ok {
|
||||
return fmt.Errorf("metric %q was not found in metrics", metricName)
|
||||
}
|
||||
for _, sample := range samples {
|
||||
for _, l := range expectedLabels {
|
||||
if _, ok := sample.Metric[model.LabelName(l)]; !ok {
|
||||
return fmt.Errorf("metric %q is missing label %q, sample: %q", metricName, l, sample.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Histogram wraps prometheus histogram DTO (data transfer object)
|
||||
type Histogram struct {
|
||||
*dto.Histogram
|
||||
}
|
||||
|
||||
// HistogramVec wraps a slice of Histogram.
|
||||
// Note that each Histogram must have the same number of buckets.
|
||||
type HistogramVec []*Histogram
|
||||
|
||||
// GetAggregatedSampleCount aggregates the sample count of each inner Histogram.
|
||||
func (vec HistogramVec) GetAggregatedSampleCount() uint64 {
|
||||
var count uint64
|
||||
for _, hist := range vec {
|
||||
count += hist.GetSampleCount()
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// GetAggregatedSampleSum aggregates the sample sum of each inner Histogram.
|
||||
func (vec HistogramVec) GetAggregatedSampleSum() float64 {
|
||||
var sum float64
|
||||
for _, hist := range vec {
|
||||
sum += hist.GetSampleSum()
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
// Quantile first aggregates inner buckets of each Histogram, and then
|
||||
// computes q-th quantile of a cumulative histogram.
|
||||
func (vec HistogramVec) Quantile(q float64) float64 {
|
||||
var buckets []bucket
|
||||
|
||||
for i, hist := range vec {
|
||||
for j, bckt := range hist.Bucket {
|
||||
if i == 0 {
|
||||
buckets = append(buckets, bucket{
|
||||
count: float64(bckt.GetCumulativeCount()),
|
||||
upperBound: bckt.GetUpperBound(),
|
||||
})
|
||||
} else {
|
||||
buckets[j].count += float64(bckt.GetCumulativeCount())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(buckets) == 0 || buckets[len(buckets)-1].upperBound != math.Inf(+1) {
|
||||
// The list of buckets in dto.Histogram doesn't include the final +Inf bucket, so we
|
||||
// add it here for the rest of the samples.
|
||||
buckets = append(buckets, bucket{
|
||||
count: float64(vec.GetAggregatedSampleCount()),
|
||||
upperBound: math.Inf(+1),
|
||||
})
|
||||
}
|
||||
|
||||
return bucketQuantile(q, buckets)
|
||||
}
|
||||
|
||||
// Average computes wrapped histograms' average value.
|
||||
func (vec HistogramVec) Average() float64 {
|
||||
return vec.GetAggregatedSampleSum() / float64(vec.GetAggregatedSampleCount())
|
||||
}
|
||||
|
||||
// Validate makes sure the wrapped histograms have all necessary fields set and with valid values.
|
||||
func (vec HistogramVec) Validate() error {
|
||||
bucketSize := 0
|
||||
for i, hist := range vec {
|
||||
if err := hist.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
if i == 0 {
|
||||
bucketSize = len(hist.GetBucket())
|
||||
} else if bucketSize != len(hist.GetBucket()) {
|
||||
return fmt.Errorf("found different bucket size: expect %v, but got %v at index %v", bucketSize, len(hist.GetBucket()), i)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetHistogramVecFromGatherer collects a metric, that matches the input labelValue map,
|
||||
// from a gatherer implementing k8s.io/component-base/metrics.Gatherer interface.
|
||||
// Used only for testing purposes where we need to gather metrics directly from a running binary (without metrics endpoint).
|
||||
func GetHistogramVecFromGatherer(gatherer metrics.Gatherer, metricName string, lvMap map[string]string) (HistogramVec, error) {
|
||||
var metricFamily *dto.MetricFamily
|
||||
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)
|
||||
}
|
||||
|
||||
vec := make(HistogramVec, 0)
|
||||
for _, metric := range metricFamily.GetMetric() {
|
||||
if LabelsMatch(metric, lvMap) {
|
||||
if hist := metric.GetHistogram(); hist != nil {
|
||||
vec = append(vec, &Histogram{hist})
|
||||
}
|
||||
}
|
||||
}
|
||||
return vec, nil
|
||||
}
|
||||
|
||||
func uint64Ptr(u uint64) *uint64 {
|
||||
return &u
|
||||
}
|
||||
|
||||
// Bucket of a histogram
|
||||
type bucket struct {
|
||||
upperBound float64
|
||||
count float64
|
||||
}
|
||||
|
||||
func bucketQuantile(q float64, buckets []bucket) float64 {
|
||||
if q < 0 {
|
||||
return math.Inf(-1)
|
||||
}
|
||||
if q > 1 {
|
||||
return math.Inf(+1)
|
||||
}
|
||||
|
||||
if len(buckets) < 2 {
|
||||
return math.NaN()
|
||||
}
|
||||
|
||||
rank := q * buckets[len(buckets)-1].count
|
||||
b := sort.Search(len(buckets)-1, func(i int) bool { return buckets[i].count >= rank })
|
||||
|
||||
if b == 0 {
|
||||
return buckets[0].upperBound * (rank / buckets[0].count)
|
||||
}
|
||||
|
||||
if b == len(buckets)-1 && math.IsInf(buckets[b].upperBound, 1) {
|
||||
return buckets[len(buckets)-2].upperBound
|
||||
}
|
||||
|
||||
// linear approximation of b-th bucket
|
||||
brank := rank - buckets[b-1].count
|
||||
bSize := buckets[b].upperBound - buckets[b-1].upperBound
|
||||
bCount := buckets[b].count - buckets[b-1].count
|
||||
|
||||
return buckets[b-1].upperBound + bSize*(brank/bCount)
|
||||
}
|
||||
|
||||
// Quantile computes q-th quantile of a cumulative histogram.
|
||||
// It's expected the histogram is valid (by calling Validate)
|
||||
func (hist *Histogram) Quantile(q float64) float64 {
|
||||
var buckets []bucket
|
||||
|
||||
for _, bckt := range hist.Bucket {
|
||||
buckets = append(buckets, bucket{
|
||||
count: float64(bckt.GetCumulativeCount()),
|
||||
upperBound: bckt.GetUpperBound(),
|
||||
})
|
||||
}
|
||||
|
||||
if len(buckets) == 0 || buckets[len(buckets)-1].upperBound != math.Inf(+1) {
|
||||
// The list of buckets in dto.Histogram doesn't include the final +Inf bucket, so we
|
||||
// add it here for the rest of the samples.
|
||||
buckets = append(buckets, bucket{
|
||||
count: float64(hist.GetSampleCount()),
|
||||
upperBound: math.Inf(+1),
|
||||
})
|
||||
}
|
||||
|
||||
return bucketQuantile(q, buckets)
|
||||
}
|
||||
|
||||
// Average computes histogram's average value
|
||||
func (hist *Histogram) Average() float64 {
|
||||
return hist.GetSampleSum() / float64(hist.GetSampleCount())
|
||||
}
|
||||
|
||||
// Validate makes sure the wrapped histogram has all necessary fields set and with valid values.
|
||||
func (hist *Histogram) Validate() error {
|
||||
if hist.SampleCount == nil || hist.GetSampleCount() == 0 {
|
||||
return fmt.Errorf("nil or empty histogram SampleCount")
|
||||
}
|
||||
|
||||
if hist.SampleSum == nil || hist.GetSampleSum() == 0 {
|
||||
return fmt.Errorf("nil or empty histogram SampleSum")
|
||||
}
|
||||
|
||||
for _, bckt := range hist.Bucket {
|
||||
if bckt == nil {
|
||||
return fmt.Errorf("empty histogram bucket")
|
||||
}
|
||||
if bckt.UpperBound == nil || bckt.GetUpperBound() < 0 {
|
||||
return fmt.Errorf("nil or negative histogram bucket UpperBound")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetGaugeMetricValue extracts metric value from GaugeMetric
|
||||
func GetGaugeMetricValue(m metrics.GaugeMetric) (float64, error) {
|
||||
metricProto := &dto.Metric{}
|
||||
if err := m.Write(metricProto); err != nil {
|
||||
return 0, fmt.Errorf("error writing m: %v", err)
|
||||
}
|
||||
return metricProto.Gauge.GetValue(), nil
|
||||
}
|
||||
|
||||
// GetCounterMetricValue extracts metric value from CounterMetric
|
||||
func GetCounterMetricValue(m metrics.CounterMetric) (float64, error) {
|
||||
metricProto := &dto.Metric{}
|
||||
if err := m.(metrics.Metric).Write(metricProto); err != nil {
|
||||
return 0, fmt.Errorf("error writing m: %v", err)
|
||||
}
|
||||
return metricProto.Counter.GetValue(), nil
|
||||
}
|
||||
|
||||
// GetHistogramMetricValue extracts sum of all samples from ObserverMetric
|
||||
func GetHistogramMetricValue(m metrics.ObserverMetric) (float64, error) {
|
||||
metricProto := &dto.Metric{}
|
||||
if err := m.(metrics.Metric).Write(metricProto); err != nil {
|
||||
return 0, fmt.Errorf("error writing m: %v", err)
|
||||
}
|
||||
return metricProto.Histogram.GetSampleSum(), nil
|
||||
}
|
||||
|
||||
// GetHistogramMetricCount extracts count of all samples from ObserverMetric
|
||||
func GetHistogramMetricCount(m metrics.ObserverMetric) (uint64, error) {
|
||||
metricProto := &dto.Metric{}
|
||||
if err := m.(metrics.Metric).Write(metricProto); err != nil {
|
||||
return 0, fmt.Errorf("error writing m: %v", err)
|
||||
}
|
||||
return metricProto.Histogram.GetSampleCount(), nil
|
||||
}
|
||||
|
||||
// LabelsMatch returns true if metric has all expected labels otherwise false
|
||||
func LabelsMatch(metric *dto.Metric, labelFilter map[string]string) bool {
|
||||
metricLabels := map[string]string{}
|
||||
|
||||
for _, labelPair := range metric.Label {
|
||||
metricLabels[labelPair.GetName()] = labelPair.GetValue()
|
||||
}
|
||||
|
||||
// length comparison then match key to values in the maps
|
||||
if len(labelFilter) > len(metricLabels) {
|
||||
return false
|
||||
}
|
||||
|
||||
for labelName, labelValue := range labelFilter {
|
||||
if value, ok := metricLabels[labelName]; !ok || value != labelValue {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
151
vendor/k8s.io/component-base/metrics/testutil/promlint.go
generated
vendored
151
vendor/k8s.io/component-base/metrics/testutil/promlint.go
generated
vendored
@ -1,151 +0,0 @@
|
||||
/*
|
||||
Copyright 2020 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 testutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/testutil/promlint"
|
||||
)
|
||||
|
||||
// exceptionMetrics is an exception list of metrics which violates promlint rules.
|
||||
//
|
||||
// The original entries come from the existing metrics when we introduce promlint.
|
||||
// We setup this list for allow and not fail on the current violations.
|
||||
// Generally speaking, you need to fix the problem for a new metric rather than add it into the list.
|
||||
var exceptionMetrics = []string{
|
||||
// k8s.io/apiserver/pkg/server/egressselector
|
||||
"apiserver_egress_dialer_dial_failure_count", // counter metrics should have "_total" suffix
|
||||
|
||||
// k8s.io/apiserver/pkg/server/healthz
|
||||
"apiserver_request_total", // label names should be written in 'snake_case' not 'camelCase'
|
||||
|
||||
// k8s.io/apiserver/pkg/endpoints/filters
|
||||
"authenticated_user_requests", // counter metrics should have "_total" suffix
|
||||
"authentication_attempts", // counter metrics should have "_total" suffix
|
||||
|
||||
// kube-apiserver
|
||||
"aggregator_openapi_v2_regeneration_count",
|
||||
"apiserver_admission_step_admission_duration_seconds_summary",
|
||||
"apiserver_current_inflight_requests",
|
||||
"apiserver_longrunning_gauge",
|
||||
"get_token_count",
|
||||
"get_token_fail_count",
|
||||
"ssh_tunnel_open_count",
|
||||
"ssh_tunnel_open_fail_count",
|
||||
|
||||
// kube-controller-manager
|
||||
"attachdetach_controller_forced_detaches",
|
||||
"authenticated_user_requests",
|
||||
"authentication_attempts",
|
||||
"get_token_count",
|
||||
"get_token_fail_count",
|
||||
"node_collector_evictions_number",
|
||||
}
|
||||
|
||||
// A Problem is an issue detected by a Linter.
|
||||
type Problem promlint.Problem
|
||||
|
||||
func (p *Problem) String() string {
|
||||
return fmt.Sprintf("%s:%s", p.Metric, p.Text)
|
||||
}
|
||||
|
||||
// A Linter is a Prometheus metrics linter. It identifies issues with metric
|
||||
// names, types, and metadata, and reports them to the caller.
|
||||
type Linter struct {
|
||||
promLinter *promlint.Linter
|
||||
}
|
||||
|
||||
// Lint performs a linting pass, returning a slice of Problems indicating any
|
||||
// issues found in the metrics stream. The slice is sorted by metric name
|
||||
// and issue description.
|
||||
func (l *Linter) Lint() ([]Problem, error) {
|
||||
promProblems, err := l.promLinter.Lint()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ignore problems those in exception list
|
||||
problems := make([]Problem, 0, len(promProblems))
|
||||
for i := range promProblems {
|
||||
if !l.shouldIgnore(promProblems[i].Metric) {
|
||||
problems = append(problems, Problem(promProblems[i]))
|
||||
}
|
||||
}
|
||||
|
||||
return problems, nil
|
||||
}
|
||||
|
||||
// shouldIgnore returns true if metric in the exception list, otherwise returns false.
|
||||
func (l *Linter) shouldIgnore(metricName string) bool {
|
||||
for i := range exceptionMetrics {
|
||||
if metricName == exceptionMetrics[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// NewPromLinter creates a new Linter that reads an input stream of Prometheus metrics.
|
||||
// Only the text exposition format is supported.
|
||||
func NewPromLinter(r io.Reader) *Linter {
|
||||
return &Linter{
|
||||
promLinter: promlint.New(r),
|
||||
}
|
||||
}
|
||||
|
||||
func mergeProblems(problems []Problem) string {
|
||||
var problemsMsg []string
|
||||
|
||||
for index := range problems {
|
||||
problemsMsg = append(problemsMsg, problems[index].String())
|
||||
}
|
||||
|
||||
return strings.Join(problemsMsg, ",")
|
||||
}
|
||||
|
||||
// shouldIgnore returns true if metric in the exception list, otherwise returns false.
|
||||
func shouldIgnore(metricName string) bool {
|
||||
for i := range exceptionMetrics {
|
||||
if metricName == exceptionMetrics[i] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// getLintError will ignore the metrics in exception list and converts lint problem to error.
|
||||
func getLintError(problems []promlint.Problem) error {
|
||||
var filteredProblems []Problem
|
||||
for _, problem := range problems {
|
||||
if shouldIgnore(problem.Metric) {
|
||||
continue
|
||||
}
|
||||
|
||||
filteredProblems = append(filteredProblems, Problem(problem))
|
||||
}
|
||||
|
||||
if len(filteredProblems) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("lint error: %s", mergeProblems(filteredProblems))
|
||||
}
|
159
vendor/k8s.io/component-base/metrics/testutil/testutil.go
generated
vendored
159
vendor/k8s.io/component-base/metrics/testutil/testutil.go
generated
vendored
@ -1,159 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 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 testutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/testutil"
|
||||
|
||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/component-base/metrics"
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
)
|
||||
|
||||
type TB interface {
|
||||
Logf(format string, args ...any)
|
||||
Errorf(format string, args ...any)
|
||||
Fatalf(format string, args ...any)
|
||||
}
|
||||
|
||||
// CollectAndCompare registers the provided Collector with a newly created
|
||||
// pedantic Registry. It then does the same as GatherAndCompare, gathering the
|
||||
// metrics from the pedantic Registry.
|
||||
func CollectAndCompare(c metrics.Collector, expected io.Reader, metricNames ...string) error {
|
||||
lintProblems, err := testutil.CollectAndLint(c, metricNames...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := getLintError(lintProblems); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return testutil.CollectAndCompare(c, expected, metricNames...)
|
||||
}
|
||||
|
||||
// GatherAndCompare gathers all metrics from the provided Gatherer and compares
|
||||
// it to an expected output read from the provided Reader in the Prometheus text
|
||||
// exposition format. If any metricNames are provided, only metrics with those
|
||||
// names are compared.
|
||||
func GatherAndCompare(g metrics.Gatherer, expected io.Reader, metricNames ...string) error {
|
||||
lintProblems, err := testutil.GatherAndLint(g, metricNames...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := getLintError(lintProblems); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return testutil.GatherAndCompare(g, expected, metricNames...)
|
||||
}
|
||||
|
||||
// CustomCollectAndCompare registers the provided StableCollector with a newly created
|
||||
// registry. It then does the same as GatherAndCompare, gathering the
|
||||
// metrics from the pedantic Registry.
|
||||
func CustomCollectAndCompare(c metrics.StableCollector, expected io.Reader, metricNames ...string) error {
|
||||
registry := metrics.NewKubeRegistry()
|
||||
registry.CustomMustRegister(c)
|
||||
|
||||
return GatherAndCompare(registry, expected, metricNames...)
|
||||
}
|
||||
|
||||
// ScrapeAndCompare calls a remote exporter's endpoint which is expected to return some metrics in
|
||||
// plain text format. Then it compares it with the results that the `expected` would return.
|
||||
// If the `metricNames` is not empty it would filter the comparison only to the given metric names.
|
||||
func ScrapeAndCompare(url string, expected io.Reader, metricNames ...string) error {
|
||||
return testutil.ScrapeAndCompare(url, expected, metricNames...)
|
||||
}
|
||||
|
||||
// NewFakeKubeRegistry creates a fake `KubeRegistry` that takes the input version as `build in version`.
|
||||
// It should only be used in testing scenario especially for the deprecated metrics.
|
||||
// The input version format should be `major.minor.patch`, e.g. '1.18.0'.
|
||||
func NewFakeKubeRegistry(ver string) metrics.KubeRegistry {
|
||||
backup := metrics.BuildVersion
|
||||
defer func() {
|
||||
metrics.BuildVersion = backup
|
||||
}()
|
||||
|
||||
metrics.BuildVersion = func() apimachineryversion.Info {
|
||||
return apimachineryversion.Info{
|
||||
GitVersion: fmt.Sprintf("v%s-alpha+1.12345", ver),
|
||||
}
|
||||
}
|
||||
|
||||
return metrics.NewKubeRegistry()
|
||||
}
|
||||
|
||||
func AssertVectorCount(t TB, name string, labelFilter map[string]string, wantCount int) {
|
||||
metrics, err := legacyregistry.DefaultGatherer.Gather()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to gather metrics: %s", err)
|
||||
}
|
||||
|
||||
counterSum := 0
|
||||
for _, mf := range metrics {
|
||||
if mf.GetName() != name {
|
||||
continue // Ignore other metrics.
|
||||
}
|
||||
for _, metric := range mf.GetMetric() {
|
||||
if !LabelsMatch(metric, labelFilter) {
|
||||
continue
|
||||
}
|
||||
counterSum += int(metric.GetCounter().GetValue())
|
||||
}
|
||||
}
|
||||
if wantCount != counterSum {
|
||||
t.Errorf("Wanted count %d, got %d for metric %s with labels %#+v", wantCount, counterSum, name, labelFilter)
|
||||
for _, mf := range metrics {
|
||||
if mf.GetName() == name {
|
||||
for _, metric := range mf.GetMetric() {
|
||||
t.Logf("\tnear match: %s", metric.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func AssertHistogramTotalCount(t TB, name string, labelFilter map[string]string, wantCount int) {
|
||||
metrics, err := legacyregistry.DefaultGatherer.Gather()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to gather metrics: %s", err)
|
||||
}
|
||||
counterSum := 0
|
||||
for _, mf := range metrics {
|
||||
if mf.GetName() != name {
|
||||
continue // Ignore other metrics.
|
||||
}
|
||||
for _, metric := range mf.GetMetric() {
|
||||
if !LabelsMatch(metric, labelFilter) {
|
||||
continue
|
||||
}
|
||||
counterSum += int(metric.GetHistogram().GetSampleCount())
|
||||
}
|
||||
}
|
||||
if wantCount != counterSum {
|
||||
t.Errorf("Wanted count %d, got %d for metric %s with labels %#+v", wantCount, counterSum, name, labelFilter)
|
||||
for _, mf := range metrics {
|
||||
if mf.GetName() == name {
|
||||
for _, metric := range mf.GetMetric() {
|
||||
t.Logf("\tnear match: %s\n", metric.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
8
vendor/k8s.io/component-base/tracing/OWNERS
generated
vendored
8
vendor/k8s.io/component-base/tracing/OWNERS
generated
vendored
@ -1,8 +0,0 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- sig-instrumentation-approvers
|
||||
reviewers:
|
||||
- sig-instrumentation-reviewers
|
||||
labels:
|
||||
- sig/instrumentation
|
88
vendor/k8s.io/component-base/tracing/api/v1/config.go
generated
vendored
88
vendor/k8s.io/component-base/tracing/api/v1/config.go
generated
vendored
@ -1,88 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 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 v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/component-base/featuregate"
|
||||
)
|
||||
|
||||
var (
|
||||
maxSamplingRatePerMillion = int32(1000000)
|
||||
)
|
||||
|
||||
// ValidateTracingConfiguration validates the tracing configuration
|
||||
func ValidateTracingConfiguration(traceConfig *TracingConfiguration, featureGate featuregate.FeatureGate, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if traceConfig == nil {
|
||||
return allErrs
|
||||
}
|
||||
if traceConfig.SamplingRatePerMillion != nil {
|
||||
allErrs = append(allErrs, validateSamplingRate(*traceConfig.SamplingRatePerMillion, fldPath.Child("samplingRatePerMillion"))...)
|
||||
}
|
||||
if traceConfig.Endpoint != nil {
|
||||
allErrs = append(allErrs, validateEndpoint(*traceConfig.Endpoint, fldPath.Child("endpoint"))...)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateSamplingRate(rate int32, fldPath *field.Path) field.ErrorList {
|
||||
errs := field.ErrorList{}
|
||||
if rate < 0 {
|
||||
errs = append(errs, field.Invalid(
|
||||
fldPath, rate,
|
||||
"sampling rate must be positive",
|
||||
))
|
||||
}
|
||||
if rate > maxSamplingRatePerMillion {
|
||||
errs = append(errs, field.Invalid(
|
||||
fldPath, rate,
|
||||
"sampling rate per million must be less than or equal to one million",
|
||||
))
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
func validateEndpoint(endpoint string, fldPath *field.Path) field.ErrorList {
|
||||
errs := field.ErrorList{}
|
||||
if !strings.Contains(endpoint, "//") {
|
||||
endpoint = "dns://" + endpoint
|
||||
}
|
||||
url, err := url.Parse(endpoint)
|
||||
if err != nil {
|
||||
errs = append(errs, field.Invalid(
|
||||
fldPath, endpoint,
|
||||
err.Error(),
|
||||
))
|
||||
return errs
|
||||
}
|
||||
switch url.Scheme {
|
||||
case "dns":
|
||||
case "unix":
|
||||
case "unix-abstract":
|
||||
default:
|
||||
errs = append(errs, field.Invalid(
|
||||
fldPath, endpoint,
|
||||
fmt.Sprintf("unsupported scheme: %v. Options are none, dns, unix, or unix-abstract. See https://github.com/grpc/grpc/blob/master/doc/naming.md", url.Scheme),
|
||||
))
|
||||
}
|
||||
return errs
|
||||
}
|
29
vendor/k8s.io/component-base/tracing/api/v1/doc.go
generated
vendored
29
vendor/k8s.io/component-base/tracing/api/v1/doc.go
generated
vendored
@ -1,29 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 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.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
|
||||
// Package v1 contains the configuration API for tracing.
|
||||
//
|
||||
// The intention is to only have a single version of this API, potentially with
|
||||
// new fields added over time in a backwards-compatible manner. Fields for
|
||||
// alpha or beta features are allowed as long as they are defined so that not
|
||||
// changing the defaults leaves those features disabled.
|
||||
//
|
||||
// The "v1" package name is just a reminder that API compatibility rules apply,
|
||||
// not an indication of the stability of all features covered by it.
|
||||
|
||||
package v1 // import "k8s.io/component-base/tracing/api/v1"
|
32
vendor/k8s.io/component-base/tracing/api/v1/types.go
generated
vendored
32
vendor/k8s.io/component-base/tracing/api/v1/types.go
generated
vendored
@ -1,32 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 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 v1
|
||||
|
||||
// TracingConfiguration provides versioned configuration for OpenTelemetry tracing clients.
|
||||
type TracingConfiguration struct {
|
||||
// Endpoint of the collector this component will report traces to.
|
||||
// The connection is insecure, and does not currently support TLS.
|
||||
// Recommended is unset, and endpoint is the otlp grpc default, localhost:4317.
|
||||
// +optional
|
||||
Endpoint *string `json:"endpoint,omitempty"`
|
||||
|
||||
// SamplingRatePerMillion is the number of samples to collect per million spans.
|
||||
// Recommended is unset. If unset, sampler respects its parent span's sampling
|
||||
// rate, but otherwise never samples.
|
||||
// +optional
|
||||
SamplingRatePerMillion *int32 `json:"samplingRatePerMillion,omitempty"`
|
||||
}
|
48
vendor/k8s.io/component-base/tracing/api/v1/zz_generated.deepcopy.go
generated
vendored
48
vendor/k8s.io/component-base/tracing/api/v1/zz_generated.deepcopy.go
generated
vendored
@ -1,48 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TracingConfiguration) DeepCopyInto(out *TracingConfiguration) {
|
||||
*out = *in
|
||||
if in.Endpoint != nil {
|
||||
in, out := &in.Endpoint, &out.Endpoint
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.SamplingRatePerMillion != nil {
|
||||
in, out := &in.SamplingRatePerMillion, &out.SamplingRatePerMillion
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TracingConfiguration.
|
||||
func (in *TracingConfiguration) DeepCopy() *TracingConfiguration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TracingConfiguration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
98
vendor/k8s.io/component-base/tracing/tracing.go
generated
vendored
98
vendor/k8s.io/component-base/tracing/tracing.go
generated
vendored
@ -1,98 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 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 tracing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
utiltrace "k8s.io/utils/trace"
|
||||
)
|
||||
|
||||
const instrumentationScope = "k8s.io/component-base/tracing"
|
||||
|
||||
// Start creates spans using both OpenTelemetry, and the k8s.io/utils/trace package.
|
||||
// It only creates an OpenTelemetry span if the incoming context already includes a span.
|
||||
func Start(ctx context.Context, name string, attributes ...attribute.KeyValue) (context.Context, *Span) {
|
||||
// If the incoming context already includes an OpenTelemetry span, create a child span with the provided name and attributes.
|
||||
// If the caller is not using OpenTelemetry, or has tracing disabled (e.g. with a component-specific feature flag), this is a noop.
|
||||
ctx, otelSpan := trace.SpanFromContext(ctx).TracerProvider().Tracer(instrumentationScope).Start(ctx, name, trace.WithAttributes(attributes...))
|
||||
// If there is already a utiltrace span in the context, use that as our parent span.
|
||||
utilSpan := utiltrace.FromContext(ctx).Nest(name, attributesToFields(attributes)...)
|
||||
// Set the trace as active in the context so that subsequent Start calls create nested spans.
|
||||
return utiltrace.ContextWithTrace(ctx, utilSpan), &Span{
|
||||
otelSpan: otelSpan,
|
||||
utilSpan: utilSpan,
|
||||
}
|
||||
}
|
||||
|
||||
// Span is a component part of a trace. It represents a single named
|
||||
// and timed operation of a workflow being observed.
|
||||
// This Span is a combination of an OpenTelemetry and k8s.io/utils/trace span
|
||||
// to facilitate the migration to OpenTelemetry.
|
||||
type Span struct {
|
||||
otelSpan trace.Span
|
||||
utilSpan *utiltrace.Trace
|
||||
}
|
||||
|
||||
// AddEvent adds a point-in-time event with a name and attributes.
|
||||
func (s *Span) AddEvent(name string, attributes ...attribute.KeyValue) {
|
||||
s.otelSpan.AddEvent(name, trace.WithAttributes(attributes...))
|
||||
if s.utilSpan != nil {
|
||||
s.utilSpan.Step(name, attributesToFields(attributes)...)
|
||||
}
|
||||
}
|
||||
|
||||
// End ends the span, and logs if the span duration is greater than the logThreshold.
|
||||
func (s *Span) End(logThreshold time.Duration) {
|
||||
s.otelSpan.End()
|
||||
if s.utilSpan != nil {
|
||||
s.utilSpan.LogIfLong(logThreshold)
|
||||
}
|
||||
}
|
||||
|
||||
// RecordError will record err as an exception span event for this span.
|
||||
// If this span is not being recorded or err is nil then this method does nothing.
|
||||
func (s *Span) RecordError(err error, attributes ...attribute.KeyValue) {
|
||||
s.otelSpan.RecordError(err, trace.WithAttributes(attributes...))
|
||||
}
|
||||
|
||||
func attributesToFields(attributes []attribute.KeyValue) []utiltrace.Field {
|
||||
fields := make([]utiltrace.Field, len(attributes))
|
||||
for i := range attributes {
|
||||
attr := attributes[i]
|
||||
fields[i] = utiltrace.Field{Key: string(attr.Key), Value: attr.Value.AsInterface()}
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
// SpanFromContext returns the *Span from the current context. It is composed of the active
|
||||
// OpenTelemetry and k8s.io/utils/trace spans.
|
||||
func SpanFromContext(ctx context.Context) *Span {
|
||||
return &Span{
|
||||
otelSpan: trace.SpanFromContext(ctx),
|
||||
utilSpan: utiltrace.FromContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
// ContextWithSpan returns a context with the Span included in the context.
|
||||
func ContextWithSpan(ctx context.Context, s *Span) context.Context {
|
||||
return trace.ContextWithSpan(utiltrace.ContextWithTrace(ctx, s.utilSpan), s.otelSpan)
|
||||
}
|
134
vendor/k8s.io/component-base/tracing/utils.go
generated
vendored
134
vendor/k8s.io/component-base/tracing/utils.go
generated
vendored
@ -1,134 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 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 tracing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
oteltrace "go.opentelemetry.io/otel/trace"
|
||||
noopoteltrace "go.opentelemetry.io/otel/trace/noop"
|
||||
|
||||
"k8s.io/client-go/transport"
|
||||
"k8s.io/component-base/tracing/api/v1"
|
||||
)
|
||||
|
||||
// TracerProvider is an OpenTelemetry TracerProvider which can be shut down
|
||||
type TracerProvider interface {
|
||||
oteltrace.TracerProvider
|
||||
Shutdown(context.Context) error
|
||||
}
|
||||
|
||||
type noopTracerProvider struct {
|
||||
oteltrace.TracerProvider
|
||||
}
|
||||
|
||||
func (n *noopTracerProvider) Shutdown(context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewNoopTracerProvider() TracerProvider {
|
||||
return &noopTracerProvider{TracerProvider: noopoteltrace.NewTracerProvider()}
|
||||
}
|
||||
|
||||
// NewProvider creates a TracerProvider in a component, and enforces recommended tracing behavior
|
||||
func NewProvider(ctx context.Context,
|
||||
tracingConfig *v1.TracingConfiguration,
|
||||
addedOpts []otlptracegrpc.Option,
|
||||
resourceOpts []resource.Option,
|
||||
) (TracerProvider, error) {
|
||||
if tracingConfig == nil {
|
||||
return NewNoopTracerProvider(), nil
|
||||
}
|
||||
opts := append([]otlptracegrpc.Option{}, addedOpts...)
|
||||
if tracingConfig.Endpoint != nil {
|
||||
opts = append(opts, otlptracegrpc.WithEndpoint(*tracingConfig.Endpoint))
|
||||
}
|
||||
opts = append(opts, otlptracegrpc.WithInsecure())
|
||||
exporter, err := otlptracegrpc.New(ctx, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res, err := resource.New(ctx, resourceOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// sampler respects parent span's sampling rate or
|
||||
// otherwise never samples.
|
||||
sampler := sdktrace.NeverSample()
|
||||
// Or, emit spans for a fraction of transactions
|
||||
if tracingConfig.SamplingRatePerMillion != nil && *tracingConfig.SamplingRatePerMillion > 0 {
|
||||
sampler = sdktrace.TraceIDRatioBased(float64(*tracingConfig.SamplingRatePerMillion) / float64(1000000))
|
||||
}
|
||||
// batch span processor to aggregate spans before export.
|
||||
bsp := sdktrace.NewBatchSpanProcessor(exporter)
|
||||
tp := sdktrace.NewTracerProvider(
|
||||
sdktrace.WithSampler(sdktrace.ParentBased(sampler)),
|
||||
sdktrace.WithSpanProcessor(bsp),
|
||||
sdktrace.WithResource(res),
|
||||
)
|
||||
return tp, nil
|
||||
}
|
||||
|
||||
// WithTracing adds tracing to requests if the incoming request is sampled
|
||||
func WithTracing(handler http.Handler, tp oteltrace.TracerProvider, spanName string) http.Handler {
|
||||
opts := []otelhttp.Option{
|
||||
otelhttp.WithPropagators(Propagators()),
|
||||
otelhttp.WithTracerProvider(tp),
|
||||
}
|
||||
wrappedHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Add the http.target attribute to the otelhttp span
|
||||
// Workaround for https://github.com/open-telemetry/opentelemetry-go-contrib/issues/3743
|
||||
if r.URL != nil {
|
||||
oteltrace.SpanFromContext(r.Context()).SetAttributes(semconv.HTTPTarget(r.URL.RequestURI()))
|
||||
}
|
||||
handler.ServeHTTP(w, r)
|
||||
})
|
||||
// With Noop TracerProvider, the otelhttp still handles context propagation.
|
||||
// See https://github.com/open-telemetry/opentelemetry-go/tree/main/example/passthrough
|
||||
return otelhttp.NewHandler(wrappedHandler, spanName, opts...)
|
||||
}
|
||||
|
||||
// WrapperFor can be used to add tracing to a *rest.Config.
|
||||
// Example usage:
|
||||
// tp := NewProvider(...)
|
||||
// config, _ := rest.InClusterConfig()
|
||||
// config.Wrap(WrapperFor(tp))
|
||||
// kubeclient, _ := clientset.NewForConfig(config)
|
||||
func WrapperFor(tp oteltrace.TracerProvider) transport.WrapperFunc {
|
||||
return func(rt http.RoundTripper) http.RoundTripper {
|
||||
opts := []otelhttp.Option{
|
||||
otelhttp.WithPropagators(Propagators()),
|
||||
otelhttp.WithTracerProvider(tp),
|
||||
}
|
||||
// With Noop TracerProvider, the otelhttp still handles context propagation.
|
||||
// See https://github.com/open-telemetry/opentelemetry-go/tree/main/example/passthrough
|
||||
return otelhttp.NewTransport(rt, opts...)
|
||||
}
|
||||
}
|
||||
|
||||
// Propagators returns the recommended set of propagators.
|
||||
func Propagators() propagation.TextMapPropagator {
|
||||
return propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})
|
||||
}
|
52
vendor/k8s.io/component-base/zpages/flagz/flagreader.go
generated
vendored
52
vendor/k8s.io/component-base/zpages/flagz/flagreader.go
generated
vendored
@ -1,52 +0,0 @@
|
||||
/*
|
||||
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
126
vendor/k8s.io/component-base/zpages/flagz/flagz.go
generated
vendored
@ -1,126 +0,0 @@
|
||||
/*
|
||||
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