diff --git a/management/server/migration/migration.go b/management/server/migration/migration.go index 9dc101d24..0a6951736 100644 --- a/management/server/migration/migration.go +++ b/management/server/migration/migration.go @@ -18,11 +18,9 @@ import ( ) func GetColumnName(db *gorm.DB, column string) string { - if db.Name() == "mysql" { return fmt.Sprintf("`%s`", column) } - return column } @@ -220,7 +218,6 @@ func MigrateNetIPFieldFromBlobToJSON[T any](ctx context.Context, db *gorm.DB, fi } func MigrateSetupKeyToHashedSetupKey[T any](ctx context.Context, db *gorm.DB) error { - orgColumnName := "key" oldColumnName := GetColumnName(db, orgColumnName) newColumnName := "key_secret" diff --git a/management/server/testutil/store.go b/management/server/testutil/store.go index 0ff1e87bd..e96960562 100644 --- a/management/server/testutil/store.go +++ b/management/server/testutil/store.go @@ -11,18 +11,31 @@ import ( "runtime" "time" - log "github.com/sirupsen/logrus" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mysql" "github.com/testcontainers/testcontainers-go/modules/postgres" "github.com/testcontainers/testcontainers-go/wait" ) -var mysqlContainerConfigPath = "../testdata/mysql.cnf" +var ( + mysqlContainerConfigPath = "../testdata/mysql.cnf" + mysqlContainer = (*mysql.MySQLContainer)(nil) + postgresContainer = (*postgres.PostgresContainer)(nil) + mysqlConnStr = "" + postgresConnStr = "" +) +func emptyCleanup() { return } + +// CreateMysqlTestContainer creates a new MySQL container for testing. func CreateMysqlTestContainer() (func(), error) { ctx := context.Background() + if mysqlContainer != nil && mysqlContainer.IsRunning() { + refreshMysqlDatabase(ctx) + return emptyCleanup, os.Setenv("NETBIRD_STORE_ENGINE_MYSQL_DSN", mysqlConnStr) + } + _, caller, _, ok := runtime.Caller(0) if !ok { return nil, fmt.Errorf("failed to get caller information") @@ -39,23 +52,25 @@ func CreateMysqlTestContainer() (func(), error) { return nil, err } - cleanup := func() { - if err = container.Terminate(ctx); err != nil { - log.WithContext(ctx).Warnf("failed to terminate container: %s", err) - } - } - talksConn, err := container.ConnectionString(ctx) if err != nil { - return cleanup, err + return nil, err } + mysqlContainer = container + mysqlConnStr = talksConn - return cleanup, os.Setenv("NETBIRD_STORE_ENGINE_MYSQL_DSN", talksConn) + return emptyCleanup, os.Setenv("NETBIRD_STORE_ENGINE_MYSQL_DSN", talksConn) } +// CreatePostgresTestContainer creates a new PostgreSQL container for testing. func CreatePostgresTestContainer() (func(), error) { ctx := context.Background() + if postgresContainer != nil && postgresContainer.IsRunning() { + refreshPostgresDatabase(ctx) + return emptyCleanup, os.Setenv("NETBIRD_STORE_ENGINE_POSTGRES_DSN", postgresConnStr) + } + container, err := postgres.RunContainer(ctx, testcontainers.WithImage("postgres:16-alpine"), postgres.WithDatabase("netbird"), @@ -70,16 +85,22 @@ func CreatePostgresTestContainer() (func(), error) { return nil, err } - cleanup := func() { - if err = container.Terminate(ctx); err != nil { - log.WithContext(ctx).Warnf("failed to terminate container: %s", err) - } - } - talksConn, err := container.ConnectionString(ctx) if err != nil { - return cleanup, err + return nil, err } + postgresContainer = container + postgresConnStr = talksConn - return cleanup, os.Setenv("NETBIRD_STORE_ENGINE_POSTGRES_DSN", talksConn) + return emptyCleanup, os.Setenv("NETBIRD_STORE_ENGINE_POSTGRES_DSN", talksConn) +} + +func refreshMysqlDatabase(ctx context.Context) { + _, _, _ = mysqlContainer.Exec(ctx, []string{"mysqladmin", "--user=root", "drop", "netbird", "-f"}) + _, _, _ = mysqlContainer.Exec(ctx, []string{"mysqladmin", "--user=root", "create", "netbird"}) +} + +func refreshPostgresDatabase(ctx context.Context) { + _, _, _ = postgresContainer.Exec(ctx, []string{"dropdb", "-f", "netbird"}) + _, _, _ = postgresContainer.Exec(ctx, []string{"createdb", "netbird"}) } diff --git a/management/server/types/user.go b/management/server/types/user.go index 5f1b71792..9a6c734e9 100644 --- a/management/server/types/user.go +++ b/management/server/types/user.go @@ -84,7 +84,7 @@ type User struct { // Blocked indicates whether the user is blocked. Blocked users can't use the system. Blocked bool // LastLogin is the last time the user logged in to IdP - LastLogin time.Time + LastLogin time.Time `gorm:"type:TIMESTAMP;null;default:null"` // CreatedAt records the time the user was created CreatedAt time.Time