[management] optimize test execution (#3204)

This commit is contained in:
Pascal Fischer
2025-02-19 19:13:45 +01:00
committed by GitHub
parent 27b3891b14
commit 7e6beee7f6
16 changed files with 1019 additions and 643 deletions

View File

@@ -42,7 +42,7 @@ func TestGetDNSSettings(t *testing.T) {
account, err := initTestDNSAccount(t, am)
if err != nil {
t.Fatal("failed to init testing account")
t.Fatalf("failed to init testing account: %s", err)
}
dnsSettings, err := am.GetDNSSettings(context.Background(), account.Id, dnsAdminUserID)
@@ -124,12 +124,12 @@ func TestSaveDNSSettings(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
am, err := createDNSManager(t)
if err != nil {
t.Error("failed to create account manager")
t.Fatalf("failed to create account manager")
}
account, err := initTestDNSAccount(t, am)
if err != nil {
t.Error("failed to init testing account")
t.Fatalf("failed to init testing account: %v", err)
}
err = am.SaveDNSSettings(context.Background(), account.Id, testCase.userID, testCase.inputSettings)
@@ -156,22 +156,22 @@ func TestGetNetworkMap_DNSConfigSync(t *testing.T) {
am, err := createDNSManager(t)
if err != nil {
t.Error("failed to create account manager")
t.Fatalf("failed to create account manager: %s", err)
}
account, err := initTestDNSAccount(t, am)
if err != nil {
t.Error("failed to init testing account")
t.Fatalf("failed to init testing account: %s", err)
}
peer1, err := account.FindPeerByPubKey(dnsPeer1Key)
if err != nil {
t.Error("failed to init testing account")
t.Fatalf("failed to init testing account: %s", err)
}
peer2, err := account.FindPeerByPubKey(dnsPeer2Key)
if err != nil {
t.Error("failed to init testing account")
t.Fatalf("failed to init testing account: %s", err)
}
newAccountDNSConfig, err := am.GetNetworkMap(context.Background(), peer1.ID)

View File

@@ -29,7 +29,7 @@ func TestDefaultAccountManager_CreateGroup(t *testing.T) {
_, account, err := initTestGroupAccount(am)
if err != nil {
t.Error("failed to init testing account")
t.Fatalf("failed to init testing account: %s", err)
}
for _, group := range account.Groups {
group.Issued = types.GroupIssuedIntegration
@@ -59,12 +59,12 @@ func TestDefaultAccountManager_CreateGroup(t *testing.T) {
func TestDefaultAccountManager_DeleteGroup(t *testing.T) {
am, err := createManager(t)
if err != nil {
t.Error("failed to create account manager")
t.Fatalf("failed to create account manager: %s", err)
}
_, account, err := initTestGroupAccount(am)
if err != nil {
t.Error("failed to init testing account")
t.Fatalf("failed to init testing account: %s", err)
}
testCases := []struct {

View File

@@ -1,13 +0,0 @@
package server_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestManagement(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Management Service Suite")
}

File diff suppressed because it is too large Load Diff

View File

@@ -379,12 +379,12 @@ func TestCreateNameServerGroup(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
am, err := createNSManager(t)
if err != nil {
t.Error("failed to create account manager")
t.Fatalf("failed to create account manager: %s", err)
}
account, err := initTestNSAccount(t, am)
if err != nil {
t.Error("failed to init testing account")
t.Fatalf("failed to init testing account: %s", err)
}
outNSGroup, err := am.CreateNameServerGroup(
@@ -607,12 +607,12 @@ func TestSaveNameServerGroup(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
am, err := createNSManager(t)
if err != nil {
t.Error("failed to create account manager")
t.Fatalf("failed to create account manager: %s", err)
}
account, err := initTestNSAccount(t, am)
if err != nil {
t.Error("failed to init testing account")
t.Fatalf("failed to init testing account: %s", err)
}
account.NameServerGroups[testCase.existingNSGroup.ID] = testCase.existingNSGroup
@@ -706,7 +706,7 @@ func TestDeleteNameServerGroup(t *testing.T) {
account, err := initTestNSAccount(t, am)
if err != nil {
t.Error("failed to init testing account")
t.Fatalf("failed to init testing account: %s", err)
}
account.NameServerGroups[testingNSGroup.ID] = testingNSGroup
@@ -741,7 +741,7 @@ func TestGetNameServerGroup(t *testing.T) {
account, err := initTestNSAccount(t, am)
if err != nil {
t.Error("failed to init testing account")
t.Fatalf("failed to init testing account: %s", err)
}
foundGroup, err := am.GetNameServerGroup(context.Background(), account.Id, testUserID, existingNSGroupID)
@@ -761,6 +761,7 @@ func TestGetNameServerGroup(t *testing.T) {
func createNSManager(t *testing.T) (*DefaultAccountManager, error) {
t.Helper()
store, err := createNSStore(t)
if err != nil {
return nil, err

View File

@@ -13,12 +13,11 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/netbirdio/netbird/management/domain"
"github.com/netbirdio/netbird/management/server/activity"
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
networkTypes "github.com/netbirdio/netbird/management/server/networks/types"
"github.com/netbirdio/netbird/management/domain"
"github.com/netbirdio/netbird/management/server/activity"
nbpeer "github.com/netbirdio/netbird/management/server/peer"
"github.com/netbirdio/netbird/management/server/store"
"github.com/netbirdio/netbird/management/server/telemetry"

View File

@@ -37,40 +37,44 @@ import (
nbroute "github.com/netbirdio/netbird/route"
)
func TestSqlite_NewStore(t *testing.T) {
func runTestForAllEngines(t *testing.T, testDataFile string, f func(t *testing.T, store Store)) {
t.Helper()
for _, engine := range supportedEngines {
if os.Getenv("NETBIRD_STORE_ENGINE") != "" && os.Getenv("NETBIRD_STORE_ENGINE") != string(engine) {
continue
}
t.Setenv("NETBIRD_STORE_ENGINE", string(engine))
store, cleanUp, err := NewTestStoreFromSQL(context.Background(), testDataFile, t.TempDir())
t.Cleanup(cleanUp)
assert.NoError(t, err)
t.Run(string(engine), func(t *testing.T) {
f(t, store)
})
os.Unsetenv("NETBIRD_STORE_ENGINE")
}
}
func Test_NewStore(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("The SQLite store is not properly supported by Windows yet")
}
t.Setenv("NETBIRD_STORE_ENGINE", string(SqliteStoreEngine))
store, cleanUp, err := NewTestStoreFromSQL(context.Background(), "", t.TempDir())
t.Cleanup(cleanUp)
assert.NoError(t, err)
if len(store.GetAllAccounts(context.Background())) != 0 {
t.Errorf("expected to create a new empty Accounts map when creating a new FileStore")
}
runTestForAllEngines(t, "", func(t *testing.T, store Store) {
if store == nil {
t.Errorf("expected to create a new Store")
}
if len(store.GetAllAccounts(context.Background())) != 0 {
t.Errorf("expected to create a new empty Accounts map when creating a new FileStore")
}
})
}
func TestSqlite_SaveAccount_Large(t *testing.T) {
func Test_SaveAccount_Large(t *testing.T) {
if (os.Getenv("CI") == "true" && runtime.GOOS == "darwin") || runtime.GOOS == "windows" {
t.Skip("skip CI tests on darwin and windows")
}
t.Run("SQLite", func(t *testing.T) {
t.Setenv("NETBIRD_STORE_ENGINE", string(SqliteStoreEngine))
store, cleanUp, err := NewTestStoreFromSQL(context.Background(), "", t.TempDir())
t.Cleanup(cleanUp)
assert.NoError(t, err)
runLargeTest(t, store)
})
// create store outside to have a better time counter for the test
t.Setenv("NETBIRD_STORE_ENGINE", string(SqliteStoreEngine))
store, cleanUp, err := NewTestStoreFromSQL(context.Background(), "", t.TempDir())
t.Cleanup(cleanUp)
assert.NoError(t, err)
t.Run("PostgreSQL", func(t *testing.T) {
runTestForAllEngines(t, "", func(t *testing.T, store Store) {
runLargeTest(t, store)
})
}
@@ -215,77 +219,74 @@ func randomIPv4() net.IP {
return net.IP(b)
}
func TestSqlite_SaveAccount(t *testing.T) {
func Test_SaveAccount(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("The SQLite store is not properly supported by Windows yet")
}
t.Setenv("NETBIRD_STORE_ENGINE", string(SqliteStoreEngine))
store, cleanUp, err := NewTestStoreFromSQL(context.Background(), "", t.TempDir())
t.Cleanup(cleanUp)
assert.NoError(t, err)
runTestForAllEngines(t, "", func(t *testing.T, store Store) {
account := newAccountWithId(context.Background(), "account_id", "testuser", "")
setupKey, _ := types.GenerateDefaultSetupKey()
account.SetupKeys[setupKey.Key] = setupKey
account.Peers["testpeer"] = &nbpeer.Peer{
Key: "peerkey",
IP: net.IP{127, 0, 0, 1},
Meta: nbpeer.PeerSystemMeta{},
Name: "peer name",
Status: &nbpeer.PeerStatus{Connected: true, LastSeen: time.Now().UTC()},
}
account := newAccountWithId(context.Background(), "account_id", "testuser", "")
setupKey, _ := types.GenerateDefaultSetupKey()
account.SetupKeys[setupKey.Key] = setupKey
account.Peers["testpeer"] = &nbpeer.Peer{
Key: "peerkey",
IP: net.IP{127, 0, 0, 1},
Meta: nbpeer.PeerSystemMeta{},
Name: "peer name",
Status: &nbpeer.PeerStatus{Connected: true, LastSeen: time.Now().UTC()},
}
err := store.SaveAccount(context.Background(), account)
require.NoError(t, err)
err = store.SaveAccount(context.Background(), account)
require.NoError(t, err)
account2 := newAccountWithId(context.Background(), "account_id2", "testuser2", "")
setupKey, _ = types.GenerateDefaultSetupKey()
account2.SetupKeys[setupKey.Key] = setupKey
account2.Peers["testpeer2"] = &nbpeer.Peer{
Key: "peerkey2",
IP: net.IP{127, 0, 0, 2},
Meta: nbpeer.PeerSystemMeta{},
Name: "peer name 2",
Status: &nbpeer.PeerStatus{Connected: true, LastSeen: time.Now().UTC()},
}
account2 := newAccountWithId(context.Background(), "account_id2", "testuser2", "")
setupKey, _ = types.GenerateDefaultSetupKey()
account2.SetupKeys[setupKey.Key] = setupKey
account2.Peers["testpeer2"] = &nbpeer.Peer{
Key: "peerkey2",
IP: net.IP{127, 0, 0, 2},
Meta: nbpeer.PeerSystemMeta{},
Name: "peer name 2",
Status: &nbpeer.PeerStatus{Connected: true, LastSeen: time.Now().UTC()},
}
err = store.SaveAccount(context.Background(), account2)
require.NoError(t, err)
err = store.SaveAccount(context.Background(), account2)
require.NoError(t, err)
if len(store.GetAllAccounts(context.Background())) != 2 {
t.Errorf("expecting 2 Accounts to be stored after SaveAccount()")
}
if len(store.GetAllAccounts(context.Background())) != 2 {
t.Errorf("expecting 2 Accounts to be stored after SaveAccount()")
}
a, err := store.GetAccount(context.Background(), account.Id)
if a == nil {
t.Errorf("expecting Account to be stored after SaveAccount(): %v", err)
}
a, err := store.GetAccount(context.Background(), account.Id)
if a == nil {
t.Errorf("expecting Account to be stored after SaveAccount(): %v", err)
}
if a != nil && len(a.Policies) != 1 {
t.Errorf("expecting Account to have one policy stored after SaveAccount(), got %d", len(a.Policies))
}
if a != nil && len(a.Policies) != 1 {
t.Errorf("expecting Account to have one policy stored after SaveAccount(), got %d", len(a.Policies))
}
if a != nil && len(a.Policies[0].Rules) != 1 {
t.Errorf("expecting Account to have one policy rule stored after SaveAccount(), got %d", len(a.Policies[0].Rules))
return
}
if a != nil && len(a.Policies[0].Rules) != 1 {
t.Errorf("expecting Account to have one policy rule stored after SaveAccount(), got %d", len(a.Policies[0].Rules))
return
}
if a, err := store.GetAccountByPeerPubKey(context.Background(), "peerkey"); a == nil {
t.Errorf("expecting PeerKeyID2AccountID index updated after SaveAccount(): %v", err)
}
if a, err := store.GetAccountByPeerPubKey(context.Background(), "peerkey"); a == nil {
t.Errorf("expecting PeerKeyID2AccountID index updated after SaveAccount(): %v", err)
}
if a, err := store.GetAccountByUser(context.Background(), "testuser"); a == nil {
t.Errorf("expecting UserID2AccountID index updated after SaveAccount(): %v", err)
}
if a, err := store.GetAccountByUser(context.Background(), "testuser"); a == nil {
t.Errorf("expecting UserID2AccountID index updated after SaveAccount(): %v", err)
}
if a, err := store.GetAccountByPeerID(context.Background(), "testpeer"); a == nil {
t.Errorf("expecting PeerID2AccountID index updated after SaveAccount(): %v", err)
}
if a, err := store.GetAccountByPeerID(context.Background(), "testpeer"); a == nil {
t.Errorf("expecting PeerID2AccountID index updated after SaveAccount(): %v", err)
}
if a, err := store.GetAccountBySetupKey(context.Background(), setupKey.Key); a == nil {
t.Errorf("expecting SetupKeyID2AccountID index updated after SaveAccount(): %v", err)
}
if a, err := store.GetAccountBySetupKey(context.Background(), setupKey.Key); a == nil {
t.Errorf("expecting SetupKeyID2AccountID index updated after SaveAccount(): %v", err)
}
})
}
func TestSqlite_DeleteAccount(t *testing.T) {
@@ -402,27 +403,24 @@ func TestSqlite_DeleteAccount(t *testing.T) {
}
}
func TestSqlite_GetAccount(t *testing.T) {
func Test_GetAccount(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("The SQLite store is not properly supported by Windows yet")
}
t.Setenv("NETBIRD_STORE_ENGINE", string(SqliteStoreEngine))
store, cleanUp, err := NewTestStoreFromSQL(context.Background(), "../testdata/store.sql", t.TempDir())
t.Cleanup(cleanUp)
assert.NoError(t, err)
runTestForAllEngines(t, "../testdata/store.sql", func(t *testing.T, store Store) {
id := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
id := "bf1c8084-ba50-4ce7-9439-34653001fc3b"
account, err := store.GetAccount(context.Background(), id)
require.NoError(t, err)
require.Equal(t, id, account.Id, "account id should match")
account, err := store.GetAccount(context.Background(), id)
require.NoError(t, err)
require.Equal(t, id, account.Id, "account id should match")
_, err = store.GetAccount(context.Background(), "non-existing-account")
assert.Error(t, err)
parsedErr, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, status.NotFound, parsedErr.Type(), "should return not found error")
_, err = store.GetAccount(context.Background(), "non-existing-account")
assert.Error(t, err)
parsedErr, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, status.NotFound, parsedErr.Type(), "should return not found error")
})
}
func TestSqlStore_SavePeer(t *testing.T) {
@@ -580,51 +578,45 @@ func TestSqlStore_SavePeerLocation(t *testing.T) {
require.Equal(t, status.NotFound, parsedErr.Type(), "should return not found error")
}
func TestSqlite_TestGetAccountByPrivateDomain(t *testing.T) {
func Test_TestGetAccountByPrivateDomain(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("The SQLite store is not properly supported by Windows yet")
}
t.Setenv("NETBIRD_STORE_ENGINE", string(SqliteStoreEngine))
store, cleanUp, err := NewTestStoreFromSQL(context.Background(), "../testdata/store.sql", t.TempDir())
t.Cleanup(cleanUp)
assert.NoError(t, err)
runTestForAllEngines(t, "../testdata/store.sql", func(t *testing.T, store Store) {
existingDomain := "test.com"
existingDomain := "test.com"
account, err := store.GetAccountByPrivateDomain(context.Background(), existingDomain)
require.NoError(t, err, "should found account")
require.Equal(t, existingDomain, account.Domain, "domains should match")
account, err := store.GetAccountByPrivateDomain(context.Background(), existingDomain)
require.NoError(t, err, "should found account")
require.Equal(t, existingDomain, account.Domain, "domains should match")
_, err = store.GetAccountByPrivateDomain(context.Background(), "missing-domain.com")
require.Error(t, err, "should return error on domain lookup")
parsedErr, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, status.NotFound, parsedErr.Type(), "should return not found error")
_, err = store.GetAccountByPrivateDomain(context.Background(), "missing-domain.com")
require.Error(t, err, "should return error on domain lookup")
parsedErr, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, status.NotFound, parsedErr.Type(), "should return not found error")
})
}
func TestSqlite_GetTokenIDByHashedToken(t *testing.T) {
func Test_GetTokenIDByHashedToken(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("The SQLite store is not properly supported by Windows yet")
}
t.Setenv("NETBIRD_STORE_ENGINE", string(SqliteStoreEngine))
store, cleanUp, err := NewTestStoreFromSQL(context.Background(), "../testdata/store.sql", t.TempDir())
t.Cleanup(cleanUp)
assert.NoError(t, err)
runTestForAllEngines(t, "../testdata/store.sql", func(t *testing.T, store Store) {
hashed := "SoMeHaShEdToKeN"
id := "9dj38s35-63fb-11ec-90d6-0242ac120003"
hashed := "SoMeHaShEdToKeN"
id := "9dj38s35-63fb-11ec-90d6-0242ac120003"
token, err := store.GetTokenIDByHashedToken(context.Background(), hashed)
require.NoError(t, err)
require.Equal(t, id, token)
token, err := store.GetTokenIDByHashedToken(context.Background(), hashed)
require.NoError(t, err)
require.Equal(t, id, token)
_, err = store.GetTokenIDByHashedToken(context.Background(), "non-existing-hash")
require.Error(t, err)
parsedErr, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, status.NotFound, parsedErr.Type(), "should return not found error")
_, err = store.GetTokenIDByHashedToken(context.Background(), "non-existing-hash")
require.Error(t, err)
parsedErr, ok := status.FromError(err)
require.True(t, ok)
require.Equal(t, status.NotFound, parsedErr.Type(), "should return not found error")
})
}
func TestMigrate(t *testing.T) {

View File

@@ -9,11 +9,16 @@ import (
"os"
"path"
"path/filepath"
"regexp"
"runtime"
"slices"
"strings"
"time"
"github.com/google/uuid"
log "github.com/sirupsen/logrus"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
@@ -193,6 +198,8 @@ const (
mysqlDsnEnv = "NETBIRD_STORE_ENGINE_MYSQL_DSN"
)
var supportedEngines = []Engine{SqliteStoreEngine, PostgresStoreEngine, MysqlStoreEngine}
func getStoreEngineFromEnv() Engine {
// NETBIRD_STORE_ENGINE supposed to be used in tests. Otherwise, rely on the config file.
kind, ok := os.LookupEnv("NETBIRD_STORE_ENGINE")
@@ -201,7 +208,7 @@ func getStoreEngineFromEnv() Engine {
}
value := Engine(strings.ToLower(kind))
if value == SqliteStoreEngine || value == PostgresStoreEngine || value == MysqlStoreEngine {
if slices.Contains(supportedEngines, value) {
return value
}
@@ -349,51 +356,126 @@ func NewTestStoreFromSQL(ctx context.Context, filename string, dataDir string) (
}
func getSqlStoreEngine(ctx context.Context, store *SqlStore, kind Engine) (Store, func(), error) {
if kind == PostgresStoreEngine {
cleanUp, err := testutil.CreatePostgresTestContainer()
if err != nil {
return nil, nil, err
var cleanup func()
var err error
switch kind {
case PostgresStoreEngine:
store, cleanup, err = newReusedPostgresStore(ctx, store, kind)
case MysqlStoreEngine:
store, cleanup, err = newReusedMysqlStore(ctx, store, kind)
default:
cleanup = func() {
// sqlite doesn't need to be cleaned up
}
dsn, ok := os.LookupEnv(postgresDsnEnv)
if !ok {
return nil, nil, fmt.Errorf("%s is not set", postgresDsnEnv)
}
store, err = NewPostgresqlStoreFromSqlStore(ctx, store, dsn, nil)
if err != nil {
return nil, nil, err
}
return store, cleanUp, nil
}
if kind == MysqlStoreEngine {
cleanUp, err := testutil.CreateMysqlTestContainer()
if err != nil {
return nil, nil, err
}
dsn, ok := os.LookupEnv(mysqlDsnEnv)
if !ok {
return nil, nil, fmt.Errorf("%s is not set", mysqlDsnEnv)
}
store, err = NewMysqlStoreFromSqlStore(ctx, store, dsn, nil)
if err != nil {
return nil, nil, err
}
return store, cleanUp, nil
if err != nil {
return nil, cleanup, fmt.Errorf("failed to create test store: %v", err)
}
closeConnection := func() {
cleanup()
store.Close(ctx)
}
return store, closeConnection, nil
}
func newReusedPostgresStore(ctx context.Context, store *SqlStore, kind Engine) (*SqlStore, func(), error) {
if envDsn, ok := os.LookupEnv(postgresDsnEnv); !ok || envDsn == "" {
var err error
_, err = testutil.CreatePostgresTestContainer()
if err != nil {
return nil, nil, err
}
}
dsn, ok := os.LookupEnv(postgresDsnEnv)
if !ok {
return nil, nil, fmt.Errorf("%s is not set", postgresDsnEnv)
}
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
return nil, nil, fmt.Errorf("failed to open postgres connection: %v", err)
}
dsn, cleanup, err := createRandomDB(dsn, db, kind)
if err != nil {
return nil, cleanup, err
}
store, err = NewPostgresqlStoreFromSqlStore(ctx, store, dsn, nil)
if err != nil {
return nil, cleanup, err
}
return store, cleanup, nil
}
func newReusedMysqlStore(ctx context.Context, store *SqlStore, kind Engine) (*SqlStore, func(), error) {
if envDsn, ok := os.LookupEnv(mysqlDsnEnv); !ok || envDsn == "" {
var err error
_, err = testutil.CreateMysqlTestContainer()
if err != nil {
return nil, nil, err
}
}
dsn, ok := os.LookupEnv(mysqlDsnEnv)
if !ok {
return nil, nil, fmt.Errorf("%s is not set", mysqlDsnEnv)
}
db, err := gorm.Open(mysql.Open(dsn+"?charset=utf8&parseTime=True&loc=Local"), &gorm.Config{})
if err != nil {
return nil, nil, fmt.Errorf("failed to open mysql connection: %v", err)
}
dsn, cleanup, err := createRandomDB(dsn, db, kind)
if err != nil {
return nil, cleanup, err
}
store, err = NewMysqlStoreFromSqlStore(ctx, store, dsn, nil)
if err != nil {
return nil, nil, err
}
return store, cleanup, nil
}
func createRandomDB(dsn string, db *gorm.DB, engine Engine) (string, func(), error) {
dbName := fmt.Sprintf("test_db_%s", strings.ReplaceAll(uuid.New().String(), "-", "_"))
if err := db.Exec(fmt.Sprintf("CREATE DATABASE %s", dbName)).Error; err != nil {
return "", nil, fmt.Errorf("failed to create database: %v", err)
}
var err error
cleanup := func() {
switch engine {
case PostgresStoreEngine:
err = db.Exec(fmt.Sprintf("DROP DATABASE %s WITH (FORCE)", dbName)).Error
case MysqlStoreEngine:
// err = killMySQLConnections(dsn, dbName)
err = db.Exec(fmt.Sprintf("DROP DATABASE %s", dbName)).Error
}
if err != nil {
log.Errorf("failed to drop database %s: %v", dbName, err)
panic(err)
}
sqlDB, _ := db.DB()
_ = sqlDB.Close()
}
return replaceDBName(dsn, dbName), cleanup, nil
}
func replaceDBName(dsn, newDBName string) string {
re := regexp.MustCompile(`(?P<pre>[:/@])(?P<dbname>[^/?]+)(?P<post>\?|$)`)
return re.ReplaceAllString(dsn, `${pre}`+newDBName+`${post}`)
}
func loadSQL(db *gorm.DB, filepath string) error {
sqlContent, err := os.ReadFile(filepath)
if err != nil {

View File

@@ -22,7 +22,7 @@ func CreateMysqlTestContainer() (func(), error) {
myContainer, err := mysql.RunContainer(ctx,
testcontainers.WithImage("mlsmaycon/warmed-mysql:8"),
mysql.WithDatabase("testing"),
mysql.WithUsername("testing"),
mysql.WithUsername("root"),
mysql.WithPassword("testing"),
testcontainers.WithWaitStrategy(
wait.ForLog("/usr/sbin/mysqld: ready for connections").
@@ -34,6 +34,7 @@ func CreateMysqlTestContainer() (func(), error) {
}
cleanup := func() {
os.Unsetenv("NETBIRD_STORE_ENGINE_MYSQL_DSN")
timeoutCtx, cancelFunc := context.WithTimeout(ctx, 1*time.Second)
defer cancelFunc()
if err = myContainer.Terminate(timeoutCtx); err != nil {
@@ -68,6 +69,7 @@ func CreatePostgresTestContainer() (func(), error) {
}
cleanup := func() {
os.Unsetenv("NETBIRD_STORE_ENGINE_POSTGRES_DSN")
timeoutCtx, cancelFunc := context.WithTimeout(ctx, 1*time.Second)
defer cancelFunc()
if err = pgContainer.Terminate(timeoutCtx); err != nil {

View File

@@ -80,7 +80,7 @@ type User struct {
// AutoGroups is a list of Group IDs to auto-assign to peers registered by this user
AutoGroups []string `gorm:"serializer:json"`
PATs map[string]*PersonalAccessToken `gorm:"-"`
PATsG []PersonalAccessToken `json:"-" gorm:"foreignKey:UserID;references:id"`
PATsG []PersonalAccessToken `json:"-" gorm:"foreignKey:UserID;references:id;constraint:OnDelete:CASCADE;"`
// 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