2 Copyright 2014 The Kubernetes Authors.
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
8 http://www.apache.org/licenses/LICENSE-2.0
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.
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
27 "k8s.io/apimachinery/pkg/conversion"
28 "k8s.io/apimachinery/pkg/runtime"
29 "k8s.io/apimachinery/pkg/runtime/schema"
30 "k8s.io/apimachinery/pkg/types"
33 // errNotList is returned when an object implements the Object style interfaces but not the List style
35 var errNotList = fmt.Errorf("object does not implement the List interfaces")
37 var errNotCommon = fmt.Errorf("object does not implement the common interface for accessing the SelfLink")
39 // CommonAccessor returns a Common interface for the provided object or an error if the object does
41 func CommonAccessor(obj interface{}) (metav1.Common, error) {
42 switch t := obj.(type) {
45 case metav1.ListInterface:
47 case ListMetaAccessor:
48 if m := t.GetListMeta(); m != nil {
51 return nil, errNotCommon
52 case metav1.ListMetaAccessor:
53 if m := t.GetListMeta(); m != nil {
56 return nil, errNotCommon
59 case metav1.ObjectMetaAccessor:
60 if m := t.GetObjectMeta(); m != nil {
63 return nil, errNotCommon
65 return nil, errNotCommon
69 // ListAccessor returns a List interface for the provided object or an error if the object does
71 // IMPORTANT: Objects are NOT a superset of lists. Do not use this check to determine whether an
72 // object *is* a List.
73 func ListAccessor(obj interface{}) (List, error) {
74 switch t := obj.(type) {
77 case metav1.ListInterface:
79 case ListMetaAccessor:
80 if m := t.GetListMeta(); m != nil {
83 return nil, errNotList
84 case metav1.ListMetaAccessor:
85 if m := t.GetListMeta(); m != nil {
88 return nil, errNotList
90 return nil, errNotList
94 // errNotObject is returned when an object implements the List style interfaces but not the Object style
96 var errNotObject = fmt.Errorf("object does not implement the Object interfaces")
98 // Accessor takes an arbitrary object pointer and returns meta.Interface.
99 // obj must be a pointer to an API type. An error is returned if the minimum
100 // required fields are missing. Fields that are not required return the default
101 // value and are a no-op if set.
102 func Accessor(obj interface{}) (metav1.Object, error) {
103 switch t := obj.(type) {
106 case metav1.ObjectMetaAccessor:
107 if m := t.GetObjectMeta(); m != nil {
110 return nil, errNotObject
112 return nil, errNotObject
116 // AsPartialObjectMetadata takes the metav1 interface and returns a partial object.
117 // TODO: consider making this solely a conversion action.
118 func AsPartialObjectMetadata(m metav1.Object) *metav1beta1.PartialObjectMetadata {
119 switch t := m.(type) {
120 case *metav1.ObjectMeta:
121 return &metav1beta1.PartialObjectMetadata{ObjectMeta: *t}
123 return &metav1beta1.PartialObjectMetadata{
124 ObjectMeta: metav1.ObjectMeta{
126 GenerateName: m.GetGenerateName(),
127 Namespace: m.GetNamespace(),
128 SelfLink: m.GetSelfLink(),
130 ResourceVersion: m.GetResourceVersion(),
131 Generation: m.GetGeneration(),
132 CreationTimestamp: m.GetCreationTimestamp(),
133 DeletionTimestamp: m.GetDeletionTimestamp(),
134 DeletionGracePeriodSeconds: m.GetDeletionGracePeriodSeconds(),
135 Labels: m.GetLabels(),
136 Annotations: m.GetAnnotations(),
137 OwnerReferences: m.GetOwnerReferences(),
138 Finalizers: m.GetFinalizers(),
139 ClusterName: m.GetClusterName(),
140 Initializers: m.GetInitializers(),
146 // TypeAccessor returns an interface that allows retrieving and modifying the APIVersion
147 // and Kind of an in-memory internal object.
148 // TODO: this interface is used to test code that does not have ObjectMeta or ListMeta
149 // in round tripping (objects which can use apiVersion/kind, but do not fit the Kube
151 func TypeAccessor(obj interface{}) (Type, error) {
152 if typed, ok := obj.(runtime.Object); ok {
153 return objectAccessor{typed}, nil
155 v, err := conversion.EnforcePtr(obj)
160 if v.Kind() != reflect.Struct {
161 return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface())
164 typeMeta := v.FieldByName("TypeMeta")
165 if !typeMeta.IsValid() {
166 return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t)
168 a := &genericAccessor{}
169 if err := extractFromTypeMeta(typeMeta, a); err != nil {
170 return nil, fmt.Errorf("unable to find type fields on %#v: %v", typeMeta, err)
175 type objectAccessor struct {
179 func (obj objectAccessor) GetKind() string {
180 return obj.GetObjectKind().GroupVersionKind().Kind
183 func (obj objectAccessor) SetKind(kind string) {
184 gvk := obj.GetObjectKind().GroupVersionKind()
186 obj.GetObjectKind().SetGroupVersionKind(gvk)
189 func (obj objectAccessor) GetAPIVersion() string {
190 return obj.GetObjectKind().GroupVersionKind().GroupVersion().String()
193 func (obj objectAccessor) SetAPIVersion(version string) {
194 gvk := obj.GetObjectKind().GroupVersionKind()
195 gv, err := schema.ParseGroupVersion(version)
197 gv = schema.GroupVersion{Version: version}
199 gvk.Group, gvk.Version = gv.Group, gv.Version
200 obj.GetObjectKind().SetGroupVersionKind(gvk)
203 // NewAccessor returns a MetadataAccessor that can retrieve
204 // or manipulate resource version on objects derived from core API
205 // metadata concepts.
206 func NewAccessor() MetadataAccessor {
207 return resourceAccessor{}
210 // resourceAccessor implements ResourceVersioner and SelfLinker.
211 type resourceAccessor struct{}
213 func (resourceAccessor) Kind(obj runtime.Object) (string, error) {
214 return objectAccessor{obj}.GetKind(), nil
217 func (resourceAccessor) SetKind(obj runtime.Object, kind string) error {
218 objectAccessor{obj}.SetKind(kind)
222 func (resourceAccessor) APIVersion(obj runtime.Object) (string, error) {
223 return objectAccessor{obj}.GetAPIVersion(), nil
226 func (resourceAccessor) SetAPIVersion(obj runtime.Object, version string) error {
227 objectAccessor{obj}.SetAPIVersion(version)
231 func (resourceAccessor) Namespace(obj runtime.Object) (string, error) {
232 accessor, err := Accessor(obj)
236 return accessor.GetNamespace(), nil
239 func (resourceAccessor) SetNamespace(obj runtime.Object, namespace string) error {
240 accessor, err := Accessor(obj)
244 accessor.SetNamespace(namespace)
248 func (resourceAccessor) Name(obj runtime.Object) (string, error) {
249 accessor, err := Accessor(obj)
253 return accessor.GetName(), nil
256 func (resourceAccessor) SetName(obj runtime.Object, name string) error {
257 accessor, err := Accessor(obj)
261 accessor.SetName(name)
265 func (resourceAccessor) GenerateName(obj runtime.Object) (string, error) {
266 accessor, err := Accessor(obj)
270 return accessor.GetGenerateName(), nil
273 func (resourceAccessor) SetGenerateName(obj runtime.Object, name string) error {
274 accessor, err := Accessor(obj)
278 accessor.SetGenerateName(name)
282 func (resourceAccessor) UID(obj runtime.Object) (types.UID, error) {
283 accessor, err := Accessor(obj)
287 return accessor.GetUID(), nil
290 func (resourceAccessor) SetUID(obj runtime.Object, uid types.UID) error {
291 accessor, err := Accessor(obj)
299 func (resourceAccessor) SelfLink(obj runtime.Object) (string, error) {
300 accessor, err := CommonAccessor(obj)
304 return accessor.GetSelfLink(), nil
307 func (resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error {
308 accessor, err := CommonAccessor(obj)
312 accessor.SetSelfLink(selfLink)
316 func (resourceAccessor) Labels(obj runtime.Object) (map[string]string, error) {
317 accessor, err := Accessor(obj)
321 return accessor.GetLabels(), nil
324 func (resourceAccessor) SetLabels(obj runtime.Object, labels map[string]string) error {
325 accessor, err := Accessor(obj)
329 accessor.SetLabels(labels)
333 func (resourceAccessor) Annotations(obj runtime.Object) (map[string]string, error) {
334 accessor, err := Accessor(obj)
338 return accessor.GetAnnotations(), nil
341 func (resourceAccessor) SetAnnotations(obj runtime.Object, annotations map[string]string) error {
342 accessor, err := Accessor(obj)
346 accessor.SetAnnotations(annotations)
350 func (resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) {
351 accessor, err := CommonAccessor(obj)
355 return accessor.GetResourceVersion(), nil
358 func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) error {
359 accessor, err := CommonAccessor(obj)
363 accessor.SetResourceVersion(version)
367 func (resourceAccessor) Continue(obj runtime.Object) (string, error) {
368 accessor, err := ListAccessor(obj)
372 return accessor.GetContinue(), nil
375 func (resourceAccessor) SetContinue(obj runtime.Object, version string) error {
376 accessor, err := ListAccessor(obj)
380 accessor.SetContinue(version)
384 // extractFromOwnerReference extracts v to o. v is the OwnerReferences field of an object.
385 func extractFromOwnerReference(v reflect.Value, o *metav1.OwnerReference) error {
386 if err := runtime.Field(v, "APIVersion", &o.APIVersion); err != nil {
389 if err := runtime.Field(v, "Kind", &o.Kind); err != nil {
392 if err := runtime.Field(v, "Name", &o.Name); err != nil {
395 if err := runtime.Field(v, "UID", &o.UID); err != nil {
398 var controllerPtr *bool
399 if err := runtime.Field(v, "Controller", &controllerPtr); err != nil {
402 if controllerPtr != nil {
403 controller := *controllerPtr
404 o.Controller = &controller
406 var blockOwnerDeletionPtr *bool
407 if err := runtime.Field(v, "BlockOwnerDeletion", &blockOwnerDeletionPtr); err != nil {
410 if blockOwnerDeletionPtr != nil {
411 block := *blockOwnerDeletionPtr
412 o.BlockOwnerDeletion = &block
417 // setOwnerReference sets v to o. v is the OwnerReferences field of an object.
418 func setOwnerReference(v reflect.Value, o *metav1.OwnerReference) error {
419 if err := runtime.SetField(o.APIVersion, v, "APIVersion"); err != nil {
422 if err := runtime.SetField(o.Kind, v, "Kind"); err != nil {
425 if err := runtime.SetField(o.Name, v, "Name"); err != nil {
428 if err := runtime.SetField(o.UID, v, "UID"); err != nil {
431 if o.Controller != nil {
432 controller := *(o.Controller)
433 if err := runtime.SetField(&controller, v, "Controller"); err != nil {
437 if o.BlockOwnerDeletion != nil {
438 block := *(o.BlockOwnerDeletion)
439 if err := runtime.SetField(&block, v, "BlockOwnerDeletion"); err != nil {
446 // genericAccessor contains pointers to strings that can modify an arbitrary
447 // struct and implements the Accessor interface.
448 type genericAccessor struct {
455 resourceVersion *string
457 creationTimestamp *metav1.Time
458 deletionTimestamp **metav1.Time
459 labels *map[string]string
460 annotations *map[string]string
461 ownerReferences reflect.Value
465 func (a genericAccessor) GetNamespace() string {
466 if a.namespace == nil {
472 func (a genericAccessor) SetNamespace(namespace string) {
473 if a.namespace == nil {
476 *a.namespace = namespace
479 func (a genericAccessor) GetName() string {
486 func (a genericAccessor) SetName(name string) {
493 func (a genericAccessor) GetGenerateName() string {
494 if a.generateName == nil {
497 return *a.generateName
500 func (a genericAccessor) SetGenerateName(generateName string) {
501 if a.generateName == nil {
504 *a.generateName = generateName
507 func (a genericAccessor) GetUID() types.UID {
514 func (a genericAccessor) SetUID(uid types.UID) {
521 func (a genericAccessor) GetAPIVersion() string {
525 func (a genericAccessor) SetAPIVersion(version string) {
526 *a.apiVersion = version
529 func (a genericAccessor) GetKind() string {
533 func (a genericAccessor) SetKind(kind string) {
537 func (a genericAccessor) GetResourceVersion() string {
538 return *a.resourceVersion
541 func (a genericAccessor) SetResourceVersion(version string) {
542 *a.resourceVersion = version
545 func (a genericAccessor) GetSelfLink() string {
549 func (a genericAccessor) SetSelfLink(selfLink string) {
550 *a.selfLink = selfLink
553 func (a genericAccessor) GetCreationTimestamp() metav1.Time {
554 return *a.creationTimestamp
557 func (a genericAccessor) SetCreationTimestamp(timestamp metav1.Time) {
558 *a.creationTimestamp = timestamp
561 func (a genericAccessor) GetDeletionTimestamp() *metav1.Time {
562 return *a.deletionTimestamp
565 func (a genericAccessor) SetDeletionTimestamp(timestamp *metav1.Time) {
566 *a.deletionTimestamp = timestamp
569 func (a genericAccessor) GetLabels() map[string]string {
576 func (a genericAccessor) SetLabels(labels map[string]string) {
580 func (a genericAccessor) GetAnnotations() map[string]string {
581 if a.annotations == nil {
584 return *a.annotations
587 func (a genericAccessor) SetAnnotations(annotations map[string]string) {
588 if a.annotations == nil {
589 emptyAnnotations := make(map[string]string)
590 a.annotations = &emptyAnnotations
592 *a.annotations = annotations
595 func (a genericAccessor) GetFinalizers() []string {
596 if a.finalizers == nil {
602 func (a genericAccessor) SetFinalizers(finalizers []string) {
603 *a.finalizers = finalizers
606 func (a genericAccessor) GetOwnerReferences() []metav1.OwnerReference {
607 var ret []metav1.OwnerReference
608 s := a.ownerReferences
609 if s.Kind() != reflect.Ptr || s.Elem().Kind() != reflect.Slice {
610 klog.Errorf("expect %v to be a pointer to slice", s)
614 // Set the capacity to one element greater to avoid copy if the caller later append an element.
615 ret = make([]metav1.OwnerReference, s.Len(), s.Len()+1)
616 for i := 0; i < s.Len(); i++ {
617 if err := extractFromOwnerReference(s.Index(i), &ret[i]); err != nil {
618 klog.Errorf("extractFromOwnerReference failed: %v", err)
625 func (a genericAccessor) SetOwnerReferences(references []metav1.OwnerReference) {
626 s := a.ownerReferences
627 if s.Kind() != reflect.Ptr || s.Elem().Kind() != reflect.Slice {
628 klog.Errorf("expect %v to be a pointer to slice", s)
631 newReferences := reflect.MakeSlice(s.Type(), len(references), len(references))
632 for i := 0; i < len(references); i++ {
633 if err := setOwnerReference(newReferences.Index(i), &references[i]); err != nil {
634 klog.Errorf("setOwnerReference failed: %v", err)
641 // extractFromTypeMeta extracts pointers to version and kind fields from an object
642 func extractFromTypeMeta(v reflect.Value, a *genericAccessor) error {
643 if err := runtime.FieldPtr(v, "APIVersion", &a.apiVersion); err != nil {
646 if err := runtime.FieldPtr(v, "Kind", &a.kind); err != nil {