k8s.io/apiserver@v0.31.1/pkg/admission/conversion.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 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 admission 18 19 import ( 20 "k8s.io/apimachinery/pkg/runtime" 21 "k8s.io/apimachinery/pkg/runtime/schema" 22 ) 23 24 // VersionedAttributes is a wrapper around the original admission attributes, adding versioned 25 // variants of the object and old object. 26 type VersionedAttributes struct { 27 // Attributes holds the original admission attributes 28 Attributes 29 // VersionedOldObject holds Attributes.OldObject (if non-nil), converted to VersionedKind. 30 // It must never be mutated. 31 VersionedOldObject runtime.Object 32 // VersionedObject holds Attributes.Object (if non-nil), converted to VersionedKind. 33 // If mutated, Dirty must be set to true by the mutator. 34 VersionedObject runtime.Object 35 // VersionedKind holds the fully qualified kind 36 VersionedKind schema.GroupVersionKind 37 // Dirty indicates VersionedObject has been modified since being converted from Attributes.Object 38 Dirty bool 39 } 40 41 // GetObject overrides the Attributes.GetObject() 42 func (v *VersionedAttributes) GetObject() runtime.Object { 43 if v.VersionedObject != nil { 44 return v.VersionedObject 45 } 46 return v.Attributes.GetObject() 47 } 48 49 // ConvertToGVK converts object to the desired gvk. 50 func ConvertToGVK(obj runtime.Object, gvk schema.GroupVersionKind, o ObjectInterfaces) (runtime.Object, error) { 51 // Unlike other resources, custom resources do not have internal version, so 52 // if obj is a custom resource, it should not need conversion. 53 if obj.GetObjectKind().GroupVersionKind() == gvk { 54 return obj, nil 55 } 56 out, err := o.GetObjectCreater().New(gvk) 57 if err != nil { 58 return nil, err 59 } 60 err = o.GetObjectConvertor().Convert(obj, out, nil) 61 if err != nil { 62 return nil, err 63 } 64 // Explicitly set the GVK 65 out.GetObjectKind().SetGroupVersionKind(gvk) 66 return out, nil 67 } 68 69 // NewVersionedAttributes returns versioned attributes with the old and new object (if non-nil) converted to the requested kind 70 func NewVersionedAttributes(attr Attributes, gvk schema.GroupVersionKind, o ObjectInterfaces) (*VersionedAttributes, error) { 71 // convert the old and new objects to the requested version 72 versionedAttr := &VersionedAttributes{ 73 Attributes: attr, 74 VersionedKind: gvk, 75 } 76 if oldObj := attr.GetOldObject(); oldObj != nil { 77 out, err := ConvertToGVK(oldObj, gvk, o) 78 if err != nil { 79 return nil, err 80 } 81 versionedAttr.VersionedOldObject = out 82 } 83 if obj := attr.GetObject(); obj != nil { 84 out, err := ConvertToGVK(obj, gvk, o) 85 if err != nil { 86 return nil, err 87 } 88 versionedAttr.VersionedObject = out 89 } 90 return versionedAttr, nil 91 } 92 93 // ConvertVersionedAttributes converts VersionedObject and VersionedOldObject to the specified kind, if needed. 94 // If attr.VersionedKind already matches the requested kind, no conversion is performed. 95 // If conversion is required: 96 // * attr.VersionedObject is used as the source for the new object if Dirty=true (and is round-tripped through attr.Attributes.Object, clearing Dirty in the process) 97 // * attr.Attributes.Object is used as the source for the new object if Dirty=false 98 // * attr.Attributes.OldObject is used as the source for the old object 99 func ConvertVersionedAttributes(attr *VersionedAttributes, gvk schema.GroupVersionKind, o ObjectInterfaces) error { 100 // we already have the desired kind, we're done 101 if attr.VersionedKind == gvk { 102 return nil 103 } 104 105 // convert the original old object to the desired GVK 106 if oldObj := attr.Attributes.GetOldObject(); oldObj != nil { 107 out, err := ConvertToGVK(oldObj, gvk, o) 108 if err != nil { 109 return err 110 } 111 attr.VersionedOldObject = out 112 } 113 114 if attr.VersionedObject != nil { 115 // convert the existing versioned object to internal 116 if attr.Dirty { 117 err := o.GetObjectConvertor().Convert(attr.VersionedObject, attr.Attributes.GetObject(), nil) 118 if err != nil { 119 return err 120 } 121 } 122 123 // and back to external 124 out, err := ConvertToGVK(attr.Attributes.GetObject(), gvk, o) 125 if err != nil { 126 return err 127 } 128 attr.VersionedObject = out 129 } 130 131 // Remember we converted to this version 132 attr.VersionedKind = gvk 133 attr.Dirty = false 134 135 return nil 136 }