diff --git a/cluster/cluster_members.mapper.go b/cluster/cluster_members.mapper.go index 6d7ee1c63..6647e80d2 100644 --- a/cluster/cluster_members.mapper.go +++ b/cluster/cluster_members.mapper.go @@ -10,7 +10,7 @@ import ( "github.com/canonical/lxd/shared/api" - "github.com/canonical/microcluster/v3/internal/db/query" + "github.com/canonical/microcluster/v3/cluster/db" ) var _ = api.ServerEnvironment{} @@ -71,7 +71,7 @@ func getCoreClusterMembers(ctx context.Context, stmt *sql.Stmt, args ...any) ([] return nil } - err := query.SelectObjects(ctx, stmt, dest, args...) + err := db.SelectObjects(ctx, stmt, dest, args...) if err != nil { return nil, fmt.Errorf("Failed to fetch from \"core_cluster_members\" table: %w", err) } @@ -95,7 +95,7 @@ func getCoreClusterMembersRaw(ctx context.Context, tx *sql.Tx, sql string, args return nil } - err := query.Scan(ctx, tx, sql, dest, args...) + err := db.Scan(ctx, tx, sql, dest, args...) if err != nil { return nil, fmt.Errorf("Failed to fetch from \"core_cluster_members\" table: %w", err) } diff --git a/internal/db/query/objects.go b/cluster/db/objects.go similarity index 93% rename from internal/db/query/objects.go rename to cluster/db/objects.go index 3f31399a8..7e2492cbf 100644 --- a/internal/db/query/objects.go +++ b/cluster/db/objects.go @@ -1,5 +1,5 @@ -// Package query object functions that match LXD's object handling patterns. -package query +// Package db object functions that match LXD's object handling patterns. +package db import ( "context" diff --git a/internal/db/query/objects_test.go b/cluster/db/objects_test.go similarity index 88% rename from internal/db/query/objects_test.go rename to cluster/db/objects_test.go index df67f15c6..993c31b6b 100644 --- a/internal/db/query/objects_test.go +++ b/cluster/db/objects_test.go @@ -1,4 +1,4 @@ -package query_test +package db_test import ( "context" @@ -8,13 +8,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/canonical/microcluster/v3/internal/db/query" + "github.com/canonical/microcluster/v3/cluster/db" ) // Exercise possible failure modes. func TestSelectObjects_Error(t *testing.T) { cases := []struct { - dest query.Dest + dest db.Dest query string error string }{ @@ -35,7 +35,7 @@ func TestSelectObjects_Error(t *testing.T) { stmt, err := tx.Prepare(c.query) require.NoError(t, err) - err = query.SelectObjects(context.TODO(), stmt, c.dest) + err = db.SelectObjects(context.TODO(), stmt, c.dest) assert.EqualError(t, err, c.error) }) } @@ -61,7 +61,7 @@ func TestSelectObjects(t *testing.T) { stmt, err := tx.Prepare("SELECT id, name FROM test WHERE name=?") require.NoError(t, err) - err = query.SelectObjects(context.TODO(), stmt, dest, "bar") + err = db.SelectObjects(context.TODO(), stmt, dest, "bar") require.NoError(t, err) assert.Equal(t, 1, object.ID) diff --git a/cluster/db/schema.go b/cluster/db/schema.go new file mode 100644 index 000000000..8c74e3ed2 --- /dev/null +++ b/cluster/db/schema.go @@ -0,0 +1,10 @@ +package db + +import ( + "context" + "database/sql" +) + +// Update represents a database schema update function. +// It takes a context and transaction and applies the schema changes. +type Update func(ctx context.Context, tx *sql.Tx) error diff --git a/internal/db/query/slices.go b/cluster/db/slices.go similarity index 95% rename from internal/db/query/slices.go rename to cluster/db/slices.go index f23779fc4..c0bc562e7 100644 --- a/internal/db/query/slices.go +++ b/cluster/db/slices.go @@ -1,5 +1,5 @@ -// Package query slice functions that match LXD's slice handling patterns. -package query +// Package db slice functions that match LXD's slice handling patterns. +package db import ( "context" diff --git a/internal/db/query/slices_test.go b/cluster/db/slices_test.go similarity index 82% rename from internal/db/query/slices_test.go rename to cluster/db/slices_test.go index 0feb1f3a8..5d4ad6d7b 100644 --- a/internal/db/query/slices_test.go +++ b/cluster/db/slices_test.go @@ -1,4 +1,4 @@ -package query_test +package db_test import ( "context" @@ -8,7 +8,7 @@ import ( _ "github.com/mattn/go-sqlite3" "github.com/stretchr/testify/assert" - "github.com/canonical/microcluster/v3/internal/db/query" + "github.com/canonical/microcluster/v3/cluster/db" ) // Exercise possible failure modes. @@ -16,7 +16,7 @@ func TestStrings_Error(t *testing.T) { for _, c := range testStringsErrorCases { t.Run(c.query, func(t *testing.T) { tx := newTxForSlices(t) - values, err := query.SelectStrings(context.Background(), tx, c.query) + values, err := db.SelectStrings(context.Background(), tx, c.query) assert.EqualError(t, err, c.error) assert.Nil(t, values) }) @@ -34,7 +34,7 @@ var testStringsErrorCases = []struct { // All values yield by the query are returned. func TestStrings(t *testing.T) { tx := newTxForSlices(t) - values, err := query.SelectStrings(context.Background(), tx, "SELECT name FROM test ORDER BY name") + values, err := db.SelectStrings(context.Background(), tx, "SELECT name FROM test ORDER BY name") assert.NoError(t, err) assert.Equal(t, []string{"bar", "foo"}, values) } @@ -44,7 +44,7 @@ func TestIntegers_Error(t *testing.T) { for _, c := range testIntegersErrorCases { t.Run(c.query, func(t *testing.T) { tx := newTxForSlices(t) - values, err := query.SelectIntegers(context.Background(), tx, c.query) + values, err := db.SelectIntegers(context.Background(), tx, c.query) assert.EqualError(t, err, c.error) assert.Nil(t, values) }) @@ -62,7 +62,7 @@ var testIntegersErrorCases = []struct { // All values yield by the query are returned. func TestIntegers(t *testing.T) { tx := newTxForSlices(t) - values, err := query.SelectIntegers(context.Background(), tx, "SELECT id FROM test ORDER BY id") + values, err := db.SelectIntegers(context.Background(), tx, "SELECT id FROM test ORDER BY id") assert.NoError(t, err) assert.Equal(t, []int{0, 1}, values) } diff --git a/cluster/token_records.mapper.go b/cluster/token_records.mapper.go index 360ca56cc..eed261015 100644 --- a/cluster/token_records.mapper.go +++ b/cluster/token_records.mapper.go @@ -10,7 +10,7 @@ import ( "github.com/canonical/lxd/shared/api" - "github.com/canonical/microcluster/v3/internal/db/query" + "github.com/canonical/microcluster/v3/cluster/db" ) var _ = api.ServerEnvironment{} @@ -116,7 +116,7 @@ func getCoreTokenRecords(ctx context.Context, stmt *sql.Stmt, args ...any) ([]Co return nil } - err := query.SelectObjects(ctx, stmt, dest, args...) + err := db.SelectObjects(ctx, stmt, dest, args...) if err != nil { return nil, fmt.Errorf("Failed to fetch from \"core_token_records\" table: %w", err) } @@ -140,7 +140,7 @@ func getCoreTokenRecordsRaw(ctx context.Context, tx *sql.Tx, sql string, args .. return nil } - err := query.Scan(ctx, tx, sql, dest, args...) + err := db.Scan(ctx, tx, sql, dest, args...) if err != nil { return nil, fmt.Errorf("Failed to fetch from \"core_token_records\" table: %w", err) } diff --git a/example/database/extended.mapper.go b/example/database/extended.mapper.go index 321aad26e..d8a3aade3 100644 --- a/example/database/extended.mapper.go +++ b/example/database/extended.mapper.go @@ -11,7 +11,7 @@ import ( "github.com/canonical/lxd/shared/api" "github.com/canonical/microcluster/v3/cluster" - "github.com/canonical/microcluster/v3/internal/db/query" + "github.com/canonical/microcluster/v3/cluster/db" ) var _ = api.ServerEnvironment{} @@ -116,10 +116,10 @@ func GetExtendedTables(ctx context.Context, tx *sql.Tx, filters ...ExtendedTable // Select. if sqlStmt != nil { - err = query.SelectObjects(ctx, sqlStmt, dest, args...) + err = db.SelectObjects(ctx, sqlStmt, dest, args...) } else { queryStr := strings.Join(queryParts[:], "ORDER BY") - err = query.Scan(ctx, tx, queryStr, dest, args...) + err = db.Scan(ctx, tx, queryStr, dest, args...) } if err != nil { diff --git a/example/database/extended_schema.go b/example/database/extended_schema.go index b2a1063f9..427f14d15 100644 --- a/example/database/extended_schema.go +++ b/example/database/extended_schema.go @@ -5,12 +5,12 @@ import ( "context" "database/sql" - "github.com/canonical/microcluster/v3/internal/db/schema" + "github.com/canonical/microcluster/v3/cluster/db" ) // SchemaExtensions is a list of schema extensions that can be passed to the MicroCluster daemon. // Each entry will increase the database schema version by one, and will be applied after internal schema updates. -var SchemaExtensions = []schema.Update{ +var SchemaExtensions = []db.Update{ schemaAppend1, schemaAppend2, } diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index af5a52df9..7e79149fc 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -24,9 +24,9 @@ import ( "github.com/canonical/microcluster/v3/client" "github.com/canonical/microcluster/v3/cluster" + clusterDB "github.com/canonical/microcluster/v3/cluster/db" internalConfig "github.com/canonical/microcluster/v3/internal/config" "github.com/canonical/microcluster/v3/internal/db" - "github.com/canonical/microcluster/v3/internal/db/schema" "github.com/canonical/microcluster/v3/internal/endpoints" "github.com/canonical/microcluster/v3/internal/extensions" internalLog "github.com/canonical/microcluster/v3/internal/log" @@ -60,7 +60,7 @@ type Args struct { HeartbeatInterval time.Duration // List of schema updates in the order that they should be applied. - ExtensionsSchema []schema.Update + ExtensionsSchema []clusterDB.Update // List of extensions supported by the endpoints of the core/default cluster API. APIExtensions []string @@ -247,7 +247,7 @@ func (d *Daemon) Run(ctx context.Context, stateDir string, args Args) error { } } -func (d *Daemon) init(listenAddress string, socketGroup string, heartbeatInterval time.Duration, schemaExtensions []schema.Update, apiExtensions []string, hooks *state.Hooks) error { +func (d *Daemon) init(listenAddress string, socketGroup string, heartbeatInterval time.Duration, schemaExtensions []clusterDB.Update, apiExtensions []string, hooks *state.Hooks) error { d.applyHooks(hooks) // Register smart error mappings. diff --git a/internal/db/db_test.go b/internal/db/db_test.go index df8f240d0..a0b74b148 100644 --- a/internal/db/db_test.go +++ b/internal/db/db_test.go @@ -13,8 +13,7 @@ import ( "github.com/stretchr/testify/suite" "github.com/canonical/microcluster/v3/cluster" - "github.com/canonical/microcluster/v3/internal/db/query" - "github.com/canonical/microcluster/v3/internal/db/schema" + clusterDB "github.com/canonical/microcluster/v3/cluster/db" "github.com/canonical/microcluster/v3/internal/db/update" "github.com/canonical/microcluster/v3/internal/extensions" "github.com/canonical/microcluster/v3/internal/log" @@ -160,7 +159,7 @@ func (s *dbSuite) Test_waitUpgradeSchema() { for i, t := range tests { s.T().Logf("%s (case %d)", t.name, i) - db, err := NewTestDB([]schema.Update{}) + db, err := NewTestDB([]clusterDB.Update{}) s.NoError(err) tx, err := db.db.BeginTx(db.ctx, nil) @@ -209,7 +208,7 @@ func (s *dbSuite) Test_waitUpgradeSchema() { // Apply the local updates to the schema table. manager := &update.SchemaUpdateManager{} - updates := []schema.Update{} + updates := []clusterDB.Update{} for j := 0; j < int(t.upgradedLocalInfo.schemaInt)+1; j++ { _, err = db.db.Exec(stmt, j, 0) s.NoError(err) @@ -219,7 +218,7 @@ func (s *dbSuite) Test_waitUpgradeSchema() { manager.SetInternalUpdates(updates) - updates = []schema.Update{} + updates = []clusterDB.Update{} for j := 0; j < int(t.upgradedLocalInfo.schemaExt)+1; j++ { _, err = db.db.Exec(stmt, j, 1) s.NoError(err) @@ -249,10 +248,10 @@ func (s *dbSuite) Test_waitUpgradeSchema() { tx, err = db.db.BeginTx(db.ctx, nil) s.NoError(err) - schemaInternal, err := query.SelectIntegers(db.ctx, tx, "SELECT schema_internal FROM core_cluster_members ORDER BY id") + schemaInternal, err := clusterDB.SelectIntegers(db.ctx, tx, "SELECT schema_internal FROM core_cluster_members ORDER BY id") s.NoError(err) - schemaExternal, err := query.SelectIntegers(db.ctx, tx, "SELECT schema_external FROM core_cluster_members ORDER BY id") + schemaExternal, err := clusterDB.SelectIntegers(db.ctx, tx, "SELECT schema_external FROM core_cluster_members ORDER BY id") s.NoError(err) s.NoError(tx.Commit()) @@ -338,7 +337,7 @@ func (s *dbSuite) Test_waitUpgradeAPI() { for i, t := range tests { s.T().Logf("%s (case %d)", t.name, i) - db, err := NewTestDB([]schema.Update{}) + db, err := NewTestDB([]clusterDB.Update{}) s.NoError(err) ctx := context.Background() @@ -388,12 +387,12 @@ func (s *dbSuite) Test_waitUpgradeAPI() { _, err = db.db.Exec(stmt, 0, 0) s.NoError(err) - updates := []schema.Update{func(ctx context.Context, tx *sql.Tx) error { return nil }} + updates := []clusterDB.Update{func(ctx context.Context, tx *sql.Tx) error { return nil }} manager.SetInternalUpdates(updates) _, err = db.db.Exec(stmt, 0, 1) s.NoError(err) - updates = []schema.Update{func(ctx context.Context, tx *sql.Tx) error { return nil }} + updates = []clusterDB.Update{func(ctx context.Context, tx *sql.Tx) error { return nil }} manager.SetExternalUpdates(updates) if t.expectWait { @@ -416,7 +415,7 @@ func (s *dbSuite) Test_waitUpgradeAPI() { tx, err = db.db.BeginTx(ctx, nil) s.NoError(err) - res, err := query.SelectStrings(ctx, tx, "SELECT api_extensions FROM core_cluster_members ORDER BY id") + res, err := clusterDB.SelectStrings(ctx, tx, "SELECT api_extensions FROM core_cluster_members ORDER BY id") s.NoError(err) allExtensions := make([]extensions.Extensions, 0) for _, r := range res { @@ -505,7 +504,7 @@ func (s *dbSuite) Test_waitUpgradeSchemaAndAPI() { for i, t := range tests { s.T().Logf("%s (case %d)", t.name, i) - db, err := NewTestDB([]schema.Update{}) + db, err := NewTestDB([]clusterDB.Update{}) s.NoError(err) ctx := context.Background() @@ -552,7 +551,7 @@ func (s *dbSuite) Test_waitUpgradeSchemaAndAPI() { // Apply the local updates to the schema table. manager := &update.SchemaUpdateManager{} - updates := []schema.Update{} + updates := []clusterDB.Update{} for j := 0; j < int(t.upgradedLocalInfo.schemaInt)+1; j++ { _, err = db.db.Exec(stmt, j, 0) s.NoError(err) @@ -562,7 +561,7 @@ func (s *dbSuite) Test_waitUpgradeSchemaAndAPI() { manager.SetInternalUpdates(updates) - updates = []schema.Update{} + updates = []clusterDB.Update{} for j := 0; j < int(t.upgradedLocalInfo.schemaExt)+1; j++ { _, err = db.db.Exec(stmt, j, 1) s.NoError(err) @@ -592,13 +591,13 @@ func (s *dbSuite) Test_waitUpgradeSchemaAndAPI() { tx, err = db.db.BeginTx(ctx, nil) s.NoError(err) - schemaInternal, err := query.SelectIntegers(ctx, tx, "SELECT schema_internal FROM core_cluster_members ORDER BY id") + schemaInternal, err := clusterDB.SelectIntegers(ctx, tx, "SELECT schema_internal FROM core_cluster_members ORDER BY id") s.NoError(err) - schemaExternal, err := query.SelectIntegers(ctx, tx, "SELECT schema_external FROM core_cluster_members ORDER BY id") + schemaExternal, err := clusterDB.SelectIntegers(ctx, tx, "SELECT schema_external FROM core_cluster_members ORDER BY id") s.NoError(err) - res, err := query.SelectStrings(ctx, tx, "SELECT api_extensions FROM core_cluster_members ORDER BY id") + res, err := clusterDB.SelectStrings(ctx, tx, "SELECT api_extensions FROM core_cluster_members ORDER BY id") s.NoError(err) allExtensions := make([]extensions.Extensions, 0) for _, r := range res { @@ -649,8 +648,8 @@ func (s *dbSuite) Test_waitUpgradeSchemaAndAPI() { } } -// NewTedb returns a sqlite DB set up with the default microcluster schema. -func NewTestDB(extensionsExternal []schema.Update) (*DqliteDB, error) { +// NewTestDB returns a sqlite DB set up with the default microcluster schema. +func NewTestDB(extensionsExternal []clusterDB.Update) (*DqliteDB, error) { var err error ctx := context.WithValue(context.Background(), log.CtxLogger, slog.Default()) diff --git a/internal/db/dqlite.go b/internal/db/dqlite.go index 99db1880a..f5d44c548 100644 --- a/internal/db/dqlite.go +++ b/internal/db/dqlite.go @@ -25,7 +25,7 @@ import ( "github.com/canonical/lxd/shared/tcp" "github.com/canonical/microcluster/v3/cluster" - "github.com/canonical/microcluster/v3/internal/db/schema" + clusterDB "github.com/canonical/microcluster/v3/cluster/db" "github.com/canonical/microcluster/v3/internal/db/update" "github.com/canonical/microcluster/v3/internal/extensions" "github.com/canonical/microcluster/v3/internal/log" @@ -115,7 +115,7 @@ func (db *DqliteDB) log() *slog.Logger { } // SetSchema sets schema and API extensions on the DB. -func (db *DqliteDB) SetSchema(schemaExtensions []schema.Update, apiExtensions extensions.Extensions) { +func (db *DqliteDB) SetSchema(schemaExtensions []clusterDB.Update, apiExtensions extensions.Extensions) { s := update.NewSchema() s.AppendSchema(schemaExtensions, apiExtensions) db.schema = s.Schema() diff --git a/internal/db/query/transaction_test.go b/internal/db/query/transaction_test.go index df4e5a641..f4d405de7 100644 --- a/internal/db/query/transaction_test.go +++ b/internal/db/query/transaction_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + dbClient "github.com/canonical/microcluster/v3/cluster/db" "github.com/canonical/microcluster/v3/internal/db/query" "github.com/canonical/microcluster/v3/internal/log" ) @@ -46,7 +47,7 @@ func TestTransaction_FunctionError(t *testing.T) { tx, err := db.Begin() assert.NoError(t, err) - tables, err := query.SelectStrings(context.Background(), tx, "SELECT name FROM sqlite_master WHERE type = 'table'") + tables, err := dbClient.SelectStrings(context.Background(), tx, "SELECT name FROM sqlite_master WHERE type = 'table'") assert.NoError(t, err) assert.NotContains(t, tables, "test") _ = tx.Rollback() diff --git a/internal/db/schema/schema.go b/internal/db/schema/schema.go index 3b0c0c953..85b3190af 100644 --- a/internal/db/schema/schema.go +++ b/internal/db/schema/schema.go @@ -5,10 +5,6 @@ import ( "database/sql" ) -// Update represents a database schema update function. -// It takes a context and transaction and applies the schema changes. -type Update func(ctx context.Context, tx *sql.Tx) error - // Hook is a callback that gets fired when a update gets applied. type Hook func(ctx context.Context, version int, tx *sql.Tx) error diff --git a/internal/db/update/cluster.go b/internal/db/update/cluster.go index b02c38fda..2bfd5eed6 100644 --- a/internal/db/update/cluster.go +++ b/internal/db/update/cluster.go @@ -6,7 +6,7 @@ import ( "fmt" "log/slog" - "github.com/canonical/microcluster/v3/internal/db/query" + "github.com/canonical/microcluster/v3/cluster/db" "github.com/canonical/microcluster/v3/internal/extensions" "github.com/canonical/microcluster/v3/internal/log" ) @@ -134,7 +134,7 @@ func GetClusterMemberSchemaVersions(ctx context.Context, tx *sql.Tx) (internalSc return nil } - err = query.Scan(ctx, tx, sql, dest) + err = db.Scan(ctx, tx, sql, dest) if err != nil { return nil, nil, err } @@ -240,7 +240,7 @@ func GetClusterMemberAPIExtensions(ctx context.Context, tx *sql.Tx) ([]extension // Since we need to check this table to perform the update that renames it, we can use this function to dynamically determine its name. func getClusterTableName(ctx context.Context, tx *sql.Tx) (string, error) { stmt := "SELECT name FROM sqlite_master WHERE name = 'internal_cluster_members' OR name = 'core_cluster_members'" - tables, err := query.SelectStrings(ctx, tx, stmt) + tables, err := db.SelectStrings(ctx, tx, stmt) if err != nil { return "", err } diff --git a/internal/db/update/schema.go b/internal/db/update/schema.go index e1a453e6a..c0d82e755 100644 --- a/internal/db/update/schema.go +++ b/internal/db/update/schema.go @@ -9,6 +9,7 @@ import ( "github.com/canonical/lxd/shared" + clusterDB "github.com/canonical/microcluster/v3/cluster/db" "github.com/canonical/microcluster/v3/internal/db/query" "github.com/canonical/microcluster/v3/internal/db/schema" "github.com/canonical/microcluster/v3/internal/extensions" @@ -27,7 +28,7 @@ const ( // SchemaUpdate holds the configuration for executing schema updates. type SchemaUpdate struct { - updates map[updateType][]schema.Update // Ordered series of internal and external updates making up the schema + updates map[updateType][]clusterDB.Update // Ordered series of internal and external updates making up the schema apiExtensions extensions.Extensions hook schema.Hook // Optional hook to execute whenever a update gets applied fresh string // Optional SQL statement used to create schema from scratch @@ -121,7 +122,7 @@ func (s *SchemaUpdate) Ensure(ctx context.Context, db *sql.DB) (int, error) { err = query.Transaction(ctx, db, func(ctx context.Context, tx *sql.Tx) error { if exists && updateSchemaTable { - versions, err = query.SelectIntegers(ctx, tx, "SELECT COALESCE(MAX(version), 0) FROM schemas") + versions, err = clusterDB.SelectIntegers(ctx, tx, "SELECT COALESCE(MAX(version), 0) FROM schemas") if err != nil { return err } @@ -144,7 +145,7 @@ func (s *SchemaUpdate) Ensure(ctx context.Context, db *sql.DB) (int, error) { // The result is list of size 2, with index 0 corresponding to the max internal version and index 1 to the max external version, thanks to UNION ALL. // The selected column must default to zero, otherwise query.SelectIntegers will fail to parse a null value as an integer. maxVersionsStmt := "SELECT COALESCE(MAX(version), 0) FROM schemas WHERE type = 0 UNION ALL SELECT COALESCE(MAX(version), 0) FROM schemas WHERE type = 1" - versions, err = query.SelectIntegers(ctx, tx, maxVersionsStmt) + versions, err = clusterDB.SelectIntegers(ctx, tx, maxVersionsStmt) if err != nil { return err } @@ -202,7 +203,7 @@ func (s *SchemaUpdate) Ensure(ctx context.Context, db *sql.DB) (int, error) { } maxVersionsStmt := "SELECT COALESCE(MAX(version), 0) FROM schemas WHERE type = 0 UNION ALL SELECT COALESCE(MAX(version), 0) FROM schemas WHERE type = 1" - versions, err = query.SelectIntegers(ctx, tx, maxVersionsStmt) + versions, err = clusterDB.SelectIntegers(ctx, tx, maxVersionsStmt) if err != nil { return err } @@ -254,7 +255,7 @@ func (s *SchemaUpdate) Ensure(ctx context.Context, db *sql.DB) (int, error) { } // Apply any pending update that was not yet applied. -func ensureUpdatesAreApplied(ctx context.Context, tx *sql.Tx, updateType updateType, version int, updates []schema.Update, hook schema.Hook) error { +func ensureUpdatesAreApplied(ctx context.Context, tx *sql.Tx, updateType updateType, version int, updates []clusterDB.Update, hook schema.Hook) error { if version > len(updates) { return fmt.Errorf("Schema version %d is more recent than expected %d", version, len(updates)) } diff --git a/internal/db/update/update.go b/internal/db/update/update.go index c158cd544..6886a6271 100644 --- a/internal/db/update/update.go +++ b/internal/db/update/update.go @@ -5,7 +5,7 @@ import ( "database/sql" "fmt" - "github.com/canonical/microcluster/v3/internal/db/schema" + clusterDB "github.com/canonical/microcluster/v3/cluster/db" "github.com/canonical/microcluster/v3/internal/extensions" ) @@ -21,7 +21,7 @@ CREATE TABLE schemas ( // SchemaUpdateManager contains a map of schema update type to slice of schema.Update. type SchemaUpdateManager struct { - updates map[updateType][]schema.Update + updates map[updateType][]clusterDB.Update apiExtensions extensions.Extensions } @@ -29,7 +29,7 @@ type SchemaUpdateManager struct { // NewSchema returns a new SchemaUpdateManager containing microcluster schema updates. func NewSchema() *SchemaUpdateManager { mgr := &SchemaUpdateManager{} - mgr.updates = map[updateType][]schema.Update{ + mgr.updates = map[updateType][]clusterDB.Update{ updateInternal: { updateFromV0, updateFromV1, @@ -44,18 +44,18 @@ func NewSchema() *SchemaUpdateManager { } // SetInternalUpdates replaces the set of internal schema updates. -func (s *SchemaUpdateManager) SetInternalUpdates(updates []schema.Update) { +func (s *SchemaUpdateManager) SetInternalUpdates(updates []clusterDB.Update) { if s.updates == nil { - s.updates = map[updateType][]schema.Update{} + s.updates = map[updateType][]clusterDB.Update{} } s.updates[updateInternal] = updates } // SetExternalUpdates replaces the set of external schema updates. -func (s *SchemaUpdateManager) SetExternalUpdates(updates []schema.Update) { +func (s *SchemaUpdateManager) SetExternalUpdates(updates []clusterDB.Update) { if s.updates == nil { - s.updates = map[updateType][]schema.Update{} + s.updates = map[updateType][]clusterDB.Update{} } s.updates[updateExternal] = updates @@ -69,7 +69,7 @@ func (s *SchemaUpdateManager) Schema() *SchemaUpdate { } // AppendSchema sets the given schema and API updates as the list of external extensions on the update manager. -func (s *SchemaUpdateManager) AppendSchema(schemaExtensions []schema.Update, apiExtensions extensions.Extensions) { +func (s *SchemaUpdateManager) AppendSchema(schemaExtensions []clusterDB.Update, apiExtensions extensions.Extensions) { s.updates[updateExternal] = schemaExtensions s.apiExtensions = apiExtensions } diff --git a/internal/db/update/update_test.go b/internal/db/update/update_test.go index 2e2a43d04..225bb37aa 100644 --- a/internal/db/update/update_test.go +++ b/internal/db/update/update_test.go @@ -9,8 +9,7 @@ import ( "github.com/stretchr/testify/suite" - "github.com/canonical/microcluster/v3/internal/db/query" - "github.com/canonical/microcluster/v3/internal/db/schema" + clusterDB "github.com/canonical/microcluster/v3/cluster/db" ) type updateSuite struct { @@ -53,7 +52,7 @@ func (s *updateSuite) Test_updateFromV1ClusterMembers() { // Create a schema manager that corresponds to the manual configuration above. dummyUpdate := func(ctx context.Context, tx *sql.Tx) error { return nil } schemaMgr := NewSchema() - schemaMgr.AppendSchema([]schema.Update{dummyUpdate, dummyUpdate}, nil) + schemaMgr.AppendSchema([]clusterDB.Update{dummyUpdate, dummyUpdate}, nil) // Apply the updates the regular way. _, err = schemaMgr.Schema().Ensure(context.TODO(), db) @@ -61,16 +60,16 @@ func (s *updateSuite) Test_updateFromV1ClusterMembers() { tx, err = db.BeginTx(ctx, nil) s.NoError(err) - schemaInternal, err := query.SelectIntegers(ctx, tx, "SELECT schema_internal FROM core_cluster_members") + schemaInternal, err := clusterDB.SelectIntegers(ctx, tx, "SELECT schema_internal FROM core_cluster_members") s.NoError(err) - schemaExternal, err := query.SelectIntegers(ctx, tx, "SELECT schema_external FROM core_cluster_members") + schemaExternal, err := clusterDB.SelectIntegers(ctx, tx, "SELECT schema_external FROM core_cluster_members") s.NoError(err) - versionsInternal, err := query.SelectIntegers(ctx, tx, "SELECT version from schemas where type = 0") + versionsInternal, err := clusterDB.SelectIntegers(ctx, tx, "SELECT version from schemas where type = 0") s.NoError(err) - versionsExternal, err := query.SelectIntegers(ctx, tx, "SELECT version from schemas where type = 1") + versionsExternal, err := clusterDB.SelectIntegers(ctx, tx, "SELECT version from schemas where type = 1") s.NoError(err) s.NoError(tx.Commit()) @@ -100,94 +99,94 @@ func (s *updateSuite) Test_updateFromV1() { tests := []struct { name string - initialSchemaInternal []schema.Update - initialSchemaExternal []schema.Update - upgradesInternal []schema.Update - upgradesExternal []schema.Update + initialSchemaInternal []clusterDB.Update + initialSchemaExternal []clusterDB.Update + upgradesInternal []clusterDB.Update + upgradesExternal []clusterDB.Update }{ { name: "Default internal schema, no external schema, no updates", - initialSchemaInternal: []schema.Update{updateFromV0, updateFromV1}, - initialSchemaExternal: []schema.Update{}, - upgradesInternal: []schema.Update{}, - upgradesExternal: []schema.Update{}, + initialSchemaInternal: []clusterDB.Update{updateFromV0, updateFromV1}, + initialSchemaExternal: []clusterDB.Update{}, + upgradesInternal: []clusterDB.Update{}, + upgradesExternal: []clusterDB.Update{}, }, { name: "Upgrade internal schema from v0 to v1, no external schema", - initialSchemaInternal: []schema.Update{updateFromV0}, - initialSchemaExternal: []schema.Update{}, - upgradesInternal: []schema.Update{updateFromV1}, - upgradesExternal: []schema.Update{}, + initialSchemaInternal: []clusterDB.Update{updateFromV0}, + initialSchemaExternal: []clusterDB.Update{}, + upgradesInternal: []clusterDB.Update{updateFromV1}, + upgradesExternal: []clusterDB.Update{}, }, { name: "Updating internal schema from v0 to v2, no external schema", - initialSchemaInternal: []schema.Update{updateFromV0}, - initialSchemaExternal: []schema.Update{}, - upgradesInternal: []schema.Update{updateFromV1, dummyUpdate}, - upgradesExternal: []schema.Update{}, + initialSchemaInternal: []clusterDB.Update{updateFromV0}, + initialSchemaExternal: []clusterDB.Update{}, + upgradesInternal: []clusterDB.Update{updateFromV1, dummyUpdate}, + upgradesExternal: []clusterDB.Update{}, }, { name: "Updating internal schema from v1 to v2, no external schema", - initialSchemaInternal: []schema.Update{updateFromV0, updateFromV1}, - initialSchemaExternal: []schema.Update{}, - upgradesInternal: []schema.Update{dummyUpdate}, - upgradesExternal: []schema.Update{}, + initialSchemaInternal: []clusterDB.Update{updateFromV0, updateFromV1}, + initialSchemaExternal: []clusterDB.Update{}, + upgradesInternal: []clusterDB.Update{dummyUpdate}, + upgradesExternal: []clusterDB.Update{}, }, { name: "Default internal schema, v1 external schema, no updates", - initialSchemaInternal: []schema.Update{updateFromV0, updateFromV1}, - initialSchemaExternal: []schema.Update{dummyUpdate}, - upgradesInternal: []schema.Update{}, - upgradesExternal: []schema.Update{}, + initialSchemaInternal: []clusterDB.Update{updateFromV0, updateFromV1}, + initialSchemaExternal: []clusterDB.Update{dummyUpdate}, + upgradesInternal: []clusterDB.Update{}, + upgradesExternal: []clusterDB.Update{}, }, { name: "Default internal schema, update external schema from v0 to v1", - initialSchemaInternal: []schema.Update{updateFromV0, updateFromV1}, - initialSchemaExternal: []schema.Update{}, - upgradesInternal: []schema.Update{}, - upgradesExternal: []schema.Update{dummyUpdate}, + initialSchemaInternal: []clusterDB.Update{updateFromV0, updateFromV1}, + initialSchemaExternal: []clusterDB.Update{}, + upgradesInternal: []clusterDB.Update{}, + upgradesExternal: []clusterDB.Update{dummyUpdate}, }, { name: "Default internal schema, update external schema from v1 to v2", - initialSchemaInternal: []schema.Update{updateFromV0, updateFromV1}, - initialSchemaExternal: []schema.Update{dummyUpdate}, - upgradesInternal: []schema.Update{}, - upgradesExternal: []schema.Update{dummyUpdate}, + initialSchemaInternal: []clusterDB.Update{updateFromV0, updateFromV1}, + initialSchemaExternal: []clusterDB.Update{dummyUpdate}, + upgradesInternal: []clusterDB.Update{}, + upgradesExternal: []clusterDB.Update{dummyUpdate}, }, { name: "Update internal schema from v1 to v2, update external schema from v1 to v2", - initialSchemaInternal: []schema.Update{updateFromV0, updateFromV1}, - initialSchemaExternal: []schema.Update{dummyUpdate}, - upgradesInternal: []schema.Update{dummyUpdate}, - upgradesExternal: []schema.Update{dummyUpdate}, + initialSchemaInternal: []clusterDB.Update{updateFromV0, updateFromV1}, + initialSchemaExternal: []clusterDB.Update{dummyUpdate}, + upgradesInternal: []clusterDB.Update{dummyUpdate}, + upgradesExternal: []clusterDB.Update{dummyUpdate}, }, { name: "Update internal schema from v0 to v1, external schema at v1", - initialSchemaInternal: []schema.Update{updateFromV0}, - initialSchemaExternal: []schema.Update{dummyUpdate}, - upgradesInternal: []schema.Update{updateFromV1}, - upgradesExternal: []schema.Update{}, + initialSchemaInternal: []clusterDB.Update{updateFromV0}, + initialSchemaExternal: []clusterDB.Update{dummyUpdate}, + upgradesInternal: []clusterDB.Update{updateFromV1}, + upgradesExternal: []clusterDB.Update{}, }, { name: "Update internal schema from v0 to v2, external schema at v1", - initialSchemaInternal: []schema.Update{updateFromV0}, - initialSchemaExternal: []schema.Update{dummyUpdate}, - upgradesInternal: []schema.Update{updateFromV1, dummyUpdate}, - upgradesExternal: []schema.Update{}, + initialSchemaInternal: []clusterDB.Update{updateFromV0}, + initialSchemaExternal: []clusterDB.Update{dummyUpdate}, + upgradesInternal: []clusterDB.Update{updateFromV1, dummyUpdate}, + upgradesExternal: []clusterDB.Update{}, }, { name: "Update internal schema from v0 to v2, update external schema from v0 to v1", - initialSchemaInternal: []schema.Update{updateFromV0}, - initialSchemaExternal: []schema.Update{}, - upgradesInternal: []schema.Update{updateFromV1, dummyUpdate}, - upgradesExternal: []schema.Update{dummyUpdate}, + initialSchemaInternal: []clusterDB.Update{updateFromV0}, + initialSchemaExternal: []clusterDB.Update{}, + upgradesInternal: []clusterDB.Update{updateFromV1, dummyUpdate}, + upgradesExternal: []clusterDB.Update{dummyUpdate}, }, { name: "Update internal schema from v0 to v2, update external schema from v1 to v2", - initialSchemaInternal: []schema.Update{updateFromV0}, - initialSchemaExternal: []schema.Update{dummyUpdate}, - upgradesInternal: []schema.Update{updateFromV1, dummyUpdate}, - upgradesExternal: []schema.Update{dummyUpdate}, + initialSchemaInternal: []clusterDB.Update{updateFromV0}, + initialSchemaExternal: []clusterDB.Update{dummyUpdate}, + upgradesInternal: []clusterDB.Update{updateFromV1, dummyUpdate}, + upgradesExternal: []clusterDB.Update{dummyUpdate}, }, } @@ -195,7 +194,7 @@ func (s *updateSuite) Test_updateFromV1() { s.T().Logf("%s (case %d)", t.name, i) schema := &SchemaUpdateManager{ - updates: map[updateType][]schema.Update{ + updates: map[updateType][]clusterDB.Update{ updateInternal: t.initialSchemaInternal, updateExternal: t.initialSchemaExternal, }, @@ -213,7 +212,7 @@ func (s *updateSuite) Test_updateFromV1() { ctx := context.Background() tx, err := db.BeginTx(ctx, nil) s.NoError(err) - versions, err := query.SelectIntegers(ctx, tx, "SELECT MAX(version) FROM schemas WHERE type = 0 UNION ALL SELECT COALESCE(MAX(version), 0) FROM schemas WHERE type = 1") + versions, err := clusterDB.SelectIntegers(ctx, tx, "SELECT MAX(version) FROM schemas WHERE type = 0 UNION ALL SELECT COALESCE(MAX(version), 0) FROM schemas WHERE type = 1") s.NoError(err) s.Equal(len(schema.updates[updateInternal]), versions[0])