Skip to content

Commit

Permalink
Use built-in KeepImage: true from go-testcontainers (#517)
Browse files Browse the repository at this point in the history
  • Loading branch information
turt2live authored Dec 1, 2023
1 parent 26ca001 commit 5753811
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 105 deletions.
3 changes: 0 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ WORKDIR /opt
RUN dos2unix ./build.sh ./docker/run.sh && chmod 744 ./build.sh
RUN ./build.sh

# the label is applied last so we don't pollute the image list with a weird amount of labelled images
LABEL io.t2bot.mmr.cleanup="true"

# ---- Stage 1 ----
# Final runtime stage.
FROM alpine
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ database:
Note that the postgresql image is *insecure* and not recommended for production use. It also does not follow best practices
for database management - use at your own risk.
**Note**: Running the Go tests requires Docker, and may pollute your cached images with tons of layers. It is suggested to
clean these images up manually from time to time, or rely on an ephemeral build system instead.
## Importing media from synapse
Media is imported by connecting to your synapse database and downloading all the content from the homeserver. This is so
Expand Down
1 change: 0 additions & 1 deletion test/test_internals/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ func (c *ContainerDeps) Teardown() {
if err := os.Remove(c.mmrExtConfigPath); err != nil && !os.IsNotExist(err) {
log.Fatalf("Error cleaning up MMR-External config file '%s': %s", c.mmrExtConfigPath, err.Error())
}
TeardownMmrCaches()
}

func (c *ContainerDeps) Debug() {
Expand Down
108 changes: 11 additions & 97 deletions test/test_internals/deps_mmr.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@ package test_internals

import (
"context"
"errors"
"fmt"
"io"
"log"
"os"
"path"
"strconv"
"strings"
"sync/atomic"
"text/template"

"github.com/docker/docker/api/types"
"github.com/docker/go-connections/nat"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
Expand All @@ -40,53 +37,6 @@ type mmrContainer struct {
MachineId int
}

var mmrCachedImage string
var mmrCachedContext *os.File
var mmrCachedSuites atomic.Int32

func MarkUsingCachedMmrBuild() {
mmrCachedSuites.Add(1)
log.Println("+1 cached build usage")
}

func reuseMmrBuild(ctx context.Context) (string, error) {
if mmrCachedImage != "" {
return mmrCachedImage, nil
}
log.Println("[Test Deps] Building MMR image...")
cr, err := createDockerContext()
if err != nil {
return "", err
}
mmrCachedContext = cr
buildReq := testcontainers.GenericContainerRequest{
ContainerRequest: testcontainers.ContainerRequest{
FromDockerfile: testcontainers.FromDockerfile{
Dockerfile: "Dockerfile",
Context: ".",
ContextArchive: cr,
PrintBuildLog: true,
},
},
Started: false,
}
provider, err := buildReq.ProviderType.GetProvider(testcontainers.WithLogger(testcontainers.Logger))
if err != nil {
return "", err
}
if dockerProvider, ok := provider.(*testcontainers.DockerProvider); !ok {
return "", errors.New("expected a docker provider")
} else {
tag, err := dockerProvider.BuildImage(ctx, &buildReq)
if err != nil {
return "", err
}
mmrCachedImage = tag
}
log.Println("[Test Deps] Cached build as ", mmrCachedImage)
return mmrCachedImage, nil
}

func writeMmrConfig(tmplArgs mmrTmplArgs) (string, error) {
// Prepare a config template
t, err := template.New("mmr.config.yaml").ParseFiles(path.Join(".", "test", "templates", "mmr.config.yaml"))
Expand Down Expand Up @@ -126,20 +76,24 @@ func makeMmrInstances(ctx context.Context, count int, depNet *NetworkDep, tmplAr
return nil, err
}

// Cache the MMR image
mmrImage, err := reuseMmrBuild(ctx)
if err != nil {
return nil, err
}

// Start the containers (using the same DB and config)
mmrs := make([]*mmrContainer, 0)
for i := 0; i < count; i++ {
// Create the docker container (from dockerfile)
cr, err := createDockerContext()
if err != nil {
return nil, err
}
p, _ := nat.NewPort("tcp", "8000")
container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: testcontainers.ContainerRequest{
Image: mmrImage,
FromDockerfile: testcontainers.FromDockerfile{
Dockerfile: "Dockerfile",
Context: ".",
ContextArchive: cr,
PrintBuildLog: true,
KeepImage: true,
},
ExposedPorts: []string{"8000/tcp"},
Mounts: []testcontainers.ContainerMount{
testcontainers.BindMount(intTmpName, "/data/media-repo.yaml"),
Expand Down Expand Up @@ -193,43 +147,3 @@ func (c *mmrContainer) Teardown() {
func (c *mmrContainer) Logs() (io.ReadCloser, error) {
return c.container.Logs(c.ctx)
}

func TeardownMmrCaches() {
mmrCachedSuites.Add(-1)
if mmrCachedSuites.Load() > 0 {
log.Println("Not cleaning up MMR cached images: image still in use")
return
}

if mmrCachedContext != nil {
_ = mmrCachedContext.Close() // ignore errors because testcontainers might have already closed it
if err := os.Remove(mmrCachedContext.Name()); err != nil && !os.IsNotExist(err) {
log.Fatalf("Error cleaning up MMR cached context file '%s': %s", mmrCachedContext.Name(), err.Error())
}
}
if mmrCachedImage != "" {
if p, err := (testcontainers.GenericContainerRequest{}.ProviderType.GetProvider()); err != nil {
log.Fatalf("Error cleaning up MMR cached build image '%s': %s", mmrCachedImage, err.Error())
} else if dockerProvider, ok := p.(*testcontainers.DockerProvider); !ok {
log.Fatalf("Error cleaning up MMR cached build image '%s': unable to cast provider to DockerProvider", mmrCachedImage)
} else {
rmImage := func(imageName string) {
if _, err = dockerProvider.Client().ImageRemove(context.Background(), imageName, types.ImageRemoveOptions{
PruneChildren: true,
}); err != nil {
log.Fatalf("Error removing MMR cached build image '%s': %s", imageName, err.Error())
}
}
if images, err := dockerProvider.Client().ImageList(context.Background(), types.ImageListOptions{All: true}); err != nil {
log.Fatalf("Error listing Docker images to clean up MMR image '%s': %s", mmrCachedImage, err.Error())
} else {
rmImage(mmrCachedImage)
for _, i := range images {
if i.Labels != nil && i.Labels["io.t2bot.mmr.cleanup"] == "true" {
rmImage(i.ID)
}
}
}
}
}
}
4 changes: 0 additions & 4 deletions test/upload_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ import (
"github.com/turt2live/matrix-media-repo/util"
)

func init() {
test_internals.MarkUsingCachedMmrBuild()
}

type UploadTestSuite struct {
suite.Suite
deps *test_internals.ContainerDeps
Expand Down

0 comments on commit 5753811

Please sign in to comment.