sq/magefile_sakila.go
2022-11-20 11:59:35 -07:00

162 lines
5.1 KiB
Go

//go:build mage
// This magefile contains targets for starting and stopping
// the Sakila test containers locally.
package main
import (
"context"
"fmt"
"sync"
"time"
"github.com/magefile/mage/mg"
"github.com/testcontainers/testcontainers-go/wait"
"golang.org/x/sync/errgroup"
"github.com/testcontainers/testcontainers-go"
)
// Sakila is the mage namespace for sakila targets.
type Sakila mg.Namespace
const startupTimeout = time.Minute * 5
// containerReqs is the set of database server containers required for
// integration testing.
//
// NOTE: The wait.ForLog mechanism is probably not fully correct for any of the
//
// containers (e.g. the string may appear multiple times in the log output),
// thus the containers may not have started fully when WaitingFor completes.
var containerReqs = []testcontainers.ContainerRequest{
{
Image: "sakiladb/sqlserver:2017",
Name: "sakiladb-sqlserver-2017",
ExposedPorts: []string{"14337:1433"},
WaitingFor: wait.ForLog("Changed database context to 'sakila'.").WithStartupTimeout(startupTimeout),
},
// {
// Image: "sakiladb/postgres:9",
// Name: "sakiladb-postgres-9",
// ExposedPorts: []string{"54329:5432"},
// WaitingFor: wait.ForLog("PostgreSQL init process complete; ready for start up.").WithStartupTimeout(startupTimeout),
// },
// {
// Image: "sakiladb/postgres:10",
// Name: "sakiladb-postgres-10",
// ExposedPorts: []string{"54330:5432"},
// WaitingFor: wait.ForLog("PostgreSQL init process complete; ready for start up.").WithStartupTimeout(startupTimeout),
// },
// {
// Image: "sakiladb/postgres:11",
// Name: "sakiladb-postgres-11",
// ExposedPorts: []string{"54331:5432"},
// WaitingFor: wait.ForLog("PostgreSQL init process complete; ready for start up.").WithStartupTimeout(startupTimeout),
// },
// {
// Image: "sakiladb/postgres:12",
// Name: "sakiladb-postgres-12",
// ExposedPorts: []string{"54332:5432"},
// WaitingFor: wait.ForLog("PostgreSQL init process complete; ready for start up.").WithStartupTimeout(startupTimeout),
// },
// {
// Image: "sakiladb/mysql:5.6",
// Name: "sakiladb-mysql-5.6",
// ExposedPorts: []string{"33066:3306"},
// WaitingFor: wait.ForLog("[Note] mysqld: ready for connections.").WithStartupTimeout(startupTimeout),
// },
// {
// Image: "sakiladb/mysql:5.7",
// Name: "sakiladb-mysql-5.7",
// ExposedPorts: []string{"33067:3306"},
// WaitingFor: wait.ForLog("[Note] mysqld: ready for connections.").WithStartupTimeout(startupTimeout),
// },
// {
// Image: "sakiladb/mysql:8",
// Name: "sakiladb-mysql-8",
// ExposedPorts: []string{"33068:3306"},
// WaitingFor: wait.ForLog("[Server] /usr/sbin/mysqld: ready for connections.").WithStartupTimeout(startupTimeout),
// },
}
var startedContainers []testcontainers.Container
var startedContainersMu sync.Mutex
func containerStarted(cont testcontainers.Container) {
startedContainersMu.Lock()
defer startedContainersMu.Unlock()
startedContainers = append(startedContainers, cont)
}
// StartAll starts all the sakila database server containers locally.
// Use RemoveAll to stop & remove the containers.
func (Sakila) StartAll(ctx context.Context) error {
const envarInfo = `export SQ_TEST_SRC__SAKILA_MY56=localhost:33066
export SQ_TEST_SRC__SAKILA_MY57=localhost:33067
export SQ_TEST_SRC__SAKILA_MY8=localhost:33068
export SQ_TEST_SRC__SAKILA_PG9=localhost:54329
export SQ_TEST_SRC__SAKILA_PG10=localhost:54330
export SQ_TEST_SRC__SAKILA_PG11=localhost:54331
export SQ_TEST_SRC__SAKILA_PG12=localhost:54332
export SQ_TEST_SRC__SAKILA_MS17=localhost:14337`
fmt.Println("Starting all containers...")
fmt.Printf("'src' the following:\n===\n%s\n===\n\n", envarInfo)
errGroup, ctx := errgroup.WithContext(ctx)
for _, containerReq := range containerReqs {
containerReq := containerReq
// The user invokes mage sakila:RemoveAll to remove all the containers.
containerReq.SkipReaper = true
errGroup.Go(func() error {
fmt.Printf("Starting container %s for %s\n", containerReq.Name, containerReq.Image)
gotContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: containerReq,
Started: true,
})
if err != nil {
return fmt.Errorf("image %s: %w", containerReq.Image, err)
}
containerStarted(gotContainer)
fmt.Printf("SUCCESS: started container %s for %s\n", containerReq.Name, containerReq.Image)
return nil
})
}
err := errGroup.Wait()
if err != nil {
fmt.Println("ERROR: problem reported trying to start all containers (some or all containers may actually have started)")
return err
}
fmt.Println("SUCCESS: All database containers started")
return nil
}
// RemoveAll removes all the Sakila docker containers.
func (Sakila) RemoveAll(ctx context.Context) {
wg := &sync.WaitGroup{}
wg.Add(len(containerReqs))
for _, containerReq := range containerReqs {
containerReq := containerReq
go func() {
defer wg.Done()
// We don't care if there's an error
_ = execDocker("rm", "-f", containerReq.Name)
}()
}
wg.Wait()
}