From c80e8751e716c069017b55279a0f29d0254d426a Mon Sep 17 00:00:00 2001 From: Jordan Keister Date: Thu, 15 Aug 2024 16:19:57 -0500 Subject: [PATCH] add optional schema migrations; default to olm.bundle.object instead of olm.csv.metadata (#1384) * Allow disabling of migrations for bundles and sqlite DBs Signed-off-by: Joe Lanford * intro new migrations package Signed-off-by: Joe Lanford * schema migration optional; default to olm.bundle.object Signed-off-by: Jordan Keister * review resolutions Signed-off-by: Jordan Keister * use a type to protect migration interactions Signed-off-by: Jordan Keister * review revisions Signed-off-by: Jordan Keister --------- Signed-off-by: Joe Lanford Signed-off-by: Jordan Keister Co-authored-by: Joe Lanford --- alpha/action/migrate.go | 6 +- alpha/action/migrate_test.go | 130 +++--- .../000_bundle_object_to_csv_metadata.go | 47 ++ alpha/action/migrations/migrations.go | 104 +++++ alpha/action/migrations/migrations_test.go | 139 ++++++ alpha/action/render.go | 56 +-- alpha/action/render_test.go | 424 ++++++++++++++++-- alpha/template/basic/basic.go | 8 +- alpha/template/semver/semver.go | 9 +- alpha/template/semver/types.go | 7 +- cmd/opm/alpha/render-graph/cmd.go | 5 +- cmd/opm/alpha/template/basic.go | 15 +- cmd/opm/alpha/template/semver.go | 16 +- cmd/opm/migrate/cmd.go | 16 +- cmd/opm/render/cmd.go | 21 +- pkg/api/api_to_model.go | 15 +- pkg/api/conversion_test.go | 5 +- pkg/registry/registry_to_model.go | 18 +- pkg/registry/registry_to_model_test.go | 4 +- pkg/server/server_test.go | 10 +- 20 files changed, 847 insertions(+), 208 deletions(-) create mode 100644 alpha/action/migrations/000_bundle_object_to_csv_metadata.go create mode 100644 alpha/action/migrations/migrations.go create mode 100644 alpha/action/migrations/migrations_test.go diff --git a/alpha/action/migrate.go b/alpha/action/migrate.go index 3a502300f..8122d1648 100644 --- a/alpha/action/migrate.go +++ b/alpha/action/migrate.go @@ -5,6 +5,7 @@ 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" ) @@ -12,6 +13,7 @@ import ( type Migrate struct { CatalogRef string OutputDir string + Migrations *migrations.Migrations WriteFunc declcfg.WriteFunc FileExt string @@ -28,8 +30,8 @@ func (m Migrate) Run(ctx context.Context) error { } r := Render{ - Refs: []string{m.CatalogRef}, - Migrate: true, + Refs: []string{m.CatalogRef}, + Migrations: m.Migrations, // Only allow catalogs to be migrated. AllowedRefMask: RefSqliteImage | RefSqliteFile | RefDCImage | RefDCDir, diff --git a/alpha/action/migrate_test.go b/alpha/action/migrate_test.go index 2e889c8c0..6a69ec4f3 100644 --- a/alpha/action/migrate_test.go +++ b/alpha/action/migrate_test.go @@ -31,8 +31,8 @@ func TestMigrate(t *testing.T) { image.SimpleReference("test.registry/bar-operator/bar-bundle:v0.2.0"): "testdata/bar-bundle-v0.2.0", } - tmpDir := t.TempDir() - dbFile := filepath.Join(tmpDir, "index.db") + sqliteDBDir := t.TempDir() + dbFile := filepath.Join(sqliteDBDir, "index.db") err := generateSqliteFile(dbFile, sqliteBundles) require.NoError(t, err) @@ -44,7 +44,6 @@ func TestMigrate(t *testing.T) { name: "SqliteImage/Success", migrate: action.Migrate{ CatalogRef: "test.registry/migrate/catalog:sqlite", - OutputDir: filepath.Join(tmpDir, "sqlite-image"), WriteFunc: declcfg.WriteYAML, FileExt: ".yaml", Registry: reg, @@ -58,7 +57,6 @@ func TestMigrate(t *testing.T) { name: "SqliteFile/Success", migrate: action.Migrate{ CatalogRef: dbFile, - OutputDir: filepath.Join(tmpDir, "sqlite-file"), WriteFunc: declcfg.WriteYAML, FileExt: ".yaml", Registry: reg, @@ -72,7 +70,6 @@ func TestMigrate(t *testing.T) { name: "DeclcfgImage/Success", migrate: action.Migrate{ CatalogRef: "test.registry/foo-operator/foo-index-declcfg:v0.2.0", - OutputDir: filepath.Join(tmpDir, "declcfg-image"), WriteFunc: declcfg.WriteYAML, FileExt: ".yaml", Registry: reg, @@ -85,7 +82,6 @@ func TestMigrate(t *testing.T) { name: "DeclcfgDir/Success", migrate: action.Migrate{ CatalogRef: "testdata/foo-index-v0.2.0-declcfg", - OutputDir: filepath.Join(tmpDir, "declcfg-dir"), WriteFunc: declcfg.WriteYAML, FileExt: ".yaml", Registry: reg, @@ -98,16 +94,31 @@ func TestMigrate(t *testing.T) { name: "BundleImage/Failure", migrate: action.Migrate{ CatalogRef: "test.registry/foo-operator/foo-bundle:v0.1.0", - OutputDir: filepath.Join(tmpDir, "bundle-image"), WriteFunc: declcfg.WriteYAML, FileExt: ".yaml", Registry: reg, }, expectErr: action.ErrNotAllowed, }, + { + name: "SqliteImage/Success/NoMigrations", + migrate: action.Migrate{ + CatalogRef: "test.registry/migrate/catalog:sqlite", + WriteFunc: declcfg.WriteYAML, + FileExt: ".yaml", + Registry: reg, + Migrations: nil, + }, + expectedFiles: map[string]string{ + "foo/catalog.yaml": migrateFooCatalogSqlite(), + "bar/catalog.yaml": migrateBarCatalogSqlite(), + }, + }, } for _, s := range specs { t.Run(s.name, func(t *testing.T) { + s.migrate.OutputDir = t.TempDir() + err := s.migrate.Run(context.Background()) require.ErrorIs(t, err, s.expectErr) if s.expectErr != nil { @@ -224,18 +235,12 @@ properties: value: packageName: bar versionRange: <0.1.0 -- type: olm.csv.metadata - value: - annotations: - olm.skipRange: <0.1.0 - apiServiceDefinitions: {} - crdDescriptions: - owned: - - kind: Foo - name: foos.test.foo - version: v1 - displayName: Foo Operator - provider: {} +- type: olm.bundle.object + value: + data: eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjEiLCJraW5kIjoiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uIiwibWV0YWRhdGEiOnsibmFtZSI6ImZvb3MudGVzdC5mb28ifSwic3BlYyI6eyJncm91cCI6InRlc3QuZm9vIiwibmFtZXMiOnsia2luZCI6IkZvbyIsInBsdXJhbCI6ImZvb3MifSwidmVyc2lvbnMiOlt7Im5hbWUiOiJ2MSJ9XX19 +- type: olm.bundle.object + value: + data: eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsib2xtLnNraXBSYW5nZSI6Ilx1MDAzYzAuMS4wIn0sIm5hbWUiOiJmb28udjAuMS4wIn0sInNwZWMiOnsiY3VzdG9tcmVzb3VyY2VkZWZpbml0aW9ucyI6eyJvd25lZCI6W3siZ3JvdXAiOiJ0ZXN0LmZvbyIsImtpbmQiOiJGb28iLCJuYW1lIjoiZm9vcy50ZXN0LmZvbyIsInZlcnNpb24iOiJ2MSJ9XX0sImRpc3BsYXlOYW1lIjoiRm9vIE9wZXJhdG9yIiwicmVsYXRlZEltYWdlcyI6W3siaW1hZ2UiOiJ0ZXN0LnJlZ2lzdHJ5L2Zvby1vcGVyYXRvci9mb286djAuMS4wIiwibmFtZSI6Im9wZXJhdG9yIn1dLCJ2ZXJzaW9uIjoiMC4xLjAifX0= relatedImages: - image: test.registry/foo-operator/foo-bundle:v0.1.0 name: "" @@ -265,18 +270,12 @@ properties: value: packageName: bar versionRange: <0.1.0 -- type: olm.csv.metadata - value: - annotations: - olm.skipRange: <0.2.0 - apiServiceDefinitions: {} - crdDescriptions: - owned: - - kind: Foo - name: foos.test.foo - version: v1 - displayName: Foo Operator - provider: {} +- type: olm.bundle.object + value: + data: eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjEiLCJraW5kIjoiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uIiwibWV0YWRhdGEiOnsibmFtZSI6ImZvb3MudGVzdC5mb28ifSwic3BlYyI6eyJncm91cCI6InRlc3QuZm9vIiwibmFtZXMiOnsia2luZCI6IkZvbyIsInBsdXJhbCI6ImZvb3MifSwidmVyc2lvbnMiOlt7Im5hbWUiOiJ2MSJ9XX19 +- type: olm.bundle.object + value: + data: eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsib2xtLnNraXBSYW5nZSI6Ilx1MDAzYzAuMi4wIn0sIm5hbWUiOiJmb28udjAuMi4wIn0sInNwZWMiOnsiY3VzdG9tcmVzb3VyY2VkZWZpbml0aW9ucyI6eyJvd25lZCI6W3siZ3JvdXAiOiJ0ZXN0LmZvbyIsImtpbmQiOiJGb28iLCJuYW1lIjoiZm9vcy50ZXN0LmZvbyIsInZlcnNpb24iOiJ2MSJ9XX0sImRpc3BsYXlOYW1lIjoiRm9vIE9wZXJhdG9yIiwiaW5zdGFsbCI6eyJzcGVjIjp7ImRlcGxveW1lbnRzIjpbeyJuYW1lIjoiZm9vLW9wZXJhdG9yIiwic3BlYyI6eyJ0ZW1wbGF0ZSI6eyJzcGVjIjp7ImNvbnRhaW5lcnMiOlt7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9mb28tb3BlcmF0b3IvZm9vOnYwLjIuMCJ9XSwiaW5pdENvbnRhaW5lcnMiOlt7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9mb28tb3BlcmF0b3IvZm9vLWluaXQ6djAuMi4wIn1dfX19fSx7Im5hbWUiOiJmb28tb3BlcmF0b3ItMiIsInNwZWMiOnsidGVtcGxhdGUiOnsic3BlYyI6eyJjb250YWluZXJzIjpbeyJpbWFnZSI6InRlc3QucmVnaXN0cnkvZm9vLW9wZXJhdG9yL2Zvby0yOnYwLjIuMCJ9XSwiaW5pdENvbnRhaW5lcnMiOlt7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9mb28tb3BlcmF0b3IvZm9vLWluaXQtMjp2MC4yLjAifV19fX19XX0sInN0cmF0ZWd5IjoiZGVwbG95bWVudCJ9LCJyZWxhdGVkSW1hZ2VzIjpbeyJpbWFnZSI6InRlc3QucmVnaXN0cnkvZm9vLW9wZXJhdG9yL2Zvbzp2MC4yLjAiLCJuYW1lIjoib3BlcmF0b3IifSx7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9mb28tb3BlcmF0b3IvZm9vLW90aGVyOnYwLjIuMCIsIm5hbWUiOiJvdGhlciJ9XSwicmVwbGFjZXMiOiJmb28udjAuMS4wIiwic2tpcHMiOlsiZm9vLnYwLjEuMSIsImZvby52MC4xLjIiXSwidmVyc2lvbiI6IjAuMi4wIn19 relatedImages: - image: test.registry/foo-operator/foo-2:v0.2.0 name: "" @@ -292,6 +291,7 @@ relatedImages: name: operator schema: olm.bundle ` + } func migrateBarCatalogSqlite() string { @@ -323,15 +323,12 @@ properties: value: packageName: bar version: 0.1.0 -- type: olm.csv.metadata - value: - apiServiceDefinitions: {} - crdDescriptions: - owned: - - kind: Bar - name: bars.test.bar - version: v1alpha1 - provider: {} +- type: olm.bundle.object + value: + data: eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjEiLCJraW5kIjoiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uIiwibWV0YWRhdGEiOnsibmFtZSI6ImJhcnMudGVzdC5iYXIifSwic3BlYyI6eyJncm91cCI6InRlc3QuYmFyIiwibmFtZXMiOnsia2luZCI6IkJhciIsInBsdXJhbCI6ImJhcnMifSwidmVyc2lvbnMiOlt7Im5hbWUiOiJ2MWFscGhhMSJ9XX19 +- type: olm.bundle.object + value: + data: eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsibmFtZSI6ImJhci52MC4xLjAifSwic3BlYyI6eyJjdXN0b21yZXNvdXJjZWRlZmluaXRpb25zIjp7Im93bmVkIjpbeyJncm91cCI6InRlc3QuYmFyIiwia2luZCI6IkJhciIsIm5hbWUiOiJiYXJzLnRlc3QuYmFyIiwidmVyc2lvbiI6InYxYWxwaGExIn1dfSwicmVsYXRlZEltYWdlcyI6W3siaW1hZ2UiOiJ0ZXN0LnJlZ2lzdHJ5L2Jhci1vcGVyYXRvci9iYXI6djAuMS4wIiwibmFtZSI6Im9wZXJhdG9yIn1dLCJ2ZXJzaW9uIjoiMC4xLjAifX0= relatedImages: - image: test.registry/bar-operator/bar-bundle:v0.1.0 name: "" @@ -352,17 +349,12 @@ properties: value: packageName: bar version: 0.2.0 -- type: olm.csv.metadata - value: - annotations: - olm.skipRange: <0.2.0 - apiServiceDefinitions: {} - crdDescriptions: - owned: - - kind: Bar - name: bars.test.bar - version: v1alpha1 - provider: {} +- type: olm.bundle.object + value: + data: eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjEiLCJraW5kIjoiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uIiwibWV0YWRhdGEiOnsibmFtZSI6ImJhcnMudGVzdC5iYXIifSwic3BlYyI6eyJncm91cCI6InRlc3QuYmFyIiwibmFtZXMiOnsia2luZCI6IkJhciIsInBsdXJhbCI6ImJhcnMifSwidmVyc2lvbnMiOlt7Im5hbWUiOiJ2MWFscGhhMSJ9XX19 +- type: olm.bundle.object + value: + data: eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsib2xtLnNraXBSYW5nZSI6Ilx1MDAzYzAuMi4wIn0sIm5hbWUiOiJiYXIudjAuMi4wIn0sInNwZWMiOnsiY3VzdG9tcmVzb3VyY2VkZWZpbml0aW9ucyI6eyJvd25lZCI6W3siZ3JvdXAiOiJ0ZXN0LmJhciIsImtpbmQiOiJCYXIiLCJuYW1lIjoiYmFycy50ZXN0LmJhciIsInZlcnNpb24iOiJ2MWFscGhhMSJ9XX0sInJlbGF0ZWRJbWFnZXMiOlt7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9iYXItb3BlcmF0b3IvYmFyOnYwLjIuMCIsIm5hbWUiOiJvcGVyYXRvciJ9XSwic2tpcHMiOlsiYmFyLnYwLjEuMCJdLCJ2ZXJzaW9uIjoiMC4yLjAifX0= relatedImages: - image: test.registry/bar-operator/bar-bundle:v0.2.0 name: "" @@ -434,18 +426,12 @@ properties: value: packageName: bar versionRange: <0.1.0 -- type: olm.csv.metadata - value: - annotations: - olm.skipRange: <0.1.0 - apiServiceDefinitions: {} - crdDescriptions: - owned: - - kind: Foo - name: foos.test.foo - version: v1 - displayName: Foo Operator - provider: {} +- type: olm.bundle.object + value: + data: eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsib2xtLnNraXBSYW5nZSI6Ilx1MDAzYzAuMS4wIn0sIm5hbWUiOiJmb28udjAuMS4wIn0sInNwZWMiOnsiY3VzdG9tcmVzb3VyY2VkZWZpbml0aW9ucyI6eyJvd25lZCI6W3siZ3JvdXAiOiJ0ZXN0LmZvbyIsImtpbmQiOiJGb28iLCJuYW1lIjoiZm9vcy50ZXN0LmZvbyIsInZlcnNpb24iOiJ2MSJ9XX0sImRpc3BsYXlOYW1lIjoiRm9vIE9wZXJhdG9yIiwicmVsYXRlZEltYWdlcyI6W3siaW1hZ2UiOiJ0ZXN0LnJlZ2lzdHJ5L2Zvby1vcGVyYXRvci9mb286djAuMS4wIiwibmFtZSI6Im9wZXJhdG9yIn1dLCJ2ZXJzaW9uIjoiMC4xLjAifX0= +- type: olm.bundle.object + value: + data: eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjEiLCJraW5kIjoiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uIiwibWV0YWRhdGEiOnsibmFtZSI6ImZvb3MudGVzdC5mb28ifSwic3BlYyI6eyJncm91cCI6InRlc3QuZm9vIiwibmFtZXMiOnsia2luZCI6IkZvbyIsInBsdXJhbCI6ImZvb3MifSwidmVyc2lvbnMiOlt7Im5hbWUiOiJ2MSJ9XX19 relatedImages: - image: test.registry/foo-operator/foo-bundle:v0.1.0 name: "" @@ -475,18 +461,12 @@ properties: value: packageName: bar versionRange: <0.1.0 -- type: olm.csv.metadata - value: - annotations: - olm.skipRange: <0.2.0 - apiServiceDefinitions: {} - crdDescriptions: - owned: - - kind: Foo - name: foos.test.foo - version: v1 - displayName: Foo Operator - provider: {} +- type: olm.bundle.object + value: + data: eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsib2xtLnNraXBSYW5nZSI6Ilx1MDAzYzAuMi4wIn0sIm5hbWUiOiJmb28udjAuMi4wIn0sInNwZWMiOnsiY3VzdG9tcmVzb3VyY2VkZWZpbml0aW9ucyI6eyJvd25lZCI6W3siZ3JvdXAiOiJ0ZXN0LmZvbyIsImtpbmQiOiJGb28iLCJuYW1lIjoiZm9vcy50ZXN0LmZvbyIsInZlcnNpb24iOiJ2MSJ9XX0sImRpc3BsYXlOYW1lIjoiRm9vIE9wZXJhdG9yIiwiaW5zdGFsbCI6eyJzcGVjIjp7ImRlcGxveW1lbnRzIjpbeyJuYW1lIjoiZm9vLW9wZXJhdG9yIiwic3BlYyI6eyJ0ZW1wbGF0ZSI6eyJzcGVjIjp7ImNvbnRhaW5lcnMiOlt7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9mb28tb3BlcmF0b3IvZm9vOnYwLjIuMCJ9XSwiaW5pdENvbnRhaW5lcnMiOlt7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9mb28tb3BlcmF0b3IvZm9vLWluaXQ6djAuMi4wIn1dfX19fSx7Im5hbWUiOiJmb28tb3BlcmF0b3ItMiIsInNwZWMiOnsidGVtcGxhdGUiOnsic3BlYyI6eyJjb250YWluZXJzIjpbeyJpbWFnZSI6InRlc3QucmVnaXN0cnkvZm9vLW9wZXJhdG9yL2Zvby0yOnYwLjIuMCJ9XSwiaW5pdENvbnRhaW5lcnMiOlt7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9mb28tb3BlcmF0b3IvZm9vLWluaXQtMjp2MC4yLjAifV19fX19XX0sInN0cmF0ZWd5IjoiZGVwbG95bWVudCJ9LCJyZWxhdGVkSW1hZ2VzIjpbeyJpbWFnZSI6InRlc3QucmVnaXN0cnkvZm9vLW9wZXJhdG9yL2Zvbzp2MC4yLjAiLCJuYW1lIjoib3BlcmF0b3IifSx7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9mb28tb3BlcmF0b3IvZm9vLW90aGVyOnYwLjIuMCIsIm5hbWUiOiJvdGhlciJ9XSwicmVwbGFjZXMiOiJmb28udjAuMS4wIiwic2tpcHMiOlsiZm9vLnYwLjEuMSIsImZvby52MC4xLjIiXSwidmVyc2lvbiI6IjAuMi4wIn19 +- type: olm.bundle.object + value: + data: eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjEiLCJraW5kIjoiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uIiwibWV0YWRhdGEiOnsibmFtZSI6ImZvb3MudGVzdC5mb28ifSwic3BlYyI6eyJncm91cCI6InRlc3QuZm9vIiwibmFtZXMiOnsia2luZCI6IkZvbyIsInBsdXJhbCI6ImZvb3MifSwidmVyc2lvbnMiOlt7Im5hbWUiOiJ2MSJ9XX19 relatedImages: - image: test.registry/foo-operator/foo-2:v0.2.0 name: "" diff --git a/alpha/action/migrations/000_bundle_object_to_csv_metadata.go b/alpha/action/migrations/000_bundle_object_to_csv_metadata.go new file mode 100644 index 000000000..d5c6896ea --- /dev/null +++ b/alpha/action/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" +) + +func bundleObjectToCSVMetadata(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/migrations/migrations.go b/alpha/action/migrations/migrations.go new file mode 100644 index 000000000..22ff86b74 --- /dev/null +++ b/alpha/action/migrations/migrations.go @@ -0,0 +1,104 @@ +package migrations + +import ( + "fmt" + "slices" + "strings" + "text/tabwriter" + + "github.com/operator-framework/operator-registry/alpha/declcfg" +) + +type MigrationToken string + +const ( + invalidMigration string = "" + NoMigrations string = "none" + AllMigrations string = "all" +) + +type Migration interface { + Token() MigrationToken + Help() string + Migrate(*declcfg.DeclarativeConfig) error +} + +func newMigration(token string, help string, fn func(config *declcfg.DeclarativeConfig) error) Migration { + return &simpleMigration{token: MigrationToken(token), help: help, fn: fn} +} + +type simpleMigration struct { + token MigrationToken + help string + fn func(*declcfg.DeclarativeConfig) error +} + +func (s simpleMigration) Token() MigrationToken { + return s.token +} + +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 +} + +// allMigrations represents the migration catalog +// the order of these migrations is important +var allMigrations = []Migration{ + newMigration(NoMigrations, "do nothing", func(_ *declcfg.DeclarativeConfig) error { return nil }), + newMigration("bundle-object-to-csv-metadata", `migrates bundles' "olm.bundle.object" to "olm.csv.metadata"`, bundleObjectToCSVMetadata), +} + +func NewMigrations(name string) (*Migrations, error) { + if name == AllMigrations { + return &Migrations{Migrations: slices.Clone(allMigrations)}, nil + } + + migrations := slices.Clone(allMigrations) + + found := false + keep := migrations[:0] + for _, migration := range migrations { + keep = append(keep, migration) + if migration.Token() == MigrationToken(name) { + found = true + break + } + } + if !found { + return nil, fmt.Errorf("unknown migration level %q", name) + } + return &Migrations{Migrations: keep}, nil +} + +func HelpText() string { + var help strings.Builder + help.WriteString("\nThe migrator will run all migrations up to and including the selected level.\n\n") + help.WriteString("Available migrators:\n") + if len(allMigrations) == 0 { + help.WriteString(" (no migrations available in this version)\n") + } + + tabber := tabwriter.NewWriter(&help, 0, 0, 1, ' ', 0) + for _, migration := range allMigrations { + fmt.Fprintf(tabber, " - %s\t: %s\n", migration.Token(), migration.Help()) + } + tabber.Flush() + 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 +} diff --git a/alpha/action/migrations/migrations_test.go b/alpha/action/migrations/migrations_test.go new file mode 100644 index 000000000..2d8eee035 --- /dev/null +++ b/alpha/action/migrations/migrations_test.go @@ -0,0 +1,139 @@ +package migrations + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/alpha/property" + "github.com/stretchr/testify/require" +) + +func TestMigrations(t *testing.T) { + noneMigration, err := NewMigrations(NoMigrations) + require.NoError(t, err) + csvMigration, err := NewMigrations("bundle-object-to-csv-metadata") + require.NoError(t, err) + allMigrations, err := NewMigrations(AllMigrations) + require.NoError(t, err) + + migrationPhaseEvaluators := map[MigrationToken]func(*declcfg.DeclarativeConfig) error{ + MigrationToken(NoMigrations): func(d *declcfg.DeclarativeConfig) error { + if diff := cmp.Diff(*d, unmigratedCatalogFBC()); diff != "" { + return fmt.Errorf("'none' migrator is not expected to change the config\n%s", diff) + } + return nil + }, + MigrationToken("bundle-object-to-csv-metadata"): func(d *declcfg.DeclarativeConfig) error { + if diff := cmp.Diff(*d, csvMetadataCatalogFBC()); diff != "" { + return fmt.Errorf("unexpected result of migration\n%s", diff) + } + return nil + }, + } + + tests := []struct { + name string + migrators *Migrations + }{ + { + name: "NoMigrations", + migrators: noneMigration, + }, + { + name: "BundleObjectToCSVMetadata", + migrators: csvMigration, + }, + { + name: "MigrationSequence", + migrators: allMigrations, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + var config declcfg.DeclarativeConfig = unmigratedCatalogFBC() + + for _, m := range test.migrators.Migrations { + err := m.Migrate(&config) + require.NoError(t, err) + err = migrationPhaseEvaluators[m.Token()](&config) + require.NoError(t, err) + } + }) + } +} + +func mustBuildCSVMetadata(r io.Reader) property.Property { + var csv v1alpha1.ClusterServiceVersion + if err := json.NewDecoder(r).Decode(&csv); err != nil { + panic(err) + } + return property.MustBuildCSVMetadata(csv) +} + +var fooRawCsv = []byte(`{"apiVersion": "operators.coreos.com/v1alpha1", "kind": "ClusterServiceVersion", "metadata": {"name": "foo.v0.1.0"}, "spec": {"displayName": "Foo Operator", "customresourcedefinitions": {"owned": [{"group": "test.foo", "version": "v1", "kind": "Foo", "name": "foos.test.foo"}]}, "version": "0.1.0", "relatedImages": [{"name": "operator", "image": "test.registry/foo-operator/foo:v0.1.0"}]}}`) + +var fooRawCrd = []byte(`--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: foos.test.foo +spec: + group: test.foo + names: + kind: Foo + plural: foos + versions: + - name: v1`, +) + +func unmigratedCatalogFBC() declcfg.DeclarativeConfig { + return declcfg.DeclarativeConfig{ + Bundles: []declcfg.Bundle{ + { + Schema: "olm.bundle", + Name: "foo.v0.1.0", + Package: "foo", + Image: "quay.io/openshift-community-operators/foo:v0.1.0", + Properties: []property.Property{ + property.MustBuildGVK("test.foo", "v1", "Foo"), + property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), + property.MustBuildPackage("foo", "0.1.0"), + property.MustBuildPackageRequired("bar", "<0.1.0"), + property.MustBuildBundleObject(fooRawCrd), + property.MustBuildBundleObject(fooRawCsv), + }, + Objects: []string{string(fooRawCsv), string(fooRawCrd)}, + CsvJSON: string(fooRawCsv), + }, + }, + } +} + +func csvMetadataCatalogFBC() declcfg.DeclarativeConfig { + return declcfg.DeclarativeConfig{ + Bundles: []declcfg.Bundle{ + { + Schema: "olm.bundle", + Name: "foo.v0.1.0", + Package: "foo", + Image: "quay.io/openshift-community-operators/foo:v0.1.0", + Properties: []property.Property{ + property.MustBuildGVK("test.foo", "v1", "Foo"), + property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), + property.MustBuildPackage("foo", "0.1.0"), + property.MustBuildPackageRequired("bar", "<0.1.0"), + mustBuildCSVMetadata(bytes.NewReader(fooRawCsv)), + }, + Objects: []string{string(fooRawCsv), string(fooRawCrd)}, + CsvJSON: string(fooRawCsv), + }, + }, + } +} diff --git a/alpha/action/render.go b/alpha/action/render.go index be63aab53..798ffb5e5 100644 --- a/alpha/action/render.go +++ b/alpha/action/render.go @@ -15,9 +15,9 @@ import ( "github.com/h2non/filetype" "github.com/h2non/filetype/matchers" - "github.com/operator-framework/api/pkg/operators/v1alpha1" "k8s.io/apimachinery/pkg/util/sets" + "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" @@ -54,8 +54,8 @@ type Render struct { Refs []string Registry image.Registry AllowedRefMask RefType - Migrate bool ImageRefTemplate *template.Template + Migrations *migrations.Migrations skipSqliteDeprecationLog bool } @@ -88,10 +88,8 @@ func (r Render) Run(ctx context.Context) (*declcfg.DeclarativeConfig, error) { }) } - if r.Migrate { - if err := migrate(cfg); err != nil { - return nil, fmt.Errorf("migrate: %v", err) - } + if err := r.migrate(cfg); err != nil { + return nil, fmt.Errorf("migrate: %v", err) } cfgs = append(cfgs, *cfg) @@ -416,48 +414,12 @@ func moveBundleObjectsToEndOfPropertySlices(cfg *declcfg.DeclarativeConfig) { } } -func migrate(cfg *declcfg.DeclarativeConfig) error { - migrations := []func(*declcfg.DeclarativeConfig) error{ - convertObjectsToCSVMetadata, - } - - for _, m := range migrations { - if err := m(cfg); err != nil { - return err - } - } - return nil -} - -func convertObjectsToCSVMetadata(cfg *declcfg.DeclarativeConfig) error { -BundleLoop: - for bi, b := range cfg.Bundles { - if b.Image == "" || b.CsvJSON == "" { - continue - } - - 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. - continue BundleLoop - default: - // Keep all of the other properties - props = append(props, p) - } - } - cfg.Bundles[bi].Properties = append(props, property.MustBuildCSVMetadata(csv)) +func (r Render) migrate(cfg *declcfg.DeclarativeConfig) error { + // If there are no migrations, do nothing. + if r.Migrations == nil { + return nil } - return nil + return r.Migrations.Migrate(cfg) } func combineConfigs(cfgs []declcfg.DeclarativeConfig) *declcfg.DeclarativeConfig { diff --git a/alpha/action/render_test.go b/alpha/action/render_test.go index b1ee6840f..3c69d4a26 100644 --- a/alpha/action/render_test.go +++ b/alpha/action/render_test.go @@ -1,12 +1,11 @@ package action_test import ( - "bytes" "context" "embed" "encoding/json" "errors" - "io" + "fmt" "io/fs" "os" "path/filepath" @@ -14,12 +13,12 @@ import ( "testing/fstest" "text/template" - "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "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/alpha/property" "github.com/operator-framework/operator-registry/pkg/containertools" @@ -29,6 +28,22 @@ import ( "github.com/operator-framework/operator-registry/pkg/sqlite" ) +type fauxMigration struct { + token string + help string + migrate func(*declcfg.DeclarativeConfig) error +} + +func (m fauxMigration) Token() migrations.MigrationToken { + return migrations.MigrationToken(m.token) +} +func (m fauxMigration) Help() string { + return m.help +} +func (m fauxMigration) Migrate(config *declcfg.DeclarativeConfig) error { + return m.migrate(config) +} + func TestRender(t *testing.T) { type spec struct { name string @@ -72,6 +87,16 @@ func TestRender(t *testing.T) { image.SimpleReference("test.registry/foo-operator/foo-bundle:v0.2.0"): "testdata/foo-bundle-v0.2.0", } assert.NoError(t, generateSqliteFile(dbFile, imageMap)) + testMigrations := migrations.Migrations{ + Migrations: []migrations.Migration{ + fauxMigration{"faux-migration", "my help text", func(d *declcfg.DeclarativeConfig) error { + for i, _ := range d.Bundles { + d.Bundles[i].Name = fmt.Sprintf("%s-MIGRATED", d.Bundles[i].Name) + } + return nil + }}, + }, + } specs := []spec{ { @@ -109,7 +134,8 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.1.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - mustBuildCSVMetadata(bytes.NewReader(foov1csv)), + property.MustBuildBundleObject(foov1crd), + property.MustBuildBundleObject(foov1csv), }, RelatedImages: []declcfg.RelatedImage{ { @@ -133,7 +159,101 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.2.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - mustBuildCSVMetadata(bytes.NewReader(foov2csv)), + property.MustBuildBundleObject(foov2crd), + property.MustBuildBundleObject(foov2csv), + }, + RelatedImages: []declcfg.RelatedImage{ + { + Image: "test.registry/foo-operator/foo-2:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-bundle:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-init-2:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-init:v0.2.0", + }, + { + Name: "other", + Image: "test.registry/foo-operator/foo-other:v0.2.0", + }, + { + Name: "operator", + Image: "test.registry/foo-operator/foo:v0.2.0", + }, + }, + CsvJSON: string(foov2csv), + Objects: []string{string(foov2csv), string(foov2crd)}, + }, + }, + }, + assertion: require.NoError, + }, + { + name: "Success/SqliteIndexImageWithMigration", + render: action.Render{ + Refs: []string{"test.registry/foo-operator/foo-index-sqlite:v0.2.0"}, + Registry: reg, + Migrations: &testMigrations, + }, + expectCfg: &declcfg.DeclarativeConfig{ + Packages: []declcfg.Package{ + { + Schema: "olm.package", + Name: "foo", + DefaultChannel: "beta", + }, + }, + Channels: []declcfg.Channel{ + {Schema: "olm.channel", Package: "foo", Name: "beta", Entries: []declcfg.ChannelEntry{ + {Name: "foo.v0.1.0", SkipRange: "<0.1.0"}, + {Name: "foo.v0.2.0", Replaces: "foo.v0.1.0", SkipRange: "<0.2.0", Skips: []string{"foo.v0.1.1", "foo.v0.1.2"}}, + }}, + {Schema: "olm.channel", Package: "foo", Name: "stable", Entries: []declcfg.ChannelEntry{ + {Name: "foo.v0.1.0", SkipRange: "<0.1.0"}, + {Name: "foo.v0.2.0", Replaces: "foo.v0.1.0", SkipRange: "<0.2.0", Skips: []string{"foo.v0.1.1", "foo.v0.1.2"}}, + }}, + }, + Bundles: []declcfg.Bundle{ + { + Schema: "olm.bundle", + Name: "foo.v0.1.0-MIGRATED", + Package: "foo", + Image: "test.registry/foo-operator/foo-bundle:v0.1.0", + Properties: []property.Property{ + property.MustBuildGVK("test.foo", "v1", "Foo"), + property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), + property.MustBuildPackage("foo", "0.1.0"), + property.MustBuildPackageRequired("bar", "<0.1.0"), + property.MustBuildBundleObject(foov1crd), + property.MustBuildBundleObject(foov1csv), + }, + RelatedImages: []declcfg.RelatedImage{ + { + Image: "test.registry/foo-operator/foo-bundle:v0.1.0", + }, + { + Name: "operator", + Image: "test.registry/foo-operator/foo:v0.1.0", + }, + }, + CsvJSON: string(foov1csv), + Objects: []string{string(foov1csv), string(foov1crd)}, + }, + { + Schema: "olm.bundle", + Name: "foo.v0.2.0-MIGRATED", + Package: "foo", + Image: "test.registry/foo-operator/foo-bundle:v0.2.0", + Properties: []property.Property{ + property.MustBuildGVK("test.foo", "v1", "Foo"), + property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), + property.MustBuildPackage("foo", "0.2.0"), + property.MustBuildPackageRequired("bar", "<0.1.0"), + property.MustBuildBundleObject(foov2crd), + property.MustBuildBundleObject(foov2csv), }, RelatedImages: []declcfg.RelatedImage{ { @@ -199,7 +319,8 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.1.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - mustBuildCSVMetadata(bytes.NewReader(foov1csv)), + property.MustBuildBundleObject(foov1crd), + property.MustBuildBundleObject(foov1csv), }, RelatedImages: []declcfg.RelatedImage{ { @@ -223,7 +344,101 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.2.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - mustBuildCSVMetadata(bytes.NewReader(foov2csv)), + property.MustBuildBundleObject(foov2crd), + property.MustBuildBundleObject(foov2csv), + }, + RelatedImages: []declcfg.RelatedImage{ + { + Image: "test.registry/foo-operator/foo-2:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-bundle:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-init-2:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-init:v0.2.0", + }, + { + Name: "other", + Image: "test.registry/foo-operator/foo-other:v0.2.0", + }, + { + Name: "operator", + Image: "test.registry/foo-operator/foo:v0.2.0", + }, + }, + CsvJSON: string(foov2csv), + Objects: []string{string(foov2csv), string(foov2crd)}, + }, + }, + }, + assertion: require.NoError, + }, + { + name: "Success/SqliteFileMigration", + render: action.Render{ + Refs: []string{dbFile}, + Registry: reg, + Migrations: &testMigrations, + }, + expectCfg: &declcfg.DeclarativeConfig{ + Packages: []declcfg.Package{ + { + Schema: "olm.package", + Name: "foo", + DefaultChannel: "beta", + }, + }, + Channels: []declcfg.Channel{ + {Schema: "olm.channel", Package: "foo", Name: "beta", Entries: []declcfg.ChannelEntry{ + {Name: "foo.v0.1.0", SkipRange: "<0.1.0"}, + {Name: "foo.v0.2.0", Replaces: "foo.v0.1.0", SkipRange: "<0.2.0", Skips: []string{"foo.v0.1.1", "foo.v0.1.2"}}, + }}, + {Schema: "olm.channel", Package: "foo", Name: "stable", Entries: []declcfg.ChannelEntry{ + {Name: "foo.v0.1.0", SkipRange: "<0.1.0"}, + {Name: "foo.v0.2.0", Replaces: "foo.v0.1.0", SkipRange: "<0.2.0", Skips: []string{"foo.v0.1.1", "foo.v0.1.2"}}, + }}, + }, + Bundles: []declcfg.Bundle{ + { + Schema: "olm.bundle", + Name: "foo.v0.1.0-MIGRATED", + Package: "foo", + Image: "test.registry/foo-operator/foo-bundle:v0.1.0", + Properties: []property.Property{ + property.MustBuildGVK("test.foo", "v1", "Foo"), + property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), + property.MustBuildPackage("foo", "0.1.0"), + property.MustBuildPackageRequired("bar", "<0.1.0"), + property.MustBuildBundleObject(foov1crd), + property.MustBuildBundleObject(foov1csv), + }, + RelatedImages: []declcfg.RelatedImage{ + { + Image: "test.registry/foo-operator/foo-bundle:v0.1.0", + }, + { + Name: "operator", + Image: "test.registry/foo-operator/foo:v0.1.0", + }, + }, + CsvJSON: string(foov1csv), + Objects: []string{string(foov1csv), string(foov1crd)}, + }, + { + Schema: "olm.bundle", + Name: "foo.v0.2.0-MIGRATED", + Package: "foo", + Image: "test.registry/foo-operator/foo-bundle:v0.2.0", + Properties: []property.Property{ + property.MustBuildGVK("test.foo", "v1", "Foo"), + property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), + property.MustBuildPackage("foo", "0.2.0"), + property.MustBuildPackageRequired("bar", "<0.1.0"), + property.MustBuildBundleObject(foov2crd), + property.MustBuildBundleObject(foov2csv), }, RelatedImages: []declcfg.RelatedImage{ { @@ -453,9 +668,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"}, + Registry: reg, + Migrations: &testMigrations, }, expectCfg: &declcfg.DeclarativeConfig{ Packages: []declcfg.Package{ @@ -484,7 +699,7 @@ func TestRender(t *testing.T) { Bundles: []declcfg.Bundle{ { Schema: "olm.bundle", - Name: "foo.v0.1.0", + Name: "foo.v0.1.0-MIGRATED", Package: "foo", Image: "test.registry/foo-operator/foo-bundle:v0.1.0", Properties: []property.Property{ @@ -492,7 +707,8 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.1.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - mustBuildCSVMetadata(bytes.NewReader(foov1csv)), + property.MustBuildBundleObject(foov1csv), + property.MustBuildBundleObject(foov1crd), }, RelatedImages: []declcfg.RelatedImage{ { @@ -508,7 +724,7 @@ func TestRender(t *testing.T) { }, { Schema: "olm.bundle", - Name: "foo.v0.2.0", + Name: "foo.v0.2.0-MIGRATED", Package: "foo", Image: "test.registry/foo-operator/foo-bundle:v0.2.0", Properties: []property.Property{ @@ -516,7 +732,8 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.2.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - mustBuildCSVMetadata(bytes.NewReader(foov2csv)), + property.MustBuildBundleObject(foov2csv), + property.MustBuildBundleObject(foov2crd), }, RelatedImages: []declcfg.RelatedImage{ { @@ -550,9 +767,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"}, + Registry: reg, + Migrations: &testMigrations, }, expectCfg: &declcfg.DeclarativeConfig{ Packages: []declcfg.Package{ @@ -581,7 +798,7 @@ func TestRender(t *testing.T) { Bundles: []declcfg.Bundle{ { Schema: "olm.bundle", - Name: "foo.v0.1.0", + Name: "foo.v0.1.0-MIGRATED", Package: "foo", Image: "test.registry/foo-operator/foo-bundle:v0.1.0", Properties: []property.Property{ @@ -589,7 +806,8 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.1.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - mustBuildCSVMetadata(bytes.NewReader(foov1csv)), + property.MustBuildBundleObject(foov1csv), + property.MustBuildBundleObject(foov1crd), }, RelatedImages: []declcfg.RelatedImage{ { @@ -605,7 +823,7 @@ func TestRender(t *testing.T) { }, { Schema: "olm.bundle", - Name: "foo.v0.2.0", + Name: "foo.v0.2.0-MIGRATED", Package: "foo", Image: "test.registry/foo-operator/foo-bundle:v0.2.0", Properties: []property.Property{ @@ -613,7 +831,8 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.2.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - mustBuildCSVMetadata(bytes.NewReader(foov2csv)), + property.MustBuildBundleObject(foov2csv), + property.MustBuildBundleObject(foov2crd), }, RelatedImages: []declcfg.RelatedImage{ { @@ -662,7 +881,59 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.2.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - mustBuildCSVMetadata(bytes.NewReader(foov2csv)), + property.MustBuildBundleObject(foov2crd), + property.MustBuildBundleObject(foov2csv), + }, + Objects: []string{string(foov2csv), string(foov2crd)}, + CsvJSON: string(foov2csv), + RelatedImages: []declcfg.RelatedImage{ + { + Image: "test.registry/foo-operator/foo-2:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-bundle:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-init-2:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-init:v0.2.0", + }, + { + Name: "other", + Image: "test.registry/foo-operator/foo-other:v0.2.0", + }, + { + Name: "operator", + Image: "test.registry/foo-operator/foo:v0.2.0", + }, + }, + }, + }, + }, + assertion: require.NoError, + }, + { + name: "Success/BundleImageMigration", + render: action.Render{ + Refs: []string{"test.registry/foo-operator/foo-bundle:v0.2.0"}, + Registry: reg, + Migrations: &testMigrations, + }, + expectCfg: &declcfg.DeclarativeConfig{ + Bundles: []declcfg.Bundle{ + { + Schema: "olm.bundle", + Name: "foo.v0.2.0-MIGRATED", + Package: "foo", + Image: "test.registry/foo-operator/foo-bundle:v0.2.0", + Properties: []property.Property{ + property.MustBuildGVK("test.foo", "v1", "Foo"), + property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), + property.MustBuildPackage("foo", "0.2.0"), + property.MustBuildPackageRequired("bar", "<0.1.0"), + property.MustBuildBundleObject(foov2crd), + property.MustBuildBundleObject(foov2csv), }, Objects: []string{string(foov2csv), string(foov2crd)}, CsvJSON: string(foov2csv), @@ -711,7 +982,54 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.2.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - mustBuildCSVMetadata(bytes.NewReader(foov2csvNoRelatedImages)), + property.MustBuildBundleObject(foov2crdNoRelatedImages), + property.MustBuildBundleObject(foov2csvNoRelatedImages), + }, + Objects: []string{string(foov2csvNoRelatedImages), string(foov2crdNoRelatedImages)}, + CsvJSON: string(foov2csvNoRelatedImages), + RelatedImages: []declcfg.RelatedImage{ + { + Image: "test.registry/foo-operator/foo-2:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-bundle-no-csv-related-images:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-init-2:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-init:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo:v0.2.0", + }, + }, + }, + }, + }, + assertion: require.NoError, + }, + { + name: "Success/BundleImageWithNoCSVRelatedImagesMigration", + render: action.Render{ + Refs: []string{"test.registry/foo-operator/foo-bundle-no-csv-related-images:v0.2.0"}, + Registry: reg, + Migrations: &testMigrations, + }, + expectCfg: &declcfg.DeclarativeConfig{ + Bundles: []declcfg.Bundle{ + { + Schema: "olm.bundle", + Name: "foo.v0.2.0-MIGRATED", + Package: "foo", + Image: "test.registry/foo-operator/foo-bundle-no-csv-related-images:v0.2.0", + Properties: []property.Property{ + property.MustBuildGVK("test.foo", "v1", "Foo"), + property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), + property.MustBuildPackage("foo", "0.2.0"), + property.MustBuildPackageRequired("bar", "<0.1.0"), + property.MustBuildBundleObject(foov2crd), + property.MustBuildBundleObject(foov2csvNoRelatedImages), }, Objects: []string{string(foov2csvNoRelatedImages), string(foov2crdNoRelatedImages)}, CsvJSON: string(foov2csvNoRelatedImages), @@ -756,7 +1074,57 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.2.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - mustBuildCSVMetadata(bytes.NewReader(foov2csv)), + property.MustBuildBundleObject(foov2crd), + property.MustBuildBundleObject(foov2csv), + }, + Objects: []string{string(foov2csv), string(foov2crd)}, + CsvJSON: string(foov2csv), + RelatedImages: []declcfg.RelatedImage{ + { + Image: "test.registry/foo-operator/foo-2:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-init-2:v0.2.0", + }, + { + Image: "test.registry/foo-operator/foo-init:v0.2.0", + }, + { + Name: "other", + Image: "test.registry/foo-operator/foo-other:v0.2.0", + }, + { + Name: "operator", + Image: "test.registry/foo-operator/foo:v0.2.0", + }, + }, + }, + }, + }, + assertion: require.NoError, + }, + { + name: "Success/BundleDirectoryWithImageRefTemplateMigration", + render: action.Render{ + Refs: []string{"testdata/foo-bundle-v0.2.0"}, + ImageRefTemplate: template.Must(template.New("imageRef").Parse("test.registry/{{.Package}}-operator/{{.Package}}:v{{.Version}}")), + Registry: reg, + Migrations: &testMigrations, + }, + expectCfg: &declcfg.DeclarativeConfig{ + Bundles: []declcfg.Bundle{ + { + Schema: "olm.bundle", + Name: "foo.v0.2.0-MIGRATED", + Package: "foo", + Image: "test.registry/foo-operator/foo:v0.2.0", + Properties: []property.Property{ + property.MustBuildGVK("test.foo", "v1", "Foo"), + property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), + property.MustBuildPackage("foo", "0.2.0"), + property.MustBuildPackageRequired("bar", "<0.1.0"), + property.MustBuildBundleObject(foov2crd), + property.MustBuildBundleObject(foov2csv), }, Objects: []string{string(foov2csv), string(foov2crd)}, CsvJSON: string(foov2csv), @@ -1195,11 +1563,3 @@ func generateSqliteFile(path string, imageMap map[image.Reference]string) error } return nil } - -func mustBuildCSVMetadata(r io.Reader) property.Property { - var csv v1alpha1.ClusterServiceVersion - if err := json.NewDecoder(r).Decode(&csv); err != nil { - panic(err) - } - return property.MustBuildCSVMetadata(csv) -} diff --git a/alpha/template/basic/basic.go b/alpha/template/basic/basic.go index 73a6327e9..0456dc151 100644 --- a/alpha/template/basic/basic.go +++ b/alpha/template/basic/basic.go @@ -6,16 +6,19 @@ import ( "fmt" "io" + "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" - "k8s.io/apimachinery/pkg/util/yaml" ) const schema string = "olm.template.basic" type Template struct { - Registry image.Registry + Registry image.Registry + Migrations *migrations.Migrations } type BasicTemplate struct { @@ -58,6 +61,7 @@ func (t Template) Render(ctx context.Context, reader io.Reader) (*declcfg.Declar r := action.Render{ Registry: t.Registry, AllowedRefMask: action.RefBundleImage, + Migrations: t.Migrations, } for _, b := range cfg.Bundles { diff --git a/alpha/template/semver/semver.go b/alpha/template/semver/semver.go index a580fbc01..dfd584a1c 100644 --- a/alpha/template/semver/semver.go +++ b/alpha/template/semver/semver.go @@ -6,13 +6,13 @@ import ( "io" "sort" - "github.com/operator-framework/operator-registry/alpha/action" - "github.com/operator-framework/operator-registry/alpha/declcfg" - "github.com/operator-framework/operator-registry/alpha/property" - "github.com/blang/semver/v4" "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" ) func (t Template) Render(ctx context.Context) (*declcfg.DeclarativeConfig, error) { @@ -35,6 +35,7 @@ func (t Template) Render(ctx context.Context) (*declcfg.DeclarativeConfig, error AllowedRefMask: action.RefBundleImage, Refs: []string{b}, Registry: t.Registry, + Migrations: t.Migrations, } c, err := r.Run(ctx) if err != nil { diff --git a/alpha/template/semver/types.go b/alpha/template/semver/types.go index 971718b34..f170074c3 100644 --- a/alpha/template/semver/types.go +++ b/alpha/template/semver/types.go @@ -4,13 +4,16 @@ import ( "io" "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 + Data io.Reader + Registry image.Registry + Migrations *migrations.Migrations } // IO structs -- BEGIN diff --git a/cmd/opm/alpha/render-graph/cmd.go b/cmd/opm/alpha/render-graph/cmd.go index d3f7523e1..29d36eef9 100644 --- a/cmd/opm/alpha/render-graph/cmd.go +++ b/cmd/opm/alpha/render-graph/cmd.go @@ -5,11 +5,12 @@ import ( "log" "os" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/operator-framework/operator-registry/alpha/action" "github.com/operator-framework/operator-registry/alpha/declcfg" "github.com/operator-framework/operator-registry/cmd/opm/internal/util" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" ) func NewCmd() *cobra.Command { diff --git a/cmd/opm/alpha/template/basic.go b/cmd/opm/alpha/template/basic.go index 91f4c75d7..b1b77a888 100644 --- a/cmd/opm/alpha/template/basic.go +++ b/cmd/opm/alpha/template/basic.go @@ -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" @@ -15,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", @@ -62,6 +64,14 @@ When FILE is '-' or not provided, the template is read from standard input`, template.Registry = reg + if migrateLevel != "" { + m, err := migrations.NewMigrations(migrateLevel) + if err != nil { + log.Fatal(err) + } + template.Migrations = m + } + // only taking first file argument cfg, err := template.Render(cmd.Context(), data) if err != nil { @@ -73,5 +83,8 @@ When FILE is '-' or not provided, the template is read from standard input`, } }, } + + cmd.Flags().StringVar(&migrateLevel, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText()) + return cmd } diff --git a/cmd/opm/alpha/template/semver.go b/cmd/opm/alpha/template/semver.go index b498f6b78..e0547a67c 100644 --- a/cmd/opm/alpha/template/semver.go +++ b/cmd/opm/alpha/template/semver.go @@ -7,14 +7,19 @@ import ( "os" "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" - "github.com/spf13/cobra" ) func newSemverTemplateCmd() *cobra.Command { + var ( + migrateLevel string + ) + cmd := &cobra.Command{ Use: "semver [FILE]", Short: `Generate a file-based catalog from a single 'semver template' file @@ -67,6 +72,13 @@ When FILE is '-' or not provided, the template is read from standard input`, Data: data, Registry: reg, } + if migrateLevel != "" { + m, err := migrations.NewMigrations(migrateLevel) + if err != nil { + log.Fatal(err) + } + template.Migrations = m + } out, err := template.Render(cmd.Context()) if err != nil { log.Fatalf("semver %q: %v", source, err) @@ -82,5 +94,7 @@ When FILE is '-' or not provided, the template is read from standard input`, }, } + cmd.Flags().StringVar(&migrateLevel, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText()) + return cmd } diff --git a/cmd/opm/migrate/cmd.go b/cmd/opm/migrate/cmd.go index ca3126da2..edf496a33 100644 --- a/cmd/opm/migrate/cmd.go +++ b/cmd/opm/migrate/cmd.go @@ -7,14 +7,16 @@ 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" ) func NewCmd() *cobra.Command { var ( - migrate action.Migrate - output string + migrate action.Migrate + migrateLevel string + output string ) cmd := &cobra.Command{ Use: "migrate ", @@ -42,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 != "" { + m, err := migrations.NewMigrations(migrateLevel) + if err != nil { + log.Fatal(err) + } + migrate.Migrations = m + } + logrus.Infof("rendering index %q as file-based catalog", migrate.CatalogRef) if err := migrate.Run(cmd.Context()); err != nil { logrus.New().Fatal(err) @@ -51,5 +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(&migrateLevel, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText()) + return cmd } diff --git a/cmd/opm/render/cmd.go b/cmd/opm/render/cmd.go index 4cdd5e584..683d11a1c 100644 --- a/cmd/opm/render/cmd.go +++ b/cmd/opm/render/cmd.go @@ -10,6 +10,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/cmd/opm/internal/util" "github.com/operator-framework/operator-registry/pkg/sqlite" @@ -20,6 +21,9 @@ func NewCmd(showAlphaHelp bool) *cobra.Command { render action.Render output string imageRefTemplate string + + oldMigrateAllFlag bool + migrateLevel string ) cmd := &cobra.Command{ Use: "render [catalog-image | catalog-directory | bundle-image | bundle-directory | sqlite-file]...", @@ -63,6 +67,18 @@ database files. render.ImageRefTemplate = tmpl } + // if the deprecated flag was used, set the level explicitly to the last migration to perform all migrations + var m *migrations.Migrations + if oldMigrateAllFlag { + m, err = migrations.NewMigrations(migrations.AllMigrations) + } else if migrateLevel != "" { + m, err = migrations.NewMigrations(migrateLevel) + } + if err != nil { + log.Fatal(err) + } + render.Migrations = m + cfg, err := render.Run(cmd.Context()) if err != nil { log.Fatal(err) @@ -74,7 +90,10 @@ database files. }, } cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format of the streamed file-based catalog objects (json|yaml)") - cmd.Flags().BoolVar(&render.Migrate, "migrate", false, "Perform migrations on the rendered FBC") + + cmd.Flags().StringVar(&migrateLevel, "migrate-level", "", "Name of the last migration to run (default: none)\n"+migrations.HelpText()) + cmd.Flags().BoolVar(&oldMigrateAllFlag, "migrate", false, "Perform all available schema migrations on the rendered FBC") + cmd.MarkFlagsMutuallyExclusive("migrate", "migrate-level") // Alpha flags cmd.Flags().StringVar(&imageRefTemplate, "alpha-image-ref-template", "", "When bundle image reference information is unavailable, populate it with this template") diff --git a/pkg/api/api_to_model.go b/pkg/api/api_to_model.go index e9408c455..b478d7af0 100644 --- a/pkg/api/api_to_model.go +++ b/pkg/api/api_to_model.go @@ -5,8 +5,6 @@ import ( "fmt" "sort" - "github.com/operator-framework/api/pkg/operators/v1alpha1" - "github.com/operator-framework/operator-registry/alpha/model" "github.com/operator-framework/operator-registry/alpha/property" ) @@ -108,17 +106,8 @@ func convertAPIBundleToModelProperties(b *Bundle) ([]property.Property, error) { out = append(out, property.MustBuildGVKRequired(p.Group, p.Version, p.Kind)) } - // If there is a bundle image reference and a valid CSV, create an - // olm.csv.metadata property. Otherwise, create a bundle object property for - // each object in the bundle. - var csv v1alpha1.ClusterServiceVersion - csvErr := json.Unmarshal([]byte(b.CsvJson), &csv) - if csvErr == nil && b.BundlePath != "" { - out = append(out, property.MustBuildCSVMetadata(csv)) - } else { - for _, obj := range b.Object { - out = append(out, property.MustBuildBundleObject([]byte(obj))) - } + for _, obj := range b.Object { + out = append(out, property.MustBuildBundleObject([]byte(obj))) } sort.Slice(out, func(i, j int) bool { diff --git a/pkg/api/conversion_test.go b/pkg/api/conversion_test.go index 55dc94904..59b164bbc 100644 --- a/pkg/api/conversion_test.go +++ b/pkg/api/conversion_test.go @@ -59,7 +59,10 @@ func testModelBundle(t *testing.T) model.Bundle { property.MustBuildPackageRequired("test", ">=1.2.3 <2.0.0-0"), property.MustBuildGVKRequired("testapi.coreos.com", "v1", "Testapi"), property.MustBuildGVK("etcd.database.coreos.com", "v1beta2", "EtcdBackup"), - property.MustBuildCSVMetadata(csv), + property.MustBuildBundleObject([]byte(crdbackups)), + property.MustBuildBundleObject([]byte(crdclusters)), + property.MustBuildBundleObject([]byte(csvJson)), + property.MustBuildBundleObject([]byte(crdrestores)), }, CsvJSON: csvJson, Objects: []string{ diff --git a/pkg/registry/registry_to_model.go b/pkg/registry/registry_to_model.go index 431c4d1e0..0ba64c72d 100644 --- a/pkg/registry/registry_to_model.go +++ b/pkg/registry/registry_to_model.go @@ -5,9 +5,6 @@ import ( "fmt" "sort" - "github.com/operator-framework/api/pkg/operators" - "github.com/operator-framework/api/pkg/operators/v1alpha1" - "github.com/operator-framework/operator-registry/alpha/property" ) @@ -102,21 +99,8 @@ func ObjectsAndPropertiesFromBundle(b *Bundle) ([]string, []property.Property, e if err != nil { return nil, nil, fmt.Errorf("marshal object %s/%s (%s) to json: %v", obj.GetName(), obj.GetNamespace(), obj.GroupVersionKind(), err) } + props = append(props, property.MustBuildBundleObject(objData)) objects = append(objects, string(objData)) - - // Make an olm.bundle.object property if there is no bundle image set. - // Otherwise, make a olm.csv.metadata property if the object is a CSV - // (and fallback to olm.bundle.object if parsing the CSV fails). - if b.BundleImage == "" { - props = append(props, property.MustBuildBundleObject(objData)) - } else if obj.GetKind() == operators.ClusterServiceVersionKind { - var csv v1alpha1.ClusterServiceVersion - if err := json.Unmarshal(objData, &csv); err != nil { - props = append(props, property.MustBuildBundleObject(objData)) - } else { - props = append(props, property.MustBuildCSVMetadata(csv)) - } - } } if packageProvidedProperty == nil { diff --git a/pkg/registry/registry_to_model_test.go b/pkg/registry/registry_to_model_test.go index 264507fd7..25cd1ff1b 100644 --- a/pkg/registry/registry_to_model_test.go +++ b/pkg/registry/registry_to_model_test.go @@ -57,7 +57,9 @@ func testExpectedProperties(t *testing.T) []property.Property { Type: "olm.constraint", Value: json.RawMessage(`{"cel":{"rule":"properties.exists(p, p.type == \"certified\")"},"failureMessage":"require to have \"certified\""}`), }, - property.MustBuildCSVMetadata(csv), + } + for _, obj := range testExpectedObjects() { + props = append(props, property.MustBuildBundleObject([]byte(obj))) } return props } diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go index 307e47701..fbc551398 100644 --- a/pkg/server/server_test.go +++ b/pkg/server/server_test.go @@ -327,7 +327,7 @@ func TestGetBundle(t *testing.T) { } ) t.Run("Sqlite", testGetBundle(dbAddress, etcdoperator_v0_9_2("alpha", false, false, includeManifestsAll))) - t.Run("FBCCache", testGetBundle(cacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsCSVOnly))) + t.Run("FBCCache", testGetBundle(cacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsAll))) t.Run("FBCCacheWithDeprecations", testGetBundle(deprecationCacheAddress, cockroachBundle)) } @@ -351,7 +351,7 @@ func TestGetBundleForChannel(t *testing.T) { CsvJson: b.CsvJson + "\n", })) } - t.Run("FBCCache", testGetBundleForChannel(cacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsCSVOnly))) + t.Run("FBCCache", testGetBundleForChannel(cacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsAll))) } func testGetBundleForChannel(addr string, expected *api.Bundle) func(*testing.T) { @@ -456,7 +456,7 @@ func testGetChannelEntriesThatReplace(addr string, expected []*api.ChannelEntry) func TestGetBundleThatReplaces(t *testing.T) { t.Run("Sqlite", testGetBundleThatReplaces(dbAddress, etcdoperator_v0_9_2("alpha", false, false, includeManifestsAll))) - t.Run("FBCCache", testGetBundleThatReplaces(cacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsCSVOnly))) + t.Run("FBCCache", testGetBundleThatReplaces(cacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsAll))) } func testGetBundleThatReplaces(addr string, expected *api.Bundle) func(*testing.T) { @@ -472,7 +472,7 @@ func testGetBundleThatReplaces(addr string, expected *api.Bundle) func(*testing. func TestGetBundleThatReplacesSynthetic(t *testing.T) { t.Run("Sqlite", testGetBundleThatReplacesSynthetic(dbAddress, etcdoperator_v0_9_2("alpha", false, false, includeManifestsAll))) - t.Run("FBCCache", testGetBundleThatReplacesSynthetic(cacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsCSVOnly))) + t.Run("FBCCache", testGetBundleThatReplacesSynthetic(cacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsAll))) } func testGetBundleThatReplacesSynthetic(addr string, expected *api.Bundle) func(*testing.T) { @@ -682,7 +682,7 @@ func testGetLatestChannelEntriesThatProvide(addr string) func(t *testing.T) { func TestGetDefaultBundleThatProvides(t *testing.T) { t.Run("Sqlite", testGetDefaultBundleThatProvides(dbAddress, etcdoperator_v0_9_2("alpha", false, false, includeManifestsAll))) - t.Run("FBCCache", testGetDefaultBundleThatProvides(cacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsCSVOnly))) + t.Run("FBCCache", testGetDefaultBundleThatProvides(cacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsAll))) } func testGetDefaultBundleThatProvides(addr string, expected *api.Bundle) func(*testing.T) {