From a8d127cff2b60c4b97a50b4e4e8a62cd1a46f0d5 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Mon, 19 Aug 2024 20:29:53 -0400 Subject: [PATCH] template/*: allow passing custom bundle renderer --- alpha/action/render.go | 8 ++++---- alpha/template/basic/basic.go | 16 ++-------------- alpha/template/semver/semver.go | 33 +++++++++++++++----------------- alpha/template/semver/types.go | 9 ++++----- cmd/opm/alpha/template/basic.go | 19 ++++++++++++++---- cmd/opm/alpha/template/semver.go | 24 +++++++++++++++++------ 6 files changed, 58 insertions(+), 51 deletions(-) diff --git a/alpha/action/render.go b/alpha/action/render.go index 798ffb5e5..07631b7c4 100644 --- a/alpha/action/render.go +++ b/alpha/action/render.go @@ -162,19 +162,19 @@ func (r Render) renderReference(ctx context.Context, ref string) (*declcfg.Decla func (r Render) imageToDeclcfg(ctx context.Context, imageRef string) (*declcfg.DeclarativeConfig, error) { ref := image.SimpleReference(imageRef) if err := r.Registry.Pull(ctx, ref); err != nil { - return nil, err + return nil, fmt.Errorf("failed to pull image %q: %v", ref, err) } labels, err := r.Registry.Labels(ctx, ref) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get labels for image %q: %v", ref, err) } tmpDir, err := os.MkdirTemp("", "render-unpack-") if err != nil { - return nil, err + return nil, fmt.Errorf("create tempdir: %v", err) } defer os.RemoveAll(tmpDir) if err := r.Registry.Unpack(ctx, ref, tmpDir); err != nil { - return nil, err + return nil, fmt.Errorf("failed to unpack image %q: %v", ref, err) } var cfg *declcfg.DeclarativeConfig diff --git a/alpha/template/basic/basic.go b/alpha/template/basic/basic.go index 0456dc151..a34d7541d 100644 --- a/alpha/template/basic/basic.go +++ b/alpha/template/basic/basic.go @@ -8,17 +8,13 @@ import ( "k8s.io/apimachinery/pkg/util/yaml" - "github.com/operator-framework/operator-registry/alpha/action" - "github.com/operator-framework/operator-registry/alpha/action/migrations" "github.com/operator-framework/operator-registry/alpha/declcfg" - "github.com/operator-framework/operator-registry/pkg/image" ) const schema string = "olm.template.basic" type Template struct { - Registry image.Registry - Migrations *migrations.Migrations + RenderBundle func(context.Context, string) (*declcfg.DeclarativeConfig, error) } type BasicTemplate struct { @@ -57,19 +53,11 @@ func (t Template) Render(ctx context.Context, reader io.Reader) (*declcfg.Declar } outb := cfg.Bundles[:0] - // populate registry, incl any flags from CLI, and enforce only rendering bundle images - r := action.Render{ - Registry: t.Registry, - AllowedRefMask: action.RefBundleImage, - Migrations: t.Migrations, - } - for _, b := range cfg.Bundles { if !isBundleTemplate(&b) { return nil, fmt.Errorf("unexpected fields present in basic template bundle") } - r.Refs = []string{b.Image} - contributor, err := r.Run(ctx) + contributor, err := t.RenderBundle(ctx, b.Image) if err != nil { return nil, err } diff --git a/alpha/template/semver/semver.go b/alpha/template/semver/semver.go index dfd584a1c..61dd28669 100644 --- a/alpha/template/semver/semver.go +++ b/alpha/template/semver/semver.go @@ -10,7 +10,6 @@ import ( "k8s.io/apimachinery/pkg/util/errors" "sigs.k8s.io/yaml" - "github.com/operator-framework/operator-registry/alpha/action" "github.com/operator-framework/operator-registry/alpha/declcfg" "github.com/operator-framework/operator-registry/alpha/property" ) @@ -25,22 +24,20 @@ func (t Template) Render(ctx context.Context) (*declcfg.DeclarativeConfig, error var cfgs []declcfg.DeclarativeConfig - bundleDict := make(map[string]struct{}) + bundleDict := make(map[string]string) buildBundleList(&sv.Candidate.Bundles, &bundleDict) buildBundleList(&sv.Fast.Bundles, &bundleDict) buildBundleList(&sv.Stable.Bundles, &bundleDict) for b := range bundleDict { - r := action.Render{ - AllowedRefMask: action.RefBundleImage, - Refs: []string{b}, - Registry: t.Registry, - Migrations: t.Migrations, - } - c, err := r.Run(ctx) + c, err := t.RenderBundle(ctx, b) if err != nil { return nil, err } + if len(c.Bundles) != 1 { + return nil, fmt.Errorf("bundle reference %q resulted in %d bundles, expected 1", b, len(c.Bundles)) + } + bundleDict[b] = c.Bundles[0].Image cfgs = append(cfgs, *c) } out = *combineConfigs(cfgs) @@ -49,7 +46,7 @@ func (t Template) Render(ctx context.Context) (*declcfg.DeclarativeConfig, error return nil, fmt.Errorf("render: no bundles specified or no bundles could be rendered") } - channelBundleVersions, err := sv.getVersionsFromStandardChannels(&out) + channelBundleVersions, err := sv.getVersionsFromStandardChannels(&out, bundleDict) if err != nil { return nil, fmt.Errorf("render: unable to post-process bundle info: %v", err) } @@ -61,10 +58,10 @@ func (t Template) Render(ctx context.Context) (*declcfg.DeclarativeConfig, error return &out, nil } -func buildBundleList(bundles *[]semverTemplateBundleEntry, dict *map[string]struct{}) { +func buildBundleList(bundles *[]semverTemplateBundleEntry, dict *map[string]string) { for _, b := range *bundles { if _, ok := (*dict)[b.Image]; !ok { - (*dict)[b.Image] = struct{}{} + (*dict)[b.Image] = "" } } } @@ -114,10 +111,10 @@ func readFile(reader io.Reader) (*semverTemplate, error) { return &sv, nil } -func (sv *semverTemplate) getVersionsFromStandardChannels(cfg *declcfg.DeclarativeConfig) (*bundleVersions, error) { +func (sv *semverTemplate) getVersionsFromStandardChannels(cfg *declcfg.DeclarativeConfig, bundleDict map[string]string) (*bundleVersions, error) { versions := bundleVersions{} - bdm, err := sv.getVersionsFromChannel(sv.Candidate.Bundles, cfg) + bdm, err := sv.getVersionsFromChannel(sv.Candidate.Bundles, bundleDict, cfg) if err != nil { return nil, err } @@ -126,7 +123,7 @@ func (sv *semverTemplate) getVersionsFromStandardChannels(cfg *declcfg.Declarati } versions[candidateChannelArchetype] = bdm - bdm, err = sv.getVersionsFromChannel(sv.Fast.Bundles, cfg) + bdm, err = sv.getVersionsFromChannel(sv.Fast.Bundles, bundleDict, cfg) if err != nil { return nil, err } @@ -135,7 +132,7 @@ func (sv *semverTemplate) getVersionsFromStandardChannels(cfg *declcfg.Declarati } versions[fastChannelArchetype] = bdm - bdm, err = sv.getVersionsFromChannel(sv.Stable.Bundles, cfg) + bdm, err = sv.getVersionsFromChannel(sv.Stable.Bundles, bundleDict, cfg) if err != nil { return nil, err } @@ -147,7 +144,7 @@ func (sv *semverTemplate) getVersionsFromStandardChannels(cfg *declcfg.Declarati return &versions, nil } -func (sv *semverTemplate) getVersionsFromChannel(semverBundles []semverTemplateBundleEntry, cfg *declcfg.DeclarativeConfig) (map[string]semver.Version, error) { +func (sv *semverTemplate) getVersionsFromChannel(semverBundles []semverTemplateBundleEntry, bundleDict map[string]string, cfg *declcfg.DeclarativeConfig) (map[string]semver.Version, error) { entries := make(map[string]semver.Version) // we iterate over the channel bundles from the template, to: @@ -158,7 +155,7 @@ func (sv *semverTemplate) getVersionsFromChannel(semverBundles []semverTemplateB // test if the bundle specified in the template is present in the successfully-rendered bundles index := 0 for index < len(cfg.Bundles) { - if cfg.Bundles[index].Image == semverBundle.Image { + if cfg.Bundles[index].Image == bundleDict[semverBundle.Image] { break } index++ diff --git a/alpha/template/semver/types.go b/alpha/template/semver/types.go index f170074c3..b0846a64f 100644 --- a/alpha/template/semver/types.go +++ b/alpha/template/semver/types.go @@ -1,19 +1,18 @@ package semver import ( + "context" "io" "github.com/blang/semver/v4" - "github.com/operator-framework/operator-registry/alpha/action/migrations" - "github.com/operator-framework/operator-registry/pkg/image" + "github.com/operator-framework/operator-registry/alpha/declcfg" ) // data passed into this module externally type Template struct { - Data io.Reader - Registry image.Registry - Migrations *migrations.Migrations + Data io.Reader + RenderBundle func(context.Context, string) (*declcfg.DeclarativeConfig, error) } // IO structs -- BEGIN diff --git a/cmd/opm/alpha/template/basic.go b/cmd/opm/alpha/template/basic.go index b1b77a888..4195bd0fe 100644 --- a/cmd/opm/alpha/template/basic.go +++ b/cmd/opm/alpha/template/basic.go @@ -1,6 +1,7 @@ package template import ( + "context" "io" "log" "os" @@ -8,6 +9,7 @@ import ( "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/operator-framework/operator-registry/alpha/action" "github.com/operator-framework/operator-registry/alpha/action/migrations" "github.com/operator-framework/operator-registry/alpha/declcfg" "github.com/operator-framework/operator-registry/alpha/template/basic" @@ -62,14 +64,23 @@ When FILE is '-' or not provided, the template is read from standard input`, } defer reg.Destroy() - template.Registry = reg - + var m *migrations.Migrations if migrateLevel != "" { - m, err := migrations.NewMigrations(migrateLevel) + m, err = migrations.NewMigrations(migrateLevel) if err != nil { log.Fatal(err) } - template.Migrations = m + } + + template.RenderBundle = func(ctx context.Context, image string) (*declcfg.DeclarativeConfig, error) { + // populate registry, incl any flags from CLI, and enforce only rendering bundle images + r := action.Render{ + Refs: []string{image}, + Registry: reg, + AllowedRefMask: action.RefBundleImage, + Migrations: m, + } + return r.Run(ctx) } // only taking first file argument diff --git a/cmd/opm/alpha/template/semver.go b/cmd/opm/alpha/template/semver.go index e0547a67c..97dccbc6c 100644 --- a/cmd/opm/alpha/template/semver.go +++ b/cmd/opm/alpha/template/semver.go @@ -1,6 +1,7 @@ package template import ( + "context" "fmt" "io" "log" @@ -9,6 +10,7 @@ import ( "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/operator-framework/operator-registry/alpha/action" "github.com/operator-framework/operator-registry/alpha/action/migrations" "github.com/operator-framework/operator-registry/alpha/declcfg" "github.com/operator-framework/operator-registry/alpha/template/semver" @@ -68,17 +70,27 @@ When FILE is '-' or not provided, the template is read from standard input`, } defer reg.Destroy() - template := semver.Template{ - Data: data, - Registry: reg, - } + var m *migrations.Migrations if migrateLevel != "" { - m, err := migrations.NewMigrations(migrateLevel) + m, err = migrations.NewMigrations(migrateLevel) if err != nil { log.Fatal(err) } - template.Migrations = m } + + template := semver.Template{ + Data: data, + RenderBundle: func(ctx context.Context, ref string) (*declcfg.DeclarativeConfig, error) { + renderer := action.Render{ + Refs: []string{ref}, + Registry: reg, + AllowedRefMask: action.RefBundleImage, + Migrations: m, + } + return renderer.Run(ctx) + }, + } + out, err := template.Render(cmd.Context()) if err != nil { log.Fatalf("semver %q: %v", source, err)