You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
boundary/internal/cmd/commands/database/funcs_test.go

236 lines
6.8 KiB

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package database
import (
"context"
"testing"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/db/common"
"github.com/hashicorp/boundary/internal/db/schema"
"github.com/hashicorp/boundary/testing/dbtest"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestMigrateDatabase(t *testing.T) {
ctx := context.Background()
dialect := dbtest.Postgres
cases := []struct {
name string
initialized bool
urlProvider func() string
expectedCode int
expectedOutput string
expectedError string
}{
{
name: "not_initialized_expected_not_intialized",
initialized: false,
urlProvider: func() string {
c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1))
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, c())
})
return u
},
expectedCode: 0,
expectedOutput: "Migrations successfully run.\n",
},
{
name: "basic_initialized_expects_initialized",
initialized: true,
urlProvider: func() string {
c, u, _, err := dbtest.StartUsingTemplate(dialect)
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, c())
})
dBase, err := common.SqlOpen(dialect, u)
require.NoError(t, err)
earlyMigrationVersion := 2000
man, err := schema.NewManager(ctx, schema.Dialect(dialect), dBase, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": earlyMigrationVersion}),
))
require.NoError(t, err)
_, err = man.ApplyMigrations(ctx)
require.NoError(t, err)
return u
},
expectedCode: 0,
expectedOutput: "Migrations successfully run.\n",
},
{
name: "basic_initialized_expects_not_initialized",
initialized: false,
urlProvider: func() string {
c, u, _, err := dbtest.StartUsingTemplate(dialect)
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, c())
})
dBase, err := common.SqlOpen(dialect, u)
require.NoError(t, err)
earlyMigrationVersion := 2000
man, err := schema.NewManager(ctx, schema.Dialect(dialect), dBase, schema.WithEditions(
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": earlyMigrationVersion}),
))
require.NoError(t, err)
_, err = man.ApplyMigrations(ctx)
require.NoError(t, err)
return u
},
expectedCode: -1,
expectedOutput: "Database has already been initialized. Please use 'boundary database migrate'\nfor any upgrade needs.\n",
},
{
name: "old_version_table_used_intialized",
initialized: true,
urlProvider: func() string {
c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1))
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, c())
})
dBase, err := common.SqlOpen(dialect, u)
require.NoError(t, err)
createStmt := `create table if not exists schema_migrations (version bigint primary key, dirty boolean not null)`
_, err = dBase.Exec(createStmt)
require.NoError(t, err)
return u
},
expectedCode: 0,
expectedOutput: "Migrations successfully run.\n",
},
{
name: "old_version_table_used_not_intialized",
initialized: false,
urlProvider: func() string {
c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1))
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, c())
})
dBase, err := common.SqlOpen(dialect, u)
require.NoError(t, err)
createStmt := `create table if not exists schema_migrations (version bigint primary key, dirty boolean not null)`
_, err = dBase.Exec(createStmt)
require.NoError(t, err)
return u
},
expectedCode: -1,
expectedOutput: "Database has already been initialized. Please use 'boundary database migrate'\nfor any upgrade needs.\n",
},
{
name: "bad_url_initialized",
initialized: true,
urlProvider: func() string { return "badurl" },
expectedCode: 2,
expectedError: "Unable to connect to the database at \"badurl\"\n",
},
{
name: "bad_url_not_intialized",
initialized: false,
urlProvider: func() string { return "badurl" },
expectedCode: 2,
expectedError: "Unable to connect to the database at \"badurl\"\n",
},
{
name: "cant_get_lock_initialized",
initialized: true,
urlProvider: func() string {
c, u, _, err := dbtest.StartUsingTemplate(dialect)
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, c())
})
dBase, err := common.SqlOpen(dialect, u)
require.NoError(t, err)
man, err := schema.NewManager(ctx, schema.Dialect(dialect), dBase)
require.NoError(t, err)
// This is an advisory lock on the DB which is released when the DB session ends.
err = man.ExclusiveLock(ctx)
require.NoError(t, err)
return u
},
expectedCode: 2,
expectedError: "Unable to capture a lock on the database.\n",
},
{
name: "cant_get_lock_not_initialized",
initialized: false,
urlProvider: func() string {
c, u, _, err := dbtest.StartUsingTemplate(dialect)
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, c())
})
dBase, err := common.SqlOpen(dialect, u)
require.NoError(t, err)
man, err := schema.NewManager(ctx, schema.Dialect(dialect), dBase)
require.NoError(t, err)
// This is an advisory lock on the DB which is released when the DB session ends.
err = man.ExclusiveLock(ctx)
require.NoError(t, err)
return u
},
expectedCode: 2,
expectedError: "Unable to capture a lock on the database.\n",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
u := tc.urlProvider()
ui := cli.NewMockUi()
clean, errCode := migrateDatabase(ctx, ui, dialect, u, tc.initialized, 10, nil)
clean()
assert.EqualValues(t, tc.expectedCode, errCode)
assert.Equal(t, tc.expectedOutput, ui.OutputWriter.String())
assert.Equal(t, tc.expectedError, ui.ErrorWriter.String())
})
}
}
func TestVerifyOplogIsEmpty(t *testing.T) {
dialect := "postgres"
ctx := context.Background()
c, u, _, err := dbtest.StartUsingTemplate(dialect)
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, c())
})
_ = c
dBase, err := common.SqlOpen(dialect, u)
require.NoError(t, err)
man, err := schema.NewManager(ctx, schema.Dialect(dialect), dBase)
require.NoError(t, err)
_, err = man.ApplyMigrations(ctx)
require.NoError(t, err)
cmd := InitCommand{Server: base.NewServer(base.NewCommand(cli.NewMockUi()))}
cmd.DatabaseUrl = u
require.NoError(t, cmd.OpenAndSetServerDatabase(ctx, dialect))
assert.NoError(t, cmd.verifyOplogIsEmpty(ctx))
}