diff --git a/cmd/kubecfg/kubecfg.go b/cmd/kubecfg/kubecfg.go index 9708946dec..c6c74546da 100644 --- a/cmd/kubecfg/kubecfg.go +++ b/cmd/kubecfg/kubecfg.go @@ -31,6 +31,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubecfg" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" @@ -372,7 +373,7 @@ func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool { if err != nil { glog.Fatalf("error obtaining resource version for update: %v", err) } - jsonBase, err := runtime.FindTypeMeta(obj) + jsonBase, err := meta.FindTypeMeta(obj) if err != nil { glog.Fatalf("error finding json base for update: %v", err) } @@ -408,7 +409,7 @@ func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool { if err != nil { glog.Fatalf("error setting resource version: %v", err) } - jsonBase, err := runtime.FindTypeMeta(obj) + jsonBase, err := meta.FindTypeMeta(obj) if err != nil { glog.Fatalf("error setting resource version: %v", err) } diff --git a/pkg/api/latest/latest.go b/pkg/api/latest/latest.go index 5dec503baf..531a006766 100644 --- a/pkg/api/latest/latest.go +++ b/pkg/api/latest/latest.go @@ -20,6 +20,7 @@ import ( "fmt" "strings" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" @@ -47,13 +48,13 @@ var Codec = v1beta1.Codec // ResourceVersioner describes a default versioner that can handle all types // of versioning. // TODO: when versioning changes, make this part of each API definition. -var ResourceVersioner = runtime.NewTypeMetaResourceVersioner() +var ResourceVersioner = meta.NewTypeMetaResourceVersioner() // SelfLinker can set or get the SelfLink field of all API types. // TODO: when versioning changes, make this part of each API definition. // TODO(lavalamp): Combine SelfLinker & ResourceVersioner interfaces, force all uses // to go through the InterfacesFor method below. -var SelfLinker = runtime.NewTypeMetaSelfLinker() +var SelfLinker = meta.NewTypeMetaSelfLinker() // VersionInterfaces contains the interfaces one should use for dealing with types of a particular version. type VersionInterfaces struct { diff --git a/pkg/api/meta/doc.go b/pkg/api/meta/doc.go new file mode 100644 index 0000000000..a388f1d7ec --- /dev/null +++ b/pkg/api/meta/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2014 Google Inc. 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 meta provides functions for retrieving API metadata from objects +// belonging to the Kubernetes API +package meta diff --git a/pkg/runtime/typemeta.go b/pkg/api/meta/meta.go similarity index 87% rename from pkg/runtime/typemeta.go rename to pkg/api/meta/meta.go index 6dc616bd6f..6ce01543d1 100644 --- a/pkg/runtime/typemeta.go +++ b/pkg/api/meta/meta.go @@ -14,18 +14,19 @@ See the License for the specific language governing permissions and limitations under the License. */ -package runtime +package meta import ( "fmt" "reflect" "github.com/GoogleCloudPlatform/kubernetes/pkg/conversion" + "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" ) // FindTypeMeta takes an arbitary api type, returns pointer to its TypeMeta field. // obj must be a pointer to an api type. -func FindTypeMeta(obj Object) (TypeMetaInterface, error) { +func FindTypeMeta(obj runtime.Object) (TypeMetaInterface, error) { v, err := conversion.EnforcePtr(obj) if err != nil { return nil, err @@ -48,14 +49,14 @@ func FindTypeMeta(obj Object) (TypeMetaInterface, error) { // NewTypeMetaResourceVersioner returns a ResourceVersioner that can set or // retrieve ResourceVersion on objects derived from TypeMeta. -func NewTypeMetaResourceVersioner() ResourceVersioner { +func NewTypeMetaResourceVersioner() runtime.ResourceVersioner { return jsonBaseModifier{} } // jsonBaseModifier implements ResourceVersioner and SelfLinker. type jsonBaseModifier struct{} -func (v jsonBaseModifier) ResourceVersion(obj Object) (string, error) { +func (v jsonBaseModifier) ResourceVersion(obj runtime.Object) (string, error) { json, err := FindTypeMeta(obj) if err != nil { return "", err @@ -63,7 +64,7 @@ func (v jsonBaseModifier) ResourceVersion(obj Object) (string, error) { return json.ResourceVersion(), nil } -func (v jsonBaseModifier) SetResourceVersion(obj Object, version string) error { +func (v jsonBaseModifier) SetResourceVersion(obj runtime.Object, version string) error { json, err := FindTypeMeta(obj) if err != nil { return err @@ -72,7 +73,7 @@ func (v jsonBaseModifier) SetResourceVersion(obj Object, version string) error { return nil } -func (v jsonBaseModifier) ID(obj Object) (string, error) { +func (v jsonBaseModifier) ID(obj runtime.Object) (string, error) { json, err := FindTypeMeta(obj) if err != nil { return "", err @@ -80,7 +81,7 @@ func (v jsonBaseModifier) ID(obj Object) (string, error) { return json.ID(), nil } -func (v jsonBaseModifier) SelfLink(obj Object) (string, error) { +func (v jsonBaseModifier) SelfLink(obj runtime.Object) (string, error) { json, err := FindTypeMeta(obj) if err != nil { return "", err @@ -88,7 +89,7 @@ func (v jsonBaseModifier) SelfLink(obj Object) (string, error) { return json.SelfLink(), nil } -func (v jsonBaseModifier) SetSelfLink(obj Object, selfLink string) error { +func (v jsonBaseModifier) SetSelfLink(obj runtime.Object, selfLink string) error { json, err := FindTypeMeta(obj) if err != nil { return err @@ -98,12 +99,12 @@ func (v jsonBaseModifier) SetSelfLink(obj Object, selfLink string) error { } // NewTypeMetaSelfLinker returns a SelfLinker that works on all TypeMeta SelfLink fields. -func NewTypeMetaSelfLinker() SelfLinker { +func NewTypeMetaSelfLinker() runtime.SelfLinker { return jsonBaseModifier{} } // TypeMetaInterface lets you work with a TypeMeta from any of the versioned or -// internal APIObjects. +// internal APIruntime.Objects. type TypeMetaInterface interface { ID() string SetID(ID string) diff --git a/pkg/runtime/typemeta_test.go b/pkg/api/meta/meta_test.go similarity index 92% rename from pkg/runtime/typemeta_test.go rename to pkg/api/meta/meta_test.go index bd4375048d..156d19e3c4 100644 --- a/pkg/runtime/typemeta_test.go +++ b/pkg/api/meta/meta_test.go @@ -14,12 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -package runtime +package meta import ( "reflect" "testing" + "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" ) @@ -86,7 +87,7 @@ func TestGenericTypeMeta(t *testing.T) { } type MyAPIObject struct { - TypeMeta `yaml:",inline" json:",inline"` + runtime.TypeMeta `yaml:",inline" json:",inline"` } func (*MyAPIObject) IsAnAPIObject() {} @@ -98,13 +99,13 @@ func (*MyIncorrectlyMarkedAsAPIObject) IsAnAPIObject() {} func TestResourceVersionerOfAPI(t *testing.T) { type T struct { - Object + runtime.Object Expected string } testCases := map[string]T{ "empty api object": {&MyAPIObject{}, ""}, - "api object with version": {&MyAPIObject{TypeMeta: TypeMeta{ResourceVersion: "1"}}, "1"}, - "pointer to api object with version": {&MyAPIObject{TypeMeta: TypeMeta{ResourceVersion: "1"}}, "1"}, + "api object with version": {&MyAPIObject{TypeMeta: runtime.TypeMeta{ResourceVersion: "1"}}, "1"}, + "pointer to api object with version": {&MyAPIObject{TypeMeta: runtime.TypeMeta{ResourceVersion: "1"}}, "1"}, } versioning := NewTypeMetaResourceVersioner() for key, testCase := range testCases { @@ -118,7 +119,7 @@ func TestResourceVersionerOfAPI(t *testing.T) { } failingCases := map[string]struct { - Object + runtime.Object Expected string }{ "not a valid object to try": {&MyIncorrectlyMarkedAsAPIObject{}, "1"}, @@ -131,10 +132,10 @@ func TestResourceVersionerOfAPI(t *testing.T) { } setCases := map[string]struct { - Object + runtime.Object Expected string }{ - "pointer to api object with version": {&MyAPIObject{TypeMeta: TypeMeta{ResourceVersion: "1"}}, "1"}, + "pointer to api object with version": {&MyAPIObject{TypeMeta: runtime.TypeMeta{ResourceVersion: "1"}}, "1"}, } for key, testCase := range setCases { if err := versioning.SetResourceVersion(testCase.Object, "5"); err != nil { @@ -152,13 +153,13 @@ func TestResourceVersionerOfAPI(t *testing.T) { func TestTypeMetaSelfLinker(t *testing.T) { table := map[string]struct { - obj Object + obj runtime.Object expect string try string succeed bool }{ "normal": { - obj: &MyAPIObject{TypeMeta: TypeMeta{SelfLink: "foobar"}}, + obj: &MyAPIObject{TypeMeta: runtime.TypeMeta{SelfLink: "foobar"}}, expect: "foobar", try: "newbar", succeed: true, diff --git a/pkg/api/ref.go b/pkg/api/ref.go index fc6fd51fc5..b8ad6153f6 100644 --- a/pkg/api/ref.go +++ b/pkg/api/ref.go @@ -21,6 +21,7 @@ import ( "fmt" "regexp" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" ) @@ -35,7 +36,7 @@ func GetReference(obj runtime.Object) (*ObjectReference, error) { if obj == nil { return nil, ErrNilObject } - jsonBase, err := runtime.FindTypeMeta(obj) + jsonBase, err := meta.FindTypeMeta(obj) if err != nil { return nil, err } diff --git a/pkg/api/serialization_test.go b/pkg/api/serialization_test.go index e5c9c2371e..fa3f9e5158 100644 --- a/pkg/api/serialization_test.go +++ b/pkg/api/serialization_test.go @@ -26,6 +26,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta2" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" @@ -46,17 +47,6 @@ var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs( // APIVersion and Kind must remain blank in memory. j.APIVersion = "" j.Kind = "" - j.Name = c.RandString() - // TODO: Fix JSON/YAML packages and/or write custom encoding - // for uint64's. Somehow the LS *byte* of this is lost, but - // only when all 8 bytes are set. - j.ResourceVersion = strconv.FormatUint(c.RandUint64()>>8, 10) - j.SelfLink = c.RandString() - - var sec, nsec int64 - c.Fuzz(&sec) - c.Fuzz(&nsec) - j.CreationTimestamp = util.Unix(sec, nsec).Rfc3339Copy() }, func(j *api.TypeMeta, c fuzz.Continue) { // We have to customize the randomization of TypeMetas because their @@ -111,7 +101,7 @@ var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs( func runTest(t *testing.T, codec runtime.Codec, source runtime.Object) { name := reflect.TypeOf(source).Elem().Name() apiObjectFuzzer.Fuzz(source) - j, err := runtime.FindTypeMeta(source) + j, err := meta.FindTypeMeta(source) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, source) } @@ -170,7 +160,7 @@ func TestTypes(t *testing.T) { t.Errorf("Couldn't make a %v? %v", kind, err) continue } - if _, err := runtime.FindTypeMeta(item); err != nil { + if _, err := meta.FindTypeMeta(item); err != nil { t.Logf("%s is not a TypeMeta and cannot be round tripped: %v", kind, err) continue } diff --git a/pkg/client/cache/reflector.go b/pkg/client/cache/reflector.go index 2029865726..243d56db86 100644 --- a/pkg/client/cache/reflector.go +++ b/pkg/client/cache/reflector.go @@ -23,6 +23,7 @@ import ( "time" apierrs "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" @@ -78,7 +79,7 @@ func (r *Reflector) listAndWatch() { glog.Errorf("Failed to list %v: %v", r.expectedType, err) return } - jsonBase, err := runtime.FindTypeMeta(list) + jsonBase, err := meta.FindTypeMeta(list) if err != nil { glog.Errorf("Unable to understand list result %#v", list) return @@ -112,7 +113,7 @@ func (r *Reflector) listAndWatch() { func (r *Reflector) syncWith(items []runtime.Object) error { found := map[string]interface{}{} for _, item := range items { - jsonBase, err := runtime.FindTypeMeta(item) + jsonBase, err := meta.FindTypeMeta(item) if err != nil { return fmt.Errorf("unexpected item in list: %v", err) } @@ -139,7 +140,7 @@ func (r *Reflector) watchHandler(w watch.Interface, resourceVersion *string) err glog.Errorf("expected type %v, but watch event object had type %v", e, a) continue } - jsonBase, err := runtime.FindTypeMeta(event.Object) + jsonBase, err := meta.FindTypeMeta(event.Object) if err != nil { glog.Errorf("unable to understand watch event %#v", event) continue diff --git a/pkg/kubectl/modify.go b/pkg/kubectl/modify.go index 3c06734d9f..c0dfe27744 100644 --- a/pkg/kubectl/modify.go +++ b/pkg/kubectl/modify.go @@ -20,6 +20,7 @@ import ( "fmt" "io" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" ) @@ -109,7 +110,7 @@ func doUpdate(c *client.RESTClient, resource string, obj runtime.Object) (string // Update the object we are trying to send to the server with the // correct resource version. - typeMeta, err := runtime.FindTypeMeta(obj) + typeMeta, err := meta.FindTypeMeta(obj) if err != nil { return "", err } @@ -149,7 +150,7 @@ func doDelete(c *client.RESTClient, resource string, obj runtime.Object) (string } func getIDFromObj(obj runtime.Object) (string, error) { - typeMeta, err := runtime.FindTypeMeta(obj) + typeMeta, err := meta.FindTypeMeta(obj) if err != nil { return "", err } @@ -157,7 +158,7 @@ func getIDFromObj(obj runtime.Object) (string, error) { } func getResourceVersionFromObj(obj runtime.Object) (string, error) { - typeMeta, err := runtime.FindTypeMeta(obj) + typeMeta, err := meta.FindTypeMeta(obj) if err != nil { return "", err } diff --git a/pkg/runtime/embedded_test.go b/pkg/runtime/embedded_test.go index 6fca4c41db..c7b7c721d9 100644 --- a/pkg/runtime/embedded_test.go +++ b/pkg/runtime/embedded_test.go @@ -29,12 +29,14 @@ var Codec = runtime.CodecFor(scheme, "v1test") type EmbeddedTest struct { runtime.TypeMeta `yaml:",inline" json:",inline"` + ID string `yaml:"id,omitempty" json:"id,omitempty"` Object runtime.EmbeddedObject `yaml:"object,omitempty" json:"object,omitempty"` EmptyObject runtime.EmbeddedObject `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"` } type EmbeddedTestExternal struct { runtime.TypeMeta `yaml:",inline" json:",inline"` + ID string `yaml:"id,omitempty" json:"id,omitempty"` Object runtime.RawExtension `yaml:"object,omitempty" json:"object,omitempty"` EmptyObject runtime.RawExtension `yaml:"emptyObject,omitempty" json:"emptyObject,omitempty"` } @@ -49,9 +51,11 @@ func TestEmbeddedObject(t *testing.T) { outer := &EmbeddedTest{ TypeMeta: runtime.TypeMeta{Name: "outer"}, + ID: "outer", Object: runtime.EmbeddedObject{ &EmbeddedTest{ TypeMeta: runtime.TypeMeta{Name: "inner"}, + ID: "inner", }, }, } diff --git a/pkg/runtime/types.go b/pkg/runtime/types.go index f657861f7a..7475444166 100644 --- a/pkg/runtime/types.go +++ b/pkg/runtime/types.go @@ -26,8 +26,8 @@ import ( // TypeMeta is shared by all top level objects. The proper way to use it is to inline it in your type, // like this: // type MyAwesomeAPIObject struct { -// runtime.TypeMeta `yaml:",inline" json:",inline"` -// ... // other fields +// runtime.TypeMeta `yaml:",inline" json:",inline"` +// ... // other fields // } // func (*MyAwesomeAPIObject) IsAnAPIObject() {} // @@ -35,12 +35,13 @@ import ( // your own with the same fields. // type TypeMeta struct { - Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` + APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"` + Kind string `json:"kind,omitempty" yaml:"kind,omitempty"` + Name string `json:"name,omitempty" yaml:"name,omitempty"` CreationTimestamp util.Time `json:"creationTimestamp,omitempty" yaml:"creationTimestamp,omitempty"` SelfLink string `json:"selfLink,omitempty" yaml:"selfLink,omitempty"` ResourceVersion string `json:"resourceVersion,omitempty" yaml:"resourceVersion,omitempty"` - APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"` } // PluginBase is like TypeMeta, but it's intended for plugin objects that won't ever be encoded diff --git a/pkg/tools/etcd_tools_test.go b/pkg/tools/etcd_tools_test.go index f899befb7c..a784d425bb 100644 --- a/pkg/tools/etcd_tools_test.go +++ b/pkg/tools/etcd_tools_test.go @@ -25,6 +25,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/coreos/go-etcd/etcd" @@ -44,7 +45,7 @@ func (*TestResource) IsAnAPIObject() {} var scheme *runtime.Scheme var codec runtime.Codec -var versioner = RuntimeVersionAdapter{runtime.NewTypeMetaResourceVersioner()} +var versioner = RuntimeVersionAdapter{meta.NewTypeMetaResourceVersioner()} func init() { scheme = runtime.NewScheme()