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 {
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
}

View File

@ -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"}}},
},
}

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
// 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

View File

@ -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

View File

@ -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"}}`),
},
},
},

View File

@ -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}",

View File

@ -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

View File

@ -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

View File

@ -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)
}

View File

@ -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
}

View File

@ -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)

View File

@ -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()
}

View File

@ -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
}

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)
}
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)
}

View File

@ -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()

View File

@ -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
}