Fresh dep ensure

This commit is contained in:
Mike Cronce
2018-11-26 13:23:56 -05:00
parent 93cb8a04d7
commit 407478ab9a
9016 changed files with 551394 additions and 279685 deletions

View File

@ -1,98 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["swagger_doc_generator_test.go"],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"codec.go",
"codec_check.go",
"conversion.go",
"converter.go",
"doc.go",
"embedded.go",
"error.go",
"extension.go",
"generated.pb.go",
"helper.go",
"interfaces.go",
"register.go",
"scheme.go",
"scheme_builder.go",
"swagger_doc_generator.go",
"types.go",
"types_proto.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/apimachinery/pkg/runtime",
deps = [
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion/queryparams:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
],
)
go_test(
name = "go_default_xtest",
srcs = [
"conversion_test.go",
"converter_test.go",
"embedded_test.go",
"extension_test.go",
"scheme_test.go",
],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/testing:all-srcs",
],
tags = ["automanaged"],
)
filegroup(
name = "go_default_library_protos",
srcs = ["generated.proto"],
visibility = ["//visibility:public"],
)

View File

@ -76,24 +76,6 @@ func EncodeOrDie(e Encoder, obj Object) string {
return string(bytes)
}
// DefaultingSerializer invokes defaulting after decoding.
type DefaultingSerializer struct {
Defaulter ObjectDefaulter
Decoder Decoder
// Encoder is optional to allow this type to be used as both a Decoder and an Encoder
Encoder
}
// Decode performs a decode and then allows the defaulter to act on the provided object.
func (d DefaultingSerializer) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into Object) (Object, *schema.GroupVersionKind, error) {
obj, gvk, err := d.Decoder.Decode(data, defaultGVK, into)
if err != nil {
return obj, gvk, err
}
d.Defaulter.Default(obj)
return obj, gvk, nil
}
// UseOrCreateObject returns obj if the canonical ObjectKind returned by the provided typer matches gvk, or
// invokes the ObjectCreator to instantiate a new gvk. Returns an error if the typer cannot find the object.
func UseOrCreateObject(t ObjectTyper, c ObjectCreater, gvk schema.GroupVersionKind, obj Object) (Object, error) {

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Defines conversions between generic types and structs to map query strings
// Package runtime defines conversions between generic types and structs to map query strings
// to struct objects.
package runtime
@ -27,7 +27,7 @@ import (
"k8s.io/apimachinery/pkg/conversion"
)
// DefaultFieldSelectorConversion auto-accepts metav1 values for name and namespace.
// DefaultMetaV1FieldSelectorConversion auto-accepts metav1 values for name and namespace.
// A cluster scoped resource specifying namespace empty works fine and specifying a particular
// namespace will return no results, as expected.
func DefaultMetaV1FieldSelectorConversion(label, value string) (string, string, error) {
@ -82,7 +82,7 @@ func Convert_Slice_string_To_int(input *[]string, out *int, s conversion.Scope)
return nil
}
// Conver_Slice_string_To_bool will convert a string parameter to boolean.
// Convert_Slice_string_To_bool will convert a string parameter to boolean.
// Only the absence of a value, a value of "false", or a value of "0" resolve to false.
// Any other value (including empty string) resolves to true.
func Convert_Slice_string_To_bool(input *[]string, out *bool, s conversion.Scope) error {

View File

@ -33,7 +33,7 @@ import (
"k8s.io/apimachinery/pkg/util/json"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"github.com/golang/glog"
"k8s.io/klog"
)
// UnstructuredConverter is an interface for converting between interface{}
@ -73,7 +73,6 @@ var (
mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{})
stringType = reflect.TypeOf(string(""))
int64Type = reflect.TypeOf(int64(0))
uint64Type = reflect.TypeOf(uint64(0))
float64Type = reflect.TypeOf(float64(0))
boolType = reflect.TypeOf(bool(false))
fieldCache = newFieldsCache()
@ -134,10 +133,10 @@ func (c *unstructuredConverter) FromUnstructured(u map[string]interface{}, obj i
newObj := reflect.New(t.Elem()).Interface()
newErr := fromUnstructuredViaJSON(u, newObj)
if (err != nil) != (newErr != nil) {
glog.Fatalf("FromUnstructured unexpected error for %v: error: %v", u, err)
klog.Fatalf("FromUnstructured unexpected error for %v: error: %v", u, err)
}
if err == nil && !c.comparison.DeepEqual(obj, newObj) {
glog.Fatalf("FromUnstructured mismatch\nobj1: %#v\nobj2: %#v", obj, newObj)
klog.Fatalf("FromUnstructured mismatch\nobj1: %#v\nobj2: %#v", obj, newObj)
}
}
return err
@ -411,8 +410,7 @@ func (c *unstructuredConverter) ToUnstructured(obj interface{}) (map[string]inte
var u map[string]interface{}
var err error
if unstr, ok := obj.(Unstructured); ok {
// UnstructuredContent() mutates the object so we need to make a copy first
u = unstr.DeepCopyObject().(Unstructured).UnstructuredContent()
u = unstr.UnstructuredContent()
} else {
t := reflect.TypeOf(obj)
value := reflect.ValueOf(obj)
@ -426,10 +424,10 @@ func (c *unstructuredConverter) ToUnstructured(obj interface{}) (map[string]inte
newUnstr := map[string]interface{}{}
newErr := toUnstructuredViaJSON(obj, &newUnstr)
if (err != nil) != (newErr != nil) {
glog.Fatalf("ToUnstructured unexpected error for %v: error: %v; newErr: %v", obj, err, newErr)
klog.Fatalf("ToUnstructured unexpected error for %v: error: %v; newErr: %v", obj, err, newErr)
}
if err == nil && !c.comparison.DeepEqual(u, newUnstr) {
glog.Fatalf("ToUnstructured mismatch\nobj1: %#v\nobj2: %#v", u, newUnstr)
klog.Fatalf("ToUnstructured mismatch\nobj1: %#v\nobj2: %#v", u, newUnstr)
}
}
if err != nil {
@ -439,22 +437,32 @@ func (c *unstructuredConverter) ToUnstructured(obj interface{}) (map[string]inte
}
// DeepCopyJSON deep copies the passed value, assuming it is a valid JSON representation i.e. only contains
// types produced by json.Unmarshal().
// types produced by json.Unmarshal() and also int64.
// bool, int64, float64, string, []interface{}, map[string]interface{}, json.Number and nil
func DeepCopyJSON(x map[string]interface{}) map[string]interface{} {
return DeepCopyJSONValue(x).(map[string]interface{})
}
// DeepCopyJSONValue deep copies the passed value, assuming it is a valid JSON representation i.e. only contains
// types produced by json.Unmarshal().
// types produced by json.Unmarshal() and also int64.
// bool, int64, float64, string, []interface{}, map[string]interface{}, json.Number and nil
func DeepCopyJSONValue(x interface{}) interface{} {
switch x := x.(type) {
case map[string]interface{}:
if x == nil {
// Typed nil - an interface{} that contains a type map[string]interface{} with a value of nil
return x
}
clone := make(map[string]interface{}, len(x))
for k, v := range x {
clone[k] = DeepCopyJSONValue(v)
}
return clone
case []interface{}:
if x == nil {
// Typed nil - an interface{} that contains a type []interface{} with a value of nil
return x
}
clone := make([]interface{}, len(x))
for i, v := range x {
clone[i] = DeepCopyJSONValue(v)
@ -584,10 +592,14 @@ func toUnstructured(sv, dv reflect.Value) error {
dv.Set(reflect.ValueOf(sv.Int()))
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 {
dv.Set(reflect.New(uint64Type))
uVal := sv.Uint()
if uVal > math.MaxInt64 {
return fmt.Errorf("unsigned value %d does not fit into int64 (overflow)", uVal)
}
dv.Set(reflect.ValueOf(sv.Uint()))
if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 {
dv.Set(reflect.New(int64Type))
}
dv.Set(reflect.ValueOf(int64(uVal)))
return nil
case reflect.Float32, reflect.Float64:
if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 {

View File

@ -18,20 +18,27 @@ limitations under the License.
// that follow the kubernetes API object conventions, which are:
//
// 0. Your API objects have a common metadata struct member, TypeMeta.
//
// 1. Your code refers to an internal set of API objects.
//
// 2. In a separate package, you have an external set of API objects.
//
// 3. The external set is considered to be versioned, and no breaking
// changes are ever made to it (fields may be added but not changed
// or removed).
// changes are ever made to it (fields may be added but not changed
// or removed).
//
// 4. As your api evolves, you'll make an additional versioned package
// with every major change.
// with every major change.
//
// 5. Versioned packages have conversion functions which convert to
// and from the internal version.
// and from the internal version.
//
// 6. You'll continue to support older versions according to your
// deprecation policy, and you can easily provide a program/library
// to update old versions into new versions because of 5.
// deprecation policy, and you can easily provide a program/library
// to update old versions into new versions because of 5.
//
// 7. All of your serializations and deserializations are handled in a
// centralized place.
// centralized place.
//
// Package runtime provides a conversion helper to make 5 easy, and the
// Encode/Decode/DecodeInto trio to accomplish 7. You can also register
@ -41,5 +48,4 @@ limitations under the License.
//
// As a bonus, a few common types useful from all api objects and versions
// are provided in types.go.
package runtime // import "k8s.io/apimachinery/pkg/runtime"

View File

@ -31,7 +31,7 @@ type encodable struct {
func (e encodable) GetObjectKind() schema.ObjectKind { return e.obj.GetObjectKind() }
func (e encodable) DeepCopyObject() Object {
var out encodable = e
out := e
out.obj = e.obj.DeepCopyObject()
copy(out.versions, e.versions)
return out
@ -46,14 +46,14 @@ func NewEncodable(e Encoder, obj Object, versions ...schema.GroupVersion) Object
return encodable{e, obj, versions}
}
func (re encodable) UnmarshalJSON(in []byte) error {
func (e encodable) UnmarshalJSON(in []byte) error {
return errors.New("runtime.encodable cannot be unmarshalled from JSON")
}
// Marshal may get called on pointers or values, so implement MarshalJSON on value.
// http://stackoverflow.com/questions/21390979/custom-marshaljson-never-gets-called-in-go
func (re encodable) MarshalJSON() ([]byte, error) {
return Encode(re.E, re.obj)
func (e encodable) MarshalJSON() ([]byte, error) {
return Encode(e.E, e.obj)
}
// NewEncodableList creates an object that will be encoded with the provided codec on demand.
@ -70,28 +70,28 @@ func NewEncodableList(e Encoder, objects []Object, versions ...schema.GroupVersi
return out
}
func (re *Unknown) UnmarshalJSON(in []byte) error {
if re == nil {
func (e *Unknown) UnmarshalJSON(in []byte) error {
if e == nil {
return errors.New("runtime.Unknown: UnmarshalJSON on nil pointer")
}
re.TypeMeta = TypeMeta{}
re.Raw = append(re.Raw[0:0], in...)
re.ContentEncoding = ""
re.ContentType = ContentTypeJSON
e.TypeMeta = TypeMeta{}
e.Raw = append(e.Raw[0:0], in...)
e.ContentEncoding = ""
e.ContentType = ContentTypeJSON
return nil
}
// Marshal may get called on pointers or values, so implement MarshalJSON on value.
// http://stackoverflow.com/questions/21390979/custom-marshaljson-never-gets-called-in-go
func (re Unknown) MarshalJSON() ([]byte, error) {
func (e Unknown) MarshalJSON() ([]byte, error) {
// If ContentType is unset, we assume this is JSON.
if re.ContentType != "" && re.ContentType != ContentTypeJSON {
if e.ContentType != "" && e.ContentType != ContentTypeJSON {
return nil, errors.New("runtime.Unknown: MarshalJSON on non-json data")
}
if re.Raw == nil {
if e.Raw == nil {
return []byte("null"), nil
}
return re.Raw, nil
return e.Raw, nil
}
func Convert_runtime_Object_To_runtime_RawExtension(in *Object, out *RawExtension, s conversion.Scope) error {

View File

@ -24,38 +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 &notRegisteredErr{gvk: gvk}
func NewNotRegisteredErrForKind(schemeName string, gvk schema.GroupVersionKind) error {
return &notRegisteredErr{schemeName: schemeName, gvk: gvk}
}
func NewNotRegisteredErrForType(t reflect.Type) error {
return &notRegisteredErr{t: t}
func NewNotRegisteredErrForType(schemeName string, t reflect.Type) error {
return &notRegisteredErr{schemeName: schemeName, t: t}
}
func NewNotRegisteredErrForTarget(t reflect.Type, target GroupVersioner) error {
return &notRegisteredErr{t: t, target: target}
func NewNotRegisteredErrForTarget(schemeName string, t reflect.Type, target GroupVersioner) error {
return &notRegisteredErr{schemeName: schemeName, t: t, target: target}
}
func NewNotRegisteredGVKErrForTarget(schemeName string, gvk schema.GroupVersionKind, target GroupVersioner) error {
return &notRegisteredErr{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 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

View File

@ -32,7 +32,7 @@ func (re *RawExtension) UnmarshalJSON(in []byte) error {
return nil
}
// Marshal may get called on pointers or values, so implement MarshalJSON on value.
// MarshalJSON may get called on pointers or values, so implement MarshalJSON on value.
// http://stackoverflow.com/questions/21390979/custom-marshaljson-never-gets-called-in-go
func (re RawExtension) MarshalJSON() ([]byte, error) {
if re.Raw == nil {

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Kubernetes Authors.
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,9 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by protoc-gen-gogo.
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime/generated.proto
// DO NOT EDIT!
/*
Package runtime is a generated protocol buffer package.
@ -158,24 +157,6 @@ func (m *Unknown) MarshalTo(dAtA []byte) (int, error) {
return i, nil
}
func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
dAtA[offset+4] = uint8(v >> 32)
dAtA[offset+5] = uint8(v >> 40)
dAtA[offset+6] = uint8(v >> 48)
dAtA[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
@ -744,30 +725,29 @@ func init() {
}
var fileDescriptorGenerated = []byte{
// 395 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x90, 0x4f, 0x6f, 0xd3, 0x30,
0x18, 0xc6, 0xe3, 0xb5, 0x52, 0x87, 0x5b, 0x69, 0xc8, 0x1c, 0x08, 0x3b, 0x38, 0x53, 0x4f, 0xec,
0x30, 0x5b, 0x1a, 0x42, 0xe2, 0xba, 0x4c, 0x93, 0x40, 0x08, 0x09, 0x59, 0xfc, 0x91, 0x38, 0xe1,
0x26, 0x26, 0xb3, 0x42, 0x5f, 0x47, 0x8e, 0x43, 0xd8, 0x8d, 0x8f, 0xc0, 0xc7, 0xea, 0x71, 0xc7,
0x9e, 0x2a, 0x1a, 0x3e, 0x04, 0x57, 0x54, 0xd7, 0x2d, 0xa5, 0x08, 0xed, 0x16, 0xbf, 0xcf, 0xf3,
0x7b, 0xde, 0xe7, 0x0d, 0x7e, 0x5e, 0x3e, 0xab, 0x99, 0x36, 0xbc, 0x6c, 0x26, 0xca, 0x82, 0x72,
0xaa, 0xe6, 0x5f, 0x14, 0xe4, 0xc6, 0xf2, 0x20, 0xc8, 0x4a, 0x4f, 0x65, 0x76, 0xad, 0x41, 0xd9,
0x1b, 0x5e, 0x95, 0x05, 0xb7, 0x0d, 0x38, 0x3d, 0x55, 0xbc, 0x50, 0xa0, 0xac, 0x74, 0x2a, 0x67,
0x95, 0x35, 0xce, 0x90, 0x64, 0x0d, 0xb0, 0x5d, 0x80, 0x55, 0x65, 0xc1, 0x02, 0x70, 0x7c, 0x56,
0x68, 0x77, 0xdd, 0x4c, 0x58, 0x66, 0xa6, 0xbc, 0x30, 0x85, 0xe1, 0x9e, 0x9b, 0x34, 0x9f, 0xfc,
0xcb, 0x3f, 0xfc, 0xd7, 0x3a, 0xef, 0xf8, 0xc9, 0xff, 0x0a, 0x34, 0x4e, 0x7f, 0xe6, 0x1a, 0x5c,
0xed, 0xec, 0x7e, 0x89, 0xf1, 0x29, 0x1e, 0x09, 0xd9, 0x5e, 0x7d, 0x75, 0x0a, 0x6a, 0x6d, 0x80,
0x3c, 0xc2, 0x3d, 0x2b, 0xdb, 0x18, 0x9d, 0xa0, 0xc7, 0xa3, 0x74, 0xd0, 0x2d, 0x92, 0x9e, 0x90,
0xad, 0x58, 0xcd, 0xc6, 0x1f, 0xf1, 0xe1, 0x9b, 0x9b, 0x4a, 0xbd, 0x52, 0x4e, 0x92, 0x73, 0x8c,
0x65, 0xa5, 0xdf, 0x29, 0xbb, 0x82, 0xbc, 0xfb, 0x5e, 0x4a, 0x66, 0x8b, 0x24, 0xea, 0x16, 0x09,
0xbe, 0x78, 0xfd, 0x22, 0x28, 0x62, 0xc7, 0x45, 0x4e, 0x70, 0xbf, 0xd4, 0x90, 0xc7, 0x07, 0xde,
0x3d, 0x0a, 0xee, 0xfe, 0x4b, 0x0d, 0xb9, 0xf0, 0xca, 0xf8, 0x17, 0xc2, 0x83, 0xb7, 0x50, 0x82,
0x69, 0x81, 0xbc, 0xc7, 0x87, 0x2e, 0x6c, 0xf3, 0xf9, 0xc3, 0xf3, 0x53, 0x76, 0xc7, 0x0f, 0x63,
0x9b, 0x7a, 0xe9, 0xfd, 0x10, 0xbe, 0x2d, 0x2c, 0xb6, 0x61, 0x9b, 0x0b, 0x0f, 0xfe, 0xbd, 0x90,
0x5c, 0xe0, 0xa3, 0xcc, 0x80, 0x53, 0xe0, 0xae, 0x20, 0x33, 0xb9, 0x86, 0x22, 0xee, 0xf9, 0xb2,
0x0f, 0x43, 0xde, 0xd1, 0xe5, 0xdf, 0xb2, 0xd8, 0xf7, 0x93, 0xa7, 0x78, 0x18, 0x46, 0xab, 0xd5,
0x71, 0xdf, 0xe3, 0x0f, 0x02, 0x3e, 0xbc, 0xfc, 0x23, 0x89, 0x5d, 0x5f, 0x7a, 0x36, 0x5b, 0xd2,
0xe8, 0x76, 0x49, 0xa3, 0xf9, 0x92, 0x46, 0xdf, 0x3a, 0x8a, 0x66, 0x1d, 0x45, 0xb7, 0x1d, 0x45,
0xf3, 0x8e, 0xa2, 0x1f, 0x1d, 0x45, 0xdf, 0x7f, 0xd2, 0xe8, 0xc3, 0x20, 0x1c, 0xfa, 0x3b, 0x00,
0x00, 0xff, 0xff, 0x3f, 0x1e, 0x24, 0x09, 0x85, 0x02, 0x00, 0x00,
// 378 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x8f, 0x4f, 0xab, 0x13, 0x31,
0x14, 0xc5, 0x27, 0xaf, 0x85, 0x3e, 0xd3, 0xc2, 0x93, 0xb8, 0x70, 0x74, 0x91, 0x79, 0x74, 0xe5,
0x5b, 0xbc, 0x04, 0x1e, 0x08, 0x6e, 0x3b, 0xa5, 0xa0, 0x88, 0x20, 0xc1, 0x3f, 0xe0, 0xca, 0x74,
0x26, 0x4e, 0xc3, 0xd0, 0x9b, 0x21, 0xcd, 0x38, 0x76, 0xe7, 0x47, 0xf0, 0x63, 0x75, 0xd9, 0x65,
0x57, 0xc5, 0x8e, 0x1f, 0xc2, 0xad, 0x34, 0x4d, 0x6b, 0xd5, 0x85, 0xbb, 0xe4, 0x9e, 0xf3, 0x3b,
0xf7, 0x1e, 0xfc, 0xbc, 0x7c, 0xb6, 0x60, 0xda, 0xf0, 0xb2, 0x9e, 0x2a, 0x0b, 0xca, 0xa9, 0x05,
0xff, 0xac, 0x20, 0x37, 0x96, 0x07, 0x41, 0x56, 0x7a, 0x2e, 0xb3, 0x99, 0x06, 0x65, 0x97, 0xbc,
0x2a, 0x0b, 0x6e, 0x6b, 0x70, 0x7a, 0xae, 0x78, 0xa1, 0x40, 0x59, 0xe9, 0x54, 0xce, 0x2a, 0x6b,
0x9c, 0x21, 0xc9, 0x01, 0x60, 0xe7, 0x00, 0xab, 0xca, 0x82, 0x05, 0xe0, 0xf1, 0x6d, 0xa1, 0xdd,
0xac, 0x9e, 0xb2, 0xcc, 0xcc, 0x79, 0x61, 0x0a, 0xc3, 0x3d, 0x37, 0xad, 0x3f, 0xf9, 0x9f, 0xff,
0xf8, 0xd7, 0x21, 0x6f, 0x78, 0x83, 0x07, 0x42, 0x36, 0x93, 0x2f, 0x4e, 0xc1, 0x42, 0x1b, 0x20,
0x8f, 0x70, 0xc7, 0xca, 0x26, 0x46, 0xd7, 0xe8, 0xc9, 0x20, 0xed, 0xb5, 0xdb, 0xa4, 0x23, 0x64,
0x23, 0xf6, 0xb3, 0xe1, 0x47, 0x7c, 0xf9, 0x66, 0x59, 0xa9, 0x57, 0xca, 0x49, 0x72, 0x87, 0xb1,
0xac, 0xf4, 0x3b, 0x65, 0xf7, 0x90, 0x77, 0xdf, 0x4b, 0xc9, 0x6a, 0x9b, 0x44, 0xed, 0x36, 0xc1,
0xa3, 0xd7, 0x2f, 0x82, 0x22, 0xce, 0x5c, 0xe4, 0x1a, 0x77, 0x4b, 0x0d, 0x79, 0x7c, 0xe1, 0xdd,
0x83, 0xe0, 0xee, 0xbe, 0xd4, 0x90, 0x0b, 0xaf, 0x0c, 0x7f, 0x22, 0xdc, 0x7b, 0x0b, 0x25, 0x98,
0x06, 0xc8, 0x7b, 0x7c, 0xe9, 0xc2, 0x36, 0x9f, 0xdf, 0xbf, 0xbb, 0x61, 0xff, 0xe9, 0xce, 0x8e,
0xe7, 0xa5, 0xf7, 0x43, 0xf8, 0xe9, 0x60, 0x71, 0x0a, 0x3b, 0x36, 0xbc, 0xf8, 0xb7, 0x21, 0x19,
0xe1, 0xab, 0xcc, 0x80, 0x53, 0xe0, 0x26, 0x90, 0x99, 0x5c, 0x43, 0x11, 0x77, 0xfc, 0xb1, 0x0f,
0x43, 0xde, 0xd5, 0xf8, 0x4f, 0x59, 0xfc, 0xed, 0x27, 0x4f, 0x71, 0x3f, 0x8c, 0xf6, 0xab, 0xe3,
0xae, 0xc7, 0x1f, 0x04, 0xbc, 0x3f, 0xfe, 0x2d, 0x89, 0x73, 0x5f, 0x7a, 0xbb, 0xda, 0xd1, 0x68,
0xbd, 0xa3, 0xd1, 0x66, 0x47, 0xa3, 0xaf, 0x2d, 0x45, 0xab, 0x96, 0xa2, 0x75, 0x4b, 0xd1, 0xa6,
0xa5, 0xe8, 0x7b, 0x4b, 0xd1, 0xb7, 0x1f, 0x34, 0xfa, 0xd0, 0x0b, 0x45, 0x7f, 0x05, 0x00, 0x00,
0xff, 0xff, 0xe3, 0x33, 0x18, 0x0b, 0x50, 0x02, 0x00, 0x00,
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Kubernetes Authors.
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -21,17 +21,15 @@ syntax = 'proto2';
package k8s.io.apimachinery.pkg.runtime;
import "k8s.io/apimachinery/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated".
option go_package = "runtime";
// RawExtension is used to hold extensions in external versions.
//
//
// To use this, make a field which has RawExtension as its type in your external, versioned
// struct, and Object in your internal struct. You also need to register your
// various plugin types.
//
//
// // Internal package:
// type MyAPIObject struct {
// runtime.TypeMeta `json:",inline"`
@ -40,7 +38,7 @@ option go_package = "runtime";
// type PluginA struct {
// AOption string `json:"aOption"`
// }
//
//
// // External package:
// type MyAPIObject struct {
// runtime.TypeMeta `json:",inline"`
@ -49,7 +47,7 @@ option go_package = "runtime";
// type PluginA struct {
// AOption string `json:"aOption"`
// }
//
//
// // On the wire, the JSON will look something like this:
// {
// "kind":"MyAPIObject",
@ -59,7 +57,7 @@ option go_package = "runtime";
// "aOption":"foo",
// },
// }
//
//
// So what happens? Decode first uses json or yaml to unmarshal the serialized data into
// your external MyAPIObject. That causes the raw JSON to be stored, but not unpacked.
// The next step is to copy (using pkg/conversion) into the internal struct. The runtime
@ -67,13 +65,13 @@ option go_package = "runtime";
// JSON stored in RawExtension, turning it into the correct object type, and storing it
// in the Object. (TODO: In the case where the object is of an unknown type, a
// runtime.Unknown object will be created and stored.)
//
//
// +k8s:deepcopy-gen=true
// +protobuf=true
// +k8s:openapi-gen=true
message RawExtension {
// Raw is the underlying serialization of this object.
//
//
// TODO: Determine how to detect ContentType and ContentEncoding of 'Raw' data.
optional bytes raw = 1;
}
@ -85,10 +83,10 @@ message RawExtension {
// ... // other fields
// }
// func (obj *MyAwesomeAPIObject) SetGroupVersionKind(gvk *metav1.GroupVersionKind) { metav1.UpdateTypeMeta(obj,gvk) }; GroupVersionKind() *GroupVersionKind
//
//
// TypeMeta is provided here for convenience. You may use it directly from this package or define
// your own with the same fields.
//
//
// +k8s:deepcopy-gen=false
// +protobuf=true
// +k8s:openapi-gen=true
@ -105,7 +103,7 @@ message TypeMeta {
// TypeMeta features-- kind, version, etc.
// TODO: Make this object have easy access to field based accessors and settors for
// metadata and field mutatation.
//
//
// +k8s:deepcopy-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +protobuf=true

View File

@ -87,7 +87,7 @@ func Field(v reflect.Value, fieldName string, dest interface{}) error {
return fmt.Errorf("couldn't assign/convert %v to %v", field.Type(), destValue.Type())
}
// fieldPtr puts the address of fieldName, which must be a member of v,
// FieldPtr puts the address of fieldName, which must be a member of v,
// into dest, which must be an address of a variable to which this field's
// address can be assigned.
func FieldPtr(v reflect.Value, fieldName string, dest interface{}) error {

View File

@ -39,14 +39,14 @@ type GroupVersioner interface {
KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (target schema.GroupVersionKind, ok bool)
}
// Encoders write objects to a serialized form
// Encoder writes objects to a serialized form
type Encoder interface {
// Encode writes an object to a stream. Implementations may return errors if the versions are
// incompatible, or if no conversion is defined.
Encode(obj Object, w io.Writer) error
}
// Decoders attempt to load an object from data.
// Decoder attempts to load an object from data.
type Decoder interface {
// Decode attempts to deserialize the provided data using either the innate typing of the scheme or the
// default kind, group, and version provided. It returns a decoded object as well as the kind, group, and
@ -174,15 +174,18 @@ type ObjectVersioner interface {
// ObjectConvertor converts an object to a different version.
type ObjectConvertor interface {
// Convert attempts to convert one object into another, or returns an error. This method does
// not guarantee the in object is not mutated. The context argument will be passed to
// all nested conversions.
// Convert attempts to convert one object into another, or returns an error. This
// method does not mutate the in object, but the in and out object might share data structures,
// i.e. the out object cannot be mutated without mutating the in object as well.
// The context argument will be passed to all nested conversions.
Convert(in, out, context interface{}) error
// ConvertToVersion takes the provided object and converts it the provided version. This
// method does not guarantee that the in object is not mutated. This method is similar to
// Convert() but handles specific details of choosing the correct output version.
// method does not mutate the in object, but the in and out object might share data structures,
// i.e. the out object cannot be mutated without mutating the in object as well.
// This method is similar to Convert() but handles specific details of choosing the correct
// output version.
ConvertToVersion(in Object, gv GroupVersioner) (out Object, err error)
ConvertFieldLabel(version, kind, label, value string) (string, string, error)
ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error)
}
// ObjectTyper contains methods for extracting the APIVersion and Kind
@ -221,7 +224,7 @@ type SelfLinker interface {
Namespace(obj Object) (string, error)
}
// All API types registered with Scheme must support the Object interface. Since objects in a scheme are
// Object interface must be supported by all API types registered with Scheme. Since objects in a scheme are
// expected to be serialized to the wire, the interface an Object must provide to the Scheme allows
// serializers to set the kind, version, and group the object is represented as. An Object may choose
// to return a no-op ObjectKindAccessor in cases where it is not expected to be serialized.
@ -234,9 +237,9 @@ type Object interface {
// to JSON allowed.
type Unstructured interface {
Object
// UnstructuredContent returns a non-nil, mutable map of the contents of this object. Values may be
// UnstructuredContent returns a non-nil map with this object's contents. Values may be
// []interface{}, map[string]interface{}, or any primitive type. Contents are typically serialized to
// and from JSON.
// and from JSON. SetUnstructuredContent should be used to mutate the contents.
UnstructuredContent() map[string]interface{}
// SetUnstructuredContent updates the object content to match the provided map.
SetUnstructuredContent(map[string]interface{})

View File

@ -0,0 +1,150 @@
/*
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 runtime
import (
"testing"
"reflect"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff"
)
func TestPreferredVersionsAllGroups(t *testing.T) {
tests := []struct {
name string
versionPriority map[string][]string
observedVersions []schema.GroupVersion
expectedPrioritized map[string][]schema.GroupVersion
expectedPreferred map[schema.GroupVersion]bool
}{
{
name: "observedOnly",
observedVersions: []schema.GroupVersion{
{Group: "", Version: "v3"},
{Group: "foo", Version: "v1"},
{Group: "foo", Version: "v2"},
{Group: "", Version: "v1"},
},
expectedPrioritized: map[string][]schema.GroupVersion{
"": {
{Group: "", Version: "v3"},
{Group: "", Version: "v1"},
},
"foo": {
{Group: "foo", Version: "v1"},
{Group: "foo", Version: "v2"},
},
},
expectedPreferred: map[schema.GroupVersion]bool{
{Group: "", Version: "v3"}: true,
{Group: "foo", Version: "v1"}: true,
},
},
{
name: "specifiedOnly",
versionPriority: map[string][]string{
"": {"v3", "v1"},
"foo": {"v1", "v2"},
},
expectedPrioritized: map[string][]schema.GroupVersion{
"": {
{Group: "", Version: "v3"},
{Group: "", Version: "v1"},
},
"foo": {
{Group: "foo", Version: "v1"},
{Group: "foo", Version: "v2"},
},
},
expectedPreferred: map[schema.GroupVersion]bool{
{Group: "", Version: "v3"}: true,
{Group: "foo", Version: "v1"}: true,
},
},
{
name: "both",
versionPriority: map[string][]string{
"": {"v3", "v1"},
"foo": {"v1", "v2"},
},
observedVersions: []schema.GroupVersion{
{Group: "", Version: "v1"},
{Group: "", Version: "v3"},
{Group: "", Version: "v4"},
{Group: "", Version: "v5"},
{Group: "bar", Version: "v1"},
{Group: "bar", Version: "v2"},
},
expectedPrioritized: map[string][]schema.GroupVersion{
"": {
{Group: "", Version: "v3"},
{Group: "", Version: "v1"},
{Group: "", Version: "v4"},
{Group: "", Version: "v5"},
},
"foo": {
{Group: "foo", Version: "v1"},
{Group: "foo", Version: "v2"},
},
"bar": {
{Group: "bar", Version: "v1"},
{Group: "bar", Version: "v2"},
},
},
expectedPreferred: map[schema.GroupVersion]bool{
{Group: "", Version: "v3"}: true,
{Group: "foo", Version: "v1"}: true,
{Group: "bar", Version: "v1"}: true,
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
scheme := NewScheme()
scheme.versionPriority = test.versionPriority
scheme.observedVersions = test.observedVersions
for group, expected := range test.expectedPrioritized {
actual := scheme.PrioritizedVersionsForGroup(group)
if !reflect.DeepEqual(expected, actual) {
t.Error(diff.ObjectDiff(expected, actual))
}
}
prioritizedAll := scheme.PrioritizedVersionsAllGroups()
actualPrioritizedAll := map[string][]schema.GroupVersion{}
for _, actual := range prioritizedAll {
actualPrioritizedAll[actual.Group] = append(actualPrioritizedAll[actual.Group], actual)
}
if !reflect.DeepEqual(test.expectedPrioritized, actualPrioritizedAll) {
t.Error(diff.ObjectDiff(test.expectedPrioritized, actualPrioritizedAll))
}
preferredAll := scheme.PreferredVersionAllGroups()
actualPreferredAll := map[schema.GroupVersion]bool{}
for _, actual := range preferredAll {
actualPreferredAll[actual] = true
}
if !reflect.DeepEqual(test.expectedPreferred, actualPreferredAll) {
t.Error(diff.ObjectDiff(test.expectedPreferred, actualPreferredAll))
}
})
}
}

View File

@ -1,43 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["group_version_test.go"],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"generated.pb.go",
"group_version.go",
"interfaces.go",
],
importpath = "k8s.io/apimachinery/pkg/runtime/schema",
deps = ["//vendor/github.com/gogo/protobuf/proto:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
filegroup(
name = "go_default_library_protos",
srcs = ["generated.proto"],
visibility = ["//visibility:public"],
)

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Kubernetes Authors.
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,17 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by protoc-gen-gogo.
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto
// DO NOT EDIT!
/*
Package schema is a generated protocol buffer package.
Package schema is a generated protocol buffer package.
It is generated from these files:
k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto
It is generated from these files:
k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto
It has these top-level messages:
It has these top-level messages:
*/
package schema
@ -48,18 +47,17 @@ func init() {
}
var fileDescriptorGenerated = []byte{
// 202 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0xce, 0xaf, 0x4e, 0x04, 0x31,
0x10, 0xc7, 0xf1, 0xd6, 0x20, 0x90, 0xc8, 0x13, 0x23, 0x51, 0xd0, 0x11, 0x18, 0x34, 0x2f, 0x80,
0xc7, 0x75, 0xf7, 0x86, 0x6e, 0x53, 0xfa, 0x27, 0xed, 0x94, 0x04, 0xc7, 0x23, 0xf0, 0x58, 0x27,
0x4f, 0xae, 0x64, 0xcb, 0x8b, 0x90, 0xb4, 0x2b, 0x08, 0xc9, 0xb9, 0xfe, 0xd2, 0x7c, 0x26, 0xdf,
0xeb, 0x67, 0xf7, 0x58, 0x94, 0x8d, 0xe8, 0xea, 0x44, 0x39, 0x10, 0x53, 0xc1, 0x77, 0x0a, 0xc7,
0x98, 0x71, 0xff, 0xd0, 0xc9, 0x7a, 0x3d, 0x2f, 0x36, 0x50, 0xfe, 0xc0, 0xe4, 0x0c, 0xe6, 0x1a,
0xd8, 0x7a, 0xc2, 0x32, 0x2f, 0xe4, 0x35, 0x1a, 0x0a, 0x94, 0x35, 0xd3, 0x51, 0xa5, 0x1c, 0x39,
0xde, 0xdc, 0x0e, 0xa7, 0xfe, 0x3a, 0x95, 0x9c, 0x51, 0xbb, 0x53, 0xc3, 0x1d, 0xee, 0x8d, 0xe5,
0xa5, 0x4e, 0x6a, 0x8e, 0x1e, 0x4d, 0x34, 0x11, 0x3b, 0x9f, 0xea, 0x6b, 0x5f, 0x7d, 0xf4, 0xd7,
0x38, 0x7b, 0x78, 0xb8, 0x94, 0x53, 0xd9, 0xbe, 0xa1, 0x0d, 0x5c, 0x38, 0xff, 0x6f, 0x79, 0xba,
0x3b, 0x6d, 0x20, 0xce, 0x1b, 0x88, 0x75, 0x03, 0xf1, 0xd9, 0x40, 0x9e, 0x1a, 0xc8, 0x73, 0x03,
0xb9, 0x36, 0x90, 0xdf, 0x0d, 0xe4, 0xd7, 0x0f, 0x88, 0x97, 0xab, 0x51, 0xf4, 0x1b, 0x00, 0x00,
0xff, 0xff, 0xfd, 0x59, 0x57, 0x93, 0x0b, 0x01, 0x00, 0x00,
// 185 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0xcc, 0xaf, 0x6e, 0xc3, 0x30,
0x10, 0xc7, 0x71, 0x9b, 0x0c, 0x0c, 0x0e, 0x0e, 0x1c, 0x1c, 0xda, 0x7c, 0x74, 0xb8, 0x2f, 0x50,
0x5e, 0xe6, 0x24, 0x57, 0xc7, 0xb2, 0xfc, 0x47, 0x8e, 0x5d, 0xa9, 0xac, 0x8f, 0xd0, 0xc7, 0x0a,
0x0c, 0x0c, 0x6c, 0xdc, 0x17, 0xa9, 0x64, 0x07, 0x94, 0xdd, 0x4f, 0xa7, 0xcf, 0xf7, 0xf3, 0x68,
0xfe, 0x27, 0xa1, 0x3d, 0x9a, 0xdc, 0x51, 0x74, 0x94, 0x68, 0xc2, 0x0b, 0xb9, 0xc1, 0x47, 0xdc,
0x1f, 0x32, 0x68, 0x2b, 0xfb, 0x51, 0x3b, 0x8a, 0x57, 0x0c, 0x46, 0x61, 0xcc, 0x2e, 0x69, 0x4b,
0x38, 0xf5, 0x23, 0x59, 0x89, 0x8a, 0x1c, 0x45, 0x99, 0x68, 0x10, 0x21, 0xfa, 0xe4, 0xbf, 0x7e,
0x9a, 0x13, 0xef, 0x4e, 0x04, 0xa3, 0xc4, 0xee, 0x44, 0x73, 0xdf, 0x7f, 0x4a, 0xa7, 0x31, 0x77,
0xa2, 0xf7, 0x16, 0x95, 0x57, 0x1e, 0x2b, 0xef, 0xf2, 0xb9, 0xae, 0x3a, 0xea, 0xd5, 0xb2, 0x87,
0xdf, 0x79, 0x03, 0xb6, 0x6c, 0xc0, 0xd6, 0x0d, 0xd8, 0xad, 0x00, 0x9f, 0x0b, 0xf0, 0xa5, 0x00,
0x5f, 0x0b, 0xf0, 0x47, 0x01, 0x7e, 0x7f, 0x02, 0x3b, 0x7d, 0xb4, 0xf8, 0x2b, 0x00, 0x00, 0xff,
0xff, 0xba, 0x7e, 0x65, 0xf4, 0xd6, 0x00, 0x00, 0x00,
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 The Kubernetes Authors.
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -21,8 +21,6 @@ syntax = 'proto2';
package k8s.io.apimachinery.pkg.runtime.schema;
import "k8s.io/apimachinery/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated".
option go_package = "schema";

View File

@ -66,7 +66,7 @@ func (gr GroupResource) Empty() bool {
return len(gr.Group) == 0 && len(gr.Resource) == 0
}
func (gr *GroupResource) String() string {
func (gr GroupResource) String() string {
if len(gr.Group) == 0 {
return gr.Resource
}
@ -85,11 +85,10 @@ func ParseGroupKind(gk string) GroupKind {
// ParseGroupResource turns "resource.group" string into a GroupResource struct. Empty strings are allowed
// for each field.
func ParseGroupResource(gr string) GroupResource {
if i := strings.Index(gr, "."); i == -1 {
return GroupResource{Resource: gr}
} else {
if i := strings.Index(gr, "."); i >= 0 {
return GroupResource{Group: gr[i+1:], Resource: gr[:i]}
}
return GroupResource{Resource: gr}
}
// GroupVersionResource unambiguously identifies a resource. It doesn't anonymously include GroupVersion
@ -112,7 +111,7 @@ func (gvr GroupVersionResource) GroupVersion() GroupVersion {
return GroupVersion{Group: gvr.Group, Version: gvr.Version}
}
func (gvr *GroupVersionResource) String() string {
func (gvr GroupVersionResource) String() string {
return strings.Join([]string{gvr.Group, "/", gvr.Version, ", Resource=", gvr.Resource}, "")
}
@ -131,7 +130,7 @@ func (gk GroupKind) WithVersion(version string) GroupVersionKind {
return GroupVersionKind{Group: gk.Group, Version: version, Kind: gk.Kind}
}
func (gk *GroupKind) String() string {
func (gk GroupKind) String() string {
if len(gk.Group) == 0 {
return gk.Kind
}
@ -282,8 +281,8 @@ func bestMatch(kinds []GroupVersionKind, targets []GroupVersionKind) GroupVersio
// ToAPIVersionAndKind is a convenience method for satisfying runtime.Object on types that
// do not use TypeMeta.
func (gvk *GroupVersionKind) ToAPIVersionAndKind() (string, string) {
if gvk == nil {
func (gvk GroupVersionKind) ToAPIVersionAndKind() (string, string) {
if gvk.Empty() {
return "", ""
}
return gvk.GroupVersion().String(), gvk.Kind

View File

@ -134,3 +134,47 @@ func TestKindForGroupVersionKinds(t *testing.T) {
}
}
}
func TestParseKindArg(t *testing.T) {
tests := []struct {
input string
gvk *GroupVersionKind
gk GroupKind
}{
{input: "Pod", gk: GroupKind{Kind: "Pod"}},
{input: ".apps", gk: GroupKind{Group: "apps"}},
{input: "Pod.", gk: GroupKind{Kind: "Pod"}},
{input: "StatefulSet.apps", gk: GroupKind{Group: "apps", Kind: "StatefulSet"}},
{input: "StatefulSet.v1.apps", gvk: &GroupVersionKind{Group: "apps", Version: "v1", Kind: "StatefulSet"}, gk: GroupKind{Group: "v1.apps", Kind: "StatefulSet"}},
}
for i, test := range tests {
t.Run(test.input, func(t *testing.T) {
gvk, gk := ParseKindArg(test.input)
if (gvk != nil && test.gvk == nil) || (gvk == nil && test.gvk != nil) || (test.gvk != nil && *gvk != *test.gvk) {
t.Errorf("%d: expected output: %#v, got: %#v", i, test.gvk, gvk)
}
if gk != test.gk {
t.Errorf("%d: expected output: %#v, got: %#v", i, test.gk, gk)
}
})
}
}
func TestParseGroupKind(t *testing.T) {
tests := []struct {
input string
out GroupKind
}{
{input: "Pod", out: GroupKind{Kind: "Pod"}},
{input: ".StatefulSet", out: GroupKind{Group: "StatefulSet"}},
{input: "StatefulSet.apps", out: GroupKind{Group: "apps", Kind: "StatefulSet"}},
}
for i, test := range tests {
t.Run(test.input, func(t *testing.T) {
out := ParseGroupKind(test.input)
if out != test.out {
t.Errorf("%d: expected output: %#v, got: %#v", i, test.out, out)
}
})
}
}

View File

@ -20,9 +20,13 @@ 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"
)
// Scheme defines methods for serializing and deserializing API objects, a type
@ -59,18 +63,29 @@ type Scheme struct {
// Map from version and resource to the corresponding func to convert
// resource field labels in that version to internal version.
fieldLabelConversionFuncs map[string]map[string]FieldLabelConversionFunc
fieldLabelConversionFuncs map[schema.GroupVersionKind]FieldLabelConversionFunc
// defaulterFuncs is an array of interfaces to be called with an object to provide defaulting
// the provided object must be a pointer.
defaulterFuncs map[reflect.Type]func(interface{})
// converter stores all registered conversion functions. It also has
// default coverting behavior.
// default converting behavior.
converter *conversion.Converter
// versionPriority is a map of groups to ordered lists of versions for those groups indicating the
// default priorities of these versions as registered in the scheme
versionPriority map[string][]string
// 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
}
// Function to convert a field selector to internal representation.
// FieldLabelConversionFunc converts a field selector to internal representation.
type FieldLabelConversionFunc func(label, value string) (internalLabel, internalValue string, err error)
// NewScheme creates a new Scheme. This scheme is pluggable by default.
@ -80,23 +95,19 @@ func NewScheme() *Scheme {
typeToGVK: map[reflect.Type][]schema.GroupVersionKind{},
unversionedTypes: map[reflect.Type]schema.GroupVersionKind{},
unversionedKinds: map[string]reflect.Type{},
fieldLabelConversionFuncs: map[string]map[string]FieldLabelConversionFunc{},
fieldLabelConversionFuncs: map[schema.GroupVersionKind]FieldLabelConversionFunc{},
defaulterFuncs: map[reflect.Type]func(interface{}){},
versionPriority: map[string][]string{},
schemeName: naming.GetNameFromCallsite(internalPackages...),
}
s.converter = conversion.NewConverter(s.nameFunc)
s.AddConversionFuncs(DefaultEmbeddedConversions()...)
utilruntime.Must(s.AddConversionFuncs(DefaultEmbeddedConversions()...))
// Enable map[string][]string conversions by default
if err := s.AddConversionFuncs(DefaultStringConversions...); err != nil {
panic(err)
}
if err := s.RegisterInputDefaults(&map[string][]string{}, JSONKeyMapper, conversion.AllowDifferentFieldTypeNames|conversion.IgnoreMissingFields); err != nil {
panic(err)
}
if err := s.RegisterInputDefaults(&url.Values{}, JSONKeyMapper, conversion.AllowDifferentFieldTypeNames|conversion.IgnoreMissingFields); err != nil {
panic(err)
}
utilruntime.Must(s.AddConversionFuncs(DefaultStringConversions...))
utilruntime.Must(s.RegisterInputDefaults(&map[string][]string{}, JSONKeyMapper, conversion.AllowDifferentFieldTypeNames|conversion.IgnoreMissingFields))
utilruntime.Must(s.RegisterInputDefaults(&url.Values{}, JSONKeyMapper, conversion.AllowDifferentFieldTypeNames|conversion.IgnoreMissingFields))
return s
}
@ -111,7 +122,7 @@ func (s *Scheme) nameFunc(t reflect.Type) string {
for _, gvk := range gvks {
internalGV := gvk.GroupVersion()
internalGV.Version = "__internal" // this is hacky and maybe should be passed in
internalGV.Version = APIVersionInternal // this is hacky and maybe should be passed in
internalGVK := internalGV.WithKind(gvk.Kind)
if internalType, exists := s.gvkToType[internalGVK]; exists {
@ -141,13 +152,14 @@ func (s *Scheme) Converter() *conversion.Converter {
// TODO: there is discussion about removing unversioned and replacing it with objects that are manifest into
// every version with particular schemas. Resolve this method at that point.
func (s *Scheme) AddUnversionedTypes(version schema.GroupVersion, types ...Object) {
s.addObservedVersion(version)
s.AddKnownTypes(version, types...)
for _, obj := range types {
t := reflect.TypeOf(obj).Elem()
gvk := version.WithKind(t.Name())
s.unversionedTypes[t] = gvk
if old, ok := s.unversionedKinds[gvk.Kind]; ok && t != old {
panic(fmt.Sprintf("%v.%v has already been registered as unversioned kind %q - kind name must be unique", old.PkgPath(), old.Name(), gvk))
panic(fmt.Sprintf("%v.%v has already been registered as unversioned kind %q - kind name must be unique in scheme %q", old.PkgPath(), old.Name(), gvk, s.schemeName))
}
s.unversionedKinds[gvk.Kind] = t
}
@ -158,6 +170,7 @@ func (s *Scheme) AddUnversionedTypes(version schema.GroupVersion, types ...Objec
// the struct becomes the "kind" field when encoding. Version may not be empty - use the
// APIVersionInternal constant if you have a type that does not have a formal version.
func (s *Scheme) AddKnownTypes(gv schema.GroupVersion, types ...Object) {
s.addObservedVersion(gv)
for _, obj := range types {
t := reflect.TypeOf(obj)
if t.Kind() != reflect.Ptr {
@ -173,6 +186,7 @@ func (s *Scheme) AddKnownTypes(gv schema.GroupVersion, types ...Object) {
// your structs. Version may not be empty - use the APIVersionInternal constant if you have a
// type that does not have a formal version.
func (s *Scheme) AddKnownTypeWithName(gvk schema.GroupVersionKind, obj Object) {
s.addObservedVersion(gvk.GroupVersion())
t := reflect.TypeOf(obj)
if len(gvk.Version) == 0 {
panic(fmt.Sprintf("version is required on all types: %s %v", gvk, t))
@ -186,7 +200,7 @@ func (s *Scheme) AddKnownTypeWithName(gvk schema.GroupVersionKind, obj Object) {
}
if oldT, found := s.gvkToType[gvk]; found && oldT != t {
panic(fmt.Sprintf("Double registration of different types for %v: old=%v.%v, new=%v.%v", gvk, oldT.PkgPath(), oldT.Name(), t.PkgPath(), t.Name()))
panic(fmt.Sprintf("Double registration of different types for %v: old=%v.%v, new=%v.%v in scheme %q", gvk, oldT.PkgPath(), oldT.Name(), t.PkgPath(), t.Name(), s.schemeName))
}
s.gvkToType[gvk] = t
@ -241,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]
@ -279,15 +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)
}
// AddGenericConversionFunc adds a function that accepts the ConversionFunc call pattern
// (for two conversion types) to the converter. These functions are checked first during
// a normal conversion, but are otherwise not called. Use AddConversionFuncs when registering
// typed conversions.
func (s *Scheme) AddGenericConversionFunc(fn conversion.GenericConversionFunc) {
s.converter.AddGenericConversionFunc(fn)
return nil, NewNotRegisteredErrForKind(s.schemeName, kind)
}
// Log sets a logger on the scheme. For test purposes only
@ -341,36 +347,27 @@ func (s *Scheme) AddConversionFuncs(conversionFuncs ...interface{}) error {
return nil
}
// AddGeneratedConversionFuncs registers conversion functions that were
// automatically generated.
func (s *Scheme) AddGeneratedConversionFuncs(conversionFuncs ...interface{}) error {
for _, f := range conversionFuncs {
if err := s.converter.RegisterGeneratedConversionFunc(f); err != nil {
return err
}
}
return nil
// AddConversionFunc registers a function that converts between a and b by passing objects of those
// types to the provided function. The function *must* accept objects of a and b - this machinery will not enforce
// any other guarantee.
func (s *Scheme) AddConversionFunc(a, b interface{}, fn conversion.ConversionFunc) error {
return s.converter.RegisterUntypedConversionFunc(a, b, fn)
}
// AddGeneratedConversionFunc registers a function that converts between a and b by passing objects of those
// types to the provided function. The function *must* accept objects of a and b - this machinery will not enforce
// any other guarantee.
func (s *Scheme) AddGeneratedConversionFunc(a, b interface{}, fn conversion.ConversionFunc) error {
return s.converter.RegisterGeneratedUntypedConversionFunc(a, b, fn)
}
// AddFieldLabelConversionFunc adds a conversion function to convert field selectors
// of the given kind from the given version to internal version representation.
func (s *Scheme) AddFieldLabelConversionFunc(version, kind string, conversionFunc FieldLabelConversionFunc) error {
if s.fieldLabelConversionFuncs[version] == nil {
s.fieldLabelConversionFuncs[version] = map[string]FieldLabelConversionFunc{}
}
s.fieldLabelConversionFuncs[version][kind] = conversionFunc
func (s *Scheme) AddFieldLabelConversionFunc(gvk schema.GroupVersionKind, conversionFunc FieldLabelConversionFunc) error {
s.fieldLabelConversionFuncs[gvk] = conversionFunc
return nil
}
// AddStructFieldConversion allows you to specify a mechanical copy for a moved
// or renamed struct field without writing an entire conversion function. See
// the comment in conversion.Converter.SetStructFieldCopy for parameter details.
// Call as many times as needed, even on the same fields.
func (s *Scheme) AddStructFieldConversion(srcFieldType interface{}, srcFieldName string, destFieldType interface{}, destFieldName string) error {
return s.converter.SetStructFieldCopy(srcFieldType, srcFieldName, destFieldType, destFieldName)
}
// RegisterInputDefaults sets the provided field mapping function and field matching
// as the defaults for the provided input type. The fn may be nil, in which case no
// mapping will happen by default. Use this method to register a mechanism for handling
@ -379,7 +376,7 @@ func (s *Scheme) RegisterInputDefaults(in interface{}, fn conversion.FieldMappin
return s.converter.RegisterInputDefaults(in, fn, defaultFlags)
}
// AddTypeDefaultingFuncs registers a function that is passed a pointer to an
// AddTypeDefaultingFunc registers a function that is passed a pointer to an
// object and can default fields on the object. These functions will be invoked
// when Default() is called. The function will never be called unless the
// defaulted object matches srcType. If this function is invoked twice with the
@ -472,11 +469,8 @@ func (s *Scheme) Convert(in, out interface{}, context interface{}) error {
// ConvertFieldLabel alters the given field label and value for an kind field selector from
// versioned representation to an unversioned one or returns an error.
func (s *Scheme) ConvertFieldLabel(version, kind, label, value string) (string, string, error) {
if s.fieldLabelConversionFuncs[version] == nil {
return DefaultMetaV1FieldSelectorConversion(label, value)
}
conversionFunc, ok := s.fieldLabelConversionFuncs[version][kind]
func (s *Scheme) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
conversionFunc, ok := s.fieldLabelConversionFuncs[gvk]
if !ok {
return DefaultMetaV1FieldSelectorConversion(label, value)
}
@ -527,7 +521,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)
@ -540,7 +534,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)
@ -620,3 +614,141 @@ func setTargetKind(obj Object, kind schema.GroupVersionKind) {
}
obj.GetObjectKind().SetGroupVersionKind(kind)
}
// SetVersionPriority allows specifying a precise order of priority. All specified versions must be in the same group,
// and the specified order overwrites any previously specified order for this group
func (s *Scheme) SetVersionPriority(versions ...schema.GroupVersion) error {
groups := sets.String{}
order := []string{}
for _, version := range versions {
if len(version.Version) == 0 || version.Version == APIVersionInternal {
return fmt.Errorf("internal versions cannot be prioritized: %v", version)
}
groups.Insert(version.Group)
order = append(order, version.Version)
}
if len(groups) != 1 {
return fmt.Errorf("must register versions for exactly one group: %v", strings.Join(groups.List(), ", "))
}
s.versionPriority[groups.List()[0]] = order
return nil
}
// PrioritizedVersionsForGroup returns versions for a single group in priority order
func (s *Scheme) PrioritizedVersionsForGroup(group string) []schema.GroupVersion {
ret := []schema.GroupVersion{}
for _, version := range s.versionPriority[group] {
ret = append(ret, schema.GroupVersion{Group: group, Version: version})
}
for _, observedVersion := range s.observedVersions {
if observedVersion.Group != group {
continue
}
found := false
for _, existing := range ret {
if existing == observedVersion {
found = true
break
}
}
if !found {
ret = append(ret, observedVersion)
}
}
return ret
}
// PrioritizedVersionsAllGroups returns all known versions in their priority order. Groups are random, but
// versions for a single group are prioritized
func (s *Scheme) PrioritizedVersionsAllGroups() []schema.GroupVersion {
ret := []schema.GroupVersion{}
for group, versions := range s.versionPriority {
for _, version := range versions {
ret = append(ret, schema.GroupVersion{Group: group, Version: version})
}
}
for _, observedVersion := range s.observedVersions {
found := false
for _, existing := range ret {
if existing == observedVersion {
found = true
break
}
}
if !found {
ret = append(ret, observedVersion)
}
}
return ret
}
// PreferredVersionAllGroups returns the most preferred version for every group.
// group ordering is random.
func (s *Scheme) PreferredVersionAllGroups() []schema.GroupVersion {
ret := []schema.GroupVersion{}
for group, versions := range s.versionPriority {
for _, version := range versions {
ret = append(ret, schema.GroupVersion{Group: group, Version: version})
break
}
}
for _, observedVersion := range s.observedVersions {
found := false
for _, existing := range ret {
if existing.Group == observedVersion.Group {
found = true
break
}
}
if !found {
ret = append(ret, observedVersion)
}
}
return ret
}
// IsGroupRegistered returns true if types for the group have been registered with the scheme
func (s *Scheme) IsGroupRegistered(group string) bool {
for _, observedVersion := range s.observedVersions {
if observedVersion.Group == group {
return true
}
}
return false
}
// IsVersionRegistered returns true if types for the version have been registered with the scheme
func (s *Scheme) IsVersionRegistered(version schema.GroupVersion) bool {
for _, observedVersion := range s.observedVersions {
if observedVersion == version {
return true
}
}
return false
}
func (s *Scheme) addObservedVersion(version schema.GroupVersion) {
if len(version.Version) == 0 || version.Version == APIVersionInternal {
return
}
for _, observedVersion := range s.observedVersions {
if observedVersion == version {
return
}
}
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"}

View File

@ -22,19 +22,15 @@ import (
"strings"
"testing"
"github.com/google/gofuzz"
flag "github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
runtimetesting "k8s.io/apimachinery/pkg/runtime/testing"
"k8s.io/apimachinery/pkg/util/diff"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)
var fuzzIters = flag.Int("fuzz-iters", 50, "How many fuzzing iterations to do.")
func TestScheme(t *testing.T) {
internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal}
internalGVK := internalGV.WithKind("Simple")
@ -460,17 +456,6 @@ func TestUnversionedTypes(t *testing.T) {
}
}
// TestObjectFuzzer can randomly populate all the above objects.
var TestObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 100).Funcs(
func(j *runtimetesting.MyWeirdCustomEmbeddedVersionKindField, c fuzz.Continue) {
// We have to customize the randomization of MyWeirdCustomEmbeddedVersionKindFields because their
// APIVersion and Kind must remain blank in memory.
j.APIVersion = ""
j.ObjectKind = ""
j.ID = c.RandString()
},
)
// Returns a new Scheme set up with the test objects.
func GetTestScheme() *runtime.Scheme {
internalGV := schema.GroupVersion{Version: runtime.APIVersionInternal}
@ -496,9 +481,10 @@ func GetTestScheme() *runtime.Scheme {
s.AddKnownTypeWithName(differentExternalGV.WithKind("TestType1"), &runtimetesting.ExternalTestType1{})
s.AddUnversionedTypes(externalGV, &runtimetesting.UnversionedType{})
s.AddConversionFuncs(func(in *runtimetesting.TestType1, out *runtimetesting.ExternalTestType1, s conversion.Scope) {
utilruntime.Must(s.AddConversionFuncs(func(in *runtimetesting.TestType1, out *runtimetesting.ExternalTestType1, s conversion.Scope) error {
out.A = in.A
})
return nil
}))
return s
}
@ -684,7 +670,7 @@ func TestConvertToVersion(t *testing.T) {
gv: schema.GroupVersions{{Version: runtime.APIVersionInternal}, {Version: "v1"}},
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "v1", ObjectKind: "TestType1"},
A: "test",
A: "test",
},
},
// unversioned type returned as-is
@ -695,7 +681,7 @@ func TestConvertToVersion(t *testing.T) {
same: true,
out: &runtimetesting.UnversionedType{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "v1", ObjectKind: "UnversionedType"},
A: "test",
A: "test",
},
},
// unversioned type returned when not included in the target types
@ -706,7 +692,7 @@ func TestConvertToVersion(t *testing.T) {
same: true,
out: &runtimetesting.UnversionedType{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "v1", ObjectKind: "UnversionedType"},
A: "test",
A: "test",
},
},
// detected as already being in the target version
@ -717,7 +703,7 @@ func TestConvertToVersion(t *testing.T) {
same: true,
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "v1", ObjectKind: "TestType1"},
A: "test",
A: "test",
},
},
// detected as already being in the first target version
@ -728,7 +714,7 @@ func TestConvertToVersion(t *testing.T) {
same: true,
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "v1", ObjectKind: "TestType1"},
A: "test",
A: "test",
},
},
// detected as already being in the first target version
@ -739,7 +725,7 @@ func TestConvertToVersion(t *testing.T) {
same: true,
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "v1", ObjectKind: "TestType1"},
A: "test",
A: "test",
},
},
// the external type is registered in multiple groups, versions, and kinds, and can be targeted to all of them (1/3): different kind
@ -750,7 +736,7 @@ func TestConvertToVersion(t *testing.T) {
same: true,
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "v1", ObjectKind: "TestType3"},
A: "test",
A: "test",
},
},
// the external type is registered in multiple groups, versions, and kinds, and can be targeted to all of them (2/3): different gv
@ -761,7 +747,7 @@ func TestConvertToVersion(t *testing.T) {
same: true,
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "custom/v1", ObjectKind: "TestType3"},
A: "test",
A: "test",
},
},
// the external type is registered in multiple groups, versions, and kinds, and can be targeted to all of them (3/3): different gvk
@ -772,7 +758,7 @@ func TestConvertToVersion(t *testing.T) {
same: true,
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "custom/v1", ObjectKind: "TestType5"},
A: "test",
A: "test",
},
},
// multi group versioner recognizes multiple groups and forces the output to a particular version, copies because version differs
@ -782,7 +768,7 @@ func TestConvertToVersion(t *testing.T) {
gv: runtime.NewMultiGroupVersioner(schema.GroupVersion{Group: "other", Version: "v2"}, schema.GroupKind{Group: "custom", Kind: "TestType3"}, schema.GroupKind{Kind: "TestType1"}),
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "other/v2", ObjectKind: "TestType1"},
A: "test",
A: "test",
},
},
// multi group versioner recognizes multiple groups and forces the output to a particular version, copies because version differs
@ -792,7 +778,7 @@ func TestConvertToVersion(t *testing.T) {
gv: runtime.NewMultiGroupVersioner(schema.GroupVersion{Group: "other", Version: "v2"}, schema.GroupKind{Kind: "TestType1"}, schema.GroupKind{Group: "custom", Kind: "TestType3"}),
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "other/v2", ObjectKind: "TestType1"},
A: "test",
A: "test",
},
},
// multi group versioner is unable to find a match when kind AND group don't match (there is no TestType1 kind in group "other", and no kind "TestType5" in the default group)
@ -812,7 +798,7 @@ func TestConvertToVersion(t *testing.T) {
same: true,
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "v1", ObjectKind: "TestType1"},
A: "test",
A: "test",
},
},
// multi group versioner recognizes multiple groups and forces the output to a particular version, performs no copy
@ -823,7 +809,7 @@ func TestConvertToVersion(t *testing.T) {
same: true,
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "v1", ObjectKind: "TestType1"},
A: "test",
A: "test",
},
},
// group versioner can choose a particular target kind for a given input when kind is the same across group versions
@ -833,7 +819,7 @@ func TestConvertToVersion(t *testing.T) {
gv: testGroupVersioner{ok: true, target: schema.GroupVersionKind{Version: "v1", Kind: "TestType3"}},
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "v1", ObjectKind: "TestType3"},
A: "test",
A: "test",
},
},
// group versioner can choose a different kind
@ -843,7 +829,7 @@ func TestConvertToVersion(t *testing.T) {
gv: testGroupVersioner{ok: true, target: schema.GroupVersionKind{Kind: "TestType5", Group: "custom", Version: "v1"}},
out: &runtimetesting.ExternalTestType1{
MyWeirdCustomEmbeddedVersionKindField: runtimetesting.MyWeirdCustomEmbeddedVersionKindField{APIVersion: "custom/v1", ObjectKind: "TestType5"},
A: "test",
A: "test",
},
},
}

View File

@ -1,64 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["codec_test.go"],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"codec_factory.go",
"negotiated_codec.go",
"protobuf_extension.go",
],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer",
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/streaming:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/testing:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/yaml:all-srcs",
],
tags = ["automanaged"],
)

View File

@ -32,9 +32,9 @@ import (
serializertesting "k8s.io/apimachinery/pkg/runtime/serializer/testing"
"k8s.io/apimachinery/pkg/util/diff"
"github.com/ghodss/yaml"
"github.com/google/gofuzz"
flag "github.com/spf13/pflag"
"sigs.k8s.io/yaml"
)
var fuzzIters = flag.Int("fuzz-iters", 50, "How many fuzzing iterations to do.")

View File

@ -1,55 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["meta_test.go"],
embed = [":go_default_library"],
)
go_library(
name = "go_default_library",
srcs = [
"json.go",
"meta.go",
],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer/json",
deps = [
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/github.com/json-iterator/go:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/framer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
],
)
go_test(
name = "go_default_xtest",
srcs = ["json_test.go"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -22,8 +22,9 @@ import (
"strconv"
"unsafe"
"github.com/ghodss/yaml"
jsoniter "github.com/json-iterator/go"
"github.com/modern-go/reflect2"
"sigs.k8s.io/yaml"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -68,36 +69,62 @@ type Serializer struct {
var _ runtime.Serializer = &Serializer{}
var _ recognizer.RecognizingDecoder = &Serializer{}
func init() {
// Force jsoniter to decode number to interface{} via ints, if possible.
decodeNumberAsInt64IfPossible := func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
switch iter.WhatIsNext() {
case jsoniter.NumberValue:
var number json.Number
iter.ReadVal(&number)
u64, err := strconv.ParseUint(string(number), 10, 64)
if err == nil {
*(*interface{})(ptr) = u64
return
}
i64, err := strconv.ParseInt(string(number), 10, 64)
if err == nil {
*(*interface{})(ptr) = i64
return
}
f64, err := strconv.ParseFloat(string(number), 64)
if err == nil {
*(*interface{})(ptr) = f64
return
}
// Not much we can do here.
default:
*(*interface{})(ptr) = iter.Read()
}
}
jsoniter.RegisterTypeDecoderFunc("interface {}", decodeNumberAsInt64IfPossible)
type customNumberExtension struct {
jsoniter.DummyExtension
}
func (cne *customNumberExtension) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder {
if typ.String() == "interface {}" {
return customNumberDecoder{}
}
return nil
}
type customNumberDecoder struct {
}
func (customNumberDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
switch iter.WhatIsNext() {
case jsoniter.NumberValue:
var number jsoniter.Number
iter.ReadVal(&number)
i64, err := strconv.ParseInt(string(number), 10, 64)
if err == nil {
*(*interface{})(ptr) = i64
return
}
f64, err := strconv.ParseFloat(string(number), 64)
if err == nil {
*(*interface{})(ptr) = f64
return
}
iter.ReportError("DecodeNumber", err.Error())
default:
*(*interface{})(ptr) = iter.Read()
}
}
// CaseSensitiveJsonIterator returns a jsoniterator API that's configured to be
// case-sensitive when unmarshalling, and otherwise compatible with
// the encoding/json standard library.
func CaseSensitiveJsonIterator() jsoniter.API {
config := jsoniter.Config{
EscapeHTML: true,
SortMapKeys: true,
ValidateJsonRawMessage: true,
CaseSensitive: true,
}.Froze()
// Force jsoniter to decode number to interface{} via int64/float64, if possible.
config.RegisterExtension(&customNumberExtension{})
return config
}
// Private copy of jsoniter to try to shield against possible mutations
// from outside. Still does not protect from package level jsoniter.Register*() functions - someone calling them
// in some other library will mess with every usage of the jsoniter library in the whole program.
// See https://github.com/json-iterator/go/issues/265
var caseSensitiveJsonIterator = CaseSensitiveJsonIterator()
// gvkWithDefaults returns group kind and version defaulting from provided default
func gvkWithDefaults(actual, defaultGVK schema.GroupVersionKind) schema.GroupVersionKind {
if len(actual.Kind) == 0 {
@ -162,7 +189,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i
types, _, err := s.typer.ObjectKinds(into)
switch {
case runtime.IsNotRegisteredError(err), isUnstructured:
if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(data, into); err != nil {
if err := caseSensitiveJsonIterator.Unmarshal(data, into); err != nil {
return nil, actual, err
}
return into, actual, nil
@ -186,7 +213,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i
return nil, actual, err
}
if err := jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(data, obj); err != nil {
if err := caseSensitiveJsonIterator.Unmarshal(data, obj); err != nil {
return nil, actual, err
}
return obj, actual, nil
@ -195,7 +222,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *schema.GroupVersionKind, i
// Encode serializes the provided object to the given writer.
func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {
if s.yaml {
json, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(obj)
json, err := caseSensitiveJsonIterator.Marshal(obj)
if err != nil {
return err
}
@ -208,7 +235,7 @@ func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error {
}
if s.pretty {
data, err := jsoniter.ConfigCompatibleWithStandardLibrary.MarshalIndent(obj, "", " ")
data, err := caseSensitiveJsonIterator.MarshalIndent(obj, "", " ")
if err != nil {
return err
}
@ -246,7 +273,7 @@ func (jsonFramer) NewFrameReader(r io.ReadCloser) io.ReadCloser {
return framer.NewJSONFramedReader(r)
}
// Framer is the default JSON framing behavior, with newlines delimiting individual objects.
// YAMLFramer is the default JSON framing behavior, with newlines delimiting individual objects.
var YAMLFramer = yamlFramer{}
type yamlFramer struct{}

View File

@ -29,9 +29,31 @@ import (
)
type testDecodable struct {
Other string
Value int `json:"value"`
gvk schema.GroupVersionKind
Other string
Value int `json:"value"`
Spec DecodableSpec `json:"spec"`
Interface interface{} `json:"interface"`
gvk schema.GroupVersionKind
}
// DecodableSpec has 15 fields. json-iterator treats struct with more than 10
// fields differently from struct that has less than 10 fields.
type DecodableSpec struct {
A int `json:"A"`
B int `json:"B"`
C int `json:"C"`
D int `json:"D"`
E int `json:"E"`
F int `json:"F"`
G int `json:"G"`
H int `json:"h"`
I int `json:"i"`
J int `json:"j"`
K int `json:"k"`
L int `json:"l"`
M int `json:"m"`
N int `json:"n"`
O int `json:"o"`
}
func (d *testDecodable) GetObjectKind() schema.ObjectKind { return d }
@ -158,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",
@ -221,6 +243,37 @@ func TestDecode(t *testing.T) {
},
},
},
// Error on invalid number
{
data: []byte(`{"kind":"Test","apiVersion":"other/blah","interface":1e1000}`),
creater: &mockCreater{obj: &testDecodable{}},
expectedGVK: &schema.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"},
errFn: func(err error) bool {
return strings.Contains(err.Error(), `json_test.testDecodable.Interface: DecodeNumber: strconv.ParseFloat: parsing "1e1000": value out of range`)
},
},
// Unmarshalling is case-sensitive
{
// "VaLue" should have been "value"
data: []byte(`{"kind":"Test","apiVersion":"other/blah","VaLue":1,"Other":"test"}`),
into: &testDecodable{},
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",
},
},
// Unmarshalling is case-sensitive for big struct.
{
// "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("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},
},
},
}
for i, test := range testCases {

View File

@ -1,35 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"protobuf.go",
],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
deps = [
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/framer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -20,10 +20,12 @@ import (
"bytes"
"fmt"
"io"
"net/http"
"reflect"
"github.com/gogo/protobuf/proto"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
@ -50,6 +52,15 @@ func (e errNotMarshalable) Error() string {
return fmt.Sprintf("object %v does not implement the protobuf marshalling interface and cannot be encoded to a protobuf message", e.t)
}
func (e errNotMarshalable) Status() metav1.Status {
return metav1.Status{
Status: metav1.StatusFailure,
Code: http.StatusNotAcceptable,
Reason: metav1.StatusReason("NotAcceptable"),
Message: e.Error(),
}
}
func IsNotMarshalable(err error) bool {
_, ok := err.(errNotMarshalable)
return err != nil && ok

View File

@ -1,32 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["recognizer.go"],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/recognizer/testing:all-srcs",
],
tags = ["automanaged"],
)

View File

@ -1,30 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["recognizer_test.go"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -0,0 +1,91 @@
/*
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 serializer
import (
"testing"
"k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff"
)
type FakeV1Obj struct {
metav1.TypeMeta
metav1.ObjectMeta
}
func (*FakeV1Obj) DeepCopyObject() runtime.Object {
panic("not supported")
}
type FakeV2DifferentObj struct {
metav1.TypeMeta
metav1.ObjectMeta
}
func (*FakeV2DifferentObj) DeepCopyObject() runtime.Object {
panic("not supported")
}
func TestSparse(t *testing.T) {
v1 := schema.GroupVersion{Group: "mygroup", Version: "v1"}
v2 := schema.GroupVersion{Group: "mygroup", Version: "v2"}
scheme := runtime.NewScheme()
scheme.AddKnownTypes(v1, &FakeV1Obj{})
scheme.AddKnownTypes(v2, &FakeV2DifferentObj{})
codecs := NewCodecFactory(scheme)
srcObj1 := &FakeV1Obj{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}
srcObj2 := &FakeV2DifferentObj{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}
encoder := codecs.LegacyCodec(v2, v1)
decoder := codecs.UniversalDecoder(v2, v1)
srcObj1Bytes, err := runtime.Encode(encoder, srcObj1)
if err != nil {
t.Fatal(err)
}
t.Log(string(srcObj1Bytes))
srcObj2Bytes, err := runtime.Encode(encoder, srcObj2)
if err != nil {
t.Fatal(err)
}
t.Log(string(srcObj2Bytes))
uncastDstObj1, err := runtime.Decode(decoder, srcObj1Bytes)
if err != nil {
t.Fatal(err)
}
uncastDstObj2, err := runtime.Decode(decoder, srcObj2Bytes)
if err != nil {
t.Fatal(err)
}
// clear typemeta
uncastDstObj1.(*FakeV1Obj).TypeMeta = metav1.TypeMeta{}
uncastDstObj2.(*FakeV2DifferentObj).TypeMeta = metav1.TypeMeta{}
if !equality.Semantic.DeepEqual(srcObj1, uncastDstObj1) {
t.Fatal(diff.ObjectDiff(srcObj1, uncastDstObj1))
}
if !equality.Semantic.DeepEqual(srcObj2, uncastDstObj2) {
t.Fatal(diff.ObjectDiff(srcObj2, uncastDstObj2))
}
}

View File

@ -1,41 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["streaming_test.go"],
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/framer:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["streaming.go"],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -1,33 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"types.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer/testing",
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -1,7 +1,7 @@
// +build !ignore_autogenerated
/*
Copyright 2018 The Kubernetes Authors.
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -70,12 +70,8 @@ func (in *ExternalTestType1) DeepCopyInto(out *ExternalTestType1) {
}
if in.O != nil {
in, out := &in.O, &out.O
if *in == nil {
*out = nil
} else {
*out = new(ExternalTestType2)
**out = **in
}
*out = new(ExternalTestType2)
**out = **in
}
if in.P != nil {
in, out := &in.P, &out.P
@ -147,12 +143,8 @@ func (in *TestType1) DeepCopyInto(out *TestType1) {
}
if in.O != nil {
in, out := &in.O, &out.O
if *in == nil {
*out = nil
} else {
*out = new(TestType2)
**out = **in
}
*out = new(TestType2)
**out = **in
}
if in.P != nil {
in, out := &in.P, &out.P

View File

@ -1,41 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["versioning_test.go"],
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["versioning.go"],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -18,23 +18,13 @@ package versioning
import (
"io"
"reflect"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"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?
@ -44,7 +34,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
@ -59,6 +49,7 @@ func NewCodec(
defaulter runtime.ObjectDefaulter,
encodeVersion runtime.GroupVersioner,
decodeVersion runtime.GroupVersioner,
originalSchemeName string,
) runtime.Codec {
internal := &codec{
encoder: encoder,
@ -70,6 +61,8 @@ func NewCodec(
encodeVersion: encodeVersion,
decodeVersion: decodeVersion,
originalSchemeName: originalSchemeName,
}
return internal
}
@ -84,6 +77,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
@ -95,7 +91,16 @@ func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into ru
into = versioned.Last()
}
obj, gvk, err := c.decoder.Decode(data, defaultGVK, into)
// If the into object is unstructured and expresses an opinion about its group/version,
// create a new instance of the type so we always exercise the conversion path (skips short-circuiting on `into == obj`)
decodeInto := into
if into != nil {
if _, ok := into.(runtime.Unstructured); ok && !into.GetObjectKind().GroupVersionKind().GroupVersion().Empty() {
decodeInto = reflect.New(reflect.TypeOf(into).Elem()).Interface().(runtime.Object)
}
}
obj, gvk, err := c.decoder.Decode(data, defaultGVK, decodeInto)
if err != nil {
return nil, gvk, err
}
@ -166,9 +171,27 @@ func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into ru
// Encode ensures the provided object is output in the appropriate group and version, invoking
// conversion if necessary. Unversioned objects (according to the ObjectTyper) are output as is.
func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
switch obj.(type) {
case *runtime.Unknown, runtime.Unstructured:
switch obj := obj.(type) {
case *runtime.Unknown:
return c.encoder.Encode(obj, w)
case runtime.Unstructured:
// An unstructured list can contain objects of multiple group version kinds. don't short-circuit just
// because the top-level type matches our desired destination type. actually send the object to the converter
// to give it a chance to convert the list items if needed.
if _, ok := obj.(*unstructured.UnstructuredList); !ok {
// avoid conversion roundtrip if GVK is the right one already or is empty (yes, this is a hack, but the old behaviour we rely on in kubectl)
objGVK := obj.GetObjectKind().GroupVersionKind()
if len(objGVK.Version) == 0 {
return c.encoder.Encode(obj, w)
}
targetGVK, ok := c.encodeVersion.KindForGroupVersionKinds([]schema.GroupVersionKind{objGVK})
if !ok {
return runtime.NewNotRegisteredGVKErrForTarget(c.originalSchemeName, objGVK, c.encodeVersion)
}
if targetGVK == objGVK {
return c.encoder.Encode(obj, w)
}
}
}
gvks, isUnversioned, err := c.typer.ObjectKinds(obj)

View File

@ -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)
@ -129,25 +130,25 @@ func TestDecode(t *testing.T) {
}{
{
serializer: &mockSerializer{actual: gvk1},
convertor: &checkConvertor{groupVersion: schema.GroupVersion{Group: "other", Version: "__internal"}},
convertor: &checkConvertor{groupVersion: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}},
expectedGVK: gvk1,
decodes: schema.GroupVersion{Group: "other", Version: "__internal"},
decodes: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal},
},
{
serializer: &mockSerializer{actual: gvk1, obj: decodable1},
convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: "__internal"}},
convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}},
expectedGVK: gvk1,
sameObject: decodable2,
decodes: schema.GroupVersion{Group: "other", Version: "__internal"},
decodes: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal},
},
// defaultGVK.Group is allowed to force a conversion to the destination group
{
serializer: &mockSerializer{actual: gvk1, obj: decodable1},
defaultGVK: &schema.GroupVersionKind{Group: "force"},
convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "force", Version: "__internal"}},
convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "force", Version: runtime.APIVersionInternal}},
expectedGVK: gvk1,
sameObject: decodable2,
decodes: schema.GroupVersion{Group: "force", Version: "__internal"},
decodes: schema.GroupVersion{Group: "force", Version: runtime.APIVersionInternal},
},
// uses direct conversion for into when objects differ
{
@ -184,10 +185,10 @@ func TestDecode(t *testing.T) {
into: &runtime.VersionedObjects{Objects: []runtime.Object{}},
serializer: &mockSerializer{actual: gvk1, obj: decodable1},
convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: "__internal"}},
convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal}},
expectedGVK: gvk1,
expectedObject: &runtime.VersionedObjects{Objects: []runtime.Object{decodable1, decodable2}},
decodes: schema.GroupVersion{Group: "other", Version: "__internal"},
decodes: schema.GroupVersion{Group: "other", Version: runtime.APIVersionInternal},
},
// decode into the same version as the serialized object
@ -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) {
@ -306,7 +307,7 @@ func (c *checkConvertor) ConvertToVersion(in runtime.Object, outVersion runtime.
}
return c.obj, c.err
}
func (c *checkConvertor) ConvertFieldLabel(version, kind, label, value string) (string, string, error) {
func (c *checkConvertor) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
return "", "", fmt.Errorf("unexpected call to ConvertFieldLabel")
}

View File

@ -1,30 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["yaml.go"],
importpath = "k8s.io/apimachinery/pkg/runtime/serializer/yaml",
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -1,34 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"types.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/apimachinery/pkg/runtime/testing",
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -263,7 +263,7 @@ func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error {
func (obj *Unstructured) UnstructuredContent() map[string]interface{} {
if obj.Object == nil {
obj.Object = make(map[string]interface{})
return make(map[string]interface{})
}
return obj.Object
}

View File

@ -1,7 +1,7 @@
// +build !ignore_autogenerated
/*
Copyright 2018 The Kubernetes Authors.
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -28,14 +28,10 @@ import (
func (in *EmbeddedTest) DeepCopyInto(out *EmbeddedTest) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Object == nil {
out.Object = nil
} else {
if in.Object != nil {
out.Object = in.Object.DeepCopyObject()
}
if in.EmptyObject == nil {
out.EmptyObject = nil
} else {
if in.EmptyObject != nil {
out.EmptyObject = in.EmptyObject.DeepCopyObject()
}
return
@ -284,12 +280,8 @@ func (in *ExternalTestType1) DeepCopyInto(out *ExternalTestType1) {
}
if in.O != nil {
in, out := &in.O, &out.O
if *in == nil {
*out = nil
} else {
*out = new(ExternalTestType2)
**out = **in
}
*out = new(ExternalTestType2)
**out = **in
}
if in.P != nil {
in, out := &in.P, &out.P
@ -370,9 +362,7 @@ func (in *InternalComplex) DeepCopyObject() runtime.Object {
func (in *InternalExtensionType) DeepCopyInto(out *InternalExtensionType) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Extension == nil {
out.Extension = nil
} else {
if in.Extension != nil {
out.Extension = in.Extension.DeepCopyObject()
}
return
@ -400,9 +390,7 @@ func (in *InternalExtensionType) DeepCopyObject() runtime.Object {
func (in *InternalOptionalExtensionType) DeepCopyInto(out *InternalOptionalExtensionType) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Extension == nil {
out.Extension = nil
} else {
if in.Extension != nil {
out.Extension = in.Extension.DeepCopyObject()
}
return
@ -459,9 +447,7 @@ func (in *ObjectTest) DeepCopyInto(out *ObjectTest) {
in, out := &in.Items, &out.Items
*out = make([]runtime.Object, len(*in))
for i := range *in {
if (*in)[i] == nil {
(*out)[i] = nil
} else {
if (*in)[i] != nil {
(*out)[i] = (*in)[i].DeepCopyObject()
}
}
@ -539,12 +525,8 @@ func (in *TestType1) DeepCopyInto(out *TestType1) {
}
if in.O != nil {
in, out := &in.O, &out.O
if *in == nil {
*out = nil
} else {
*out = new(TestType2)
**out = **in
}
*out = new(TestType2)
**out = **in
}
if in.P != nil {
in, out := &in.P, &out.P

View File

@ -1,7 +1,7 @@
// +build !ignore_autogenerated
/*
Copyright 2018 The Kubernetes Authors.
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -28,9 +28,7 @@ func (in *RawExtension) DeepCopyInto(out *RawExtension) {
*out = make([]byte, len(*in))
copy(*out, *in)
}
if in.Object == nil {
out.Object = nil
} else {
if in.Object != nil {
out.Object = in.Object.DeepCopyObject()
}
return
@ -83,9 +81,7 @@ func (in *VersionedObjects) DeepCopyInto(out *VersionedObjects) {
in, out := &in.Objects, &out.Objects
*out = make([]Object, len(*in))
for i := range *in {
if (*in)[i] == nil {
(*out)[i] = nil
} else {
if (*in)[i] != nil {
(*out)[i] = (*in)[i].DeepCopyObject()
}
}