mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +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/json:all-srcs",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/jsonmergepatch: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/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/net:all-srcs",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/proxy:all-srcs",
|
"//staging/src/k8s.io/apimachinery/pkg/util/proxy:all-srcs",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/rand: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 {
|
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 {
|
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,
|
dropInvalidMetadata: true,
|
||||||
}}
|
}}
|
||||||
c := schemaCoercingConverter{delegate: t.converter, validator: unstructuredSchemaCoercer{}}
|
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
|
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/runtime/schema:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/errors: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/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/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
|
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
|
||||||
|
@ -24,46 +24,47 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type notRegisteredErr struct {
|
type notRegisteredErr struct {
|
||||||
gvk schema.GroupVersionKind
|
schemeName string
|
||||||
target GroupVersioner
|
gvk schema.GroupVersionKind
|
||||||
t reflect.Type
|
target GroupVersioner
|
||||||
|
t reflect.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNotRegisteredErrForKind(gvk schema.GroupVersionKind) error {
|
func NewNotRegisteredErrForKind(schemeName string, gvk schema.GroupVersionKind) error {
|
||||||
return ¬RegisteredErr{gvk: gvk}
|
return ¬RegisteredErr{schemeName: schemeName, gvk: gvk}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNotRegisteredErrForType(t reflect.Type) error {
|
func NewNotRegisteredErrForType(schemeName string, t reflect.Type) error {
|
||||||
return ¬RegisteredErr{t: t}
|
return ¬RegisteredErr{schemeName: schemeName, t: t}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNotRegisteredErrForTarget(t reflect.Type, target GroupVersioner) error {
|
func NewNotRegisteredErrForTarget(schemeName string, t reflect.Type, target GroupVersioner) error {
|
||||||
return ¬RegisteredErr{t: t, target: target}
|
return ¬RegisteredErr{schemeName: schemeName, t: t, target: target}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNotRegisteredGVKErrForTarget(gvk schema.GroupVersionKind, target GroupVersioner) error {
|
func NewNotRegisteredGVKErrForTarget(schemeName string, gvk schema.GroupVersionKind, target GroupVersioner) error {
|
||||||
return ¬RegisteredErr{gvk: gvk, target: target}
|
return ¬RegisteredErr{schemeName: schemeName, gvk: gvk, target: target}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *notRegisteredErr) Error() string {
|
func (k *notRegisteredErr) Error() string {
|
||||||
if k.t != nil && k.target != nil {
|
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{}
|
nullGVK := schema.GroupVersionKind{}
|
||||||
if k.gvk != nullGVK && k.target != nil {
|
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 {
|
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 {
|
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 {
|
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
|
// IsNotRegisteredError returns true if the error indicates the provided
|
||||||
|
@ -20,11 +20,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/conversion"
|
"k8s.io/apimachinery/pkg/conversion"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/util/naming"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"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 keeps track of the order we've seen versions during type registration
|
||||||
observedVersions []schema.GroupVersion
|
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.
|
// FieldLabelConversionFunc converts a field selector to internal representation.
|
||||||
@ -94,6 +98,7 @@ func NewScheme() *Scheme {
|
|||||||
fieldLabelConversionFuncs: map[string]map[string]FieldLabelConversionFunc{},
|
fieldLabelConversionFuncs: map[string]map[string]FieldLabelConversionFunc{},
|
||||||
defaulterFuncs: map[reflect.Type]func(interface{}){},
|
defaulterFuncs: map[reflect.Type]func(interface{}){},
|
||||||
versionPriority: map[string][]string{},
|
versionPriority: map[string][]string{},
|
||||||
|
schemeName: naming.GetNameFromCallsite(internalPackages...),
|
||||||
}
|
}
|
||||||
s.converter = conversion.NewConverter(s.nameFunc)
|
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]
|
gvks, ok := s.typeToGVK[t]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, false, NewNotRegisteredErrForType(t)
|
return nil, false, NewNotRegisteredErrForType(s.schemeName, t)
|
||||||
}
|
}
|
||||||
_, unversionedType := s.unversionedTypes[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 {
|
if t, exists := s.unversionedKinds[kind.Kind]; exists {
|
||||||
return reflect.New(t).Interface().(Object), nil
|
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
|
// 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]
|
kinds, ok := s.typeToGVK[t]
|
||||||
if !ok || len(kinds) == 0 {
|
if !ok || len(kinds) == 0 {
|
||||||
return nil, NewNotRegisteredErrForType(t)
|
return nil, NewNotRegisteredErrForType(s.schemeName, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
gvk, ok := target.KindForGroupVersionKinds(kinds)
|
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 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)
|
// 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)
|
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"}`),
|
data: []byte(`{"kind":"Test","apiVersion":"other/blah","value":1,"Other":"test"}`),
|
||||||
into: &testDecodable{},
|
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"},
|
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
|
||||||
expectedObject: &testDecodable{
|
expectedObject: &testDecodable{
|
||||||
Other: "test",
|
Other: "test",
|
||||||
@ -257,7 +257,7 @@ func TestDecode(t *testing.T) {
|
|||||||
// "VaLue" should have been "value"
|
// "VaLue" should have been "value"
|
||||||
data: []byte(`{"kind":"Test","apiVersion":"other/blah","VaLue":1,"Other":"test"}`),
|
data: []byte(`{"kind":"Test","apiVersion":"other/blah","VaLue":1,"Other":"test"}`),
|
||||||
into: &testDecodable{},
|
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"},
|
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
|
||||||
expectedObject: &testDecodable{
|
expectedObject: &testDecodable{
|
||||||
Other: "test",
|
Other: "test",
|
||||||
@ -268,7 +268,7 @@ func TestDecode(t *testing.T) {
|
|||||||
// "b" should have been "B", "I" should have been "i"
|
// "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}}`),
|
data: []byte(`{"kind":"Test","apiVersion":"other/blah","spec": {"A": 1, "b": 2, "h": 3, "I": 4}}`),
|
||||||
into: &testDecodable{},
|
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"},
|
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
|
||||||
expectedObject: &testDecodable{
|
expectedObject: &testDecodable{
|
||||||
Spec: DecodableSpec{A: 1, H: 3},
|
Spec: DecodableSpec{A: 1, H: 3},
|
||||||
|
@ -24,18 +24,6 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"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.
|
// NewDefaultingCodecForScheme is a convenience method for callers that are using a scheme.
|
||||||
func NewDefaultingCodecForScheme(
|
func NewDefaultingCodecForScheme(
|
||||||
// TODO: I should be a scheme interface?
|
// TODO: I should be a scheme interface?
|
||||||
@ -45,7 +33,7 @@ func NewDefaultingCodecForScheme(
|
|||||||
encodeVersion runtime.GroupVersioner,
|
encodeVersion runtime.GroupVersioner,
|
||||||
decodeVersion runtime.GroupVersioner,
|
decodeVersion runtime.GroupVersioner,
|
||||||
) runtime.Codec {
|
) 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
|
// NewCodec takes objects in their internal versions and converts them to external versions before
|
||||||
@ -60,6 +48,7 @@ func NewCodec(
|
|||||||
defaulter runtime.ObjectDefaulter,
|
defaulter runtime.ObjectDefaulter,
|
||||||
encodeVersion runtime.GroupVersioner,
|
encodeVersion runtime.GroupVersioner,
|
||||||
decodeVersion runtime.GroupVersioner,
|
decodeVersion runtime.GroupVersioner,
|
||||||
|
originalSchemeName string,
|
||||||
) runtime.Codec {
|
) runtime.Codec {
|
||||||
internal := &codec{
|
internal := &codec{
|
||||||
encoder: encoder,
|
encoder: encoder,
|
||||||
@ -71,6 +60,8 @@ func NewCodec(
|
|||||||
|
|
||||||
encodeVersion: encodeVersion,
|
encodeVersion: encodeVersion,
|
||||||
decodeVersion: decodeVersion,
|
decodeVersion: decodeVersion,
|
||||||
|
|
||||||
|
originalSchemeName: originalSchemeName,
|
||||||
}
|
}
|
||||||
return internal
|
return internal
|
||||||
}
|
}
|
||||||
@ -85,6 +76,9 @@ type codec struct {
|
|||||||
|
|
||||||
encodeVersion runtime.GroupVersioner
|
encodeVersion runtime.GroupVersioner
|
||||||
decodeVersion 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
|
// 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})
|
targetGVK, ok := c.encodeVersion.KindForGroupVersionKinds([]schema.GroupVersionKind{objGVK})
|
||||||
if !ok {
|
if !ok {
|
||||||
return runtime.NewNotRegisteredGVKErrForTarget(objGVK, c.encodeVersion)
|
return runtime.NewNotRegisteredGVKErrForTarget(c.originalSchemeName, objGVK, c.encodeVersion)
|
||||||
}
|
}
|
||||||
if targetGVK == objGVK {
|
if targetGVK == objGVK {
|
||||||
return c.encoder.Encode(obj, w)
|
return c.encoder.Encode(obj, w)
|
||||||
|
@ -72,7 +72,7 @@ func (d *testNestedDecodable) DecodeNestedObjects(_ runtime.Decoder) error {
|
|||||||
func TestNestedDecode(t *testing.T) {
|
func TestNestedDecode(t *testing.T) {
|
||||||
n := &testNestedDecodable{nestedErr: fmt.Errorf("unable to decode")}
|
n := &testNestedDecodable{nestedErr: fmt.Errorf("unable to decode")}
|
||||||
decoder := &mockSerializer{obj: n}
|
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 {
|
if _, _, err := codec.Decode([]byte(`{}`), nil, n); err != n.nestedErr {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -92,6 +92,7 @@ func TestNestedEncode(t *testing.T) {
|
|||||||
&mockTyper{gvks: []schema.GroupVersionKind{{Kind: "test"}}},
|
&mockTyper{gvks: []schema.GroupVersionKind{{Kind: "test"}}},
|
||||||
nil,
|
nil,
|
||||||
schema.GroupVersion{Group: "other"}, nil,
|
schema.GroupVersion{Group: "other"}, nil,
|
||||||
|
"TestNestedEncode",
|
||||||
)
|
)
|
||||||
if err := codec.Encode(n, ioutil.Discard); err != n2.nestedErr {
|
if err := codec.Encode(n, ioutil.Discard); err != n2.nestedErr {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
@ -231,7 +232,7 @@ func TestDecode(t *testing.T) {
|
|||||||
|
|
||||||
for i, test := range testCases {
|
for i, test := range testCases {
|
||||||
t.Logf("%d", i)
|
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)
|
obj, gvk, err := s.Decode([]byte(`{}`), test.defaultGVK, test.into)
|
||||||
|
|
||||||
if !reflect.DeepEqual(test.expectedGVK, gvk) {
|
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/cache:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/clock: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/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/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets: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",
|
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||||
|
@ -24,9 +24,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
|
||||||
goruntime "runtime"
|
|
||||||
"runtime/debug"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -40,6 +37,7 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/clock"
|
"k8s.io/apimachinery/pkg/util/clock"
|
||||||
|
"k8s.io/apimachinery/pkg/util/naming"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"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
|
// resyncPeriod, so that you can use reflectors to periodically process everything as
|
||||||
// well as incrementally processing the things that change.
|
// well as incrementally processing the things that change.
|
||||||
func NewReflector(lw ListerWatcher, expectedType interface{}, store Store, resyncPeriod time.Duration) *Reflector {
|
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.
|
// 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
|
// 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
|
// call chains to NewReflector, so they'd be low entropy names for reflectors
|
||||||
var internalPackages = []string{"client-go/tools/cache/", "/runtime/asm_"}
|
var internalPackages = []string{"client-go/tools/cache/"}
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run starts a watch and handles watch events. Will restart the watch if it is closed.
|
// Run starts a watch and handles watch events. Will restart the watch if it is closed.
|
||||||
// Run will exit when stopCh 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 {
|
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 {
|
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