mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 18:53:35 +00:00
rebase: bump the k8s-dependencies group in /e2e with 3 updates
Bumps the k8s-dependencies group in /e2e with 3 updates: [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery), [k8s.io/cloud-provider](https://github.com/kubernetes/cloud-provider) and [k8s.io/pod-security-admission](https://github.com/kubernetes/pod-security-admission). Updates `k8s.io/apimachinery` from 0.32.3 to 0.33.0 - [Commits](https://github.com/kubernetes/apimachinery/compare/v0.32.3...v0.33.0) Updates `k8s.io/cloud-provider` from 0.32.3 to 0.33.0 - [Commits](https://github.com/kubernetes/cloud-provider/compare/v0.32.3...v0.33.0) Updates `k8s.io/pod-security-admission` from 0.32.3 to 0.33.0 - [Commits](https://github.com/kubernetes/pod-security-admission/compare/v0.32.3...v0.33.0) --- updated-dependencies: - dependency-name: k8s.io/apimachinery dependency-version: 0.33.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-dependencies - dependency-name: k8s.io/cloud-provider dependency-version: 0.33.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-dependencies - dependency-name: k8s.io/pod-security-admission dependency-version: 0.33.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: k8s-dependencies ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
mergify[bot]
parent
d52dc2c4ba
commit
dd77e72800
2
e2e/vendor/k8s.io/apimachinery/pkg/api/errors/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/api/errors/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package errors provides detailed error types for api field validation.
|
||||
package errors // import "k8s.io/apimachinery/pkg/api/errors"
|
||||
package errors
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/api/meta/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/api/meta/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package meta provides functions for retrieving API metadata from objects
|
||||
// belonging to the Kubernetes API
|
||||
package meta // import "k8s.io/apimachinery/pkg/api/meta"
|
||||
package meta
|
||||
|
3
e2e/vendor/k8s.io/apimachinery/pkg/api/meta/help.go
generated
vendored
3
e2e/vendor/k8s.io/apimachinery/pkg/api/meta/help.go
generated
vendored
@ -221,6 +221,9 @@ func extractList(obj runtime.Object, allocNew bool) ([]runtime.Object, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if items.IsNil() {
|
||||
return nil, nil
|
||||
}
|
||||
list := make([]runtime.Object, items.Len())
|
||||
if len(list) == 0 {
|
||||
return list, nil
|
||||
|
56
e2e/vendor/k8s.io/apimachinery/pkg/api/operation/operation.go
generated
vendored
Normal file
56
e2e/vendor/k8s.io/apimachinery/pkg/api/operation/operation.go
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
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 operation
|
||||
|
||||
import "k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
// Operation provides contextual information about a validation request and the API
|
||||
// operation being validated.
|
||||
// This type is intended for use with generate validation code and may be enhanced
|
||||
// in the future to include other information needed to validate requests.
|
||||
type Operation struct {
|
||||
// Type is the category of operation being validated. This does not
|
||||
// differentiate between HTTP verbs like PUT and PATCH, but rather merges
|
||||
// those into a single "Update" category.
|
||||
Type Type
|
||||
|
||||
// Options declare the options enabled for validation.
|
||||
//
|
||||
// Options should be set according to a resource validation strategy before validation
|
||||
// is performed, and must be treated as read-only during validation.
|
||||
//
|
||||
// Options are identified by string names. Option string names may match the name of a feature
|
||||
// gate, in which case the presence of the name in the set indicates that the feature is
|
||||
// considered enabled for the resource being validated. Note that a resource may have a
|
||||
// feature enabled even when the feature gate is disabled. This can happen when feature is
|
||||
// already in-use by a resource, often because the feature gate was enabled when the
|
||||
// resource first began using the feature.
|
||||
//
|
||||
// Unset options are disabled/false.
|
||||
Options sets.Set[string]
|
||||
}
|
||||
|
||||
// Code is the request operation to be validated.
|
||||
type Type uint32
|
||||
|
||||
const (
|
||||
// Create indicates the request being validated is for a resource create operation.
|
||||
Create Type = iota
|
||||
|
||||
// Update indicates the request being validated is for a resource update operation.
|
||||
Update
|
||||
)
|
2
e2e/vendor/k8s.io/apimachinery/pkg/api/validation/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/api/validation/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package validation contains generic api type validation functions.
|
||||
package validation // import "k8s.io/apimachinery/pkg/api/validation"
|
||||
package validation
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/api/validation/generic.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/api/validation/generic.go
generated
vendored
@ -82,7 +82,7 @@ func maskTrailingDash(name string) string {
|
||||
func ValidateNonnegativeField(value int64, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if value < 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, value, IsNegativeErrorMsg))
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, value, IsNegativeErrorMsg).WithOrigin("minimum"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
43
e2e/vendor/k8s.io/apimachinery/pkg/apis/asn1/oid.go
generated
vendored
Normal file
43
e2e/vendor/k8s.io/apimachinery/pkg/apis/asn1/oid.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
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 asn1
|
||||
|
||||
import "encoding/asn1"
|
||||
|
||||
// These constants store suffixes for use with the CNCF Private Enterprise Number allocated to Kubernetes:
|
||||
// https://www.iana.org/assignments/enterprise-numbers.txt
|
||||
//
|
||||
// Root: 1.3.6.1.4.1.57683
|
||||
//
|
||||
// Cloud Native Computing Foundation
|
||||
const (
|
||||
// single-value, string value
|
||||
x509UIDSuffix = 2
|
||||
)
|
||||
|
||||
func makeOID(suffix int) asn1.ObjectIdentifier {
|
||||
return asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57683, suffix}
|
||||
}
|
||||
|
||||
// X509UID returns an OID (1.3.6.1.4.1.57683.2) for an element of an x509 distinguished name representing a user UID.
|
||||
// The UID is a unique value for a particular user that will change if the user is removed from the system
|
||||
// and another user is added with the same username.
|
||||
//
|
||||
// This element must not appear more than once in a distinguished name, and the value must be a string
|
||||
func X509UID() asn1.ObjectIdentifier {
|
||||
return makeOID(x509UIDSuffix)
|
||||
}
|
2
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/doc.go
generated
vendored
@ -17,4 +17,4 @@ limitations under the License.
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/apimachinery/pkg/apis/meta/v1
|
||||
|
||||
package internalversion // import "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
package internalversion
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme/doc.go
generated
vendored
@ -14,4 +14,4 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package scheme // import "k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme"
|
||||
package scheme
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/types.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/types.go
generated
vendored
@ -41,8 +41,6 @@ type ListOptions struct {
|
||||
// assume bookmarks are returned at any specific interval, nor may they
|
||||
// assume the server will send any BOOKMARK event during a session.
|
||||
// If this is not a watch, this field is ignored.
|
||||
// If the feature gate WatchBookmarks is not enabled in apiserver,
|
||||
// this field is ignored.
|
||||
AllowWatchBookmarks bool
|
||||
// resourceVersion sets a constraint on what resource versions a request may be served from.
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/doc.go
generated
vendored
@ -21,4 +21,4 @@ limitations under the License.
|
||||
|
||||
// +groupName=meta.k8s.io
|
||||
|
||||
package v1 // import "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
package v1
|
||||
|
13
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time_fuzz.go
generated
vendored
13
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/micro_time_fuzz.go
generated
vendored
@ -20,21 +20,22 @@ limitations under the License.
|
||||
package v1
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
"sigs.k8s.io/randfill"
|
||||
)
|
||||
|
||||
// Fuzz satisfies fuzz.Interface.
|
||||
func (t *MicroTime) Fuzz(c fuzz.Continue) {
|
||||
// Fuzz satisfies randfill.SimpleSelfFiller.
|
||||
func (t *MicroTime) RandFill(r *rand.Rand) {
|
||||
if t == nil {
|
||||
return
|
||||
}
|
||||
// Allow for about 1000 years of randomness. Accurate to a tenth of
|
||||
// micro second. Leave off nanoseconds because JSON doesn't
|
||||
// represent them so they can't round-trip properly.
|
||||
t.Time = time.Unix(c.Rand.Int63n(1000*365*24*60*60), 1000*c.Rand.Int63n(1000000))
|
||||
t.Time = time.Unix(r.Int63n(1000*365*24*60*60), 1000*r.Int63n(1000000))
|
||||
}
|
||||
|
||||
// ensure MicroTime implements fuzz.Interface
|
||||
var _ fuzz.Interface = &MicroTime{}
|
||||
// ensure MicroTime implements randfill.Interface
|
||||
var _ randfill.SimpleSelfFiller = &MicroTime{}
|
||||
|
13
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/time_fuzz.go
generated
vendored
13
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/time_fuzz.go
generated
vendored
@ -20,21 +20,22 @@ limitations under the License.
|
||||
package v1
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
"sigs.k8s.io/randfill"
|
||||
)
|
||||
|
||||
// Fuzz satisfies fuzz.Interface.
|
||||
func (t *Time) Fuzz(c fuzz.Continue) {
|
||||
// Fuzz satisfies randfill.SimpleSelfFiller.
|
||||
func (t *Time) RandFill(r *rand.Rand) {
|
||||
if t == nil {
|
||||
return
|
||||
}
|
||||
// Allow for about 1000 years of randomness. Leave off nanoseconds
|
||||
// because JSON doesn't represent them so they can't round-trip
|
||||
// properly.
|
||||
t.Time = time.Unix(c.Rand.Int63n(1000*365*24*60*60), 0)
|
||||
t.Time = time.Unix(r.Int63n(1000*365*24*60*60), 0)
|
||||
}
|
||||
|
||||
// ensure Time implements fuzz.Interface
|
||||
var _ fuzz.Interface = &Time{}
|
||||
// ensure Time implements randfill.SimpleSelfFiller
|
||||
var _ randfill.SimpleSelfFiller = &Time{}
|
||||
|
31
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go
generated
vendored
31
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/helpers.go
generated
vendored
@ -188,7 +188,7 @@ func NestedSlice(obj map[string]interface{}, fields ...string) ([]interface{}, b
|
||||
// NestedStringMap returns a copy of map[string]string value of a nested field.
|
||||
// Returns false if value is not found and an error if not a map[string]interface{} or contains non-string values in the map.
|
||||
func NestedStringMap(obj map[string]interface{}, fields ...string) (map[string]string, bool, error) {
|
||||
m, found, err := nestedMapNoCopy(obj, fields...)
|
||||
m, found, err := nestedMapNoCopy(obj, false, fields...)
|
||||
if !found || err != nil {
|
||||
return nil, found, err
|
||||
}
|
||||
@ -203,10 +203,32 @@ func NestedStringMap(obj map[string]interface{}, fields ...string) (map[string]s
|
||||
return strMap, true, nil
|
||||
}
|
||||
|
||||
// NestedNullCoercingStringMap returns a copy of map[string]string value of a nested field.
|
||||
// Returns `nil, true, nil` if the value exists and is explicitly null.
|
||||
// Returns `nil, false, err` if the value is not a map or a null value, or is a map and contains non-string non-null values.
|
||||
// Null values in the map are coerced to "" to match json decoding behavior.
|
||||
func NestedNullCoercingStringMap(obj map[string]interface{}, fields ...string) (map[string]string, bool, error) {
|
||||
m, found, err := nestedMapNoCopy(obj, true, fields...)
|
||||
if !found || err != nil || m == nil {
|
||||
return nil, found, err
|
||||
}
|
||||
strMap := make(map[string]string, len(m))
|
||||
for k, v := range m {
|
||||
if str, ok := v.(string); ok {
|
||||
strMap[k] = str
|
||||
} else if v == nil {
|
||||
strMap[k] = ""
|
||||
} else {
|
||||
return nil, false, fmt.Errorf("%v accessor error: contains non-string value in the map under key %q: %v is of the type %T, expected string", jsonPath(fields), k, v, v)
|
||||
}
|
||||
}
|
||||
return strMap, true, nil
|
||||
}
|
||||
|
||||
// NestedMap returns a deep copy of map[string]interface{} value of a nested field.
|
||||
// Returns false if value is not found and an error if not a map[string]interface{}.
|
||||
func NestedMap(obj map[string]interface{}, fields ...string) (map[string]interface{}, bool, error) {
|
||||
m, found, err := nestedMapNoCopy(obj, fields...)
|
||||
m, found, err := nestedMapNoCopy(obj, false, fields...)
|
||||
if !found || err != nil {
|
||||
return nil, found, err
|
||||
}
|
||||
@ -215,11 +237,14 @@ func NestedMap(obj map[string]interface{}, fields ...string) (map[string]interfa
|
||||
|
||||
// nestedMapNoCopy returns a map[string]interface{} value of a nested field.
|
||||
// Returns false if value is not found and an error if not a map[string]interface{}.
|
||||
func nestedMapNoCopy(obj map[string]interface{}, fields ...string) (map[string]interface{}, bool, error) {
|
||||
func nestedMapNoCopy(obj map[string]interface{}, tolerateNil bool, fields ...string) (map[string]interface{}, bool, error) {
|
||||
val, found, err := NestedFieldNoCopy(obj, fields...)
|
||||
if !found || err != nil {
|
||||
return nil, found, err
|
||||
}
|
||||
if val == nil && tolerateNil {
|
||||
return nil, true, nil
|
||||
}
|
||||
m, ok := val.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("%v accessor error: %v is of the type %T, expected map[string]interface{}", jsonPath(fields), val, val)
|
||||
|
4
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go
generated
vendored
4
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go
generated
vendored
@ -397,7 +397,7 @@ func (u *Unstructured) SetDeletionGracePeriodSeconds(deletionGracePeriodSeconds
|
||||
}
|
||||
|
||||
func (u *Unstructured) GetLabels() map[string]string {
|
||||
m, _, _ := NestedStringMap(u.Object, "metadata", "labels")
|
||||
m, _, _ := NestedNullCoercingStringMap(u.Object, "metadata", "labels")
|
||||
return m
|
||||
}
|
||||
|
||||
@ -410,7 +410,7 @@ func (u *Unstructured) SetLabels(labels map[string]string) {
|
||||
}
|
||||
|
||||
func (u *Unstructured) GetAnnotations() map[string]string {
|
||||
m, _, _ := NestedStringMap(u.Object, "metadata", "annotations")
|
||||
m, _, _ := NestedNullCoercingStringMap(u.Object, "metadata", "annotations")
|
||||
return m
|
||||
}
|
||||
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation/validation.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation/validation.go
generated
vendored
@ -104,7 +104,7 @@ func ValidateLabelSelectorRequirement(sr metav1.LabelSelectorRequirement, opts L
|
||||
func ValidateLabelName(labelName string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
for _, msg := range validation.IsQualifiedName(labelName) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, labelName, msg))
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, labelName, msg).WithOrigin("labelKey"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/doc.go
generated
vendored
@ -20,4 +20,4 @@ limitations under the License.
|
||||
|
||||
// +groupName=meta.k8s.io
|
||||
|
||||
package v1beta1 // import "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
||||
package v1beta1
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/conversion/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/conversion/doc.go
generated
vendored
@ -21,4 +21,4 @@ limitations under the License.
|
||||
// but for the fields which did not change, copying is automated. This makes it
|
||||
// easy to modify the structures you use in memory without affecting the format
|
||||
// you store on disk or respond to in your external API calls.
|
||||
package conversion // import "k8s.io/apimachinery/pkg/conversion"
|
||||
package conversion
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/conversion/queryparams/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/conversion/queryparams/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package queryparams provides conversion from versioned
|
||||
// runtime objects to URL query values
|
||||
package queryparams // import "k8s.io/apimachinery/pkg/conversion/queryparams"
|
||||
package queryparams
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/fields/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/fields/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package fields implements a simple field system, parsing and matching
|
||||
// selectors with sets of fields.
|
||||
package fields // import "k8s.io/apimachinery/pkg/fields"
|
||||
package fields
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/labels/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/labels/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package labels implements a simple label system, parsing and matching
|
||||
// selectors with sets of labels.
|
||||
package labels // import "k8s.io/apimachinery/pkg/labels"
|
||||
package labels
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/runtime/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/runtime/doc.go
generated
vendored
@ -48,4 +48,4 @@ limitations under the License.
|
||||
//
|
||||
// As a bonus, a few common types useful from all api objects and versions
|
||||
// are provided in types.go.
|
||||
package runtime // import "k8s.io/apimachinery/pkg/runtime"
|
||||
package runtime
|
||||
|
1
e2e/vendor/k8s.io/apimachinery/pkg/runtime/interfaces.go
generated
vendored
1
e2e/vendor/k8s.io/apimachinery/pkg/runtime/interfaces.go
generated
vendored
@ -259,6 +259,7 @@ type ObjectDefaulter interface {
|
||||
|
||||
type ObjectVersioner interface {
|
||||
ConvertToVersion(in Object, gv GroupVersioner) (out Object, err error)
|
||||
PrioritizedVersionsForGroup(group string) []schema.GroupVersion
|
||||
}
|
||||
|
||||
// ObjectConvertor converts an object to a different version.
|
||||
|
39
e2e/vendor/k8s.io/apimachinery/pkg/runtime/scheme.go
generated
vendored
39
e2e/vendor/k8s.io/apimachinery/pkg/runtime/scheme.go
generated
vendored
@ -17,15 +17,18 @@ limitations under the License.
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/operation"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/naming"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
// Scheme defines methods for serializing and deserializing API objects, a type
|
||||
@ -68,6 +71,12 @@ type Scheme struct {
|
||||
// the provided object must be a pointer.
|
||||
defaulterFuncs map[reflect.Type]func(interface{})
|
||||
|
||||
// validationFuncs is a map to funcs to be called with an object to perform validation.
|
||||
// The provided object must be a pointer.
|
||||
// If oldObject is non-nil, update validation is performed and may perform additional
|
||||
// validation such as transition rules and immutability checks.
|
||||
validationFuncs map[reflect.Type]func(ctx context.Context, op operation.Operation, object, oldObject interface{}, subresources ...string) field.ErrorList
|
||||
|
||||
// converter stores all registered conversion functions. It also has
|
||||
// default converting behavior.
|
||||
converter *conversion.Converter
|
||||
@ -96,6 +105,7 @@ func NewScheme() *Scheme {
|
||||
unversionedKinds: map[string]reflect.Type{},
|
||||
fieldLabelConversionFuncs: map[schema.GroupVersionKind]FieldLabelConversionFunc{},
|
||||
defaulterFuncs: map[reflect.Type]func(interface{}){},
|
||||
validationFuncs: map[reflect.Type]func(ctx context.Context, op operation.Operation, object, oldObject interface{}, subresource ...string) field.ErrorList{},
|
||||
versionPriority: map[string][]string{},
|
||||
schemeName: naming.GetNameFromCallsite(internalPackages...),
|
||||
}
|
||||
@ -347,6 +357,35 @@ func (s *Scheme) Default(src Object) {
|
||||
}
|
||||
}
|
||||
|
||||
// AddValidationFunc registered a function that can validate the object, and
|
||||
// oldObject. These functions will be invoked when Validate() or ValidateUpdate()
|
||||
// is called. The function will never be called unless the validated object
|
||||
// matches srcType. If this function is invoked twice with the same srcType, the
|
||||
// fn passed to the later call will be used instead.
|
||||
func (s *Scheme) AddValidationFunc(srcType Object, fn func(ctx context.Context, op operation.Operation, object, oldObject interface{}, subresources ...string) field.ErrorList) {
|
||||
s.validationFuncs[reflect.TypeOf(srcType)] = fn
|
||||
}
|
||||
|
||||
// Validate validates the provided Object according to the generated declarative validation code.
|
||||
// WARNING: This does not validate all objects! The handwritten validation code in validation.go
|
||||
// is not run when this is called. Only the generated zz_generated.validations.go validation code is run.
|
||||
func (s *Scheme) Validate(ctx context.Context, options sets.Set[string], object Object, subresources ...string) field.ErrorList {
|
||||
if fn, ok := s.validationFuncs[reflect.TypeOf(object)]; ok {
|
||||
return fn(ctx, operation.Operation{Type: operation.Create, Options: options}, object, nil, subresources...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateUpdate validates the provided object and oldObject according to the generated declarative validation code.
|
||||
// WARNING: This does not validate all objects! The handwritten validation code in validation.go
|
||||
// is not run when this is called. Only the generated zz_generated.validations.go validation code is run.
|
||||
func (s *Scheme) ValidateUpdate(ctx context.Context, options sets.Set[string], object, oldObject Object, subresources ...string) field.ErrorList {
|
||||
if fn, ok := s.validationFuncs[reflect.TypeOf(object)]; ok {
|
||||
return fn(ctx, operation.Operation{Type: operation.Update, Options: options}, object, oldObject, subresources...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert will attempt to convert in into out. Both must be pointers. For easy
|
||||
// testing of conversion functions. Returns an error if the conversion isn't
|
||||
// possible. You can call this with types that haven't been registered (for example,
|
||||
|
4
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/custom.go
generated
vendored
4
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/custom.go
generated
vendored
@ -140,7 +140,7 @@ func (cache *checkers) getCheckerInternal(rt reflect.Type, parent *path) (c chec
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
defer wg.Done()
|
||||
c = checker{
|
||||
placeholder := checker{
|
||||
safe: func() bool {
|
||||
wg.Wait()
|
||||
return c.safe()
|
||||
@ -150,7 +150,7 @@ func (cache *checkers) getCheckerInternal(rt reflect.Type, parent *path) (c chec
|
||||
return c.check(rv, depth)
|
||||
},
|
||||
}
|
||||
if actual, loaded := cache.m.LoadOrStore(rt, &c); loaded {
|
||||
if actual, loaded := cache.m.LoadOrStore(rt, &placeholder); loaded {
|
||||
// Someone else stored an entry for this type, use it.
|
||||
return *actual.(*checker)
|
||||
}
|
||||
|
23
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go
generated
vendored
23
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go
generated
vendored
@ -28,7 +28,7 @@ import (
|
||||
func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, options CodecFactoryOptions) []runtime.SerializerInfo {
|
||||
jsonSerializer := json.NewSerializerWithOptions(
|
||||
mf, scheme, scheme,
|
||||
json.SerializerOptions{Yaml: false, Pretty: false, Strict: options.Strict},
|
||||
json.SerializerOptions{Yaml: false, Pretty: false, Strict: options.Strict, StreamingCollectionsEncoding: options.StreamingCollectionsEncodingToJSON},
|
||||
)
|
||||
jsonSerializerType := runtime.SerializerInfo{
|
||||
MediaType: runtime.ContentTypeJSON,
|
||||
@ -38,7 +38,7 @@ func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, option
|
||||
Serializer: jsonSerializer,
|
||||
StrictSerializer: json.NewSerializerWithOptions(
|
||||
mf, scheme, scheme,
|
||||
json.SerializerOptions{Yaml: false, Pretty: false, Strict: true},
|
||||
json.SerializerOptions{Yaml: false, Pretty: false, Strict: true, StreamingCollectionsEncoding: options.StreamingCollectionsEncodingToJSON},
|
||||
),
|
||||
StreamSerializer: &runtime.StreamSerializerInfo{
|
||||
EncodesAsText: true,
|
||||
@ -61,7 +61,9 @@ func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, option
|
||||
mf, scheme, scheme,
|
||||
json.SerializerOptions{Yaml: true, Pretty: false, Strict: true},
|
||||
)
|
||||
protoSerializer := protobuf.NewSerializer(scheme, scheme)
|
||||
protoSerializer := protobuf.NewSerializerWithOptions(scheme, scheme, protobuf.SerializerOptions{
|
||||
StreamingCollectionsEncoding: options.StreamingCollectionsEncodingToProtobuf,
|
||||
})
|
||||
protoRawSerializer := protobuf.NewRawSerializer(scheme, scheme)
|
||||
|
||||
serializers := []runtime.SerializerInfo{
|
||||
@ -113,6 +115,9 @@ type CodecFactoryOptions struct {
|
||||
// Pretty includes a pretty serializer along with the non-pretty one
|
||||
Pretty bool
|
||||
|
||||
StreamingCollectionsEncodingToJSON bool
|
||||
StreamingCollectionsEncodingToProtobuf bool
|
||||
|
||||
serializers []func(runtime.ObjectCreater, runtime.ObjectTyper) runtime.SerializerInfo
|
||||
}
|
||||
|
||||
@ -147,6 +152,18 @@ func WithSerializer(f func(runtime.ObjectCreater, runtime.ObjectTyper) runtime.S
|
||||
}
|
||||
}
|
||||
|
||||
func WithStreamingCollectionEncodingToJSON() CodecFactoryOptionsMutator {
|
||||
return func(options *CodecFactoryOptions) {
|
||||
options.StreamingCollectionsEncodingToJSON = true
|
||||
}
|
||||
}
|
||||
|
||||
func WithStreamingCollectionEncodingToProtobuf() CodecFactoryOptionsMutator {
|
||||
return func(options *CodecFactoryOptions) {
|
||||
options.StreamingCollectionsEncodingToProtobuf = true
|
||||
}
|
||||
}
|
||||
|
||||
// NewCodecFactory provides methods for retrieving serializers for the supported wire formats
|
||||
// and conversion wrappers to define preferred internal and external versions. In the future,
|
||||
// as the internal version is used less, callers may instead use a defaulting serializer and
|
||||
|
230
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/collections.go
generated
vendored
Normal file
230
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/collections.go
generated
vendored
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
Copyright 2025 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"slices"
|
||||
"sort"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
func streamEncodeCollections(obj runtime.Object, w io.Writer) (bool, error) {
|
||||
list, ok := obj.(*unstructured.UnstructuredList)
|
||||
if ok {
|
||||
return true, streamingEncodeUnstructuredList(w, list)
|
||||
}
|
||||
if _, ok := obj.(json.Marshaler); ok {
|
||||
return false, nil
|
||||
}
|
||||
typeMeta, listMeta, items, err := getListMeta(obj)
|
||||
if err == nil {
|
||||
return true, streamingEncodeList(w, typeMeta, listMeta, items)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// getListMeta implements list extraction logic for json stream serialization.
|
||||
//
|
||||
// Reason for a custom logic instead of reusing accessors from meta package:
|
||||
// * Validate json tags to prevent incompatibility with json standard package.
|
||||
// * ListMetaAccessor doesn't distinguish empty from nil value.
|
||||
// * TypeAccessort reparsing "apiVersion" and serializing it with "{group}/{version}"
|
||||
func getListMeta(list runtime.Object) (metav1.TypeMeta, metav1.ListMeta, []runtime.Object, error) {
|
||||
listValue, err := conversion.EnforcePtr(list)
|
||||
if err != nil {
|
||||
return metav1.TypeMeta{}, metav1.ListMeta{}, nil, err
|
||||
}
|
||||
listType := listValue.Type()
|
||||
if listType.NumField() != 3 {
|
||||
return metav1.TypeMeta{}, metav1.ListMeta{}, nil, fmt.Errorf("expected ListType to have 3 fields")
|
||||
}
|
||||
// TypeMeta
|
||||
typeMeta, ok := listValue.Field(0).Interface().(metav1.TypeMeta)
|
||||
if !ok {
|
||||
return metav1.TypeMeta{}, metav1.ListMeta{}, nil, fmt.Errorf("expected TypeMeta field to have TypeMeta type")
|
||||
}
|
||||
if listType.Field(0).Tag.Get("json") != ",inline" {
|
||||
return metav1.TypeMeta{}, metav1.ListMeta{}, nil, fmt.Errorf(`expected TypeMeta json field tag to be ",inline"`)
|
||||
}
|
||||
// ListMeta
|
||||
listMeta, ok := listValue.Field(1).Interface().(metav1.ListMeta)
|
||||
if !ok {
|
||||
return metav1.TypeMeta{}, metav1.ListMeta{}, nil, fmt.Errorf("expected ListMeta field to have ListMeta type")
|
||||
}
|
||||
if listType.Field(1).Tag.Get("json") != "metadata,omitempty" {
|
||||
return metav1.TypeMeta{}, metav1.ListMeta{}, nil, fmt.Errorf(`expected ListMeta json field tag to be "metadata,omitempty"`)
|
||||
}
|
||||
// Items
|
||||
items, err := meta.ExtractList(list)
|
||||
if err != nil {
|
||||
return metav1.TypeMeta{}, metav1.ListMeta{}, nil, err
|
||||
}
|
||||
if listType.Field(2).Tag.Get("json") != "items" {
|
||||
return metav1.TypeMeta{}, metav1.ListMeta{}, nil, fmt.Errorf(`expected Items json field tag to be "items"`)
|
||||
}
|
||||
return typeMeta, listMeta, items, nil
|
||||
}
|
||||
|
||||
func streamingEncodeList(w io.Writer, typeMeta metav1.TypeMeta, listMeta metav1.ListMeta, items []runtime.Object) error {
|
||||
// Start
|
||||
if _, err := w.Write([]byte(`{`)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TypeMeta
|
||||
if typeMeta.Kind != "" {
|
||||
if err := encodeKeyValuePair(w, "kind", typeMeta.Kind, []byte(",")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if typeMeta.APIVersion != "" {
|
||||
if err := encodeKeyValuePair(w, "apiVersion", typeMeta.APIVersion, []byte(",")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// ListMeta
|
||||
if err := encodeKeyValuePair(w, "metadata", listMeta, []byte(",")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Items
|
||||
if err := encodeItemsObjectSlice(w, items); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// End
|
||||
_, err := w.Write([]byte("}\n"))
|
||||
return err
|
||||
}
|
||||
|
||||
func encodeItemsObjectSlice(w io.Writer, items []runtime.Object) (err error) {
|
||||
if items == nil {
|
||||
err := encodeKeyValuePair(w, "items", nil, nil)
|
||||
return err
|
||||
}
|
||||
_, err = w.Write([]byte(`"items":[`))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
suffix := []byte(",")
|
||||
for i, item := range items {
|
||||
if i == len(items)-1 {
|
||||
suffix = nil
|
||||
}
|
||||
err := encodeValue(w, item, suffix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = w.Write([]byte("]"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func streamingEncodeUnstructuredList(w io.Writer, list *unstructured.UnstructuredList) error {
|
||||
_, err := w.Write([]byte(`{`))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keys := slices.Collect(maps.Keys(list.Object))
|
||||
if _, exists := list.Object["items"]; !exists {
|
||||
keys = append(keys, "items")
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
suffix := []byte(",")
|
||||
for i, key := range keys {
|
||||
if i == len(keys)-1 {
|
||||
suffix = nil
|
||||
}
|
||||
if key == "items" {
|
||||
err = encodeItemsUnstructuredSlice(w, list.Items, suffix)
|
||||
} else {
|
||||
err = encodeKeyValuePair(w, key, list.Object[key], suffix)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = w.Write([]byte("}\n"))
|
||||
return err
|
||||
}
|
||||
|
||||
func encodeItemsUnstructuredSlice(w io.Writer, items []unstructured.Unstructured, suffix []byte) (err error) {
|
||||
_, err = w.Write([]byte(`"items":[`))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
comma := []byte(",")
|
||||
for i, item := range items {
|
||||
if i == len(items)-1 {
|
||||
comma = nil
|
||||
}
|
||||
err := encodeValue(w, item.Object, comma)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = w.Write([]byte("]"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(suffix) > 0 {
|
||||
_, err = w.Write(suffix)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func encodeKeyValuePair(w io.Writer, key string, value any, suffix []byte) (err error) {
|
||||
err = encodeValue(w, key, []byte(":"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = encodeValue(w, value, suffix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func encodeValue(w io.Writer, value any, suffix []byte) error {
|
||||
data, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(suffix) > 0 {
|
||||
_, err = w.Write(suffix)
|
||||
}
|
||||
return err
|
||||
}
|
16
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go
generated
vendored
16
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/json/json.go
generated
vendored
@ -36,7 +36,7 @@ import (
|
||||
// is not nil, the object has the group, version, and kind fields set.
|
||||
// Deprecated: use NewSerializerWithOptions instead.
|
||||
func NewSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, pretty bool) *Serializer {
|
||||
return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{false, pretty, false})
|
||||
return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{false, pretty, false, false})
|
||||
}
|
||||
|
||||
// NewYAMLSerializer creates a YAML serializer that handles encoding versioned objects into the proper YAML form. If typer
|
||||
@ -44,7 +44,7 @@ func NewSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtim
|
||||
// matches JSON, and will error if constructs are used that do not serialize to JSON.
|
||||
// Deprecated: use NewSerializerWithOptions instead.
|
||||
func NewYAMLSerializer(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper) *Serializer {
|
||||
return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{true, false, false})
|
||||
return NewSerializerWithOptions(meta, creater, typer, SerializerOptions{true, false, false, false})
|
||||
}
|
||||
|
||||
// NewSerializerWithOptions creates a JSON/YAML serializer that handles encoding versioned objects into the proper JSON/YAML
|
||||
@ -93,6 +93,9 @@ type SerializerOptions struct {
|
||||
// Strict: configures the Serializer to return strictDecodingError's when duplicate fields are present decoding JSON or YAML.
|
||||
// Note that enabling this option is not as performant as the non-strict variant, and should not be used in fast paths.
|
||||
Strict bool
|
||||
|
||||
// StreamingCollectionsEncoding enables encoding collection, one item at the time, drastically reducing memory needed.
|
||||
StreamingCollectionsEncoding bool
|
||||
}
|
||||
|
||||
// Serializer handles encoding versioned objects into the proper JSON form
|
||||
@ -242,6 +245,15 @@ func (s *Serializer) doEncode(obj runtime.Object, w io.Writer) error {
|
||||
_, err = w.Write(data)
|
||||
return err
|
||||
}
|
||||
if s.options.StreamingCollectionsEncoding {
|
||||
ok, err := streamEncodeCollections(obj, w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ok {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
encoder := json.NewEncoder(w)
|
||||
return encoder.Encode(obj)
|
||||
}
|
||||
|
174
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/collections.go
generated
vendored
Normal file
174
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/collections.go
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
Copyright 2025 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package protobuf
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"math/bits"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
errFieldCount = errors.New("expected ListType to have 3 fields")
|
||||
errTypeMetaField = errors.New("expected TypeMeta field to have TypeMeta type")
|
||||
errTypeMetaProtobufTag = errors.New(`expected TypeMeta protobuf field tag to be ""`)
|
||||
errListMetaField = errors.New("expected ListMeta field to have ListMeta type")
|
||||
errListMetaProtobufTag = errors.New(`expected ListMeta protobuf field tag to be "bytes,1,opt,name=metadata"`)
|
||||
errItemsProtobufTag = errors.New(`expected Items protobuf field tag to be "bytes,2,rep,name=items"`)
|
||||
errItemsSizer = errors.New(`expected Items elements to implement proto.Sizer`)
|
||||
)
|
||||
|
||||
// getStreamingListData implements list extraction logic for protobuf stream serialization.
|
||||
//
|
||||
// Reason for a custom logic instead of reusing accessors from meta package:
|
||||
// * Validate proto tags to prevent incompatibility with proto standard package.
|
||||
// * ListMetaAccessor doesn't distinguish empty from nil value.
|
||||
// * TypeAccessor reparsing "apiVersion" and serializing it with "{group}/{version}"
|
||||
func getStreamingListData(list runtime.Object) (data streamingListData, err error) {
|
||||
listValue, err := conversion.EnforcePtr(list)
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
listType := listValue.Type()
|
||||
if listType.NumField() != 3 {
|
||||
return data, errFieldCount
|
||||
}
|
||||
// TypeMeta: validated, but not returned as is not serialized.
|
||||
_, ok := listValue.Field(0).Interface().(metav1.TypeMeta)
|
||||
if !ok {
|
||||
return data, errTypeMetaField
|
||||
}
|
||||
if listType.Field(0).Tag.Get("protobuf") != "" {
|
||||
return data, errTypeMetaProtobufTag
|
||||
}
|
||||
// ListMeta
|
||||
listMeta, ok := listValue.Field(1).Interface().(metav1.ListMeta)
|
||||
if !ok {
|
||||
return data, errListMetaField
|
||||
}
|
||||
// if we were ever to relax the protobuf tag check we should update the hardcoded `0xa` below when writing ListMeta.
|
||||
if listType.Field(1).Tag.Get("protobuf") != "bytes,1,opt,name=metadata" {
|
||||
return data, errListMetaProtobufTag
|
||||
}
|
||||
data.listMeta = listMeta
|
||||
// Items; if we were ever to relax the protobuf tag check we should update the hardcoded `0x12` below when writing Items.
|
||||
if listType.Field(2).Tag.Get("protobuf") != "bytes,2,rep,name=items" {
|
||||
return data, errItemsProtobufTag
|
||||
}
|
||||
items, err := meta.ExtractList(list)
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
data.items = items
|
||||
data.totalSize, data.listMetaSize, data.itemsSizes, err = listSize(listMeta, items)
|
||||
return data, err
|
||||
}
|
||||
|
||||
type streamingListData struct {
|
||||
// totalSize is the total size of the serialized List object, including their proto headers/size bytes
|
||||
totalSize int
|
||||
|
||||
// listMetaSize caches results from .Size() call to listMeta, doesn't include header bytes (field identifier, size)
|
||||
listMetaSize int
|
||||
listMeta metav1.ListMeta
|
||||
|
||||
// itemsSizes caches results from .Size() call to items, doesn't include header bytes (field identifier, size)
|
||||
itemsSizes []int
|
||||
items []runtime.Object
|
||||
}
|
||||
|
||||
// listSize return size of ListMeta and items to be later used for preallocations.
|
||||
// listMetaSize and itemSizes do not include header bytes (field identifier, size).
|
||||
func listSize(listMeta metav1.ListMeta, items []runtime.Object) (totalSize, listMetaSize int, itemSizes []int, err error) {
|
||||
// ListMeta
|
||||
listMetaSize = listMeta.Size()
|
||||
totalSize += 1 + sovGenerated(uint64(listMetaSize)) + listMetaSize
|
||||
// Items
|
||||
itemSizes = make([]int, len(items))
|
||||
for i, item := range items {
|
||||
sizer, ok := item.(proto.Sizer)
|
||||
if !ok {
|
||||
return totalSize, listMetaSize, nil, errItemsSizer
|
||||
}
|
||||
n := sizer.Size()
|
||||
itemSizes[i] = n
|
||||
totalSize += 1 + sovGenerated(uint64(n)) + n
|
||||
}
|
||||
return totalSize, listMetaSize, itemSizes, nil
|
||||
}
|
||||
|
||||
func streamingEncodeUnknownList(w io.Writer, unk runtime.Unknown, listData streamingListData, memAlloc runtime.MemoryAllocator) error {
|
||||
_, err := w.Write(protoEncodingPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// encodeList is responsible for encoding the List into the unknown Raw.
|
||||
encodeList := func(writer io.Writer) (int, error) {
|
||||
return streamingEncodeList(writer, listData, memAlloc)
|
||||
}
|
||||
_, err = unk.MarshalToWriter(w, listData.totalSize, encodeList)
|
||||
return err
|
||||
}
|
||||
|
||||
func streamingEncodeList(w io.Writer, listData streamingListData, memAlloc runtime.MemoryAllocator) (size int, err error) {
|
||||
// ListMeta; 0xa = (1 << 3) | 2; field number: 1, type: 2 (LEN). https://protobuf.dev/programming-guides/encoding/#structure
|
||||
n, err := doEncodeWithHeader(&listData.listMeta, w, 0xa, listData.listMetaSize, memAlloc)
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
// Items; 0x12 = (2 << 3) | 2; field number: 2, type: 2 (LEN). https://protobuf.dev/programming-guides/encoding/#structure
|
||||
for i, item := range listData.items {
|
||||
n, err := doEncodeWithHeader(item, w, 0x12, listData.itemsSizes[i], memAlloc)
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
}
|
||||
return size, nil
|
||||
}
|
||||
|
||||
func writeVarintGenerated(w io.Writer, v int) (int, error) {
|
||||
buf := make([]byte, sovGenerated(uint64(v)))
|
||||
encodeVarintGenerated(buf, len(buf), uint64(v))
|
||||
return w.Write(buf)
|
||||
}
|
||||
|
||||
// sovGenerated is copied from `generated.pb.go` returns size of varint.
|
||||
func sovGenerated(v uint64) int {
|
||||
return (bits.Len64(v|1) + 6) / 7
|
||||
}
|
||||
|
||||
// encodeVarintGenerated is copied from `generated.pb.go` encodes varint.
|
||||
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovGenerated(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
2
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package protobuf provides a Kubernetes serializer for the protobuf format.
|
||||
package protobuf // import "k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
|
||||
package protobuf
|
||||
|
87
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go
generated
vendored
87
e2e/vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf/protobuf.go
generated
vendored
@ -72,10 +72,18 @@ func IsNotMarshalable(err error) bool {
|
||||
// is passed, the encoded object will have group, version, and kind fields set. If typer is nil, the objects will be written
|
||||
// as-is (any type info passed with the object will be used).
|
||||
func NewSerializer(creater runtime.ObjectCreater, typer runtime.ObjectTyper) *Serializer {
|
||||
return NewSerializerWithOptions(creater, typer, SerializerOptions{})
|
||||
}
|
||||
|
||||
// NewSerializerWithOptions creates a Protobuf serializer that handles encoding versioned objects into the proper wire form. If a typer
|
||||
// is passed, the encoded object will have group, version, and kind fields set. If typer is nil, the objects will be written
|
||||
// as-is (any type info passed with the object will be used).
|
||||
func NewSerializerWithOptions(creater runtime.ObjectCreater, typer runtime.ObjectTyper, opts SerializerOptions) *Serializer {
|
||||
return &Serializer{
|
||||
prefix: protoEncodingPrefix,
|
||||
creater: creater,
|
||||
typer: typer,
|
||||
options: opts,
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,6 +92,14 @@ type Serializer struct {
|
||||
prefix []byte
|
||||
creater runtime.ObjectCreater
|
||||
typer runtime.ObjectTyper
|
||||
|
||||
options SerializerOptions
|
||||
}
|
||||
|
||||
// SerializerOptions holds the options which are used to configure a Proto serializer.
|
||||
type SerializerOptions struct {
|
||||
// StreamingCollectionsEncoding enables encoding collection, one item at the time, drastically reducing memory needed.
|
||||
StreamingCollectionsEncoding bool
|
||||
}
|
||||
|
||||
var _ runtime.Serializer = &Serializer{}
|
||||
@ -209,6 +225,13 @@ func (s *Serializer) doEncode(obj runtime.Object, w io.Writer, memAlloc runtime.
|
||||
},
|
||||
}
|
||||
}
|
||||
if s.options.StreamingCollectionsEncoding {
|
||||
listData, err := getStreamingListData(obj)
|
||||
if err == nil {
|
||||
// Doesn't honor custom proto marshaling methods (like json streaming), because all proto objects implement proto methods.
|
||||
return streamingEncodeUnknownList(w, unk, listData, memAlloc)
|
||||
}
|
||||
}
|
||||
|
||||
switch t := obj.(type) {
|
||||
case bufferedMarshaller:
|
||||
@ -428,6 +451,39 @@ func (s *RawSerializer) encode(obj runtime.Object, w io.Writer, memAlloc runtime
|
||||
}
|
||||
|
||||
func (s *RawSerializer) doEncode(obj runtime.Object, w io.Writer, memAlloc runtime.MemoryAllocator) error {
|
||||
_, err := doEncode(obj, w, nil, memAlloc)
|
||||
return err
|
||||
}
|
||||
|
||||
func doEncodeWithHeader(obj any, w io.Writer, field byte, precomputedSize int, memAlloc runtime.MemoryAllocator) (size int, err error) {
|
||||
// Field identifier
|
||||
n, err := w.Write([]byte{field})
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
// Size
|
||||
n, err = writeVarintGenerated(w, precomputedSize)
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
// Obj
|
||||
n, err = doEncode(obj, w, &precomputedSize, memAlloc)
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
if n != precomputedSize {
|
||||
return size, fmt.Errorf("the size value was %d, but doEncode wrote %d bytes to data", precomputedSize, n)
|
||||
}
|
||||
return size, nil
|
||||
}
|
||||
|
||||
// doEncode encodes provided object into writer using a allocator if possible.
|
||||
// Avoids call by object Size if precomputedObjSize is provided.
|
||||
// precomputedObjSize should not include header bytes (field identifier, size).
|
||||
func doEncode(obj any, w io.Writer, precomputedObjSize *int, memAlloc runtime.MemoryAllocator) (int, error) {
|
||||
if memAlloc == nil {
|
||||
klog.Error("a mandatory memory allocator wasn't provided, this might have a negative impact on performance, check invocations of EncodeWithAllocator method, falling back on runtime.SimpleAllocator")
|
||||
memAlloc = &runtime.SimpleAllocator{}
|
||||
@ -436,40 +492,43 @@ func (s *RawSerializer) doEncode(obj runtime.Object, w io.Writer, memAlloc runti
|
||||
case bufferedReverseMarshaller:
|
||||
// this path performs a single allocation during write only when the Allocator wasn't provided
|
||||
// it also requires the caller to implement the more efficient Size and MarshalToSizedBuffer methods
|
||||
encodedSize := uint64(t.Size())
|
||||
data := memAlloc.Allocate(encodedSize)
|
||||
if precomputedObjSize == nil {
|
||||
s := t.Size()
|
||||
precomputedObjSize = &s
|
||||
}
|
||||
data := memAlloc.Allocate(uint64(*precomputedObjSize))
|
||||
|
||||
n, err := t.MarshalToSizedBuffer(data)
|
||||
if err != nil {
|
||||
return err
|
||||
return 0, err
|
||||
}
|
||||
_, err = w.Write(data[:n])
|
||||
return err
|
||||
return w.Write(data[:n])
|
||||
|
||||
case bufferedMarshaller:
|
||||
// this path performs a single allocation during write only when the Allocator wasn't provided
|
||||
// it also requires the caller to implement the more efficient Size and MarshalTo methods
|
||||
encodedSize := uint64(t.Size())
|
||||
data := memAlloc.Allocate(encodedSize)
|
||||
if precomputedObjSize == nil {
|
||||
s := t.Size()
|
||||
precomputedObjSize = &s
|
||||
}
|
||||
data := memAlloc.Allocate(uint64(*precomputedObjSize))
|
||||
|
||||
n, err := t.MarshalTo(data)
|
||||
if err != nil {
|
||||
return err
|
||||
return 0, err
|
||||
}
|
||||
_, err = w.Write(data[:n])
|
||||
return err
|
||||
return w.Write(data[:n])
|
||||
|
||||
case proto.Marshaler:
|
||||
// this path performs extra allocations
|
||||
data, err := t.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
return 0, err
|
||||
}
|
||||
_, err = w.Write(data)
|
||||
return err
|
||||
return w.Write(data)
|
||||
|
||||
default:
|
||||
return errNotMarshalable{reflect.TypeOf(obj)}
|
||||
return 0, errNotMarshalable{reflect.TypeOf(obj)}
|
||||
}
|
||||
}
|
||||
|
||||
|
127
e2e/vendor/k8s.io/apimachinery/pkg/runtime/types_proto.go
generated
vendored
127
e2e/vendor/k8s.io/apimachinery/pkg/runtime/types_proto.go
generated
vendored
@ -18,6 +18,7 @@ package runtime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type ProtobufMarshaller interface {
|
||||
@ -28,6 +29,124 @@ type ProtobufReverseMarshaller interface {
|
||||
MarshalToSizedBuffer(data []byte) (int, error)
|
||||
}
|
||||
|
||||
const (
|
||||
typeMetaTag = 0xa
|
||||
rawTag = 0x12
|
||||
contentEncodingTag = 0x1a
|
||||
contentTypeTag = 0x22
|
||||
|
||||
// max length of a varint for a uint64
|
||||
maxUint64VarIntLength = 10
|
||||
)
|
||||
|
||||
// MarshalToWriter allows a caller to provide a streaming writer for raw bytes,
|
||||
// instead of populating them inside the Unknown struct.
|
||||
// rawSize is the number of bytes rawWriter will write in a success case.
|
||||
// writeRaw is called when it is time to write the raw bytes. It must return `rawSize, nil` or an error.
|
||||
func (m *Unknown) MarshalToWriter(w io.Writer, rawSize int, writeRaw func(io.Writer) (int, error)) (int, error) {
|
||||
size := 0
|
||||
|
||||
// reuse the buffer for varint marshaling
|
||||
varintBuffer := make([]byte, maxUint64VarIntLength)
|
||||
writeVarint := func(i int) (int, error) {
|
||||
offset := encodeVarintGenerated(varintBuffer, len(varintBuffer), uint64(i))
|
||||
return w.Write(varintBuffer[offset:])
|
||||
}
|
||||
|
||||
// TypeMeta
|
||||
{
|
||||
n, err := w.Write([]byte{typeMetaTag})
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
|
||||
typeMetaBytes, err := m.TypeMeta.Marshal()
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
|
||||
n, err = writeVarint(len(typeMetaBytes))
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
|
||||
n, err = w.Write(typeMetaBytes)
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
}
|
||||
|
||||
// Raw, delegating write to writeRaw()
|
||||
{
|
||||
n, err := w.Write([]byte{rawTag})
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
|
||||
n, err = writeVarint(rawSize)
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
|
||||
n, err = writeRaw(w)
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
if n != int(rawSize) {
|
||||
return size, fmt.Errorf("the size value was %d, but encoding wrote %d bytes to data", rawSize, n)
|
||||
}
|
||||
}
|
||||
|
||||
// ContentEncoding
|
||||
{
|
||||
n, err := w.Write([]byte{contentEncodingTag})
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
|
||||
n, err = writeVarint(len(m.ContentEncoding))
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
|
||||
n, err = w.Write([]byte(m.ContentEncoding))
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
}
|
||||
|
||||
// ContentEncoding
|
||||
{
|
||||
n, err := w.Write([]byte{contentTypeTag})
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
|
||||
n, err = writeVarint(len(m.ContentType))
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
|
||||
n, err = w.Write([]byte(m.ContentType))
|
||||
size += n
|
||||
if err != nil {
|
||||
return size, err
|
||||
}
|
||||
}
|
||||
return size, nil
|
||||
}
|
||||
|
||||
// NestedMarshalTo allows a caller to avoid extra allocations during serialization of an Unknown
|
||||
// that will contain an object that implements ProtobufMarshaller or ProtobufReverseMarshaller.
|
||||
func (m *Unknown) NestedMarshalTo(data []byte, b ProtobufMarshaller, size uint64) (int, error) {
|
||||
@ -43,12 +162,12 @@ func (m *Unknown) NestedMarshalTo(data []byte, b ProtobufMarshaller, size uint64
|
||||
copy(data[i:], m.ContentType)
|
||||
i = encodeVarintGenerated(data, i, uint64(len(m.ContentType)))
|
||||
i--
|
||||
data[i] = 0x22
|
||||
data[i] = contentTypeTag
|
||||
i -= len(m.ContentEncoding)
|
||||
copy(data[i:], m.ContentEncoding)
|
||||
i = encodeVarintGenerated(data, i, uint64(len(m.ContentEncoding)))
|
||||
i--
|
||||
data[i] = 0x1a
|
||||
data[i] = contentEncodingTag
|
||||
if b != nil {
|
||||
if r, ok := b.(ProtobufReverseMarshaller); ok {
|
||||
n1, err := r.MarshalToSizedBuffer(data[:i])
|
||||
@ -75,7 +194,7 @@ func (m *Unknown) NestedMarshalTo(data []byte, b ProtobufMarshaller, size uint64
|
||||
}
|
||||
i = encodeVarintGenerated(data, i, size)
|
||||
i--
|
||||
data[i] = 0x12
|
||||
data[i] = rawTag
|
||||
}
|
||||
n2, err := m.TypeMeta.MarshalToSizedBuffer(data[:i])
|
||||
if err != nil {
|
||||
@ -84,6 +203,6 @@ func (m *Unknown) NestedMarshalTo(data []byte, b ProtobufMarshaller, size uint64
|
||||
i -= n2
|
||||
i = encodeVarintGenerated(data, i, uint64(n2))
|
||||
i--
|
||||
data[i] = 0xa
|
||||
data[i] = typeMetaTag
|
||||
return msgSize - i, nil
|
||||
}
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/types/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/types/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package types implements various generic types used throughout kubernetes.
|
||||
package types // import "k8s.io/apimachinery/pkg/types"
|
||||
package types
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/util/diff/diff.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/util/diff/diff.go
generated
vendored
@ -23,7 +23,7 @@ import (
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp" //nolint:depguard
|
||||
"k8s.io/apimachinery/pkg/util/dump"
|
||||
)
|
||||
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/util/errors/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/util/errors/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package errors implements various utility functions and types around errors.
|
||||
package errors // import "k8s.io/apimachinery/pkg/util/errors"
|
||||
package errors
|
||||
|
6
e2e/vendor/k8s.io/apimachinery/pkg/util/framer/framer.go
generated
vendored
6
e2e/vendor/k8s.io/apimachinery/pkg/util/framer/framer.go
generated
vendored
@ -91,12 +91,12 @@ func (r *lengthDelimitedFrameReader) Read(data []byte) (int, error) {
|
||||
}
|
||||
n, err := io.ReadAtLeast(r.r, data[:max], int(max))
|
||||
r.remaining -= n
|
||||
if err == io.ErrShortBuffer || r.remaining > 0 {
|
||||
return n, io.ErrShortBuffer
|
||||
}
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
if r.remaining > 0 {
|
||||
return n, io.ErrShortBuffer
|
||||
}
|
||||
if n != expect {
|
||||
return n, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/util/httpstream/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/util/httpstream/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package httpstream adds multiplexed streaming support to HTTP requests and
|
||||
// responses via connection upgrades.
|
||||
package httpstream // import "k8s.io/apimachinery/pkg/util/httpstream"
|
||||
package httpstream
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/util/httpstream/wsstream/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/util/httpstream/wsstream/doc.go
generated
vendored
@ -66,4 +66,4 @@ limitations under the License.
|
||||
// WRITE []byte{0, 102, 111, 111, 10} # send "foo\n" on channel 0 (STDIN)
|
||||
// WRITE []byte{255, 0} # send CLOSE signal (STDIN)
|
||||
// CLOSE
|
||||
package wsstream // import "k8s.io/apimachinery/pkg/util/httpstream/wsstream"
|
||||
package wsstream
|
||||
|
14
e2e/vendor/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go
generated
vendored
14
e2e/vendor/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go
generated
vendored
@ -20,24 +20,24 @@ limitations under the License.
|
||||
package intstr
|
||||
|
||||
import (
|
||||
fuzz "github.com/google/gofuzz"
|
||||
"sigs.k8s.io/randfill"
|
||||
)
|
||||
|
||||
// Fuzz satisfies fuzz.Interface
|
||||
func (intstr *IntOrString) Fuzz(c fuzz.Continue) {
|
||||
// RandFill satisfies randfill.NativeSelfFiller
|
||||
func (intstr *IntOrString) RandFill(c randfill.Continue) {
|
||||
if intstr == nil {
|
||||
return
|
||||
}
|
||||
if c.RandBool() {
|
||||
if c.Bool() {
|
||||
intstr.Type = Int
|
||||
c.Fuzz(&intstr.IntVal)
|
||||
c.Fill(&intstr.IntVal)
|
||||
intstr.StrVal = ""
|
||||
} else {
|
||||
intstr.Type = String
|
||||
intstr.IntVal = 0
|
||||
c.Fuzz(&intstr.StrVal)
|
||||
c.Fill(&intstr.StrVal)
|
||||
}
|
||||
}
|
||||
|
||||
// ensure IntOrString implements fuzz.Interface
|
||||
var _ fuzz.Interface = &IntOrString{}
|
||||
var _ randfill.NativeSelfFiller = &IntOrString{}
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/util/proxy/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/util/proxy/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package proxy provides transport and upgrade support for proxies.
|
||||
package proxy // import "k8s.io/apimachinery/pkg/util/proxy"
|
||||
package proxy
|
||||
|
46
e2e/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go
generated
vendored
46
e2e/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go
generated
vendored
@ -36,6 +36,11 @@ var (
|
||||
)
|
||||
|
||||
// PanicHandlers is a list of functions which will be invoked when a panic happens.
|
||||
//
|
||||
// The code invoking these handlers prepares a contextual logger so that
|
||||
// klog.FromContext(ctx) already skips over the panic handler itself and
|
||||
// several other intermediate functions, ideally such that the log output
|
||||
// is attributed to the code which triggered the panic.
|
||||
var PanicHandlers = []func(context.Context, interface{}){logPanic}
|
||||
|
||||
// HandleCrash simply catches a crash and logs an error. Meant to be called via
|
||||
@ -45,7 +50,7 @@ var PanicHandlers = []func(context.Context, interface{}){logPanic}
|
||||
//
|
||||
// E.g., you can provide one or more additional handlers for something like shutting down go routines gracefully.
|
||||
//
|
||||
// Contextual logging: HandleCrashWithContext should be used instead of HandleCrash in code which supports contextual logging.
|
||||
// Contextual logging: HandleCrashWithContext or HandleCrashWithLogger should be used instead of HandleCrash in code which supports contextual logging.
|
||||
func HandleCrash(additionalHandlers ...func(interface{})) {
|
||||
if r := recover(); r != nil {
|
||||
additionalHandlersWithContext := make([]func(context.Context, interface{}), len(additionalHandlers))
|
||||
@ -74,10 +79,30 @@ func HandleCrashWithContext(ctx context.Context, additionalHandlers ...func(cont
|
||||
}
|
||||
}
|
||||
|
||||
// handleCrash is the common implementation of HandleCrash and HandleCrash.
|
||||
// HandleCrashWithLogger simply catches a crash and logs an error. Meant to be called via
|
||||
// defer. Additional context-specific handlers can be provided, and will be
|
||||
// called in case of panic. HandleCrash actually crashes, after calling the
|
||||
// handlers and logging the panic message.
|
||||
//
|
||||
// E.g., you can provide one or more additional handlers for something like shutting down go routines gracefully.
|
||||
func HandleCrashWithLogger(logger klog.Logger, additionalHandlers ...func(context.Context, interface{})) {
|
||||
if r := recover(); r != nil {
|
||||
ctx := klog.NewContext(context.Background(), logger)
|
||||
handleCrash(ctx, r, additionalHandlers...)
|
||||
}
|
||||
}
|
||||
|
||||
// handleCrash is the common implementation of the HandleCrash* variants.
|
||||
// Having those call a common implementation ensures that the stack depth
|
||||
// is the same regardless through which path the handlers get invoked.
|
||||
func handleCrash(ctx context.Context, r any, additionalHandlers ...func(context.Context, interface{})) {
|
||||
// We don't really know how many call frames to skip because the Go
|
||||
// panic handler is between us and the code where the panic occurred.
|
||||
// If it's one function (as in Go 1.21), then skipping four levels
|
||||
// gets us to the function which called the `defer HandleCrashWithontext(...)`.
|
||||
logger := klog.FromContext(ctx).WithCallDepth(4)
|
||||
ctx = klog.NewContext(ctx, logger)
|
||||
|
||||
for _, fn := range PanicHandlers {
|
||||
fn(ctx, r)
|
||||
}
|
||||
@ -106,11 +131,7 @@ func logPanic(ctx context.Context, r interface{}) {
|
||||
stacktrace := make([]byte, size)
|
||||
stacktrace = stacktrace[:runtime.Stack(stacktrace, false)]
|
||||
|
||||
// We don't really know how many call frames to skip because the Go
|
||||
// panic handler is between us and the code where the panic occurred.
|
||||
// If it's one function (as in Go 1.21), then skipping four levels
|
||||
// gets us to the function which called the `defer HandleCrashWithontext(...)`.
|
||||
logger := klog.FromContext(ctx).WithCallDepth(4)
|
||||
logger := klog.FromContext(ctx)
|
||||
|
||||
// For backwards compatibility, conversion to string
|
||||
// is handled here instead of defering to the logging
|
||||
@ -176,12 +197,19 @@ func HandleError(err error) {
|
||||
// and key/value pairs.
|
||||
//
|
||||
// This variant should be used instead of HandleError because it supports
|
||||
// structured, contextual logging.
|
||||
// structured, contextual logging. Alternatively, [HandleErrorWithLogger] can
|
||||
// be used if a logger is available instead of a context.
|
||||
func HandleErrorWithContext(ctx context.Context, err error, msg string, keysAndValues ...interface{}) {
|
||||
handleError(ctx, err, msg, keysAndValues...)
|
||||
}
|
||||
|
||||
// handleError is the common implementation of HandleError and HandleErrorWithContext.
|
||||
// HandleErrorWithLogger is an alternative to [HandlerErrorWithContext] which accepts
|
||||
// a logger for contextual logging.
|
||||
func HandleErrorWithLogger(logger klog.Logger, err error, msg string, keysAndValues ...interface{}) {
|
||||
handleError(klog.NewContext(context.Background(), logger), err, msg, keysAndValues...)
|
||||
}
|
||||
|
||||
// handleError is the common implementation of the HandleError* variants.
|
||||
// Using this common implementation ensures that the stack depth
|
||||
// is the same regardless through which path the handlers get invoked.
|
||||
func handleError(ctx context.Context, err error, msg string, keysAndValues ...interface{}) {
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/util/sets/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/util/sets/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package sets has generic set and specified sets. Generic set will
|
||||
// replace specified ones over time. And specific ones are deprecated.
|
||||
package sets // import "k8s.io/apimachinery/pkg/util/sets"
|
||||
package sets
|
||||
|
212
e2e/vendor/k8s.io/apimachinery/pkg/util/validation/field/error_matcher.go
generated
vendored
Normal file
212
e2e/vendor/k8s.io/apimachinery/pkg/util/validation/field/error_matcher.go
generated
vendored
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
Copyright 2025 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package field
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ErrorMatcher is a helper for comparing Error objects.
|
||||
type ErrorMatcher struct {
|
||||
// TODO(thockin): consider whether type is ever NOT required, maybe just
|
||||
// assume it.
|
||||
matchType bool
|
||||
// TODO(thockin): consider whether field could be assumed - if the
|
||||
// "want" error has a nil field, don't match on field.
|
||||
matchField bool
|
||||
// TODO(thockin): consider whether value could be assumed - if the
|
||||
// "want" error has a nil value, don't match on field.
|
||||
matchValue bool
|
||||
matchOrigin bool
|
||||
matchDetail func(want, got string) bool
|
||||
requireOriginWhenInvalid bool
|
||||
}
|
||||
|
||||
// Matches returns true if the two Error objects match according to the
|
||||
// configured criteria.
|
||||
func (m ErrorMatcher) Matches(want, got *Error) bool {
|
||||
if m.matchType && want.Type != got.Type {
|
||||
return false
|
||||
}
|
||||
if m.matchField && want.Field != got.Field {
|
||||
return false
|
||||
}
|
||||
if m.matchValue && !reflect.DeepEqual(want.BadValue, got.BadValue) {
|
||||
return false
|
||||
}
|
||||
if m.matchOrigin {
|
||||
if want.Origin != got.Origin {
|
||||
return false
|
||||
}
|
||||
if m.requireOriginWhenInvalid && want.Type == ErrorTypeInvalid {
|
||||
if want.Origin == "" || got.Origin == "" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if m.matchDetail != nil && !m.matchDetail(want.Detail, got.Detail) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Render returns a string representation of the specified Error object,
|
||||
// according to the criteria configured in the ErrorMatcher.
|
||||
func (m ErrorMatcher) Render(e *Error) string {
|
||||
buf := strings.Builder{}
|
||||
|
||||
comma := func() {
|
||||
if buf.Len() > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
}
|
||||
|
||||
if m.matchType {
|
||||
comma()
|
||||
buf.WriteString(fmt.Sprintf("Type=%q", e.Type))
|
||||
}
|
||||
if m.matchField {
|
||||
comma()
|
||||
buf.WriteString(fmt.Sprintf("Field=%q", e.Field))
|
||||
}
|
||||
if m.matchValue {
|
||||
comma()
|
||||
buf.WriteString(fmt.Sprintf("Value=%v", e.BadValue))
|
||||
}
|
||||
if m.matchOrigin || m.requireOriginWhenInvalid && e.Type == ErrorTypeInvalid {
|
||||
comma()
|
||||
buf.WriteString(fmt.Sprintf("Origin=%q", e.Origin))
|
||||
}
|
||||
if m.matchDetail != nil {
|
||||
comma()
|
||||
buf.WriteString(fmt.Sprintf("Detail=%q", e.Detail))
|
||||
}
|
||||
return "{" + buf.String() + "}"
|
||||
}
|
||||
|
||||
// Exactly returns a derived ErrorMatcher which matches all fields exactly.
|
||||
func (m ErrorMatcher) Exactly() ErrorMatcher {
|
||||
return m.ByType().ByField().ByValue().ByOrigin().ByDetailExact()
|
||||
}
|
||||
|
||||
// ByType returns a derived ErrorMatcher which also matches by type.
|
||||
func (m ErrorMatcher) ByType() ErrorMatcher {
|
||||
m.matchType = true
|
||||
return m
|
||||
}
|
||||
|
||||
// ByField returns a derived ErrorMatcher which also matches by field path.
|
||||
func (m ErrorMatcher) ByField() ErrorMatcher {
|
||||
m.matchField = true
|
||||
return m
|
||||
}
|
||||
|
||||
// ByValue returns a derived ErrorMatcher which also matches by the errant
|
||||
// value.
|
||||
func (m ErrorMatcher) ByValue() ErrorMatcher {
|
||||
m.matchValue = true
|
||||
return m
|
||||
}
|
||||
|
||||
// ByOrigin returns a derived ErrorMatcher which also matches by the origin.
|
||||
func (m ErrorMatcher) ByOrigin() ErrorMatcher {
|
||||
m.matchOrigin = true
|
||||
return m
|
||||
}
|
||||
|
||||
// RequireOriginWhenInvalid returns a derived ErrorMatcher which also requires
|
||||
// the Origin field to be set when the Type is Invalid and the matcher is
|
||||
// matching by Origin.
|
||||
func (m ErrorMatcher) RequireOriginWhenInvalid() ErrorMatcher {
|
||||
m.requireOriginWhenInvalid = true
|
||||
return m
|
||||
}
|
||||
|
||||
// ByDetailExact returns a derived ErrorMatcher which also matches errors by
|
||||
// the exact detail string.
|
||||
func (m ErrorMatcher) ByDetailExact() ErrorMatcher {
|
||||
m.matchDetail = func(want, got string) bool {
|
||||
return got == want
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// ByDetailSubstring returns a derived ErrorMatcher which also matches errors
|
||||
// by a substring of the detail string.
|
||||
func (m ErrorMatcher) ByDetailSubstring() ErrorMatcher {
|
||||
m.matchDetail = func(want, got string) bool {
|
||||
return strings.Contains(got, want)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// ByDetailRegexp returns a derived ErrorMatcher which also matches errors by a
|
||||
// regular expression of the detail string, where the "want" string is assumed
|
||||
// to be a valid regular expression.
|
||||
func (m ErrorMatcher) ByDetailRegexp() ErrorMatcher {
|
||||
m.matchDetail = func(want, got string) bool {
|
||||
return regexp.MustCompile(want).MatchString(got)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// TestIntf lets users pass a testing.T while not coupling this package to Go's
|
||||
// testing package.
|
||||
type TestIntf interface {
|
||||
Helper()
|
||||
Errorf(format string, args ...any)
|
||||
Logf(format string, args ...any)
|
||||
}
|
||||
|
||||
// Test compares two ErrorLists by the criteria configured in this matcher, and
|
||||
// fails the test if they don't match. If a given "want" error matches multiple
|
||||
// "got" errors, they will all be consumed. This might be OK (e.g. if there are
|
||||
// multiple errors on the same field from the same origin) or it might be an
|
||||
// insufficiently specific matcher, so these will be logged.
|
||||
func (m ErrorMatcher) Test(tb TestIntf, want, got ErrorList) {
|
||||
tb.Helper()
|
||||
|
||||
remaining := got
|
||||
for _, w := range want {
|
||||
tmp := make(ErrorList, 0, len(remaining))
|
||||
n := 0
|
||||
for _, g := range remaining {
|
||||
if m.Matches(w, g) {
|
||||
n++
|
||||
} else {
|
||||
tmp = append(tmp, g)
|
||||
}
|
||||
}
|
||||
if n == 0 {
|
||||
tb.Errorf("expected an error matching:\n%s", m.Render(w))
|
||||
} else if n > 1 {
|
||||
// This is not necessarily and error, but it's worth logging in
|
||||
// case it's not what the test author intended.
|
||||
tb.Logf("multiple errors matched:\n%s", m.Render(w))
|
||||
}
|
||||
remaining = tmp
|
||||
}
|
||||
if len(remaining) > 0 {
|
||||
for _, e := range remaining {
|
||||
exactly := m.Exactly() // makes a copy
|
||||
tb.Errorf("unmatched error:\n%s", exactly.Render(e))
|
||||
}
|
||||
}
|
||||
}
|
132
e2e/vendor/k8s.io/apimachinery/pkg/util/validation/field/errors.go
generated
vendored
132
e2e/vendor/k8s.io/apimachinery/pkg/util/validation/field/errors.go
generated
vendored
@ -33,13 +33,35 @@ type Error struct {
|
||||
Field string
|
||||
BadValue interface{}
|
||||
Detail string
|
||||
|
||||
// Origin uniquely identifies where this error was generated from. It is used in testing to
|
||||
// compare expected errors against actual errors without relying on exact detail string matching.
|
||||
// This allows tests to verify the correct validation logic triggered the error
|
||||
// regardless of how the error message might be formatted or localized.
|
||||
//
|
||||
// The value should be either:
|
||||
// - A simple camelCase identifier (e.g., "maximum", "maxItems")
|
||||
// - A structured format using "format=<dash-style-identifier>" for validation errors related to specific formats
|
||||
// (e.g., "format=dns-label", "format=qualified-name")
|
||||
//
|
||||
// If the Origin corresponds to an existing declarative validation tag or JSON Schema keyword,
|
||||
// use that same name for consistency.
|
||||
//
|
||||
// Origin should be set in the most deeply nested validation function that
|
||||
// can still identify the unique source of the error.
|
||||
Origin string
|
||||
|
||||
// CoveredByDeclarative is true when this error is covered by declarative
|
||||
// validation. This field is to identify errors from imperative validation
|
||||
// that should also be caught by declarative validation.
|
||||
CoveredByDeclarative bool
|
||||
}
|
||||
|
||||
var _ error = &Error{}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (v *Error) Error() string {
|
||||
return fmt.Sprintf("%s: %s", v.Field, v.ErrorBody())
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.Field, e.ErrorBody())
|
||||
}
|
||||
|
||||
type OmitValueType struct{}
|
||||
@ -48,21 +70,21 @@ var omitValue = OmitValueType{}
|
||||
|
||||
// ErrorBody returns the error message without the field name. This is useful
|
||||
// for building nice-looking higher-level error reporting.
|
||||
func (v *Error) ErrorBody() string {
|
||||
func (e *Error) ErrorBody() string {
|
||||
var s string
|
||||
switch {
|
||||
case v.Type == ErrorTypeRequired:
|
||||
s = v.Type.String()
|
||||
case v.Type == ErrorTypeForbidden:
|
||||
s = v.Type.String()
|
||||
case v.Type == ErrorTypeTooLong:
|
||||
s = v.Type.String()
|
||||
case v.Type == ErrorTypeInternal:
|
||||
s = v.Type.String()
|
||||
case v.BadValue == omitValue:
|
||||
s = v.Type.String()
|
||||
case e.Type == ErrorTypeRequired:
|
||||
s = e.Type.String()
|
||||
case e.Type == ErrorTypeForbidden:
|
||||
s = e.Type.String()
|
||||
case e.Type == ErrorTypeTooLong:
|
||||
s = e.Type.String()
|
||||
case e.Type == ErrorTypeInternal:
|
||||
s = e.Type.String()
|
||||
case e.BadValue == omitValue:
|
||||
s = e.Type.String()
|
||||
default:
|
||||
value := v.BadValue
|
||||
value := e.BadValue
|
||||
valueType := reflect.TypeOf(value)
|
||||
if value == nil || valueType == nil {
|
||||
value = "null"
|
||||
@ -76,26 +98,38 @@ func (v *Error) ErrorBody() string {
|
||||
switch t := value.(type) {
|
||||
case int64, int32, float64, float32, bool:
|
||||
// use simple printer for simple types
|
||||
s = fmt.Sprintf("%s: %v", v.Type, value)
|
||||
s = fmt.Sprintf("%s: %v", e.Type, value)
|
||||
case string:
|
||||
s = fmt.Sprintf("%s: %q", v.Type, t)
|
||||
s = fmt.Sprintf("%s: %q", e.Type, t)
|
||||
case fmt.Stringer:
|
||||
// anything that defines String() is better than raw struct
|
||||
s = fmt.Sprintf("%s: %s", v.Type, t.String())
|
||||
s = fmt.Sprintf("%s: %s", e.Type, t.String())
|
||||
default:
|
||||
// fallback to raw struct
|
||||
// TODO: internal types have panic guards against json.Marshalling to prevent
|
||||
// accidental use of internal types in external serialized form. For now, use
|
||||
// %#v, although it would be better to show a more expressive output in the future
|
||||
s = fmt.Sprintf("%s: %#v", v.Type, value)
|
||||
s = fmt.Sprintf("%s: %#v", e.Type, value)
|
||||
}
|
||||
}
|
||||
if len(v.Detail) != 0 {
|
||||
s += fmt.Sprintf(": %s", v.Detail)
|
||||
if len(e.Detail) != 0 {
|
||||
s += fmt.Sprintf(": %s", e.Detail)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// WithOrigin adds origin information to the FieldError
|
||||
func (e *Error) WithOrigin(o string) *Error {
|
||||
e.Origin = o
|
||||
return e
|
||||
}
|
||||
|
||||
// MarkCoveredByDeclarative marks the error as covered by declarative validation.
|
||||
func (e *Error) MarkCoveredByDeclarative() *Error {
|
||||
e.CoveredByDeclarative = true
|
||||
return e
|
||||
}
|
||||
|
||||
// ErrorType is a machine readable value providing more detail about why
|
||||
// a field is invalid. These values are expected to match 1-1 with
|
||||
// CauseType in api/types.go.
|
||||
@ -169,32 +203,32 @@ func (t ErrorType) String() string {
|
||||
|
||||
// TypeInvalid returns a *Error indicating "type is invalid"
|
||||
func TypeInvalid(field *Path, value interface{}, detail string) *Error {
|
||||
return &Error{ErrorTypeTypeInvalid, field.String(), value, detail}
|
||||
return &Error{ErrorTypeTypeInvalid, field.String(), value, detail, "", false}
|
||||
}
|
||||
|
||||
// NotFound returns a *Error indicating "value not found". This is
|
||||
// used to report failure to find a requested value (e.g. looking up an ID).
|
||||
func NotFound(field *Path, value interface{}) *Error {
|
||||
return &Error{ErrorTypeNotFound, field.String(), value, ""}
|
||||
return &Error{ErrorTypeNotFound, field.String(), value, "", "", false}
|
||||
}
|
||||
|
||||
// Required returns a *Error indicating "value required". This is used
|
||||
// to report required values that are not provided (e.g. empty strings, null
|
||||
// values, or empty arrays).
|
||||
func Required(field *Path, detail string) *Error {
|
||||
return &Error{ErrorTypeRequired, field.String(), "", detail}
|
||||
return &Error{ErrorTypeRequired, field.String(), "", detail, "", false}
|
||||
}
|
||||
|
||||
// Duplicate returns a *Error indicating "duplicate value". This is
|
||||
// used to report collisions of values that must be unique (e.g. names or IDs).
|
||||
func Duplicate(field *Path, value interface{}) *Error {
|
||||
return &Error{ErrorTypeDuplicate, field.String(), value, ""}
|
||||
return &Error{ErrorTypeDuplicate, field.String(), value, "", "", false}
|
||||
}
|
||||
|
||||
// Invalid returns a *Error indicating "invalid value". This is used
|
||||
// to report malformed values (e.g. failed regex match, too long, out of bounds).
|
||||
func Invalid(field *Path, value interface{}, detail string) *Error {
|
||||
return &Error{ErrorTypeInvalid, field.String(), value, detail}
|
||||
return &Error{ErrorTypeInvalid, field.String(), value, detail, "", false}
|
||||
}
|
||||
|
||||
// NotSupported returns a *Error indicating "unsupported value".
|
||||
@ -209,7 +243,7 @@ func NotSupported[T ~string](field *Path, value interface{}, validValues []T) *E
|
||||
}
|
||||
detail = "supported values: " + strings.Join(quotedValues, ", ")
|
||||
}
|
||||
return &Error{ErrorTypeNotSupported, field.String(), value, detail}
|
||||
return &Error{ErrorTypeNotSupported, field.String(), value, detail, "", false}
|
||||
}
|
||||
|
||||
// Forbidden returns a *Error indicating "forbidden". This is used to
|
||||
@ -217,7 +251,7 @@ func NotSupported[T ~string](field *Path, value interface{}, validValues []T) *E
|
||||
// some conditions, but which are not permitted by current conditions (e.g.
|
||||
// security policy).
|
||||
func Forbidden(field *Path, detail string) *Error {
|
||||
return &Error{ErrorTypeForbidden, field.String(), "", detail}
|
||||
return &Error{ErrorTypeForbidden, field.String(), "", detail, "", false}
|
||||
}
|
||||
|
||||
// TooLong returns a *Error indicating "too long". This is used to report that
|
||||
@ -231,7 +265,7 @@ func TooLong(field *Path, value interface{}, maxLength int) *Error {
|
||||
} else {
|
||||
msg = "value is too long"
|
||||
}
|
||||
return &Error{ErrorTypeTooLong, field.String(), "<value omitted>", msg}
|
||||
return &Error{ErrorTypeTooLong, field.String(), "<value omitted>", msg, "", false}
|
||||
}
|
||||
|
||||
// TooLongMaxLength returns a *Error indicating "too long".
|
||||
@ -259,14 +293,14 @@ func TooMany(field *Path, actualQuantity, maxQuantity int) *Error {
|
||||
actual = omitValue
|
||||
}
|
||||
|
||||
return &Error{ErrorTypeTooMany, field.String(), actual, msg}
|
||||
return &Error{ErrorTypeTooMany, field.String(), actual, msg, "", false}
|
||||
}
|
||||
|
||||
// InternalError returns a *Error indicating "internal error". This is used
|
||||
// to signal that an error was found that was not directly related to user
|
||||
// input. The err argument must be non-nil.
|
||||
func InternalError(field *Path, err error) *Error {
|
||||
return &Error{ErrorTypeInternal, field.String(), nil, err.Error()}
|
||||
return &Error{ErrorTypeInternal, field.String(), nil, err.Error(), "", false}
|
||||
}
|
||||
|
||||
// ErrorList holds a set of Errors. It is plausible that we might one day have
|
||||
@ -285,6 +319,22 @@ func NewErrorTypeMatcher(t ErrorType) utilerrors.Matcher {
|
||||
}
|
||||
}
|
||||
|
||||
// WithOrigin sets the origin for all errors in the list and returns the updated list.
|
||||
func (list ErrorList) WithOrigin(origin string) ErrorList {
|
||||
for _, err := range list {
|
||||
err.Origin = origin
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// MarkCoveredByDeclarative marks all errors in the list as covered by declarative validation.
|
||||
func (list ErrorList) MarkCoveredByDeclarative() ErrorList {
|
||||
for _, err := range list {
|
||||
err.CoveredByDeclarative = true
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// ToAggregate converts the ErrorList into an errors.Aggregate.
|
||||
func (list ErrorList) ToAggregate() utilerrors.Aggregate {
|
||||
if len(list) == 0 {
|
||||
@ -321,3 +371,25 @@ func (list ErrorList) Filter(fns ...utilerrors.Matcher) ErrorList {
|
||||
// FilterOut takes an Aggregate and returns an Aggregate
|
||||
return fromAggregate(err.(utilerrors.Aggregate))
|
||||
}
|
||||
|
||||
// ExtractCoveredByDeclarative returns a new ErrorList containing only the errors that should be covered by declarative validation.
|
||||
func (list ErrorList) ExtractCoveredByDeclarative() ErrorList {
|
||||
newList := ErrorList{}
|
||||
for _, err := range list {
|
||||
if err.CoveredByDeclarative {
|
||||
newList = append(newList, err)
|
||||
}
|
||||
}
|
||||
return newList
|
||||
}
|
||||
|
||||
// RemoveCoveredByDeclarative returns a new ErrorList containing only the errors that should not be covered by declarative validation.
|
||||
func (list ErrorList) RemoveCoveredByDeclarative() ErrorList {
|
||||
newList := ErrorList{}
|
||||
for _, err := range list {
|
||||
if !err.CoveredByDeclarative {
|
||||
newList = append(newList, err)
|
||||
}
|
||||
}
|
||||
return newList
|
||||
}
|
||||
|
278
e2e/vendor/k8s.io/apimachinery/pkg/util/validation/ip.go
generated
vendored
Normal file
278
e2e/vendor/k8s.io/apimachinery/pkg/util/validation/ip.go
generated
vendored
Normal file
@ -0,0 +1,278 @@
|
||||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"slices"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/klog/v2"
|
||||
netutils "k8s.io/utils/net"
|
||||
)
|
||||
|
||||
func parseIP(fldPath *field.Path, value string, strictValidation bool) (net.IP, field.ErrorList) {
|
||||
var allErrors field.ErrorList
|
||||
|
||||
ip := netutils.ParseIPSloppy(value)
|
||||
if ip == nil {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must be a valid IP address, (e.g. 10.9.8.7 or 2001:db8::ffff)"))
|
||||
return nil, allErrors
|
||||
}
|
||||
|
||||
if strictValidation {
|
||||
addr, err := netip.ParseAddr(value)
|
||||
if err != nil {
|
||||
// If netutils.ParseIPSloppy parsed it, but netip.ParseAddr
|
||||
// doesn't, then it must have illegal leading 0s.
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must not have leading 0s"))
|
||||
}
|
||||
if addr.Is4In6() {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must not be an IPv4-mapped IPv6 address"))
|
||||
}
|
||||
}
|
||||
|
||||
return ip, allErrors
|
||||
}
|
||||
|
||||
// IsValidIPForLegacyField tests that the argument is a valid IP address for a "legacy"
|
||||
// API field that predates strict IP validation. In particular, this allows IPs that are
|
||||
// not in canonical form (e.g., "FE80:0:0:0:0:0:0:0abc" instead of "fe80::abc").
|
||||
//
|
||||
// If strictValidation is false, this also allows IPs in certain invalid or ambiguous
|
||||
// formats:
|
||||
//
|
||||
// 1. IPv4 IPs are allowed to have leading "0"s in octets (e.g. "010.002.003.004").
|
||||
// Historically, net.ParseIP (and later netutils.ParseIPSloppy) simply ignored leading
|
||||
// "0"s in IPv4 addresses, but most libc-based software treats 0-prefixed IPv4 octets
|
||||
// as octal, meaning different software might interpret the same string as two
|
||||
// different IPs, potentially leading to security issues. (Current net.ParseIP and
|
||||
// netip.ParseAddr simply reject inputs with leading "0"s.)
|
||||
//
|
||||
// 2. IPv4-mapped IPv6 IPs (e.g. "::ffff:1.2.3.4") are allowed. These can also lead to
|
||||
// different software interpreting the value in different ways, because they may be
|
||||
// treated as IPv4 by some software and IPv6 by other software. (net.ParseIP and
|
||||
// netip.ParseAddr both allow these, but there are no use cases for representing IPv4
|
||||
// addresses as IPv4-mapped IPv6 addresses in Kubernetes.)
|
||||
//
|
||||
// Alternatively, when validating an update to an existing field, you can pass a list of
|
||||
// IP values from the old object that should be accepted if they appear in the new object
|
||||
// even if they are not valid.
|
||||
//
|
||||
// This function should only be used to validate the existing fields that were
|
||||
// historically validated in this way, and strictValidation should be true unless the
|
||||
// StrictIPCIDRValidation feature gate is disabled. Use IsValidIP for parsing new fields.
|
||||
func IsValidIPForLegacyField(fldPath *field.Path, value string, strictValidation bool, validOldIPs []string) field.ErrorList {
|
||||
if slices.Contains(validOldIPs, value) {
|
||||
return nil
|
||||
}
|
||||
_, allErrors := parseIP(fldPath, value, strictValidation)
|
||||
return allErrors.WithOrigin("format=ip-sloppy")
|
||||
}
|
||||
|
||||
// IsValidIP tests that the argument is a valid IP address, according to current
|
||||
// Kubernetes standards for IP address validation.
|
||||
func IsValidIP(fldPath *field.Path, value string) field.ErrorList {
|
||||
ip, allErrors := parseIP(fldPath, value, true)
|
||||
if len(allErrors) != 0 {
|
||||
return allErrors.WithOrigin("format=ip-strict")
|
||||
}
|
||||
|
||||
if value != ip.String() {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, fmt.Sprintf("must be in canonical form (%q)", ip.String())))
|
||||
}
|
||||
return allErrors.WithOrigin("format=ip-strict")
|
||||
}
|
||||
|
||||
// GetWarningsForIP returns warnings for IP address values in non-standard forms. This
|
||||
// should only be used with fields that are validated with IsValidIPForLegacyField().
|
||||
func GetWarningsForIP(fldPath *field.Path, value string) []string {
|
||||
ip := netutils.ParseIPSloppy(value)
|
||||
if ip == nil {
|
||||
klog.ErrorS(nil, "GetWarningsForIP called on value that was not validated with IsValidIPForLegacyField", "field", fldPath, "value", value)
|
||||
return nil
|
||||
}
|
||||
|
||||
addr, _ := netip.ParseAddr(value)
|
||||
if !addr.IsValid() || addr.Is4In6() {
|
||||
// This catches 2 cases: leading 0s (if ParseIPSloppy() accepted it but
|
||||
// ParseAddr() doesn't) or IPv4-mapped IPv6 (.Is4In6()). Either way,
|
||||
// re-stringifying the net.IP value will give the preferred form.
|
||||
return []string{
|
||||
fmt.Sprintf("%s: non-standard IP address %q will be considered invalid in a future Kubernetes release: use %q", fldPath, value, ip.String()),
|
||||
}
|
||||
}
|
||||
|
||||
// If ParseIPSloppy() and ParseAddr() both accept it then it's fully valid, though
|
||||
// it may be non-canonical.
|
||||
if addr.Is6() && addr.String() != value {
|
||||
return []string{
|
||||
fmt.Sprintf("%s: IPv6 address %q should be in RFC 5952 canonical format (%q)", fldPath, value, addr.String()),
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseCIDR(fldPath *field.Path, value string, strictValidation bool) (*net.IPNet, field.ErrorList) {
|
||||
var allErrors field.ErrorList
|
||||
|
||||
_, ipnet, err := netutils.ParseCIDRSloppy(value)
|
||||
if err != nil {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must be a valid CIDR value, (e.g. 10.9.8.0/24 or 2001:db8::/64)"))
|
||||
return nil, allErrors
|
||||
}
|
||||
|
||||
if strictValidation {
|
||||
prefix, err := netip.ParsePrefix(value)
|
||||
if err != nil {
|
||||
// If netutils.ParseCIDRSloppy parsed it, but netip.ParsePrefix
|
||||
// doesn't, then it must have illegal leading 0s (either in the
|
||||
// IP part or the prefix).
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must not have leading 0s in IP or prefix length"))
|
||||
} else if prefix.Addr().Is4In6() {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must not have an IPv4-mapped IPv6 address"))
|
||||
} else if prefix.Addr() != prefix.Masked().Addr() {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must not have bits set beyond the prefix length"))
|
||||
}
|
||||
}
|
||||
|
||||
return ipnet, allErrors
|
||||
}
|
||||
|
||||
// IsValidCIDRForLegacyField tests that the argument is a valid CIDR value for a "legacy"
|
||||
// API field that predates strict IP validation. In particular, this allows IPs that are
|
||||
// not in canonical form (e.g., "FE80:0abc:0:0:0:0:0:0/64" instead of "fe80:abc::/64").
|
||||
//
|
||||
// If strictValidation is false, this also allows CIDR values in certain invalid or
|
||||
// ambiguous formats:
|
||||
//
|
||||
// 1. The IP part of the CIDR value is parsed as with IsValidIPForLegacyField with
|
||||
// strictValidation=false.
|
||||
//
|
||||
// 2. The CIDR value is allowed to be either a "subnet"/"mask" (with the lower bits after
|
||||
// the prefix length all being 0), or an "interface address" as with `ip addr` (with a
|
||||
// complete IP address and associated subnet length). With strict validation, the
|
||||
// value is required to be in "subnet"/"mask" form.
|
||||
//
|
||||
// 3. The prefix length is allowed to have leading 0s.
|
||||
//
|
||||
// Alternatively, when validating an update to an existing field, you can pass a list of
|
||||
// CIDR values from the old object that should be accepted if they appear in the new
|
||||
// object even if they are not valid.
|
||||
//
|
||||
// This function should only be used to validate the existing fields that were
|
||||
// historically validated in this way, and strictValidation should be true unless the
|
||||
// StrictIPCIDRValidation feature gate is disabled. Use IsValidCIDR or
|
||||
// IsValidInterfaceAddress for parsing new fields.
|
||||
func IsValidCIDRForLegacyField(fldPath *field.Path, value string, strictValidation bool, validOldCIDRs []string) field.ErrorList {
|
||||
if slices.Contains(validOldCIDRs, value) {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, allErrors := parseCIDR(fldPath, value, strictValidation)
|
||||
return allErrors
|
||||
}
|
||||
|
||||
// IsValidCIDR tests that the argument is a valid CIDR value, according to current
|
||||
// Kubernetes standards for CIDR validation. This function is only for
|
||||
// "subnet"/"mask"-style CIDR values (e.g., "192.168.1.0/24", with no bits set beyond the
|
||||
// prefix length). Use IsValidInterfaceAddress for "ifaddr"-style CIDR values.
|
||||
func IsValidCIDR(fldPath *field.Path, value string) field.ErrorList {
|
||||
ipnet, allErrors := parseCIDR(fldPath, value, true)
|
||||
if len(allErrors) != 0 {
|
||||
return allErrors
|
||||
}
|
||||
|
||||
if value != ipnet.String() {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, fmt.Sprintf("must be in canonical form (%q)", ipnet.String())))
|
||||
}
|
||||
return allErrors
|
||||
}
|
||||
|
||||
// GetWarningsForCIDR returns warnings for CIDR values in non-standard forms. This should
|
||||
// only be used with fields that are validated with IsValidCIDRForLegacyField().
|
||||
func GetWarningsForCIDR(fldPath *field.Path, value string) []string {
|
||||
ip, ipnet, err := netutils.ParseCIDRSloppy(value)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "GetWarningsForCIDR called on value that was not validated with IsValidCIDRForLegacyField", "field", fldPath, "value", value)
|
||||
return nil
|
||||
}
|
||||
|
||||
var warnings []string
|
||||
|
||||
// Check for bits set after prefix length
|
||||
if !ip.Equal(ipnet.IP) {
|
||||
_, addrlen := ipnet.Mask.Size()
|
||||
singleIPCIDR := fmt.Sprintf("%s/%d", ip.String(), addrlen)
|
||||
warnings = append(warnings,
|
||||
fmt.Sprintf("%s: CIDR value %q is ambiguous in this context (should be %q or %q?)", fldPath, value, ipnet.String(), singleIPCIDR),
|
||||
)
|
||||
}
|
||||
|
||||
prefix, _ := netip.ParsePrefix(value)
|
||||
addr := prefix.Addr()
|
||||
if !prefix.IsValid() || addr.Is4In6() {
|
||||
// This catches 2 cases: leading 0s (if ParseCIDRSloppy() accepted it but
|
||||
// ParsePrefix() doesn't) or IPv4-mapped IPv6 (.Is4In6()). Either way,
|
||||
// re-stringifying the net.IPNet value will give the preferred form.
|
||||
warnings = append(warnings,
|
||||
fmt.Sprintf("%s: non-standard CIDR value %q will be considered invalid in a future Kubernetes release: use %q", fldPath, value, ipnet.String()),
|
||||
)
|
||||
}
|
||||
|
||||
// If ParseCIDRSloppy() and ParsePrefix() both accept it then it's fully valid,
|
||||
// though it may be non-canonical. But only check this if there are no other
|
||||
// warnings, since either of the other warnings would also cause a round-trip
|
||||
// failure.
|
||||
if len(warnings) == 0 && addr.Is6() && prefix.String() != value {
|
||||
warnings = append(warnings,
|
||||
fmt.Sprintf("%s: IPv6 CIDR value %q should be in RFC 5952 canonical format (%q)", fldPath, value, prefix.String()),
|
||||
)
|
||||
}
|
||||
|
||||
return warnings
|
||||
}
|
||||
|
||||
// IsValidInterfaceAddress tests that the argument is a valid "ifaddr"-style CIDR value in
|
||||
// canonical form (e.g., "192.168.1.5/24", with a complete IP address and associated
|
||||
// subnet length). Use IsValidCIDR for "subnet"/"mask"-style CIDR values (e.g.,
|
||||
// "192.168.1.0/24").
|
||||
func IsValidInterfaceAddress(fldPath *field.Path, value string) field.ErrorList {
|
||||
var allErrors field.ErrorList
|
||||
ip, ipnet, err := netutils.ParseCIDRSloppy(value)
|
||||
if err != nil {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must be a valid address in CIDR form, (e.g. 10.9.8.7/24 or 2001:db8::1/64)"))
|
||||
return allErrors
|
||||
}
|
||||
|
||||
// The canonical form of `value` is not `ipnet.String()`, because `ipnet` doesn't
|
||||
// include the bits after the prefix. We need to construct the canonical form
|
||||
// ourselves from `ip` and `ipnet.Mask`.
|
||||
maskSize, _ := ipnet.Mask.Size()
|
||||
if netutils.IsIPv4(ip) && maskSize > net.IPv4len*8 {
|
||||
// "::ffff:192.168.0.1/120" -> "192.168.0.1/24"
|
||||
maskSize -= (net.IPv6len - net.IPv4len) * 8
|
||||
}
|
||||
canonical := fmt.Sprintf("%s/%d", ip.String(), maskSize)
|
||||
if value != canonical {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, fmt.Sprintf("must be in canonical form (%q)", canonical)))
|
||||
}
|
||||
return allErrors
|
||||
}
|
40
e2e/vendor/k8s.io/apimachinery/pkg/util/validation/validation.go
generated
vendored
40
e2e/vendor/k8s.io/apimachinery/pkg/util/validation/validation.go
generated
vendored
@ -24,7 +24,6 @@ import (
|
||||
"unicode"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
netutils "k8s.io/utils/net"
|
||||
)
|
||||
|
||||
const qnameCharFmt string = "[A-Za-z0-9]"
|
||||
@ -369,45 +368,6 @@ func IsValidPortName(port string) []string {
|
||||
return errs
|
||||
}
|
||||
|
||||
// IsValidIP tests that the argument is a valid IP address.
|
||||
func IsValidIP(fldPath *field.Path, value string) field.ErrorList {
|
||||
var allErrors field.ErrorList
|
||||
if netutils.ParseIPSloppy(value) == nil {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must be a valid IP address, (e.g. 10.9.8.7 or 2001:db8::ffff)"))
|
||||
}
|
||||
return allErrors
|
||||
}
|
||||
|
||||
// IsValidIPv4Address tests that the argument is a valid IPv4 address.
|
||||
func IsValidIPv4Address(fldPath *field.Path, value string) field.ErrorList {
|
||||
var allErrors field.ErrorList
|
||||
ip := netutils.ParseIPSloppy(value)
|
||||
if ip == nil || ip.To4() == nil {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must be a valid IPv4 address"))
|
||||
}
|
||||
return allErrors
|
||||
}
|
||||
|
||||
// IsValidIPv6Address tests that the argument is a valid IPv6 address.
|
||||
func IsValidIPv6Address(fldPath *field.Path, value string) field.ErrorList {
|
||||
var allErrors field.ErrorList
|
||||
ip := netutils.ParseIPSloppy(value)
|
||||
if ip == nil || ip.To4() != nil {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must be a valid IPv6 address"))
|
||||
}
|
||||
return allErrors
|
||||
}
|
||||
|
||||
// IsValidCIDR tests that the argument is a valid CIDR value.
|
||||
func IsValidCIDR(fldPath *field.Path, value string) field.ErrorList {
|
||||
var allErrors field.ErrorList
|
||||
_, _, err := netutils.ParseCIDRSloppy(value)
|
||||
if err != nil {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath, value, "must be a valid CIDR value, (e.g. 10.9.8.0/24 or 2001:db8::/64)"))
|
||||
}
|
||||
return allErrors
|
||||
}
|
||||
|
||||
const percentFmt string = "[0-9]+%"
|
||||
const percentErrMsg string = "a valid percent string must be a numeric string followed by an ending '%'"
|
||||
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/util/version/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/util/version/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package version provides utilities for version number comparisons
|
||||
package version // import "k8s.io/apimachinery/pkg/util/version"
|
||||
package version
|
||||
|
18
e2e/vendor/k8s.io/apimachinery/pkg/util/version/version.go
generated
vendored
18
e2e/vendor/k8s.io/apimachinery/pkg/util/version/version.go
generated
vendored
@ -33,7 +33,6 @@ type Version struct {
|
||||
semver bool
|
||||
preRelease string
|
||||
buildMetadata string
|
||||
info apimachineryversion.Info
|
||||
}
|
||||
|
||||
var (
|
||||
@ -456,27 +455,28 @@ func (v *Version) Compare(other string) (int, error) {
|
||||
return v.compareInternal(ov), nil
|
||||
}
|
||||
|
||||
// WithInfo returns copy of the version object with requested info
|
||||
// WithInfo returns copy of the version object.
|
||||
// Deprecated: The Info field has been removed from the Version struct. This method no longer modifies the Version object.
|
||||
func (v *Version) WithInfo(info apimachineryversion.Info) *Version {
|
||||
result := *v
|
||||
result.info = info
|
||||
return &result
|
||||
}
|
||||
|
||||
// Info returns the version information of a component.
|
||||
// Deprecated: Use Info() from effective version instead.
|
||||
func (v *Version) Info() *apimachineryversion.Info {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
// in case info is empty, or the major and minor in info is different from the actual major and minor
|
||||
v.info.Major = itoa(v.Major())
|
||||
v.info.Minor = itoa(v.Minor())
|
||||
if v.info.GitVersion == "" {
|
||||
v.info.GitVersion = v.String()
|
||||
return &apimachineryversion.Info{
|
||||
Major: Itoa(v.Major()),
|
||||
Minor: Itoa(v.Minor()),
|
||||
GitVersion: v.String(),
|
||||
}
|
||||
return &v.info
|
||||
}
|
||||
|
||||
func itoa(i uint) string {
|
||||
func Itoa(i uint) string {
|
||||
if i == 0 {
|
||||
return ""
|
||||
}
|
||||
|
50
e2e/vendor/k8s.io/apimachinery/pkg/util/wait/backoff.go
generated
vendored
50
e2e/vendor/k8s.io/apimachinery/pkg/util/wait/backoff.go
generated
vendored
@ -157,6 +157,8 @@ func (b Backoff) DelayWithReset(c clock.Clock, resetInterval time.Duration) Dela
|
||||
// Until is syntactic sugar on top of JitterUntil with zero jitter factor and
|
||||
// with sliding = true (which means the timer for period starts after the f
|
||||
// completes).
|
||||
//
|
||||
// Contextual logging: UntilWithContext should be used instead of Until in code which supports contextual logging.
|
||||
func Until(f func(), period time.Duration, stopCh <-chan struct{}) {
|
||||
JitterUntil(f, period, 0.0, true, stopCh)
|
||||
}
|
||||
@ -176,6 +178,8 @@ func UntilWithContext(ctx context.Context, f func(context.Context), period time.
|
||||
// NonSlidingUntil is syntactic sugar on top of JitterUntil with zero jitter
|
||||
// factor, with sliding = false (meaning the timer for period starts at the same
|
||||
// time as the function starts).
|
||||
//
|
||||
// Contextual logging: NonSlidingUntilWithContext should be used instead of NonSlidingUntil in code which supports contextual logging.
|
||||
func NonSlidingUntil(f func(), period time.Duration, stopCh <-chan struct{}) {
|
||||
JitterUntil(f, period, 0.0, false, stopCh)
|
||||
}
|
||||
@ -200,19 +204,44 @@ func NonSlidingUntilWithContext(ctx context.Context, f func(context.Context), pe
|
||||
//
|
||||
// Close stopCh to stop. f may not be invoked if stop channel is already
|
||||
// closed. Pass NeverStop to if you don't want it stop.
|
||||
//
|
||||
// Contextual logging: JitterUntilWithContext should be used instead of JitterUntil in code which supports contextual logging.
|
||||
func JitterUntil(f func(), period time.Duration, jitterFactor float64, sliding bool, stopCh <-chan struct{}) {
|
||||
BackoffUntil(f, NewJitteredBackoffManager(period, jitterFactor, &clock.RealClock{}), sliding, stopCh)
|
||||
}
|
||||
|
||||
// JitterUntilWithContext loops until context is done, running f every period.
|
||||
//
|
||||
// If jitterFactor is positive, the period is jittered before every run of f.
|
||||
// If jitterFactor is not positive, the period is unchanged and not jittered.
|
||||
//
|
||||
// If sliding is true, the period is computed after f runs. If it is false then
|
||||
// period includes the runtime for f.
|
||||
//
|
||||
// Cancel context to stop. f may not be invoked if context is already done.
|
||||
func JitterUntilWithContext(ctx context.Context, f func(context.Context), period time.Duration, jitterFactor float64, sliding bool) {
|
||||
BackoffUntilWithContext(ctx, f, NewJitteredBackoffManager(period, jitterFactor, &clock.RealClock{}), sliding)
|
||||
}
|
||||
|
||||
// BackoffUntil loops until stop channel is closed, run f every duration given by BackoffManager.
|
||||
//
|
||||
// If sliding is true, the period is computed after f runs. If it is false then
|
||||
// period includes the runtime for f.
|
||||
//
|
||||
// Contextual logging: BackoffUntilWithContext should be used instead of BackoffUntil in code which supports contextual logging.
|
||||
func BackoffUntil(f func(), backoff BackoffManager, sliding bool, stopCh <-chan struct{}) {
|
||||
BackoffUntilWithContext(ContextForChannel(stopCh), func(context.Context) { f() }, backoff, sliding)
|
||||
}
|
||||
|
||||
// BackoffUntilWithContext loops until context is done, run f every duration given by BackoffManager.
|
||||
//
|
||||
// If sliding is true, the period is computed after f runs. If it is false then
|
||||
// period includes the runtime for f.
|
||||
func BackoffUntilWithContext(ctx context.Context, f func(ctx context.Context), backoff BackoffManager, sliding bool) {
|
||||
var t clock.Timer
|
||||
for {
|
||||
select {
|
||||
case <-stopCh:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
}
|
||||
@ -222,8 +251,8 @@ func BackoffUntil(f func(), backoff BackoffManager, sliding bool, stopCh <-chan
|
||||
}
|
||||
|
||||
func() {
|
||||
defer runtime.HandleCrash()
|
||||
f()
|
||||
defer runtime.HandleCrashWithContext(ctx)
|
||||
f(ctx)
|
||||
}()
|
||||
|
||||
if sliding {
|
||||
@ -236,7 +265,7 @@ func BackoffUntil(f func(), backoff BackoffManager, sliding bool, stopCh <-chan
|
||||
// In order to mitigate we re-check stopCh at the beginning
|
||||
// of every loop to prevent extra executions of f().
|
||||
select {
|
||||
case <-stopCh:
|
||||
case <-ctx.Done():
|
||||
if !t.Stop() {
|
||||
<-t.C()
|
||||
}
|
||||
@ -246,19 +275,6 @@ func BackoffUntil(f func(), backoff BackoffManager, sliding bool, stopCh <-chan
|
||||
}
|
||||
}
|
||||
|
||||
// JitterUntilWithContext loops until context is done, running f every period.
|
||||
//
|
||||
// If jitterFactor is positive, the period is jittered before every run of f.
|
||||
// If jitterFactor is not positive, the period is unchanged and not jittered.
|
||||
//
|
||||
// If sliding is true, the period is computed after f runs. If it is false then
|
||||
// period includes the runtime for f.
|
||||
//
|
||||
// Cancel context to stop. f may not be invoked if context is already expired.
|
||||
func JitterUntilWithContext(ctx context.Context, f func(context.Context), period time.Duration, jitterFactor float64, sliding bool) {
|
||||
JitterUntil(func() { f(ctx) }, period, jitterFactor, sliding, ctx.Done())
|
||||
}
|
||||
|
||||
// backoffManager provides simple backoff behavior in a threadsafe manner to a caller.
|
||||
type backoffManager struct {
|
||||
backoff Backoff
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/util/wait/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/util/wait/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package wait provides tools for polling or listening for changes
|
||||
// to a condition.
|
||||
package wait // import "k8s.io/apimachinery/pkg/util/wait"
|
||||
package wait
|
||||
|
4
e2e/vendor/k8s.io/apimachinery/pkg/util/wait/loop.go
generated
vendored
4
e2e/vendor/k8s.io/apimachinery/pkg/util/wait/loop.go
generated
vendored
@ -49,7 +49,7 @@ func loopConditionUntilContext(ctx context.Context, t Timer, immediate, sliding
|
||||
// if we haven't requested immediate execution, delay once
|
||||
if immediate {
|
||||
if ok, err := func() (bool, error) {
|
||||
defer runtime.HandleCrash()
|
||||
defer runtime.HandleCrashWithContext(ctx)
|
||||
return condition(ctx)
|
||||
}(); err != nil || ok {
|
||||
return err
|
||||
@ -83,7 +83,7 @@ func loopConditionUntilContext(ctx context.Context, t Timer, immediate, sliding
|
||||
t.Next()
|
||||
}
|
||||
if ok, err := func() (bool, error) {
|
||||
defer runtime.HandleCrash()
|
||||
defer runtime.HandleCrashWithContext(ctx)
|
||||
return condition(ctx)
|
||||
}(); err != nil || ok {
|
||||
return err
|
||||
|
9
e2e/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go
generated
vendored
9
e2e/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go
generated
vendored
@ -80,6 +80,10 @@ func Forever(f func(), period time.Duration) {
|
||||
Until(f, period, NeverStop)
|
||||
}
|
||||
|
||||
// jitterRand is a dedicated random source for jitter calculations.
|
||||
// It defaults to rand.Float64, but is a package variable so it can be overridden to make unit tests deterministic.
|
||||
var jitterRand = rand.Float64
|
||||
|
||||
// Jitter returns a time.Duration between duration and duration + maxFactor *
|
||||
// duration.
|
||||
//
|
||||
@ -89,7 +93,7 @@ func Jitter(duration time.Duration, maxFactor float64) time.Duration {
|
||||
if maxFactor <= 0.0 {
|
||||
maxFactor = 1.0
|
||||
}
|
||||
wait := duration + time.Duration(rand.Float64()*maxFactor*float64(duration))
|
||||
wait := duration + time.Duration(jitterRand()*maxFactor*float64(duration))
|
||||
return wait
|
||||
}
|
||||
|
||||
@ -141,6 +145,7 @@ func (c channelContext) Value(key any) any { return nil }
|
||||
//
|
||||
// Deprecated: Will be removed when the legacy polling methods are removed.
|
||||
func runConditionWithCrashProtection(condition ConditionFunc) (bool, error) {
|
||||
//nolint:logcheck // Already deprecated.
|
||||
defer runtime.HandleCrash()
|
||||
return condition()
|
||||
}
|
||||
@ -150,7 +155,7 @@ func runConditionWithCrashProtection(condition ConditionFunc) (bool, error) {
|
||||
//
|
||||
// Deprecated: Will be removed when the legacy polling methods are removed.
|
||||
func runConditionWithCrashProtectionWithContext(ctx context.Context, condition ConditionWithContextFunc) (bool, error) {
|
||||
defer runtime.HandleCrash()
|
||||
defer runtime.HandleCrashWithContext(ctx)
|
||||
return condition(ctx)
|
||||
}
|
||||
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/util/waitgroup/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/util/waitgroup/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package waitgroup implements SafeWaitGroup wrap of sync.WaitGroup.
|
||||
// Add with positive delta when waiting will fail, to prevent sync.WaitGroup race issue.
|
||||
package waitgroup // import "k8s.io/apimachinery/pkg/util/waitgroup"
|
||||
package waitgroup
|
||||
|
163
e2e/vendor/k8s.io/apimachinery/pkg/util/yaml/decoder.go
generated
vendored
163
e2e/vendor/k8s.io/apimachinery/pkg/util/yaml/decoder.go
generated
vendored
@ -20,10 +20,12 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
jsonutil "k8s.io/apimachinery/pkg/util/json"
|
||||
|
||||
@ -92,7 +94,7 @@ func UnmarshalStrict(data []byte, v interface{}) error {
|
||||
// YAML decoding path is not used (so that error messages are
|
||||
// JSON specific).
|
||||
func ToJSON(data []byte) ([]byte, error) {
|
||||
if hasJSONPrefix(data) {
|
||||
if IsJSONBuffer(data) {
|
||||
return data, nil
|
||||
}
|
||||
return yaml.YAMLToJSON(data)
|
||||
@ -102,7 +104,8 @@ func ToJSON(data []byte) ([]byte, error) {
|
||||
// separating individual documents. It first converts the YAML
|
||||
// body to JSON, then unmarshals the JSON.
|
||||
type YAMLToJSONDecoder struct {
|
||||
reader Reader
|
||||
reader Reader
|
||||
inputOffset int
|
||||
}
|
||||
|
||||
// NewYAMLToJSONDecoder decodes YAML documents from the provided
|
||||
@ -121,7 +124,7 @@ func NewYAMLToJSONDecoder(r io.Reader) *YAMLToJSONDecoder {
|
||||
// yaml.Unmarshal.
|
||||
func (d *YAMLToJSONDecoder) Decode(into interface{}) error {
|
||||
bytes, err := d.reader.Read()
|
||||
if err != nil && err != io.EOF {
|
||||
if err != nil && err != io.EOF { //nolint:errorlint
|
||||
return err
|
||||
}
|
||||
|
||||
@ -131,9 +134,14 @@ func (d *YAMLToJSONDecoder) Decode(into interface{}) error {
|
||||
return YAMLSyntaxError{err}
|
||||
}
|
||||
}
|
||||
d.inputOffset += len(bytes)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *YAMLToJSONDecoder) InputOffset() int {
|
||||
return d.inputOffset
|
||||
}
|
||||
|
||||
// YAMLDecoder reads chunks of objects and returns ErrShortBuffer if
|
||||
// the data is not sufficient.
|
||||
type YAMLDecoder struct {
|
||||
@ -229,18 +237,20 @@ func splitYAMLDocument(data []byte, atEOF bool) (advance int, token []byte, err
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
// decoder is a convenience interface for Decode.
|
||||
type decoder interface {
|
||||
Decode(into interface{}) error
|
||||
}
|
||||
|
||||
// YAMLOrJSONDecoder attempts to decode a stream of JSON documents or
|
||||
// YAML documents by sniffing for a leading { character.
|
||||
// YAMLOrJSONDecoder attempts to decode a stream of JSON or YAML documents.
|
||||
// While JSON is YAML, the way Go's JSON decode defines a multi-document stream
|
||||
// is a series of JSON objects (e.g. {}{}), but YAML defines a multi-document
|
||||
// stream as a series of documents separated by "---".
|
||||
//
|
||||
// This decoder will attempt to decode the stream as JSON first, and if that
|
||||
// fails, it will switch to YAML. Once it determines the stream is JSON (by
|
||||
// finding a non-YAML-delimited series of objects), it will not switch to YAML.
|
||||
// Once it switches to YAML it will not switch back to JSON.
|
||||
type YAMLOrJSONDecoder struct {
|
||||
r io.Reader
|
||||
bufferSize int
|
||||
|
||||
decoder decoder
|
||||
json *json.Decoder
|
||||
yaml *YAMLToJSONDecoder
|
||||
stream *StreamReader
|
||||
count int // how many objects have been decoded
|
||||
}
|
||||
|
||||
type JSONSyntaxError struct {
|
||||
@ -265,31 +275,108 @@ func (e YAMLSyntaxError) Error() string {
|
||||
// how far into the stream the decoder will look to figure out whether this
|
||||
// is a JSON stream (has whitespace followed by an open brace).
|
||||
func NewYAMLOrJSONDecoder(r io.Reader, bufferSize int) *YAMLOrJSONDecoder {
|
||||
return &YAMLOrJSONDecoder{
|
||||
r: r,
|
||||
bufferSize: bufferSize,
|
||||
d := &YAMLOrJSONDecoder{}
|
||||
|
||||
reader, _, mightBeJSON := GuessJSONStream(r, bufferSize)
|
||||
d.stream = reader
|
||||
if mightBeJSON {
|
||||
d.json = json.NewDecoder(reader)
|
||||
} else {
|
||||
d.yaml = NewYAMLToJSONDecoder(reader)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// Decode unmarshals the next object from the underlying stream into the
|
||||
// provide object, or returns an error.
|
||||
func (d *YAMLOrJSONDecoder) Decode(into interface{}) error {
|
||||
if d.decoder == nil {
|
||||
buffer, _, isJSON := GuessJSONStream(d.r, d.bufferSize)
|
||||
if isJSON {
|
||||
d.decoder = json.NewDecoder(buffer)
|
||||
// Because we don't know if this is a JSON or YAML stream, a failure from
|
||||
// both decoders is ambiguous. When in doubt, it will return the error from
|
||||
// the JSON decoder. Unfortunately, this means that if the first document
|
||||
// is invalid YAML, the error won't be awesome.
|
||||
// TODO: the errors from YAML are not great, we could improve them a lot.
|
||||
var firstErr error
|
||||
if d.json != nil {
|
||||
err := d.json.Decode(into)
|
||||
if err == nil {
|
||||
d.stream.Consume(int(d.json.InputOffset()) - d.stream.Consumed())
|
||||
d.count++
|
||||
return nil
|
||||
}
|
||||
if err == io.EOF { //nolint:errorlint
|
||||
return err
|
||||
}
|
||||
var syntax *json.SyntaxError
|
||||
if ok := errors.As(err, &syntax); ok {
|
||||
firstErr = JSONSyntaxError{
|
||||
Offset: syntax.Offset,
|
||||
Err: syntax,
|
||||
}
|
||||
} else {
|
||||
d.decoder = NewYAMLToJSONDecoder(buffer)
|
||||
firstErr = err
|
||||
}
|
||||
if d.count > 1 {
|
||||
// If we found 0 or 1 JSON object(s), this stream is still
|
||||
// ambiguous. But if we found more than 1 JSON object, then this
|
||||
// is an unambiguous JSON stream, and we should not switch to YAML.
|
||||
return err
|
||||
}
|
||||
// If JSON decoding hits the end of one object and then fails on the
|
||||
// next, it leaves any leading whitespace in the buffer, which can
|
||||
// confuse the YAML decoder. We just eat any whitespace we find, up to
|
||||
// and including the first newline.
|
||||
d.stream.Rewind()
|
||||
if err := d.consumeWhitespace(); err == nil {
|
||||
d.yaml = NewYAMLToJSONDecoder(d.stream)
|
||||
}
|
||||
d.json = nil
|
||||
}
|
||||
if d.yaml != nil {
|
||||
err := d.yaml.Decode(into)
|
||||
if err == nil {
|
||||
d.stream.Consume(d.yaml.InputOffset() - d.stream.Consumed())
|
||||
d.count++
|
||||
return nil
|
||||
}
|
||||
if err == io.EOF { //nolint:errorlint
|
||||
return err
|
||||
}
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
err := d.decoder.Decode(into)
|
||||
if syntax, ok := err.(*json.SyntaxError); ok {
|
||||
return JSONSyntaxError{
|
||||
Offset: syntax.Offset,
|
||||
Err: syntax,
|
||||
if firstErr != nil {
|
||||
return firstErr
|
||||
}
|
||||
return fmt.Errorf("decoding failed as both JSON and YAML")
|
||||
}
|
||||
|
||||
func (d *YAMLOrJSONDecoder) consumeWhitespace() error {
|
||||
consumed := 0
|
||||
for {
|
||||
buf, err := d.stream.ReadN(4)
|
||||
if err != nil && err == io.EOF { //nolint:errorlint
|
||||
return err
|
||||
}
|
||||
r, sz := utf8.DecodeRune(buf)
|
||||
if r == utf8.RuneError || sz == 0 {
|
||||
return fmt.Errorf("invalid utf8 rune")
|
||||
}
|
||||
d.stream.RewindN(len(buf) - sz)
|
||||
if !unicode.IsSpace(r) {
|
||||
d.stream.RewindN(sz)
|
||||
d.stream.Consume(consumed)
|
||||
return nil
|
||||
}
|
||||
if r == '\n' {
|
||||
d.stream.Consume(consumed)
|
||||
return nil
|
||||
}
|
||||
if err == io.EOF { //nolint:errorlint
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
return io.EOF
|
||||
}
|
||||
|
||||
type Reader interface {
|
||||
@ -311,7 +398,7 @@ func (r *YAMLReader) Read() ([]byte, error) {
|
||||
var buffer bytes.Buffer
|
||||
for {
|
||||
line, err := r.reader.Read()
|
||||
if err != nil && err != io.EOF {
|
||||
if err != nil && err != io.EOF { //nolint:errorlint
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -329,11 +416,11 @@ func (r *YAMLReader) Read() ([]byte, error) {
|
||||
if buffer.Len() != 0 {
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
if err == io.EOF {
|
||||
if err == io.EOF { //nolint:errorlint
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err == io.EOF {
|
||||
if err == io.EOF { //nolint:errorlint
|
||||
if buffer.Len() != 0 {
|
||||
// If we're at EOF, we have a final, non-terminated line. Return it.
|
||||
return buffer.Bytes(), nil
|
||||
@ -369,26 +456,20 @@ func (r *LineReader) Read() ([]byte, error) {
|
||||
// GuessJSONStream scans the provided reader up to size, looking
|
||||
// for an open brace indicating this is JSON. It will return the
|
||||
// bufio.Reader it creates for the consumer.
|
||||
func GuessJSONStream(r io.Reader, size int) (io.Reader, []byte, bool) {
|
||||
buffer := bufio.NewReaderSize(r, size)
|
||||
func GuessJSONStream(r io.Reader, size int) (*StreamReader, []byte, bool) {
|
||||
buffer := NewStreamReader(r, size)
|
||||
b, _ := buffer.Peek(size)
|
||||
return buffer, b, hasJSONPrefix(b)
|
||||
return buffer, b, IsJSONBuffer(b)
|
||||
}
|
||||
|
||||
// IsJSONBuffer scans the provided buffer, looking
|
||||
// for an open brace indicating this is JSON.
|
||||
func IsJSONBuffer(buf []byte) bool {
|
||||
return hasJSONPrefix(buf)
|
||||
return hasPrefix(buf, jsonPrefix)
|
||||
}
|
||||
|
||||
var jsonPrefix = []byte("{")
|
||||
|
||||
// hasJSONPrefix returns true if the provided buffer appears to start with
|
||||
// a JSON open brace.
|
||||
func hasJSONPrefix(buf []byte) bool {
|
||||
return hasPrefix(buf, jsonPrefix)
|
||||
}
|
||||
|
||||
// Return true if the first non-whitespace bytes in buf is
|
||||
// prefix.
|
||||
func hasPrefix(buf []byte, prefix []byte) bool {
|
||||
|
130
e2e/vendor/k8s.io/apimachinery/pkg/util/yaml/stream_reader.go
generated
vendored
Normal file
130
e2e/vendor/k8s.io/apimachinery/pkg/util/yaml/stream_reader.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
Copyright 2025 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package yaml
|
||||
|
||||
import "io"
|
||||
|
||||
// StreamReader is a reader designed for consuming streams of variable-length
|
||||
// messages. It buffers data until it is explicitly consumed, and can be
|
||||
// rewound to re-read previous data.
|
||||
type StreamReader struct {
|
||||
r io.Reader
|
||||
buf []byte
|
||||
head int // current read offset into buf
|
||||
ttlConsumed int // number of bytes which have been consumed
|
||||
}
|
||||
|
||||
// NewStreamReader creates a new StreamReader wrapping the provided
|
||||
// io.Reader.
|
||||
func NewStreamReader(r io.Reader, size int) *StreamReader {
|
||||
if size == 0 {
|
||||
size = 4096
|
||||
}
|
||||
return &StreamReader{
|
||||
r: r,
|
||||
buf: make([]byte, 0, size), // Start with a reasonable capacity
|
||||
}
|
||||
}
|
||||
|
||||
// Read implements io.Reader. It first returns any buffered data after the
|
||||
// current offset, and if that's exhausted, reads from the underlying reader
|
||||
// and buffers the data. The returned data is not considered consumed until the
|
||||
// Consume method is called.
|
||||
func (r *StreamReader) Read(p []byte) (n int, err error) {
|
||||
// If we have buffered data, return it
|
||||
if r.head < len(r.buf) {
|
||||
n = copy(p, r.buf[r.head:])
|
||||
r.head += n
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// If we've already hit EOF, return it
|
||||
if r.r == nil {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
// Read from the underlying reader
|
||||
n, err = r.r.Read(p)
|
||||
if n > 0 {
|
||||
r.buf = append(r.buf, p[:n]...)
|
||||
r.head += n
|
||||
}
|
||||
if err == nil {
|
||||
return n, nil
|
||||
}
|
||||
if err == io.EOF {
|
||||
// Store that we've hit EOF by setting r to nil
|
||||
r.r = nil
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// ReadN reads exactly n bytes from the reader, blocking until all bytes are
|
||||
// read or an error occurs. If an error occurs, the number of bytes read is
|
||||
// returned along with the error. If EOF is hit before n bytes are read, this
|
||||
// will return the bytes read so far, along with io.EOF. The returned data is
|
||||
// not considered consumed until the Consume method is called.
|
||||
func (r *StreamReader) ReadN(want int) ([]byte, error) {
|
||||
ret := make([]byte, want)
|
||||
off := 0
|
||||
for off < want {
|
||||
n, err := r.Read(ret[off:])
|
||||
if err != nil {
|
||||
return ret[:off+n], err
|
||||
}
|
||||
off += n
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Peek returns the next n bytes without advancing the reader. The returned
|
||||
// bytes are valid until the next call to Consume.
|
||||
func (r *StreamReader) Peek(n int) ([]byte, error) {
|
||||
buf, err := r.ReadN(n)
|
||||
r.RewindN(len(buf))
|
||||
if err != nil {
|
||||
return buf, err
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
// Rewind resets the reader to the beginning of the buffered data.
|
||||
func (r *StreamReader) Rewind() {
|
||||
r.head = 0
|
||||
}
|
||||
|
||||
// RewindN rewinds the reader by n bytes. If n is greater than the current
|
||||
// buffer, the reader is rewound to the beginning of the buffer.
|
||||
func (r *StreamReader) RewindN(n int) {
|
||||
r.head -= min(n, r.head)
|
||||
}
|
||||
|
||||
// Consume discards up to n bytes of previously read data from the beginning of
|
||||
// the buffer. Once consumed, that data is no longer available for rewinding.
|
||||
// If n is greater than the current buffer, the buffer is cleared. Consume
|
||||
// never consume data from the underlying reader.
|
||||
func (r *StreamReader) Consume(n int) {
|
||||
n = min(n, len(r.buf))
|
||||
r.buf = r.buf[n:]
|
||||
r.head -= n
|
||||
r.ttlConsumed += n
|
||||
}
|
||||
|
||||
// Consumed returns the number of bytes consumed from the input reader.
|
||||
func (r *StreamReader) Consumed() int {
|
||||
return r.ttlConsumed
|
||||
}
|
4
e2e/vendor/k8s.io/apimachinery/pkg/version/doc.go
generated
vendored
4
e2e/vendor/k8s.io/apimachinery/pkg/version/doc.go
generated
vendored
@ -16,5 +16,5 @@ limitations under the License.
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
|
||||
// Package version supplies the type for version information collected at build time.
|
||||
package version // import "k8s.io/apimachinery/pkg/version"
|
||||
// Package version supplies the type for version information.
|
||||
package version
|
||||
|
28
e2e/vendor/k8s.io/apimachinery/pkg/version/types.go
generated
vendored
28
e2e/vendor/k8s.io/apimachinery/pkg/version/types.go
generated
vendored
@ -20,15 +20,25 @@ package version
|
||||
// TODO: Add []string of api versions supported? It's still unclear
|
||||
// how we'll want to distribute that information.
|
||||
type Info struct {
|
||||
Major string `json:"major"`
|
||||
Minor string `json:"minor"`
|
||||
GitVersion string `json:"gitVersion"`
|
||||
GitCommit string `json:"gitCommit"`
|
||||
GitTreeState string `json:"gitTreeState"`
|
||||
BuildDate string `json:"buildDate"`
|
||||
GoVersion string `json:"goVersion"`
|
||||
Compiler string `json:"compiler"`
|
||||
Platform string `json:"platform"`
|
||||
// Major is the major version of the binary version
|
||||
Major string `json:"major"`
|
||||
// Minor is the minor version of the binary version
|
||||
Minor string `json:"minor"`
|
||||
// EmulationMajor is the major version of the emulation version
|
||||
EmulationMajor string `json:"emulationMajor,omitempty"`
|
||||
// EmulationMinor is the minor version of the emulation version
|
||||
EmulationMinor string `json:"emulationMinor,omitempty"`
|
||||
// MinCompatibilityMajor is the major version of the minimum compatibility version
|
||||
MinCompatibilityMajor string `json:"minCompatibilityMajor,omitempty"`
|
||||
// MinCompatibilityMinor is the minor version of the minimum compatibility version
|
||||
MinCompatibilityMinor string `json:"minCompatibilityMinor,omitempty"`
|
||||
GitVersion string `json:"gitVersion"`
|
||||
GitCommit string `json:"gitCommit"`
|
||||
GitTreeState string `json:"gitTreeState"`
|
||||
BuildDate string `json:"buildDate"`
|
||||
GoVersion string `json:"goVersion"`
|
||||
Compiler string `json:"compiler"`
|
||||
Platform string `json:"platform"`
|
||||
}
|
||||
|
||||
// String returns info as a human-friendly version string.
|
||||
|
2
e2e/vendor/k8s.io/apimachinery/pkg/watch/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apimachinery/pkg/watch/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package watch contains a generic watchable interface, and a fake for
|
||||
// testing code that uses the watch interface.
|
||||
package watch // import "k8s.io/apimachinery/pkg/watch"
|
||||
package watch
|
||||
|
15
e2e/vendor/k8s.io/apimachinery/pkg/watch/streamwatcher.go
generated
vendored
15
e2e/vendor/k8s.io/apimachinery/pkg/watch/streamwatcher.go
generated
vendored
@ -51,6 +51,7 @@ type Reporter interface {
|
||||
// StreamWatcher turns any stream for which you can write a Decoder interface
|
||||
// into a watch.Interface.
|
||||
type StreamWatcher struct {
|
||||
logger klog.Logger
|
||||
sync.Mutex
|
||||
source Decoder
|
||||
reporter Reporter
|
||||
@ -59,8 +60,16 @@ type StreamWatcher struct {
|
||||
}
|
||||
|
||||
// NewStreamWatcher creates a StreamWatcher from the given decoder.
|
||||
//
|
||||
// Contextual logging: NewStreamWatcherWithLogger should be used instead of NewStreamWatcher in code which supports contextual logging.
|
||||
func NewStreamWatcher(d Decoder, r Reporter) *StreamWatcher {
|
||||
return NewStreamWatcherWithLogger(klog.Background(), d, r)
|
||||
}
|
||||
|
||||
// NewStreamWatcherWithLogger creates a StreamWatcher from the given decoder and logger.
|
||||
func NewStreamWatcherWithLogger(logger klog.Logger, d Decoder, r Reporter) *StreamWatcher {
|
||||
sw := &StreamWatcher{
|
||||
logger: logger,
|
||||
source: d,
|
||||
reporter: r,
|
||||
// It's easy for a consumer to add buffering via an extra
|
||||
@ -98,7 +107,7 @@ func (sw *StreamWatcher) Stop() {
|
||||
|
||||
// receive reads result from the decoder in a loop and sends down the result channel.
|
||||
func (sw *StreamWatcher) receive() {
|
||||
defer utilruntime.HandleCrash()
|
||||
defer utilruntime.HandleCrashWithLogger(sw.logger)
|
||||
defer close(sw.result)
|
||||
defer sw.Stop()
|
||||
for {
|
||||
@ -108,10 +117,10 @@ func (sw *StreamWatcher) receive() {
|
||||
case io.EOF:
|
||||
// watch closed normally
|
||||
case io.ErrUnexpectedEOF:
|
||||
klog.V(1).Infof("Unexpected EOF during watch stream event decoding: %v", err)
|
||||
sw.logger.V(1).Info("Unexpected EOF during watch stream event decoding", "err", err)
|
||||
default:
|
||||
if net.IsProbableEOF(err) || net.IsTimeout(err) {
|
||||
klog.V(5).Infof("Unable to decode an event from the watch stream: %v", err)
|
||||
sw.logger.V(5).Info("Unable to decode an event from the watch stream", "err", err)
|
||||
} else {
|
||||
select {
|
||||
case <-sw.done:
|
||||
|
37
e2e/vendor/k8s.io/apimachinery/pkg/watch/watch.go
generated
vendored
37
e2e/vendor/k8s.io/apimachinery/pkg/watch/watch.go
generated
vendored
@ -23,6 +23,7 @@ import (
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/utils/ptr"
|
||||
)
|
||||
|
||||
// Interface can be implemented by anything that knows how to watch and report changes.
|
||||
@ -103,21 +104,34 @@ func (w emptyWatch) ResultChan() <-chan Event {
|
||||
|
||||
// FakeWatcher lets you test anything that consumes a watch.Interface; threadsafe.
|
||||
type FakeWatcher struct {
|
||||
logger klog.Logger
|
||||
result chan Event
|
||||
stopped bool
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
var _ Interface = &FakeWatcher{}
|
||||
|
||||
// Contextual logging: NewFakeWithOptions and a logger in the FakeOptions should be used instead in code which supports contextual logging.
|
||||
func NewFake() *FakeWatcher {
|
||||
return NewFakeWithOptions(FakeOptions{})
|
||||
}
|
||||
|
||||
// Contextual logging: NewFakeWithOptions and a logger in the FakeOptions should be used instead in code which supports contextual logging.
|
||||
func NewFakeWithChanSize(size int, blocking bool) *FakeWatcher {
|
||||
return NewFakeWithOptions(FakeOptions{ChannelSize: size})
|
||||
}
|
||||
|
||||
func NewFakeWithOptions(options FakeOptions) *FakeWatcher {
|
||||
return &FakeWatcher{
|
||||
result: make(chan Event),
|
||||
logger: ptr.Deref(options.Logger, klog.Background()),
|
||||
result: make(chan Event, options.ChannelSize),
|
||||
}
|
||||
}
|
||||
|
||||
func NewFakeWithChanSize(size int, blocking bool) *FakeWatcher {
|
||||
return &FakeWatcher{
|
||||
result: make(chan Event, size),
|
||||
}
|
||||
type FakeOptions struct {
|
||||
Logger *klog.Logger
|
||||
ChannelSize int
|
||||
}
|
||||
|
||||
// Stop implements Interface.Stop().
|
||||
@ -125,7 +139,7 @@ func (f *FakeWatcher) Stop() {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
if !f.stopped {
|
||||
klog.V(4).Infof("Stopping fake watcher.")
|
||||
f.logger.V(4).Info("Stopping fake watcher")
|
||||
close(f.result)
|
||||
f.stopped = true
|
||||
}
|
||||
@ -176,13 +190,22 @@ func (f *FakeWatcher) Action(action EventType, obj runtime.Object) {
|
||||
|
||||
// RaceFreeFakeWatcher lets you test anything that consumes a watch.Interface; threadsafe.
|
||||
type RaceFreeFakeWatcher struct {
|
||||
logger klog.Logger
|
||||
result chan Event
|
||||
Stopped bool
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
var _ Interface = &RaceFreeFakeWatcher{}
|
||||
|
||||
// Contextual logging: RaceFreeFakeWatcherWithLogger should be used instead of NewRaceFreeFake in code which supports contextual logging.
|
||||
func NewRaceFreeFake() *RaceFreeFakeWatcher {
|
||||
return NewRaceFreeFakeWithLogger(klog.Background())
|
||||
}
|
||||
|
||||
func NewRaceFreeFakeWithLogger(logger klog.Logger) *RaceFreeFakeWatcher {
|
||||
return &RaceFreeFakeWatcher{
|
||||
logger: logger,
|
||||
result: make(chan Event, DefaultChanSize),
|
||||
}
|
||||
}
|
||||
@ -192,7 +215,7 @@ func (f *RaceFreeFakeWatcher) Stop() {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
if !f.Stopped {
|
||||
klog.V(4).Infof("Stopping fake watcher.")
|
||||
f.logger.V(4).Info("Stopping fake watcher")
|
||||
close(f.result)
|
||||
f.Stopped = true
|
||||
}
|
||||
|
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
|
||||
package webhookadmission // import "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission"
|
||||
package webhookadmission
|
||||
|
@ -20,4 +20,4 @@ limitations under the License.
|
||||
// +groupName=apiserver.config.k8s.io
|
||||
|
||||
// Package v1 is the v1 version of the API.
|
||||
package v1 // import "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1"
|
||||
package v1
|
||||
|
@ -20,4 +20,4 @@ limitations under the License.
|
||||
// +groupName=apiserver.config.k8s.io
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the API.
|
||||
package v1alpha1 // import "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1"
|
||||
package v1alpha1
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/errors/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/errors/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package errors contains utilities for admission webhook specific errors
|
||||
package errors // import "k8s.io/apiserver/pkg/admission/plugin/webhook/errors"
|
||||
package errors
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package mutating makes calls to mutating webhooks during the admission
|
||||
// process.
|
||||
package mutating // import "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating"
|
||||
package mutating
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/predicates/namespace/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/predicates/namespace/doc.go
generated
vendored
@ -17,4 +17,4 @@ limitations under the License.
|
||||
// Package namespace defines the utilities that are used by the webhook
|
||||
// plugin to decide if a webhook should be applied to an object based on its
|
||||
// namespace.
|
||||
package namespace // import "k8s.io/apiserver/pkg/admission/plugin/webhook/predicates/namespace"
|
||||
package namespace
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/predicates/object/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/predicates/object/doc.go
generated
vendored
@ -17,4 +17,4 @@ limitations under the License.
|
||||
// Package object defines the utilities that are used by the webhook plugin to
|
||||
// decide if a webhook should run, as long as either the old object or the new
|
||||
// object has labels matching the webhook config's objectSelector.
|
||||
package object // import "k8s.io/apiserver/pkg/admission/plugin/webhook/predicates/object"
|
||||
package object
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/request/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/request/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package request creates admissionReview request based on admission attributes.
|
||||
package request // import "k8s.io/apiserver/pkg/admission/plugin/webhook/request"
|
||||
package request
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/validating/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package validating makes calls to validating (i.e., non-mutating) webhooks
|
||||
// during the admission process.
|
||||
package validating // import "k8s.io/apiserver/pkg/admission/plugin/webhook/validating"
|
||||
package validating
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/apis/apidiscovery/v2/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/apis/apidiscovery/v2/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// +groupName=apidiscovery.k8s.io
|
||||
|
||||
package v2 // import "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
|
||||
package v2
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/apis/apiserver/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/apis/apiserver/doc.go
generated
vendored
@ -18,4 +18,4 @@ limitations under the License.
|
||||
// +groupName=apiserver.k8s.io
|
||||
|
||||
// Package apiserver is the internal version of the API.
|
||||
package apiserver // import "k8s.io/apiserver/pkg/apis/apiserver"
|
||||
package apiserver
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/apis/apiserver/v1/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/apis/apiserver/v1/doc.go
generated
vendored
@ -20,4 +20,4 @@ limitations under the License.
|
||||
// +groupName=apiserver.config.k8s.io
|
||||
|
||||
// Package v1 is the v1 version of the API.
|
||||
package v1 // import "k8s.io/apiserver/pkg/apis/apiserver/v1"
|
||||
package v1
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/doc.go
generated
vendored
@ -21,4 +21,4 @@ limitations under the License.
|
||||
// +groupName=apiserver.config.k8s.io
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the API.
|
||||
package v1alpha1 // import "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"
|
||||
package v1alpha1
|
||||
|
4
e2e/vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/types.go
generated
vendored
4
e2e/vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/types.go
generated
vendored
@ -352,7 +352,9 @@ type ClaimMappings struct {
|
||||
// If username.expression uses 'claims.email', then 'claims.email_verified' must be used in
|
||||
// username.expression or extra[*].valueExpression or claimValidationRules[*].expression.
|
||||
// An example claim validation rule expression that matches the validation automatically
|
||||
// applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true)'.
|
||||
// applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true) == true'. By explicitly comparing
|
||||
// the value to true, we let type-checking see the result will be a boolean, and to make sure a non-boolean email_verified
|
||||
// claim will be caught at runtime.
|
||||
//
|
||||
// In the flag based approach, the --oidc-username-claim and --oidc-username-prefix are optional. If --oidc-username-claim is not set,
|
||||
// the default value is "sub". For the authentication config, there is no defaulting for claim or prefix. The claim and prefix must be set explicitly.
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/doc.go
generated
vendored
@ -20,4 +20,4 @@ limitations under the License.
|
||||
// +groupName=apiserver.k8s.io
|
||||
|
||||
// Package v1beta1 is the v1beta1 version of the API.
|
||||
package v1beta1 // import "k8s.io/apiserver/pkg/apis/apiserver/v1beta1"
|
||||
package v1beta1
|
||||
|
4
e2e/vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/types.go
generated
vendored
4
e2e/vendor/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/types.go
generated
vendored
@ -323,7 +323,9 @@ type ClaimMappings struct {
|
||||
// If username.expression uses 'claims.email', then 'claims.email_verified' must be used in
|
||||
// username.expression or extra[*].valueExpression or claimValidationRules[*].expression.
|
||||
// An example claim validation rule expression that matches the validation automatically
|
||||
// applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true)'.
|
||||
// applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true) == true'. By explicitly comparing
|
||||
// the value to true, we let type-checking see the result will be a boolean, and to make sure a non-boolean email_verified
|
||||
// claim will be caught at runtime.
|
||||
//
|
||||
// In the flag based approach, the --oidc-username-claim and --oidc-username-prefix are optional. If --oidc-username-claim is not set,
|
||||
// the default value is "sub". For the authentication config, there is no defaulting for claim or prefix. The claim and prefix must be set explicitly.
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/apis/audit/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/apis/audit/doc.go
generated
vendored
@ -17,4 +17,4 @@ limitations under the License.
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +groupName=audit.k8s.io
|
||||
|
||||
package audit // import "k8s.io/apiserver/pkg/apis/audit"
|
||||
package audit
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/apis/audit/v1/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/apis/audit/v1/doc.go
generated
vendored
@ -22,4 +22,4 @@ limitations under the License.
|
||||
|
||||
// +groupName=audit.k8s.io
|
||||
|
||||
package v1 // import "k8s.io/apiserver/pkg/apis/audit/v1"
|
||||
package v1
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/authentication/request/x509/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/authentication/request/x509/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package x509 provides a request authenticator that validates and
|
||||
// extracts user information from client certificates
|
||||
package x509 // import "k8s.io/apiserver/pkg/authentication/request/x509"
|
||||
package x509
|
||||
|
39
e2e/vendor/k8s.io/apiserver/pkg/authentication/request/x509/x509.go
generated
vendored
39
e2e/vendor/k8s.io/apiserver/pkg/authentication/request/x509/x509.go
generated
vendored
@ -21,15 +21,19 @@ import (
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
asn1util "k8s.io/apimachinery/pkg/apis/asn1"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/component-base/metrics"
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
)
|
||||
@ -281,9 +285,14 @@ var CommonNameUserConversion = UserConversionFunc(func(chain []*x509.Certificate
|
||||
fp := sha256.Sum256(chain[0].Raw)
|
||||
id := "X509SHA256=" + hex.EncodeToString(fp[:])
|
||||
|
||||
uid, err := parseUIDFromCert(chain[0])
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return &authenticator.Response{
|
||||
User: &user.DefaultInfo{
|
||||
Name: chain[0].Subject.CommonName,
|
||||
UID: uid,
|
||||
Groups: chain[0].Subject.Organization,
|
||||
Extra: map[string][]string{
|
||||
user.CredentialIDKey: {id},
|
||||
@ -291,3 +300,33 @@ var CommonNameUserConversion = UserConversionFunc(func(chain []*x509.Certificate
|
||||
},
|
||||
}, true, nil
|
||||
})
|
||||
|
||||
var uidOID = asn1util.X509UID()
|
||||
|
||||
func parseUIDFromCert(cert *x509.Certificate) (string, error) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.AllowParsingUserUIDFromCertAuth) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
uids := []string{}
|
||||
for _, name := range cert.Subject.Names {
|
||||
if !name.Type.Equal(uidOID) {
|
||||
continue
|
||||
}
|
||||
uid, ok := name.Value.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("unable to parse UID into a string")
|
||||
}
|
||||
uids = append(uids, uid)
|
||||
}
|
||||
if len(uids) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
if len(uids) != 1 {
|
||||
return "", fmt.Errorf("expected 1 UID, but found multiple: %v", uids)
|
||||
}
|
||||
if uids[0] == "" {
|
||||
return "", errors.New("UID cannot be an empty string")
|
||||
}
|
||||
return uids[0], nil
|
||||
}
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/authentication/user/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/authentication/user/doc.go
generated
vendored
@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package user contains utilities for dealing with simple user exchange in the auth
|
||||
// packages. The user.Info interface defines an interface for exchanging that info.
|
||||
package user // import "k8s.io/apiserver/pkg/authentication/user"
|
||||
package user
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/authorization/path/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/authorization/path/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package path contains an authorizer that allows certain paths and path prefixes.
|
||||
package path // import "k8s.io/apiserver/pkg/authorization/path"
|
||||
package path
|
||||
|
17
e2e/vendor/k8s.io/apiserver/pkg/cel/environment/base.go
generated
vendored
17
e2e/vendor/k8s.io/apiserver/pkg/cel/environment/base.go
generated
vendored
@ -32,9 +32,9 @@ import (
|
||||
celconfig "k8s.io/apiserver/pkg/apis/cel"
|
||||
"k8s.io/apiserver/pkg/cel/library"
|
||||
genericfeatures "k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/apiserver/pkg/util/compatibility"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/component-base/featuregate"
|
||||
utilversion "k8s.io/component-base/version"
|
||||
basecompatibility "k8s.io/component-base/compatibility"
|
||||
)
|
||||
|
||||
// DefaultCompatibilityVersion returns a default compatibility version for use with EnvSet
|
||||
@ -50,9 +50,9 @@ import (
|
||||
// A default version number equal to the current Kubernetes major.minor version
|
||||
// indicates fast forward CEL features that can be used when rollback is no longer needed.
|
||||
func DefaultCompatibilityVersion() *version.Version {
|
||||
effectiveVer := featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent)
|
||||
effectiveVer := compatibility.DefaultComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent)
|
||||
if effectiveVer == nil {
|
||||
effectiveVer = utilversion.DefaultKubeEffectiveVersion()
|
||||
effectiveVer = compatibility.DefaultBuildEffectiveVersion()
|
||||
}
|
||||
return effectiveVer.MinCompatibilityVersion()
|
||||
}
|
||||
@ -173,7 +173,14 @@ var baseOptsWithoutStrictCost = []VersionedOptions{
|
||||
{
|
||||
IntroducedVersion: version.MajorMinor(1, 32),
|
||||
EnvOptions: []cel.EnvOption{
|
||||
UnversionedLib(ext.TwoVarComprehensions),
|
||||
ext.TwoVarComprehensions(),
|
||||
},
|
||||
},
|
||||
// Semver
|
||||
{
|
||||
IntroducedVersion: version.MajorMinor(1, 33),
|
||||
EnvOptions: []cel.EnvOption{
|
||||
library.SemverLib(library.SemverVersion(1)),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
7
e2e/vendor/k8s.io/apiserver/pkg/cel/library/cidr.go
generated
vendored
7
e2e/vendor/k8s.io/apiserver/pkg/cel/library/cidr.go
generated
vendored
@ -160,9 +160,7 @@ var cidrLibraryDecls = map[string][]cel.FunctionOpt{
|
||||
}
|
||||
|
||||
func (*cidrs) CompileOptions() []cel.EnvOption {
|
||||
options := []cel.EnvOption{cel.Types(apiservercel.CIDRType),
|
||||
cel.Variable(apiservercel.CIDRType.TypeName(), types.NewTypeTypeWithParam(apiservercel.CIDRType)),
|
||||
}
|
||||
options := []cel.EnvOption{cel.Types(apiservercel.CIDRType)}
|
||||
for name, overloads := range cidrLibraryDecls {
|
||||
options = append(options, cel.Function(name, overloads...))
|
||||
}
|
||||
@ -231,8 +229,7 @@ func cidrContainsCIDR(arg ref.Val, other ref.Val) ref.Val {
|
||||
return types.MaybeNoSuchOverloadErr(other)
|
||||
}
|
||||
|
||||
equalMasked := cidr.Prefix.Masked() == netip.PrefixFrom(containsCIDR.Prefix.Addr(), cidr.Prefix.Bits())
|
||||
return types.Bool(equalMasked && cidr.Prefix.Bits() <= containsCIDR.Prefix.Bits())
|
||||
return types.Bool(cidr.Overlaps(containsCIDR.Prefix) && cidr.Prefix.Bits() <= containsCIDR.Prefix.Bits())
|
||||
}
|
||||
|
||||
func prefixLength(arg ref.Val) ref.Val {
|
||||
|
11
e2e/vendor/k8s.io/apiserver/pkg/cel/library/cost.go
generated
vendored
11
e2e/vendor/k8s.io/apiserver/pkg/cel/library/cost.go
generated
vendored
@ -18,13 +18,14 @@ package library
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/google/cel-go/checker"
|
||||
"github.com/google/cel-go/common"
|
||||
"github.com/google/cel-go/common/ast"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/google/cel-go/common/types/ref"
|
||||
"github.com/google/cel-go/common/types/traits"
|
||||
"math"
|
||||
|
||||
"k8s.io/apiserver/pkg/cel"
|
||||
)
|
||||
@ -202,7 +203,7 @@ func (l *CostEstimator) CallCost(function, overloadId string, args []ref.Val, re
|
||||
|
||||
return &cost
|
||||
}
|
||||
case "quantity", "isQuantity":
|
||||
case "quantity", "isQuantity", "semver", "isSemver":
|
||||
if len(args) >= 1 {
|
||||
cost := uint64(math.Ceil(float64(actualSize(args[0])) * common.StringTraversalCostFactor))
|
||||
return &cost
|
||||
@ -236,7 +237,7 @@ func (l *CostEstimator) CallCost(function, overloadId string, args []ref.Val, re
|
||||
// Simply dictionary lookup
|
||||
cost := uint64(1)
|
||||
return &cost
|
||||
case "sign", "asInteger", "isInteger", "asApproximateFloat", "isGreaterThan", "isLessThan", "compareTo", "add", "sub":
|
||||
case "sign", "asInteger", "isInteger", "asApproximateFloat", "isGreaterThan", "isLessThan", "compareTo", "add", "sub", "major", "minor", "patch":
|
||||
cost := uint64(1)
|
||||
return &cost
|
||||
case "getScheme", "getHostname", "getHost", "getPort", "getEscapedPath", "getQuery":
|
||||
@ -486,7 +487,7 @@ func (l *CostEstimator) EstimateCallCost(function, overloadId string, target *ch
|
||||
|
||||
return &checker.CallEstimate{CostEstimate: ipCompCost}
|
||||
}
|
||||
case "quantity", "isQuantity":
|
||||
case "quantity", "isQuantity", "semver", "isSemver":
|
||||
if target != nil {
|
||||
sz := l.sizeEstimate(args[0])
|
||||
return &checker.CallEstimate{CostEstimate: sz.MultiplyByCostFactor(common.StringTraversalCostFactor)}
|
||||
@ -498,7 +499,7 @@ func (l *CostEstimator) EstimateCallCost(function, overloadId string, target *ch
|
||||
}
|
||||
case "format.named":
|
||||
return &checker.CallEstimate{CostEstimate: checker.CostEstimate{Min: 1, Max: 1}}
|
||||
case "sign", "asInteger", "isInteger", "asApproximateFloat", "isGreaterThan", "isLessThan", "compareTo", "add", "sub":
|
||||
case "sign", "asInteger", "isInteger", "asApproximateFloat", "isGreaterThan", "isLessThan", "compareTo", "add", "sub", "major", "minor", "patch":
|
||||
return &checker.CallEstimate{CostEstimate: checker.CostEstimate{Min: 1, Max: 1}}
|
||||
case "getScheme", "getHostname", "getHost", "getPort", "getEscapedPath", "getQuery":
|
||||
// url accessors
|
||||
|
12
e2e/vendor/k8s.io/apiserver/pkg/cel/library/format.go
generated
vendored
12
e2e/vendor/k8s.io/apiserver/pkg/cel/library/format.go
generated
vendored
@ -20,7 +20,6 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/asaskevich/govalidator"
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/common/decls"
|
||||
"github.com/google/cel-go/common/types"
|
||||
@ -32,6 +31,13 @@ import (
|
||||
"k8s.io/kube-openapi/pkg/validation/strfmt"
|
||||
)
|
||||
|
||||
var (
|
||||
// base64_length estimate for base64 regex size from github.com/asaskevich/govalidator
|
||||
base64Length = 84
|
||||
// url_length estimate for url regex size from github.com/asaskevich/govalidator
|
||||
urlLength = 1103
|
||||
)
|
||||
|
||||
// Format provides a CEL library exposing common named Kubernetes string
|
||||
// validations. Can be used in CRD ValidationRules messageExpression.
|
||||
//
|
||||
@ -193,7 +199,7 @@ var ConstantFormats = map[string]apiservercel.Format{
|
||||
},
|
||||
// Use govalidator url regex to estimate, since ParseRequestURI
|
||||
// doesnt use regex
|
||||
MaxRegexSize: len(govalidator.URL),
|
||||
MaxRegexSize: urlLength,
|
||||
},
|
||||
"uuid": {
|
||||
Name: "uuid",
|
||||
@ -213,7 +219,7 @@ var ConstantFormats = map[string]apiservercel.Format{
|
||||
}
|
||||
return nil
|
||||
},
|
||||
MaxRegexSize: len(govalidator.Base64),
|
||||
MaxRegexSize: base64Length,
|
||||
},
|
||||
"date": {
|
||||
Name: "date",
|
||||
|
4
e2e/vendor/k8s.io/apiserver/pkg/cel/library/ip.go
generated
vendored
4
e2e/vendor/k8s.io/apiserver/pkg/cel/library/ip.go
generated
vendored
@ -187,9 +187,7 @@ var ipLibraryDecls = map[string][]cel.FunctionOpt{
|
||||
}
|
||||
|
||||
func (*ip) CompileOptions() []cel.EnvOption {
|
||||
options := []cel.EnvOption{cel.Types(apiservercel.IPType),
|
||||
cel.Variable(apiservercel.IPType.TypeName(), types.NewTypeTypeWithParam(apiservercel.IPType)),
|
||||
}
|
||||
options := []cel.EnvOption{cel.Types(apiservercel.IPType)}
|
||||
for name, overloads := range ipLibraryDecls {
|
||||
options = append(options, cel.Function(name, overloads...))
|
||||
}
|
||||
|
115
e2e/vendor/k8s.io/apiserver/pkg/cel/library/semverlib.go
generated
vendored
115
e2e/vendor/k8s.io/apiserver/pkg/cel/library/semverlib.go
generated
vendored
@ -17,6 +17,10 @@ limitations under the License.
|
||||
package library
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/common/types"
|
||||
@ -31,8 +35,10 @@ import (
|
||||
//
|
||||
// Converts a string to a semantic version or results in an error if the string is not a valid semantic version. Refer
|
||||
// to semver.org documentation for information on accepted patterns.
|
||||
//
|
||||
// An optional "normalize" argument can be passed to enable normalization. Normalization removes any "v" prefix, adds a
|
||||
// 0 minor and patch numbers to versions with only major or major.minor components specified, and removes any leading 0s.
|
||||
// semver(<string>) <Semver>
|
||||
// semver(<string>, <bool>) <Semver>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
@ -41,19 +47,28 @@ import (
|
||||
// semver('200K') // error
|
||||
// semver('Three') // error
|
||||
// semver('Mi') // error
|
||||
// semver('v1.0.0', true) // Applies normalization to remove the leading "v". Returns a Semver of "1.0.0".
|
||||
// semver('1.0', true) // Applies normalization to add the missing patch version. Returns a Semver of "1.0.0"
|
||||
// semver('01.01.01', true) // Applies normalization to remove leading zeros. Returns a Semver of "1.1.1"
|
||||
//
|
||||
// isSemver
|
||||
//
|
||||
// Returns true if a string is a valid Semver. isSemver returns true if and
|
||||
// only if semver does not result in error.
|
||||
// An optional "normalize" argument can be passed to enable normalization. Normalization removes any "v" prefix, adds a
|
||||
// 0 minor and patch numbers to versions with only major or major.minor components specified, and removes any leading 0s.
|
||||
//
|
||||
// isSemver( <string>) <bool>
|
||||
// isSemver( <string>, <bool>) <bool>
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// isSemver('1.0.0') // returns true
|
||||
// isSemver('v1.0') // returns true (tolerant parsing)
|
||||
// isSemver('hello') // returns false
|
||||
// isSemver('v1.0') // returns false (leading "v" is not allowed unless normalization is enabled)
|
||||
// isSemver('v1.0', true) // Applies normalization to remove leading "v". returns true
|
||||
// semver('1.0', true) // Applies normalization to add the missing patch version. Returns true
|
||||
// semver('01.01.01', true) // Applies normalization to remove leading zeros. Returns true
|
||||
//
|
||||
// Conversion to Scalars:
|
||||
//
|
||||
@ -84,13 +99,29 @@ import (
|
||||
// semver("1.2.3").compareTo(semver("2.0.0")) // returns -1
|
||||
// semver("1.2.3").compareTo(semver("0.1.2")) // returns 1
|
||||
|
||||
func SemverLib() cel.EnvOption {
|
||||
func SemverLib(options ...SemverOption) cel.EnvOption {
|
||||
semverLib := &semverLibType{}
|
||||
for _, o := range options {
|
||||
semverLib = o(semverLib)
|
||||
}
|
||||
return cel.Lib(semverLib)
|
||||
}
|
||||
|
||||
var semverLib = &semverLibType{}
|
||||
var semverLib = &semverLibType{version: math.MaxUint32} // include all versions
|
||||
|
||||
type semverLibType struct{}
|
||||
type semverLibType struct {
|
||||
version uint32
|
||||
}
|
||||
|
||||
// StringsOption is a functional interface for configuring the strings library.
|
||||
type SemverOption func(*semverLibType) *semverLibType
|
||||
|
||||
func SemverVersion(version uint32) SemverOption {
|
||||
return func(lib *semverLibType) *semverLibType {
|
||||
lib.version = version
|
||||
return lib
|
||||
}
|
||||
}
|
||||
|
||||
func (*semverLibType) LibraryName() string {
|
||||
return "kubernetes.Semver"
|
||||
@ -100,8 +131,8 @@ func (*semverLibType) Types() []*cel.Type {
|
||||
return []*cel.Type{apiservercel.SemverType}
|
||||
}
|
||||
|
||||
func (*semverLibType) declarations() map[string][]cel.FunctionOpt {
|
||||
return map[string][]cel.FunctionOpt{
|
||||
func (lib *semverLibType) declarations() map[string][]cel.FunctionOpt {
|
||||
fnOpts := map[string][]cel.FunctionOpt{
|
||||
"semver": {
|
||||
cel.Overload("string_to_semver", []*cel.Type{cel.StringType}, apiservercel.SemverType, cel.UnaryBinding((stringToSemver))),
|
||||
},
|
||||
@ -127,6 +158,11 @@ func (*semverLibType) declarations() map[string][]cel.FunctionOpt {
|
||||
cel.MemberOverload("semver_patch", []*cel.Type{apiservercel.SemverType}, cel.IntType, cel.UnaryBinding(semverPatch)),
|
||||
},
|
||||
}
|
||||
if lib.version >= 1 {
|
||||
fnOpts["semver"] = append(fnOpts["semver"], cel.Overload("string_bool_to_semver", []*cel.Type{cel.StringType, cel.BoolType}, apiservercel.SemverType, cel.BinaryBinding((stringToSemverNormalize))))
|
||||
fnOpts["isSemver"] = append(fnOpts["isSemver"], cel.Overload("is_semver_string_bool", []*cel.Type{cel.StringType, cel.BoolType}, cel.BoolType, cel.BinaryBinding(isSemverNormalize)))
|
||||
}
|
||||
return fnOpts
|
||||
}
|
||||
|
||||
func (s *semverLibType) CompileOptions() []cel.EnvOption {
|
||||
@ -144,16 +180,29 @@ func (*semverLibType) ProgramOptions() []cel.ProgramOption {
|
||||
}
|
||||
|
||||
func isSemver(arg ref.Val) ref.Val {
|
||||
return isSemverNormalize(arg, types.Bool(false))
|
||||
}
|
||||
func isSemverNormalize(arg ref.Val, normalizeArg ref.Val) ref.Val {
|
||||
str, ok := arg.Value().(string)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
normalize, ok := normalizeArg.Value().(bool)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
// Using semver/v4 here is okay because this function isn't
|
||||
// used to validate the Kubernetes API. In the CEL base library
|
||||
// we would have to use the regular expression from
|
||||
// pkg/apis/resource/structured/namedresources/validation/validation.go.
|
||||
_, err := semver.Parse(str)
|
||||
var err error
|
||||
if normalize {
|
||||
_, err = normalizeAndParse(str)
|
||||
} else {
|
||||
_, err = semver.Parse(str)
|
||||
}
|
||||
if err != nil {
|
||||
return types.Bool(false)
|
||||
}
|
||||
@ -162,17 +211,31 @@ func isSemver(arg ref.Val) ref.Val {
|
||||
}
|
||||
|
||||
func stringToSemver(arg ref.Val) ref.Val {
|
||||
return stringToSemverNormalize(arg, types.Bool(false))
|
||||
}
|
||||
func stringToSemverNormalize(arg ref.Val, normalizeArg ref.Val) ref.Val {
|
||||
str, ok := arg.Value().(string)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
normalize, ok := normalizeArg.Value().(bool)
|
||||
if !ok {
|
||||
return types.MaybeNoSuchOverloadErr(arg)
|
||||
}
|
||||
|
||||
// Using semver/v4 here is okay because this function isn't
|
||||
// used to validate the Kubernetes API. In the CEL base library
|
||||
// we would have to use the regular expression from
|
||||
// pkg/apis/resource/structured/namedresources/validation/validation.go
|
||||
// first before parsing.
|
||||
v, err := semver.Parse(str)
|
||||
var err error
|
||||
var v semver.Version
|
||||
if normalize {
|
||||
v, err = normalizeAndParse(str)
|
||||
} else {
|
||||
v, err = semver.Parse(str)
|
||||
}
|
||||
if err != nil {
|
||||
return types.WrapErr(err)
|
||||
}
|
||||
@ -245,3 +308,37 @@ func semverCompareTo(arg ref.Val, other ref.Val) ref.Val {
|
||||
|
||||
return types.Int(v.Compare(v2))
|
||||
}
|
||||
|
||||
// normalizeAndParse removes any "v" prefix, adds a 0 minor and patch numbers to versions with
|
||||
// only major or major.minor components specified, and removes any leading 0s.
|
||||
// normalizeAndParse is based on semver.ParseTolerant but does not trim extra whitespace and is
|
||||
// guaranteed to not change behavior in the future.
|
||||
func normalizeAndParse(s string) (semver.Version, error) {
|
||||
s = strings.TrimPrefix(s, "v")
|
||||
|
||||
// Split into major.minor.(patch+pr+meta)
|
||||
parts := strings.SplitN(s, ".", 3)
|
||||
// Remove leading zeros.
|
||||
for i, p := range parts {
|
||||
if len(p) > 1 {
|
||||
p = strings.TrimLeft(p, "0")
|
||||
if len(p) == 0 || !strings.ContainsAny(p[0:1], "0123456789") {
|
||||
p = "0" + p
|
||||
}
|
||||
parts[i] = p
|
||||
}
|
||||
}
|
||||
|
||||
// Fill up shortened versions.
|
||||
if len(parts) < 3 {
|
||||
if strings.ContainsAny(parts[len(parts)-1], "+-") {
|
||||
return semver.Version{}, errors.New("short version cannot contain PreRelease/Build meta data")
|
||||
}
|
||||
for len(parts) < 3 {
|
||||
parts = append(parts, "0")
|
||||
}
|
||||
}
|
||||
s = strings.Join(parts, ".")
|
||||
|
||||
return semver.Parse(s)
|
||||
}
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/fake.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/fake.go
generated
vendored
@ -25,7 +25,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp" //nolint:depguard
|
||||
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
|
10
e2e/vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/handler.go
generated
vendored
10
e2e/vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/handler.go
generated
vendored
@ -29,6 +29,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
apidiscoveryv2conversion "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
|
||||
genericfeatures "k8s.io/apiserver/pkg/features"
|
||||
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||
|
||||
@ -40,6 +41,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
@ -538,6 +540,14 @@ func (rdm *resourceDiscoveryManager) serveHTTP(resp http.ResponseWriter, req *ht
|
||||
resp.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if mediaType.Convert.GroupVersion() == apidiscoveryv2beta1.SchemeGroupVersion &&
|
||||
utilfeature.DefaultFeatureGate.Enabled(genericfeatures.AggregatedDiscoveryRemoveBetaType) {
|
||||
klog.Errorf("aggregated discovery version v2beta1 is removed. Please update to use v2")
|
||||
resp.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
targetGV = mediaType.Convert.GroupVersion()
|
||||
|
||||
if len(etag) > 0 {
|
||||
|
6
e2e/vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/negotiation.go
generated
vendored
6
e2e/vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/negotiation.go
generated
vendored
@ -18,6 +18,9 @@ package aggregated
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
genericfeatures "k8s.io/apiserver/pkg/features"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
)
|
||||
|
||||
// Interface is from "k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||
@ -37,6 +40,9 @@ func (discoveryEndpointRestrictions) AllowsStreamSchema(s string) bool { return
|
||||
// IsAggregatedDiscoveryGVK checks if a provided GVK is the GVK for serving aggregated discovery.
|
||||
func IsAggregatedDiscoveryGVK(gvk *schema.GroupVersionKind) bool {
|
||||
if gvk != nil {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.AggregatedDiscoveryRemoveBetaType) {
|
||||
return gvk.Group == "apidiscovery.k8s.io" && gvk.Version == "v2" && gvk.Kind == "APIGroupDiscoveryList"
|
||||
}
|
||||
return gvk.Group == "apidiscovery.k8s.io" && (gvk.Version == "v2beta1" || gvk.Version == "v2") && gvk.Kind == "APIGroupDiscoveryList"
|
||||
}
|
||||
return false
|
||||
|
14
e2e/vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/wrapper.go
generated
vendored
14
e2e/vendor/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/wrapper.go
generated
vendored
@ -28,8 +28,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||
genericfeatures "k8s.io/apiserver/pkg/features"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
)
|
||||
|
||||
type WrappedHandler struct {
|
||||
@ -39,13 +37,11 @@ type WrappedHandler struct {
|
||||
}
|
||||
|
||||
func (wrapped *WrappedHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.AggregatedDiscoveryEndpoint) {
|
||||
mediaType, _ := negotiation.NegotiateMediaTypeOptions(req.Header.Get("Accept"), wrapped.s.SupportedMediaTypes(), DiscoveryEndpointRestrictions)
|
||||
// mediaType.Convert looks at the request accept headers and is used to control whether the discovery document will be aggregated.
|
||||
if IsAggregatedDiscoveryGVK(mediaType.Convert) {
|
||||
wrapped.aggHandler.ServeHTTP(resp, req)
|
||||
return
|
||||
}
|
||||
mediaType, _ := negotiation.NegotiateMediaTypeOptions(req.Header.Get("Accept"), wrapped.s.SupportedMediaTypes(), DiscoveryEndpointRestrictions)
|
||||
// mediaType.Convert looks at the request accept headers and is used to control whether the discovery document will be aggregated.
|
||||
if IsAggregatedDiscoveryGVK(mediaType.Convert) {
|
||||
wrapped.aggHandler.ServeHTTP(resp, req)
|
||||
return
|
||||
}
|
||||
wrapped.handler.ServeHTTP(resp, req)
|
||||
}
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package endpoints contains the generic code that provides a RESTful Kubernetes-style API service.
|
||||
package endpoints // import "k8s.io/apiserver/pkg/endpoints"
|
||||
package endpoints
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/filters/authentication.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/filters/authentication.go
generated
vendored
@ -68,6 +68,7 @@ func withAuthentication(handler http.Handler, auth authenticator.Request, failed
|
||||
authenticationFinish := time.Now()
|
||||
defer func() {
|
||||
metrics(req.Context(), resp, ok, err, apiAuds, authenticationStart, authenticationFinish)
|
||||
genericapirequest.TrackAuthenticationLatency(req.Context(), authenticationFinish.Sub(authenticationStart))
|
||||
}()
|
||||
if err != nil || !ok {
|
||||
if err != nil {
|
||||
@ -118,7 +119,6 @@ func withAuthentication(handler http.Handler, auth authenticator.Request, failed
|
||||
// https://github.com/golang/net/commit/97aa3a539ec716117a9d15a4659a911f50d13c3c
|
||||
w.Header().Set("Connection", "close")
|
||||
}
|
||||
|
||||
req = req.WithContext(genericapirequest.WithUser(req.Context(), resp.User))
|
||||
handler.ServeHTTP(w, req)
|
||||
})
|
||||
|
1
e2e/vendor/k8s.io/apiserver/pkg/endpoints/filters/authorization.go
generated
vendored
1
e2e/vendor/k8s.io/apiserver/pkg/endpoints/filters/authorization.go
generated
vendored
@ -73,6 +73,7 @@ func withAuthorization(handler http.Handler, a authorizer.Authorizer, s runtime.
|
||||
authorizationFinish := time.Now()
|
||||
defer func() {
|
||||
metrics(ctx, authorized, err, authorizationStart, authorizationFinish)
|
||||
request.TrackAuthorizationLatency(ctx, authorizationFinish.Sub(authorizationStart))
|
||||
}()
|
||||
|
||||
// an authorizer like RBAC could encounter evaluation errors and still allow the request, so authorizer decision is checked before error here.
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/filters/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/filters/doc.go
generated
vendored
@ -18,4 +18,4 @@ limitations under the License.
|
||||
// _are_ api related, i.e. which are prerequisite for the API services
|
||||
// to work (in contrast to the filters in the server package which are
|
||||
// not part of the API contract).
|
||||
package filters // import "k8s.io/apiserver/pkg/endpoints/filters"
|
||||
package filters
|
||||
|
19
e2e/vendor/k8s.io/apiserver/pkg/endpoints/filters/traces.go
generated
vendored
19
e2e/vendor/k8s.io/apiserver/pkg/endpoints/filters/traces.go
generated
vendored
@ -24,6 +24,7 @@ import (
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
tracing "k8s.io/component-base/tracing"
|
||||
)
|
||||
|
||||
@ -31,7 +32,7 @@ import (
|
||||
func WithTracing(handler http.Handler, tp trace.TracerProvider) http.Handler {
|
||||
opts := []otelhttp.Option{
|
||||
otelhttp.WithPropagators(tracing.Propagators()),
|
||||
otelhttp.WithPublicEndpoint(),
|
||||
otelhttp.WithPublicEndpointFn(notSystemPrivilegedGroup),
|
||||
otelhttp.WithTracerProvider(tp),
|
||||
otelhttp.WithSpanNameFormatter(func(operation string, r *http.Request) string {
|
||||
ctx := r.Context()
|
||||
@ -43,6 +44,11 @@ func WithTracing(handler http.Handler, tp trace.TracerProvider) http.Handler {
|
||||
}),
|
||||
}
|
||||
wrappedHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Adjust otelhttp tracing start time to match the start time used
|
||||
// for Prometheus metrics.
|
||||
if startTime, ok := request.ReceivedTimestampFrom(r.Context()); ok {
|
||||
r = r.WithContext(otelhttp.ContextWithStartTime(r.Context(), startTime))
|
||||
}
|
||||
// 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 {
|
||||
@ -73,3 +79,14 @@ func getSpanNameFromRequestInfo(info *request.RequestInfo, r *http.Request) stri
|
||||
}
|
||||
return r.Method + " " + spanName
|
||||
}
|
||||
|
||||
func notSystemPrivilegedGroup(req *http.Request) bool {
|
||||
if u, ok := request.UserFrom(req.Context()); ok {
|
||||
for _, group := range u.GetGroups() {
|
||||
if group == user.SystemPrivilegedGroup || group == user.MonitoringGroup {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/handlers/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/handlers/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package handlers contains HTTP handlers to implement the apiserver APIs.
|
||||
package handlers // import "k8s.io/apiserver/pkg/endpoints/handlers"
|
||||
package handlers
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/handlers/negotiation/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/handlers/negotiation/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package negotiation contains media type negotiation logic.
|
||||
package negotiation // import "k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||
package negotiation
|
||||
|
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/doc.go
generated
vendored
2
e2e/vendor/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/doc.go
generated
vendored
@ -15,4 +15,4 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
// Package responsewriters containers helpers to write responses in HTTP handlers.
|
||||
package responsewriters // import "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||
package responsewriters
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user