github.com/crossplane/upjet@v1.3.0/pkg/controller/conversion/functions.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Crossplane Authors <https://crossplane.io>
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package conversion
     6  
     7  import (
     8  	"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
     9  	"github.com/pkg/errors"
    10  	"k8s.io/apimachinery/pkg/runtime"
    11  
    12  	"github.com/crossplane/upjet/pkg/config/conversion"
    13  	"github.com/crossplane/upjet/pkg/resource"
    14  )
    15  
    16  // RoundTrip round-trips from `src` to `dst` via an unstructured map[string]any
    17  // representation of the `src` object and applies the registered webhook
    18  // conversion functions of this registry.
    19  func (r *registry) RoundTrip(dst, src resource.Terraformed) error { //nolint:gocyclo // considered breaking this according to the converters and I did not like it
    20  	srcMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(src)
    21  	if err != nil {
    22  		return errors.Wrap(err, "cannot convert the conversion source object into the map[string]any representation")
    23  	}
    24  	gvk := dst.GetObjectKind().GroupVersionKind()
    25  	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(srcMap, dst); err != nil {
    26  		return errors.Wrap(err, "cannot convert the map[string]any representation of the source object to the conversion target object")
    27  	}
    28  	// restore the original GVK for the conversion destination
    29  	dst.GetObjectKind().SetGroupVersionKind(gvk)
    30  
    31  	// now we will try to run the registered webhook conversions
    32  	dstMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(dst)
    33  	if err != nil {
    34  		return errors.Wrap(err, "cannot convert the conversion destination object into the map[string]any representation")
    35  	}
    36  	srcPaved := fieldpath.Pave(srcMap)
    37  	dstPaved := fieldpath.Pave(dstMap)
    38  	for _, c := range r.GetConversions(dst) {
    39  		if pc, ok := c.(conversion.PavedConversion); ok {
    40  			if _, err := pc.ConvertPaved(srcPaved, dstPaved); err != nil {
    41  				return errors.Wrapf(err, "cannot apply the PavedConversion for the %q object", dst.GetTerraformResourceType())
    42  			}
    43  		}
    44  	}
    45  	// convert the map[string]any representation of the conversion target back to
    46  	// the original type.
    47  	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(dstMap, dst); err != nil {
    48  		return errors.Wrap(err, "cannot convert the map[string]any representation of the conversion target object to the target object")
    49  	}
    50  
    51  	for _, c := range r.GetConversions(dst) {
    52  		if tc, ok := c.(conversion.ManagedConversion); ok {
    53  			if _, err := tc.ConvertManaged(src, dst); err != nil {
    54  				return errors.Wrapf(err, "cannot apply the TerraformedConversion for the %q object", dst.GetTerraformResourceType())
    55  			}
    56  		}
    57  	}
    58  
    59  	return nil
    60  }
    61  
    62  // RoundTrip round-trips from `src` to `dst` via an unstructured map[string]any
    63  // representation of the `src` object and applies the registered webhook
    64  // conversion functions.
    65  func RoundTrip(dst, src resource.Terraformed) error {
    66  	return instance.RoundTrip(dst, src)
    67  }