From 66abaaac6f89fccca2624df0d4cddf3169dea77a Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Fri, 19 Jul 2024 15:19:31 -0400 Subject: [PATCH] intro new migrations package Signed-off-by: Joe Lanford --- .../000_bundle_object_to_csv_metadata.go | 47 +++++++++++ .../action/internal/migrations/migrations.go | 84 +++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 alpha/action/internal/migrations/000_bundle_object_to_csv_metadata.go create mode 100644 alpha/action/internal/migrations/migrations.go diff --git a/alpha/action/internal/migrations/000_bundle_object_to_csv_metadata.go b/alpha/action/internal/migrations/000_bundle_object_to_csv_metadata.go new file mode 100644 index 000000000..cc9d4f35d --- /dev/null +++ b/alpha/action/internal/migrations/000_bundle_object_to_csv_metadata.go @@ -0,0 +1,47 @@ +package migrations + +import ( + "encoding/json" + + "github.com/operator-framework/api/pkg/operators/v1alpha1" + + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/alpha/property" +) + +var BundleObjectToCSVMetadata = NewMigration("bundle-object-to-csv-metadata", func(cfg *declcfg.DeclarativeConfig) error { + convertBundleObjectToCSVMetadata := func(b *declcfg.Bundle) error { + if b.Image == "" || b.CsvJSON == "" { + return nil + } + + var csv v1alpha1.ClusterServiceVersion + if err := json.Unmarshal([]byte(b.CsvJSON), &csv); err != nil { + return err + } + + props := b.Properties[:0] + for _, p := range b.Properties { + switch p.Type { + case property.TypeBundleObject: + // Get rid of the bundle objects + case property.TypeCSVMetadata: + // If this bundle already has a CSV metadata + // property, we won't mutate the bundle at all. + return nil + default: + // Keep all of the other properties + props = append(props, p) + } + } + b.Properties = append(props, property.MustBuildCSVMetadata(csv)) + return nil + } + + for bi := range cfg.Bundles { + if err := convertBundleObjectToCSVMetadata(&cfg.Bundles[bi]); err != nil { + return err + } + } + return nil +}) diff --git a/alpha/action/internal/migrations/migrations.go b/alpha/action/internal/migrations/migrations.go new file mode 100644 index 000000000..d52b76f6b --- /dev/null +++ b/alpha/action/internal/migrations/migrations.go @@ -0,0 +1,84 @@ +package migrations + +import ( + "fmt" + "slices" + "strings" + + "github.com/operator-framework/operator-registry/alpha/declcfg" +) + +type Migration interface { + Name() string + Migrate(*declcfg.DeclarativeConfig) error +} + +func NewMigration(name string, fn func(config *declcfg.DeclarativeConfig) error) Migration { + return &simpleMigration{name: name, fn: fn} +} + +type simpleMigration struct { + name string + fn func(*declcfg.DeclarativeConfig) error +} + +func (s simpleMigration) Name() string { + return s.name +} + +func (s simpleMigration) Migrate(config *declcfg.DeclarativeConfig) error { + return s.fn(config) +} + +type Migrations struct { + migrations []Migration +} + +var allMigrations = []Migration{ + BundleObjectToCSVMetadata, +} + +func NewMigrations(level string) (*Migrations, error) { + migrations := slices.Clone(allMigrations) + if level == "" { + return &Migrations{migrations: migrations}, nil + } + + found := false + keep := migrations[:0] + for _, migration := range migrations { + keep = append(keep, migration) + if migration.Name() == level { + found = true + break + } + } + if !found { + return nil, fmt.Errorf("unknown migration level %q", level) + } + return &Migrations{migrations: keep}, nil +} + +func (m *Migrations) HelpText() string { + var help strings.Builder + help.WriteString("-- Migrations --\n") + help.WriteString(" To run a migration, use the --level flag with the migration name.\n") + help.WriteString(" The migrator will run all migrations up to and including the selected level.\n\n") + help.WriteString(" Available migration levels:\n") + if len(m.migrations) == 0 { + help.WriteString(" (no migrations available in this version)\n") + } + for i, migration := range m.migrations { + help.WriteString(fmt.Sprintf(" - %s\n", i+1, migration.Name())) + } + return help.String() +} + +func (m *Migrations) Migrate(config *declcfg.DeclarativeConfig) error { + for _, migration := range m.migrations { + if err := migration.Migrate(config); err != nil { + return err + } + } + return nil +}