147 lines
3.7 KiB
Go
147 lines
3.7 KiB
Go
// Copyright IBM Corp. 2020, 2026
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package infra
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net/url"
|
|
"os/exec"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/ory/dockertest/v3"
|
|
"github.com/ory/dockertest/v3/docker"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type RedisContainerInfo struct {
|
|
Hostname string
|
|
Port string
|
|
Username string
|
|
Password string
|
|
}
|
|
|
|
type redisConfig struct {
|
|
User string
|
|
Password string
|
|
NetworkAlias string
|
|
}
|
|
|
|
// SetupRedisContainer starts a Redis container and returns its connection info
|
|
func SetupRedisContainer(t *testing.T) *RedisContainerInfo {
|
|
pool, err := dockertest.NewPool("")
|
|
require.NoError(t, err)
|
|
|
|
network, err := pool.NetworksByName("e2e_cluster")
|
|
require.NoError(t, err, "Failed to get e2e_cluster network")
|
|
|
|
c := startRedis(t, pool, &network[0], "redis", "latest")
|
|
require.NotNil(t, c, "Redis container should not be nil")
|
|
t.Cleanup(func() {
|
|
if err := pool.Purge(c.Resource); err != nil {
|
|
t.Logf("Failed to purge Redis container: %v", err)
|
|
}
|
|
})
|
|
|
|
u, err := url.Parse(c.UriNetwork)
|
|
t.Log(u)
|
|
require.NoError(t, err, "Failed to parse Redis URL")
|
|
|
|
user, hostname, port := u.User.Username(), u.Hostname(), u.Port()
|
|
pw, pwSet := u.User.Password()
|
|
|
|
t.Logf("Redis info: user=%s, host=%s, port=%s, password-set:%t",
|
|
user, hostname, port, pwSet)
|
|
|
|
return &RedisContainerInfo{
|
|
Hostname: hostname,
|
|
Port: port,
|
|
Username: user,
|
|
Password: pw,
|
|
}
|
|
}
|
|
|
|
// startRedis starts a Redis database in a docker container.
|
|
// Returns information about the container
|
|
func startRedis(t testing.TB, pool *dockertest.Pool, network *dockertest.Network, repository, tag string) *Container {
|
|
t.Log("Starting Redis database...")
|
|
c, err := LoadConfig()
|
|
require.NoError(t, err)
|
|
|
|
err = pool.Client.PullImage(docker.PullImageOptions{
|
|
Repository: fmt.Sprintf("%s/%s", c.DockerMirror, repository),
|
|
Tag: tag,
|
|
}, docker.AuthConfiguration{})
|
|
require.NoError(t, err)
|
|
|
|
config := redisConfig{
|
|
User: "e2eboundary",
|
|
Password: "e2eboundary",
|
|
NetworkAlias: "e2eredis",
|
|
}
|
|
|
|
resource, err := pool.RunWithOptions(&dockertest.RunOptions{
|
|
Repository: fmt.Sprintf("%s/%s", c.DockerMirror, repository),
|
|
Tag: tag,
|
|
ExposedPorts: []string{"6379/tcp"},
|
|
Name: config.NetworkAlias,
|
|
Networks: []*dockertest.Network{network},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
err = pool.Retry(func() error {
|
|
cmd := exec.Command("docker", "exec", config.NetworkAlias, "redis-cli", "PING")
|
|
output, cmdErr := cmd.CombinedOutput()
|
|
if cmdErr != nil {
|
|
return fmt.Errorf("failed to connect to Redis container '%s': %v\nOutput: %s", config.NetworkAlias, cmdErr, string(output))
|
|
}
|
|
return nil
|
|
})
|
|
require.NoError(t, err, "Redis container did not start in time or is not healthy")
|
|
|
|
// configure redis users
|
|
// e2e user
|
|
err = exec.Command(
|
|
"docker", "exec", config.NetworkAlias, "redis-cli",
|
|
"ACL", "SETUSER", config.User, "on", fmt.Sprintf(">%s", config.Password), "+@all", "allkeys",
|
|
).Run()
|
|
require.NoError(t, err)
|
|
|
|
// default user
|
|
err = exec.Command(
|
|
"docker", "exec", config.NetworkAlias, "redis-cli",
|
|
"ACL", "SETUSER", "default", fmt.Sprintf(">%s", config.Password),
|
|
).Run()
|
|
require.NoError(t, err)
|
|
|
|
return &Container{
|
|
Resource: resource,
|
|
UriLocalhost: fmt.Sprintf(
|
|
"redis://%s:%s@localhost:6379",
|
|
config.User,
|
|
config.Password,
|
|
),
|
|
UriNetwork: fmt.Sprintf(
|
|
"redis://%s:%s@%s:6379",
|
|
config.User,
|
|
config.Password,
|
|
config.NetworkAlias,
|
|
),
|
|
}
|
|
}
|
|
|
|
func SendRedisCommand(stdin io.WriteCloser, stdout io.ReadCloser, cmdStr string) (string, error) {
|
|
_, err := stdin.Write([]byte(cmdStr))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
buf := make([]byte, 1024)
|
|
n, err := stdout.Read(buf)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return strings.TrimSpace(string(buf[:n])), nil
|
|
}
|