diff --git a/pkg/master/master_test.go b/pkg/master/master_test.go index 5934983c15f..f7ac4ebc381 100644 --- a/pkg/master/master_test.go +++ b/pkg/master/master_test.go @@ -237,9 +237,10 @@ func testInstallThirdPartyAPIGetVersion(t *testing.T, version string) { if err := decodeResponse(resp, &item); err != nil { t.Errorf("unexpected error: %v", err) } - + // Fill in data that the apiserver injects + expectedObj.SelfLink = item.SelfLink if !reflect.DeepEqual(item, expectedObj) { - t.Errorf("expected:\n%v\nsaw:\n%v\n", expectedObj, item) + t.Errorf("expected:\n%#v\nsaw:\n%#v\n", expectedObj, item) } } @@ -285,8 +286,14 @@ func testInstallThirdPartyAPIPostForVersion(t *testing.T, version string) { t.Errorf("unexpected error: %v", err) } - if !reflect.DeepEqual(item, inputObj) { - t.Errorf("expected:\n%v\nsaw:\n%v\n", inputObj, item) + // fill in fields set by the apiserver + expectedObj := inputObj + expectedObj.SelfLink = item.SelfLink + expectedObj.Namespace = item.Namespace + expectedObj.UID = item.UID + expectedObj.CreationTimestamp = item.CreationTimestamp + if !reflect.DeepEqual(item, expectedObj) { + t.Errorf("expected:\n%v\nsaw:\n%v\n", expectedObj, item) } etcdResp, err := fakeClient.Get(etcdtest.PathPrefix()+"/ThirdPartyResourceData/company.com/foos/default/test", false, false) @@ -324,7 +331,8 @@ func testInstallThirdPartyAPIDeleteVersion(t *testing.T, version string) { expectedObj := Foo{ ObjectMeta: api.ObjectMeta{ - Name: "test", + Name: "test", + Namespace: "default", }, TypeMeta: api.TypeMeta{ Kind: "Foo", @@ -353,6 +361,9 @@ func testInstallThirdPartyAPIDeleteVersion(t *testing.T, version string) { t.Errorf("unexpected error: %v", err) } + // Fill in fields set by the apiserver + expectedObj.SelfLink = item.SelfLink + expectedObj.Namespace = item.Namespace if !reflect.DeepEqual(item, expectedObj) { t.Errorf("expected:\n%v\nsaw:\n%v\n", expectedObj, item) } diff --git a/pkg/registry/thirdpartyresourcedata/codec.go b/pkg/registry/thirdpartyresourcedata/codec.go index bc190a1b9fd..5ecf9aaa963 100644 --- a/pkg/registry/thirdpartyresourcedata/codec.go +++ b/pkg/registry/thirdpartyresourcedata/codec.go @@ -100,12 +100,12 @@ func (t *thirdPartyResourceDataCodec) populate(objIn *expapi.ThirdPartyResourceD } func (t *thirdPartyResourceDataCodec) populateFromObject(objIn *expapi.ThirdPartyResourceData, mapObj map[string]interface{}, data []byte) error { - kind, ok := mapObj["kind"].(string) - if !ok { - return fmt.Errorf("unexpected object for kind: %#v", mapObj["kind"]) + typeMeta := api.TypeMeta{} + if err := json.Unmarshal(data, &typeMeta); err != nil { + return err } - if kind != t.kind { - return fmt.Errorf("unexpected kind: %s, expected: %s", kind, t.kind) + if typeMeta.Kind != t.kind { + return fmt.Errorf("unexpected kind: %s, expected %s", typeMeta.Kind, t.kind) } metadata, ok := mapObj["metadata"].(map[string]interface{}) @@ -113,38 +113,15 @@ func (t *thirdPartyResourceDataCodec) populateFromObject(objIn *expapi.ThirdPart return fmt.Errorf("unexpected object for metadata: %#v", mapObj["metadata"]) } - if resourceVersion, ok := metadata["resourceVersion"]; ok { - resourceVersionStr, ok := resourceVersion.(string) - if !ok { - return fmt.Errorf("unexpected object for resourceVersion: %v", resourceVersion) - } - - objIn.ResourceVersion = resourceVersionStr + metadataData, err := json.Marshal(metadata) + if err != nil { + return err } - name, ok := metadata["name"].(string) - if !ok { - return fmt.Errorf("unexpected object for name: %#v", metadata) + if err := json.Unmarshal(metadataData, &objIn.ObjectMeta); err != nil { + return err } - if labels, ok := metadata["labels"]; ok { - labelMap, ok := labels.(map[string]interface{}) - if !ok { - return fmt.Errorf("unexpected object for labels: %v", labelMap) - } - for key, value := range labelMap { - valueStr, ok := value.(string) - if !ok { - return fmt.Errorf("unexpected label: %v", value) - } - if objIn.Labels == nil { - objIn.Labels = map[string]string{} - } - objIn.Labels[key] = valueStr - } - } - - objIn.Name = name objIn.Data = data return nil } @@ -230,16 +207,33 @@ const template = `{ "items": [ %s ] }` +func encodeToJSON(obj *expapi.ThirdPartyResourceData) ([]byte, error) { + var objOut interface{} + if err := json.Unmarshal(obj.Data, &objOut); err != nil { + return nil, err + } + objMap, ok := objOut.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("unexpected type: %v", objOut) + } + objMap["metadata"] = obj.ObjectMeta + return json.Marshal(objMap) +} + func (t *thirdPartyResourceDataCodec) Encode(obj runtime.Object) (data []byte, err error) { switch obj := obj.(type) { case *expapi.ThirdPartyResourceData: - return obj.Data, nil + return encodeToJSON(obj) case *expapi.ThirdPartyResourceDataList: // TODO: There must be a better way to do this... buff := &bytes.Buffer{} dataStrings := make([]string, len(obj.Items)) for ix := range obj.Items { - dataStrings[ix] = string(obj.Items[ix].Data) + data, err := encodeToJSON(&obj.Items[ix]) + if err != nil { + return nil, err + } + dataStrings[ix] = string(data) } fmt.Fprintf(buff, template, t.kind+"List", strings.Join(dataStrings, ",")) return buff.Bytes(), nil diff --git a/pkg/registry/thirdpartyresourcedata/codec_test.go b/pkg/registry/thirdpartyresourcedata/codec_test.go index 30665cfd7c5..72fc1e5b709 100644 --- a/pkg/registry/thirdpartyresourcedata/codec_test.go +++ b/pkg/registry/thirdpartyresourcedata/codec_test.go @@ -20,9 +20,11 @@ import ( "encoding/json" "reflect" "testing" + "time" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/expapi" + "k8s.io/kubernetes/pkg/util" ) type Foo struct { @@ -59,6 +61,16 @@ func TestCodec(t *testing.T) { obj: &Foo{ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "baz"}, TypeMeta: api.TypeMeta{Kind: "Foo"}}, name: "resource version", }, + { + obj: &Foo{ + ObjectMeta: api.ObjectMeta{ + Name: "bar", + CreationTimestamp: util.Time{time.Unix(100, 0)}, + }, + TypeMeta: api.TypeMeta{Kind: "Foo"}, + }, + name: "creation time", + }, { obj: &Foo{ ObjectMeta: api.ObjectMeta{