Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CheckSchema: Verify intermediate schema upgrades #789

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
5 changes: 4 additions & 1 deletion doc/04-Upgrading.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# Upgrading Icinga DB

Specific version upgrades are described below. Please note that version upgrades are incremental.
If you are upgrading across multiple versions, make sure to follow the steps for each of them.

If you are upgrading across multiple versions, make sure to follow the steps for each version in order of release.
For example, when upgrading from 1.1.0 to 1.2.0,
follow all instructions for upgrading to 1.1.1, then all for 1.2.0, including schema upgrades.

## Upgrading to Icinga DB v1.2.0

Expand Down
31 changes: 26 additions & 5 deletions pkg/icingadb/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ const (
)

// CheckSchema asserts the database schema of the expected version being present.
//
// Icinga DB uses incremental schema updates. Each schema version is identified by a continuous rising positive integer.
// With the initial schema import, the schema version of that time will be inserted in a row within the icingadb_schema
// table. Each subsequent schema update inserts another row with its version number. To have a consistent database
// schema, each schema update must be applied. NOTE: This might change in the future.
func CheckSchema(ctx context.Context, db *database.DB) error {
var expectedDbSchemaVersion uint16
switch db.DriverName() {
Expand All @@ -25,13 +30,13 @@ func CheckSchema(ctx context.Context, db *database.DB) error {
expectedDbSchemaVersion = expectedPostgresSchemaVersion
}

var version uint16
var versions []uint16

err := retry.WithBackoff(
ctx,
func(ctx context.Context) (err error) {
query := "SELECT version FROM icingadb_schema ORDER BY id DESC LIMIT 1"
err = db.QueryRowxContext(ctx, query).Scan(&version)
query := "SELECT version FROM icingadb_schema ORDER BY version ASC"
err = db.SelectContext(ctx, &versions, query)
if err != nil {
err = database.CantPerformQuery(err, query)
}
Expand All @@ -44,13 +49,29 @@ func CheckSchema(ctx context.Context, db *database.DB) error {
return errors.Wrap(err, "can't check database schema version")
}

if version != expectedDbSchemaVersion {
if len(versions) == 0 {
return fmt.Errorf("no database schema version is stored in the database")
}

// Check if each schema update between the initial import and the latest version was applied or, in other words,
// that no schema update was left out. The loop goes over the ascending sorted array of schema versions, verifying
// that each element's successor is the increment of this version, ensuring no gaps in between.
for i := 0; i < len(versions)-1; i++ {
oxzi marked this conversation as resolved.
Show resolved Hide resolved
if versions[i] != versions[i+1]-1 {
return fmt.Errorf(
"incomplete database schema upgrade: intermediate version v%d is missing,"+
" please make sure you have applied all database migrations after upgrading Icinga DB",
versions[i]+1)
}
}

if latestVersion := versions[len(versions)-1]; latestVersion != expectedDbSchemaVersion {
// Since these error messages are trivial and mostly caused by users, we don't need
// to print a stack trace here. However, since errors.Errorf() does this automatically,
// we need to use fmt instead.
return fmt.Errorf(
"unexpected database schema version: v%d (expected v%d), please make sure you have applied all database"+
" migrations after upgrading Icinga DB", version, expectedDbSchemaVersion,
" migrations after upgrading Icinga DB", latestVersion, expectedDbSchemaVersion,
)
}

Expand Down
Loading