diff --git a/integration/dockertestutil/config.go b/integration/dockertestutil/config.go new file mode 100644 index 00000000..2a5ac144 --- /dev/null +++ b/integration/dockertestutil/config.go @@ -0,0 +1,28 @@ +package dockertestutil + +import "github.com/ory/dockertest/v3/docker" + +func DockerRestartPolicy(config *docker.HostConfig) { + // set AutoRemove to true so that stopped container goes away by itself on error *immediately*. + // when set to false, containers remain until the end of the integration test. + config.AutoRemove = false + config.RestartPolicy = docker.RestartPolicy{ + Name: "no", + } +} + +func DockerAllowLocalIPv6(config *docker.HostConfig) { + if config.Sysctls == nil { + config.Sysctls = make(map[string]string, 1) + } + config.Sysctls["net.ipv6.conf.all.disable_ipv6"] = "0" +} + +func DockerAllowNetworkAdministration(config *docker.HostConfig) { + config.CapAdd = append(config.CapAdd, "NET_ADMIN") + config.Mounts = append(config.Mounts, docker.HostMount{ + Type: "bind", + Source: "/dev/net/tun", + Target: "/dev/net/tun", + }) +} diff --git a/integration/dockertestutil/execute.go b/integration/dockertestutil/execute.go new file mode 100644 index 00000000..71afa698 --- /dev/null +++ b/integration/dockertestutil/execute.go @@ -0,0 +1,94 @@ +package dockertestutil + +import ( + "bytes" + "errors" + "fmt" + "time" + + "github.com/ory/dockertest/v3" +) + +const dockerExecuteTimeout = time.Second * 10 + +var ( + ErrDockertestCommandFailed = errors.New("dockertest command failed") + ErrDockertestCommandTimeout = errors.New("dockertest command timed out") +) + +type ExecuteCommandConfig struct { + timeout time.Duration +} + +type ExecuteCommandOption func(*ExecuteCommandConfig) error + +func ExecuteCommandTimeout(timeout time.Duration) ExecuteCommandOption { + return ExecuteCommandOption(func(conf *ExecuteCommandConfig) error { + conf.timeout = timeout + + return nil + }) +} + +func ExecuteCommand( + resource *dockertest.Resource, + cmd []string, + env []string, + options ...ExecuteCommandOption, +) (string, string, error) { + var stdout bytes.Buffer + var stderr bytes.Buffer + + execConfig := ExecuteCommandConfig{ + timeout: dockerExecuteTimeout, + } + + for _, opt := range options { + if err := opt(&execConfig); err != nil { + return "", "", fmt.Errorf("execute-command/options: %w", err) + } + } + + type result struct { + exitCode int + err error + } + + resultChan := make(chan result, 1) + + // Run your long running function in it's own goroutine and pass back it's + // response into our channel. + go func() { + exitCode, err := resource.Exec( + cmd, + dockertest.ExecOptions{ + Env: append(env, "HEADSCALE_LOG_LEVEL=disabled"), + StdOut: &stdout, + StdErr: &stderr, + }, + ) + resultChan <- result{exitCode, err} + }() + + // Listen on our channel AND a timeout channel - which ever happens first. + select { + case res := <-resultChan: + if res.err != nil { + return stdout.String(), stderr.String(), res.err + } + + if res.exitCode != 0 { + // Uncomment for debugging + // log.Println("Command: ", cmd) + // log.Println("stdout: ", stdout.String()) + // log.Println("stderr: ", stderr.String()) + + return stdout.String(), stderr.String(), ErrDockertestCommandFailed + } + + return stdout.String(), stderr.String(), nil + case <-time.After(execConfig.timeout): + + return stdout.String(), stderr.String(), ErrDockertestCommandTimeout + } +} diff --git a/integration/dockertestutil/network.go b/integration/dockertestutil/network.go new file mode 100644 index 00000000..b4ff87cf --- /dev/null +++ b/integration/dockertestutil/network.go @@ -0,0 +1,21 @@ +package dockertestutil + +import "github.com/ory/dockertest/v3" + +func GetFirstOrCreateNetwork(pool *dockertest.Pool, name string) (*dockertest.Network, error) { + networks, err := pool.NetworksByName(name) + if err != nil || len(networks) == 0 { + if _, err := pool.CreateNetwork(name); err == nil { + // Create does not give us an updated version of the resource, so we need to + // get it again. + networks, err := pool.NetworksByName(name) + if err != nil { + return nil, err + } + + return &networks[0], nil + } + } + + return &networks[0], nil +}