Merge pull request #23112 from wojtek-t/rename_raw_json_in_raw_extension

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2016-03-18 08:30:20 -07:00
commit ec5ad0f774
16 changed files with 65 additions and 52 deletions

View File

@ -76,9 +76,9 @@ func ExtractList(obj runtime.Object) ([]runtime.Object, error) {
switch { switch {
case item.Object != nil: case item.Object != nil:
list[i] = item.Object list[i] = item.Object
case item.RawJSON != nil: case item.Raw != nil:
// TODO: Set ContentEncoding and ContentType. // TODO: Set ContentEncoding and ContentType correctly.
list[i] = &runtime.Unknown{Raw: item.RawJSON} list[i] = &runtime.Unknown{Raw: item.Raw}
default: default:
list[i] = nil list[i] = nil
} }

View File

@ -114,8 +114,8 @@ func TestExtractListGeneric(t *testing.T) {
func TestExtractListGenericV1(t *testing.T) { func TestExtractListGenericV1(t *testing.T) {
pl := &v1.List{ pl := &v1.List{
Items: []runtime.RawExtension{ Items: []runtime.RawExtension{
{RawJSON: []byte("foo")}, {Raw: []byte("foo")},
{RawJSON: []byte("bar")}, {Raw: []byte("bar")},
{Object: &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "other"}}}, {Object: &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "other"}}},
}, },
} }

View File

@ -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 // 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 // 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. // API discovery we want to present the specific kind, not the generic internal representation.
type KindProvider interface { type KindProvider interface {
Kind() string Kind() string

View File

@ -474,14 +474,15 @@ func (v *StreamVisitor) Visit(fn VisitorFunc) error {
} }
return err return err
} }
ext.RawJSON = bytes.TrimSpace(ext.RawJSON) // TODO: This needs to be able to handle object in other encodings and schemas.
if len(ext.RawJSON) == 0 || bytes.Equal(ext.RawJSON, []byte("null")) { ext.Raw = bytes.TrimSpace(ext.Raw)
if len(ext.Raw) == 0 || bytes.Equal(ext.Raw, []byte("null")) {
continue 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) 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 err != nil {
if fnErr := fn(info, err); fnErr != nil { if fnErr := fn(info, err); fnErr != nil {
return fnErr return fnErr

View File

@ -299,10 +299,10 @@ func TestNamePrinter(t *testing.T) {
}, },
Items: []runtime.RawExtension{ 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"}}`),
}, },
}, },
}, },

View File

