mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
name runtime.Schemes so we can see which one fails
This commit is contained in:
parent
d3731fe098
commit
340802b079
@ -47,6 +47,7 @@ filegroup(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/json:all-srcs",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/jsonmergepatch:all-srcs",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/mergepatch:all-srcs",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/naming:all-srcs",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/net:all-srcs",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/proxy:all-srcs",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/rand:all-srcs",
|
||||
|
@ -606,7 +606,7 @@ func (s unstructuredNegotiatedSerializer) SupportedMediaTypes() []runtime.Serial
|
||||
}
|
||||
|
||||
func (s unstructuredNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
|
||||
return versioning.NewCodec(encoder, nil, s.converter, Scheme, Scheme, Scheme, gv, nil)
|
||||
return versioning.NewCodec(encoder, nil, s.converter, Scheme, Scheme, Scheme, gv, nil, "crdNegotiatedSerializer")
|
||||
}
|
||||
|
||||
func (s unstructuredNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
|
||||
@ -710,7 +710,17 @@ func (t crdConversionRESTOptionsGetter) GetRESTOptions(resource schema.GroupReso
|
||||
dropInvalidMetadata: true,
|
||||
}}
|
||||
c := schemaCoercingConverter{delegate: t.converter, validator: unstructuredSchemaCoercer{}}
|
||||
ret.StorageConfig.Codec = versioning.NewCodec(ret.StorageConfig.Codec, d, c, &unstructuredCreator{}, crdserverscheme.NewUnstructuredObjectTyper(), &unstructuredDefaulter{delegate: Scheme}, t.encoderVersion, t.decoderVersion)
|
||||
ret.StorageConfig.Codec = versioning.NewCodec(
|
||||
ret.StorageConfig.Codec,
|
||||
d,
|
||||
c,
|
||||
&unstructuredCreator{},
|
||||
crdserverscheme.NewUnstructuredObjectTyper(),
|
||||
&unstructuredDefaulter{delegate: Scheme},
|
||||
t.encoderVersion,
|
||||
t.decoderVersion,
|
||||
"crdRESTOptions",
|
||||
)
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/json:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/naming:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
|
||||
|
@ -24,46 +24,47 @@ import (
|
||||
)
|
||||
|
||||
type notRegisteredErr struct {
|
||||
schemeName string
|
||||
gvk schema.GroupVersionKind
|
||||
target GroupVersioner
|
||||
t reflect.Type
|
||||
}
|
||||
|
||||
func NewNotRegisteredErrForKind(gvk schema.GroupVersionKind) error {
|
||||
return ¬RegisteredErr{gvk: gvk}
|
||||
func NewNotRegisteredErrForKind(schemeName string, gvk schema.GroupVersionKind) error {
|
||||
return ¬RegisteredErr{schemeName: schemeName, gvk: gvk}
|
||||
}
|
||||
|
||||
func NewNotRegisteredErrForType(t reflect.Type) error {
|
||||
return ¬RegisteredErr{t: t}
|
||||
func NewNotRegisteredErrForType(schemeName string, t reflect.Type) error {
|
||||
return ¬RegisteredErr{schemeName: schemeName, t: t}
|
||||
}
|
||||
|
||||
func NewNotRegisteredErrForTarget(t reflect.Type, target GroupVersioner) error {
|
||||
return ¬RegisteredErr{t: t, target: target}
|
||||
func NewNotRegisteredErrForTarget(schemeName string, t reflect.Type, target GroupVersioner) error {
|
||||
return ¬RegisteredErr{schemeName: schemeName, t: t, target: target}
|
||||
}
|
||||
|
||||
func NewNotRegisteredGVKErrForTarget(gvk schema.GroupVersionKind, target GroupVersioner) error {
|
||||
return ¬RegisteredErr{gvk: gvk, target: target}
|
||||
func NewNotRegisteredGVKErrForTarget(schemeName string, gvk schema.GroupVersionKind, target GroupVersioner) error {
|
||||
return ¬RegisteredErr{schemeName: schemeName, gvk: gvk, target: target}
|
||||
}
|
||||
|
||||
func (k *notRegisteredErr) Error() string {
|
||||
if k.t != nil && k.target != nil {
|
||||
return fmt.Sprintf("%v is not suitable for converting to %q", k.t, k.target)
|
||||
return fmt.Sprintf("%v is not suitable for converting to %q in scheme %q", k.t, k.target, k.schemeName)
|
||||
}
|
||||
nullGVK := schema.GroupVersionKind{}
|
||||
if k.gvk != nullGVK && k.target != nil {
|
||||
return fmt.Sprintf("%q is not suitable for converting to %q", k.gvk.GroupVersion(), k.target)
|
||||
return fmt.Sprintf("%q is not suitable for converting to %q in scheme %q", k.gvk.GroupVersion(), k.target, k.schemeName)
|
||||
}
|
||||
if k.t != nil {
|
||||
return fmt.Sprintf("no kind is registered for the type %v", k.t)
|
||||
return fmt.Sprintf("no kind is registered for the type %v in scheme %q", k.t, k.schemeName)
|
||||
}
|
||||
if len(k.gvk.Kind) == 0 {
|
||||
return fmt.Sprintf("no version %q has been registered", k.gvk.GroupVersion())
|
||||
return fmt.Sprintf("no version %q has been registered in scheme %q", k.gvk.GroupVersion(), k.schemeName)
|
||||
}
|
||||
if k.gvk.Version == APIVersionInternal {
|
||||
return fmt.Sprintf("no kind %q is registered for the internal version of group %q", k.gvk.Kind, k.gvk.Group)
|
||||
return fmt.Sprintf("no kind %q is registered for the internal version of group %q in scheme %q", k.gvk.Kind, k.gvk.Group, k.schemeName)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("no kind %q is registered for version %q", k.gvk.Kind, k.gvk.GroupVersion())
|
||||
return fmt.Sprintf("no kind %q is registered for version %q in scheme %q", k.gvk.Kind, k.gvk.GroupVersion(), k.schemeName)
|
||||
}
|
||||
|
||||
// IsNotRegisteredError returns true if the error indicates the provided
|
||||
|
@ -20,11 +20,11 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
|
||||
"strings"
|
||||
|
||||
"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"
|
||||
)
|
||||
@ -79,6 +79,10 @@ type Scheme struct {
|
||||
|
||||
// observedVersions keeps track of the order we've seen versions during type registration
|
||||
observedVersions []schema.GroupVersion
|
||||
|
||||
// schemeName is the name of this scheme. If you don't specify a name, the stack of the NewScheme caller will be used.
|
||||
// This is useful for error reporting to indicate the origin of the scheme.
|
||||
schemeName string
|
||||
}
|
||||
|
||||
// FieldLabelConversionFunc converts a field selector to internal representation.
|
||||
@ -94,6 +98,7 @@ func NewScheme() *Scheme {
|
||||
fieldLabelConversionFuncs: map[string]map[string]FieldLabelConversionFunc{},
|
||||
defaulterFuncs: map[reflect.Type]func(interface{}){},
|
||||
versionPriority: map[string][]string{},
|
||||
schemeName: naming.GetNameFromCallsite(internalPackages...),
|
||||
}
|
||||
s.converter = conversion.NewConverter(s.nameFunc)
|
||||
|
||||
@ -250,7 +255,7 @@ func (s *Scheme) ObjectKinds(obj Object) ([]schema.GroupVersionKind, bool, error
|
||||
|
||||
gvks, ok := s.typeToGVK[t]
|
||||
if !ok {
|
||||
return nil, false, NewNotRegisteredErrForType(t)
|
||||
return nil, false, NewNotRegisteredErrForType(s.schemeName, t)
|
||||
}
|
||||
_, unversionedType := s.unversionedTypes[t]
|
||||
|
||||
@ -288,7 +293,7 @@ func (s *Scheme) New(kind schema.GroupVersionKind) (Object, error) {
|
||||
if t, exists := s.unversionedKinds[kind.Kind]; exists {
|
||||
return reflect.New(t).Interface().(Object), nil
|
||||
}
|
||||
return nil, NewNotRegisteredErrForKind(kind)
|
||||
return nil, NewNotRegisteredErrForKind(s.schemeName, kind)
|
||||
}
|
||||
|
||||
// AddGenericConversionFunc adds a function that accepts the ConversionFunc call pattern
|
||||
@ -536,7 +541,7 @@ func (s *Scheme) convertToVersion(copy bool, in Object, target GroupVersioner) (
|
||||
|
||||
kinds, ok := s.typeToGVK[t]
|
||||
if !ok || len(kinds) == 0 {
|
||||
return nil, NewNotRegisteredErrForType(t)
|
||||
return nil, NewNotRegisteredErrForType(s.schemeName, t)
|
||||
}
|
||||
|
||||
gvk, ok := target.KindForGroupVersionKinds(kinds)
|
||||
@ -549,7 +554,7 @@ func (s *Scheme) convertToVersion(copy bool, in Object, target GroupVersioner) (
|
||||
}
|
||||
return copyAndSetTargetKind(copy, in, unversionedKind)
|
||||
}
|
||||
return nil, NewNotRegisteredErrForTarget(t, target)
|
||||
return nil, NewNotRegisteredErrForTarget(s.schemeName, t, target)
|
||||
}
|
||||
|
||||
// target wants to use the existing type, set kind and return (no conversion necessary)
|
||||
@ -759,3 +764,11 @@ func (s *Scheme) addObservedVersion(version schema.GroupVersion) {
|
||||
|
||||
s.observedVersions = append(s.observedVersions, version)
|
||||
}
|
||||
|
||||
func (s *Scheme) Name() string {
|
||||
return s.schemeName
|
||||
}
|
||||
|
||||
// internalPackages are packages that ignored when creating a default reflector name. These packages are in the common
|
||||
// call chains to NewReflector, so they'd be low entropy names for reflectors
|
||||
var internalPackages = []string{"k8s.io/apimachinery/pkg/runtime/scheme.go"}
|
||||
|
@ -180,7 +180,7 @@ func TestDecode(t *testing.T) {
|
||||
{
|
||||
data: []byte(`{"kind":"Test","apiVersion":"other/blah","value":1,"Other":"test"}`),
|
||||
into: &testDecodable{},
|
||||
typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind(schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
|
||||
typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind("mock", schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
|
||||
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
|
||||
expectedObject: &testDecodable{
|
||||
Other: "test",
|
||||
@ -257,7 +257,7 @@ func TestDecode(t *testing.T) {
|
||||
// "VaLue" should have been "value"
|
||||
data: []byte(`{"kind":"Test","apiVersion":"other/blah","VaLue":1,"Other":"test"}`),
|
||||
into: &testDecodable{},
|
||||
typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind(schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
|
||||
typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind("mock", schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
|
||||
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
|
||||
expectedObject: &testDecodable{
|
||||
Other: "test",
|
||||
@ -268,7 +268,7 @@ func TestDecode(t *testing.T) {
|
||||
// "b" should have been "B", "I" should have been "i"
|
||||
data: []byte(`{"kind":"Test","apiVersion":"other/blah","spec": {"A": 1, "b": 2, "h": 3, "I": 4}}`),
|
||||
into: &testDecodable{},
|
||||
typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind(schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
|
||||
typer: &mockTyper{err: runtime.NewNotRegisteredErrForKind("mock", schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"})},
|
||||
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
|
||||
expectedObject: &testDecodable{
|
||||
Spec: DecodableSpec{A: 1, H: 3},
|
||||
|
@ -24,18 +24,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// NewCodecForScheme is a convenience method for callers that are using a scheme.
|
||||
func NewCodecForScheme(
|
||||
// TODO: I should be a scheme interface?
|
||||
scheme *runtime.Scheme,
|
||||
encoder runtime.Encoder,
|
||||
decoder runtime.Decoder,
|
||||
encodeVersion runtime.GroupVersioner,
|
||||
decodeVersion runtime.GroupVersioner,
|
||||
) runtime.Codec {
|
||||
return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, nil, encodeVersion, decodeVersion)
|
||||
}
|
||||
|
||||
// NewDefaultingCodecForScheme is a convenience method for callers that are using a scheme.
|
||||
func NewDefaultingCodecForScheme(
|
||||
// TODO: I should be a scheme interface?
|
||||
@ -45,7 +33,7 @@ func NewDefaultingCodecForScheme(
|
||||
encodeVersion runtime.GroupVersioner,
|
||||
decodeVersion runtime.GroupVersioner,
|
||||
) runtime.Codec {
|
||||
return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, scheme, encodeVersion, decodeVersion)
|
||||
return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, scheme, encodeVersion, decodeVersion, scheme.Name())
|
||||
}
|
||||
|
||||
// NewCodec takes objects in their internal versions and converts them to external versions before
|
||||
@ -60,6 +48,7 @@ func NewCodec(
|
||||
defaulter runtime.ObjectDefaulter,
|
||||
encodeVersion runtime.GroupVersioner,
|
||||
decodeVersion runtime.GroupVersioner,
|
||||
originalSchemeName string,
|
||||
) runtime.Codec {
|
||||
internal := &codec{
|
||||
encoder: encoder,
|
||||
@ -71,6 +60,8 @@ func NewCodec(
|
||||
|
||||
encodeVersion: encodeVersion,
|
||||
decodeVersion: decodeVersion,
|
||||
|
||||
originalSchemeName: originalSchemeName,
|
||||
}
|
||||
return internal
|
||||
}
|
||||
@ -85,6 +76,9 @@ type codec struct {
|
||||
|
||||
encodeVersion runtime.GroupVersioner
|
||||
decodeVersion runtime.GroupVersioner
|
||||
|
||||
// originalSchemeName is optional, but when filled in it holds the name of the scheme from which this codec originates
|
||||
originalSchemeName string
|
||||
}
|
||||
|
||||
// Decode attempts a decode of the object, then tries to convert it to the internal version. If into is provided and the decoding is
|
||||
@ -182,7 +176,7 @@ func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
|
||||
}
|
||||
targetGVK, ok := c.encodeVersion.KindForGroupVersionKinds([]schema.GroupVersionKind{objGVK})
|
||||
if !ok {
|
||||
return runtime.NewNotRegisteredGVKErrForTarget(objGVK, c.encodeVersion)
|
||||
return runtime.NewNotRegisteredGVKErrForTarget(c.originalSchemeName, objGVK, c.encodeVersion)
|
||||
}
|
||||
if targetGVK == objGVK {
|
||||
return c.encoder.Encode(obj, w)
|
||||
|
@ -72,7 +72,7 @@ func (d *testNestedDecodable) DecodeNestedObjects(_ runtime.Decoder) error {
|
||||
func TestNestedDecode(t *testing.T) {
|
||||
n := &testNestedDecodable{nestedErr: fmt.Errorf("unable to decode")}
|
||||
decoder := &mockSerializer{obj: n}
|
||||
codec := NewCodec(nil, decoder, nil, nil, nil, nil, nil, nil)
|
||||
codec := NewCodec(nil, decoder, nil, nil, nil, nil, nil, nil, "TestNestedDecode")
|
||||
if _, _, err := codec.Decode([]byte(`{}`), nil, n); err != n.nestedErr {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@ -92,6 +92,7 @@ func TestNestedEncode(t *testing.T) {
|
||||
&mockTyper{gvks: []schema.GroupVersionKind{{Kind: "test"}}},
|
||||
nil,
|
||||
schema.GroupVersion{Group: "other"}, nil,
|
||||
"TestNestedEncode",
|
||||
)
|
||||
if err := codec.Encode(n, ioutil.Discard); err != n2.nestedErr {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
@ -231,7 +232,7 @@ func TestDecode(t *testing.T) {
|
||||
|
||||
for i, test := range testCases {
|
||||
t.Logf("%d", i)
|
||||
s := NewCodec(test.serializer, test.serializer, test.convertor, test.creater, test.typer, test.defaulter, test.encodes, test.decodes)
|
||||
s := NewCodec(test.serializer, test.serializer, test.convertor, test.creater, test.typer, test.defaulter, test.encodes, test.decodes, fmt.Sprintf("mock-%d", i))
|
||||
obj, gvk, err := s.Decode([]byte(`{}`), test.defaultGVK, test.into)
|
||||
|
||||
if !reflect.DeepEqual(test.expectedGVK, gvk) {
|
||||
|
29
staging/src/k8s.io/apimachinery/pkg/util/naming/BUILD
Normal file
29
staging/src/k8s.io/apimachinery/pkg/util/naming/BUILD
Normal file
@ -0,0 +1,29 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["from_stack.go"],
|
||||
importmap = "k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/util/naming",
|
||||
importpath = "k8s.io/apimachinery/pkg/util/naming",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["from_stack_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
)
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package naming
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
goruntime "runtime"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GetNameFromCallsite walks back through the call stack until we find a caller from outside of the ignoredPackages
|
||||
// it returns back a shortpath/filename:line to aid in identification of this reflector when it starts logging
|
||||
func GetNameFromCallsite(ignoredPackages ...string) string {
|
||||
name := "????"
|
||||
const maxStack = 10
|
||||
for i := 1; i < maxStack; i++ {
|
||||
_, file, line, ok := goruntime.Caller(i)
|
||||
if !ok {
|
||||
file, line, ok = extractStackCreator()
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
i += maxStack
|
||||
}
|
||||
if hasPackage(file, append(ignoredPackages, "/runtime/asm_")) {
|
||||
continue
|
||||
}
|
||||
|
||||
file = trimPackagePrefix(file)
|
||||
name = fmt.Sprintf("%s:%d", file, line)
|
||||
break
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// hasPackage returns true if the file is in one of the ignored packages.
|
||||
func hasPackage(file string, ignoredPackages []string) bool {
|
||||
for _, ignoredPackage := range ignoredPackages {
|
||||
if strings.Contains(file, ignoredPackage) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// trimPackagePrefix reduces duplicate values off the front of a package name.
|
||||
func trimPackagePrefix(file string) string {
|
||||
if l := strings.LastIndex(file, "/vendor/"); l >= 0 {
|
||||
return file[l+len("/vendor/"):]
|
||||
}
|
||||
if l := strings.LastIndex(file, "/src/"); l >= 0 {
|
||||
return file[l+5:]
|
||||
}
|
||||
if l := strings.LastIndex(file, "/pkg/"); l >= 0 {
|
||||
return file[l+1:]
|
||||
}
|
||||
return file
|
||||
}
|
||||
|
||||
var stackCreator = regexp.MustCompile(`(?m)^created by (.*)\n\s+(.*):(\d+) \+0x[[:xdigit:]]+$`)
|
||||
|
||||
// extractStackCreator retrieves the goroutine file and line that launched this stack. Returns false
|
||||
// if the creator cannot be located.
|
||||
// TODO: Go does not expose this via runtime https://github.com/golang/go/issues/11440
|
||||
func extractStackCreator() (string, int, bool) {
|
||||
stack := debug.Stack()
|
||||
matches := stackCreator.FindStringSubmatch(string(stack))
|
||||
if matches == nil || len(matches) != 4 {
|
||||
return "", 0, false
|
||||
}
|
||||
line, err := strconv.Atoi(matches[3])
|
||||
if err != nil {
|
||||
return "", 0, false
|
||||
}
|
||||
return matches[2], line, true
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package naming
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestGetNameFromCallsite(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
ignoredPackages []string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "simple",
|
||||
expected: "k8s.io/apimachinery/pkg/util/naming/from_stack_test.go:50",
|
||||
},
|
||||
{
|
||||
name: "ignore-package",
|
||||
ignoredPackages: []string{"k8s.io/apimachinery/pkg/util/naming"},
|
||||
expected: "testing/testing.go:777",
|
||||
},
|
||||
{
|
||||
name: "ignore-file",
|
||||
ignoredPackages: []string{"k8s.io/apimachinery/pkg/util/naming/from_stack_test.go"},
|
||||
expected: "testing/testing.go:777",
|
||||
},
|
||||
{
|
||||
name: "ignore-multiple",
|
||||
ignoredPackages: []string{"k8s.io/apimachinery/pkg/util/naming/from_stack_test.go", "testing/testing.go"},
|
||||
expected: "????",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
actual := GetNameFromCallsite(tc.ignoredPackages...)
|
||||
if tc.expected != actual {
|
||||
t.Fatalf("expected %q, got %q", tc.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -74,6 +74,7 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/cache:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/naming:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
|
@ -24,9 +24,6 @@ import (
|
||||
"net"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
goruntime "runtime"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -40,6 +37,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/apimachinery/pkg/util/naming"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
@ -94,7 +92,7 @@ func NewNamespaceKeyedIndexerAndReflector(lw ListerWatcher, expectedType interfa
|
||||
// resyncPeriod, so that you can use reflectors to periodically process everything as
|
||||
// well as incrementally processing the things that change.
|
||||
func NewReflector(lw ListerWatcher, expectedType interface{}, store Store, resyncPeriod time.Duration) *Reflector {
|
||||
return NewNamedReflector(getDefaultReflectorName(internalPackages...), lw, expectedType, store, resyncPeriod)
|
||||
return NewNamedReflector(naming.GetNameFromCallsite(internalPackages...), lw, expectedType, store, resyncPeriod)
|
||||
}
|
||||
|
||||
// reflectorDisambiguator is used to disambiguate started reflectors.
|
||||
@ -125,74 +123,7 @@ func makeValidPrometheusMetricLabel(in string) string {
|
||||
|
||||
// internalPackages are packages that ignored when creating a default reflector name. These packages are in the common
|
||||
// call chains to NewReflector, so they'd be low entropy names for reflectors
|
||||
var internalPackages = []string{"client-go/tools/cache/", "/runtime/asm_"}
|
||||
|
||||
// getDefaultReflectorName walks back through the call stack until we find a caller from outside of the ignoredPackages
|
||||
// it returns back a shortpath/filename:line to aid in identification of this reflector when it starts logging
|
||||
func getDefaultReflectorName(ignoredPackages ...string) string {
|
||||
name := "????"
|
||||
const maxStack = 10
|
||||
for i := 1; i < maxStack; i++ {
|
||||
_, file, line, ok := goruntime.Caller(i)
|
||||
if !ok {
|
||||
file, line, ok = extractStackCreator()
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
i += maxStack
|
||||
}
|
||||
if hasPackage(file, ignoredPackages) {
|
||||
continue
|
||||
}
|
||||
|
||||
file = trimPackagePrefix(file)
|
||||
name = fmt.Sprintf("%s:%d", file, line)
|
||||
break
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// hasPackage returns true if the file is in one of the ignored packages.
|
||||
func hasPackage(file string, ignoredPackages []string) bool {
|
||||
for _, ignoredPackage := range ignoredPackages {
|
||||
if strings.Contains(file, ignoredPackage) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// trimPackagePrefix reduces duplicate values off the front of a package name.
|
||||
func trimPackagePrefix(file string) string {
|
||||
if l := strings.LastIndex(file, "k8s.io/client-go/pkg/"); l >= 0 {
|
||||
return file[l+len("k8s.io/client-go/"):]
|
||||
}
|
||||
if l := strings.LastIndex(file, "/src/"); l >= 0 {
|
||||
return file[l+5:]
|
||||
}
|
||||
if l := strings.LastIndex(file, "/pkg/"); l >= 0 {
|
||||
return file[l+1:]
|
||||
}
|
||||
return file
|
||||
}
|
||||
|
||||
var stackCreator = regexp.MustCompile(`(?m)^created by (.*)\n\s+(.*):(\d+) \+0x[[:xdigit:]]+$`)
|
||||
|
||||
// extractStackCreator retrieves the goroutine file and line that launched this stack. Returns false
|
||||
// if the creator cannot be located.
|
||||
// TODO: Go does not expose this via runtime https://github.com/golang/go/issues/11440
|
||||
func extractStackCreator() (string, int, bool) {
|
||||
stack := debug.Stack()
|
||||
matches := stackCreator.FindStringSubmatch(string(stack))
|
||||
if matches == nil || len(matches) != 4 {
|
||||
return "", 0, false
|
||||
}
|
||||
line, err := strconv.Atoi(matches[3])
|
||||
if err != nil {
|
||||
return "", 0, false
|
||||
}
|
||||
return matches[2], line, true
|
||||
}
|
||||
var internalPackages = []string{"client-go/tools/cache/"}
|
||||
|
||||
// Run starts a watch and handles watch events. Will restart the watch if it is closed.
|
||||
// Run will exit when stopCh is closed.
|
||||
|
@ -45,9 +45,9 @@ func (s *wrappedSerializer) UniversalDeserializer() runtime.Decoder {
|
||||
}
|
||||
|
||||
func (s *wrappedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
|
||||
return versioning.NewCodec(encoder, nil, s.scheme, s.scheme, s.scheme, s.scheme, gv, nil)
|
||||
return versioning.NewCodec(encoder, nil, s.scheme, s.scheme, s.scheme, s.scheme, gv, nil, s.scheme.Name())
|
||||
}
|
||||
|
||||
func (s *wrappedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
|
||||
return versioning.NewCodec(nil, decoder, s.scheme, s.scheme, s.scheme, s.scheme, nil, gv)
|
||||
return versioning.NewCodec(nil, decoder, s.scheme, s.scheme, s.scheme, s.scheme, nil, gv, s.scheme.Name())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user