From 89585237cdb9fe79ae3d7e8028562d0a3cafa52a Mon Sep 17 00:00:00 2001 From: Wojciech Tyczynski Date: Thu, 17 Mar 2016 11:32:14 +0100 Subject: [PATCH] Rename RawJSON to Raw in runtime.RawExtension and add ContentType & ContentEncoding. --- pkg/api/meta/help.go | 6 +++--- pkg/api/meta/help_test.go | 4 ++-- pkg/api/rest/rest.go | 2 +- pkg/kubectl/resource/visitor.go | 9 +++++---- pkg/kubectl/resource_printer_test.go | 4 ++-- pkg/kubectl/sorting_printer_test.go | 24 ++++++++++++------------ pkg/runtime/deep_copy_generated.go | 6 +++--- pkg/runtime/embedded.go | 8 ++++---- pkg/runtime/embedded_test.go | 4 ++-- pkg/runtime/extension.go | 7 ++++--- pkg/runtime/extension_test.go | 2 +- pkg/runtime/protobuf/protobuf.go | 15 +++++++++++---- pkg/runtime/types.go | 20 ++++++++++++-------- pkg/watch/json/decoder.go | 2 +- pkg/watch/json/decoder_test.go | 2 +- pkg/watch/json/types.go | 2 +- 16 files changed, 65 insertions(+), 52 deletions(-) diff --git a/pkg/api/meta/help.go b/pkg/api/meta/help.go index f24c57ab1e3..cdc07930fe8 100644 --- a/pkg/api/meta/help.go +++ b/pkg/api/meta/help.go @@ -76,9 +76,9 @@ func ExtractList(obj runtime.Object) ([]runtime.Object, error) { switch { case item.Object != nil: list[i] = item.Object - case item.RawJSON != nil: - // TODO: Set ContentEncoding and ContentType. - list[i] = &runtime.Unknown{Raw: item.RawJSON} + case item.Raw != nil: + // TODO: Set ContentEncoding and ContentType correctly. + list[i] = &runtime.Unknown{Raw: item.Raw} default: list[i] = nil } diff --git a/pkg/api/meta/help_test.go b/pkg/api/meta/help_test.go index 435784fdcf1..fa221b67861 100644 --- a/pkg/api/meta/help_test.go +++ b/pkg/api/meta/help_test.go @@ -114,8 +114,8 @@ func TestExtractListGeneric(t *testing.T) { func TestExtractListGenericV1(t *testing.T) { pl := &v1.List{ Items: []runtime.RawExtension{ - {RawJSON: []byte("foo")}, - {RawJSON: []byte("bar")}, + {Raw: []byte("foo")}, + {Raw: []byte("bar")}, {Object: &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "other"}}}, }, } diff --git a/pkg/api/rest/rest.go b/pkg/api/rest/rest.go index d07023dad5d..4565730f2f5 100644 --- a/pkg/api/rest/rest.go +++ b/pkg/api/rest/rest.go @@ -57,7 +57,7 @@ type Storage interface { // KindProvider specifies a different kind for its API than for its internal storage. This is necessary for external // objects that are not compiled into the api server. For such objects, there is no in-memory representation for -// the object, so they must be represented as generic objects (e.g. RawJSON), but when we present the object as part of +// the object, so they must be represented as generic objects (e.g. runtime.Unknown), but when we present the object as part of // API discovery we want to present the specific kind, not the generic internal representation. type KindProvider interface { Kind() string diff --git a/pkg/kubectl/resource/visitor.go b/pkg/kubectl/resource/visitor.go index 76569389c7d..be138b210e6 100644 --- a/pkg/kubectl/resource/visitor.go +++ b/pkg/kubectl/resource/visitor.go @@ -474,14 +474,15 @@ func (v *StreamVisitor) Visit(fn VisitorFunc) error { } return err } - ext.RawJSON = bytes.TrimSpace(ext.RawJSON) - if len(ext.RawJSON) == 0 || bytes.Equal(ext.RawJSON, []byte("null")) { + // TODO: This needs to be able to handle object in other encodings and schemas. + ext.Raw = bytes.TrimSpace(ext.Raw) + if len(ext.Raw) == 0 || bytes.Equal(ext.Raw, []byte("null")) { continue } - if err := ValidateSchema(ext.RawJSON, v.Schema); err != nil { + if err := ValidateSchema(ext.Raw, v.Schema); err != nil { return fmt.Errorf("error validating %q: %v", v.Source, err) } - info, err := v.InfoForData(ext.RawJSON, v.Source) + info, err := v.InfoForData(ext.Raw, v.Source) if err != nil { if fnErr := fn(info, err); fnErr != nil { return fnErr diff --git a/pkg/kubectl/resource_printer_test.go b/pkg/kubectl/resource_printer_test.go index ec27d706f91..29a22a5ab41 100644 --- a/pkg/kubectl/resource_printer_test.go +++ b/pkg/kubectl/resource_printer_test.go @@ -299,10 +299,10 @@ func TestNamePrinter(t *testing.T) { }, Items: []runtime.RawExtension{ { - RawJSON: []byte(`{"kind": "Pod", "apiVersion": "v1", "metadata": { "name": "foo"}}`), + Raw: []byte(`{"kind": "Pod", "apiVersion": "v1", "metadata": { "name": "foo"}}`), }, { - RawJSON: []byte(`{"kind": "Pod", "apiVersion": "v1", "metadata": { "name": "bar"}}`), + Raw: []byte(`{"kind": "Pod", "apiVersion": "v1", "metadata": { "name": "bar"}}`), }, }, }, diff --git a/pkg/kubectl/sorting_printer_test.go b/pkg/kubectl/sorting_printer_test.go index f1d1d0c65cb..4839159a358 100644 --- a/pkg/kubectl/sorting_printer_test.go +++ b/pkg/kubectl/sorting_printer_test.go @@ -190,16 +190,16 @@ func TestSortingPrinter(t *testing.T) { name: "v1.List in order", obj: &api.List{ Items: []runtime.RawExtension{ - {RawJSON: encodeOrDie(a)}, - {RawJSON: encodeOrDie(b)}, - {RawJSON: encodeOrDie(c)}, + {Raw: encodeOrDie(a)}, + {Raw: encodeOrDie(b)}, + {Raw: encodeOrDie(c)}, }, }, sort: &api.List{ Items: []runtime.RawExtension{ - {RawJSON: encodeOrDie(a)}, - {RawJSON: encodeOrDie(b)}, - {RawJSON: encodeOrDie(c)}, + {Raw: encodeOrDie(a)}, + {Raw: encodeOrDie(b)}, + {Raw: encodeOrDie(c)}, }, }, field: "{.metadata.name}", @@ -208,16 +208,16 @@ func TestSortingPrinter(t *testing.T) { name: "v1.List in reverse", obj: &api.List{ Items: []runtime.RawExtension{ - {RawJSON: encodeOrDie(c)}, - {RawJSON: encodeOrDie(b)}, - {RawJSON: encodeOrDie(a)}, + {Raw: encodeOrDie(c)}, + {Raw: encodeOrDie(b)}, + {Raw: encodeOrDie(a)}, }, }, sort: &api.List{ Items: []runtime.RawExtension{ - {RawJSON: encodeOrDie(a)}, - {RawJSON: encodeOrDie(b)}, - {RawJSON: encodeOrDie(c)}, + {Raw: encodeOrDie(a)}, + {Raw: encodeOrDie(b)}, + {Raw: encodeOrDie(c)}, }, }, field: "{.metadata.name}", diff --git a/pkg/runtime/deep_copy_generated.go b/pkg/runtime/deep_copy_generated.go index 36e2c2a26d6..f368440a384 100644 --- a/pkg/runtime/deep_copy_generated.go +++ b/pkg/runtime/deep_copy_generated.go @@ -27,12 +27,12 @@ import ( ) func DeepCopy_runtime_RawExtension(in RawExtension, out *RawExtension, c *conversion.Cloner) error { - if in.RawJSON != nil { - in, out := in.RawJSON, &out.RawJSON + if in.Raw != nil { + in, out := in.Raw, &out.Raw *out = make([]byte, len(in)) copy(*out, in) } else { - out.RawJSON = nil + out.Raw = nil } if in.Object == nil { out.Object = nil diff --git a/pkg/runtime/embedded.go b/pkg/runtime/embedded.go index e358df814e6..9e2ef82719c 100644 --- a/pkg/runtime/embedded.go +++ b/pkg/runtime/embedded.go @@ -92,19 +92,19 @@ func DefaultEmbeddedConversions() []interface{} { return []interface{}{ func(in *Object, out *RawExtension, s conversion.Scope) error { if in == nil { - out.RawJSON = []byte("null") + out.Raw = []byte("null") return nil } obj := *in if unk, ok := obj.(*Unknown); ok { if unk.Raw != nil { - out.RawJSON = unk.Raw + out.Raw = unk.Raw return nil } obj = out.Object } if obj == nil { - out.RawJSON = nil + out.Raw = nil return nil } out.Object = obj @@ -116,7 +116,7 @@ func DefaultEmbeddedConversions() []interface{} { *out = in.Object return nil } - data := in.RawJSON + data := in.Raw if len(data) == 0 || (len(data) == 4 && string(data) == "null") { *out = nil return nil diff --git a/pkg/runtime/embedded_test.go b/pkg/runtime/embedded_test.go index 162e4d16979..7875d9ffc0c 100644 --- a/pkg/runtime/embedded_test.go +++ b/pkg/runtime/embedded_test.go @@ -138,7 +138,7 @@ func TestArrayOfRuntimeObject(t *testing.T) { if err := json.Unmarshal(wire, obj); err != nil { t.Fatalf("unexpected error: %v", err) } - t.Logf("exact wire is: %s", string(obj.Items[0].RawJSON)) + t.Logf("exact wire is: %s", string(obj.Items[0].Raw)) items[3] = &ObjectTest{Items: innerItems} internal.Items = items @@ -230,7 +230,7 @@ func TestNestedObject(t *testing.T) { if externalViaJSON.Kind == "" || externalViaJSON.APIVersion == "" || externalViaJSON.ID != "outer" { t.Errorf("Expected objects to have type info set, got %#v", externalViaJSON) } - if !reflect.DeepEqual(externalViaJSON.EmptyObject.RawJSON, []byte("null")) || len(externalViaJSON.Object.RawJSON) == 0 { + if !reflect.DeepEqual(externalViaJSON.EmptyObject.Raw, []byte("null")) || len(externalViaJSON.Object.Raw) == 0 { t.Errorf("Expected deserialization of nested objects into bytes, got %#v", externalViaJSON) } diff --git a/pkg/runtime/extension.go b/pkg/runtime/extension.go index 629f675b69e..eca82986eab 100644 --- a/pkg/runtime/extension.go +++ b/pkg/runtime/extension.go @@ -25,14 +25,14 @@ func (re *RawExtension) UnmarshalJSON(in []byte) error { if re == nil { return errors.New("runtime.RawExtension: UnmarshalJSON on nil pointer") } - re.RawJSON = append(re.RawJSON[0:0], in...) + re.Raw = append(re.Raw[0:0], in...) 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 RawExtension) MarshalJSON() ([]byte, error) { - if re.RawJSON == nil { + if re.Raw == nil { // TODO: this is to support legacy behavior of JSONPrinter and YAMLPrinter, which // expect to call json.Marshal on arbitrary versioned objects (even those not in // the scheme). pkg/kubectl/resource#AsVersionedObjects and its interaction with @@ -43,5 +43,6 @@ func (re RawExtension) MarshalJSON() ([]byte, error) { } return []byte("null"), nil } - return re.RawJSON, nil + // TODO: Check whether ContentType is actually JSON before returning it. + return re.Raw, nil } diff --git a/pkg/runtime/extension_test.go b/pkg/runtime/extension_test.go index 3d8a087a931..3545284e999 100644 --- a/pkg/runtime/extension_test.go +++ b/pkg/runtime/extension_test.go @@ -28,7 +28,7 @@ func TestEmbeddedRawExtensionMarshal(t *testing.T) { Ext runtime.RawExtension } - extension := test{Ext: runtime.RawExtension{RawJSON: []byte(`{"foo":"bar"}`)}} + extension := test{Ext: runtime.RawExtension{Raw: []byte(`{"foo":"bar"}`)}} data, err := json.Marshal(extension) if err != nil { t.Fatalf("unexpected error: %v", err) diff --git a/pkg/runtime/protobuf/protobuf.go b/pkg/runtime/protobuf/protobuf.go index cc050a50b23..c555b124d84 100644 --- a/pkg/runtime/protobuf/protobuf.go +++ b/pkg/runtime/protobuf/protobuf.go @@ -64,7 +64,10 @@ func (c codec) Decode(data []byte) (runtime.Object, error) { if !ok { return nil, fmt.Errorf("runtime object is not a proto.Message: %v", reflect.TypeOf(obj)) } - if err := proto.Unmarshal(unknown.RawJSON, pobj); err != nil { + if unknown.ContentType != runtime.ContentTypeProtobuf { + return nil, fmt.Errorf("unmarshal non-protobuf object with protobuf decoder") + } + if err := proto.Unmarshal(unknown.Raw, pobj); err != nil { return nil, err } if unknown.APIVersion != c.outputVersion { @@ -90,13 +93,16 @@ func (c codec) DecodeInto(data []byte, obj runtime.Object) error { if err := proto.Unmarshal(data, unknown); err != nil { return err } + if unknown.ContentType != runtime.ContentTypeProtobuf { + return nil, fmt.Errorf("unmarshal non-protobuf object with protobuf decoder") + } if unknown.APIVersion == version && unknown.Kind == kind { pobj, ok := obj.(proto.Message) if !ok { return fmt.Errorf("runtime object is not a proto.Message: %v", reflect.TypeOf(obj)) } - return proto.Unmarshal(unknown.RawJSON, pobj) + return proto.Unmarshal(unknown.Raw, pobj) } versioned, err := c.creater.New(unknown.APIVersion, unknown.Kind) @@ -109,7 +115,7 @@ func (c codec) DecodeInto(data []byte, obj runtime.Object) error { return fmt.Errorf("runtime object is not a proto.Message: %v", reflect.TypeOf(obj)) } - if err := proto.Unmarshal(unknown.RawJSON, pobj); err != nil { + if err := proto.Unmarshal(unknown.Raw, pobj); err != nil { return err } return c.convertor.Convert(versioned, obj) @@ -149,7 +155,8 @@ func (c codec) Encode(obj runtime.Object) (data []byte, err error) { Kind: kind, APIVersion: version, }, - RawJSON: b, + Raw: b, + ContentType: runtime.ContentTypeProtobuf, }).Marshal() } diff --git a/pkg/runtime/types.go b/pkg/runtime/types.go index b8de2fc21c0..5a3f3fdb251 100644 --- a/pkg/runtime/types.go +++ b/pkg/runtime/types.go @@ -36,6 +36,12 @@ type TypeMeta struct { Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` } +const ( + ContentTypeJSON string = "application/json" + // TODO: Fix the value. + ContentTypeProtobuf string = "application/protobuf" +) + // 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 @@ -80,17 +86,15 @@ type TypeMeta struct { // // +protobuf=true type RawExtension struct { - // RawJSON is the underlying serialization of this object. - RawJSON []byte + // Raw is the underlying serialization of this object. + // + // TODO: Determine how to detect ContentType and ContentEncoding of 'Raw' data. + Raw []byte // Object can hold a representation of this extension - useful for working with versioned // structs. Object Object `json:"-"` } -// TODO; Where should it be? -// TODO; What value it should have? -const ContentTypeJSON string = "application/json" - // Unknown allows api objects with unknown types to be passed-through. This can be used // to deal with the API objects from a plug-in. Unknown objects still have functioning // TypeMeta features-- kind, version, etc. @@ -105,10 +109,10 @@ type Unknown struct { // except for passing it through the system. Raw []byte // ContentEncoding is encoding used to encode 'Raw' data. - // Unspecified mean no encoding. + // Unspecified means no encoding. ContentEncoding string // ContentType is serialization method used to serialize 'Raw'. - // TODO: Define what unspecified means. + // Unspecified means ContentTypeJSON. ContentType string } diff --git a/pkg/watch/json/decoder.go b/pkg/watch/json/decoder.go index d1632336f67..45bf06d2f28 100644 --- a/pkg/watch/json/decoder.go +++ b/pkg/watch/json/decoder.go @@ -56,7 +56,7 @@ func (d *Decoder) Decode() (watch.EventType, runtime.Object, error) { return "", nil, fmt.Errorf("got invalid watch event type: %v", got.Type) } - obj, err := runtime.Decode(d.codec, got.Object.RawJSON) + obj, err := runtime.Decode(d.codec, got.Object.Raw) if err != nil { return "", nil, fmt.Errorf("unable to decode watch event: %v", err) } diff --git a/pkg/watch/json/decoder_test.go b/pkg/watch/json/decoder_test.go index ceb50b2ce0f..e8ad4e91c7a 100644 --- a/pkg/watch/json/decoder_test.go +++ b/pkg/watch/json/decoder_test.go @@ -43,7 +43,7 @@ func TestDecoder(t *testing.T) { if err != nil { t.Fatalf("Unexpected error %v", err) } - if err := encoder.Encode(&WatchEvent{eventType, runtime.RawExtension{RawJSON: json.RawMessage(data)}}); err != nil { + if err := encoder.Encode(&WatchEvent{eventType, runtime.RawExtension{Raw: json.RawMessage(data)}}); err != nil { t.Errorf("Unexpected error %v", err) } in.Close() diff --git a/pkg/watch/json/types.go b/pkg/watch/json/types.go index 28ee0dec75f..d1b638b52fc 100644 --- a/pkg/watch/json/types.go +++ b/pkg/watch/json/types.go @@ -49,5 +49,5 @@ func Object(encoder runtime.Encoder, event *watch.Event) (interface{}, error) { if err != nil { return nil, err } - return &WatchEvent{event.Type, runtime.RawExtension{RawJSON: json.RawMessage(data)}}, nil + return &WatchEvent{event.Type, runtime.RawExtension{Raw: json.RawMessage(data)}}, nil }