github.com/crossplane/upjet@v1.3.0/pkg/migration/registry.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Crossplane Authors <https://crossplane.io>
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package migration
     6  
     7  import (
     8  	"regexp"
     9  
    10  	"github.com/crossplane/crossplane-runtime/pkg/resource"
    11  	xpv1 "github.com/crossplane/crossplane/apis/apiextensions/v1"
    12  	xpmetav1 "github.com/crossplane/crossplane/apis/pkg/meta/v1"
    13  	xpmetav1alpha1 "github.com/crossplane/crossplane/apis/pkg/meta/v1alpha1"
    14  	xppkgv1 "github.com/crossplane/crossplane/apis/pkg/v1"
    15  	xppkgv1beta1 "github.com/crossplane/crossplane/apis/pkg/v1beta1"
    16  	"github.com/pkg/errors"
    17  	"k8s.io/apimachinery/pkg/runtime"
    18  	"k8s.io/apimachinery/pkg/runtime/schema"
    19  )
    20  
    21  var (
    22  	// AllCompositions matches all v1.Composition names.
    23  	AllCompositions = regexp.MustCompile(`.*`)
    24  	// AllConfigurations matches all metav1.Configuration names.
    25  	AllConfigurations = regexp.MustCompile(`.*`)
    26  	// CrossplaneLockName is the Crossplane package lock's `metadata.name`
    27  	CrossplaneLockName = regexp.MustCompile(`^lock$`)
    28  )
    29  
    30  const (
    31  	errAddToScheme           = "failed to register types with the registry's scheme"
    32  	errFmtNewObject          = "failed to instantiate a new runtime.Object using runtime.Scheme for: %s"
    33  	errFmtNotManagedResource = "specified GVK does not belong to a managed resource: %s"
    34  )
    35  
    36  type patchSetConverter struct {
    37  	// re is the regular expression against which a Composition's name
    38  	// will be matched to determine whether the conversion function
    39  	// will be invoked.
    40  	re *regexp.Regexp
    41  	// converter is the PatchSetConverter to be run on the Composition's
    42  	// patch sets.
    43  	converter PatchSetConverter
    44  }
    45  
    46  type configurationMetadataConverter struct {
    47  	// re is the regular expression against which a Configuration's name
    48  	// will be matched to determine whether the conversion function
    49  	// will be invoked.
    50  	re *regexp.Regexp
    51  	// converter is the ConfigurationMetadataConverter to be run on the Configuration's
    52  	// metadata.
    53  	converter ConfigurationMetadataConverter
    54  }
    55  
    56  type configurationPackageConverter struct {
    57  	// re is the regular expression against which a Configuration package's
    58  	// reference will be matched to determine whether the conversion function
    59  	// will be invoked.
    60  	re *regexp.Regexp
    61  	// converter is the ConfigurationPackageConverter to be run on the
    62  	// Configuration package.
    63  	converter ConfigurationPackageConverter
    64  }
    65  
    66  type providerPackageConverter struct {
    67  	// re is the regular expression against which a Provider package's
    68  	// reference will be matched to determine whether the conversion function
    69  	// will be invoked.
    70  	re *regexp.Regexp
    71  	// converter is the ProviderPackageConverter to be run on the
    72  	// Provider package.
    73  	converter ProviderPackageConverter
    74  }
    75  
    76  type packageLockConverter struct {
    77  	// re is the regular expression against which a package Lock's name
    78  	// will be matched to determine whether the conversion function
    79  	// will be invoked.
    80  	re *regexp.Regexp
    81  	// converter is the PackageLockConverter to be run on the package Lock.
    82  	converter PackageLockConverter
    83  }
    84  
    85  // Registry is a registry of `migration.Converter`s keyed with
    86  // the associated `schema.GroupVersionKind`s and an associated
    87  // runtime.Scheme with which the corresponding types are registered.
    88  type Registry struct {
    89  	unstructuredPreProcessors      map[Category][]UnstructuredPreProcessor
    90  	resourcePreProcessors          []ManagedPreProcessor
    91  	resourceConverters             map[schema.GroupVersionKind]ResourceConverter
    92  	templateConverters             map[schema.GroupVersionKind]ComposedTemplateConverter
    93  	patchSetConverters             []patchSetConverter
    94  	configurationMetaConverters    []configurationMetadataConverter
    95  	configurationPackageConverters []configurationPackageConverter
    96  	providerPackageConverters      []providerPackageConverter
    97  	packageLockConverters          []packageLockConverter
    98  	categoricalConverters          map[Category][]CategoricalConverter
    99  	scheme                         *runtime.Scheme
   100  	claimTypes                     []schema.GroupVersionKind
   101  	compositeTypes                 []schema.GroupVersionKind
   102  }
   103  
   104  // NewRegistry returns a new Registry initialized with
   105  // the specified runtime.Scheme.
   106  func NewRegistry(scheme *runtime.Scheme) *Registry {
   107  	return &Registry{
   108  		resourceConverters:        make(map[schema.GroupVersionKind]ResourceConverter),
   109  		templateConverters:        make(map[schema.GroupVersionKind]ComposedTemplateConverter),
   110  		categoricalConverters:     make(map[Category][]CategoricalConverter),
   111  		unstructuredPreProcessors: make(map[Category][]UnstructuredPreProcessor),
   112  		scheme:                    scheme,
   113  	}
   114  }
   115  
   116  // make sure a converter is being registered for a managed resource,
   117  // and it's registered with our runtime scheme.
   118  // This will be needed, during runtime, for properly converting resources.
   119  func (r *Registry) assertManagedResource(gvk schema.GroupVersionKind) {
   120  	obj, err := r.scheme.New(gvk)
   121  	if err != nil {
   122  		panic(errors.Wrapf(err, errFmtNewObject, gvk))
   123  	}
   124  	if _, ok := obj.(resource.Managed); !ok {
   125  		panic(errors.Errorf(errFmtNotManagedResource, gvk))
   126  	}
   127  }
   128  
   129  // RegisterResourceConverter registers the specified ResourceConverter
   130  // for the specified GVK with this Registry.
   131  func (r *Registry) RegisterResourceConverter(gvk schema.GroupVersionKind, conv ResourceConverter) {
   132  	r.assertManagedResource(gvk)
   133  	r.resourceConverters[gvk] = conv
   134  }
   135  
   136  // RegisterTemplateConverter registers the specified ComposedTemplateConverter
   137  // for the specified GVK with this Registry.
   138  func (r *Registry) RegisterTemplateConverter(gvk schema.GroupVersionKind, conv ComposedTemplateConverter) {
   139  	r.assertManagedResource(gvk)
   140  	r.templateConverters[gvk] = conv
   141  }
   142  
   143  // RegisterCompositionConverter is a convenience method for registering both
   144  // a ResourceConverter and a ComposedTemplateConverter that act on the same
   145  // managed resource kind and are implemented by the same type.
   146  func (r *Registry) RegisterCompositionConverter(gvk schema.GroupVersionKind, conv CompositionConverter) {
   147  	r.RegisterResourceConverter(gvk, conv)
   148  	r.RegisterTemplateConverter(gvk, conv)
   149  }
   150  
   151  // RegisterPatchSetConverter registers the given PatchSetConverter for
   152  // the compositions whose name match the given regular expression.
   153  func (r *Registry) RegisterPatchSetConverter(re *regexp.Regexp, psConv PatchSetConverter) {
   154  	r.patchSetConverters = append(r.patchSetConverters, patchSetConverter{
   155  		re:        re,
   156  		converter: psConv,
   157  	})
   158  }
   159  
   160  // RegisterConfigurationMetadataConverter registers the given ConfigurationMetadataConverter
   161  // for the configurations whose name match the given regular expression.
   162  func (r *Registry) RegisterConfigurationMetadataConverter(re *regexp.Regexp, confConv ConfigurationMetadataConverter) {
   163  	r.configurationMetaConverters = append(r.configurationMetaConverters, configurationMetadataConverter{
   164  		re:        re,
   165  		converter: confConv,
   166  	})
   167  }
   168  
   169  // RegisterConfigurationMetadataV1ConversionFunction registers the specified
   170  // ConfigurationMetadataV1ConversionFn for the v1 configurations whose name match
   171  // the given regular expression.
   172  func (r *Registry) RegisterConfigurationMetadataV1ConversionFunction(re *regexp.Regexp, confConversionFn ConfigurationMetadataV1ConversionFn) {
   173  	r.RegisterConfigurationMetadataConverter(re, &delegatingConverter{
   174  		confMetaV1Fn: confConversionFn,
   175  	})
   176  }
   177  
   178  // RegisterConfigurationMetadataV1Alpha1ConversionFunction registers the specified
   179  // ConfigurationMetadataV1Alpha1ConversionFn for the v1alpha1 configurations
   180  // whose name match the given regular expression.
   181  func (r *Registry) RegisterConfigurationMetadataV1Alpha1ConversionFunction(re *regexp.Regexp, confConversionFn ConfigurationMetadataV1Alpha1ConversionFn) {
   182  	r.RegisterConfigurationMetadataConverter(re, &delegatingConverter{
   183  		confMetaV1Alpha1Fn: confConversionFn,
   184  	})
   185  }
   186  
   187  // RegisterConfigurationPackageConverter registers the specified
   188  // ConfigurationPackageConverter for the Configuration v1 packages whose reference
   189  // match the given regular expression.
   190  func (r *Registry) RegisterConfigurationPackageConverter(re *regexp.Regexp, pkgConv ConfigurationPackageConverter) {
   191  	r.configurationPackageConverters = append(r.configurationPackageConverters, configurationPackageConverter{
   192  		re:        re,
   193  		converter: pkgConv,
   194  	})
   195  }
   196  
   197  // RegisterConfigurationPackageV1ConversionFunction registers the specified
   198  // ConfigurationPackageV1ConversionFn for the Configuration v1 packages whose reference
   199  // match the given regular expression.
   200  func (r *Registry) RegisterConfigurationPackageV1ConversionFunction(re *regexp.Regexp, confConversionFn ConfigurationPackageV1ConversionFn) {
   201  	r.RegisterConfigurationPackageConverter(re, &delegatingConverter{
   202  		confPackageV1Fn: confConversionFn,
   203  	})
   204  }
   205  
   206  // RegisterProviderPackageConverter registers the given ProviderPackageConverter
   207  // for the provider packages whose references match the given regular expression.
   208  func (r *Registry) RegisterProviderPackageConverter(re *regexp.Regexp, pkgConv ProviderPackageConverter) {
   209  	r.providerPackageConverters = append(r.providerPackageConverters, providerPackageConverter{
   210  		re:        re,
   211  		converter: pkgConv,
   212  	})
   213  }
   214  
   215  // RegisterProviderPackageV1ConversionFunction registers the specified
   216  // ProviderPackageV1ConversionFn for the provider v1 packages whose reference
   217  // match the given regular expression.
   218  func (r *Registry) RegisterProviderPackageV1ConversionFunction(re *regexp.Regexp, pkgConversionFn ProviderPackageV1ConversionFn) {
   219  	r.RegisterProviderPackageConverter(re, &delegatingConverter{
   220  		providerPackageV1Fn: pkgConversionFn,
   221  	})
   222  }
   223  
   224  // RegisterPackageLockConverter registers the given PackageLockConverter.
   225  func (r *Registry) RegisterPackageLockConverter(re *regexp.Regexp, lockConv PackageLockConverter) {
   226  	r.packageLockConverters = append(r.packageLockConverters, packageLockConverter{
   227  		re:        re,
   228  		converter: lockConv,
   229  	})
   230  }
   231  
   232  // RegisterCategoricalConverter registers the specified CategoricalConverter
   233  // for the specified Category of resources.
   234  func (r *Registry) RegisterCategoricalConverter(c Category, converter CategoricalConverter) {
   235  	r.categoricalConverters[c] = append(r.categoricalConverters[c], converter)
   236  }
   237  
   238  // RegisterCategoricalConverterFunction registers the specified
   239  // CategoricalConverterFunctionFn for the specified Category.
   240  func (r *Registry) RegisterCategoricalConverterFunction(c Category, converterFn CategoricalConverterFunctionFn) {
   241  	r.RegisterCategoricalConverter(c, &delegatingConverter{
   242  		categoricalConverterFn: converterFn,
   243  	})
   244  }
   245  
   246  // RegisterPackageLockV1Beta1ConversionFunction registers the specified
   247  // RegisterPackageLockV1Beta1ConversionFunction for the package v1beta1 locks.
   248  func (r *Registry) RegisterPackageLockV1Beta1ConversionFunction(re *regexp.Regexp, lockConversionFn PackageLockV1Beta1ConversionFn) {
   249  	r.RegisterPackageLockConverter(re, &delegatingConverter{
   250  		packageLockV1Beta1Fn: lockConversionFn,
   251  	})
   252  }
   253  
   254  // AddToScheme registers types with this Registry's runtime.Scheme
   255  func (r *Registry) AddToScheme(sb func(scheme *runtime.Scheme) error) error {
   256  	return errors.Wrap(sb(r.scheme), errAddToScheme)
   257  }
   258  
   259  // AddCompositionTypes registers the Composition types with
   260  // the registry's scheme. Only the v1 API of Compositions
   261  // is currently supported.
   262  func (r *Registry) AddCompositionTypes() error {
   263  	return r.AddToScheme(xpv1.AddToScheme)
   264  }
   265  
   266  // AddCrossplanePackageTypes registers the
   267  // {Provider,Configuration,Lock, etc.}.pkg types with
   268  // the registry's scheme.
   269  func (r *Registry) AddCrossplanePackageTypes() error {
   270  	if err := r.AddToScheme(xppkgv1beta1.AddToScheme); err != nil {
   271  		return err
   272  	}
   273  	return r.AddToScheme(xppkgv1.AddToScheme)
   274  }
   275  
   276  // AddClaimType registers a new composite resource claim type
   277  // with the given GVK
   278  func (r *Registry) AddClaimType(gvk schema.GroupVersionKind) {
   279  	r.claimTypes = append(r.claimTypes, gvk)
   280  }
   281  
   282  // AddCompositeType registers a new composite resource type with the given GVK
   283  func (r *Registry) AddCompositeType(gvk schema.GroupVersionKind) {
   284  	r.compositeTypes = append(r.compositeTypes, gvk)
   285  }
   286  
   287  // GetManagedResourceGVKs returns a list of all registered managed resource
   288  // GVKs
   289  func (r *Registry) GetManagedResourceGVKs() []schema.GroupVersionKind {
   290  	gvks := make([]schema.GroupVersionKind, 0, len(r.resourceConverters)+len(r.templateConverters))
   291  	for gvk := range r.resourceConverters {
   292  		gvks = append(gvks, gvk)
   293  	}
   294  	for gvk := range r.templateConverters {
   295  		gvks = append(gvks, gvk)
   296  	}
   297  	return gvks
   298  }
   299  
   300  // GetCompositionGVKs returns the registered Composition GVKs.
   301  func (r *Registry) GetCompositionGVKs() []schema.GroupVersionKind {
   302  	// Composition types are registered with this registry's scheme
   303  	if _, ok := r.scheme.AllKnownTypes()[xpv1.CompositionGroupVersionKind]; ok {
   304  		return []schema.GroupVersionKind{xpv1.CompositionGroupVersionKind}
   305  	}
   306  	return nil
   307  }
   308  
   309  // GetCrossplanePackageGVKs returns the registered Crossplane package GVKs.
   310  func (r *Registry) GetCrossplanePackageGVKs() []schema.GroupVersionKind {
   311  	if r.scheme.AllKnownTypes()[xppkgv1.ProviderGroupVersionKind] == nil ||
   312  		r.scheme.AllKnownTypes()[xppkgv1.ConfigurationGroupVersionKind] == nil ||
   313  		r.scheme.AllKnownTypes()[xppkgv1beta1.LockGroupVersionKind] == nil {
   314  		return nil
   315  	}
   316  	return []schema.GroupVersionKind{
   317  		xppkgv1.ProviderGroupVersionKind,
   318  		xppkgv1.ConfigurationGroupVersionKind,
   319  		xppkgv1beta1.LockGroupVersionKind,
   320  	}
   321  }
   322  
   323  // GetAllRegisteredGVKs returns a list of registered GVKs
   324  // including v1.CompositionGroupVersionKind,
   325  // metav1.ConfigurationGroupVersionKind,
   326  // metav1alpha1.ConfigurationGroupVersionKind
   327  // pkg.ConfigurationGroupVersionKind,
   328  // pkg.ProviderGroupVersionKind,
   329  // pkg.LockGroupVersionKind.
   330  func (r *Registry) GetAllRegisteredGVKs() []schema.GroupVersionKind {
   331  	gvks := make([]schema.GroupVersionKind, 0, len(r.claimTypes)+len(r.compositeTypes)+len(r.resourceConverters)+len(r.templateConverters)+1)
   332  	gvks = append(gvks, r.claimTypes...)
   333  	gvks = append(gvks, r.compositeTypes...)
   334  	gvks = append(gvks, r.GetManagedResourceGVKs()...)
   335  	gvks = append(gvks, xpv1.CompositionGroupVersionKind, xpmetav1.ConfigurationGroupVersionKind, xpmetav1alpha1.ConfigurationGroupVersionKind,
   336  		xppkgv1.ConfigurationGroupVersionKind, xppkgv1.ProviderGroupVersionKind, xppkgv1beta1.LockGroupVersionKind)
   337  	return gvks
   338  }
   339  
   340  // ResourceConversionFn is a function that converts the specified migration
   341  // source managed resource to one or more migration target managed resources.
   342  type ResourceConversionFn func(mg resource.Managed) ([]resource.Managed, error)
   343  
   344  // ComposedTemplateConversionFn is a function that converts from the specified
   345  // migration source v1.ComposedTemplate to one or more migration
   346  // target v1.ComposedTemplates.
   347  type ComposedTemplateConversionFn func(sourceTemplate xpv1.ComposedTemplate, convertedTemplates ...*xpv1.ComposedTemplate) error
   348  
   349  // PatchSetsConversionFn is a function that converts
   350  // the `spec.patchSets` of a Composition from the migration source provider's
   351  // schema to the migration target provider's schema.
   352  type PatchSetsConversionFn func(psMap map[string]*xpv1.PatchSet) error
   353  
   354  // ConfigurationMetadataV1ConversionFn is a function that converts the specified
   355  // migration source Configuration v1 metadata to the migration target
   356  // Configuration metadata.
   357  type ConfigurationMetadataV1ConversionFn func(configuration *xpmetav1.Configuration) error
   358  
   359  // ConfigurationMetadataV1Alpha1ConversionFn is a function that converts the specified
   360  // migration source Configuration v1alpha1 metadata to the migration target
   361  // Configuration metadata.
   362  type ConfigurationMetadataV1Alpha1ConversionFn func(configuration *xpmetav1alpha1.Configuration) error
   363  
   364  // PackageLockV1Beta1ConversionFn is a function that converts the specified
   365  // migration source package v1beta1 lock to the migration target
   366  // package lock.
   367  type PackageLockV1Beta1ConversionFn func(pkg *xppkgv1beta1.Lock) error
   368  
   369  // ConfigurationPackageV1ConversionFn is a function that converts the specified
   370  // migration source Configuration v1 package to the migration target
   371  // Configuration package(s).
   372  type ConfigurationPackageV1ConversionFn func(pkg *xppkgv1.Configuration) error
   373  
   374  // ProviderPackageV1ConversionFn is a function that converts the specified
   375  // migration source provider v1 package to the migration target
   376  // Provider package(s).
   377  type ProviderPackageV1ConversionFn func(pkg xppkgv1.Provider) ([]xppkgv1.Provider, error)
   378  
   379  // CategoricalConverterFunctionFn is a function that converts resources of a
   380  // Category. Because it receives an unstructured argument, it should be
   381  // used for implementing generic conversion functions acting on a specific
   382  // category.
   383  type CategoricalConverterFunctionFn func(u *UnstructuredWithMetadata) error
   384  
   385  type delegatingConverter struct {
   386  	rFn                    ResourceConversionFn
   387  	cmpFn                  ComposedTemplateConversionFn
   388  	psFn                   PatchSetsConversionFn
   389  	confMetaV1Fn           ConfigurationMetadataV1ConversionFn
   390  	confMetaV1Alpha1Fn     ConfigurationMetadataV1Alpha1ConversionFn
   391  	confPackageV1Fn        ConfigurationPackageV1ConversionFn
   392  	providerPackageV1Fn    ProviderPackageV1ConversionFn
   393  	packageLockV1Beta1Fn   PackageLockV1Beta1ConversionFn
   394  	categoricalConverterFn CategoricalConverterFunctionFn
   395  }
   396  
   397  func (d *delegatingConverter) Convert(u *UnstructuredWithMetadata) error {
   398  	if d.categoricalConverterFn == nil {
   399  		return nil
   400  	}
   401  	return d.categoricalConverterFn(u)
   402  }
   403  
   404  func (d *delegatingConverter) ConfigurationPackageV1(pkg *xppkgv1.Configuration) error {
   405  	if d.confPackageV1Fn == nil {
   406  		return nil
   407  	}
   408  	return d.confPackageV1Fn(pkg)
   409  }
   410  
   411  func (d *delegatingConverter) PackageLockV1Beta1(lock *xppkgv1beta1.Lock) error {
   412  	if d.packageLockV1Beta1Fn == nil {
   413  		return nil
   414  	}
   415  	return d.packageLockV1Beta1Fn(lock)
   416  }
   417  
   418  func (d *delegatingConverter) ProviderPackageV1(pkg xppkgv1.Provider) ([]xppkgv1.Provider, error) {
   419  	if d.providerPackageV1Fn == nil {
   420  		return []xppkgv1.Provider{pkg}, nil
   421  	}
   422  	return d.providerPackageV1Fn(pkg)
   423  }
   424  
   425  func (d *delegatingConverter) ConfigurationMetadataV1(c *xpmetav1.Configuration) error {
   426  	if d.confMetaV1Fn == nil {
   427  		return nil
   428  	}
   429  	return d.confMetaV1Fn(c)
   430  }
   431  
   432  func (d *delegatingConverter) ConfigurationMetadataV1Alpha1(c *xpmetav1alpha1.Configuration) error {
   433  	if d.confMetaV1Alpha1Fn == nil {
   434  		return nil
   435  	}
   436  	return d.confMetaV1Alpha1Fn(c)
   437  }
   438  
   439  func (d *delegatingConverter) PatchSets(psMap map[string]*xpv1.PatchSet) error {
   440  	if d.psFn == nil {
   441  		return nil
   442  	}
   443  	return d.psFn(psMap)
   444  }
   445  
   446  // Resource takes a managed resource and returns zero or more managed
   447  // resources to be created by calling the configured ResourceConversionFn.
   448  func (d *delegatingConverter) Resource(mg resource.Managed) ([]resource.Managed, error) {
   449  	if d.rFn == nil {
   450  		return []resource.Managed{mg}, nil
   451  	}
   452  	return d.rFn(mg)
   453  }
   454  
   455  // ComposedTemplate converts from the specified migration source
   456  // v1.ComposedTemplate to the migration target schema by calling the configured
   457  // ComposedTemplateConversionFn.
   458  func (d *delegatingConverter) ComposedTemplate(sourceTemplate xpv1.ComposedTemplate, convertedTemplates ...*xpv1.ComposedTemplate) error {
   459  	if d.cmpFn == nil {
   460  		return nil
   461  	}
   462  	return d.cmpFn(sourceTemplate, convertedTemplates...)
   463  }
   464  
   465  // DefaultCompositionConverter is a generic composition converter
   466  // conversionMap: is fieldpath map for conversion
   467  // Key of the conversionMap points to the source field
   468  // Value of the conversionMap points to the target field
   469  // Example: "spec.forProvider.assumeRolePolicyDocument": "spec.forProvider.assumeRolePolicy",
   470  // fns are functions that manipulate the patchsets
   471  func DefaultCompositionConverter(conversionMap map[string]string, fns ...func(sourceTemplate xpv1.ComposedTemplate) ([]xpv1.Patch, error)) ComposedTemplateConversionFn {
   472  	return func(sourceTemplate xpv1.ComposedTemplate, convertedTemplates ...*xpv1.ComposedTemplate) error {
   473  		var patchesToAdd []xpv1.Patch
   474  		for _, fn := range fns {
   475  			patches, err := fn(sourceTemplate)
   476  			if err != nil {
   477  				return errors.Wrap(err, "cannot run the patch sets converter function")
   478  			}
   479  			patchesToAdd = append(patchesToAdd, patches...)
   480  		}
   481  		patchesToAdd = append(patchesToAdd, ConvertComposedTemplatePatchesMap(sourceTemplate, conversionMap)...)
   482  		for i := range convertedTemplates {
   483  			convertedTemplates[i].Patches = append(convertedTemplates[i].Patches, patchesToAdd...)
   484  		}
   485  		return nil
   486  	}
   487  }
   488  
   489  // RegisterAPIConversionFunctions registers the supplied ResourceConversionFn and
   490  // ComposedTemplateConversionFn for the specified GVK, and the supplied
   491  // PatchSetsConversionFn for all the discovered Compositions.
   492  // The specified GVK must belong to a Crossplane managed resource type and
   493  // the type must already have been registered with this registry's scheme
   494  // by calling Registry.AddToScheme.
   495  func (r *Registry) RegisterAPIConversionFunctions(gvk schema.GroupVersionKind, rFn ResourceConversionFn, cmpFn ComposedTemplateConversionFn, psFn PatchSetsConversionFn) {
   496  	d := &delegatingConverter{
   497  		rFn:   rFn,
   498  		cmpFn: cmpFn,
   499  		psFn:  psFn,
   500  	}
   501  	r.RegisterPatchSetConverter(AllCompositions, d)
   502  	r.RegisterCompositionConverter(gvk, d)
   503  }
   504  
   505  // RegisterConversionFunctions registers the supplied ResourceConversionFn and
   506  // ComposedTemplateConversionFn for the specified GVK, and the supplied
   507  // PatchSetsConversionFn for all the discovered Compositions.
   508  // The specified GVK must belong to a Crossplane managed resource type and
   509  // the type must already have been registered with this registry's scheme
   510  // by calling Registry.AddToScheme.
   511  // Deprecated: Use RegisterAPIConversionFunctions instead.
   512  func (r *Registry) RegisterConversionFunctions(gvk schema.GroupVersionKind, rFn ResourceConversionFn, cmpFn ComposedTemplateConversionFn, psFn PatchSetsConversionFn) {
   513  	r.RegisterAPIConversionFunctions(gvk, rFn, cmpFn, psFn)
   514  }
   515  
   516  func (r *Registry) RegisterPreProcessor(category Category, pp UnstructuredPreProcessor) {
   517  	r.unstructuredPreProcessors[category] = append(r.unstructuredPreProcessors[category], pp)
   518  }
   519  
   520  // PreProcessor is a function type to convert pre-processor functions to
   521  // UnstructuredPreProcessor.
   522  type PreProcessor func(u UnstructuredWithMetadata) error
   523  
   524  func (pp PreProcessor) PreProcess(u UnstructuredWithMetadata) error {
   525  	if pp == nil {
   526  		return nil
   527  	}
   528  	return pp(u)
   529  }
   530  
   531  func (r *Registry) RegisterResourcePreProcessor(pp ManagedPreProcessor) {
   532  	r.resourcePreProcessors = append(r.resourcePreProcessors, pp)
   533  }
   534  
   535  type ResourcePreProcessor func(mg resource.Managed) error
   536  
   537  func (pp ResourcePreProcessor) ResourcePreProcessor(mg resource.Managed) error {
   538  	if pp == nil {
   539  		return nil
   540  	}
   541  	return pp(mg)
   542  }