package test import ( "context" "database/sql" "git.dragse.it/anthrove/otter-space-sdk/pkg/models" migrate "github.com/rubenv/sql-migrate" postgrescontainer "github.com/testcontainers/testcontainers-go/modules/postgres" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" "net/url" "strconv" "strings" "time" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" ) const ( databaseName = "anthrove" databaseUser = "anthrove" databasePassword = "anthrove" migrationSource = "../../pkg/database/migrations" ) func StartPostgresContainer(ctx context.Context) (*postgrescontainer.PostgresContainer, *gorm.DB, error) { pgContainer, err := postgrescontainer.RunContainer(ctx, testcontainers.WithImage("postgres:alpine"), postgrescontainer.WithDatabase(databaseName), postgrescontainer.WithUsername(databaseUser), postgrescontainer.WithPassword(databasePassword), testcontainers.WithWaitStrategy( wait.ForLog("database system is ready to accept connections"). WithOccurrence(2).WithStartupTimeout(5*time.Second)), ) if err != nil { return nil, nil, err } connectionString, err := pgContainer.ConnectionString(ctx, "sslmode=disable") if err != nil { return nil, nil, err } err = migrateDatabase(connectionString) if err != nil { return nil, nil, err } gormDB, err := getGormDB(connectionString) if err != nil { return nil, nil, err } return pgContainer, gormDB, nil } func migrateDatabase(connectionString string) error { db, err := sql.Open("postgres", connectionString) if err != nil { return err } migrations := &migrate.FileMigrationSource{ Dir: migrationSource, } _, err = migrate.Exec(db, "postgres", migrations, migrate.Up) if err != nil { return err } return nil } func getGormDB(connectionString string) (*gorm.DB, error) { return gorm.Open(postgres.Open(connectionString), &gorm.Config{ Logger: logger.Default.LogMode(logger.Info), }) } func DatabaseModesFromConnectionString(ctx context.Context, pgContainer *postgrescontainer.PostgresContainer) (*models.DatabaseConfig, error) { var err error connectionString, err := pgContainer.ConnectionString(ctx) if err != nil { return nil, err } url, err := url.Parse(connectionString) if err != nil { return nil, err } split := strings.Split(url.Host, ":") host := split[0] port, err := strconv.Atoi(split[1]) if err != nil { return nil, err } database := strings.TrimPrefix(url.Path, "/") username := url.User.Username() password, _ := url.User.Password() return &models.DatabaseConfig{ Endpoint: host, Username: username, Password: password, Database: database, Port: port, SSL: false, Timezone: "Europe/Berlin", Debug: true, }, nil }