Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pkg/api/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func BundleStringToObjectStrings(bundleString string) ([]string, error) {
return objs, nil
}

func BundleStringToAPIBundle(bundleString string, entry *registry.ChannelEntry) (*Bundle, error) {
func BundleStringToAPIBundle(bundleString string, bundlepathString string, entry *registry.ChannelEntry) (*Bundle, error) {
objs, err := BundleStringToObjectStrings(bundleString)
if err != nil {
return nil, err
Expand All @@ -80,5 +80,6 @@ func BundleStringToAPIBundle(bundleString string, entry *registry.ChannelEntry)
}
out.ChannelName = entry.ChannelName
out.PackageName = entry.PackageName
out.BundlePath = bundlepathString
return out, nil
}
242 changes: 149 additions & 93 deletions pkg/api/registry.pb.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pkg/api/registry.proto
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ message Bundle{
string channelName = 3;
string csvJson = 4;
repeated string object = 5;
string bundlePath = 6;
}

message ChannelEntry{
Expand Down
16 changes: 8 additions & 8 deletions pkg/registry/empty.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ func (EmptyQuery) GetPackage(ctx context.Context, name string) (*PackageManifest
return nil, errors.New("empty querier: cannot get package")
}

func (EmptyQuery) GetBundle(ctx context.Context, pkgName, channelName, csvName string) (string, error) {
return "", errors.New("empty querier: cannot get bundle")
func (EmptyQuery) GetBundle(ctx context.Context, pkgName, channelName, csvName string) (string, string, error) {
return "", "", errors.New("empty querier: cannot get bundle")
}

func (EmptyQuery) GetBundleForChannel(ctx context.Context, pkgName string, channelName string) (string, error) {
return "", errors.New("empty querier: cannot get bundle for channel")
func (EmptyQuery) GetBundleForChannel(ctx context.Context, pkgName string, channelName string) (string, string, error) {
return "", "", errors.New("empty querier: cannot get bundle for channel")
}

func (EmptyQuery) GetChannelEntriesThatReplace(ctx context.Context, name string) (entries []*ChannelEntry, err error) {
return nil, errors.New("empty querier: cannot get channel entries that replace")
}

func (EmptyQuery) GetBundleThatReplaces(ctx context.Context, name, pkgName, channelName string) (string, error) {
return "", errors.New("empty querier: cannot get bundle that replaces")
func (EmptyQuery) GetBundleThatReplaces(ctx context.Context, name, pkgName, channelName string) (string, string, error) {
return "", "", errors.New("empty querier: cannot get bundle that replaces")
}

func (EmptyQuery) GetChannelEntriesThatProvide(ctx context.Context, group, version, kind string) (entries []*ChannelEntry, err error) {
Expand All @@ -46,8 +46,8 @@ func (EmptyQuery) GetLatestChannelEntriesThatProvide(ctx context.Context, group,
return nil, errors.New("empty querier: cannot get latest channel entries that provide")
}

func (EmptyQuery) GetBundleThatProvides(ctx context.Context, group, version, kind string) (string, *ChannelEntry, error) {
return "", nil, errors.New("empty querier: cannot get bundle that provides")
func (EmptyQuery) GetBundleThatProvides(ctx context.Context, group, version, kind string) (string, string, *ChannelEntry, error) {
return "", "", nil, errors.New("empty querier: cannot get bundle that provides")
}

func (EmptyQuery) ListImages(ctx context.Context) ([]string, error) {
Expand Down
8 changes: 4 additions & 4 deletions pkg/registry/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ type Query interface {
ListTables(ctx context.Context) ([]string, error)
ListPackages(ctx context.Context) ([]string, error)
GetPackage(ctx context.Context, name string) (*PackageManifest, error)
GetBundle(ctx context.Context, pkgName, channelName, csvName string) (string, error)
GetBundleForChannel(ctx context.Context, pkgName string, channelName string) (string, error)
GetBundle(ctx context.Context, pkgName, channelName, csvName string) (string, string, error)
GetBundleForChannel(ctx context.Context, pkgName string, channelName string) (string, string, error)
// Get all channel entries that say they replace this one
GetChannelEntriesThatReplace(ctx context.Context, name string) (entries []*ChannelEntry, err error)
// Get the bundle in a package/channel that replace this one
GetBundleThatReplaces(ctx context.Context, name, pkgName, channelName string) (string, error)
GetBundleThatReplaces(ctx context.Context, name, pkgName, channelName string) (string, string, error)
// Get all channel entries that provide an api
GetChannelEntriesThatProvide(ctx context.Context, group, version, kind string) (entries []*ChannelEntry, err error)
// Get latest channel entries that provide an api
GetLatestChannelEntriesThatProvide(ctx context.Context, group, version, kind string) (entries []*ChannelEntry, err error)
// Get the the latest bundle that provides the API in a default channel
GetBundleThatProvides(ctx context.Context, group, version, kind string) (string, *ChannelEntry, error)
GetBundleThatProvides(ctx context.Context, group, version, kind string) (string, string, *ChannelEntry, error)
// List all images in the database
ListImages(ctx context.Context) ([]string, error)
// List all images for a particular bundle
Expand Down
29 changes: 21 additions & 8 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,40 @@ func (s *RegistryServer) GetPackage(ctx context.Context, req *api.GetPackageRequ
}

func (s *RegistryServer) GetBundle(ctx context.Context, req *api.GetBundleRequest) (*api.Bundle, error) {
bundleString, err := s.store.GetBundle(ctx, req.GetPkgName(), req.GetChannelName(), req.GetCsvName())
bundleString, bundlepathString, err := s.store.GetBundle(ctx, req.GetPkgName(), req.GetChannelName(), req.GetCsvName())
if err != nil {
return nil, err
}
// If the value of the `bundle` field in the OperatorBundle table is NULL, return a
// Bundle struct with available fields
if bundleString == "" {
bundle := &api.Bundle{
PackageName: req.PkgName,
ChannelName: req.ChannelName,
CsvName: req.CsvName,
CsvJson: "",
Object: []string{},
BundlePath: bundlepathString,
}
return bundle, nil
}
entry := &registry.ChannelEntry{
PackageName: req.GetPkgName(),
ChannelName: req.GetChannelName(),
}
return api.BundleStringToAPIBundle(bundleString, entry)
return api.BundleStringToAPIBundle(bundleString, bundlepathString, entry)
}

func (s *RegistryServer) GetBundleForChannel(ctx context.Context, req *api.GetBundleInChannelRequest) (*api.Bundle, error) {
bundleString, err := s.store.GetBundleForChannel(ctx, req.GetPkgName(), req.GetChannelName())
bundleString, bundlepathString, err := s.store.GetBundleForChannel(ctx, req.GetPkgName(), req.GetChannelName())
if err != nil {
return nil, err
}
entry := &registry.ChannelEntry{
PackageName: req.GetPkgName(),
ChannelName: req.GetChannelName(),
}
return api.BundleStringToAPIBundle(bundleString, entry)
return api.BundleStringToAPIBundle(bundleString, bundlepathString, entry)
}

func (s *RegistryServer) GetChannelEntriesThatReplace(req *api.GetAllReplacementsRequest, stream api.Registry_GetChannelEntriesThatReplaceServer) error {
Expand All @@ -76,7 +89,7 @@ func (s *RegistryServer) GetChannelEntriesThatReplace(req *api.GetAllReplacement
}

func (s *RegistryServer) GetBundleThatReplaces(ctx context.Context, req *api.GetReplacementRequest) (*api.Bundle, error) {
bundleString, err := s.store.GetBundleThatReplaces(ctx, req.GetCsvName(), req.GetPkgName(), req.GetChannelName())
bundleString, bundlepathString, err := s.store.GetBundleThatReplaces(ctx, req.GetCsvName(), req.GetPkgName(), req.GetChannelName())
if err != nil {
return nil, err
}
Expand All @@ -85,7 +98,7 @@ func (s *RegistryServer) GetBundleThatReplaces(ctx context.Context, req *api.Get
ChannelName: req.GetChannelName(),
Replaces: req.GetCsvName(),
}
return api.BundleStringToAPIBundle(bundleString, entry)
return api.BundleStringToAPIBundle(bundleString, bundlepathString, entry)
}

func (s *RegistryServer) GetChannelEntriesThatProvide(req *api.GetAllProvidersRequest, stream api.Registry_GetChannelEntriesThatProvideServer) error {
Expand Down Expand Up @@ -115,9 +128,9 @@ func (s *RegistryServer) GetLatestChannelEntriesThatProvide(req *api.GetLatestPr
}

func (s *RegistryServer) GetDefaultBundleThatProvides(ctx context.Context, req *api.GetDefaultProviderRequest) (*api.Bundle, error) {
bundleString, channelEntry, err := s.store.GetBundleThatProvides(ctx, req.GetGroup(), req.GetVersion(), req.GetKind())
bundleString, bundlepathString, channelEntry, err := s.store.GetBundleThatProvides(ctx, req.GetGroup(), req.GetVersion(), req.GetKind())
if err != nil {
return nil, err
}
return api.BundleStringToAPIBundle(bundleString, channelEntry)
return api.BundleStringToAPIBundle(bundleString, bundlepathString, channelEntry)
}
5 changes: 5 additions & 0 deletions pkg/server/server_test.go

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions pkg/sqlite/configmap_test.go

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions pkg/sqlite/directory_test.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pkg/sqlite/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (s *SQLLoader) AddOperatorBundle(bundle *registry.Bundle) error {
tx.Rollback()
}()

stmt, err := tx.Prepare("insert into operatorbundle(name, csv, bundle) values(?, ?, ?)")
stmt, err := tx.Prepare("insert into operatorbundle(name, csv, bundle, bundlepath) values(?, ?, ?, ?)")
if err != nil {
return err
}
Expand All @@ -77,7 +77,7 @@ func (s *SQLLoader) AddOperatorBundle(bundle *registry.Bundle) error {
return fmt.Errorf("csv name not found")
}

if _, err := stmt.Exec(csvName, csvBytes, bundleBytes); err != nil {
if _, err := stmt.Exec(csvName, csvBytes, bundleBytes, nil); err != nil {
return err
}

Expand Down
55 changes: 55 additions & 0 deletions pkg/sqlite/migrations/002_bundle_path.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package migrations

import (
"context"
"database/sql"
)

const BundlePathMigrationKey = 2

var bundlePathMigration = &Migration{
Id: BundlePathMigrationKey,
Up: func(ctx context.Context, tx *sql.Tx) error {
sql := `
ALTER TABLE operatorbundle
ADD COLUMN bundlepath TEXT;
`
_, err := tx.ExecContext(ctx, sql)
return err
},
Down: func(ctx context.Context, tx *sql.Tx) error {
foreingKeyOff := `PRAGMA foreign_keys = 0`
createTempTable := `CREATE TABLE operatorbundle_backup (name TEXT,csv TEXT,bundle TEXT)`
backupTargetTable := `INSERT INTO operatorbundle_backup SELECT name,csv,bundle FROM operatorbundle`
dropTargetTable := `DROP TABLE operatorbundle`
renameBackUpTable := `ALTER TABLE operatorbundle_backup RENAME TO operatorbundle;`
foreingKeyOn := `PRAGMA foreign_keys = 1`
_, err := tx.ExecContext(ctx, foreingKeyOff)
if err != nil {
return err
}
_, err = tx.ExecContext(ctx, createTempTable)
if err != nil {
return err
}
_, err = tx.ExecContext(ctx, backupTargetTable)
if err != nil {
return err
}
_, err = tx.ExecContext(ctx, dropTargetTable)
if err != nil {
return err
}
_, err = tx.ExecContext(ctx, renameBackUpTable)
if err != nil {
return err
}
_, err = tx.ExecContext(ctx, foreingKeyOn)
return err
},
}

// Register this migration
func init() {
migrations[BundlePathMigrationKey] = bundlePathMigration
}
44 changes: 44 additions & 0 deletions pkg/sqlite/migrations/002_bundle_path_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package migrations_test

import (
"context"
"testing"

"github.com/operator-framework/operator-registry/pkg/sqlite"
"github.com/operator-framework/operator-registry/pkg/sqlite/migrations"
"github.com/stretchr/testify/require"
)

func TestBundlePathUp(t *testing.T) {
db, migrator, cleanup := CreateTestDbAt(t, migrations.BundlePathMigrationKey-1)
defer cleanup()

err := migrator.Up(context.TODO(), migrations.Only(migrations.BundlePathMigrationKey))
require.NoError(t, err)

// Adding row with bundlepath colum should not fail after migrating up
tx, err := db.Begin()
stmt, err := tx.Prepare("insert into operatorbundle(name, csv, bundle, bundlepath) values(?, ?, ?, ?)")
require.NoError(t, err)
defer stmt.Close()

_, err = stmt.Exec("testName", "testCSV", "testBundle", "quay.io/test")
require.NoError(t, err)

}

func TestBundlePathDown(t *testing.T) {
db, migrator, cleanup := CreateTestDbAt(t, migrations.BundlePathMigrationKey)
defer cleanup()

querier := sqlite.NewSQLLiteQuerierFromDb(db)
imagesBeforeMigration, err := querier.GetImagesForBundle(context.TODO(), "etcdoperator.v0.6.1")

err = migrator.Down(context.TODO(), migrations.Only(migrations.BundlePathMigrationKey))
require.NoError(t, err)

imagesAfterMigration, err := querier.GetImagesForBundle(context.TODO(), "etcdoperator.v0.6.1")

// Migrating down entails sensitive operations. Ensure data is preserved accross down migration
require.Equal(t, len(imagesBeforeMigration), len(imagesAfterMigration))
}
Loading