mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	name runtime.Schemes so we can see which one fails
This commit is contained in:
		@@ -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 {
 | 
			
		||||
	gvk    schema.GroupVersionKind
 | 
			
		||||
	target GroupVersioner
 | 
			
		||||
	t      reflect.Type
 | 
			
		||||
	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())
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user