Skip to content

Commit

Permalink
use a type to protect migration interactions
Browse files Browse the repository at this point in the history
Signed-off-by: Jordan Keister <jordan@nimblewidget.com>
  • Loading branch information
grokspawn committed Aug 5, 2024
1 parent 9e68d1c commit 4b0ab63
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 22 deletions.
3 changes: 2 additions & 1 deletion alpha/action/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import (
"fmt"
"os"

"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"
)

type Migrate struct {
CatalogRef string
OutputDir string
Level string
Level migrations.MigrationToken

WriteFunc declcfg.WriteFunc
FileExt string
Expand Down
40 changes: 30 additions & 10 deletions alpha/action/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,31 @@ import (
"github.com/operator-framework/operator-registry/alpha/declcfg"
)

type MigrationToken string

const MigrationTokenInvalid MigrationToken = ""

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

func newMigration(name string, help string, fn func(config *declcfg.DeclarativeConfig) error) Migration {
return &simpleMigration{name: name, help: help, fn: fn}
s := strings.ReplaceAll(help, "`", "'")
return &simpleMigration{token: MigrationToken(name), name: name, help: s, fn: fn}
}

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

func (s simpleMigration) Token() MigrationToken {
return s.token
}

func (s simpleMigration) Name() string {
Expand All @@ -41,11 +52,20 @@ type Migrations struct {
Migrations []Migration
}

func GetLastMigrationName() string {
func GetLastMigration() MigrationToken {
if len(allMigrations) == 0 {
return ""
}
return allMigrations[len(allMigrations)-1].Name()
return allMigrations[len(allMigrations)-1].Token()
}

func ValidateName(name string) (MigrationToken, error) {
for _, migration := range allMigrations {
if migration.Name() == name {
return migration.Token(), nil
}
}
return MigrationTokenInvalid, fmt.Errorf("unknown migration level %q", name)
}

// allMigrations represents the migration catalog
Expand All @@ -54,7 +74,7 @@ var allMigrations = []Migration{
bundleObjectToCSVMetadata,
}

func NewMigrations(level string) (*Migrations, error) {
func NewMigrations(level MigrationToken) (*Migrations, error) {
if level == "" {
return &Migrations{}, nil
}
Expand All @@ -65,7 +85,7 @@ func NewMigrations(level string) (*Migrations, error) {
keep := migrations[:0]
for _, migration := range migrations {
keep = append(keep, migration)
if migration.Name() == level {
if migration.Token() == level {
found = true
break
}
Expand All @@ -84,9 +104,9 @@ func HelpText() string {
help.WriteString(" (no migrations available in this version)\n")
}

tabber := tabwriter.NewWriter(&help, 20, 30, 1, '\t', tabwriter.AlignRight)
tabber := tabwriter.NewWriter(&help, 8, 8, 1, '\t', 0)
for _, migration := range allMigrations {
fmt.Fprintf(tabber, " - %s\t%s\n", migration.Name(), migration.Help())
fmt.Fprintf(tabber, " - %s\t%s\n", migration.Name(), migration.Help())
}
tabber.Flush()
return help.String()
Expand Down
4 changes: 2 additions & 2 deletions alpha/action/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ type Render struct {
Refs []string
Registry image.Registry
AllowedRefMask RefType
MigrationLevel string
MigrationLevel migrations.MigrationToken
ImageRefTemplate *template.Template

skipSqliteDeprecationLog bool
Expand Down Expand Up @@ -414,7 +414,7 @@ func moveBundleObjectsToEndOfPropertySlices(cfg *declcfg.DeclarativeConfig) {
}
}

func migrate(cfg *declcfg.DeclarativeConfig, migrateLevel string) error {
func migrate(cfg *declcfg.DeclarativeConfig, migrateLevel migrations.MigrationToken) error {
mobj, err := migrations.NewMigrations(migrateLevel)
if err != nil {
return err
Expand Down
3 changes: 2 additions & 1 deletion alpha/template/basic/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ 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"
)
Expand All @@ -17,7 +18,7 @@ const schema string = "olm.template.basic"

type Template struct {
Registry image.Registry
MigrationLevel string
MigrationLevel migrations.MigrationToken
}

type BasicTemplate struct {
Expand Down
3 changes: 2 additions & 1 deletion alpha/template/semver/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import (

"github.com/blang/semver/v4"

"github.com/operator-framework/operator-registry/alpha/action/migrations"
"github.com/operator-framework/operator-registry/pkg/image"
)

// data passed into this module externally
type Template struct {
Data io.Reader
Registry image.Registry
MigrationLevel string
MigrationLevel migrations.MigrationToken
}

// IO structs -- BEGIN
Expand Down
13 changes: 11 additions & 2 deletions cmd/opm/alpha/template/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import (

func newBasicTemplateCmd() *cobra.Command {
var (
template basic.Template
template basic.Template
migrateLevel string
)
cmd := &cobra.Command{
Use: "basic basic-template-file",
Expand Down Expand Up @@ -63,6 +64,14 @@ When FILE is '-' or not provided, the template is read from standard input`,

template.Registry = reg

if migrateLevel != "" {
token, err := migrations.ValidateName(migrateLevel)
if err != nil {
log.Fatal(err)
}
template.MigrationLevel = token
}

// only taking first file argument
cfg, err := template.Render(cmd.Context(), data)
if err != nil {
Expand All @@ -75,7 +84,7 @@ When FILE is '-' or not provided, the template is read from standard input`,
},
}

cmd.Flags().StringVar(&template.MigrationLevel, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText())
cmd.Flags().StringVar(&migrateLevel, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText())

return cmd
}
7 changes: 7 additions & 0 deletions cmd/opm/alpha/template/semver.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ When FILE is '-' or not provided, the template is read from standard input`,
Data: data,
Registry: reg,
}
if migrateLevel != "" {
token, err := migrations.ValidateName(migrateLevel)
if err != nil {
log.Fatal(err)
}
template.MigrationLevel = token
}
out, err := template.Render(cmd.Context())
if err != nil {
log.Fatalf("semver %q: %v", source, err)
Expand Down
15 changes: 12 additions & 3 deletions cmd/opm/migrate/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import (

func NewCmd() *cobra.Command {
var (
migrate action.Migrate
output string
migrate action.Migrate
migrateLevel string
output string
)
cmd := &cobra.Command{
Use: "migrate <indexRef> <outputDir>",
Expand Down Expand Up @@ -43,6 +44,14 @@ parsers that assume that a file contains exactly one valid JSON object.
log.Fatalf("invalid --output value %q, expected (json|yaml)", output)
}

if migrateLevel != "" {
level, err := migrations.ValidateName(migrateLevel)
if err != nil {
log.Fatal(err)
}
migrate.Level = level
}

logrus.Infof("rendering index %q as file-based catalog", migrate.CatalogRef)
if err := migrate.Run(cmd.Context()); err != nil {
logrus.New().Fatal(err)
Expand All @@ -52,7 +61,7 @@ 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().StringVar(&migrate.Level, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText())
cmd.Flags().StringVar(&migrateLevel, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText())

return cmd
}
11 changes: 9 additions & 2 deletions cmd/opm/render/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func NewCmd(showAlphaHelp bool) *cobra.Command {
imageRefTemplate string

deprecatedMigrateFlag bool
migrateLevel string
)
cmd := &cobra.Command{
Use: "render [catalog-image | catalog-directory | bundle-image | bundle-directory | sqlite-file]...",
Expand Down Expand Up @@ -68,7 +69,13 @@ database files.

// if the deprecated flag was used, set the level explicitly to the last migration to perform all migrations
if deprecatedMigrateFlag {
render.MigrationLevel = migrations.GetLastMigrationName()
render.MigrationLevel = migrations.GetLastMigration()
} else if migrateLevel != "" {
level, err := migrations.ValidateName(migrateLevel)
if err != nil {
log.Fatal(err)
}
render.MigrationLevel = level
}

cfg, err := render.Run(cmd.Context())
Expand All @@ -83,7 +90,7 @@ database files.
}
cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format of the streamed file-based catalog objects (json|yaml)")

cmd.Flags().StringVar(&render.MigrationLevel, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText())
cmd.Flags().StringVar(&migrateLevel, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText())
cmd.Flags().BoolVar(&deprecatedMigrateFlag, "migrate", false, "Perform migrations on the rendered FBC")
cmd.Flags().MarkDeprecated("migrate", "use --migrate-level instead")
cmd.MarkFlagsMutuallyExclusive("migrate", "migrate-level")
Expand Down

0 comments on commit 4b0ab63

Please sign in to comment.