From 8f203a28f1d17b9371673ff147aa7e8f34f093f5 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Mon, 7 Dec 2015 22:01:12 -0500 Subject: [PATCH] Change runtime.Object signature --- .../testdata/apis/testgroup/register.go | 4 +- .../testdata/apis/testgroup/v1/register.go | 4 +- contrib/mesos/pkg/election/etcd_master.go | 3 +- pkg/api/errors/errors_test.go | 2 +- pkg/api/meta.go | 20 ++ pkg/api/meta/help_test.go | 9 +- pkg/api/meta/interfaces.go | 45 +-- pkg/api/meta/meta.go | 120 +++++--- pkg/api/meta/meta_test.go | 277 ++++++++++++++---- pkg/api/meta_test.go | 3 + pkg/api/ref.go | 58 ++-- pkg/api/ref_test.go | 4 +- pkg/api/register.go | 102 ++++--- pkg/api/rest/rest.go | 3 +- pkg/api/unversioned/group_version.go | 45 +++ pkg/api/unversioned/register.go | 17 +- pkg/api/unversioned/types.go | 7 - pkg/api/v1/register.go | 82 +++--- pkg/apis/abac/register.go | 2 +- pkg/apis/abac/v0/register.go | 2 +- pkg/apis/abac/v1beta1/register.go | 2 +- pkg/apis/componentconfig/register.go | 2 +- pkg/apis/componentconfig/v1alpha1/register.go | 2 +- pkg/apis/extensions/register.go | 36 +-- pkg/apis/extensions/v1beta1/register.go | 38 +-- pkg/apis/metrics/register.go | 4 +- pkg/apis/metrics/v1alpha1/register.go | 4 +- pkg/apiserver/apiserver_test.go | 6 +- pkg/apiserver/resthandler_test.go | 2 +- pkg/apiserver/testing/types.go | 8 +- pkg/client/cache/index.go | 2 +- pkg/client/cache/reflector.go | 4 +- pkg/client/cache/store.go | 6 +- .../unversioned/clientcmd/api/register.go | 8 +- .../unversioned/clientcmd/api/v1/register.go | 8 +- pkg/client/unversioned/request_test.go | 3 +- .../serviceaccounts_controller.go | 2 +- pkg/conversion/meta.go | 13 + pkg/conversion/queryparams/convert_test.go | 12 +- pkg/fieldpath/fieldpath.go | 8 +- pkg/kubectl/apply.go | 2 +- pkg/kubectl/cmd/cmd_test.go | 24 +- pkg/kubectl/resource_printer_test.go | 4 +- pkg/kubectl/stop.go | 2 +- pkg/kubectl/testing/types.go | 2 +- pkg/registry/generic/etcd/etcd.go | 2 +- pkg/registry/generic/matcher_test.go | 5 +- pkg/registry/generic/rest/streamer.go | 6 +- pkg/runtime/conversion_test.go | 18 +- pkg/runtime/embedded_test.go | 8 +- pkg/runtime/interfaces.go | 11 +- pkg/runtime/register.go | 44 +++ pkg/runtime/scheme_test.go | 50 +++- pkg/runtime/types.go | 6 +- pkg/storage/cacher_test.go | 2 +- pkg/storage/testing/types.go | 2 +- pkg/storage/testing/utils.go | 2 +- pkg/storage/util.go | 8 +- pkg/storage/watch_cache.go | 2 +- pkg/watch/mux.go | 5 +- pkg/watch/mux_test.go | 3 +- pkg/watch/watch_test.go | 4 +- plugin/pkg/scheduler/api/register.go | 2 +- plugin/pkg/scheduler/api/v1/register.go | 2 +- 64 files changed, 831 insertions(+), 364 deletions(-) create mode 100644 pkg/runtime/register.go diff --git a/cmd/libs/go2idl/client-gen/testdata/apis/testgroup/register.go b/cmd/libs/go2idl/client-gen/testdata/apis/testgroup/register.go index 0bf36b50a3..d9fdf1ca01 100644 --- a/cmd/libs/go2idl/client-gen/testdata/apis/testgroup/register.go +++ b/cmd/libs/go2idl/client-gen/testdata/apis/testgroup/register.go @@ -39,5 +39,5 @@ func addKnownTypes() { &unversioned.ListOptions{}) } -func (*TestType) IsAnAPIObject() {} -func (*TestTypeList) IsAnAPIObject() {} +func (obj *TestType) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *TestTypeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/cmd/libs/go2idl/client-gen/testdata/apis/testgroup/v1/register.go b/cmd/libs/go2idl/client-gen/testdata/apis/testgroup/v1/register.go index 5e76ec9579..01602255d1 100644 --- a/cmd/libs/go2idl/client-gen/testdata/apis/testgroup/v1/register.go +++ b/cmd/libs/go2idl/client-gen/testdata/apis/testgroup/v1/register.go @@ -42,5 +42,5 @@ func addKnownTypes() { &unversioned.ListOptions{}) } -func (*TestType) IsAnAPIObject() {} -func (*TestTypeList) IsAnAPIObject() {} +func (obj *TestType) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *TestTypeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/contrib/mesos/pkg/election/etcd_master.go b/contrib/mesos/pkg/election/etcd_master.go index 904e01f319..7303885589 100644 --- a/contrib/mesos/pkg/election/etcd_master.go +++ b/contrib/mesos/pkg/election/etcd_master.go @@ -22,6 +22,7 @@ import ( "github.com/coreos/go-etcd/etcd" "github.com/golang/glog" + "k8s.io/kubernetes/pkg/api/unversioned" etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util" "k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/watch" @@ -34,7 +35,7 @@ type Master string // TODO(k8s): Either fix watch so this isn't necessary, or make this a real API Object. // TODO(k8s): when it becomes clear how this package will be used, move these declarations to // to the proper place. -func (Master) IsAnAPIObject() {} +func (obj Master) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } // NewEtcdMasterElector returns an implementation of election.MasterElector backed by etcd. func NewEtcdMasterElector(h *etcd.Client) MasterElector { diff --git a/pkg/api/errors/errors_test.go b/pkg/api/errors/errors_test.go index dc6b138b87..0e7cebbb74 100644 --- a/pkg/api/errors/errors_test.go +++ b/pkg/api/errors/errors_test.go @@ -169,7 +169,7 @@ func Test_reasonForError(t *testing.T) { type TestType struct{} -func (*TestType) IsAnAPIObject() {} +func (obj *TestType) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } func TestFromObject(t *testing.T) { table := []struct { diff --git a/pkg/api/meta.go b/pkg/api/meta.go index a69f66d86d..ec84c3c8a9 100644 --- a/pkg/api/meta.go +++ b/pkg/api/meta.go @@ -20,6 +20,7 @@ import ( "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/conversion" "k8s.io/kubernetes/pkg/runtime" + "k8s.io/kubernetes/pkg/types" "k8s.io/kubernetes/pkg/util" ) @@ -60,3 +61,22 @@ func ListMetaFor(obj runtime.Object) (*unversioned.ListMeta, error) { err = runtime.FieldPtr(v, "ListMeta", &meta) return meta, err } + +// Namespace implements meta.Object for any object with an ObjectMeta typed field. Allows +// fast, direct access to metadata fields for API objects. +func (meta *ObjectMeta) GetNamespace() string { return meta.Namespace } +func (meta *ObjectMeta) SetNamespace(namespace string) { meta.Namespace = namespace } +func (meta *ObjectMeta) GetName() string { return meta.Name } +func (meta *ObjectMeta) SetName(name string) { meta.Name = name } +func (meta *ObjectMeta) GetGenerateName() string { return meta.GenerateName } +func (meta *ObjectMeta) SetGenerateName(generateName string) { meta.GenerateName = generateName } +func (meta *ObjectMeta) GetUID() types.UID { return meta.UID } +func (meta *ObjectMeta) SetUID(uid types.UID) { meta.UID = uid } +func (meta *ObjectMeta) GetResourceVersion() string { return meta.ResourceVersion } +func (meta *ObjectMeta) SetResourceVersion(version string) { meta.ResourceVersion = version } +func (meta *ObjectMeta) GetSelfLink() string { return meta.SelfLink } +func (meta *ObjectMeta) SetSelfLink(selfLink string) { meta.SelfLink = selfLink } +func (meta *ObjectMeta) GetLabels() map[string]string { return meta.Labels } +func (meta *ObjectMeta) SetLabels(labels map[string]string) { meta.Labels = labels } +func (meta *ObjectMeta) GetAnnotations() map[string]string { return meta.Annotations } +func (meta *ObjectMeta) SetAnnotations(annotations map[string]string) { meta.Annotations = annotations } diff --git a/pkg/api/meta/help_test.go b/pkg/api/meta/help_test.go index f0c0bb50d4..23af10734c 100644 --- a/pkg/api/meta/help_test.go +++ b/pkg/api/meta/help_test.go @@ -22,6 +22,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/meta" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util" @@ -114,7 +115,9 @@ type fakePtrInterfaceList struct { Items *[]runtime.Object } -func (f fakePtrInterfaceList) IsAnAPIObject() {} +func (obj fakePtrInterfaceList) GetObjectKind() unversioned.ObjectKind { + return unversioned.EmptyObjectKind +} func TestExtractListOfInterfacePtrs(t *testing.T) { pl := &fakePtrInterfaceList{ @@ -133,7 +136,9 @@ type fakePtrValueList struct { Items []*api.Pod } -func (f fakePtrValueList) IsAnAPIObject() {} +func (obj fakePtrValueList) GetObjectKind() unversioned.ObjectKind { + return unversioned.EmptyObjectKind +} func TestExtractListOfValuePtrs(t *testing.T) { pl := &fakePtrValueList{ diff --git a/pkg/api/meta/interfaces.go b/pkg/api/meta/interfaces.go index 0244315a2e..c8b8d0ce39 100644 --- a/pkg/api/meta/interfaces.go +++ b/pkg/api/meta/interfaces.go @@ -29,37 +29,48 @@ type VersionInterfaces struct { MetadataAccessor } -// Interface lets you work with object and list metadata from any of the versioned or +type ObjectMetaAccessor interface { + GetObjectMeta() Object +} + +// Object lets you work with object metadata from any of the versioned or // internal API objects. Attempting to set or retrieve a field on an object that does // not support that field (Name, UID, Namespace on lists) will be a no-op and return // a default value. -// TODO: rename to ObjectInterface when we clear up these interfaces. -type Interface interface { - TypeInterface - - Namespace() string +type Object interface { + GetNamespace() string SetNamespace(namespace string) - Name() string + GetName() string SetName(name string) - GenerateName() string + GetGenerateName() string SetGenerateName(name string) - UID() types.UID + GetUID() types.UID SetUID(uid types.UID) - ResourceVersion() string + GetResourceVersion() string SetResourceVersion(version string) - SelfLink() string + GetSelfLink() string SetSelfLink(selfLink string) - Labels() map[string]string + GetLabels() map[string]string SetLabels(labels map[string]string) - Annotations() map[string]string + GetAnnotations() map[string]string SetAnnotations(annotations map[string]string) } -// TypeInterface exposes the type and APIVersion of versioned or internal API objects. -type TypeInterface interface { - APIVersion() string +// List lets you work with list metadata from any of the versioned or +// internal API objects. Attempting to set or retrieve a field on an object that does +// not support that field will be a no-op and return a default value. +type List interface { + GetResourceVersion() string + SetResourceVersion(version string) + GetSelfLink() string + SetSelfLink(selfLink string) +} + +// Type exposes the type and APIVersion of versioned or internal API objects. +type Type interface { + GetAPIVersion() string SetAPIVersion(version string) - Kind() string + GetKind() string SetKind(kind string) } diff --git a/pkg/api/meta/meta.go b/pkg/api/meta/meta.go index 4a02bf54b3..bf11abd187 100644 --- a/pkg/api/meta/meta.go +++ b/pkg/api/meta/meta.go @@ -20,6 +20,7 @@ import ( "fmt" "reflect" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/conversion" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/types" @@ -29,8 +30,18 @@ import ( // obj must be a pointer to an API type. An error is returned if the minimum // required fields are missing. Fields that are not required return the default // value and are a no-op if set. -// TODO: add a fast path for *TypeMeta and *ObjectMeta for internal objects -func Accessor(obj interface{}) (Interface, error) { +func Accessor(obj interface{}) (Object, error) { + if oi, ok := obj.(ObjectMetaAccessor); ok { + if om := oi.GetObjectMeta(); om != nil { + return om, nil + } + } + // we may get passed an object that is directly portable to Object + if oi, ok := obj.(Object); ok { + return oi, nil + } + // legacy path for objects that do not implement Object and ObjectMetaAccessor via + // reflection - very slow code path. v, err := conversion.EnforcePtr(obj) if err != nil { return nil, err @@ -79,7 +90,10 @@ func Accessor(obj interface{}) (Interface, error) { // TODO: this interface is used to test code that does not have ObjectMeta or ListMeta // in round tripping (objects which can use apiVersion/kind, but do not fit the Kube // api conventions). -func TypeAccessor(obj interface{}) (TypeInterface, error) { +func TypeAccessor(obj interface{}) (Type, error) { + if typed, ok := obj.(runtime.Object); ok { + return objectAccessor{typed}, nil + } v, err := conversion.EnforcePtr(obj) if err != nil { return nil, err @@ -100,6 +114,46 @@ func TypeAccessor(obj interface{}) (TypeInterface, error) { return a, nil } +type objectAccessor struct { + runtime.Object +} + +func (obj objectAccessor) GetKind() string { + if gvk := obj.GetObjectKind().GroupVersionKind(); gvk != nil { + return gvk.Kind + } + return "" +} + +func (obj objectAccessor) SetKind(kind string) { + gvk := obj.GetObjectKind().GroupVersionKind() + if gvk == nil { + gvk = &unversioned.GroupVersionKind{} + } + gvk.Kind = kind + obj.GetObjectKind().SetGroupVersionKind(gvk) +} + +func (obj objectAccessor) GetAPIVersion() string { + if gvk := obj.GetObjectKind().GroupVersionKind(); gvk != nil { + return gvk.GroupVersion().String() + } + return "" +} + +func (obj objectAccessor) SetAPIVersion(version string) { + gvk := obj.GetObjectKind().GroupVersionKind() + if gvk == nil { + gvk = &unversioned.GroupVersionKind{} + } + gv, err := unversioned.ParseGroupVersion(version) + if err != nil { + gv = unversioned.GroupVersion{Version: version} + } + gvk.Group, gvk.Version = gv.Group, gv.Version + obj.GetObjectKind().SetGroupVersionKind(gvk) +} + // NewAccessor returns a MetadataAccessor that can retrieve // or manipulate resource version on objects derived from core API // metadata concepts. @@ -111,36 +165,20 @@ func NewAccessor() MetadataAccessor { type resourceAccessor struct{} func (resourceAccessor) Kind(obj runtime.Object) (string, error) { - accessor, err := Accessor(obj) - if err != nil { - return "", err - } - return accessor.Kind(), nil + return objectAccessor{obj}.GetKind(), nil } func (resourceAccessor) SetKind(obj runtime.Object, kind string) error { - accessor, err := Accessor(obj) - if err != nil { - return err - } - accessor.SetKind(kind) + objectAccessor{obj}.SetKind(kind) return nil } func (resourceAccessor) APIVersion(obj runtime.Object) (string, error) { - accessor, err := Accessor(obj) - if err != nil { - return "", err - } - return accessor.APIVersion(), nil + return objectAccessor{obj}.GetAPIVersion(), nil } func (resourceAccessor) SetAPIVersion(obj runtime.Object, version string) error { - accessor, err := Accessor(obj) - if err != nil { - return err - } - accessor.SetAPIVersion(version) + objectAccessor{obj}.SetAPIVersion(version) return nil } @@ -149,7 +187,7 @@ func (resourceAccessor) Namespace(obj runtime.Object) (string, error) { if err != nil { return "", err } - return accessor.Namespace(), nil + return accessor.GetNamespace(), nil } func (resourceAccessor) SetNamespace(obj runtime.Object, namespace string) error { @@ -166,7 +204,7 @@ func (resourceAccessor) Name(obj runtime.Object) (string, error) { if err != nil { return "", err } - return accessor.Name(), nil + return accessor.GetName(), nil } func (resourceAccessor) SetName(obj runtime.Object, name string) error { @@ -183,7 +221,7 @@ func (resourceAccessor) GenerateName(obj runtime.Object) (string, error) { if err != nil { return "", err } - return accessor.GenerateName(), nil + return accessor.GetGenerateName(), nil } func (resourceAccessor) SetGenerateName(obj runtime.Object, name string) error { @@ -200,7 +238,7 @@ func (resourceAccessor) UID(obj runtime.Object) (types.UID, error) { if err != nil { return "", err } - return accessor.UID(), nil + return accessor.GetUID(), nil } func (resourceAccessor) SetUID(obj runtime.Object, uid types.UID) error { @@ -217,7 +255,7 @@ func (resourceAccessor) SelfLink(obj runtime.Object) (string, error) { if err != nil { return "", err } - return accessor.SelfLink(), nil + return accessor.GetSelfLink(), nil } func (resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error { @@ -234,7 +272,7 @@ func (resourceAccessor) Labels(obj runtime.Object) (map[string]string, error) { if err != nil { return nil, err } - return accessor.Labels(), nil + return accessor.GetLabels(), nil } func (resourceAccessor) SetLabels(obj runtime.Object, labels map[string]string) error { @@ -251,7 +289,7 @@ func (resourceAccessor) Annotations(obj runtime.Object) (map[string]string, erro if err != nil { return nil, err } - return accessor.Annotations(), nil + return accessor.GetAnnotations(), nil } func (resourceAccessor) SetAnnotations(obj runtime.Object, annotations map[string]string) error { @@ -268,7 +306,7 @@ func (resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) { if err != nil { return "", err } - return accessor.ResourceVersion(), nil + return accessor.GetResourceVersion(), nil } func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) error { @@ -295,7 +333,7 @@ type genericAccessor struct { annotations *map[string]string } -func (a genericAccessor) Namespace() string { +func (a genericAccessor) GetNamespace() string { if a.namespace == nil { return "" } @@ -309,7 +347,7 @@ func (a genericAccessor) SetNamespace(namespace string) { *a.namespace = namespace } -func (a genericAccessor) Name() string { +func (a genericAccessor) GetName() string { if a.name == nil { return "" } @@ -323,7 +361,7 @@ func (a genericAccessor) SetName(name string) { *a.name = name } -func (a genericAccessor) GenerateName() string { +func (a genericAccessor) GetGenerateName() string { if a.generateName == nil { return "" } @@ -337,7 +375,7 @@ func (a genericAccessor) SetGenerateName(generateName string) { *a.generateName = generateName } -func (a genericAccessor) UID() types.UID { +func (a genericAccessor) GetUID() types.UID { if a.uid == nil { return "" } @@ -351,7 +389,7 @@ func (a genericAccessor) SetUID(uid types.UID) { *a.uid = uid } -func (a genericAccessor) APIVersion() string { +func (a genericAccessor) GetAPIVersion() string { return *a.apiVersion } @@ -359,7 +397,7 @@ func (a genericAccessor) SetAPIVersion(version string) { *a.apiVersion = version } -func (a genericAccessor) Kind() string { +func (a genericAccessor) GetKind() string { return *a.kind } @@ -367,7 +405,7 @@ func (a genericAccessor) SetKind(kind string) { *a.kind = kind } -func (a genericAccessor) ResourceVersion() string { +func (a genericAccessor) GetResourceVersion() string { return *a.resourceVersion } @@ -375,7 +413,7 @@ func (a genericAccessor) SetResourceVersion(version string) { *a.resourceVersion = version } -func (a genericAccessor) SelfLink() string { +func (a genericAccessor) GetSelfLink() string { return *a.selfLink } @@ -383,7 +421,7 @@ func (a genericAccessor) SetSelfLink(selfLink string) { *a.selfLink = selfLink } -func (a genericAccessor) Labels() map[string]string { +func (a genericAccessor) GetLabels() map[string]string { if a.labels == nil { return nil } @@ -394,7 +432,7 @@ func (a genericAccessor) SetLabels(labels map[string]string) { *a.labels = labels } -func (a genericAccessor) Annotations() map[string]string { +func (a genericAccessor) GetAnnotations() map[string]string { if a.annotations == nil { return nil } diff --git a/pkg/api/meta/meta_test.go b/pkg/api/meta/meta_test.go index 37cedb2be6..9d6c7abd62 100644 --- a/pkg/api/meta/meta_test.go +++ b/pkg/api/meta/meta_test.go @@ -14,16 +14,117 @@ See the License for the specific language governing permissions and limitations under the License. */ -package meta +package meta_test import ( "reflect" "testing" + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" + "k8s.io/kubernetes/pkg/types" ) +func TestAPIObjectMeta(t *testing.T) { + j := &api.Pod{ + TypeMeta: unversioned.TypeMeta{APIVersion: "/a", Kind: "b"}, + ObjectMeta: api.ObjectMeta{ + Namespace: "bar", + Name: "foo", + GenerateName: "prefix", + UID: "uid", + ResourceVersion: "1", + SelfLink: "some/place/only/we/know", + Labels: map[string]string{"foo": "bar"}, + Annotations: map[string]string{"x": "y"}, + }, + } + var _ meta.Object = &j.ObjectMeta + var _ meta.ObjectMetaAccessor = j + accessor, err := meta.Accessor(j) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if accessor != meta.Object(&j.ObjectMeta) { + t.Fatalf("should have returned the same pointer: %#v %#v", accessor, j) + } + if e, a := "bar", accessor.GetNamespace(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "foo", accessor.GetName(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "prefix", accessor.GetGenerateName(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "uid", string(accessor.GetUID()); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "1", accessor.GetResourceVersion(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + + typeAccessor, err := meta.TypeAccessor(j) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if e, a := "/a", typeAccessor.GetAPIVersion(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "b", typeAccessor.GetKind(); e != a { + t.Errorf("expected %v, got %v", e, a) + } + + accessor.SetNamespace("baz") + accessor.SetName("bar") + accessor.SetGenerateName("generate") + accessor.SetUID("other") + typeAccessor.SetAPIVersion("c") + typeAccessor.SetKind("d") + accessor.SetResourceVersion("2") + accessor.SetSelfLink("google.com") + + // Prove that accessor changes the original object. + if e, a := "baz", j.Namespace; e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "bar", j.Name; e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "generate", j.GenerateName; e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := types.UID("other"), j.UID; e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "/c", j.APIVersion; e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "d", j.Kind; e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "2", j.ResourceVersion; e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "google.com", j.SelfLink; e != a { + t.Errorf("expected %v, got %v", e, a) + } + + typeAccessor.SetAPIVersion("d") + typeAccessor.SetKind("e") + if e, a := "/d", j.APIVersion; e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "e", j.Kind; e != a { + t.Errorf("expected %v, got %v", e, a) + } +} + func TestGenericTypeMeta(t *testing.T) { type TypeMeta struct { Kind string `json:"kind,omitempty"` @@ -55,43 +156,37 @@ func TestGenericTypeMeta(t *testing.T) { Annotations: map[string]string{"x": "y"}, }, } - accessor, err := Accessor(&j) + accessor, err := meta.Accessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } - if e, a := "bar", accessor.Namespace(); e != a { + if e, a := "bar", accessor.GetNamespace(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "foo", accessor.Name(); e != a { + if e, a := "foo", accessor.GetName(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "prefix", accessor.GenerateName(); e != a { + if e, a := "prefix", accessor.GetGenerateName(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "uid", string(accessor.UID()); e != a { + if e, a := "uid", string(accessor.GetUID()); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "a", accessor.APIVersion(); e != a { + if e, a := "1", accessor.GetResourceVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "b", accessor.Kind(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "1", accessor.ResourceVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "some/place/only/we/know", accessor.SelfLink(); e != a { + if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { t.Errorf("expected %v, got %v", e, a) } - typeAccessor, err := TypeAccessor(&j) + typeAccessor, err := meta.TypeAccessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } - if e, a := "a", accessor.APIVersion(); e != a { + if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "b", accessor.Kind(); e != a { + if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } @@ -99,8 +194,8 @@ func TestGenericTypeMeta(t *testing.T) { accessor.SetName("bar") accessor.SetGenerateName("generate") accessor.SetUID("other") - accessor.SetAPIVersion("c") - accessor.SetKind("d") + typeAccessor.SetAPIVersion("c") + typeAccessor.SetKind("d") accessor.SetResourceVersion("2") accessor.SetSelfLink("google.com") @@ -157,7 +252,13 @@ type InternalObject struct { TypeMeta InternalTypeMeta `json:",inline"` } -func (*InternalObject) IsAnAPIObject() {} +func (obj *InternalObject) GetObjectKind() unversioned.ObjectKind { return obj } +func (obj *InternalObject) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.TypeMeta.APIVersion, obj.TypeMeta.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *InternalObject) GroupVersionKind() *unversioned.GroupVersionKind { + return unversioned.FromAPIVersionAndKind(obj.TypeMeta.APIVersion, obj.TypeMeta.Kind) +} func TestGenericTypeMetaAccessor(t *testing.T) { j := &InternalObject{ @@ -166,7 +267,7 @@ func TestGenericTypeMetaAccessor(t *testing.T) { Name: "foo", GenerateName: "prefix", UID: "uid", - APIVersion: "a", + APIVersion: "/a", Kind: "b", ResourceVersion: "1", SelfLink: "some/place/only/we/know", @@ -174,7 +275,7 @@ func TestGenericTypeMetaAccessor(t *testing.T) { Annotations: map[string]string{"x": "y"}, }, } - accessor := NewAccessor() + accessor := meta.NewAccessor() namespace, err := accessor.Namespace(j) if err != nil { t.Errorf("unexpected error: %v", err) @@ -207,7 +308,7 @@ func TestGenericTypeMetaAccessor(t *testing.T) { if err != nil { t.Errorf("unexpected error: %v", err) } - if e, a := "a", apiVersion; e != a { + if e, a := "/a", apiVersion; e != a { t.Errorf("expected %v, got %v", e, a) } kind, err := accessor.Kind(j) @@ -291,7 +392,7 @@ func TestGenericTypeMetaAccessor(t *testing.T) { if e, a := "other", j.TypeMeta.UID; e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "c", j.TypeMeta.APIVersion; e != a { + if e, a := "/c", j.TypeMeta.APIVersion; e != a { t.Errorf("expected %v, got %v", e, a) } if e, a := "d", j.TypeMeta.Kind; e != a { @@ -347,38 +448,43 @@ func TestGenericObjectMeta(t *testing.T) { Annotations: map[string]string{"a": "b"}, }, } - accessor, err := Accessor(&j) + accessor, err := meta.Accessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } - if e, a := "bar", accessor.Namespace(); e != a { + if e, a := "bar", accessor.GetNamespace(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "foo", accessor.Name(); e != a { + if e, a := "foo", accessor.GetName(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "prefix", accessor.GenerateName(); e != a { + if e, a := "prefix", accessor.GetGenerateName(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "uid", string(accessor.UID()); e != a { + if e, a := "uid", string(accessor.GetUID()); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "a", accessor.APIVersion(); e != a { + if e, a := "1", accessor.GetResourceVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "b", accessor.Kind(); e != a { + if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "1", accessor.ResourceVersion(); e != a { + if e, a := 1, len(accessor.GetLabels()); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "some/place/only/we/know", accessor.SelfLink(); e != a { + if e, a := 1, len(accessor.GetAnnotations()); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := 1, len(accessor.Labels()); e != a { + + typeAccessor, err := meta.TypeAccessor(&j) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := 1, len(accessor.Annotations()); e != a { + if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } @@ -386,8 +492,8 @@ func TestGenericObjectMeta(t *testing.T) { accessor.SetName("bar") accessor.SetGenerateName("generate") accessor.SetUID("other") - accessor.SetAPIVersion("c") - accessor.SetKind("d") + typeAccessor.SetAPIVersion("c") + typeAccessor.SetKind("d") accessor.SetResourceVersion("2") accessor.SetSelfLink("google.com") accessor.SetLabels(map[string]string{"other": "label"}) @@ -449,33 +555,38 @@ func TestGenericListMeta(t *testing.T) { SelfLink: "some/place/only/we/know", }, } - accessor, err := Accessor(&j) + accessor, err := meta.Accessor(&j) if err != nil { t.Fatalf("unexpected error: %v", err) } - if e, a := "", accessor.Name(); e != a { + if e, a := "", accessor.GetName(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "", string(accessor.UID()); e != a { + if e, a := "", string(accessor.GetUID()); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "a", accessor.APIVersion(); e != a { + if e, a := "1", accessor.GetResourceVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "b", accessor.Kind(); e != a { + if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "1", accessor.ResourceVersion(); e != a { + + typeAccessor, err := meta.TypeAccessor(&j) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if e, a := "a", typeAccessor.GetAPIVersion(); e != a { t.Errorf("expected %v, got %v", e, a) } - if e, a := "some/place/only/we/know", accessor.SelfLink(); e != a { + if e, a := "b", typeAccessor.GetKind(); e != a { t.Errorf("expected %v, got %v", e, a) } accessor.SetName("bar") accessor.SetUID("other") - accessor.SetAPIVersion("c") - accessor.SetKind("d") + typeAccessor.SetAPIVersion("c") + typeAccessor.SetKind("d") accessor.SetResourceVersion("2") accessor.SetSelfLink("google.com") @@ -498,12 +609,19 @@ type MyAPIObject struct { TypeMeta InternalTypeMeta `json:",inline"` } -func (*MyAPIObject) IsAnAPIObject() {} - -type MyIncorrectlyMarkedAsAPIObject struct { +func (obj *MyAPIObject) GetObjectKind() unversioned.ObjectKind { return obj } +func (obj *MyAPIObject) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.TypeMeta.APIVersion, obj.TypeMeta.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *MyAPIObject) GroupVersionKind() *unversioned.GroupVersionKind { + return unversioned.FromAPIVersionAndKind(obj.TypeMeta.APIVersion, obj.TypeMeta.Kind) } -func (*MyIncorrectlyMarkedAsAPIObject) IsAnAPIObject() {} +type MyIncorrectlyMarkedAsAPIObject struct{} + +func (obj *MyIncorrectlyMarkedAsAPIObject) GetObjectKind() unversioned.ObjectKind { + return unversioned.EmptyObjectKind +} func TestResourceVersionerOfAPI(t *testing.T) { type T struct { @@ -515,7 +633,7 @@ func TestResourceVersionerOfAPI(t *testing.T) { "api object with version": {&MyAPIObject{TypeMeta: InternalTypeMeta{ResourceVersion: "1"}}, "1"}, "pointer to api object with version": {&MyAPIObject{TypeMeta: InternalTypeMeta{ResourceVersion: "1"}}, "1"}, } - versioning := NewAccessor() + versioning := meta.NewAccessor() for key, testCase := range testCases { actual, err := versioning.ResourceVersion(testCase.Object) if err != nil { @@ -578,7 +696,7 @@ func TestTypeMetaSelfLinker(t *testing.T) { }, } - linker := runtime.SelfLinker(NewAccessor()) + linker := runtime.SelfLinker(meta.NewAccessor()) for name, item := range table { got, err := linker.SelfLink(item.obj) if e, a := item.succeed, err == nil; e != a { @@ -603,3 +721,58 @@ func TestTypeMetaSelfLinker(t *testing.T) { } } } + +// BenchmarkAccessorSetFastPath shows the interface fast path +func BenchmarkAccessorSetFastPath(b *testing.B) { + obj := &api.Pod{ + TypeMeta: unversioned.TypeMeta{APIVersion: "/a", Kind: "b"}, + ObjectMeta: api.ObjectMeta{ + Namespace: "bar", + Name: "foo", + GenerateName: "prefix", + UID: "uid", + ResourceVersion: "1", + SelfLink: "some/place/only/we/know", + Labels: map[string]string{"foo": "bar"}, + Annotations: map[string]string{"x": "y"}, + }, + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + acc, err := meta.Accessor(obj) + if err != nil { + b.Fatal(err) + } + acc.SetNamespace("something") + } + b.StopTimer() +} + +// BenchmarkAccessorSetReflection provides a baseline for accessor performance +func BenchmarkAccessorSetReflection(b *testing.B) { + obj := &InternalObject{ + InternalTypeMeta{ + Namespace: "bar", + Name: "foo", + GenerateName: "prefix", + UID: "uid", + APIVersion: "/a", + Kind: "b", + ResourceVersion: "1", + SelfLink: "some/place/only/we/know", + Labels: map[string]string{"foo": "bar"}, + Annotations: map[string]string{"x": "y"}, + }, + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + acc, err := meta.Accessor(obj) + if err != nil { + b.Fatal(err) + } + acc.SetNamespace("something") + } + b.StopTimer() +} diff --git a/pkg/api/meta_test.go b/pkg/api/meta_test.go index f3b293cd99..e4a9657a0b 100644 --- a/pkg/api/meta_test.go +++ b/pkg/api/meta_test.go @@ -20,8 +20,11 @@ import ( "testing" "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/meta" ) +var _ meta.Object = &api.ObjectMeta{} + // TestFillObjectMetaSystemFields validates that system populated fields are set on an object func TestFillObjectMetaSystemFields(t *testing.T) { ctx := api.NewDefaultContext() diff --git a/pkg/api/ref.go b/pkg/api/ref.go index e04af0474d..95690b821a 100644 --- a/pkg/api/ref.go +++ b/pkg/api/ref.go @@ -23,6 +23,7 @@ import ( "strings" "k8s.io/kubernetes/pkg/api/meta" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" ) @@ -49,10 +50,16 @@ func GetReference(obj runtime.Object) (*ObjectReference, error) { return nil, err } + gvk := obj.GetObjectKind().GroupVersionKind() + // if the object referenced is actually persisted, we can just get kind from meta // if we are building an object reference to something not yet persisted, we should fallback to scheme - kind := meta.Kind() - if kind == "" { + var kind string + if gvk != nil { + kind = gvk.Kind + } + if len(kind) == 0 { + // TODO: this is wrong gvk, err := Scheme.ObjectKind(obj) if err != nil { return nil, err @@ -61,32 +68,34 @@ func GetReference(obj runtime.Object) (*ObjectReference, error) { } // if the object referenced is actually persisted, we can also get version from meta - version := meta.APIVersion() - if version == "" { - selfLink := meta.SelfLink() - if selfLink == "" { + var version string + if gvk != nil { + version = gvk.GroupVersion().String() + } + if len(version) == 0 { + selfLink := meta.GetSelfLink() + if len(selfLink) == 0 { return nil, ErrNoSelfLink - } else { - selfLinkUrl, err := url.Parse(selfLink) - if err != nil { - return nil, err - } - // example paths: ///* - parts := strings.Split(selfLinkUrl.Path, "/") - if len(parts) < 3 { - return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", selfLink, version) - } - version = parts[2] } + selfLinkUrl, err := url.Parse(selfLink) + if err != nil { + return nil, err + } + // example paths: ///* + parts := strings.Split(selfLinkUrl.Path, "/") + if len(parts) < 3 { + return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", selfLink, version) + } + version = parts[2] } return &ObjectReference{ Kind: kind, APIVersion: version, - Name: meta.Name(), - Namespace: meta.Namespace(), - UID: meta.UID(), - ResourceVersion: meta.ResourceVersion(), + Name: meta.GetName(), + Namespace: meta.GetNamespace(), + UID: meta.GetUID(), + ResourceVersion: meta.GetResourceVersion(), }, nil } @@ -102,4 +111,9 @@ func GetPartialReference(obj runtime.Object, fieldPath string) (*ObjectReference // IsAnAPIObject allows clients to preemptively get a reference to an API object and pass it to places that // intend only to get a reference to that object. This simplifies the event recording interface. -func (*ObjectReference) IsAnAPIObject() {} +func (obj *ObjectReference) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *ObjectReference) GroupVersionKind() *unversioned.GroupVersionKind { + return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) +} diff --git a/pkg/api/ref_test.go b/pkg/api/ref_test.go index cec77d5454..4f716672e9 100644 --- a/pkg/api/ref_test.go +++ b/pkg/api/ref_test.go @@ -26,14 +26,14 @@ import ( type FakeAPIObject struct{} -func (*FakeAPIObject) IsAnAPIObject() {} +func (obj *FakeAPIObject) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } type ExtensionAPIObject struct { unversioned.TypeMeta ObjectMeta } -func (*ExtensionAPIObject) IsAnAPIObject() {} +func (obj *ExtensionAPIObject) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } func TestGetReference(t *testing.T) { table := map[string]struct { diff --git a/pkg/api/register.go b/pkg/api/register.go index bae0def24b..2776f8e4be 100644 --- a/pkg/api/register.go +++ b/pkg/api/register.go @@ -17,6 +17,7 @@ limitations under the License. package api import ( + "k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" ) @@ -94,44 +95,63 @@ func init() { Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.APIResourceList{}) } -func (*Pod) IsAnAPIObject() {} -func (*PodList) IsAnAPIObject() {} -func (*PodStatusResult) IsAnAPIObject() {} -func (*PodTemplate) IsAnAPIObject() {} -func (*PodTemplateList) IsAnAPIObject() {} -func (*ReplicationController) IsAnAPIObject() {} -func (*ReplicationControllerList) IsAnAPIObject() {} -func (*Service) IsAnAPIObject() {} -func (*ServiceList) IsAnAPIObject() {} -func (*Endpoints) IsAnAPIObject() {} -func (*EndpointsList) IsAnAPIObject() {} -func (*Node) IsAnAPIObject() {} -func (*NodeList) IsAnAPIObject() {} -func (*Binding) IsAnAPIObject() {} -func (*Event) IsAnAPIObject() {} -func (*EventList) IsAnAPIObject() {} -func (*List) IsAnAPIObject() {} -func (*LimitRange) IsAnAPIObject() {} -func (*LimitRangeList) IsAnAPIObject() {} -func (*ResourceQuota) IsAnAPIObject() {} -func (*ResourceQuotaList) IsAnAPIObject() {} -func (*Namespace) IsAnAPIObject() {} -func (*NamespaceList) IsAnAPIObject() {} -func (*ServiceAccount) IsAnAPIObject() {} -func (*ServiceAccountList) IsAnAPIObject() {} -func (*Secret) IsAnAPIObject() {} -func (*SecretList) IsAnAPIObject() {} -func (*PersistentVolume) IsAnAPIObject() {} -func (*PersistentVolumeList) IsAnAPIObject() {} -func (*PersistentVolumeClaim) IsAnAPIObject() {} -func (*PersistentVolumeClaimList) IsAnAPIObject() {} -func (*DeleteOptions) IsAnAPIObject() {} -func (*ListOptions) IsAnAPIObject() {} -func (*PodAttachOptions) IsAnAPIObject() {} -func (*PodLogOptions) IsAnAPIObject() {} -func (*PodExecOptions) IsAnAPIObject() {} -func (*PodProxyOptions) IsAnAPIObject() {} -func (*ComponentStatus) IsAnAPIObject() {} -func (*ComponentStatusList) IsAnAPIObject() {} -func (*SerializedReference) IsAnAPIObject() {} -func (*RangeAllocation) IsAnAPIObject() {} +func (obj *Pod) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *Pod) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodStatusResult) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *PodStatusResult) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodTemplate) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *PodTemplate) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodTemplateList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ReplicationController) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *ReplicationController) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ReplicationControllerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Service) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *Service) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ServiceList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Endpoints) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *Endpoints) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *EndpointsList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Node) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *Node) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *NodeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Binding) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *Binding) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Event) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *Event) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *EventList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *List) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ListOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *LimitRange) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *LimitRange) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *LimitRangeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ResourceQuota) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *ResourceQuota) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ResourceQuotaList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Namespace) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *Namespace) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *NamespaceList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ServiceAccount) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *ServiceAccount) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ServiceAccountList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Secret) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *Secret) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *SecretList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PersistentVolume) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *PersistentVolume) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PersistentVolumeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PersistentVolumeClaim) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *PersistentVolumeClaim) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PersistentVolumeClaimList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *DeleteOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodAttachOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodLogOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodExecOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodProxyOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ComponentStatus) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *ComponentStatus) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ComponentStatusList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *SerializedReference) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *RangeAllocation) GetObjectMeta() meta.Object { return &obj.ObjectMeta } +func (obj *RangeAllocation) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ObjectReference) GetObjectKind() unversioned.ObjectKind { return obj } diff --git a/pkg/api/rest/rest.go b/pkg/api/rest/rest.go index ae3f296b96..393d6d5cec 100644 --- a/pkg/api/rest/rest.go +++ b/pkg/api/rest/rest.go @@ -274,5 +274,4 @@ type ConnectRequest struct { ResourcePath string } -// IsAnAPIObject makes ConnectRequest a runtime.Object -func (*ConnectRequest) IsAnAPIObject() {} +func (obj *ConnectRequest) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } diff --git a/pkg/api/unversioned/group_version.go b/pkg/api/unversioned/group_version.go index 0ed4353f78..546496ce5e 100644 --- a/pkg/api/unversioned/group_version.go +++ b/pkg/api/unversioned/group_version.go @@ -198,3 +198,48 @@ func (gv *GroupVersion) UnmarshalJSON(value []byte) error { func (gv *GroupVersion) UnmarshalText(value []byte) error { return gv.unmarshal(value) } + +// ToAPIVersionAndKind is a convenience method for satisfying runtime.Object on types that +// do not use TypeMeta. +func (gvk *GroupVersionKind) ToAPIVersionAndKind() (string, string) { + if gvk == nil { + return "", "" + } + return gvk.GroupVersion().String(), gvk.Kind +} + +// FromAPIVersionAndKind returns a GVK representing the provided fields for types that +// do not use TypeMeta. This method exists to support test types and legacy serializations +// that have a distinct group and kind. +// TODO: further reduce usage of this method. +func FromAPIVersionAndKind(apiVersion, kind string) *GroupVersionKind { + if gv, err := ParseGroupVersion(apiVersion); err == nil { + return &GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind} + } + return &GroupVersionKind{Kind: kind} +} + +// All objects that are serialized from a Scheme encode their type information. This interface is used +// by serialization to set type information from the Scheme onto the serialized version of an object. +// For objects that cannot be serialized or have unique requirements, this interface may be a no-op. +// TODO: this belongs in pkg/runtime, move unversioned.GVK into runtime. +type ObjectKind interface { + // SetGroupVersionKind sets or clears the intended serialized kind of an object. Passing kind nil + // should clear the current setting. + SetGroupVersionKind(kind *GroupVersionKind) + // GroupVersionKind returns the stored group, version, and kind of an object, or nil if the object does + // not expose or provide these fields. + GroupVersionKind() *GroupVersionKind +} + +// EmptyObjectKind implements the ObjectKind interface as a noop +// TODO: this belongs in pkg/runtime, move unversioned.GVK into runtime. +var EmptyObjectKind = emptyObjectKind{} + +type emptyObjectKind struct{} + +// SetGroupVersionKind implements the ObjectKind interface +func (emptyObjectKind) SetGroupVersionKind(gvk *GroupVersionKind) {} + +// GroupVersionKind implements the ObjectKind interface +func (emptyObjectKind) GroupVersionKind() *GroupVersionKind { return nil } diff --git a/pkg/api/unversioned/register.go b/pkg/api/unversioned/register.go index a5389f2b2e..0e3d684c62 100644 --- a/pkg/api/unversioned/register.go +++ b/pkg/api/unversioned/register.go @@ -24,4 +24,19 @@ func Kind(kind string) GroupKind { return SchemeGroupVersion.WithKind(kind).GroupKind() } -// TODO this doesn't actually register them right now due to cycles. +// SetGroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta +func (obj *TypeMeta) SetGroupVersionKind(gvk *GroupVersionKind) { + obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() +} + +// GroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta +func (obj *TypeMeta) GroupVersionKind() *GroupVersionKind { + return FromAPIVersionAndKind(obj.APIVersion, obj.Kind) +} + +func (obj *ListOptions) GetObjectKind() ObjectKind { return &obj.TypeMeta } +func (obj *Status) GetObjectKind() ObjectKind { return &obj.TypeMeta } +func (obj *APIVersions) GetObjectKind() ObjectKind { return &obj.TypeMeta } +func (obj *APIGroupList) GetObjectKind() ObjectKind { return &obj.TypeMeta } +func (obj *APIGroup) GetObjectKind() ObjectKind { return &obj.TypeMeta } +func (obj *APIResourceList) GetObjectKind() ObjectKind { return &obj.TypeMeta } diff --git a/pkg/api/unversioned/types.go b/pkg/api/unversioned/types.go index cee962a3b8..56eb3cd939 100644 --- a/pkg/api/unversioned/types.go +++ b/pkg/api/unversioned/types.go @@ -302,13 +302,6 @@ const ( CauseTypeUnexpectedServerResponse CauseType = "UnexpectedServerResponse" ) -func (*ListOptions) IsAnAPIObject() {} -func (*Status) IsAnAPIObject() {} -func (*APIVersions) IsAnAPIObject() {} -func (*APIGroupList) IsAnAPIObject() {} -func (*APIGroup) IsAnAPIObject() {} -func (*APIResourceList) IsAnAPIObject() {} - // APIVersions lists the versions that are available, to allow clients to // discover the API at /api, which is the root path of the legacy v1 API. // diff --git a/pkg/api/v1/register.go b/pkg/api/v1/register.go index f961b8e2dd..880a0ae284 100644 --- a/pkg/api/v1/register.go +++ b/pkg/api/v1/register.go @@ -94,44 +94,44 @@ func addKnownTypes() { api.Scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.Status{}) } -func (*Pod) IsAnAPIObject() {} -func (*PodList) IsAnAPIObject() {} -func (*PodStatusResult) IsAnAPIObject() {} -func (*PodTemplate) IsAnAPIObject() {} -func (*PodTemplateList) IsAnAPIObject() {} -func (*ReplicationController) IsAnAPIObject() {} -func (*ReplicationControllerList) IsAnAPIObject() {} -func (*Service) IsAnAPIObject() {} -func (*ServiceList) IsAnAPIObject() {} -func (*Endpoints) IsAnAPIObject() {} -func (*EndpointsList) IsAnAPIObject() {} -func (*Node) IsAnAPIObject() {} -func (*NodeList) IsAnAPIObject() {} -func (*Binding) IsAnAPIObject() {} -func (*Event) IsAnAPIObject() {} -func (*EventList) IsAnAPIObject() {} -func (*List) IsAnAPIObject() {} -func (*LimitRange) IsAnAPIObject() {} -func (*LimitRangeList) IsAnAPIObject() {} -func (*ResourceQuota) IsAnAPIObject() {} -func (*ResourceQuotaList) IsAnAPIObject() {} -func (*Namespace) IsAnAPIObject() {} -func (*NamespaceList) IsAnAPIObject() {} -func (*Secret) IsAnAPIObject() {} -func (*SecretList) IsAnAPIObject() {} -func (*ServiceAccount) IsAnAPIObject() {} -func (*ServiceAccountList) IsAnAPIObject() {} -func (*PersistentVolume) IsAnAPIObject() {} -func (*PersistentVolumeList) IsAnAPIObject() {} -func (*PersistentVolumeClaim) IsAnAPIObject() {} -func (*PersistentVolumeClaimList) IsAnAPIObject() {} -func (*DeleteOptions) IsAnAPIObject() {} -func (*ListOptions) IsAnAPIObject() {} -func (*PodAttachOptions) IsAnAPIObject() {} -func (*PodLogOptions) IsAnAPIObject() {} -func (*PodExecOptions) IsAnAPIObject() {} -func (*PodProxyOptions) IsAnAPIObject() {} -func (*ComponentStatus) IsAnAPIObject() {} -func (*ComponentStatusList) IsAnAPIObject() {} -func (*SerializedReference) IsAnAPIObject() {} -func (*RangeAllocation) IsAnAPIObject() {} +func (obj *Pod) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodStatusResult) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodTemplate) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodTemplateList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ReplicationController) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ReplicationControllerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Service) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ServiceList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Endpoints) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *EndpointsList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Node) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *NodeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Binding) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Event) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *EventList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *List) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *LimitRange) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *LimitRangeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ResourceQuota) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ResourceQuotaList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Namespace) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *NamespaceList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Secret) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *SecretList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ServiceAccount) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ServiceAccountList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PersistentVolume) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PersistentVolumeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PersistentVolumeClaim) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PersistentVolumeClaimList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *DeleteOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ListOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodAttachOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodLogOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodExecOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *PodProxyOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ComponentStatus) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ComponentStatusList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *SerializedReference) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *RangeAllocation) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/apis/abac/register.go b/pkg/apis/abac/register.go index 0ae7b85c04..bc99f922b1 100644 --- a/pkg/apis/abac/register.go +++ b/pkg/apis/abac/register.go @@ -34,4 +34,4 @@ func init() { ) } -func (*Policy) IsAnAPIObject() {} +func (obj *Policy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/apis/abac/v0/register.go b/pkg/apis/abac/v0/register.go index 1651e5570c..edc19f6ec0 100644 --- a/pkg/apis/abac/v0/register.go +++ b/pkg/apis/abac/v0/register.go @@ -34,4 +34,4 @@ func init() { ) } -func (*Policy) IsAnAPIObject() {} +func (obj *Policy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/apis/abac/v1beta1/register.go b/pkg/apis/abac/v1beta1/register.go index b5bf2b6f9f..61997ed962 100644 --- a/pkg/apis/abac/v1beta1/register.go +++ b/pkg/apis/abac/v1beta1/register.go @@ -34,4 +34,4 @@ func init() { ) } -func (*Policy) IsAnAPIObject() {} +func (obj *Policy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/apis/componentconfig/register.go b/pkg/apis/componentconfig/register.go index 2359f041b6..ec012ee3b7 100644 --- a/pkg/apis/componentconfig/register.go +++ b/pkg/apis/componentconfig/register.go @@ -48,4 +48,4 @@ func addKnownTypes() { ) } -func (_ *KubeProxyConfiguration) IsAnAPIObject() {} +func (obj *KubeProxyConfiguration) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/apis/componentconfig/v1alpha1/register.go b/pkg/apis/componentconfig/v1alpha1/register.go index 2ea498b794..56da8fd2cc 100644 --- a/pkg/apis/componentconfig/v1alpha1/register.go +++ b/pkg/apis/componentconfig/v1alpha1/register.go @@ -41,4 +41,4 @@ func addKnownTypes() { ) } -func (_ *KubeProxyConfiguration) IsAnAPIObject() {} +func (obj *KubeProxyConfiguration) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/apis/extensions/register.go b/pkg/apis/extensions/register.go index 07141bd669..b346c89dbd 100644 --- a/pkg/apis/extensions/register.go +++ b/pkg/apis/extensions/register.go @@ -68,21 +68,21 @@ func addKnownTypes() { ) } -func (*ClusterAutoscaler) IsAnAPIObject() {} -func (*ClusterAutoscalerList) IsAnAPIObject() {} -func (*Deployment) IsAnAPIObject() {} -func (*DeploymentList) IsAnAPIObject() {} -func (*HorizontalPodAutoscaler) IsAnAPIObject() {} -func (*HorizontalPodAutoscalerList) IsAnAPIObject() {} -func (*Job) IsAnAPIObject() {} -func (*JobList) IsAnAPIObject() {} -func (*ReplicationControllerDummy) IsAnAPIObject() {} -func (*Scale) IsAnAPIObject() {} -func (*ThirdPartyResource) IsAnAPIObject() {} -func (*ThirdPartyResourceList) IsAnAPIObject() {} -func (*DaemonSet) IsAnAPIObject() {} -func (*DaemonSetList) IsAnAPIObject() {} -func (*ThirdPartyResourceData) IsAnAPIObject() {} -func (*ThirdPartyResourceDataList) IsAnAPIObject() {} -func (*Ingress) IsAnAPIObject() {} -func (*IngressList) IsAnAPIObject() {} +func (obj *ClusterAutoscaler) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ClusterAutoscalerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Deployment) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *DeploymentList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *HorizontalPodAutoscaler) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *HorizontalPodAutoscalerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Job) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *JobList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ReplicationControllerDummy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Scale) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ThirdPartyResource) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ThirdPartyResourceList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *DaemonSet) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *DaemonSetList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ThirdPartyResourceData) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ThirdPartyResourceDataList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Ingress) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *IngressList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/apis/extensions/v1beta1/register.go b/pkg/apis/extensions/v1beta1/register.go index d2c8795ff1..72a9497f1f 100644 --- a/pkg/apis/extensions/v1beta1/register.go +++ b/pkg/apis/extensions/v1beta1/register.go @@ -61,22 +61,22 @@ func addKnownTypes() { ) } -func (*ClusterAutoscaler) IsAnAPIObject() {} -func (*ClusterAutoscalerList) IsAnAPIObject() {} -func (*Deployment) IsAnAPIObject() {} -func (*DeploymentList) IsAnAPIObject() {} -func (*HorizontalPodAutoscaler) IsAnAPIObject() {} -func (*HorizontalPodAutoscalerList) IsAnAPIObject() {} -func (*Job) IsAnAPIObject() {} -func (*JobList) IsAnAPIObject() {} -func (*ReplicationControllerDummy) IsAnAPIObject() {} -func (*Scale) IsAnAPIObject() {} -func (*ThirdPartyResource) IsAnAPIObject() {} -func (*ThirdPartyResourceList) IsAnAPIObject() {} -func (*DaemonSet) IsAnAPIObject() {} -func (*DaemonSetList) IsAnAPIObject() {} -func (*ThirdPartyResourceData) IsAnAPIObject() {} -func (*ThirdPartyResourceDataList) IsAnAPIObject() {} -func (*Ingress) IsAnAPIObject() {} -func (*IngressList) IsAnAPIObject() {} -func (*ListOptions) IsAnAPIObject() {} +func (obj *ClusterAutoscaler) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ClusterAutoscalerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Deployment) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *DeploymentList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *HorizontalPodAutoscaler) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *HorizontalPodAutoscalerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Job) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *JobList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ReplicationControllerDummy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Scale) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ThirdPartyResource) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ThirdPartyResourceList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *DaemonSet) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *DaemonSetList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ThirdPartyResourceData) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ThirdPartyResourceDataList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Ingress) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *IngressList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ListOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/apis/metrics/register.go b/pkg/apis/metrics/register.go index 181b31a178..b59ef1f13d 100644 --- a/pkg/apis/metrics/register.go +++ b/pkg/apis/metrics/register.go @@ -51,5 +51,5 @@ func addKnownTypes() { ) } -func (*RawNode) IsAnAPIObject() {} -func (*RawPod) IsAnAPIObject() {} +func (obj *RawNode) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *RawPod) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/apis/metrics/v1alpha1/register.go b/pkg/apis/metrics/v1alpha1/register.go index cacaebbd62..5acb2ce6c8 100644 --- a/pkg/apis/metrics/v1alpha1/register.go +++ b/pkg/apis/metrics/v1alpha1/register.go @@ -43,5 +43,5 @@ func addKnownTypes() { ) } -func (*RawNode) IsAnAPIObject() {} -func (*RawPod) IsAnAPIObject() {} +func (obj *RawNode) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *RawPod) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/apiserver/apiserver_test.go b/pkg/apiserver/apiserver_test.go index 5a1f14c26c..1bda5e7806 100644 --- a/pkg/apiserver/apiserver_test.go +++ b/pkg/apiserver/apiserver_test.go @@ -365,7 +365,7 @@ func (s *SimpleStream) Close() error { return nil } -func (s *SimpleStream) IsAnAPIObject() {} +func (obj *SimpleStream) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } func (s *SimpleStream) InputStream(version, accept string) (io.ReadCloser, bool, string, error) { s.version = version @@ -2680,7 +2680,9 @@ type UnregisteredAPIObject struct { Value string } -func (*UnregisteredAPIObject) IsAnAPIObject() {} +func (obj *UnregisteredAPIObject) GetObjectKind() unversioned.ObjectKind { + return unversioned.EmptyObjectKind +} func TestWriteJSONDecodeError(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { diff --git a/pkg/apiserver/resthandler_test.go b/pkg/apiserver/resthandler_test.go index 15dfdffc5c..ab060b1045 100644 --- a/pkg/apiserver/resthandler_test.go +++ b/pkg/apiserver/resthandler_test.go @@ -45,7 +45,7 @@ type testPatchSubType struct { StringField string `json:"theField"` } -func (*testPatchType) IsAnAPIObject() {} +func (obj *testPatchType) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } func TestPatchAnonymousField(t *testing.T) { originalJS := `{"kind":"testPatchType","theField":"my-value"}` diff --git a/pkg/apiserver/testing/types.go b/pkg/apiserver/testing/types.go index 8f0f6bac7f..c6a3df3cdd 100644 --- a/pkg/apiserver/testing/types.go +++ b/pkg/apiserver/testing/types.go @@ -28,7 +28,7 @@ type Simple struct { Labels map[string]string `json:"labels,omitempty"` } -func (*Simple) IsAnAPIObject() {} +func (obj *Simple) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } type SimpleRoot struct { unversioned.TypeMeta `json:",inline"` @@ -37,7 +37,7 @@ type SimpleRoot struct { Labels map[string]string `json:"labels,omitempty"` } -func (*SimpleRoot) IsAnAPIObject() {} +func (obj *SimpleRoot) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } type SimpleGetOptions struct { unversioned.TypeMeta `json:",inline"` @@ -53,7 +53,7 @@ func (SimpleGetOptions) SwaggerDoc() map[string]string { } } -func (*SimpleGetOptions) IsAnAPIObject() {} +func (obj *SimpleGetOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } type SimpleList struct { unversioned.TypeMeta `json:",inline"` @@ -61,4 +61,4 @@ type SimpleList struct { Items []Simple `json:"items,omitempty"` } -func (*SimpleList) IsAnAPIObject() {} +func (obj *SimpleList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/client/cache/index.go b/pkg/client/cache/index.go index 0730ca459e..a0c0c288c7 100644 --- a/pkg/client/cache/index.go +++ b/pkg/client/cache/index.go @@ -59,7 +59,7 @@ func MetaNamespaceIndexFunc(obj interface{}) ([]string, error) { if err != nil { return []string{""}, fmt.Errorf("object has no meta: %v", err) } - return []string{meta.Namespace()}, nil + return []string{meta.GetNamespace()}, nil } // Index maps the indexed value to a set of keys in the store that match on that value diff --git a/pkg/client/cache/reflector.go b/pkg/client/cache/reflector.go index 97ab5470ec..49b007fe7e 100644 --- a/pkg/client/cache/reflector.go +++ b/pkg/client/cache/reflector.go @@ -240,7 +240,7 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error { if err != nil { return fmt.Errorf("%s: Unable to understand list result %#v", r.name, list) } - resourceVersion = metaInterface.ResourceVersion() + resourceVersion = metaInterface.GetResourceVersion() items, err := meta.ExtractList(list) if err != nil { return fmt.Errorf("%s: Unable to understand list result %#v (%v)", r.name, list, err) @@ -335,7 +335,7 @@ loop: util.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", r.name, event)) continue } - newResourceVersion := meta.ResourceVersion() + newResourceVersion := meta.GetResourceVersion() switch event.Type { case watch.Added: r.store.Add(event.Object) diff --git a/pkg/client/cache/store.go b/pkg/client/cache/store.go index a4e0856fec..17a360f8e4 100644 --- a/pkg/client/cache/store.go +++ b/pkg/client/cache/store.go @@ -80,10 +80,10 @@ func MetaNamespaceKeyFunc(obj interface{}) (string, error) { if err != nil { return "", fmt.Errorf("object has no meta: %v", err) } - if len(meta.Namespace()) > 0 { - return meta.Namespace() + "/" + meta.Name(), nil + if len(meta.GetNamespace()) > 0 { + return meta.GetNamespace() + "/" + meta.GetName(), nil } - return meta.Name(), nil + return meta.GetName(), nil } // SplitMetaNamespaceKey returns the namespace and name that diff --git a/pkg/client/unversioned/clientcmd/api/register.go b/pkg/client/unversioned/clientcmd/api/register.go index b5946dc7bd..f3be591718 100644 --- a/pkg/client/unversioned/clientcmd/api/register.go +++ b/pkg/client/unversioned/clientcmd/api/register.go @@ -34,4 +34,10 @@ func init() { ) } -func (*Config) IsAnAPIObject() {} +func (obj *Config) GetObjectKind() unversioned.ObjectKind { return obj } +func (obj *Config) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *Config) GroupVersionKind() *unversioned.GroupVersionKind { + return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) +} diff --git a/pkg/client/unversioned/clientcmd/api/v1/register.go b/pkg/client/unversioned/clientcmd/api/v1/register.go index c9e96039c7..18b77e07b1 100644 --- a/pkg/client/unversioned/clientcmd/api/v1/register.go +++ b/pkg/client/unversioned/clientcmd/api/v1/register.go @@ -35,4 +35,10 @@ func init() { ) } -func (*Config) IsAnAPIObject() {} +func (obj *Config) GetObjectKind() unversioned.ObjectKind { return obj } +func (obj *Config) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *Config) GroupVersionKind() *unversioned.GroupVersionKind { + return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) +} diff --git a/pkg/client/unversioned/request_test.go b/pkg/client/unversioned/request_test.go index 137d0fe693..7345954998 100644 --- a/pkg/client/unversioned/request_test.go +++ b/pkg/client/unversioned/request_test.go @@ -226,7 +226,8 @@ func TestRequestURI(t *testing.T) { type NotAnAPIObject struct{} -func (NotAnAPIObject) IsAnAPIObject() {} +func (obj NotAnAPIObject) GroupVersionKind() *unversioned.GroupVersionKind { return nil } +func (obj NotAnAPIObject) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) {} func TestRequestBody(t *testing.T) { // test unknown type diff --git a/pkg/controller/serviceaccount/serviceaccounts_controller.go b/pkg/controller/serviceaccount/serviceaccounts_controller.go index 2cc46eaa3a..c3a355c2aa 100644 --- a/pkg/controller/serviceaccount/serviceaccounts_controller.go +++ b/pkg/controller/serviceaccount/serviceaccounts_controller.go @@ -38,7 +38,7 @@ func nameIndexFunc(obj interface{}) ([]string, error) { if err != nil { return []string{""}, fmt.Errorf("object has no meta: %v", err) } - return []string{meta.Name()}, nil + return []string{meta.GetName()}, nil } // ServiceAccountsControllerOptions contains options for running a ServiceAccountsController diff --git a/pkg/conversion/meta.go b/pkg/conversion/meta.go index a418de04b4..bb33d12cb5 100644 --- a/pkg/conversion/meta.go +++ b/pkg/conversion/meta.go @@ -80,7 +80,20 @@ func (f SimpleMetaFactory) Update(version, kind string, obj interface{}) error { // on a pointer to a struct to version and kind. Provided as a convenience for others // implementing MetaFactory. Pass an array to baseFields to check one or more nested structs // for the named fields. The version field is treated as optional if it is not present in the struct. +// TODO: this method is on its way out func UpdateVersionAndKind(baseFields []string, versionField, version, kindField, kind string, obj interface{}) error { + if typed, ok := obj.(unversioned.ObjectKind); ok { + if len(version) == 0 && len(kind) == 0 { + typed.SetGroupVersionKind(nil) + } else { + gv, err := unversioned.ParseGroupVersion(version) + if err != nil { + return err + } + typed.SetGroupVersionKind(&unversioned.GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind}) + } + return nil + } v, err := EnforcePtr(obj) if err != nil { return err diff --git a/pkg/conversion/queryparams/convert_test.go b/pkg/conversion/queryparams/convert_test.go index c409756e44..8b513f076d 100644 --- a/pkg/conversion/queryparams/convert_test.go +++ b/pkg/conversion/queryparams/convert_test.go @@ -14,13 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -package queryparams +package queryparams_test import ( "net/url" "reflect" "testing" + "k8s.io/kubernetes/pkg/api/unversioned" + "k8s.io/kubernetes/pkg/conversion/queryparams" "k8s.io/kubernetes/pkg/runtime" ) @@ -38,7 +40,7 @@ type bar struct { Ignored2 string } -func (*bar) IsAnAPIObject() {} +func (obj *bar) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } type foo struct { Str string `json:"str"` @@ -51,14 +53,14 @@ type foo struct { Testmap map[string]string `json:"testmap,omitempty"` } -func (*foo) IsAnAPIObject() {} +func (obj *foo) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } type baz struct { Ptr *int `json:"ptr"` Bptr *bool `json:"bptr,omitempty"` } -func (*baz) IsAnAPIObject() {} +func (obj *baz) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } func validateResult(t *testing.T, input interface{}, actual, expected url.Values) { local := url.Values{} @@ -160,7 +162,7 @@ func TestConvert(t *testing.T) { } for _, test := range tests { - result, err := Convert(test.input) + result, err := queryparams.Convert(test.input) if err != nil { t.Errorf("Unexpected error while converting %#v: %v", test.input, err) } diff --git a/pkg/fieldpath/fieldpath.go b/pkg/fieldpath/fieldpath.go index d1f978e8a1..88c8a3131c 100644 --- a/pkg/fieldpath/fieldpath.go +++ b/pkg/fieldpath/fieldpath.go @@ -47,13 +47,13 @@ func ExtractFieldPathAsString(obj interface{}, fieldPath string) (string, error) switch fieldPath { case "metadata.annotations": - return formatMap(accessor.Annotations()), nil + return formatMap(accessor.GetAnnotations()), nil case "metadata.labels": - return formatMap(accessor.Labels()), nil + return formatMap(accessor.GetLabels()), nil case "metadata.name": - return accessor.Name(), nil + return accessor.GetName(), nil case "metadata.namespace": - return accessor.Namespace(), nil + return accessor.GetNamespace(), nil } return "", fmt.Errorf("Unsupported fieldPath: %v", fieldPath) diff --git a/pkg/kubectl/apply.go b/pkg/kubectl/apply.go index f8e89046a7..9edbd6fa73 100644 --- a/pkg/kubectl/apply.go +++ b/pkg/kubectl/apply.go @@ -92,7 +92,7 @@ func GetModifiedConfiguration(info *resource.Info, annotate bool) ([]byte, error } // Get the current annotations from the object. - annotations := accessor.Annotations() + annotations := accessor.GetAnnotations() if annotations == nil { annotations = map[string]string{} } diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index dce8e043d8..7ad957aef5 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -64,9 +64,27 @@ type ExternalType2 struct { Name string `json:"name"` } -func (*internalType) IsAnAPIObject() {} -func (*externalType) IsAnAPIObject() {} -func (*ExternalType2) IsAnAPIObject() {} +func (obj *internalType) GetObjectKind() unversioned.ObjectKind { return obj } +func (obj *internalType) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *internalType) GroupVersionKind() *unversioned.GroupVersionKind { + return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) +} +func (obj *externalType) GetObjectKind() unversioned.ObjectKind { return obj } +func (obj *externalType) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *externalType) GroupVersionKind() *unversioned.GroupVersionKind { + return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) +} +func (obj *ExternalType2) GetObjectKind() unversioned.ObjectKind { return obj } +func (obj *ExternalType2) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *ExternalType2) GroupVersionKind() *unversioned.GroupVersionKind { + return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) +} var versionErr = errors.New("not a version") diff --git a/pkg/kubectl/resource_printer_test.go b/pkg/kubectl/resource_printer_test.go index b2b57123d3..1f71995a26 100644 --- a/pkg/kubectl/resource_printer_test.go +++ b/pkg/kubectl/resource_printer_test.go @@ -85,11 +85,11 @@ type TestPrintType struct { Data string } -func (*TestPrintType) IsAnAPIObject() {} +func (obj *TestPrintType) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } type TestUnknownType struct{} -func (*TestUnknownType) IsAnAPIObject() {} +func (obj *TestUnknownType) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } func TestPrinter(t *testing.T) { //test inputs diff --git a/pkg/kubectl/stop.go b/pkg/kubectl/stop.go index 4a85d8b668..992d648762 100644 --- a/pkg/kubectl/stop.go +++ b/pkg/kubectl/stop.go @@ -103,7 +103,7 @@ type ServiceReaper struct { type objInterface interface { Delete(name string) error - Get(name string) (meta.Interface, error) + Get(name string) (meta.Object, error) } // getOverlappingControllers finds rcs that this controller overlaps, as well as rcs overlapping this controller. diff --git a/pkg/kubectl/testing/types.go b/pkg/kubectl/testing/types.go index 8eefd437c2..2fbc2ed45f 100644 --- a/pkg/kubectl/testing/types.go +++ b/pkg/kubectl/testing/types.go @@ -30,4 +30,4 @@ type TestStruct struct { IntList []int `json:"IntList"` } -func (ts *TestStruct) IsAnAPIObject() {} +func (obj *TestStruct) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/registry/generic/etcd/etcd.go b/pkg/registry/generic/etcd/etcd.go index 597c9f7ec4..3107afa01a 100644 --- a/pkg/registry/generic/etcd/etcd.go +++ b/pkg/registry/generic/etcd/etcd.go @@ -443,7 +443,7 @@ func (e *Etcd) DeleteCollection(ctx api.Context, options *api.DeleteOptions, lis if err != nil { return nil, err } - if _, err := e.Delete(ctx, accessor.Name(), options); err != nil { + if _, err := e.Delete(ctx, accessor.GetName(), options); err != nil { return nil, err } } diff --git a/pkg/registry/generic/matcher_test.go b/pkg/registry/generic/matcher_test.go index 5cd99cf0a1..17c7fb3636 100644 --- a/pkg/registry/generic/matcher_test.go +++ b/pkg/registry/generic/matcher_test.go @@ -20,6 +20,7 @@ import ( "errors" "testing" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" @@ -33,8 +34,8 @@ type IgnoredList struct { Items []Ignored } -func (*Ignored) IsAnAPIObject() {} -func (*IgnoredList) IsAnAPIObject() {} +func (obj *Ignored) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } +func (obj *IgnoredList) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } func TestSelectionPredicate(t *testing.T) { table := map[string]struct { diff --git a/pkg/registry/generic/rest/streamer.go b/pkg/registry/generic/rest/streamer.go index 6c5dedaba0..afa9eb5b5d 100644 --- a/pkg/registry/generic/rest/streamer.go +++ b/pkg/registry/generic/rest/streamer.go @@ -23,6 +23,7 @@ import ( "strings" "k8s.io/kubernetes/pkg/api/rest" + "k8s.io/kubernetes/pkg/api/unversioned" ) // LocationStreamer is a resource that streams the contents of a particular @@ -38,8 +39,9 @@ type LocationStreamer struct { // a LocationStreamer must implement a rest.ResourceStreamer var _ rest.ResourceStreamer = &LocationStreamer{} -// IsAnAPIObject marks this object as a runtime.Object -func (*LocationStreamer) IsAnAPIObject() {} +func (obj *LocationStreamer) GetObjectKind() unversioned.ObjectKind { + return unversioned.EmptyObjectKind +} // InputStream returns a stream with the contents of the URL location. If no location is provided, // a null stream is returned. diff --git a/pkg/runtime/conversion_test.go b/pkg/runtime/conversion_test.go index e200526ee0..cf31550839 100644 --- a/pkg/runtime/conversion_test.go +++ b/pkg/runtime/conversion_test.go @@ -25,7 +25,7 @@ import ( ) type InternalComplex struct { - TypeMeta + runtime.TypeMeta String string Integer int Integer64 int64 @@ -34,16 +34,16 @@ type InternalComplex struct { } type ExternalComplex struct { - TypeMeta `json:",inline"` - String string `json:"string" description:"testing"` - Integer int `json:"int"` - Integer64 int64 `json:",omitempty"` - Int64 int64 - Bool bool `json:"bool"` + runtime.TypeMeta `json:",inline"` + String string `json:"string" description:"testing"` + Integer int `json:"int"` + Integer64 int64 `json:",omitempty"` + Int64 int64 + Bool bool `json:"bool"` } -func (*InternalComplex) IsAnAPIObject() {} -func (*ExternalComplex) IsAnAPIObject() {} +func (obj *InternalComplex) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ExternalComplex) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } func TestStringMapConversion(t *testing.T) { internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""} diff --git a/pkg/runtime/embedded_test.go b/pkg/runtime/embedded_test.go index 8cec3149a0..c0b9c867f9 100644 --- a/pkg/runtime/embedded_test.go +++ b/pkg/runtime/embedded_test.go @@ -56,10 +56,10 @@ type ObjectTestExternal struct { Items []runtime.RawExtension `json:"items,omitempty"` } -func (*ObjectTest) IsAnAPIObject() {} -func (*ObjectTestExternal) IsAnAPIObject() {} -func (*EmbeddedTest) IsAnAPIObject() {} -func (*EmbeddedTestExternal) IsAnAPIObject() {} +func (obj *ObjectTest) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ObjectTestExternal) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *EmbeddedTest) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *EmbeddedTestExternal) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } func TestDecodeEmptyRawExtensionAsObject(t *testing.T) { internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""} diff --git a/pkg/runtime/interfaces.go b/pkg/runtime/interfaces.go index 8dab5926c4..7e6eb64768 100644 --- a/pkg/runtime/interfaces.go +++ b/pkg/runtime/interfaces.go @@ -140,11 +140,10 @@ type SelfLinker interface { Namespace(obj Object) (string, error) } -// All api types must support the Object interface. It's deliberately tiny so that this is not an onerous -// burden. Implement it with a pointer receiver; this will allow us to use the go compiler to check the -// one thing about our objects that it's capable of checking for us. +// All API types registered with Scheme must support the Object interface. Since objects in a scheme are +// expected to be serialized to the wire, the interface an Object must provide to the Scheme allows +// serializers to set the kind, version, and group the object is represented as. An Object may choose +// to return a no-op ObjectKindAccessor in cases where it is not expected to be serialized. type Object interface { - // This function is used only to enforce membership. It's never called. - // TODO: Consider mass rename in the future to make it do something useful. - IsAnAPIObject() + GetObjectKind() unversioned.ObjectKind } diff --git a/pkg/runtime/register.go b/pkg/runtime/register.go new file mode 100644 index 0000000000..53186957ac --- /dev/null +++ b/pkg/runtime/register.go @@ -0,0 +1,44 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package runtime + +import ( + "k8s.io/kubernetes/pkg/api/unversioned" +) + +// SetGroupVersionKind satisfies the ObjectKind interface for all objects that embed PluginBase +func (obj *PluginBase) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + _, obj.Kind = gvk.ToAPIVersionAndKind() +} + +// GroupVersionKind satisfies the ObjectKind interface for all objects that embed PluginBase +func (obj *PluginBase) GroupVersionKind() *unversioned.GroupVersionKind { + return unversioned.FromAPIVersionAndKind("", obj.Kind) +} + +// SetGroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta +func (obj *TypeMeta) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() +} + +// GroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta +func (obj *TypeMeta) GroupVersionKind() *unversioned.GroupVersionKind { + return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) +} + +func (obj *Unknown) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *Unstructured) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/runtime/scheme_test.go b/pkg/runtime/scheme_test.go index 44ebdd75e9..dfe91424b1 100644 --- a/pkg/runtime/scheme_test.go +++ b/pkg/runtime/scheme_test.go @@ -30,6 +30,16 @@ type TypeMeta struct { APIVersion string `json:"apiVersion,omitempty"` } +// SetGroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta +func (obj *TypeMeta) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() +} + +// GroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta +func (obj *TypeMeta) GroupVersionKind() *unversioned.GroupVersionKind { + return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) +} + type InternalSimple struct { TypeMeta `json:",inline"` TestString string `json:"testString"` @@ -40,8 +50,14 @@ type ExternalSimple struct { TestString string `json:"testString"` } -func (*InternalSimple) IsAnAPIObject() {} -func (*ExternalSimple) IsAnAPIObject() {} +func (obj *InternalSimple) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *InternalSimple) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.TypeMeta.APIVersion, obj.TypeMeta.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *ExternalSimple) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ExternalSimple) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.TypeMeta.APIVersion, obj.TypeMeta.Kind = gvk.ToAPIVersionAndKind() +} func TestScheme(t *testing.T) { internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""} @@ -197,12 +213,30 @@ type InternalOptionalExtensionType struct { Extension runtime.EmbeddedObject `json:"extension,omitempty"` } -func (*ExtensionA) IsAnAPIObject() {} -func (*ExtensionB) IsAnAPIObject() {} -func (*ExternalExtensionType) IsAnAPIObject() {} -func (*InternalExtensionType) IsAnAPIObject() {} -func (*ExternalOptionalExtensionType) IsAnAPIObject() {} -func (*InternalOptionalExtensionType) IsAnAPIObject() {} +func (obj *ExtensionA) GetObjectKind() unversioned.ObjectKind { return &obj.PluginBase } +func (obj *ExtensionA) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + _, obj.PluginBase.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *ExtensionB) GetObjectKind() unversioned.ObjectKind { return &obj.PluginBase } +func (obj *ExtensionB) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + _, obj.PluginBase.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *ExternalExtensionType) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ExternalExtensionType) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.TypeMeta.APIVersion, obj.TypeMeta.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *InternalExtensionType) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *InternalExtensionType) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.TypeMeta.APIVersion, obj.TypeMeta.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *ExternalOptionalExtensionType) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *ExternalOptionalExtensionType) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.TypeMeta.APIVersion, obj.TypeMeta.Kind = gvk.ToAPIVersionAndKind() +} +func (obj *InternalOptionalExtensionType) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } +func (obj *InternalOptionalExtensionType) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { + obj.TypeMeta.APIVersion, obj.TypeMeta.Kind = gvk.ToAPIVersionAndKind() +} func TestExternalToInternalMapping(t *testing.T) { internalGV := unversioned.GroupVersion{Group: "test.group", Version: ""} diff --git a/pkg/runtime/types.go b/pkg/runtime/types.go index fcc26526e6..a09af5e14f 100644 --- a/pkg/runtime/types.go +++ b/pkg/runtime/types.go @@ -25,7 +25,7 @@ package runtime // runtime.TypeMeta `json:",inline"` // ... // other fields // } -// func (*MyAwesomeAPIObject) IsAnAPIObject() {} +// func (obj *MyAwesomeAPIObject) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { unversioned.UpdateTypeMeta(obj,gvk) }; GroupVersionKind() *GroupVersionKind // // TypeMeta is provided here for convenience. You may use it directly from this package or define // your own with the same fields. @@ -120,8 +120,6 @@ type Unknown struct { RawJSON []byte } -func (*Unknown) IsAnAPIObject() {} - // Unstructured allows objects that do not have Golang structs registered to be manipulated // generically. This can be used to deal with the API objects from a plug-in. Unstructured // objects still have functioning TypeMeta features-- kind, version, etc. @@ -133,5 +131,3 @@ type Unstructured struct { // children. Object map[string]interface{} } - -func (*Unstructured) IsAnAPIObject() {} diff --git a/pkg/storage/cacher_test.go b/pkg/storage/cacher_test.go index 1c74995929..2becc02478 100644 --- a/pkg/storage/cacher_test.go +++ b/pkg/storage/cacher_test.go @@ -280,7 +280,7 @@ func TestFiltering(t *testing.T) { t.Errorf("Unexpected error: %v", err) return false } - return selector.Matches(labels.Set(metadata.Labels())) + return selector.Matches(labels.Set(metadata.GetLabels())) } // We want to observe fooCreation too, so need to pass smaller resource version. initialVersion, err := strconv.Atoi(fooCreated.ResourceVersion) diff --git a/pkg/storage/testing/types.go b/pkg/storage/testing/types.go index 4fa38404cb..a1377aa04e 100644 --- a/pkg/storage/testing/types.go +++ b/pkg/storage/testing/types.go @@ -27,4 +27,4 @@ type TestResource struct { Value int `json:"value"` } -func (*TestResource) IsAnAPIObject() {} +func (obj *TestResource) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/pkg/storage/testing/utils.go b/pkg/storage/testing/utils.go index 74ca0aa474..e79ea9adfc 100644 --- a/pkg/storage/testing/utils.go +++ b/pkg/storage/testing/utils.go @@ -38,7 +38,7 @@ func CreateObjList(prefix string, helper storage.Interface, items []runtime.Obje if err != nil { return err } - err = CreateObj(helper, path.Join(prefix, meta.Name()), obj, obj, 0) + err = CreateObj(helper, path.Join(prefix, meta.GetName()), obj, obj, 0) if err != nil { return err } diff --git a/pkg/storage/util.go b/pkg/storage/util.go index deb89d6001..0a741b805a 100644 --- a/pkg/storage/util.go +++ b/pkg/storage/util.go @@ -71,11 +71,11 @@ func NamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) { if err != nil { return "", err } - name := meta.Name() + name := meta.GetName() if ok, msg := validation.IsValidPathSegmentName(name); !ok { return "", fmt.Errorf("invalid name: %v", msg) } - return prefix + "/" + meta.Namespace() + "/" + meta.Name(), nil + return prefix + "/" + meta.GetNamespace() + "/" + name, nil } func NoNamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) { @@ -83,9 +83,9 @@ func NoNamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) { if err != nil { return "", err } - name := meta.Name() + name := meta.GetName() if ok, msg := validation.IsValidPathSegmentName(name); !ok { return "", fmt.Errorf("invalid name: %v", msg) } - return prefix + "/" + meta.Name(), nil + return prefix + "/" + name, nil } diff --git a/pkg/storage/watch_cache.go b/pkg/storage/watch_cache.go index 06bd4084da..196e35e0cb 100644 --- a/pkg/storage/watch_cache.go +++ b/pkg/storage/watch_cache.go @@ -142,7 +142,7 @@ func objectToVersionedRuntimeObject(obj interface{}) (runtime.Object, uint64, er if err != nil { return nil, 0, err } - resourceVersion, err := parseResourceVersion(meta.ResourceVersion()) + resourceVersion, err := parseResourceVersion(meta.GetResourceVersion()) if err != nil { return nil, 0, err } diff --git a/pkg/watch/mux.go b/pkg/watch/mux.go index c123968d81..700c26bcad 100644 --- a/pkg/watch/mux.go +++ b/pkg/watch/mux.go @@ -19,6 +19,7 @@ package watch import ( "sync" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/runtime" ) @@ -80,7 +81,9 @@ const internalRunFunctionMarker = "internal-do-function" // a function type we can shoehorn into the queue. type functionFakeRuntimeObject func() -func (functionFakeRuntimeObject) IsAnAPIObject() {} +func (obj functionFakeRuntimeObject) GetObjectKind() unversioned.ObjectKind { + return unversioned.EmptyObjectKind +} // Execute f, blocking the incoming queue (and waiting for it to drain first). // The purpose of this terrible hack is so that watchers added after an event diff --git a/pkg/watch/mux_test.go b/pkg/watch/mux_test.go index 515833f360..066b898bc4 100644 --- a/pkg/watch/mux_test.go +++ b/pkg/watch/mux_test.go @@ -22,6 +22,7 @@ import ( "testing" "time" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/util" ) @@ -30,7 +31,7 @@ type myType struct { Value string } -func (*myType) IsAnAPIObject() {} +func (obj *myType) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } func TestBroadcaster(t *testing.T) { table := []Event{ diff --git a/pkg/watch/watch_test.go b/pkg/watch/watch_test.go index 7088e4f80e..33b6e5cc09 100644 --- a/pkg/watch/watch_test.go +++ b/pkg/watch/watch_test.go @@ -18,11 +18,13 @@ package watch import ( "testing" + + "k8s.io/kubernetes/pkg/api/unversioned" ) type testType string -func (testType) IsAnAPIObject() {} +func (obj testType) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } func TestFake(t *testing.T) { f := NewFake() diff --git a/plugin/pkg/scheduler/api/register.go b/plugin/pkg/scheduler/api/register.go index ad70a531da..53a19cedaf 100644 --- a/plugin/pkg/scheduler/api/register.go +++ b/plugin/pkg/scheduler/api/register.go @@ -34,4 +34,4 @@ func init() { ) } -func (*Policy) IsAnAPIObject() {} +func (obj *Policy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/plugin/pkg/scheduler/api/v1/register.go b/plugin/pkg/scheduler/api/v1/register.go index 5f5cb49064..49545b8510 100644 --- a/plugin/pkg/scheduler/api/v1/register.go +++ b/plugin/pkg/scheduler/api/v1/register.go @@ -35,4 +35,4 @@ func init() { ) } -func (*Policy) IsAnAPIObject() {} +func (obj *Policy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }