crossplane / upjet

A code generation framework and runtime for Crossplane providers
Apache License 2.0
320 stars 90 forks source link

Add config.Resource.PreviousVersions to specify the previous versions of an MR API #402

Closed ulucinar closed 6 months ago

ulucinar commented 6 months ago

Description of your changes

When generating new versions of the CRD APIs associated with a managed resource, upjet's code generation pipeline can potentially run into the following issue:

We have a roadmap item to modularize the code generation pipeline to make it more dynamic and scalable but it's a much larger effort. As a workaround, we had introduced the config.Resource.OverrideFieldNames API through which one can override the name upjet is generating for a CRD type. However, this requires manual configuration.

For most cases, this has been feasible as we rarely do bulk breaking changes in the MR APIs. However recently, we are rolling out API changes across the official providers that replace the singleton lists in the MR APIs with embedded objects (please see https://github.com/crossplane/upjet/pull/387 and https://github.com/crossplane-contrib/provider-upjet-gcp/pull/508 for more context). Such systemic changes affecting multiple resources can result in a need to override the generated type names for many resources. What's worse, @sergenyalcin identified in https://github.com/crossplane-contrib/provider-upjet-azure/pull/733 that the current config.Resource.OverrideFieldNames API is unable to handle certain types of overrides where we need to override the same leaf at multiple paths. We need to be able to specify the canonical paths of the overrides being defined.

So, we've decided to address this issue by making upjet's code generation pipelines aware of the existing previous versions of the CRDs (MR APIs). One can configure an older version of an API as follows:

p.AddResourceConfigurator("aws_msk_cluster", func(r *config.Resource) {
  r.Version = "v1beta2"
  r.PreviousVersions = []string{"v1beta1"}
  ...

While generating the CRDs in a package, upjet will then load the type definitions from these previous versions specified and use them as input to its already existing name conflict resolution function.

We also deprecate the config.Resource.OverrideFieldNames API whose only known use case is preventing the type name conflicts in the generated CRDs. So, config.Resource.OverrideFieldNames is deprecated in favor of the `config.Resource.PreviousVersions-based mechanism described above.

I have:

How has this code been tested

Tested in the context of https://github.com/crossplane-contrib/provider-upjet-azure/pull/733 & https://github.com/crossplane-contrib/provider-upjet-gcp/pull/508. As an example, please observe the changes in here, where the API is replaced and we observe no diff in the generated APIs.