diff --git a/test/deps.go b/test/deps.go index 0904ee326020fe7ccce38cbc4bdf6e00b70e684b..611f1bb935a1ea1209ce5bf335da1e799003b8f7 100644 --- a/test/deps.go +++ b/test/deps.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log" + "os" "path" "time" @@ -18,17 +19,24 @@ type ContainerDeps struct { redisContainer testcontainers.Container homeservers []*SynapseDep machines []*mmrContainer + depNet *NetworkDep } func MakeTestDeps() (*ContainerDeps, error) { ctx := context.Background() + // Create a network + depNet, err := MakeNetwork() + if err != nil { + return nil, err + } + // Start two synapses for testing - syn1, err := MakeSynapse("first.example.org") + syn1, err := MakeSynapse("first.example.org", depNet) if err != nil { return nil, err } - syn2, err := MakeSynapse("second.example.org") + syn2, err := MakeSynapse("second.example.org", depNet) if err != nil { return nil, err } @@ -39,6 +47,7 @@ func MakeTestDeps() (*ContainerDeps, error) { postgres.WithDatabase("mmr"), postgres.WithUsername("postgres"), postgres.WithPassword("test1234"), + depNet.ApplyToContainer(), testcontainers.WithWaitStrategy( wait.ForLog("database system is ready to accept connections").WithOccurrence(2).WithStartupTimeout(5*time.Second)), ) @@ -51,31 +60,32 @@ func MakeTestDeps() (*ContainerDeps, error) { } // Start a redis container + cwd, err := os.Getwd() + if err != nil { + return nil, err + } redisContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ Image: "docker.io/library/redis:7", ExposedPorts: []string{"6379/tcp"}, Mounts: []testcontainers.ContainerMount{ - testcontainers.BindMount(path.Join(".", "dev", "redis.conf"), "/usr/local/etc/redis/redis.conf"), + testcontainers.BindMount(path.Join(cwd, ".", "dev", "redis.conf"), "/usr/local/etc/redis/redis.conf"), }, - Cmd: []string{"redis-server", "/usr/local/etc/redis/redis.conf"}, + Cmd: []string{"redis-server", "/usr/local/etc/redis/redis.conf"}, + Networks: []string{depNet.NetId}, }, Started: true, }) if err != nil { return nil, err } - redisHost, err := redisContainer.Host(ctx) - if err != nil { - return nil, err - } - redisPort, err := redisContainer.MappedPort(ctx, "6379/tcp") + redisHost, err := redisContainer.ContainerIP(ctx) if err != nil { return nil, err } // Start two MMRs for testing - mmrs, err := makeMmrInstances(ctx, 2, mmrTmplArgs{ + mmrs, err := makeMmrInstances(ctx, 2, depNet, mmrTmplArgs{ Homeservers: []mmrHomeserverTmplArgs{ { ServerName: syn1.ServerName, @@ -86,7 +96,7 @@ func MakeTestDeps() (*ContainerDeps, error) { ClientServerApiUrl: syn2.ClientServerApiUrl, }, }, - RedisAddr: fmt.Sprintf("%s:%d", redisHost, redisPort.Int()), + RedisAddr: fmt.Sprintf("%s:%d", redisHost, 6379), // we're behind the network for redis PgConnectionString: pgConnStr, }) @@ -96,6 +106,7 @@ func MakeTestDeps() (*ContainerDeps, error) { redisContainer: redisContainer, homeservers: []*SynapseDep{syn1, syn2}, machines: mmrs, + depNet: depNet, }, nil } @@ -112,4 +123,5 @@ func (c *ContainerDeps) Teardown() { if err := c.pgContainer.Terminate(c.ctx); err != nil { log.Fatalf("Error shutting down mmr-postgres container: %s", err.Error()) } + c.depNet.Teardown() } diff --git a/test/deps_mmr.go b/test/deps_mmr.go index 2d1e1ae830ac78fff5e0c182cb9ad04021f12edf..5e6a76148aa3749b0ce871d81430f4f46db9dba9 100644 --- a/test/deps_mmr.go +++ b/test/deps_mmr.go @@ -10,6 +10,7 @@ import ( "strings" "text/template" + "github.com/docker/go-connections/nat" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" ) @@ -34,7 +35,7 @@ type mmrContainer struct { MachineId int } -func makeMmrInstances(ctx context.Context, count int, tmplArgs mmrTmplArgs) ([]*mmrContainer, error) { +func makeMmrInstances(ctx context.Context, count int, depNet *NetworkDep, tmplArgs mmrTmplArgs) ([]*mmrContainer, error) { // Prepare a config template t, err := template.New("mmr.config.yaml").ParseFiles(path.Join(".", "test", "templates", "mmr.config.yaml")) if err != nil { @@ -64,6 +65,7 @@ func makeMmrInstances(ctx context.Context, count int, tmplArgs mmrTmplArgs) ([]* mmrs := make([]*mmrContainer, 0) for i := 0; i < count; i++ { // Create the docker container (from dockerfile) + p, _ := nat.NewPort("tcp", "8000") container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ FromDockerfile: testcontainers.FromDockerfile{ @@ -76,7 +78,8 @@ func makeMmrInstances(ctx context.Context, count int, tmplArgs mmrTmplArgs) ([]* Env: map[string]string{ "MACHINE_ID": strconv.Itoa(i), }, - WaitingFor: wait.ForHTTP("/healthz"), + Networks: []string{depNet.NetId}, + WaitingFor: wait.ForHTTP("/healthz").WithPort(p), }, Started: true, }) diff --git a/test/deps_network.go b/test/deps_network.go new file mode 100644 index 0000000000000000000000000000000000000000..b9495cf4c9ba19c2257e5af79741cbf93e84f270 --- /dev/null +++ b/test/deps_network.go @@ -0,0 +1,62 @@ +package test + +import ( + "context" + "log" + + "github.com/testcontainers/testcontainers-go" + "github.com/turt2live/matrix-media-repo/util/ids" +) + +type NetworkDep struct { + ctx context.Context + dockerNet testcontainers.Network + + NetId string +} + +type netCustomizer struct { + testcontainers.ContainerCustomizer + network *NetworkDep +} + +func (c *netCustomizer) Customize(req *testcontainers.GenericContainerRequest) { + if req.Networks == nil { + req.Networks = make([]string, 0) + } + req.Networks = append(req.Networks, c.network.NetId) +} + +func MakeNetwork() (*NetworkDep, error) { + ctx := context.Background() + + netId, err := ids.NewUniqueId() + if err != nil { + return nil, err + } + dockerNet, err := testcontainers.GenericNetwork(ctx, testcontainers.GenericNetworkRequest{ + NetworkRequest: testcontainers.NetworkRequest{ + Name: netId, + }, + ProviderType: testcontainers.ProviderDocker, + }) + if err != nil { + return nil, err + } + + return &NetworkDep{ + ctx: ctx, + dockerNet: dockerNet, + NetId: netId, + }, nil +} + +func (n *NetworkDep) ApplyToContainer() testcontainers.ContainerCustomizer { + return &netCustomizer{network: n} +} + +func (n *NetworkDep) Teardown() { + if err := n.dockerNet.Remove(n.ctx); err != nil { + log.Fatalf("Error cleaning up docker network '%s': %s", n.NetId, err.Error()) + } +} diff --git a/test/deps_synapse.go b/test/deps_synapse.go index 2035cf2c377369b2aa6b00cad7687e672678c4e3..9ef346056ba4f2b03fbed1a93807e9bf8c59efd3 100644 --- a/test/deps_synapse.go +++ b/test/deps_synapse.go @@ -32,7 +32,16 @@ type SynapseDep struct { ServerName string } -func MakeSynapse(domainName string) (*SynapseDep, error) { +type fixNetwork struct { + testcontainers.ContainerCustomizer + NetId string +} + +func (f *fixNetwork) Customize(req *testcontainers.GenericContainerRequest) { + req.Networks = []string{f.NetId} +} + +func MakeSynapse(domainName string, depNet *NetworkDep) (*SynapseDep, error) { ctx := context.Background() // Start postgresql database @@ -41,6 +50,8 @@ func MakeSynapse(domainName string) (*SynapseDep, error) { postgres.WithDatabase("synapse"), postgres.WithUsername("postgres"), postgres.WithPassword("test1234"), + WithEnvironment("POSTGRES_INITDB_ARGS", "--encoding=UTF8 --locale=C"), + depNet.ApplyToContainer(), testcontainers.WithWaitStrategy( wait.ForLog("database system is ready to accept connections").WithOccurrence(2).WithStartupTimeout(5*time.Second)), ) @@ -57,15 +68,11 @@ func MakeSynapse(domainName string) (*SynapseDep, error) { if err != nil { return nil, err } - pgport, err := pgContainer.MappedPort(ctx, "5432/tcp") - if err != nil { - return nil, err - } w := new(strings.Builder) err = t.Execute(w, synapseTmplArgs{ ServerName: domainName, PgHost: pghost, - PgPort: pgport.Int(), + PgPort: 5432, // we're behind the network here }) if err != nil { return nil, err @@ -105,6 +112,7 @@ func MakeSynapse(domainName string) (*SynapseDep, error) { testcontainers.BindMount(d, "/app"), }, WaitingFor: wait.ForHTTP("/health").WithPort(p), + Networks: []string{depNet.NetId}, }, Started: true, }) @@ -113,7 +121,7 @@ func MakeSynapse(domainName string) (*SynapseDep, error) { } // Prepare the CS API URL - synHost, err := synContainer.Host(ctx) + synHost, err := synContainer.ContainerIP(ctx) if err != nil { return nil, err } diff --git a/test/testcontainers_ext.go b/test/testcontainers_ext.go new file mode 100644 index 0000000000000000000000000000000000000000..3fccb7fa225a68c8d4d53f070c8204c68d1d175c --- /dev/null +++ b/test/testcontainers_ext.go @@ -0,0 +1,23 @@ +package test + +import "github.com/testcontainers/testcontainers-go" + +type EnvCustomizer struct { + testcontainers.ContainerCustomizer + varName string + varValue string +} + +func WithEnvironment(name string, value string) *EnvCustomizer { + return &EnvCustomizer{ + varName: name, + varValue: value, + } +} + +func (c *EnvCustomizer) Customize(req *testcontainers.GenericContainerRequest) { + if req.Env == nil { + req.Env = make(map[string]string) + } + req.Env[c.varName] = c.varValue +}