package test import ( "context" "database/sql" "net/url" "strconv" "strings" "time" "git.anthrove.art/Anthrove/otter-space-sdk/v4/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" _ "github.com/lib/pq" "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.Run(ctx, "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(60*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), TranslateError: true, }) } func DatabaseModesFromConnectionString(ctx context.Context, pgContainer *postgrescontainer.PostgresContainer) (models.DatabaseConfig, error) { var err error var databaseConfig models.DatabaseConfig connectionString, err := pgContainer.ConnectionString(ctx) if err != nil { return databaseConfig, err } connectionStringUrl, err := url.Parse(connectionString) if err != nil { return databaseConfig, err } split := strings.Split(connectionStringUrl.Host, ":") host := split[0] port, err := strconv.Atoi(split[1]) if err != nil { return databaseConfig, err } database := strings.TrimPrefix(connectionStringUrl.Path, "/") username := connectionStringUrl.User.Username() password, _ := connectionStringUrl.User.Password() databaseConfig = models.DatabaseConfig{ Endpoint: host, Username: username, Password: password, Database: database, Port: port, SSL: false, Timezone: "Europe/Berlin", Debug: true, } return databaseConfig, nil }