@ -190,16 +190,16 @@ func TestSortingPrinter(t *testing.T) {
name: "v1.List in order", name: "v1.List in order",
obj: &api.List{ obj: &api.List{
Items: []runtime.RawExtension{ Items: []runtime.RawExtension{
{RawJSON: encodeOrDie(a)}, {Raw: encodeOrDie(a)},
{RawJSON: encodeOrDie(b)}, {Raw: encodeOrDie(b)},
{RawJSON: encodeOrDie(c)}, {Raw: encodeOrDie(c)},
}, },
}, },
sort: &api.List{ sort: &api.List{
Items: []runtime.RawExtension{ Items: []runtime.RawExtension{
{RawJSON: encodeOrDie(a)}, {Raw: encodeOrDie(a)},
{RawJSON: encodeOrDie(b)}, {Raw: encodeOrDie(b)},
{RawJSON: encodeOrDie(c)}, {Raw: encodeOrDie(c)},
}, },
}, },
field: "{.metadata.name}", field: "{.metadata.name}",
@ -208,16 +208,16 @@ func TestSortingPrinter(t *testing.T) {
name: "v1.List in reverse", name: "v1.List in reverse",
obj: &api.List{ obj: &api.List{
Items: []runtime.RawExtension{ Items: []runtime.RawExtension{
{RawJSON: encodeOrDie(c)}, {Raw: encodeOrDie(c)},
{RawJSON: encodeOrDie(b)}, {Raw: encodeOrDie(b)},
{RawJSON: encodeOrDie(a)}, {Raw: encodeOrDie(a)},
}, },
}, },
sort: &api.List{ sort: &api.List{
Items: []runtime.RawExtension{ Items: []runtime.RawExtension{
{RawJSON: encodeOrDie(a)}, {Raw: encodeOrDie(a)},
{RawJSON: encodeOrDie(b)}, {Raw: encodeOrDie(b)},
{RawJSON: encodeOrDie(c)}, {Raw: encodeOrDie(c)},
}, },
}, },
field: "{.metadata.name}", field: "{.metadata.name}",

View File

@ -27,12 +27,12 @@ import (
) )
func DeepCopy_runtime_RawExtension(in RawExtension, out *RawExtension, c *conversion.Cloner) error { func DeepCopy_runtime_RawExtension(in RawExtension, out *RawExtension, c *conversion.Cloner) error {
if in.RawJSON != nil { if in.Raw != nil {
in, out := in.RawJSON, &out.RawJSON in, out := in.Raw, &out.Raw
*out = make([]byte, len(in)) *out = make([]byte, len(in))
copy(*out, in) copy(*out, in)
} else { } else {
out.RawJSON = nil out.Raw = nil
} }
if in.Object == nil { if in.Object == nil {
out.Object = nil out.Object = nil

View File

@ -92,19 +92,19 @@ func DefaultEmbeddedConversions() []interface{} {
return []interface{}{ return []interface{}{
func(in *Object, out *RawExtension, s conversion.Scope) error { func(in *Object, out *RawExtension, s conversion.Scope) error {
if in == nil { if in == nil {
out.RawJSON = []byte("null") out.Raw = []byte("null")
return nil return nil
} }
obj := *in obj := *in
if unk, ok := obj.(*Unknown); ok { if unk, ok := obj.(*Unknown); ok {
if unk.Raw != nil { if unk.Raw != nil {
out.RawJSON = unk.Raw out.Raw = unk.Raw
return nil return nil
} }
obj = out.Object obj = out.Object
} }
if obj == nil { if obj == nil {
out.RawJSON = nil out.Raw = nil
return nil return nil
} }
out.Object = obj out.Object = obj
@ -116,7 +116,7 @@ func DefaultEmbeddedConversions() []interface{} {
*out = in.Object *out = in.Object
return nil return nil
} }
data := in.RawJSON data := in.Raw
if len(data) == 0 || (len(data) == 4 && string(data) == "null") { if len(data) == 0 || (len(data) == 4 && string(data) == "null") {
*out = nil *out = nil
return nil return nil

View File

@ -138,7 +138,7 @@ func TestArrayOfRuntimeObject(t *testing.T) {
if err := json.Unmarshal(wire, obj); err != nil { if err := json.Unmarshal(wire, obj); err != nil {
t.Fatalf("unexpected error: %v", err) 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} items[3] = &ObjectTest{Items: innerItems}
internal.Items = items internal.Items = items
@ -230,7 +230,7 @@ func TestNestedObject(t *testing.T) {
if externalViaJSON.Kind == "" || externalViaJSON.APIVersion == "" || externalViaJSON.ID != "outer" { if externalViaJSON.Kind == "" || externalViaJSON.APIVersion == "" || externalViaJSON.ID != "outer" {
t.Errorf("Expected objects to have type info set, got %#v", externalViaJSON) 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) t.Errorf("Expected deserialization of nested objects into bytes, got %#v", externalViaJSON)
} }

View File

@ -25,14 +25,14 @@ func (re *RawExtension) UnmarshalJSON(in []byte) error {
if re == nil { if re == nil {
return errors.New("runtime.RawExtension: UnmarshalJSON on nil pointer") 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 return nil
} }
// Marshal may get called on pointers or values, so implement MarshalJSON on value. // 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 // http://stackoverflow.com/questions/21390979/custom-marshaljson-never-gets-called-in-go
func (re RawExtension) MarshalJSON() ([]byte, error) { 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 // 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 // expect to call json.Marshal on arbitrary versioned objects (even those not in
// the scheme). pkg/kubectl/resource#AsVersionedObjects and its interaction with // 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 []byte("null"), nil
} }
return re.RawJSON, nil // TODO: Check whether ContentType is actually JSON before returning it.
return re.Raw, nil
} }

View File

@ -28,7 +28,7 @@ func TestEmbeddedRawExtensionMarshal(t *testing.T) {
Ext runtime.RawExtension 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) data, err := json.Marshal(extension)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)

View File

@ -64,7 +64,10 @@ func (c codec) Decode(data []byte) (runtime.Object, error) {
if !ok { if !ok {
return nil, fmt.Errorf("runtime object is not a proto.Message: %v", reflect.TypeOf(obj)) 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 return nil, err
} }
if unknown.APIVersion != c.outputVersion { 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 { if err := proto.Unmarshal(data, unknown); err != nil {
return err 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 { if unknown.APIVersion == version && unknown.Kind == kind {
pobj, ok := obj.(proto.Message) pobj, ok := obj.(proto.Message)
if !ok { if !ok {
return fmt.Errorf("runtime object is not a proto.Message: %v", reflect.TypeOf(obj)) 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) 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)) 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 err
} }
return c.convertor.Convert(versioned, obj) return c.convertor.Convert(versioned, obj)
@ -149,7 +155,8 @@ func (c codec) Encode(obj runtime.Object) (data []byte, err error) {
Kind: kind, Kind: kind,
APIVersion: version, APIVersion: version,
}, },
RawJSON: b, Raw: b,
ContentType: runtime.ContentTypeProtobuf,
}).Marshal() }).Marshal()
} }

View File

@ -36,6 +36,12 @@ type TypeMeta struct {
Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` 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. // 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 // 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 // +protobuf=true
type RawExtension struct { type RawExtension struct {
// RawJSON is the underlying serialization of this object. // Raw is the underlying serialization of this object.
RawJSON []byte //
// 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 // Object can hold a representation of this extension - useful for working with versioned
// structs. // structs.
Object Object `json:"-"` 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 // 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 // to deal with the API objects from a plug-in. Unknown objects still have functioning
// TypeMeta features-- kind, version, etc. // TypeMeta features-- kind, version, etc.
@ -105,10 +109,10 @@ type Unknown struct {
// except for passing it through the system. // except for passing it through the system.
Raw []byte Raw []byte
// ContentEncoding is encoding used to encode 'Raw' data. // ContentEncoding is encoding used to encode 'Raw' data.
// Unspecified mean no encoding. // Unspecified means no encoding.
ContentEncoding string ContentEncoding string
// ContentType is serialization method used to serialize 'Raw'. // ContentType is serialization method used to serialize 'Raw'.
// TODO: Define what unspecified means. // Unspecified means ContentTypeJSON.
ContentType string ContentType string
} }

View File

@ -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) 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 { if err != nil {
return "", nil, fmt.Errorf("unable to decode watch event: %v", err) return "", nil, fmt.Errorf("unable to decode watch event: %v", err)
} }

View File

@ -43,7 +43,7 @@ func TestDecoder(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Unexpected error %v", err) 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) t.Errorf("Unexpected error %v", err)
} }
in.Close() in.Close()

View File

@ -49,5 +49,5 @@ func Object(encoder runtime.Encoder, event *watch.Event) (interface{}, error) {
if err != nil { if err != nil {
return nil, err 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
} }