cloud/bmaas: test and document upgrades across migrations
Change-Id: I1c405b0f2ecc10331b79d02deb8a63f3b148f502
Reviewed-on: https://review.monogon.dev/c/monogon/+/1566
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
Tested-by: Jenkins CI
diff --git a/cloud/bmaas/bmdb/migrations_test.go b/cloud/bmaas/bmdb/migrations_test.go
index 052d5e1..9ee4ae2 100644
--- a/cloud/bmaas/bmdb/migrations_test.go
+++ b/cloud/bmaas/bmdb/migrations_test.go
@@ -1,7 +1,10 @@
package bmdb
import (
+ "context"
"testing"
+
+ "source.monogon.dev/cloud/bmaas/bmdb/model"
)
// TestMigrateUpDown performs a full-up and full-down migration test on an
@@ -57,3 +60,85 @@
t.Fatalf("Initial up migration failed: %v", err)
}
}
+
+func TestMigration1681826233(t *testing.T) {
+ // This migration adds a new nullable field to backoffs.
+
+ // This guarantees that versions [prev, ver] can run concurrently in a cluster.
+ min := uint(1672749980)
+ max := uint(1681826233)
+
+ ctx, ctxC := context.WithCancel(context.Background())
+ defer t.Cleanup(ctxC)
+
+ b := dut()
+ conn, err := b.Open(false)
+ if err != nil {
+ t.Fatalf("Starting empty database failed: %v", err)
+ }
+
+ // First, make sure the change can actually progress if we have some backoffs
+ // already.
+ if err := b.Database.MigrateUpToIncluding(min); err != nil {
+ t.Fatalf("Migration to minimum version failed: %v", err)
+ }
+
+ // Create machine and old-style backoff.
+ q := model.New(conn.db)
+ machine, err := q.NewMachine(ctx)
+ if err != nil {
+ t.Fatalf("Could not create machine: %v", err)
+ }
+ _, err = conn.db.Exec(`
+ INSERT INTO work_backoff
+ (machine_id, process, until, cause)
+ VALUES
+ ($1, 'UnitTest1', now(), 'test');
+ `, machine.MachineID)
+ if err != nil {
+ t.Fatalf("Could not create old-style backoff on old version: %v", err)
+ }
+
+ // Migrate to newer version.
+ if err := b.Database.MigrateUpToIncluding(max); err != nil {
+ t.Fatalf("Migration to maximum version failed: %v", err)
+ }
+
+ // The migration should be read succesfully.
+ boffs, err := q.WorkBackoffOf(ctx, model.WorkBackoffOfParams{
+ MachineID: machine.MachineID,
+ Process: "UnitTest1",
+ })
+ if err != nil {
+ t.Fatalf("Reading backoff failed: %v", err)
+ }
+ if len(boffs) != 1 {
+ t.Errorf("No backoff found")
+ } else {
+ boff := boffs[0]
+ if boff.LastIntervalSeconds.Valid {
+ t.Errorf("Expected interval to be NULL")
+ }
+ }
+
+ // Simultaneously, any concurrently running bmdb user on an older version should
+ // still be able to insert and read backoffs old style.
+ _, err = conn.db.Exec(`
+ INSERT INTO work_backoff
+ (machine_id, process, until, cause)
+ VALUES
+ ($1, 'UnitTest2', now(), 'test');
+ `, machine.MachineID)
+ if err != nil {
+ t.Fatalf("Could not create old-style backoff on new version: %v", err)
+ }
+ rows, err := conn.db.Query(`
+ SELECT machine_id, process, until, cause FROM work_backoff
+ `)
+ for rows.Next() {
+ var mid, process, until, cause string
+ if err := rows.Scan(&mid, &process, &until, &cause); err != nil {
+ t.Errorf("Scan failed: %v", err)
+ }
+ }
+}