From 3eca0b5ad03be6460e71f0c047a6a04d200f3e80 Mon Sep 17 00:00:00 2001 From: "Dr. Stefan Schimanski" Date: Mon, 29 May 2017 10:21:34 +0200 Subject: [PATCH 1/3] integration test: check API version onf Status object --- test/integration/master/master_test.go | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/integration/master/master_test.go b/test/integration/master/master_test.go index 709ee2589f2..a632cb63bc3 100644 --- a/test/integration/master/master_test.go +++ b/test/integration/master/master_test.go @@ -101,6 +101,41 @@ func TestEmptyList(t *testing.T) { } } +func TestStatus(t *testing.T) { + _, s, closeFn := framework.RunAMaster(nil) + defer closeFn() + + u := s.URL + "/apis/batch/v1/namespaces/default/jobs/foo" + resp, err := http.Get(u) + if err != nil { + t.Fatalf("unexpected error getting %s: %v", u, err) + } + if resp.StatusCode != http.StatusNotFound { + t.Fatalf("got status %v instead of 404", resp.StatusCode) + } + defer resp.Body.Close() + data, _ := ioutil.ReadAll(resp.Body) + decodedData := map[string]interface{}{} + if err := json.Unmarshal(data, &decodedData); err != nil { + t.Logf("body: %s", string(data)) + t.Fatalf("got error decoding data: %v", err) + } + t.Logf("body: %s", string(data)) + + if got, expected := decodedData["apiVersion"], "v1"; got != expected { + t.Errorf("unexpected apiVersion %q, expected %q", got, expected) + } + if got, expected := decodedData["kind"], "Status"; got != expected { + t.Errorf("unexpected kind %q, expected %q", got, expected) + } + if got, expected := decodedData["status"], "Failure"; got != expected { + t.Errorf("unexpected status %q, expected %q", got, expected) + } + if got, expected := decodedData["code"], float64(404); got != expected { + t.Errorf("unexpected code %v, expected %v", got, expected) + } +} + func TestWatchSucceedsWithoutArgs(t *testing.T) { _, s, closeFn := framework.RunAMaster(nil) defer closeFn() From 5ea58748f10d5d9333df70d1d24881af5586ba66 Mon Sep 17 00:00:00 2001 From: "Dr. Stefan Schimanski" Date: Tue, 23 May 2017 10:25:08 +0200 Subject: [PATCH 2/3] apimachinery: idempotent registration of unversioned types --- staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go b/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go index d4f5f4a8db5..6c9475fa0d6 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go @@ -151,8 +151,8 @@ func (s *Scheme) AddUnversionedTypes(version schema.GroupVersion, types ...Objec t := reflect.TypeOf(obj).Elem() gvk := version.WithKind(t.Name()) s.unversionedTypes[t] = gvk - if _, ok := s.unversionedKinds[gvk.Kind]; ok { - panic(fmt.Sprintf("%v has already been registered as unversioned kind %q - kind name must be unique", reflect.TypeOf(t), gvk.Kind)) + 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)) } s.unversionedKinds[gvk.Kind] = t } From e3b92a11f1e9b898265d50eba92727b8209e0bb2 Mon Sep 17 00:00:00 2001 From: "Dr. Stefan Schimanski" Date: Fri, 19 May 2017 17:35:02 +0200 Subject: [PATCH 3/3] apimachinery: move unversioned registration to metav1 --- pkg/api/register.go | 12 ------------ .../garbagecollector/metaonly/metaonly.go | 4 ++-- .../apimachinery/pkg/apis/meta/v1/register.go | 13 +++++++++++++ .../k8s.io/apimachinery/pkg/runtime/scheme_test.go | 13 +++++++++++++ staging/src/k8s.io/client-go/pkg/api/register.go | 12 ------------ 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/pkg/api/register.go b/pkg/api/register.go index 23cfaabdbe1..5f261bdfb5b 100644 --- a/pkg/api/register.go +++ b/pkg/api/register.go @@ -50,10 +50,6 @@ const GroupName = "" // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal} -// Unversioned is group version for unversioned API objects -// TODO: this should be v1 probably -var Unversioned = schema.GroupVersion{Group: "", Version: "v1"} - // ParameterCodec handles versioning of objects that are converted to query parameters. var ParameterCodec = runtime.NewParameterCodec(Scheme) @@ -123,13 +119,5 @@ func addKnownTypes(scheme *runtime.Scheme) error { &ConfigMapList{}, ) - // Register Unversioned types under their own special group - scheme.AddUnversionedTypes(Unversioned, - &metav1.Status{}, - &metav1.APIVersions{}, - &metav1.APIGroupList{}, - &metav1.APIGroup{}, - &metav1.APIResourceList{}, - ) return nil } diff --git a/pkg/controller/garbagecollector/metaonly/metaonly.go b/pkg/controller/garbagecollector/metaonly/metaonly.go index bf7053c9b1d..e9f2872ccf9 100644 --- a/pkg/controller/garbagecollector/metaonly/metaonly.go +++ b/pkg/controller/garbagecollector/metaonly/metaonly.go @@ -52,14 +52,14 @@ func NewMetadataCodecFactory() serializer.CodecFactory { if kind.Version == runtime.APIVersionInternal { continue } - if kind == api.Unversioned.WithKind("Status") { + if kind == metav1.Unversioned.WithKind("Status") { // this is added below as unversioned continue } metaOnlyObject := gvkToMetadataOnlyObject(kind) scheme.AddKnownTypeWithName(kind, metaOnlyObject) } - scheme.AddUnversionedTypes(api.Unversioned, &metav1.Status{}) + scheme.AddUnversionedTypes(metav1.Unversioned, &metav1.Status{}) return serializer.NewCodecFactory(scheme) } diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/register.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/register.go index 8645d1abc75..6e449a436a1 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/register.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/register.go @@ -27,6 +27,10 @@ const GroupName = "meta.k8s.io" // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} +// Unversioned is group version for unversioned API objects +// TODO: this should be v1 probably +var Unversioned = schema.GroupVersion{Group: "", Version: "v1"} + // WatchEventKind is name reserved for serializing watch events. const WatchEventKind = "WatchEvent" @@ -56,6 +60,15 @@ func AddToGroupVersion(scheme *runtime.Scheme, groupVersion schema.GroupVersion) Convert_versioned_Event_to_versioned_InternalEvent, ) + // Register Unversioned types under their own special group + scheme.AddUnversionedTypes(Unversioned, + &Status{}, + &APIVersions{}, + &APIGroupList{}, + &APIGroup{}, + &APIResourceList{}, + ) + // register manually. This usually goes through the SchemeBuilder, which we cannot use here. scheme.AddGeneratedDeepCopyFuncs(GetGeneratedDeepCopyFuncs()...) AddConversionFuncs(scheme) diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/scheme_test.go b/staging/src/k8s.io/apimachinery/pkg/runtime/scheme_test.go index d34b491bd84..9ce19928a17 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/scheme_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/scheme_test.go @@ -570,6 +570,7 @@ func TestAddKnownTypesIdemPotent(t *testing.T) { t.Errorf("expected only one type after double registration with custom name") } + s.AddUnversionedTypes(gv, &InternalSimple{}) s.AddUnversionedTypes(gv, &InternalSimple{}) if len(s.KnownTypes(gv)) != 1 { t.Errorf("expected only one %v type after double registration with custom name", gv) @@ -587,6 +588,11 @@ func TestAddKnownTypesIdemPotent(t *testing.T) { } } +// EmbeddableTypeMeta passes GetObjectKind to the type which embeds it. +type EmbeddableTypeMeta runtime.TypeMeta + +func (tm *EmbeddableTypeMeta) GetObjectKind() schema.ObjectKind { return (*runtime.TypeMeta)(tm) } + func TestConflictingAddKnownTypes(t *testing.T) { s := runtime.NewScheme() gv := schema.GroupVersion{Group: "foo", Version: "v1"} @@ -612,7 +618,14 @@ func TestConflictingAddKnownTypes(t *testing.T) { panicked <- true } }() + s.AddUnversionedTypes(gv, &InternalSimple{}) + + // redefine InternalSimple with the same name, but obviously as a different type + type InternalSimple struct { + EmbeddableTypeMeta `json:",inline"` + TestString string `json:"testString"` + } s.AddUnversionedTypes(gv, &InternalSimple{}) panicked <- false }() diff --git a/staging/src/k8s.io/client-go/pkg/api/register.go b/staging/src/k8s.io/client-go/pkg/api/register.go index 23cfaabdbe1..5f261bdfb5b 100644 --- a/staging/src/k8s.io/client-go/pkg/api/register.go +++ b/staging/src/k8s.io/client-go/pkg/api/register.go @@ -50,10 +50,6 @@ const GroupName = "" // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal} -// Unversioned is group version for unversioned API objects -// TODO: this should be v1 probably -var Unversioned = schema.GroupVersion{Group: "", Version: "v1"} - // ParameterCodec handles versioning of objects that are converted to query parameters. var ParameterCodec = runtime.NewParameterCodec(Scheme) @@ -123,13 +119,5 @@ func addKnownTypes(scheme *runtime.Scheme) error { &ConfigMapList{}, ) - // Register Unversioned types under their own special group - scheme.AddUnversionedTypes(Unversioned, - &metav1.Status{}, - &metav1.APIVersions{}, - &metav1.APIGroupList{}, - &metav1.APIGroup{}, - &metav1.APIResourceList{}, - ) return nil }