blob: b50337e13f479c5ef60f75bb14547a6fdd2bce20 [file] [log] [blame]
sslobodrd046be82019-01-16 10:02:22 -05001/*
2Copyright 2014 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package meta
18
19import (
20 "fmt"
21 "reflect"
22
sslobodrd046be82019-01-16 10:02:22 -050023 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24 metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
25 "k8s.io/apimachinery/pkg/conversion"
26 "k8s.io/apimachinery/pkg/runtime"
27 "k8s.io/apimachinery/pkg/runtime/schema"
28 "k8s.io/apimachinery/pkg/types"
Stephane Barbarie260a5632019-02-26 16:12:49 -050029 "k8s.io/klog"
sslobodrd046be82019-01-16 10:02:22 -050030)
31
32// errNotList is returned when an object implements the Object style interfaces but not the List style
33// interfaces.
34var errNotList = fmt.Errorf("object does not implement the List interfaces")
35
36var errNotCommon = fmt.Errorf("object does not implement the common interface for accessing the SelfLink")
37
38// CommonAccessor returns a Common interface for the provided object or an error if the object does
39// not provide List.
40func CommonAccessor(obj interface{}) (metav1.Common, error) {
41 switch t := obj.(type) {
42 case List:
43 return t, nil
44 case metav1.ListInterface:
45 return t, nil
46 case ListMetaAccessor:
47 if m := t.GetListMeta(); m != nil {
48 return m, nil
49 }
50 return nil, errNotCommon
51 case metav1.ListMetaAccessor:
52 if m := t.GetListMeta(); m != nil {
53 return m, nil
54 }
55 return nil, errNotCommon
56 case metav1.Object:
57 return t, nil
58 case metav1.ObjectMetaAccessor:
59 if m := t.GetObjectMeta(); m != nil {
60 return m, nil
61 }
62 return nil, errNotCommon
63 default:
64 return nil, errNotCommon
65 }
66}
67
68// ListAccessor returns a List interface for the provided object or an error if the object does
69// not provide List.
70// IMPORTANT: Objects are NOT a superset of lists. Do not use this check to determine whether an
71// object *is* a List.
72func ListAccessor(obj interface{}) (List, error) {
73 switch t := obj.(type) {
74 case List:
75 return t, nil
76 case metav1.ListInterface:
77 return t, nil
78 case ListMetaAccessor:
79 if m := t.GetListMeta(); m != nil {
80 return m, nil
81 }
82 return nil, errNotList
83 case metav1.ListMetaAccessor:
84 if m := t.GetListMeta(); m != nil {
85 return m, nil
86 }
87 return nil, errNotList
88 default:
89 return nil, errNotList
90 }
91}
92
93// errNotObject is returned when an object implements the List style interfaces but not the Object style
94// interfaces.
95var errNotObject = fmt.Errorf("object does not implement the Object interfaces")
96
97// Accessor takes an arbitrary object pointer and returns meta.Interface.
98// obj must be a pointer to an API type. An error is returned if the minimum
99// required fields are missing. Fields that are not required return the default
100// value and are a no-op if set.
101func Accessor(obj interface{}) (metav1.Object, error) {
102 switch t := obj.(type) {
103 case metav1.Object:
104 return t, nil
105 case metav1.ObjectMetaAccessor:
106 if m := t.GetObjectMeta(); m != nil {
107 return m, nil
108 }
109 return nil, errNotObject
110 default:
111 return nil, errNotObject
112 }
113}
114
115// AsPartialObjectMetadata takes the metav1 interface and returns a partial object.
116// TODO: consider making this solely a conversion action.
117func AsPartialObjectMetadata(m metav1.Object) *metav1beta1.PartialObjectMetadata {
118 switch t := m.(type) {
119 case *metav1.ObjectMeta:
120 return &metav1beta1.PartialObjectMetadata{ObjectMeta: *t}
121 default:
122 return &metav1beta1.PartialObjectMetadata{
123 ObjectMeta: metav1.ObjectMeta{
124 Name: m.GetName(),
125 GenerateName: m.GetGenerateName(),
126 Namespace: m.GetNamespace(),
127 SelfLink: m.GetSelfLink(),
128 UID: m.GetUID(),
129 ResourceVersion: m.GetResourceVersion(),
130 Generation: m.GetGeneration(),
131 CreationTimestamp: m.GetCreationTimestamp(),
132 DeletionTimestamp: m.GetDeletionTimestamp(),
133 DeletionGracePeriodSeconds: m.GetDeletionGracePeriodSeconds(),
134 Labels: m.GetLabels(),
135 Annotations: m.GetAnnotations(),
136 OwnerReferences: m.GetOwnerReferences(),
137 Finalizers: m.GetFinalizers(),
138 ClusterName: m.GetClusterName(),
139 Initializers: m.GetInitializers(),
Stephane Barbarie260a5632019-02-26 16:12:49 -0500140 ManagedFields: m.GetManagedFields(),
sslobodrd046be82019-01-16 10:02:22 -0500141 },
142 }
143 }
144}
145
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
150// api conventions).
151func TypeAccessor(obj interface{}) (Type, error) {
152 if typed, ok := obj.(runtime.Object); ok {
153 return objectAccessor{typed}, nil
154 }
155 v, err := conversion.EnforcePtr(obj)
156 if err != nil {
157 return nil, err
158 }
159 t := v.Type()
160 if v.Kind() != reflect.Struct {
161 return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface())
162 }
163
164 typeMeta := v.FieldByName("TypeMeta")
165 if !typeMeta.IsValid() {
166 return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t)
167 }
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)
171 }
172 return a, nil
173}
174
175type objectAccessor struct {
176 runtime.Object
177}
178
179func (obj objectAccessor) GetKind() string {
180 return obj.GetObjectKind().GroupVersionKind().Kind
181}
182
183func (obj objectAccessor) SetKind(kind string) {
184 gvk := obj.GetObjectKind().GroupVersionKind()
185 gvk.Kind = kind
186 obj.GetObjectKind().SetGroupVersionKind(gvk)
187}
188
189func (obj objectAccessor) GetAPIVersion() string {
190 return obj.GetObjectKind().GroupVersionKind().GroupVersion().String()
191}
192
193func (obj objectAccessor) SetAPIVersion(version string) {
194 gvk := obj.GetObjectKind().GroupVersionKind()
195 gv, err := schema.ParseGroupVersion(version)
196 if err != nil {
197 gv = schema.GroupVersion{Version: version}
198 }
199 gvk.Group, gvk.Version = gv.Group, gv.Version
200 obj.GetObjectKind().SetGroupVersionKind(gvk)
201}
202
203// NewAccessor returns a MetadataAccessor that can retrieve
204// or manipulate resource version on objects derived from core API
205// metadata concepts.
206func NewAccessor() MetadataAccessor {
207 return resourceAccessor{}
208}
209
210// resourceAccessor implements ResourceVersioner and SelfLinker.
211type resourceAccessor struct{}
212
213func (resourceAccessor) Kind(obj runtime.Object) (string, error) {
214 return objectAccessor{obj}.GetKind(), nil
215}
216
217func (resourceAccessor) SetKind(obj runtime.Object, kind string) error {
218 objectAccessor{obj}.SetKind(kind)
219 return nil
220}
221
222func (resourceAccessor) APIVersion(obj runtime.Object) (string, error) {
223 return objectAccessor{obj}.GetAPIVersion(), nil
224}
225
226func (resourceAccessor) SetAPIVersion(obj runtime.Object, version string) error {
227 objectAccessor{obj}.SetAPIVersion(version)
228 return nil
229}
230
231func (resourceAccessor) Namespace(obj runtime.Object) (string, error) {
232 accessor, err := Accessor(obj)
233 if err != nil {
234 return "", err
235 }
236 return accessor.GetNamespace(), nil
237}
238
239func (resourceAccessor) SetNamespace(obj runtime.Object, namespace string) error {
240 accessor, err := Accessor(obj)
241 if err != nil {
242 return err
243 }
244 accessor.SetNamespace(namespace)
245 return nil
246}
247
248func (resourceAccessor) Name(obj runtime.Object) (string, error) {
249 accessor, err := Accessor(obj)
250 if err != nil {
251 return "", err
252 }
253 return accessor.GetName(), nil
254}
255
256func (resourceAccessor) SetName(obj runtime.Object, name string) error {
257 accessor, err := Accessor(obj)
258 if err != nil {
259 return err
260 }
261 accessor.SetName(name)
262 return nil
263}
264
265func (resourceAccessor) GenerateName(obj runtime.Object) (string, error) {
266 accessor, err := Accessor(obj)
267 if err != nil {
268 return "", err
269 }
270 return accessor.GetGenerateName(), nil
271}
272
273func (resourceAccessor) SetGenerateName(obj runtime.Object, name string) error {
274 accessor, err := Accessor(obj)
275 if err != nil {
276 return err
277 }
278 accessor.SetGenerateName(name)
279 return nil
280}
281
282func (resourceAccessor) UID(obj runtime.Object) (types.UID, error) {
283 accessor, err := Accessor(obj)
284 if err != nil {
285 return "", err
286 }
287 return accessor.GetUID(), nil
288}
289
290func (resourceAccessor) SetUID(obj runtime.Object, uid types.UID) error {
291 accessor, err := Accessor(obj)
292 if err != nil {
293 return err
294 }
295 accessor.SetUID(uid)
296 return nil
297}
298
299func (resourceAccessor) SelfLink(obj runtime.Object) (string, error) {
300 accessor, err := CommonAccessor(obj)
301 if err != nil {
302 return "", err
303 }
304 return accessor.GetSelfLink(), nil
305}
306
307func (resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error {
308 accessor, err := CommonAccessor(obj)
309 if err != nil {
310 return err
311 }
312 accessor.SetSelfLink(selfLink)
313 return nil
314}
315
316func (resourceAccessor) Labels(obj runtime.Object) (map[string]string, error) {
317 accessor, err := Accessor(obj)
318 if err != nil {
319 return nil, err
320 }
321 return accessor.GetLabels(), nil
322}
323
324func (resourceAccessor) SetLabels(obj runtime.Object, labels map[string]string) error {
325 accessor, err := Accessor(obj)
326 if err != nil {
327 return err
328 }
329 accessor.SetLabels(labels)
330 return nil
331}
332
333func (resourceAccessor) Annotations(obj runtime.Object) (map[string]string, error) {
334 accessor, err := Accessor(obj)
335 if err != nil {
336 return nil, err
337 }
338 return accessor.GetAnnotations(), nil
339}
340
341func (resourceAccessor) SetAnnotations(obj runtime.Object, annotations map[string]string) error {
342 accessor, err := Accessor(obj)
343 if err != nil {
344 return err
345 }
346 accessor.SetAnnotations(annotations)
347 return nil
348}
349
350func (resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) {
351 accessor, err := CommonAccessor(obj)
352 if err != nil {
353 return "", err
354 }
355 return accessor.GetResourceVersion(), nil
356}
357
358func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) error {
359 accessor, err := CommonAccessor(obj)
360 if err != nil {
361 return err
362 }
363 accessor.SetResourceVersion(version)
364 return nil
365}
366
367func (resourceAccessor) Continue(obj runtime.Object) (string, error) {
368 accessor, err := ListAccessor(obj)
369 if err != nil {
370 return "", err
371 }
372 return accessor.GetContinue(), nil
373}
374
375func (resourceAccessor) SetContinue(obj runtime.Object, version string) error {
376 accessor, err := ListAccessor(obj)
377 if err != nil {
378 return err
379 }
380 accessor.SetContinue(version)
381 return nil
382}
383
384// extractFromOwnerReference extracts v to o. v is the OwnerReferences field of an object.
385func extractFromOwnerReference(v reflect.Value, o *metav1.OwnerReference) error {
386 if err := runtime.Field(v, "APIVersion", &o.APIVersion); err != nil {
387 return err
388 }
389 if err := runtime.Field(v, "Kind", &o.Kind); err != nil {
390 return err
391 }
392 if err := runtime.Field(v, "Name", &o.Name); err != nil {
393 return err
394 }
395 if err := runtime.Field(v, "UID", &o.UID); err != nil {
396 return err
397 }
398 var controllerPtr *bool
399 if err := runtime.Field(v, "Controller", &controllerPtr); err != nil {
400 return err
401 }
402 if controllerPtr != nil {
403 controller := *controllerPtr
404 o.Controller = &controller
405 }
406 var blockOwnerDeletionPtr *bool
407 if err := runtime.Field(v, "BlockOwnerDeletion", &blockOwnerDeletionPtr); err != nil {
408 return err
409 }
410 if blockOwnerDeletionPtr != nil {
411 block := *blockOwnerDeletionPtr
412 o.BlockOwnerDeletion = &block
413 }
414 return nil
415}
416
417// setOwnerReference sets v to o. v is the OwnerReferences field of an object.
418func setOwnerReference(v reflect.Value, o *metav1.OwnerReference) error {
419 if err := runtime.SetField(o.APIVersion, v, "APIVersion"); err != nil {
420 return err
421 }
422 if err := runtime.SetField(o.Kind, v, "Kind"); err != nil {
423 return err
424 }
425 if err := runtime.SetField(o.Name, v, "Name"); err != nil {
426 return err
427 }
428 if err := runtime.SetField(o.UID, v, "UID"); err != nil {
429 return err
430 }
431 if o.Controller != nil {
432 controller := *(o.Controller)
433 if err := runtime.SetField(&controller, v, "Controller"); err != nil {
434 return err
435 }
436 }
437 if o.BlockOwnerDeletion != nil {
438 block := *(o.BlockOwnerDeletion)
439 if err := runtime.SetField(&block, v, "BlockOwnerDeletion"); err != nil {
440 return err
441 }
442 }
443 return nil
444}
445
446// genericAccessor contains pointers to strings that can modify an arbitrary
447// struct and implements the Accessor interface.
448type genericAccessor struct {
449 namespace *string
450 name *string
451 generateName *string
452 uid *types.UID
453 apiVersion *string
454 kind *string
455 resourceVersion *string
456 selfLink *string
457 creationTimestamp *metav1.Time
458 deletionTimestamp **metav1.Time
459 labels *map[string]string
460 annotations *map[string]string
461 ownerReferences reflect.Value
462 finalizers *[]string
463}
464
465func (a genericAccessor) GetNamespace() string {
466 if a.namespace == nil {
467 return ""
468 }
469 return *a.namespace
470}
471
472func (a genericAccessor) SetNamespace(namespace string) {
473 if a.namespace == nil {
474 return
475 }
476 *a.namespace = namespace
477}
478
479func (a genericAccessor) GetName() string {
480 if a.name == nil {
481 return ""
482 }
483 return *a.name
484}
485
486func (a genericAccessor) SetName(name string) {
487 if a.name == nil {
488 return
489 }
490 *a.name = name
491}
492
493func (a genericAccessor) GetGenerateName() string {
494 if a.generateName == nil {
495 return ""
496 }
497 return *a.generateName
498}
499
500func (a genericAccessor) SetGenerateName(generateName string) {
501 if a.generateName == nil {
502 return
503 }
504 *a.generateName = generateName
505}
506
507func (a genericAccessor) GetUID() types.UID {
508 if a.uid == nil {
509 return ""
510 }
511 return *a.uid
512}
513
514func (a genericAccessor) SetUID(uid types.UID) {
515 if a.uid == nil {
516 return
517 }
518 *a.uid = uid
519}
520
521func (a genericAccessor) GetAPIVersion() string {
522 return *a.apiVersion
523}
524
525func (a genericAccessor) SetAPIVersion(version string) {
526 *a.apiVersion = version
527}
528
529func (a genericAccessor) GetKind() string {
530 return *a.kind
531}
532
533func (a genericAccessor) SetKind(kind string) {
534 *a.kind = kind
535}
536
537func (a genericAccessor) GetResourceVersion() string {
538 return *a.resourceVersion
539}
540
541func (a genericAccessor) SetResourceVersion(version string) {
542 *a.resourceVersion = version
543}
544
545func (a genericAccessor) GetSelfLink() string {
546 return *a.selfLink
547}
548
549func (a genericAccessor) SetSelfLink(selfLink string) {
550 *a.selfLink = selfLink
551}
552
553func (a genericAccessor) GetCreationTimestamp() metav1.Time {
554 return *a.creationTimestamp
555}
556
557func (a genericAccessor) SetCreationTimestamp(timestamp metav1.Time) {
558 *a.creationTimestamp = timestamp
559}
560
561func (a genericAccessor) GetDeletionTimestamp() *metav1.Time {
562 return *a.deletionTimestamp
563}
564
565func (a genericAccessor) SetDeletionTimestamp(timestamp *metav1.Time) {
566 *a.deletionTimestamp = timestamp
567}
568
569func (a genericAccessor) GetLabels() map[string]string {
570 if a.labels == nil {
571 return nil
572 }
573 return *a.labels
574}
575
576func (a genericAccessor) SetLabels(labels map[string]string) {
577 *a.labels = labels
578}
579
580func (a genericAccessor) GetAnnotations() map[string]string {
581 if a.annotations == nil {
582 return nil
583 }
584 return *a.annotations
585}
586
587func (a genericAccessor) SetAnnotations(annotations map[string]string) {
588 if a.annotations == nil {
589 emptyAnnotations := make(map[string]string)
590 a.annotations = &emptyAnnotations
591 }
592 *a.annotations = annotations
593}
594
595func (a genericAccessor) GetFinalizers() []string {
596 if a.finalizers == nil {
597 return nil
598 }
599 return *a.finalizers
600}
601
602func (a genericAccessor) SetFinalizers(finalizers []string) {
603 *a.finalizers = finalizers
604}
605
606func (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)
611 return ret
612 }
613 s = s.Elem()
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)
619 return ret
620 }
621 }
622 return ret
623}
624
625func (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)
629 }
630 s = s.Elem()
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)
635 return
636 }
637 }
638 s.Set(newReferences)
639}
640
641// extractFromTypeMeta extracts pointers to version and kind fields from an object
642func extractFromTypeMeta(v reflect.Value, a *genericAccessor) error {
643 if err := runtime.FieldPtr(v, "APIVersion", &a.apiVersion); err != nil {
644 return err
645 }
646 if err := runtime.FieldPtr(v, "Kind", &a.kind); err != nil {
647 return err
648 }
649 return nil
650}