Skip to content

Commit

Permalink
Merge pull request #15049 from manadart/dqlite-bootstrap-options
Browse files Browse the repository at this point in the history
[JUJU-2433] Allow Dqlite bootstrap to accept extra database mutations
  • Loading branch information
manadart authored Jan 12, 2023
2 parents 3801b78 + f07aea5 commit d51b324
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 22 deletions.
12 changes: 11 additions & 1 deletion database/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package database

import (
"context"
"database/sql"

"github.com/canonical/go-dqlite/app"
"github.com/juju/errors"
Expand All @@ -30,10 +31,13 @@ type bootstrapOptFactory interface {
// BootstrapDqlite opens a new database for the controller, and runs the
// DDL to create its schema.
//
// It accepts an optional list of functions to perform operations on the
// controller database.
//
// At this point we know there are no peers and that we are the only user
// of Dqlite, so we can eschew external address and clustering concerns.
// Those will be handled by the db-accessor worker.
func BootstrapDqlite(ctx context.Context, opt bootstrapOptFactory, logger Logger) error {
func BootstrapDqlite(ctx context.Context, opt bootstrapOptFactory, logger Logger, ops ...func(db *sql.DB) error) error {
dir, err := opt.EnsureDataDir()
if err != nil {
return errors.Trace(err)
Expand Down Expand Up @@ -75,5 +79,11 @@ func BootstrapDqlite(ctx context.Context, opt bootstrapOptFactory, logger Logger
return errors.Annotate(err, "creating controller database schema")
}

for i, op := range ops {
if err := op(db); err != nil {
return errors.Annotatef(err, "running bootstrap operation at index %d", i)
}
}

return nil
}
45 changes: 24 additions & 21 deletions database/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package database

import (
"context"
"database/sql"
"errors"
"fmt"
"net"

Expand All @@ -24,35 +26,36 @@ var _ = gc.Suite(&bootstrapSuite{})
func (s *bootstrapSuite) TestBootstrapSuccess(c *gc.C) {
opt := &testOptFactory{c: c}

c.Assert(BootstrapDqlite(context.TODO(), opt, stubLogger{}), jc.ErrorIsNil)
// check tests the variadic operation functionality
// and ensures that bootstrap applied the DDL.
check := func(db *sql.DB) error {
rows, err := db.Query("SELECT COUNT(*) FROM lease_type")
if err != nil {
return err
}

// Now use the same options to reopen the controller database
// and check that we can see bootstrap side effects.
dir, err := opt.EnsureDataDir()
c.Assert(err, jc.ErrorIsNil)
defer func() { _ = rows.Close() }()

addrOpt, err := opt.WithAddressOption()
c.Assert(err, jc.ErrorIsNil)
if !rows.Next() {
return errors.New("no rows in lease_type")
}

dqlite, err := app.New(dir, addrOpt)
c.Assert(err, jc.ErrorIsNil)
s.AddCleanup(func(*gc.C) { _ = dqlite.Close() })
var count int
err = rows.Scan(&count)
if err != nil {
return err
}

ctx := context.TODO()
c.Assert(dqlite.Ready(ctx), jc.ErrorIsNil)
if count != 3 {
return fmt.Errorf("expected 3 rows, got %d", count)
}

db, err := dqlite.Open(ctx, "controller")
c.Assert(err, jc.ErrorIsNil)
s.AddCleanup(func(*gc.C) { _ = db.Close() })
return nil
}

rows, err := db.Query("SELECT COUNT(*) FROM lease_type")
err := BootstrapDqlite(context.TODO(), opt, stubLogger{}, check)
c.Assert(err, jc.ErrorIsNil)
s.AddCleanup(func(*gc.C) { _ = rows.Close() })

var count int
c.Assert(rows.Next(), jc.IsTrue)
c.Assert(rows.Scan(&count), jc.ErrorIsNil)
c.Check(count, gc.Equals, 3)
}

type testOptFactory struct {
Expand Down

0 comments on commit d51b324

Please sign in to comment.