github.com/aclisp/heapster@v0.19.2-0.20160613100040-51756f899a96/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/meta.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package meta
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  
    23  	"k8s.io/kubernetes/pkg/api/unversioned"
    24  	"k8s.io/kubernetes/pkg/conversion"
    25  	"k8s.io/kubernetes/pkg/runtime"
    26  	"k8s.io/kubernetes/pkg/types"
    27  
    28  	"github.com/golang/glog"
    29  )
    30  
    31  // Accessor takes an arbitrary object pointer and returns meta.Interface.
    32  // obj must be a pointer to an API type. An error is returned if the minimum
    33  // required fields are missing. Fields that are not required return the default
    34  // value and are a no-op if set.
    35  func Accessor(obj interface{}) (Object, error) {
    36  	if oi, ok := obj.(ObjectMetaAccessor); ok {
    37  		if om := oi.GetObjectMeta(); om != nil {
    38  			return om, nil
    39  		}
    40  	}
    41  	// we may get passed an object that is directly portable to Object
    42  	if oi, ok := obj.(Object); ok {
    43  		return oi, nil
    44  	}
    45  
    46  	glog.V(4).Infof("Calling Accessor on non-internal object: %v", reflect.TypeOf(obj))
    47  	// legacy path for objects that do not implement Object and ObjectMetaAccessor via
    48  	// reflection - very slow code path.
    49  	v, err := conversion.EnforcePtr(obj)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	t := v.Type()
    54  	if v.Kind() != reflect.Struct {
    55  		return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface())
    56  	}
    57  
    58  	typeMeta := v.FieldByName("TypeMeta")
    59  	if !typeMeta.IsValid() {
    60  		return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t)
    61  	}
    62  
    63  	a := &genericAccessor{}
    64  	if err := extractFromTypeMeta(typeMeta, a); err != nil {
    65  		return nil, fmt.Errorf("unable to find type fields on %#v: %v", typeMeta, err)
    66  	}
    67  
    68  	objectMeta := v.FieldByName("ObjectMeta")
    69  	if objectMeta.IsValid() {
    70  		// look for the ObjectMeta fields
    71  		if err := extractFromObjectMeta(objectMeta, a); err != nil {
    72  			return nil, fmt.Errorf("unable to find object fields on %#v: %v", objectMeta, err)
    73  		}
    74  	} else {
    75  		listMeta := v.FieldByName("ListMeta")
    76  		if listMeta.IsValid() {
    77  			// look for the ListMeta fields
    78  			if err := extractFromListMeta(listMeta, a); err != nil {
    79  				return nil, fmt.Errorf("unable to find list fields on %#v: %v", listMeta, err)
    80  			}
    81  		} else {
    82  			// look for the older TypeMeta with all metadata
    83  			if err := extractFromObjectMeta(typeMeta, a); err != nil {
    84  				return nil, fmt.Errorf("unable to find object fields on %#v: %v", typeMeta, err)
    85  			}
    86  		}
    87  	}
    88  
    89  	return a, nil
    90  }
    91  
    92  // TypeAccessor returns an interface that allows retrieving and modifying the APIVersion
    93  // and Kind of an in-memory internal object.
    94  // TODO: this interface is used to test code that does not have ObjectMeta or ListMeta
    95  // in round tripping (objects which can use apiVersion/kind, but do not fit the Kube
    96  // api conventions).
    97  func TypeAccessor(obj interface{}) (Type, error) {
    98  	if typed, ok := obj.(runtime.Object); ok {
    99  		return objectAccessor{typed}, nil
   100  	}
   101  	v, err := conversion.EnforcePtr(obj)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	t := v.Type()
   106  	if v.Kind() != reflect.Struct {
   107  		return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface())
   108  	}
   109  
   110  	typeMeta := v.FieldByName("TypeMeta")
   111  	if !typeMeta.IsValid() {
   112  		return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t)
   113  	}
   114  	a := &genericAccessor{}
   115  	if err := extractFromTypeMeta(typeMeta, a); err != nil {
   116  		return nil, fmt.Errorf("unable to find type fields on %#v: %v", typeMeta, err)
   117  	}
   118  	return a, nil
   119  }
   120  
   121  type objectAccessor struct {
   122  	runtime.Object
   123  }
   124  
   125  func (obj objectAccessor) GetKind() string {
   126  	return obj.GetObjectKind().GroupVersionKind().Kind
   127  }
   128  
   129  func (obj objectAccessor) SetKind(kind string) {
   130  	gvk := obj.GetObjectKind().GroupVersionKind()
   131  	gvk.Kind = kind
   132  	obj.GetObjectKind().SetGroupVersionKind(gvk)
   133  }
   134  
   135  func (obj objectAccessor) GetAPIVersion() string {
   136  	return obj.GetObjectKind().GroupVersionKind().GroupVersion().String()
   137  }
   138  
   139  func (obj objectAccessor) SetAPIVersion(version string) {
   140  	gvk := obj.GetObjectKind().GroupVersionKind()
   141  	gv, err := unversioned.ParseGroupVersion(version)
   142  	if err != nil {
   143  		gv = unversioned.GroupVersion{Version: version}
   144  	}
   145  	gvk.Group, gvk.Version = gv.Group, gv.Version
   146  	obj.GetObjectKind().SetGroupVersionKind(gvk)
   147  }
   148  
   149  // NewAccessor returns a MetadataAccessor that can retrieve
   150  // or manipulate resource version on objects derived from core API
   151  // metadata concepts.
   152  func NewAccessor() MetadataAccessor {
   153  	return resourceAccessor{}
   154  }
   155  
   156  // resourceAccessor implements ResourceVersioner and SelfLinker.
   157  type resourceAccessor struct{}
   158  
   159  func (resourceAccessor) Kind(obj runtime.Object) (string, error) {
   160  	return objectAccessor{obj}.GetKind(), nil
   161  }
   162  
   163  func (resourceAccessor) SetKind(obj runtime.Object, kind string) error {
   164  	objectAccessor{obj}.SetKind(kind)
   165  	return nil
   166  }
   167  
   168  func (resourceAccessor) APIVersion(obj runtime.Object) (string, error) {
   169  	return objectAccessor{obj}.GetAPIVersion(), nil
   170  }
   171  
   172  func (resourceAccessor) SetAPIVersion(obj runtime.Object, version string) error {
   173  	objectAccessor{obj}.SetAPIVersion(version)
   174  	return nil
   175  }
   176  
   177  func (resourceAccessor) Namespace(obj runtime.Object) (string, error) {
   178  	accessor, err := Accessor(obj)
   179  	if err != nil {
   180  		return "", err
   181  	}
   182  	return accessor.GetNamespace(), nil
   183  }
   184  
   185  func (resourceAccessor) SetNamespace(obj runtime.Object, namespace string) error {
   186  	accessor, err := Accessor(obj)
   187  	if err != nil {
   188  		return err
   189  	}
   190  	accessor.SetNamespace(namespace)
   191  	return nil
   192  }
   193  
   194  func (resourceAccessor) Name(obj runtime.Object) (string, error) {
   195  	accessor, err := Accessor(obj)
   196  	if err != nil {
   197  		return "", err
   198  	}
   199  	return accessor.GetName(), nil
   200  }
   201  
   202  func (resourceAccessor) SetName(obj runtime.Object, name string) error {
   203  	accessor, err := Accessor(obj)
   204  	if err != nil {
   205  		return err
   206  	}
   207  	accessor.SetName(name)
   208  	return nil
   209  }
   210  
   211  func (resourceAccessor) GenerateName(obj runtime.Object) (string, error) {
   212  	accessor, err := Accessor(obj)
   213  	if err != nil {
   214  		return "", err
   215  	}
   216  	return accessor.GetGenerateName(), nil
   217  }
   218  
   219  func (resourceAccessor) SetGenerateName(obj runtime.Object, name string) error {
   220  	accessor, err := Accessor(obj)
   221  	if err != nil {
   222  		return err
   223  	}
   224  	accessor.SetGenerateName(name)
   225  	return nil
   226  }
   227  
   228  func (resourceAccessor) UID(obj runtime.Object) (types.UID, error) {
   229  	accessor, err := Accessor(obj)
   230  	if err != nil {
   231  		return "", err
   232  	}
   233  	return accessor.GetUID(), nil
   234  }
   235  
   236  func (resourceAccessor) SetUID(obj runtime.Object, uid types.UID) error {
   237  	accessor, err := Accessor(obj)
   238  	if err != nil {
   239  		return err
   240  	}
   241  	accessor.SetUID(uid)
   242  	return nil
   243  }
   244  
   245  func (resourceAccessor) SelfLink(obj runtime.Object) (string, error) {
   246  	accessor, err := Accessor(obj)
   247  	if err != nil {
   248  		return "", err
   249  	}
   250  	return accessor.GetSelfLink(), nil
   251  }
   252  
   253  func (resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error {
   254  	accessor, err := Accessor(obj)
   255  	if err != nil {
   256  		return err
   257  	}
   258  	accessor.SetSelfLink(selfLink)
   259  	return nil
   260  }
   261  
   262  func (resourceAccessor) Labels(obj runtime.Object) (map[string]string, error) {
   263  	accessor, err := Accessor(obj)
   264  	if err != nil {
   265  		return nil, err
   266  	}
   267  	return accessor.GetLabels(), nil
   268  }
   269  
   270  func (resourceAccessor) SetLabels(obj runtime.Object, labels map[string]string) error {
   271  	accessor, err := Accessor(obj)
   272  	if err != nil {
   273  		return err
   274  	}
   275  	accessor.SetLabels(labels)
   276  	return nil
   277  }
   278  
   279  func (resourceAccessor) Annotations(obj runtime.Object) (map[string]string, error) {
   280  	accessor, err := Accessor(obj)
   281  	if err != nil {
   282  		return nil, err
   283  	}
   284  	return accessor.GetAnnotations(), nil
   285  }
   286  
   287  func (resourceAccessor) SetAnnotations(obj runtime.Object, annotations map[string]string) error {
   288  	accessor, err := Accessor(obj)
   289  	if err != nil {
   290  		return err
   291  	}
   292  	accessor.SetAnnotations(annotations)
   293  	return nil
   294  }
   295  
   296  func (resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) {
   297  	accessor, err := Accessor(obj)
   298  	if err != nil {
   299  		return "", err
   300  	}
   301  	return accessor.GetResourceVersion(), nil
   302  }
   303  
   304  func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) error {
   305  	accessor, err := Accessor(obj)
   306  	if err != nil {
   307  		return err
   308  	}
   309  	accessor.SetResourceVersion(version)
   310  	return nil
   311  }
   312  
   313  // genericAccessor contains pointers to strings that can modify an arbitrary
   314  // struct and implements the Accessor interface.
   315  type genericAccessor struct {
   316  	namespace         *string
   317  	name              *string
   318  	generateName      *string
   319  	uid               *types.UID
   320  	apiVersion        *string
   321  	kind              *string
   322  	resourceVersion   *string
   323  	selfLink          *string
   324  	creationTimestamp *unversioned.Time
   325  	deletionTimestamp **unversioned.Time
   326  	labels            *map[string]string
   327  	annotations       *map[string]string
   328  }
   329  
   330  func (a genericAccessor) GetNamespace() string {
   331  	if a.namespace == nil {
   332  		return ""
   333  	}
   334  	return *a.namespace
   335  }
   336  
   337  func (a genericAccessor) SetNamespace(namespace string) {
   338  	if a.namespace == nil {
   339  		return
   340  	}
   341  	*a.namespace = namespace
   342  }
   343  
   344  func (a genericAccessor) GetName() string {
   345  	if a.name == nil {
   346  		return ""
   347  	}
   348  	return *a.name
   349  }
   350  
   351  func (a genericAccessor) SetName(name string) {
   352  	if a.name == nil {
   353  		return
   354  	}
   355  	*a.name = name
   356  }
   357  
   358  func (a genericAccessor) GetGenerateName() string {
   359  	if a.generateName == nil {
   360  		return ""
   361  	}
   362  	return *a.generateName
   363  }
   364  
   365  func (a genericAccessor) SetGenerateName(generateName string) {
   366  	if a.generateName == nil {
   367  		return
   368  	}
   369  	*a.generateName = generateName
   370  }
   371  
   372  func (a genericAccessor) GetUID() types.UID {
   373  	if a.uid == nil {
   374  		return ""
   375  	}
   376  	return *a.uid
   377  }
   378  
   379  func (a genericAccessor) SetUID(uid types.UID) {
   380  	if a.uid == nil {
   381  		return
   382  	}
   383  	*a.uid = uid
   384  }
   385  
   386  func (a genericAccessor) GetAPIVersion() string {
   387  	return *a.apiVersion
   388  }
   389  
   390  func (a genericAccessor) SetAPIVersion(version string) {
   391  	*a.apiVersion = version
   392  }
   393  
   394  func (a genericAccessor) GetKind() string {
   395  	return *a.kind
   396  }
   397  
   398  func (a genericAccessor) SetKind(kind string) {
   399  	*a.kind = kind
   400  }
   401  
   402  func (a genericAccessor) GetResourceVersion() string {
   403  	return *a.resourceVersion
   404  }
   405  
   406  func (a genericAccessor) SetResourceVersion(version string) {
   407  	*a.resourceVersion = version
   408  }
   409  
   410  func (a genericAccessor) GetSelfLink() string {
   411  	return *a.selfLink
   412  }
   413  
   414  func (a genericAccessor) SetSelfLink(selfLink string) {
   415  	*a.selfLink = selfLink
   416  }
   417  
   418  func (a genericAccessor) GetCreationTimestamp() unversioned.Time {
   419  	return *a.creationTimestamp
   420  }
   421  
   422  func (a genericAccessor) SetCreationTimestamp(timestamp unversioned.Time) {
   423  	*a.creationTimestamp = timestamp
   424  }
   425  
   426  func (a genericAccessor) GetDeletionTimestamp() *unversioned.Time {
   427  	return *a.deletionTimestamp
   428  }
   429  
   430  func (a genericAccessor) SetDeletionTimestamp(timestamp *unversioned.Time) {
   431  	*a.deletionTimestamp = timestamp
   432  }
   433  
   434  func (a genericAccessor) GetLabels() map[string]string {
   435  	if a.labels == nil {
   436  		return nil
   437  	}
   438  	return *a.labels
   439  }
   440  
   441  func (a genericAccessor) SetLabels(labels map[string]string) {
   442  	*a.labels = labels
   443  }
   444  
   445  func (a genericAccessor) GetAnnotations() map[string]string {
   446  	if a.annotations == nil {
   447  		return nil
   448  	}
   449  	return *a.annotations
   450  }
   451  
   452  func (a genericAccessor) SetAnnotations(annotations map[string]string) {
   453  	if a.annotations == nil {
   454  		emptyAnnotations := make(map[string]string)
   455  		a.annotations = &emptyAnnotations
   456  	}
   457  	*a.annotations = annotations
   458  }
   459  
   460  // extractFromTypeMeta extracts pointers to version and kind fields from an object
   461  func extractFromTypeMeta(v reflect.Value, a *genericAccessor) error {
   462  	if err := runtime.FieldPtr(v, "APIVersion", &a.apiVersion); err != nil {
   463  		return err
   464  	}
   465  	if err := runtime.FieldPtr(v, "Kind", &a.kind); err != nil {
   466  		return err
   467  	}
   468  	return nil
   469  }
   470  
   471  // extractFromObjectMeta extracts pointers to metadata fields from an object
   472  func extractFromObjectMeta(v reflect.Value, a *genericAccessor) error {
   473  	if err := runtime.FieldPtr(v, "Namespace", &a.namespace); err != nil {
   474  		return err
   475  	}
   476  	if err := runtime.FieldPtr(v, "Name", &a.name); err != nil {
   477  		return err
   478  	}
   479  	if err := runtime.FieldPtr(v, "GenerateName", &a.generateName); err != nil {
   480  		return err
   481  	}
   482  	if err := runtime.FieldPtr(v, "UID", &a.uid); err != nil {
   483  		return err
   484  	}
   485  	if err := runtime.FieldPtr(v, "ResourceVersion", &a.resourceVersion); err != nil {
   486  		return err
   487  	}
   488  	if err := runtime.FieldPtr(v, "SelfLink", &a.selfLink); err != nil {
   489  		return err
   490  	}
   491  	if err := runtime.FieldPtr(v, "Labels", &a.labels); err != nil {
   492  		return err
   493  	}
   494  	if err := runtime.FieldPtr(v, "Annotations", &a.annotations); err != nil {
   495  		return err
   496  	}
   497  	return nil
   498  }
   499  
   500  // extractFromObjectMeta extracts pointers to metadata fields from a list object
   501  func extractFromListMeta(v reflect.Value, a *genericAccessor) error {
   502  	if err := runtime.FieldPtr(v, "ResourceVersion", &a.resourceVersion); err != nil {
   503  		return err
   504  	}
   505  	if err := runtime.FieldPtr(v, "SelfLink", &a.selfLink); err != nil {
   506  		return err
   507  	}
   508  	return nil
   509  }