mirror of https://github.com/hashicorp/boundary
fix(db): Reorder migrations (#2688)
Migration numbers need to be consistent between version upgrades. The migrations for the key lifecycle management were merged into v0.11.1 as number 56, but are currently 58 in main. This reorders them down to 56, fixing an issue when migrating from 0.11.1 to main.pull/2627/head
parent
70a1302cd9
commit
eb113b5c9e
@ -0,0 +1,295 @@
|
||||
package oss_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/auth/oidc"
|
||||
"github.com/hashicorp/boundary/internal/auth/password"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/db/common"
|
||||
"github.com/hashicorp/boundary/internal/db/schema"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
"github.com/hashicorp/boundary/testing/dbtest"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMigrations_DeleteOrphanedAccounts(t *testing.T) {
|
||||
const (
|
||||
priorMigration = 56001
|
||||
currentMigration = 57001
|
||||
)
|
||||
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
dialect := dbtest.Postgres
|
||||
|
||||
c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1))
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, c())
|
||||
})
|
||||
d, err := common.SqlOpen(dialect, u)
|
||||
require.NoError(t, err)
|
||||
|
||||
// migration to the prior migration (before the one we want to test)
|
||||
m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
|
||||
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}),
|
||||
))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = m.ApplyMigrations(ctx)
|
||||
require.NoError(t, err)
|
||||
state, err := m.CurrentState(ctx)
|
||||
require.NoError(t, err)
|
||||
want := &schema.State{
|
||||
Initialized: true,
|
||||
Editions: []schema.EditionState{
|
||||
{
|
||||
Name: "oss",
|
||||
BinarySchemaVersion: priorMigration,
|
||||
DatabaseSchemaVersion: priorMigration,
|
||||
DatabaseSchemaState: schema.Equal,
|
||||
},
|
||||
},
|
||||
}
|
||||
require.Equal(t, want, state)
|
||||
|
||||
// Get a connection
|
||||
dbType, err := db.StringToDbType(dialect)
|
||||
require.NoError(t, err)
|
||||
conn, err := db.Open(ctx, dbType, u)
|
||||
require.NoError(t, err)
|
||||
|
||||
wrapper := db.TestWrapper(t)
|
||||
rw := db.New(conn)
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
err = kmsCache.CreateKeys(context.Background(), scope.Global.String(), kms.WithRandomReader(rand.Reader))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create the user we will associate accounts with
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
usr, err := iam.NewUser(scope.Global.String())
|
||||
require.NoError(t, err)
|
||||
usr.PublicId = "u_1234567890"
|
||||
num, err := rw.Exec(ctx, `
|
||||
insert into iam_user
|
||||
(public_id, scope_id)
|
||||
values
|
||||
(?, ?)
|
||||
`, []any{usr.PublicId, scope.Global.String()})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
// Create the accounts we will delete and assert their behavior
|
||||
|
||||
pwAm1, err := password.NewAuthMethod(scope.Global.String())
|
||||
require.NoError(t, err)
|
||||
pwAm1.PublicId = "ampw_1234567890"
|
||||
_, err = rw.DoTx(ctx, 0, db.ExpBackoff{}, func(r db.Reader, w db.Writer) error {
|
||||
_, err := w.Exec(ctx, `
|
||||
insert into auth_password_argon2_conf
|
||||
(private_id, password_method_id)
|
||||
values
|
||||
(?, ?)
|
||||
`, []any{"arg2conf_1234567890", pwAm1.PublicId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Exec(ctx, `
|
||||
insert into auth_password_method
|
||||
(public_id, password_conf_id, scope_id)
|
||||
values
|
||||
(?, ?, ?)
|
||||
`, []any{pwAm1.PublicId, "arg2conf_1234567890", pwAm1.ScopeId})
|
||||
return err
|
||||
})
|
||||
require.NoError(t, err)
|
||||
pwAcct1, err := password.NewAccount(pwAm1.GetPublicId(), password.WithLoginName("account1"), password.WithPassword("password"))
|
||||
require.NoError(t, err)
|
||||
pwAcct1.PublicId = "acctpw_1234567890"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_password_account
|
||||
(public_id, auth_method_id, scope_id, login_name)
|
||||
values
|
||||
(?, ?, ?, ?)
|
||||
`, []any{pwAcct1.PublicId, pwAm1.PublicId, pwAm1.ScopeId, pwAcct1.LoginName})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
pwAm2, err := password.NewAuthMethod(scope.Global.String())
|
||||
require.NoError(t, err)
|
||||
pwAm2.PublicId = "ampw_0123456789"
|
||||
_, err = rw.DoTx(ctx, 0, db.ExpBackoff{}, func(r db.Reader, w db.Writer) error {
|
||||
_, err := w.Exec(ctx, `
|
||||
insert into auth_password_argon2_conf
|
||||
(private_id, password_method_id)
|
||||
values
|
||||
(?, ?)
|
||||
`, []any{"arg2conf_0123456789", pwAm2.PublicId})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Exec(ctx, `
|
||||
insert into auth_password_method
|
||||
(public_id, password_conf_id, scope_id)
|
||||
values
|
||||
(?, ?, ?)
|
||||
`, []any{pwAm2.PublicId, "arg2conf_0123456789", pwAm2.ScopeId})
|
||||
return err
|
||||
})
|
||||
pwAcct2, err := password.NewAccount(pwAm2.GetPublicId(), password.WithLoginName("account2"), password.WithPassword("password"))
|
||||
require.NoError(t, err)
|
||||
pwAcct2.PublicId = "acctpw_0123456789"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_password_account
|
||||
(public_id, auth_method_id, scope_id, login_name)
|
||||
values
|
||||
(?, ?, ?, ?)
|
||||
`, []any{pwAcct2.PublicId, pwAm2.PublicId, pwAm2.ScopeId, pwAcct2.LoginName})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
databaseWrapper, err := kmsCache.GetWrapper(context.Background(), scope.Global.String(), kms.KeyPurposeDatabase)
|
||||
oidcAm1 := oidc.TestAuthMethod(t, conn, databaseWrapper, scope.Global.String(), oidc.InactiveState, "alice_rp1",
|
||||
"my-dogs-name", oidc.WithIssuer(oidc.TestConvertToUrls(t, "https://alice1.com")[0]), oidc.WithApiUrl(oidc.TestConvertToUrls(t, "https://api1.com")[0]))
|
||||
oidcAm1.PublicId = "amoidc_1234567890"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_oidc_method
|
||||
(public_id, scope_id, state, key_id)
|
||||
values
|
||||
(?, ?, ?, ?)
|
||||
`, []any{oidcAm1.PublicId, oidcAm1.ScopeId, oidcAm1.OperationalState, oidcAm1.KeyId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
oidcAcct1, err := oidc.NewAccount(ctx, oidcAm1.GetPublicId(), "oidcAcct1")
|
||||
require.NoError(t, err)
|
||||
oidcAcct1.PublicId = "acctoidc_0123456789"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_oidc_account
|
||||
(public_id, auth_method_id, scope_id, issuer, subject)
|
||||
values
|
||||
(?, ?, ?, ?, ?)
|
||||
`, []any{oidcAcct1.PublicId, oidcAm1.PublicId, oidcAm1.ScopeId, oidcAm1.Issuer, oidcAcct1.Subject})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
oidcAm2 := oidc.TestAuthMethod(t, conn, databaseWrapper, scope.Global.String(), oidc.InactiveState, "alice_rp2",
|
||||
"my-dogs-name", oidc.WithIssuer(oidc.TestConvertToUrls(t, "https://alice2.com")[0]), oidc.WithApiUrl(oidc.TestConvertToUrls(t, "https://api2.com")[0]))
|
||||
oidcAm2.PublicId = "amoidc_0123456789"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_oidc_method
|
||||
(public_id, scope_id, state, key_id)
|
||||
values
|
||||
(?, ?, ?, ?)
|
||||
`, []any{oidcAm2.PublicId, oidcAm2.ScopeId, oidcAm2.OperationalState, oidcAm2.KeyId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
oidcAcct2, err := oidc.NewAccount(ctx, oidcAm2.GetPublicId(), "oidcAcct2")
|
||||
require.NoError(t, err)
|
||||
oidcAcct2.PublicId = "acctoidc_1234567890"
|
||||
num, err = rw.Exec(ctx, `
|
||||
insert into auth_oidc_account
|
||||
(public_id, auth_method_id, scope_id, issuer, subject)
|
||||
values
|
||||
(?, ?, ?, ?, ?)
|
||||
`, []any{oidcAcct2.PublicId, oidcAm2.PublicId, oidcAm2.ScopeId, oidcAm2.Issuer, oidcAcct2.Subject})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
num, err = rw.Exec(ctx, `
|
||||
update auth_account set
|
||||
iam_user_id=?
|
||||
where
|
||||
public_id in (?, ?, ?, ?)
|
||||
`, []any{
|
||||
usr.PublicId,
|
||||
pwAcct1.PublicId, pwAcct2.PublicId, oidcAcct1.PublicId, oidcAcct2.PublicId,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 4, num)
|
||||
usr, accts, err := iamRepo.LookupUser(ctx, usr.GetPublicId())
|
||||
require.NoError(t, err)
|
||||
assert.ElementsMatch(t, []string{
|
||||
pwAcct1.GetPublicId(), pwAcct2.GetPublicId(),
|
||||
oidcAcct1.GetPublicId(), oidcAcct2.GetPublicId(),
|
||||
}, accts)
|
||||
|
||||
num, err = rw.Exec(ctx, `
|
||||
delete from auth_password_account
|
||||
where
|
||||
public_id=?
|
||||
`, []any{pwAcct1.PublicId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
num, err = rw.Exec(ctx, `
|
||||
delete from auth_oidc_account
|
||||
where
|
||||
public_id=?
|
||||
`, []any{oidcAcct1.PublicId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
// pwAcct1 is still listed as an account for this user! oh no!
|
||||
_, accts, err = iamRepo.LookupUser(ctx, usr.GetPublicId())
|
||||
require.NoError(t, err)
|
||||
assert.ElementsMatch(t, []string{
|
||||
pwAcct1.GetPublicId(), pwAcct2.GetPublicId(),
|
||||
oidcAcct1.GetPublicId(), oidcAcct2.GetPublicId(),
|
||||
}, accts)
|
||||
|
||||
// now we're ready for the migration we want to test.
|
||||
m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
|
||||
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}),
|
||||
))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = m.ApplyMigrations(ctx)
|
||||
require.NoError(t, err)
|
||||
state, err = m.CurrentState(ctx)
|
||||
require.NoError(t, err)
|
||||
want = &schema.State{
|
||||
Initialized: true,
|
||||
Editions: []schema.EditionState{
|
||||
{
|
||||
Name: "oss",
|
||||
BinarySchemaVersion: currentMigration,
|
||||
DatabaseSchemaVersion: currentMigration,
|
||||
DatabaseSchemaState: schema.Equal,
|
||||
},
|
||||
},
|
||||
}
|
||||
require.Equal(t, want, state)
|
||||
|
||||
// pwAcct1 is no longer listed as an account for this user. Phew!
|
||||
_, accts, err = iamRepo.LookupUser(ctx, usr.GetPublicId())
|
||||
require.NoError(t, err)
|
||||
assert.ElementsMatch(t, []string{pwAcct2.GetPublicId(), oidcAcct2.GetPublicId()}, accts)
|
||||
|
||||
num, err = rw.Exec(ctx, `
|
||||
delete from auth_password_account
|
||||
where
|
||||
public_id=?
|
||||
`, []any{pwAcct2.PublicId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
_, accts, err = iamRepo.LookupUser(ctx, usr.GetPublicId())
|
||||
require.NoError(t, err)
|
||||
assert.ElementsMatch(t, []string{oidcAcct2.GetPublicId()}, accts)
|
||||
num, err = rw.Exec(ctx, `
|
||||
delete from auth_oidc_account
|
||||
where
|
||||
public_id=?
|
||||
`, []any{oidcAcct2.PublicId})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, num)
|
||||
|
||||
// Deleting the account now removes the association with the user
|
||||
_, accts, err = iamRepo.LookupUser(ctx, usr.GetPublicId())
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, accts)
|
||||
}
|
||||
@ -1,103 +0,0 @@
|
||||
package oss_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/auth/password"
|
||||
"github.com/hashicorp/boundary/internal/authtoken"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/db/common"
|
||||
"github.com/hashicorp/boundary/internal/db/schema"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
"github.com/hashicorp/boundary/testing/dbtest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMigrations_NewForeignKeys(t *testing.T) {
|
||||
const (
|
||||
priorMigration = 58001
|
||||
currentMigration = 58002
|
||||
)
|
||||
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
dialect := dbtest.Postgres
|
||||
|
||||
c, u, _, err := dbtest.StartUsingTemplate(dialect, dbtest.WithTemplate(dbtest.Template1))
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, c())
|
||||
})
|
||||
d, err := common.SqlOpen(dialect, u)
|
||||
require.NoError(t, err)
|
||||
|
||||
// migration to the prior migration (before the one we want to test)
|
||||
m, err := schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
|
||||
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": priorMigration}),
|
||||
))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = m.ApplyMigrations(ctx)
|
||||
require.NoError(t, err)
|
||||
state, err := m.CurrentState(ctx)
|
||||
require.NoError(t, err)
|
||||
want := &schema.State{
|
||||
Initialized: true,
|
||||
Editions: []schema.EditionState{
|
||||
{
|
||||
Name: "oss",
|
||||
BinarySchemaVersion: priorMigration,
|
||||
DatabaseSchemaVersion: priorMigration,
|
||||
DatabaseSchemaState: schema.Equal,
|
||||
},
|
||||
},
|
||||
}
|
||||
require.Equal(t, want, state)
|
||||
|
||||
// Get a connection
|
||||
dbType, err := db.StringToDbType(dialect)
|
||||
require.NoError(t, err)
|
||||
conn, err := db.Open(ctx, dbType, u)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create project
|
||||
wrapper := db.TestWrapper(t)
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
err = kmsCache.CreateKeys(ctx, scope.Global.String())
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a password account
|
||||
pwam := password.TestAuthMethod(t, conn, "global")
|
||||
password.TestAccount(t, conn, pwam.PublicId, "user", password.WithPassword("password"))
|
||||
|
||||
// Create an auth token
|
||||
tok := authtoken.TestAuthToken(t, conn, kmsCache, "global")
|
||||
_ = tok
|
||||
|
||||
// now we're ready for the migration we want to test.
|
||||
m, err = schema.NewManager(ctx, schema.Dialect(dialect), d, schema.WithEditions(
|
||||
schema.TestCreatePartialEditions(schema.Dialect(dialect), schema.PartialEditions{"oss": currentMigration}),
|
||||
))
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = m.ApplyMigrations(ctx)
|
||||
require.NoError(t, err)
|
||||
state, err = m.CurrentState(ctx)
|
||||
require.NoError(t, err)
|
||||
want = &schema.State{
|
||||
Initialized: true,
|
||||
Editions: []schema.EditionState{
|
||||
{
|
||||
Name: "oss",
|
||||
BinarySchemaVersion: currentMigration,
|
||||
DatabaseSchemaVersion: currentMigration,
|
||||
DatabaseSchemaState: schema.Equal,
|
||||
},
|
||||
},
|
||||
}
|
||||
require.Equal(t, want, state)
|
||||
|
||||
// As long as there were no errors, the migration succeeded.
|
||||
}
|
||||
Loading…
Reference in new issue