diff --git a/pkg/config/resource.go b/pkg/config/resource.go index 6d5184e0..fb35aa8f 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 @@ -536,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 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 +}