Use meta.Interface and meta.Accessor

This commit is contained in:
Clayton Coleman
2014-10-23 18:01:25 -04:00
parent e5c924585c
commit 3df1c2f29d
7 changed files with 68 additions and 68 deletions

View File

@@ -373,11 +373,11 @@ func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool {
if err != nil { if err != nil {
glog.Fatalf("error obtaining resource version for update: %v", err) glog.Fatalf("error obtaining resource version for update: %v", err)
} }
jsonBase, err := meta.FindAccessor(obj) meta, err := meta.Accessor(obj)
if err != nil { if err != nil {
glog.Fatalf("error finding json base for update: %v", err) glog.Fatalf("error finding json base for update: %v", err)
} }
version = jsonBase.ResourceVersion() version = meta.ResourceVersion()
verb = "PUT" verb = "PUT"
setBody = true setBody = true
if !validStorage || !hasSuffix { if !validStorage || !hasSuffix {
@@ -409,7 +409,7 @@ func executeAPIRequest(ctx api.Context, method string, c *client.Client) bool {
if err != nil { if err != nil {
glog.Fatalf("error setting resource version: %v", err) glog.Fatalf("error setting resource version: %v", err)
} }
jsonBase, err := meta.FindAccessor(obj) jsonBase, err := meta.Accessor(obj)
if err != nil { if err != nil {
glog.Fatalf("error setting resource version: %v", err) glog.Fatalf("error setting resource version: %v", err)
} }

View File

@@ -24,46 +24,63 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
) )
// FindAccessor takes an arbitary type and returns an Accessor interfaces. // Interface lets you work with object metadata from any of the versioned or
// obj must be a pointer to an api type. An error is returned if the minimum // internal API objects.
// required fields are missing. type Interface interface {
func FindAccessor(obj interface{}) (Accessor, error) { Name() string
SetName(name string)
UID() string
SetUID(uid string)
APIVersion() string
SetAPIVersion(version string)
Kind() string
SetKind(kind string)
ResourceVersion() string
SetResourceVersion(version string)
SelfLink() string
SetSelfLink(selfLink string)
}
// Accessor takes an arbitary object pointer and returns meta.Interface.
// 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.
func Accessor(obj interface{}) (Interface, error) {
v, err := conversion.EnforcePtr(obj) v, err := conversion.EnforcePtr(obj)
if err != nil { if err != nil {
return nil, err return nil, err
} }
t := v.Type() t := v.Type()
name := t.Name()
if v.Kind() != reflect.Struct { if v.Kind() != reflect.Struct {
return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), name, v.Interface()) return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface())
} }
typeMeta := v.FieldByName("TypeMeta") typeMeta := v.FieldByName("TypeMeta")
if !typeMeta.IsValid() { if !typeMeta.IsValid() {
return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", name) return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t)
} }
a := &genericAccessor{} a := &genericAccessor{}
if err := findTypeMeta(typeMeta, a); err != nil { if err := extractFromTypeMeta(typeMeta, a); err != nil {
return nil, fmt.Errorf("unable to find type fields on %#v", typeMeta) return nil, fmt.Errorf("unable to find type fields on %#v", typeMeta)
} }
objectMeta := v.FieldByName("ObjectMeta") objectMeta := v.FieldByName("ObjectMeta")
if objectMeta.IsValid() { if objectMeta.IsValid() {
// look for the ObjectMeta fields // look for the ObjectMeta fields
if err := findObjectMeta(objectMeta, a); err != nil { if err := extractFromObjectMeta(objectMeta, a); err != nil {
return nil, fmt.Errorf("unable to find object fields on %#v", objectMeta) return nil, fmt.Errorf("unable to find object fields on %#v", objectMeta)
} }
} else { } else {
listMeta := v.FieldByName("ListMeta") listMeta := v.FieldByName("ListMeta")
if listMeta.IsValid() { if listMeta.IsValid() {
// look for the ListMeta fields // look for the ListMeta fields
if err := findListMeta(listMeta, a); err != nil { if err := extractFromListMeta(listMeta, a); err != nil {
return nil, fmt.Errorf("unable to find list fields on %#v", listMeta) return nil, fmt.Errorf("unable to find list fields on %#v", listMeta)
} }
} else { } else {
// look for the older TypeMeta with all metadata // look for the older TypeMeta with all metadata
if err := findObjectMeta(typeMeta, a); err != nil { if err := extractFromObjectMeta(typeMeta, a); err != nil {
return nil, fmt.Errorf("unable to find object fields on %#v", typeMeta) return nil, fmt.Errorf("unable to find object fields on %#v", typeMeta)
} }
} }
@@ -82,7 +99,7 @@ func NewResourceVersioner() runtime.ResourceVersioner {
type resourceAccessor struct{} type resourceAccessor struct{}
func (v resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) { func (v resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) {
accessor, err := FindAccessor(obj) accessor, err := Accessor(obj)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -90,7 +107,7 @@ func (v resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) {
} }
func (v resourceAccessor) SetResourceVersion(obj runtime.Object, version string) error { func (v resourceAccessor) SetResourceVersion(obj runtime.Object, version string) error {
accessor, err := FindAccessor(obj) accessor, err := Accessor(obj)
if err != nil { if err != nil {
return err return err
} }
@@ -99,7 +116,7 @@ func (v resourceAccessor) SetResourceVersion(obj runtime.Object, version string)
} }
func (v resourceAccessor) Name(obj runtime.Object) (string, error) { func (v resourceAccessor) Name(obj runtime.Object) (string, error) {
accessor, err := FindAccessor(obj) accessor, err := Accessor(obj)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -107,7 +124,7 @@ func (v resourceAccessor) Name(obj runtime.Object) (string, error) {
} }
func (v resourceAccessor) SelfLink(obj runtime.Object) (string, error) { func (v resourceAccessor) SelfLink(obj runtime.Object) (string, error) {
accessor, err := FindAccessor(obj) accessor, err := Accessor(obj)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -115,7 +132,7 @@ func (v resourceAccessor) SelfLink(obj runtime.Object) (string, error) {
} }
func (v resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error { func (v resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error {
accessor, err := FindAccessor(obj) accessor, err := Accessor(obj)
if err != nil { if err != nil {
return err return err
} }
@@ -128,23 +145,6 @@ func NewSelfLinker() runtime.SelfLinker {
return resourceAccessor{} return resourceAccessor{}
} }
// Accessor lets you work with object metadata from any of the versioned or
// internal APIruntime.Objects.
type Accessor interface {
Name() string
SetName(name string)
UID() string
SetUID(uid string)
APIVersion() string
SetAPIVersion(version string)
Kind() string
SetKind(kind string)
ResourceVersion() string
SetResourceVersion(version string)
SelfLink() string
SetSelfLink(selfLink string)
}
// genericAccessor contains pointers to strings that can modify an arbitrary // genericAccessor contains pointers to strings that can modify an arbitrary
// struct and implements the Accessor interface. // struct and implements the Accessor interface.
type genericAccessor struct { type genericAccessor struct {
@@ -241,8 +241,8 @@ func fieldPtr(v reflect.Value, fieldName string, dest interface{}) error {
return fmt.Errorf("Couldn't assign/convert %v to %v", field.Type(), v.Type()) return fmt.Errorf("Couldn't assign/convert %v to %v", field.Type(), v.Type())
} }
// findTypeMeta extracts pointers to version and kind fields from an object // extractFromTypeMeta extracts pointers to version and kind fields from an object
func findTypeMeta(v reflect.Value, a *genericAccessor) error { func extractFromTypeMeta(v reflect.Value, a *genericAccessor) error {
if err := fieldPtr(v, "APIVersion", &a.apiVersion); err != nil { if err := fieldPtr(v, "APIVersion", &a.apiVersion); err != nil {
return err return err
} }
@@ -252,8 +252,8 @@ func findTypeMeta(v reflect.Value, a *genericAccessor) error {
return nil return nil
} }
// findObjectMeta extracts pointers to metadata fields from an object // extractFromObjectMeta extracts pointers to metadata fields from an object
func findObjectMeta(v reflect.Value, a *genericAccessor) error { func extractFromObjectMeta(v reflect.Value, a *genericAccessor) error {
if err := fieldPtr(v, "Name", &a.name); err != nil { if err := fieldPtr(v, "Name", &a.name); err != nil {
return err return err
} }
@@ -269,8 +269,8 @@ func findObjectMeta(v reflect.Value, a *genericAccessor) error {
return nil return nil
} }
// findObjectMeta extracts pointers to metadata fields from a list object // extractFromObjectMeta extracts pointers to metadata fields from a list object
func findListMeta(v reflect.Value, a *genericAccessor) error { func extractFromListMeta(v reflect.Value, a *genericAccessor) error {
if err := fieldPtr(v, "ResourceVersion", &a.resourceVersion); err != nil { if err := fieldPtr(v, "ResourceVersion", &a.resourceVersion); err != nil {
return err return err
} }

View File

@@ -46,7 +46,7 @@ func TestGenericTypeMeta(t *testing.T) {
SelfLink: "some/place/only/we/know", SelfLink: "some/place/only/we/know",
}, },
} }
accessor, err := FindAccessor(&j) accessor, err := Accessor(&j)
if err != nil { if err != nil {
t.Fatalf("new err: %v", err) t.Fatalf("new err: %v", err)
} }
@@ -125,7 +125,7 @@ func TestGenericObjectMeta(t *testing.T) {
SelfLink: "some/place/only/we/know", SelfLink: "some/place/only/we/know",
}, },
} }
accessor, err := FindAccessor(&j) accessor, err := Accessor(&j)
if err != nil { if err != nil {
t.Fatalf("new err: %v", err) t.Fatalf("new err: %v", err)
} }
@@ -199,7 +199,7 @@ func TestGenericListMeta(t *testing.T) {
SelfLink: "some/place/only/we/know", SelfLink: "some/place/only/we/know",
}, },
} }
accessor, err := FindAccessor(&j) accessor, err := Accessor(&j)
if err != nil { if err != nil {
t.Fatalf("new err: %v", err) t.Fatalf("new err: %v", err)
} }

View File

@@ -36,7 +36,7 @@ func GetReference(obj runtime.Object) (*ObjectReference, error) {
if obj == nil { if obj == nil {
return nil, ErrNilObject return nil, ErrNilObject
} }
accessor, err := meta.FindAccessor(obj) meta, err := meta.Accessor(obj)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -44,16 +44,16 @@ func GetReference(obj runtime.Object) (*ObjectReference, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
version := versionFromSelfLink.FindStringSubmatch(accessor.SelfLink()) version := versionFromSelfLink.FindStringSubmatch(meta.SelfLink())
if len(version) < 2 { if len(version) < 2 {
return nil, fmt.Errorf("unexpected self link format: %v", accessor.SelfLink()) return nil, fmt.Errorf("unexpected self link format: %v", meta.SelfLink())
} }
return &ObjectReference{ return &ObjectReference{
Kind: kind, Kind: kind,
APIVersion: version[1], APIVersion: version[1],
// TODO: correct Name and UID when TypeMeta makes a distinction // TODO: correct Name and UID when TypeMeta makes a distinction
Name: accessor.Name(), Name: meta.Name(),
UID: accessor.UID(), UID: meta.UID(),
ResourceVersion: accessor.ResourceVersion(), ResourceVersion: meta.ResourceVersion(),
}, nil }, nil
} }

View File

@@ -101,7 +101,7 @@ var apiObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 1).Funcs(
func runTest(t *testing.T, codec runtime.Codec, source runtime.Object) { func runTest(t *testing.T, codec runtime.Codec, source runtime.Object) {
name := reflect.TypeOf(source).Elem().Name() name := reflect.TypeOf(source).Elem().Name()
apiObjectFuzzer.Fuzz(source) apiObjectFuzzer.Fuzz(source)
j, err := meta.FindAccessor(source) j, err := meta.Accessor(source)
if err != nil { if err != nil {
t.Fatalf("Unexpected error %v for %#v", err, source) t.Fatalf("Unexpected error %v for %#v", err, source)
} }
@@ -160,7 +160,7 @@ func TestTypes(t *testing.T) {
t.Errorf("Couldn't make a %v? %v", kind, err) t.Errorf("Couldn't make a %v? %v", kind, err)
continue continue
} }
if _, err := meta.FindAccessor(item); err != nil { if _, err := meta.Accessor(item); err != nil {
t.Logf("%s is not a TypeMeta and cannot be round tripped: %v", kind, err) t.Logf("%s is not a TypeMeta and cannot be round tripped: %v", kind, err)
continue continue
} }

View File

@@ -79,12 +79,12 @@ func (r *Reflector) listAndWatch() {
glog.Errorf("Failed to list %v: %v", r.expectedType, err) glog.Errorf("Failed to list %v: %v", r.expectedType, err)
return return
} }
jsonBase, err := meta.FindAccessor(list) meta, err := meta.Accessor(list)
if err != nil { if err != nil {
glog.Errorf("Unable to understand list result %#v", list) glog.Errorf("Unable to understand list result %#v", list)
return return
} }
resourceVersion = jsonBase.ResourceVersion() resourceVersion = meta.ResourceVersion()
items, err := runtime.ExtractList(list) items, err := runtime.ExtractList(list)
if err != nil { if err != nil {
glog.Errorf("Unable to understand list result %#v (%v)", list, err) glog.Errorf("Unable to understand list result %#v (%v)", list, err)
@@ -113,11 +113,11 @@ func (r *Reflector) listAndWatch() {
func (r *Reflector) syncWith(items []runtime.Object) error { func (r *Reflector) syncWith(items []runtime.Object) error {
found := map[string]interface{}{} found := map[string]interface{}{}
for _, item := range items { for _, item := range items {
jsonBase, err := meta.FindAccessor(item) meta, err := meta.Accessor(item)
if err != nil { if err != nil {
return fmt.Errorf("unexpected item in list: %v", err) return fmt.Errorf("unexpected item in list: %v", err)
} }
found[jsonBase.Name()] = item found[meta.Name()] = item
} }
r.store.Replace(found) r.store.Replace(found)
@@ -140,25 +140,25 @@ func (r *Reflector) watchHandler(w watch.Interface, resourceVersion *string) err
glog.Errorf("expected type %v, but watch event object had type %v", e, a) glog.Errorf("expected type %v, but watch event object had type %v", e, a)
continue continue
} }
jsonBase, err := meta.FindAccessor(event.Object) meta, err := meta.Accessor(event.Object)
if err != nil { if err != nil {
glog.Errorf("unable to understand watch event %#v", event) glog.Errorf("unable to understand watch event %#v", event)
continue continue
} }
switch event.Type { switch event.Type {
case watch.Added: case watch.Added:
r.store.Add(jsonBase.Name(), event.Object) r.store.Add(meta.Name(), event.Object)
case watch.Modified: case watch.Modified:
r.store.Update(jsonBase.Name(), event.Object) r.store.Update(meta.Name(), event.Object)
case watch.Deleted: case watch.Deleted:
// TODO: Will any consumers need access to the "last known // TODO: Will any consumers need access to the "last known
// state", which is passed in event.Object? If so, may need // state", which is passed in event.Object? If so, may need
// to change this. // to change this.
r.store.Delete(jsonBase.Name()) r.store.Delete(meta.Name())
default: default:
glog.Errorf("unable to understand watch event %#v", event) glog.Errorf("unable to understand watch event %#v", event)
} }
*resourceVersion = jsonBase.ResourceVersion() *resourceVersion = meta.ResourceVersion()
eventCount++ eventCount++
} }

View File

@@ -110,11 +110,11 @@ func doUpdate(c *client.RESTClient, resource string, obj runtime.Object) (string
// Update the object we are trying to send to the server with the // Update the object we are trying to send to the server with the
// correct resource version. // correct resource version.
typeMeta, err := meta.FindAccessor(obj) meta, err := meta.Accessor(obj)
if err != nil { if err != nil {
return "", err return "", err
} }
typeMeta.SetResourceVersion(version) meta.SetResourceVersion(version)
// Convert object with updated resourceVersion to data for PUT. // Convert object with updated resourceVersion to data for PUT.
data, err := c.Codec.Encode(obj) data, err := c.Codec.Encode(obj)
@@ -150,17 +150,17 @@ func doDelete(c *client.RESTClient, resource string, obj runtime.Object) (string
} }
func getIDFromObj(obj runtime.Object) (string, error) { func getIDFromObj(obj runtime.Object) (string, error) {
typeMeta, err := meta.FindAccessor(obj) meta, err := meta.Accessor(obj)
if err != nil { if err != nil {
return "", err return "", err
} }
return typeMeta.Name(), nil return meta.Name(), nil
} }
func getResourceVersionFromObj(obj runtime.Object) (string, error) { func getResourceVersionFromObj(obj runtime.Object) (string, error) {
typeMeta, err := meta.FindAccessor(obj) meta, err := meta.Accessor(obj)
if err != nil { if err != nil {
return "", err return "", err
} }
return typeMeta.ResourceVersion(), nil return meta.ResourceVersion(), nil
} }