github.com/timstclair/heapster@v0.20.0-alpha1/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/conversion"
    24  	"k8s.io/kubernetes/pkg/runtime"
    25  	"k8s.io/kubernetes/pkg/types"
    26  )
    27  
    28  // Accessor takes an arbitrary object pointer and returns meta.Interface.
    29  // obj must be a pointer to an API type. An error is returned if the minimum
    30  // required fields are missing. Fields that are not required return the default
    31  // value and are a no-op if set.
    32  // TODO: add a fast path for *TypeMeta and *ObjectMeta for internal objects
    33  func Accessor(obj interface{}) (Interface, error) {
    34  	v, err := conversion.EnforcePtr(obj)
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  	t := v.Type()
    39  	if v.Kind() != reflect.Struct {
    40  		return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface())
    41  	}
    42  
    43  	typeMeta := v.FieldByName("TypeMeta")
    44  	if !typeMeta.IsValid() {
    45  		return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t)
    46  	}
    47  
    48  	a := &genericAccessor{}
    49  	if err := extractFromTypeMeta(typeMeta, a); err != nil {
    50  		return nil, fmt.Errorf("unable to find type fields on %#v: %v", typeMeta, err)
    51  	}
    52  
    53  	objectMeta := v.FieldByName("ObjectMeta")
    54  	if objectMeta.IsValid() {
    55  		// look for the ObjectMeta fields
    56  		if err := extractFromObjectMeta(objectMeta, a); err != nil {
    57  			return nil, fmt.Errorf("unable to find object fields on %#v: %v", objectMeta, err)
    58  		}
    59  	} else {
    60  		listMeta := v.FieldByName("ListMeta")
    61  		if listMeta.IsValid() {
    62  			// look for the ListMeta fields
    63  			if err := extractFromListMeta(listMeta, a); err != nil {
    64  				return nil, fmt.Errorf("unable to find list fields on %#v: %v", listMeta, err)
    65  			}
    66  		} else {
    67  			// look for the older TypeMeta with all metadata
    68  			if err := extractFromObjectMeta(typeMeta, a); err != nil {
    69  				return nil, fmt.Errorf("unable to find object fields on %#v: %v", typeMeta, err)
    70  			}
    71  		}
    72  	}
    73  
    74  	return a, nil
    75  }
    76  
    77  // TypeAccessor returns an interface that allows retrieving and modifying the APIVersion
    78  // and Kind of an in-memory internal object.
    79  // TODO: this interface is used to test code that does not have ObjectMeta or ListMeta
    80  // in round tripping (objects which can use apiVersion/kind, but do not fit the Kube
    81  // api conventions).
    82  func TypeAccessor(obj interface{}) (TypeInterface, error) {
    83  	v, err := conversion.EnforcePtr(obj)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	t := v.Type()
    88  	if v.Kind() != reflect.Struct {
    89  		return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface())
    90  	}
    91  
    92  	typeMeta := v.FieldByName("TypeMeta")
    93  	if !typeMeta.IsValid() {
    94  		return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t)
    95  	}
    96  	a := &genericAccessor{}
    97  	if err := extractFromTypeMeta(typeMeta, a); err != nil {
    98  		return nil, fmt.Errorf("unable to find type fields on %#v: %v", typeMeta, err)
    99  	}
   100  	return a, nil
   101  }
   102  
   103  // NewAccessor returns a MetadataAccessor that can retrieve
   104  // or manipulate resource version on objects derived from core API
   105  // metadata concepts.
   106  func NewAccessor() MetadataAccessor {
   107  	return resourceAccessor{}
   108  }
   109  
   110  // resourceAccessor implements ResourceVersioner and SelfLinker.
   111  type resourceAccessor struct{}
   112  
   113  func (resourceAccessor) Kind(obj runtime.Object) (string, error) {
   114  	accessor, err := Accessor(obj)
   115  	if err != nil {
   116  		return "", err
   117  	}
   118  	return accessor.Kind(), nil
   119  }
   120  
   121  func (resourceAccessor) SetKind(obj runtime.Object, kind string) error {
   122  	accessor, err := Accessor(obj)
   123  	if err != nil {
   124  		return err
   125  	}
   126  	accessor.SetKind(kind)
   127  	return nil
   128  }
   129  
   130  func (resourceAccessor) APIVersion(obj runtime.Object) (string, error) {
   131  	accessor, err := Accessor(obj)
   132  	if err != nil {
   133  		return "", err
   134  	}
   135  	return accessor.APIVersion(), nil
   136  }
   137  
   138  func (resourceAccessor) SetAPIVersion(obj runtime.Object, version string) error {
   139  	accessor, err := Accessor(obj)
   140  	if err != nil {
   141  		return err
   142  	}
   143  	accessor.SetAPIVersion(version)
   144  	return nil
   145  }
   146  
   147  func (resourceAccessor) Namespace(obj runtime.Object) (string, error) {
   148  	accessor, err := Accessor(obj)
   149  	if err != nil {
   150  		return "", err
   151  	}
   152  	return accessor.Namespace(), nil
   153  }
   154  
   155  func (resourceAccessor) SetNamespace(obj runtime.Object, namespace string) error {
   156  	accessor, err := Accessor(obj)
   157  	if err != nil {
   158  		return err
   159  	}
   160  	accessor.SetNamespace(namespace)
   161  	return nil
   162  }
   163  
   164  func (resourceAccessor) Name(obj runtime.Object) (string, error) {
   165  	accessor, err := Accessor(obj)
   166  	if err != nil {
   167  		return "", err
   168  	}
   169  	return accessor.Name(), nil
   170  }
   171  
   172  func (resourceAccessor) SetName(obj runtime.Object, name string) error {
   173  	accessor, err := Accessor(obj)
   174  	if err != nil {
   175  		return err
   176  	}
   177  	accessor.SetName(name)
   178  	return nil
   179  }
   180  
   181  func (resourceAccessor) GenerateName(obj runtime.Object) (string, error) {
   182  	accessor, err := Accessor(obj)
   183  	if err != nil {
   184  		return "", err
   185  	}
   186  	return accessor.GenerateName(), nil
   187  }
   188  
   189  func (resourceAccessor) SetGenerateName(obj runtime.Object, name string) error {
   190  	accessor, err := Accessor(obj)
   191  	if err != nil {
   192  		return err
   193  	}
   194  	accessor.SetGenerateName(name)
   195  	return nil
   196  }
   197  
   198  func (resourceAccessor) UID(obj runtime.Object) (types.UID, error) {
   199  	accessor, err := Accessor(obj)
   200  	if err != nil {
   201  		return "", err
   202  	}
   203  	return accessor.UID(), nil
   204  }
   205  
   206  func (resourceAccessor) SetUID(obj runtime.Object, uid types.UID) error {
   207  	accessor, err := Accessor(obj)
   208  	if err != nil {
   209  		return err
   210  	}
   211  	accessor.SetUID(uid)
   212  	return nil
   213  }
   214  
   215  func (resourceAccessor) SelfLink(obj runtime.Object) (string, error) {
   216  	accessor, err := Accessor(obj)
   217  	if err != nil {
   218  		return "", err
   219  	}
   220  	return accessor.SelfLink(), nil
   221  }
   222  
   223  func (resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error {
   224  	accessor, err := Accessor(obj)
   225  	if err != nil {
   226  		return err
   227  	}
   228  	accessor.SetSelfLink(selfLink)
   229  	return nil
   230  }
   231  
   232  func (resourceAccessor) Labels(obj runtime.Object) (map[string]string, error) {
   233  	accessor, err := Accessor(obj)
   234  	if err != nil {
   235  		return nil, err
   236  	}
   237  	return accessor.Labels(), nil
   238  }
   239  
   240  func (resourceAccessor) SetLabels(obj runtime.Object, labels map[string]string) error {
   241  	accessor, err := Accessor(obj)
   242  	if err != nil {
   243  		return err
   244  	}
   245  	accessor.SetLabels(labels)
   246  	return nil
   247  }
   248  
   249  func (resourceAccessor) Annotations(obj runtime.Object) (map[string]string, error) {
   250  	accessor, err := Accessor(obj)
   251  	if err != nil {
   252  		return nil, err
   253  	}
   254  	return accessor.Annotations(), nil
   255  }
   256  
   257  func (resourceAccessor) SetAnnotations(obj runtime.Object, annotations map[string]string) error {
   258  	accessor, err := Accessor(obj)
   259  	if err != nil {
   260  		return err
   261  	}
   262  	accessor.SetAnnotations(annotations)
   263  	return nil
   264  }
   265  
   266  func (resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) {
   267  	accessor, err := Accessor(obj)
   268  	if err != nil {
   269  		return "", err
   270  	}
   271  	return accessor.ResourceVersion(), nil
   272  }
   273  
   274  func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) error {
   275  	accessor, err := Accessor(obj)
   276  	if err != nil {
   277  		return err
   278  	}
   279  	accessor.SetResourceVersion(version)
   280  	return nil
   281  }
   282  
   283  // genericAccessor contains pointers to strings that can modify an arbitrary
   284  // struct and implements the Accessor interface.
   285  type genericAccessor struct {
   286  	namespace       *string
   287  	name            *string
   288  	generateName    *string
   289  	uid             *types.UID
   290  	apiVersion      *string
   291  	kind            *string
   292  	resourceVersion *string
   293  	selfLink        *string
   294  	labels          *map[string]string
   295  	annotations     *map[string]string
   296  }
   297  
   298  func (a genericAccessor) Namespace() string {
   299  	if a.namespace == nil {
   300  		return ""
   301  	}
   302  	return *a.namespace
   303  }
   304  
   305  func (a genericAccessor) SetNamespace(namespace string) {
   306  	if a.namespace == nil {
   307  		return
   308  	}
   309  	*a.namespace = namespace
   310  }
   311  
   312  func (a genericAccessor) Name() string {
   313  	if a.name == nil {
   314  		return ""
   315  	}
   316  	return *a.name
   317  }
   318  
   319  func (a genericAccessor) SetName(name string) {
   320  	if a.name == nil {
   321  		return
   322  	}
   323  	*a.name = name
   324  }
   325  
   326  func (a genericAccessor) GenerateName() string {
   327  	if a.generateName == nil {
   328  		return ""
   329  	}
   330  	return *a.generateName
   331  }
   332  
   333  func (a genericAccessor) SetGenerateName(generateName string) {
   334  	if a.generateName == nil {
   335  		return
   336  	}
   337  	*a.generateName = generateName
   338  }
   339  
   340  func (a genericAccessor) UID() types.UID {
   341  	if a.uid == nil {
   342  		return ""
   343  	}
   344  	return *a.uid
   345  }
   346  
   347  func (a genericAccessor) SetUID(uid types.UID) {
   348  	if a.uid == nil {
   349  		return
   350  	}
   351  	*a.uid = uid
   352  }
   353  
   354  func (a genericAccessor) APIVersion() string {
   355  	return *a.apiVersion
   356  }
   357  
   358  func (a genericAccessor) SetAPIVersion(version string) {
   359  	*a.apiVersion = version
   360  }
   361  
   362  func (a genericAccessor) Kind() string {
   363  	return *a.kind
   364  }
   365  
   366  func (a genericAccessor) SetKind(kind string) {
   367  	*a.kind = kind
   368  }
   369  
   370  func (a genericAccessor) ResourceVersion() string {
   371  	return *a.resourceVersion
   372  }
   373  
   374  func (a genericAccessor) SetResourceVersion(version string) {
   375  	*a.resourceVersion = version
   376  }
   377  
   378  func (a genericAccessor) SelfLink() string {
   379  	return *a.selfLink
   380  }
   381  
   382  func (a genericAccessor) SetSelfLink(selfLink string) {
   383  	*a.selfLink = selfLink
   384  }
   385  
   386  func (a genericAccessor) Labels() map[string]string {
   387  	if a.labels == nil {
   388  		return nil
   389  	}
   390  	return *a.labels
   391  }
   392  
   393  func (a genericAccessor) SetLabels(labels map[string]string) {
   394  	*a.labels = labels
   395  }
   396  
   397  func (a genericAccessor) Annotations() map[string]string {
   398  	if a.annotations == nil {
   399  		return nil
   400  	}
   401  	return *a.annotations
   402  }
   403  
   404  func (a genericAccessor) SetAnnotations(annotations map[string]string) {
   405  	if a.annotations == nil {
   406  		emptyAnnotations := make(map[string]string)
   407  		a.annotations = &emptyAnnotations
   408  	}
   409  	*a.annotations = annotations
   410  }
   411  
   412  // extractFromTypeMeta extracts pointers to version and kind fields from an object
   413  func extractFromTypeMeta(v reflect.Value, a *genericAccessor) error {
   414  	if err := runtime.FieldPtr(v, "APIVersion", &a.apiVersion); err != nil {
   415  		return err
   416  	}
   417  	if err := runtime.FieldPtr(v, "Kind", &a.kind); err != nil {
   418  		return err
   419  	}
   420  	return nil
   421  }
   422  
   423  // extractFromObjectMeta extracts pointers to metadata fields from an object
   424  func extractFromObjectMeta(v reflect.Value, a *genericAccessor) error {
   425  	if err := runtime.FieldPtr(v, "Namespace", &a.namespace); err != nil {
   426  		return err
   427  	}
   428  	if err := runtime.FieldPtr(v, "Name", &a.name); err != nil {
   429  		return err
   430  	}
   431  	if err := runtime.FieldPtr(v, "GenerateName", &a.generateName); err != nil {
   432  		return err
   433  	}
   434  	if err := runtime.FieldPtr(v, "UID", &a.uid); err != nil {
   435  		return err
   436  	}
   437  	if err := runtime.FieldPtr(v, "ResourceVersion", &a.resourceVersion); err != nil {
   438  		return err
   439  	}
   440  	if err := runtime.FieldPtr(v, "SelfLink", &a.selfLink); err != nil {
   441  		return err
   442  	}
   443  	if err := runtime.FieldPtr(v, "Labels", &a.labels); err != nil {
   444  		return err
   445  	}
   446  	if err := runtime.FieldPtr(v, "Annotations", &a.annotations); err != nil {
   447  		return err
   448  	}
   449  	return nil
   450  }
   451  
   452  // extractFromObjectMeta extracts pointers to metadata fields from a list object
   453  func extractFromListMeta(v reflect.Value, a *genericAccessor) error {
   454  	if err := runtime.FieldPtr(v, "ResourceVersion", &a.resourceVersion); err != nil {
   455  		return err
   456  	}
   457  	if err := runtime.FieldPtr(v, "SelfLink", &a.selfLink); err != nil {
   458  		return err
   459  	}
   460  	return nil
   461  }