Skip to content

Commit

Permalink
schema migration optional; default to olm.bundle.object
Browse files Browse the repository at this point in the history
Signed-off-by: Jordan Keister <jordan@nimblewidget.com>
  • Loading branch information
grokspawn committed Jul 23, 2024
1 parent 66abaaa commit c761825
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 106 deletions.

This file was deleted.

6 changes: 3 additions & 3 deletions alpha/action/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
type Migrate struct {
CatalogRef string
OutputDir string
Stages int
Level string

WriteFunc declcfg.WriteFunc
FileExt string
Expand All @@ -29,8 +29,8 @@ func (m Migrate) Run(ctx context.Context) error {
}

r := Render{
Refs: []string{m.CatalogRef},
MigrateStages: m.Stages,
Refs: []string{m.CatalogRef},
MigrationLevel: m.Level,

// Only allow catalogs to be migrated.
AllowedRefMask: RefSqliteImage | RefSqliteFile | RefDCImage | RefDCDir,
Expand Down
50 changes: 50 additions & 0 deletions alpha/action/migrations/000_bundle_object_to_csv_metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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",
"migrates bundles' `olm.bundle.object` to `olm.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
})
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ import (

type Migration interface {
Name() string
Help() string
Migrate(*declcfg.DeclarativeConfig) error
}

func NewMigration(name string, fn func(config *declcfg.DeclarativeConfig) error) Migration {
return &simpleMigration{name: name, fn: fn}
func newMigration(name string, help string, fn func(config *declcfg.DeclarativeConfig) error) Migration {
return &simpleMigration{name: name, help: help, fn: fn}
}

type simpleMigration struct {
name string
help string
fn func(*declcfg.DeclarativeConfig) error
}

Expand All @@ -30,18 +32,24 @@ func (s simpleMigration) Migrate(config *declcfg.DeclarativeConfig) error {
return s.fn(config)
}

func (s simpleMigration) Help() string {
return s.help
}

type Migrations struct {
migrations []Migration
Migrations []Migration
}

// allMigrations represents the migration catalog
// the order of these migrations is important
var allMigrations = []Migration{
BundleObjectToCSVMetadata,
}

func NewMigrations(level string) (*Migrations, error) {
migrations := slices.Clone(allMigrations)
if level == "" {
return &Migrations{migrations: migrations}, nil
return &Migrations{Migrations: migrations}, nil
}

found := false
Expand All @@ -56,26 +64,24 @@ func NewMigrations(level string) (*Migrations, error) {
if !found {
return nil, fmt.Errorf("unknown migration level %q", level)
}
return &Migrations{migrations: keep}, nil
return &Migrations{Migrations: keep}, nil
}

func (m *Migrations) HelpText() string {
func 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(" Available migrators:\n")
if len(allMigrations) == 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()))
for _, migration := range allMigrations {
help.WriteString(fmt.Sprintf(" - %s\n", migration.Name()))
}
return help.String()
}

func (m *Migrations) Migrate(config *declcfg.DeclarativeConfig) error {
for _, migration := range m.migrations {
for _, migration := range m.Migrations {
if err := migration.Migrate(config); err != nil {
return err
}
Expand Down
30 changes: 9 additions & 21 deletions alpha/action/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (

"github.com/operator-framework/api/pkg/operators/v1alpha1"

"github.com/operator-framework/operator-registry/alpha/action/migrations"
"github.com/operator-framework/operator-registry/alpha/declcfg"
"github.com/operator-framework/operator-registry/alpha/property"
"github.com/operator-framework/operator-registry/pkg/containertools"
Expand Down Expand Up @@ -55,7 +56,7 @@ type Render struct {
Refs []string
Registry image.Registry
AllowedRefMask RefType
MigrateStages int
MigrationLevel string
ImageRefTemplate *template.Template

skipSqliteDeprecationLog bool
Expand Down Expand Up @@ -89,7 +90,7 @@ func (r Render) Run(ctx context.Context) (*declcfg.DeclarativeConfig, error) {
})
}

if err := migrate(cfg, r.MigrateStages); err != nil {
if err := migrate(cfg, r.MigrationLevel); err != nil {
return nil, fmt.Errorf("migrate: %v", err)
}

Expand Down Expand Up @@ -415,27 +416,14 @@ func moveBundleObjectsToEndOfPropertySlices(cfg *declcfg.DeclarativeConfig) {
}
}

func migrate(cfg *declcfg.DeclarativeConfig, migrateStages int) error {
// Do not delete or change the order of the below migrations.
// The --migrate-stage flag is an API that depends on the presence
// and order of these migrations.
migrations := []func(*declcfg.DeclarativeConfig) error{
convertObjectsToCSVMetadata,
}

if migrateStages > len(migrations) {
return fmt.Errorf("number of requested migration stages to run (%d) exceeds number of available migrations (%d)", migrateStages, len(migrations))
func migrate(cfg *declcfg.DeclarativeConfig, migrateLevel string) error {
mobj, err := migrations.NewMigrations(migrateLevel)
if err != nil {
return err
}

// migrateStages <0 means all migrations
// migrateStages 0 means no migrations
// migrateStages 1 means only the first migration
// etc...
for i, m := range migrations {
if i == migrateStages {
break
}
if err := m(cfg); err != nil {
for _, m := range (*mobj).Migrations {
if err := m.Migrate(cfg); err != nil {
return err
}
}
Expand Down
12 changes: 6 additions & 6 deletions alpha/action/render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,9 +453,9 @@ func TestRender(t *testing.T) {
{
name: "Success/DeclcfgImageMigrate",
render: action.Render{
Refs: []string{"test.registry/foo-operator/foo-index-declcfg:v0.2.0"},
Migrate: true,
Registry: reg,
Refs: []string{"test.registry/foo-operator/foo-index-declcfg:v0.2.0"},
MigrationLevel: "bundle-object-to-csv-metadata",
Registry: reg,
},
expectCfg: &declcfg.DeclarativeConfig{
Packages: []declcfg.Package{
Expand Down Expand Up @@ -550,9 +550,9 @@ func TestRender(t *testing.T) {
{
name: "Success/DeclcfgDirectoryMigrate",
render: action.Render{
Refs: []string{"testdata/foo-index-v0.2.0-declcfg"},
Migrate: true,
Registry: reg,
Refs: []string{"testdata/foo-index-v0.2.0-declcfg"},
MigrationLevel: "bundle-object-to-csv-metadata",
Registry: reg,
},
expectCfg: &declcfg.DeclarativeConfig{
Packages: []declcfg.Package{
Expand Down
6 changes: 3 additions & 3 deletions alpha/template/basic/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import (
const schema string = "olm.template.basic"

type Template struct {
Registry image.Registry
MigrateStages int
Registry image.Registry
MigrateLevel string
}

type BasicTemplate struct {
Expand Down Expand Up @@ -60,7 +60,7 @@ func (t Template) Render(ctx context.Context, reader io.Reader) (*declcfg.Declar
r := action.Render{
Registry: t.Registry,
AllowedRefMask: action.RefBundleImage,
MigrateStages: t.MigrateStages,
MigrationLevel: t.MigrateLevel,
}

for _, b := range cfg.Bundles {
Expand Down
2 changes: 1 addition & 1 deletion alpha/template/semver/semver.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (t Template) Render(ctx context.Context) (*declcfg.DeclarativeConfig, error
AllowedRefMask: action.RefBundleImage,
Refs: []string{b},
Registry: t.Registry,
MigrateStages: t.MigrateStages,
MigrationLevel: t.MigrateLevel,
}
c, err := r.Run(ctx)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions alpha/template/semver/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import (

// data passed into this module externally
type Template struct {
Data io.Reader
Registry image.Registry
MigrateStages int
Data io.Reader
Registry image.Registry
MigrateLevel string
}

// IO structs -- BEGIN
Expand Down
2 changes: 1 addition & 1 deletion cmd/opm/alpha/render-graph/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ $ opm alpha render-graph quay.io/operatorhubio/catalog:latest | \
render.Registry = registry

// Run all migrations
render.MigrateStages = -1
render.MigrationLevel = ""

cfg, err := render.Run(cmd.Context())
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion cmd/opm/alpha/template/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"

"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"
"github.com/operator-framework/operator-registry/cmd/opm/internal/util"
Expand Down Expand Up @@ -74,7 +75,7 @@ When FILE is '-' or not provided, the template is read from standard input`,
},
}

cmd.Flags().IntVar(&template.MigrateStages, "migrate-stages", 0, "Number of migration stages to run; use -1 for all available stages")
cmd.Flags().StringVar(&template.MigrateLevel, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText())

return cmd
}
5 changes: 3 additions & 2 deletions cmd/opm/alpha/template/semver.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import (
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"

"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"
"github.com/operator-framework/operator-registry/cmd/opm/internal/util"
)

func newSemverTemplateCmd() *cobra.Command {
var (
migrateStages int
migrateLevel string
)

cmd := &cobra.Command{
Expand Down Expand Up @@ -86,7 +87,7 @@ When FILE is '-' or not provided, the template is read from standard input`,
},
}

cmd.Flags().IntVar(&migrateStages, "migrate-stages", 0, "Number of migration stages to run; use -1 for all available stages")
cmd.Flags().StringVar(&migrateLevel, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText())

return cmd
}
7 changes: 6 additions & 1 deletion cmd/opm/migrate/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"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/pkg/sqlite"
)
Expand Down Expand Up @@ -51,6 +52,10 @@ parsers that assume that a file contains exactly one valid JSON object.
},
}
cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format (json|yaml)")
cmd.Flags().IntVar(&migrate.Stages, "stages", -1, "Number of migration stages to run; use -1 for all available stages")
cmd.Flags().StringVar(&migrate.Level, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText())
_ = cmd.RegisterFlagCompletionFunc("migrate-level", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{migrations.HelpText()}, cobra.ShellCompDirectiveDefault
})

return cmd
}
Loading

0 comments on commit c761825

Please sign in to comment.