mirror of https://github.com/pressly/goose.git
104 lines
2.7 KiB
Go
104 lines
2.7 KiB
Go
package testdb
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"log"
|
|
"strconv"
|
|
"time"
|
|
|
|
_ "github.com/go-sql-driver/mysql"
|
|
"github.com/ory/dockertest/v3"
|
|
"github.com/ory/dockertest/v3/docker"
|
|
)
|
|
|
|
const (
|
|
// https://hub.docker.com/r/starrocks/allin1-ubuntu
|
|
STARROCKS_IMAGE = "starrocks/allin1-ubuntu"
|
|
STARROCKS_VERSION = "3.2-latest"
|
|
|
|
STARROCKS_USER = "root"
|
|
STARROCKS_INIT_DB = "migrations"
|
|
)
|
|
|
|
func newStarrocks(opts ...OptionsFunc) (*sql.DB, func(), error) {
|
|
option := &options{}
|
|
for _, f := range opts {
|
|
f(option)
|
|
}
|
|
// Uses a sensible default on windows (tcp/http) and linux/osx (socket).
|
|
pool, err := dockertest.NewPool("")
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to connect to docker: %v", err)
|
|
}
|
|
|
|
options := &dockertest.RunOptions{
|
|
Repository: STARROCKS_IMAGE,
|
|
Tag: STARROCKS_VERSION,
|
|
Labels: map[string]string{"goose_test": "1"},
|
|
PortBindings: make(map[docker.Port][]docker.PortBinding),
|
|
ExposedPorts: []string{"9030/tcp"},
|
|
}
|
|
if option.bindPort > 0 {
|
|
options.PortBindings[docker.Port("9030/tcp")] = []docker.PortBinding{
|
|
{HostPort: strconv.Itoa(option.bindPort)},
|
|
}
|
|
}
|
|
container, err := pool.RunWithOptions(
|
|
options,
|
|
func(config *docker.HostConfig) {
|
|
// Set AutoRemove to true so that stopped container goes away by itself.
|
|
config.AutoRemove = true
|
|
config.RestartPolicy = docker.RestartPolicy{Name: "no"}
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to create docker container: %v", err)
|
|
}
|
|
cleanup := func() {
|
|
if option.debug {
|
|
// User must manually delete the Docker container.
|
|
return
|
|
}
|
|
if err := pool.Purge(container); err != nil {
|
|
log.Printf("failed to purge resource: %v", err)
|
|
}
|
|
}
|
|
dsn := fmt.Sprintf("%s:%s@(%s:%s)/%s?parseTime=true&interpolateParams=true",
|
|
STARROCKS_USER,
|
|
"",
|
|
"localhost",
|
|
container.GetPort("9030/tcp"), // Fetch port dynamically assigned to container,
|
|
"",
|
|
)
|
|
var db *sql.DB
|
|
|
|
// Exponential backoff-retry, because the application in the container
|
|
// might not be ready to accept connections yet. Add an extra sleep
|
|
// because container take much longer to startup.
|
|
pool.MaxWait = time.Minute * 2
|
|
if err := pool.Retry(func() error {
|
|
var err error
|
|
db, err = sql.Open("mysql", dsn)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = db.Exec("CREATE DATABASE IF NOT EXISTS " + STARROCKS_INIT_DB)
|
|
if err != nil {
|
|
return fmt.Errorf("could not create initial database: %v", err)
|
|
}
|
|
_, err = db.Exec("USE " + STARROCKS_INIT_DB)
|
|
if err != nil {
|
|
return fmt.Errorf("could not set default initial database: %v", err)
|
|
}
|
|
|
|
return db.Ping()
|
|
},
|
|
); err != nil {
|
|
return nil, cleanup, fmt.Errorf("could not connect to docker database: %v", err)
|
|
}
|
|
|
|
return db, cleanup, nil
|
|
}
|