From 50e8284f1fe2098a5de64e998018e87db163a3d0 Mon Sep 17 00:00:00 2001 From: Alper Rifat Ulucinar Date: Tue, 14 May 2024 14:09:03 +0300 Subject: [PATCH 1/2] Add config.Resource.PreviousVersions to be able to specify the known previous versions of an MR API. - upjet code generation pipelines can then utilize this information to load the already existing type names for these previous versions and prevent collisions for the generated CRD types. Signed-off-by: Alper Rifat Ulucinar --- pkg/config/resource.go | 5 +++++ pkg/pipeline/run.go | 4 ++++ pkg/pipeline/version.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/pkg/config/resource.go b/pkg/config/resource.go index 6d5184e0..a95f9f09 100644 --- a/pkg/config/resource.go +++ b/pkg/config/resource.go @@ -401,6 +401,11 @@ type Resource struct { // Version is the API version being generated for the corresponding CRD. Version string + // PreviousVersions is the list of API versions previously generated for this + // resource for multi-versioned managed resources. upjet will attempt to load + // the type definitions from these previous versions if configured. + PreviousVersions []string + // ControllerReconcileVersion is the CRD API version the associated // controller will watch & reconcile. If left unspecified, // defaults to the value of Version. This configuration parameter diff --git a/pkg/pipeline/run.go b/pkg/pipeline/run.go index 317800fe..21e688f2 100644 --- a/pkg/pipeline/run.go +++ b/pkg/pipeline/run.go @@ -98,6 +98,10 @@ func Run(pc *config.Provider, rootDir string) { //nolint:gocyclo tfGen := NewTerraformedGenerator(versionGen.Package(), rootDir, group, version) ctrlGen := NewControllerGenerator(rootDir, pc.ModulePath, group) + if err := versionGen.InsertPreviousObjects(versions); err != nil { + panic(errors.Wrapf(err, "cannot insert type definitions from the previous versions into the package scope for group %q", group)) + } + for _, name := range sortedResources(resources) { paramTypeName, err := crdGen.Generate(resources[name]) if err != nil { diff --git a/pkg/pipeline/version.go b/pkg/pipeline/version.go index d0093b82..4a6b3d41 100644 --- a/pkg/pipeline/version.go +++ b/pkg/pipeline/version.go @@ -5,6 +5,7 @@ package pipeline import ( + "fmt" "go/types" "os" "path/filepath" @@ -12,7 +13,9 @@ import ( "github.com/muvaf/typewriter/pkg/wrapper" "github.com/pkg/errors" + "golang.org/x/tools/go/packages" + "github.com/crossplane/upjet/pkg/config" "github.com/crossplane/upjet/pkg/pipeline/templates" ) @@ -60,3 +63,36 @@ func (vg *VersionGenerator) Generate() error { func (vg *VersionGenerator) Package() *types.Package { return vg.pkg } + +// InsertPreviousObjects inserts into this VersionGenerator's package scope all +// the type definitions from the previous versions of the managed resource APIs +// found in the Go package. +func (vg *VersionGenerator) InsertPreviousObjects(versions map[string]map[string]*config.Resource) error { + for _, resources := range versions { + for _, r := range resources { + for _, v := range r.PreviousVersions { + if vg.Version != v { + // if this previous version v is not the version we are currently + // processing + continue + } + pkgs, err := packages.Load(&packages.Config{ + Mode: packages.NeedTypes, + Dir: vg.DirectoryPath, + }, fmt.Sprintf("zz_%s_types.go", strings.ToLower(r.Kind))) + if err != nil { + return errors.Wrapf(err, "cannot load the previous versions of %q from path %s", r.Name, vg.pkg.Path()) + } + for _, p := range pkgs { + if p.Types == nil || p.Types.Scope() == nil { + continue + } + for _, n := range p.Types.Scope().Names() { + vg.pkg.Scope().Insert(p.Types.Scope().Lookup(n)) + } + } + } + } + } + return nil +} From b5622a10e14d199b82e1f333df6c7a2bd2ba8315 Mon Sep 17 00:00:00 2001 From: Alper Rifat Ulucinar Date: Tue, 14 May 2024 14:15:12 +0300 Subject: [PATCH 2/2] Deprecate config.Resource.OverrideFieldNames in favor of config.Resource.PreviousVersions. - The only known use case for config.Resource.OverrideFieldNames is to resolve type confilicts between the older versions of the CRDs and the ones being generated. The "PreviousVersions" API allows loading of the existing types from the filesystem so that upjet code generation pipeline's type conflict resolution mechanisms can prevent such name collisions. Signed-off-by: Alper Rifat Ulucinar --- pkg/config/resource.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/config/resource.go b/pkg/config/resource.go index a95f9f09..fb35aa8f 100644 --- a/pkg/config/resource.go +++ b/pkg/config/resource.go @@ -541,6 +541,9 @@ type Resource struct { // conflict. By convention, also used in upjet, the field name is preceded by // the value of the generated Kind, for example: // "TagParameters": "ClusterTagParameters" + // Deprecated: OverrideFieldNames has been deprecated in favor of loading + // the already existing type names from the older versions of the MR APIS + // via the PreviousVersions API. OverrideFieldNames map[string]string // requiredFields are the fields that will be marked as required in the