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  }