Files
query-orchestration/internal/test/container.go
T
Michael McGuinness 721ca8a6e6 Merged in feature/dockerfileintest (pull request #130)
Dockerfile in Test

* dockerfile

* network

* const
2025-05-03 11:29:10 +00:00

166 lines
4.2 KiB
Go

package test
import (
"bufio"
"context"
"fmt"
"log/slog"
"os"
"path/filepath"
"strconv"
"sync"
"testing"
"queryorchestration/internal/serviceconfig"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/archive"
"github.com/docker/go-connections/nat"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)
type Container struct {
Container testcontainers.Container
URI string
}
type containerConfig struct {
Name string
Cfg serviceconfig.ConfigProvider
DownstreamQueues []RunnerName
Env map[string]string
WaitForMsg string
ExposedPorts []nat.Port
MockHTTP string
}
const (
imageTag = "queryorchestration:latest"
)
var (
imageBuild sync.Once
)
func buildImage(t testing.TB, ctx context.Context) {
imageBuild.Do(func() {
dockerContextPath, err := os.Getwd()
require.NoError(t, err, "Failed to get current directory")
dockerfilePath := "build/Dockerfile"
for {
candidatePath := filepath.Join(dockerContextPath, dockerfilePath)
t.Logf("Checking for Dockerfile at: %s", dockerContextPath)
_, err := os.Stat(candidatePath)
if err == nil {
break
}
dockerContextPath = filepath.Join(dockerContextPath, "..")
}
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
require.NoError(t, err)
buildContext, err := archive.TarWithOptions(dockerContextPath, &archive.TarOptions{})
require.NoError(t, err)
defer buildContext.Close()
_, err = cli.ImageBuild(ctx, buildContext, types.ImageBuildOptions{
Dockerfile: dockerfilePath,
Tags: []string{imageTag},
})
require.NoError(t, err)
})
}
func createContainer(t testing.TB, ctx context.Context, network string, cfg *containerConfig) (testcontainers.Container, func()) {
env := map[string]string{
"PGUSER": cfg.Cfg.GetDBUser(),
"PGPASSWORD": cfg.Cfg.GetDBSecret(),
"PGHOST": dbAlias,
"PGDATABASE": cfg.Cfg.GetDBName(),
"PGPORT": strconv.Itoa(dbPort),
"DB_NOSSL": strconv.FormatBool(cfg.Cfg.IsDBNoSSL()),
"AWS_ACCESS_KEY_ID": cfg.Cfg.GetAWSKeyID(),
"AWS_SECRET_ACCESS_KEY": cfg.Cfg.GetAWSSecretKey(),
"AWS_REGION": cfg.Cfg.GetAWSRegion(),
"AWS_DEFAULT_REGION": cfg.Cfg.GetAWSRegion(),
"AWS_ENDPOINT_URL": cfg.Cfg.GetAWSEndpoint(),
"AWS_ENDPOINT_URL_SQS": cfg.Cfg.GetAWSEndpoint(),
"AWS_ENDPOINT_URL_S3": cfg.Cfg.GetAWSEndpoint(),
"AWS_ENDPOINT_URL_TEXTRACT": cfg.MockHTTP,
"AWS_S3_USE_PATH_STYLE": strconv.FormatBool(true),
"DISABLE_AUTH": "true",
"LOG_LEVEL": "DEBUG",
"COGNITO_USER_POOL_ID": "coguserpoolid",
"COGNITO_CLIENT_SECRET": "cogsecret",
"COGNITO_DOMAIN": "cogdomain",
"COGNITO_CLIENT_ID": "clientid",
}
if cfg.Env != nil {
for k, v := range cfg.Env {
env[k] = v
}
}
for _, e := range cfg.DownstreamQueues {
env[string(GetRunnerEnvFromName(e))] = GetQueueURL(t, cfg.Cfg, e)
}
buildImage(t, ctx)
req := testcontainers.ContainerRequest{
Image: imageTag,
Env: env,
WaitingFor: wait.ForLog(cfg.WaitForMsg),
Entrypoint: []string{fmt.Sprintf("./%s", cfg.Name)},
Networks: []string{network},
}
if len(cfg.ExposedPorts) > 0 {
ports := make([]string, len(cfg.ExposedPorts))
for index, port := range cfg.ExposedPorts {
ports[index] = port.Port()
}
req.ExposedPorts = ports
}
container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
})
if err != nil {
PrintContainerLogs(t, ctx, container)
require.NoError(t, err)
}
return container, func() {
err := container.Terminate(ctx)
if err != nil {
t.Error(err)
}
}
}
func PrintContainerLogs(t testing.TB, ctx context.Context, container testcontainers.Container) {
logs, err := container.Logs(ctx)
defer func() {
err := logs.Close()
require.NoError(t, err)
}()
require.NoError(t, err)
scanner := bufio.NewScanner(logs)
for scanner.Scan() {
line := scanner.Text()
slog.Info(line)
}
}