From f6ddc75c7332556f5f153709b3a1b0eac3027ac7 Mon Sep 17 00:00:00 2001 From: DPR Date: Thu, 17 Dec 2020 18:51:06 +0330 Subject: [PATCH 001/219] [ADD]: get container's running state --- container.go | 2 ++ docker.go | 19 +++++++++++++++++++ go.sum | 3 +-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/container.go b/container.go index c4cfc0ab2e..2dd26d5086 100644 --- a/container.go +++ b/container.go @@ -4,6 +4,7 @@ import ( "context" "io" + "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/pkg/archive" @@ -45,6 +46,7 @@ type Container interface { StartLogProducer(context.Context) error StopLogProducer() error Name(context.Context) (string, error) // get container name + State(context.Context) (*types.ContainerState, error) //returns container's running state Networks(context.Context) ([]string, error) // get container networks NetworkAliases(context.Context) (map[string][]string, error) // get container network aliases for a network Exec(ctx context.Context, cmd []string) (int, error) diff --git a/docker.go b/docker.go index acbc65f78d..6eb1668e16 100644 --- a/docker.go +++ b/docker.go @@ -188,6 +188,16 @@ func (c *DockerContainer) Terminate(ctx context.Context) error { return err } +// update container raw info +func (c *DockerContainer) inspectContainerFresh(ctx context.Context) (*types.ContainerJSON, error) { + inspect, err := c.provider.client.ContainerInspect(ctx, c.ID) + if err != nil { + return nil, err + } + c.raw = &inspect + return c.raw, nil +} + func (c *DockerContainer) inspectContainer(ctx context.Context) (*types.ContainerJSON, error) { if c.raw != nil { return c.raw, nil @@ -232,6 +242,15 @@ func (c *DockerContainer) Name(ctx context.Context) (string, error) { return inspect.Name, nil } +// State returns container's running state +func (c *DockerContainer) State(ctx context.Context) (*types.ContainerState, error) { + inspect, err := c.inspectContainerFresh(ctx) + if err != nil { + return nil, err + } + return inspect.State, nil +} + // Networks gets the names of the networks the container is attached to. func (c *DockerContainer) Networks(ctx context.Context) ([]string, error) { inspect, err := c.inspectContainer(ctx) diff --git a/go.sum b/go.sum index aa7528c940..552fc92593 100644 --- a/go.sum +++ b/go.sum @@ -123,8 +123,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 2ed397ff1a9c37d2110862a24a1057040c86f16e Mon Sep 17 00:00:00 2001 From: DPR Date: Fri, 18 Dec 2020 23:29:00 +0330 Subject: [PATCH 002/219] [NEW]: waitForExit --- docker.go | 2 +- wait/exit.go | 84 +++++++++++++++++++++++++++++++++++++++++++++++ wait/exit_test.go | 47 ++++++++++++++++++++++++++ wait/log_test.go | 4 +++ wait/wait.go | 2 ++ 5 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 wait/exit.go create mode 100644 wait/exit_test.go diff --git a/docker.go b/docker.go index 6eb1668e16..81fac6e35b 100644 --- a/docker.go +++ b/docker.go @@ -246,7 +246,7 @@ func (c *DockerContainer) Name(ctx context.Context) (string, error) { func (c *DockerContainer) State(ctx context.Context) (*types.ContainerState, error) { inspect, err := c.inspectContainerFresh(ctx) if err != nil { - return nil, err + return c.raw.State, err } return inspect.State, nil } diff --git a/wait/exit.go b/wait/exit.go new file mode 100644 index 0000000000..eace6702ac --- /dev/null +++ b/wait/exit.go @@ -0,0 +1,84 @@ +package wait + +import ( + "context" + "strings" + "time" +) + +// Implement interface +var _ Strategy = (*ExitStrategy)(nil) + +// ExitStrategy will wait until container exit +type ExitStrategy struct { + // all Strategies should have a timeout to avoid waiting infinitely + exitTimeout time.Duration + + // additional properties + PollInterval time.Duration +} + +//NewExitStrategy constructs with polling interval of 100 milliseconds without timeout by default +func NewExitStrategy() *ExitStrategy { + return &ExitStrategy{ + PollInterval: defaultPollInterval(), + } + +} + +// fluent builders for each property +// since go has neither covariance nor generics, the return type must be the type of the concrete implementation +// this is true for all properties, even the "shared" ones + +// WithExitTimeout can be used to change the default exit timeout +func (ws *ExitStrategy) WithExitTimeout(exitTimeout time.Duration) *ExitStrategy { + ws.exitTimeout = exitTimeout + return ws +} + +// WithPollInterval can be used to override the default polling interval of 100 milliseconds +func (ws *ExitStrategy) WithPollInterval(pollInterval time.Duration) *ExitStrategy { + ws.PollInterval = pollInterval + return ws +} + +// ForExit is the default construction for the fluid interface. +// +// For Example: +// wait. +// ForExit(). +// WithPollInterval(1 * time.Second) +func ForExit() *ExitStrategy { + return NewExitStrategy() +} + +// WaitUntilReady implements Strategy.WaitUntilReady +func (ws *ExitStrategy) WaitUntilReady(ctx context.Context, target StrategyTarget) (err error) { + // limit context to exitTimeout + if ws.exitTimeout > 0 { + var cancelContext context.CancelFunc + ctx, cancelContext = context.WithTimeout(ctx, ws.exitTimeout) + defer cancelContext() + } + + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + state, err := target.State(ctx) + if err != nil { + if !strings.Contains(err.Error(), "No such container") { + return err + } else { + return nil + } + } + if state.Running { + time.Sleep(ws.PollInterval) + continue + } + return nil + } + } +} diff --git a/wait/exit_test.go b/wait/exit_test.go new file mode 100644 index 0000000000..cbfa4a6913 --- /dev/null +++ b/wait/exit_test.go @@ -0,0 +1,47 @@ +package wait + +import ( + "context" + "io" + "testing" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/go-connections/nat" +) + +type exitStrategyTarget struct { + isRunning bool + err error +} + +func (st exitStrategyTarget) Host(ctx context.Context) (string, error) { + return "", nil +} + +func (st exitStrategyTarget) MappedPort(ctx context.Context, n nat.Port) (nat.Port, error) { + return n, nil +} + +func (st exitStrategyTarget) Logs(ctx context.Context) (io.ReadCloser, error) { + return nil, nil +} + +func (st exitStrategyTarget) Exec(ctx context.Context, cmd []string) (int, error) { + return 0, nil +} + +func (st exitStrategyTarget) State(ctx context.Context) (*types.ContainerState, error) { + return &types.ContainerState{Running: st.isRunning}, nil +} + +func TestWaitForExit(t *testing.T) { + target := exitStrategyTarget{ + isRunning: false, + } + wg := NewExitStrategy().WithExitTimeout(100 * time.Millisecond) + err := wg.WaitUntilReady(context.Background(), target) + if err != nil { + t.Fatal(err) + } +} diff --git a/wait/log_test.go b/wait/log_test.go index f6c2ac9d88..f15d18d61c 100644 --- a/wait/log_test.go +++ b/wait/log_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/docker/docker/api/types" "github.com/docker/go-connections/nat" ) @@ -30,6 +31,9 @@ func (st noopStrategyTarget) Logs(ctx context.Context) (io.ReadCloser, error) { func (st noopStrategyTarget) Exec(ctx context.Context, cmd []string) (int, error) { return 0, nil } +func (st noopStrategyTarget) State(ctx context.Context) (*types.ContainerState, error) { + return nil, nil +} func TestWaitForLog(t *testing.T) { target := noopStrategyTarget{ diff --git a/wait/wait.go b/wait/wait.go index 9439edeae6..5fcc284ccc 100644 --- a/wait/wait.go +++ b/wait/wait.go @@ -5,6 +5,7 @@ import ( "io" "time" + "github.com/docker/docker/api/types" "github.com/docker/go-connections/nat" ) @@ -17,6 +18,7 @@ type StrategyTarget interface { MappedPort(context.Context, nat.Port) (nat.Port, error) Logs(context.Context) (io.ReadCloser, error) Exec(ctx context.Context, cmd []string) (int, error) + State(context.Context) (*types.ContainerState, error) } func defaultStartupTimeout() time.Duration { From 082e2de46eedb8b8500b3d5447d7b52403cbed5d Mon Sep 17 00:00:00 2001 From: DPR Date: Fri, 18 Dec 2020 23:29:20 +0330 Subject: [PATCH 003/219] [ADD]: wait for health check --- wait/healt.go | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 wait/healt.go diff --git a/wait/healt.go b/wait/healt.go new file mode 100644 index 0000000000..73885c2e81 --- /dev/null +++ b/wait/healt.go @@ -0,0 +1,77 @@ +package wait + +import ( + "context" + "time" +) + +// Implement interface +var _ Strategy = (*HealthStrategy)(nil) + +// HealthStrategy will wait until the container becomes healthy +type HealthStrategy struct { + // all Strategies should have a startupTimeout to avoid waiting infinitely + startupTimeout time.Duration + + // additional properties + PollInterval time.Duration +} + +// NewHealthStrategy constructs with polling interval of 100 milliseconds and startup timeout of 60 seconds by default +func NewHealthStrategy() *HealthStrategy { + return &HealthStrategy{ + startupTimeout: defaultStartupTimeout(), + PollInterval: defaultPollInterval(), + } + +} + +// fluent builders for each property +// since go has neither covariance nor generics, the return type must be the type of the concrete implementation +// this is true for all properties, even the "shared" ones like startupTimeout + +// WithStartupTimeout can be used to change the default startup timeout +func (ws *HealthStrategy) WithStartupTimeout(startupTimeout time.Duration) *HealthStrategy { + ws.startupTimeout = startupTimeout + return ws +} + +// WithPollInterval can be used to override the default polling interval of 100 milliseconds +func (ws *HealthStrategy) WithPollInterval(pollInterval time.Duration) *HealthStrategy { + ws.PollInterval = pollInterval + return ws +} + +// ForHealthCheck is the default construction for the fluid interface. +// +// For Example: +// wait. +// ForHealthCheck(). +// WithPollInterval(1 * time.Second) +func ForHealthCheck() *HealthStrategy { + return NewHealthStrategy() +} + +// WaitUntilReady implements Strategy.WaitUntilReady +func (ws *HealthStrategy) WaitUntilReady(ctx context.Context, target StrategyTarget) (err error) { + // limit context to exitTimeout + ctx, cancelContext := context.WithTimeout(ctx, ws.startupTimeout) + defer cancelContext() + + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + state, err := target.State(ctx) + if err != nil { + return err + } + if state.Health.Status != "healthy" { + time.Sleep(ws.PollInterval) + continue + } + return nil + } + } +} From 0324b32b764e06c57fb7d3db9c12e830e5df2af2 Mon Sep 17 00:00:00 2001 From: DPR Date: Wed, 23 Dec 2020 11:05:48 +0330 Subject: [PATCH 004/219] [FIX]: typo health --- wait/{healt.go => health.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename wait/{healt.go => health.go} (100%) diff --git a/wait/healt.go b/wait/health.go similarity index 100% rename from wait/healt.go rename to wait/health.go From bf040d13d1f87f252e8a415965bf2b0be1d9fc67 Mon Sep 17 00:00:00 2001 From: shashank Date: Mon, 2 Nov 2020 11:02:13 -0500 Subject: [PATCH 005/219] Framework for starting wait strategy on Compose Files --- compose.go | 72 ++++++++++++++++++++++++++++++++++++++++++++----- compose_test.go | 44 ++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 7 deletions(-) diff --git a/compose.go b/compose.go index d849e159e1..15d3a5fe70 100644 --- a/compose.go +++ b/compose.go @@ -2,6 +2,7 @@ package testcontainers import ( "bytes" + "context" "fmt" "io" "io/ioutil" @@ -12,6 +13,8 @@ import ( "strings" "sync" + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" "gopkg.in/yaml.v2" ) @@ -26,18 +29,21 @@ type DockerCompose interface { Invoke() ExecError WithCommand([]string) DockerCompose WithEnv(map[string]string) DockerCompose + WithExposedService(map[string]interface{}) DockerCompose } // LocalDockerCompose represents a Docker Compose execution using local binary // docker-compose or docker-compose.exe, depending on the underlying platform type LocalDockerCompose struct { - Executable string - ComposeFilePaths []string - absComposeFilePaths []string - Identifier string - Cmd []string - Env map[string]string - Services map[string]interface{} + Executable string + ComposeFilePaths []string + absComposeFilePaths []string + Identifier string + Cmd []string + Env map[string]string + Services map[string]interface{} + WaitStrategySupplied bool + WaitStrategyMap map[string]interface{} } // NewLocalDockerCompose returns an instance of the local Docker Compose, using an @@ -66,6 +72,8 @@ func NewLocalDockerCompose(filePaths []string, identifier string) *LocalDockerCo dc.validate() dc.Identifier = strings.ToLower(identifier) + dc.WaitStrategySupplied = false + dc.WaitStrategyMap = make(map[string]interface{}) return dc } @@ -89,8 +97,44 @@ func (dc *LocalDockerCompose) getDockerComposeEnvironment() map[string]string { return environment } +func (dc *LocalDockerCompose) applyStrategyToRunningContainer() { + cli, err := client.NewClientWithOpts(client.FromEnv) + if err != nil { + panic(err) + } + + containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{}) + if err != nil { + panic(err) + } + + // Docker compose appends "_1" to every started service by default. Printing the services to verify that the right services have a wait strategy + keys := make([]string, 0, len(dc.WaitStrategyMap)) + for k := range dc.WaitStrategyMap { + keys = append(keys, strings.TrimSuffix(k, "_1")) + } + fmt.Printf("List of Containers with Wait Strategy supplied: %v\n ", keys) + + // Iterate over all the wait strategies supplied, and apply them one by one + for _, container := range containers { + for _, key := range keys { + if strings.Contains(container.Image, key) { + fmt.Printf("Running containers to apply wait strategy: %v\n", container.Image) + // Retrieve the strategy for each container + // strategy := dc.WaitStrategyMap[key+"_1"] + // strategy.waitUntilReady(context.Background(), waitStrategyTarget) - This is where I'm slightly confused + // Do I need a new target like https://github.com/testcontainers/testcontainers-go/blob/master/wait/http_test.go#L70 or https://github.com/testcontainers/testcontainers-go/blob/master/wait/sql.go#L45 + } + } + } +} + // Invoke invokes the docker compose func (dc *LocalDockerCompose) Invoke() ExecError { + if dc.WaitStrategySupplied { + fmt.Println("Wait Strategy(ies) supplied") + return executeCompose(dc, dc.Cmd) + } return executeCompose(dc, dc.Cmd) } @@ -106,6 +150,16 @@ func (dc *LocalDockerCompose) WithEnv(env map[string]string) DockerCompose { return dc } +// WithExposedService sets the strategy for the service that is to be waited on. If multiple strategies +// are given for a single service, the latest one will be applied +func (dc *LocalDockerCompose) WithExposedService(waitstrategymap map[string]interface{}) DockerCompose { + dc.WaitStrategySupplied = true + for k, v := range waitstrategymap { + dc.WaitStrategyMap[k] = v + } + return dc +} + // validate checks if the files to be run in the compose are valid YAML files, setting up // references to all services in them func (dc *LocalDockerCompose) validate() error { @@ -234,6 +288,10 @@ func executeCompose(dc *LocalDockerCompose, args []string) ExecError { } } + if dc.WaitStrategySupplied { + dc.applyStrategyToRunningContainer() + } + return execErr } diff --git a/compose_test.go b/compose_test.go index 45fb2d2174..1796915ae9 100644 --- a/compose_test.go +++ b/compose_test.go @@ -5,9 +5,11 @@ import ( "os/exec" "strings" "testing" + "time" "github.com/google/uuid" "github.com/stretchr/testify/assert" + "github.com/testcontainers/testcontainers-go/wait" ) const containerNameNginx = "nginx-simple" @@ -107,6 +109,48 @@ func TestLocalDockerCompose(t *testing.T) { checkIfError(t, err) } +func TestDockerComposeWithWaitStrategy(t *testing.T) { + path := "./testresources/docker-compose-complex.yml" + + identifier := strings.ToLower(uuid.New().String()) + + compose := NewLocalDockerCompose([]string{path}, identifier) + destroyFn := func() { + err := compose.Down() + checkIfError(t, err) + } + defer destroyFn() + + err := compose. + WithCommand([]string{"up", "-d"}). + WithExposedService(map[string]interface{}{"mysql_1": wait.NewLogStrategy("started").WithStartupTimeout(100 * time.Microsecond)}). + Invoke() + checkIfError(t, err) +} + +func TestDockerComposeWithMultipleWaitStrategies(t *testing.T) { + path := "./testresources/docker-compose-complex.yml" + + identifier := strings.ToLower(uuid.New().String()) + + compose := NewLocalDockerCompose([]string{path}, identifier) + destroyFn := func() { + err := compose.Down() + checkIfError(t, err) + } + defer destroyFn() + + err := compose. + WithCommand([]string{"up", "-d"}). + WithExposedService(map[string]interface{}{"mysql_1": wait.NewLogStrategy("started").WithStartupTimeout(100 * time.Microsecond)}). + WithExposedService(map[string]interface{}{"nginx_1": wait.ForHTTP("/").WithPort("9080/tcp")}). + Invoke() + checkIfError(t, err) +} + +// Add negative test case with Dockerfile that never starts up and a timeout period of 10-20 seconds +// Add test case for multiple wait strategies + func TestLocalDockerComposeComplex(t *testing.T) { path := "./testresources/docker-compose-complex.yml" From 437bfd25f7934270c72c437d67f7dbac17df4166 Mon Sep 17 00:00:00 2001 From: shashank Date: Wed, 4 Nov 2020 14:47:19 -0500 Subject: [PATCH 006/219] Working strategy for Log using compose --- compose.go | 30 ++++++++++++++++++++---------- compose_test.go | 27 +++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/compose.go b/compose.go index 15d3a5fe70..3dbc2eecdf 100644 --- a/compose.go +++ b/compose.go @@ -15,6 +15,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/client" + "github.com/testcontainers/testcontainers-go/wait" "gopkg.in/yaml.v2" ) @@ -29,7 +30,7 @@ type DockerCompose interface { Invoke() ExecError WithCommand([]string) DockerCompose WithEnv(map[string]string) DockerCompose - WithExposedService(map[string]interface{}) DockerCompose + WithExposedService(string, wait.Strategy) DockerCompose } // LocalDockerCompose represents a Docker Compose execution using local binary @@ -43,7 +44,7 @@ type LocalDockerCompose struct { Env map[string]string Services map[string]interface{} WaitStrategySupplied bool - WaitStrategyMap map[string]interface{} + WaitStrategyMap map[string]wait.Strategy } // NewLocalDockerCompose returns an instance of the local Docker Compose, using an @@ -73,7 +74,7 @@ func NewLocalDockerCompose(filePaths []string, identifier string) *LocalDockerCo dc.Identifier = strings.ToLower(identifier) dc.WaitStrategySupplied = false - dc.WaitStrategyMap = make(map[string]interface{}) + dc.WaitStrategyMap = make(map[string]wait.Strategy) return dc } @@ -103,6 +104,8 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() { panic(err) } + failedStrategies := make(map[string]wait.Strategy) + containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{}) if err != nil { panic(err) @@ -121,12 +124,21 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() { if strings.Contains(container.Image, key) { fmt.Printf("Running containers to apply wait strategy: %v\n", container.Image) // Retrieve the strategy for each container - // strategy := dc.WaitStrategyMap[key+"_1"] - // strategy.waitUntilReady(context.Background(), waitStrategyTarget) - This is where I'm slightly confused - // Do I need a new target like https://github.com/testcontainers/testcontainers-go/blob/master/wait/http_test.go#L70 or https://github.com/testcontainers/testcontainers-go/blob/master/wait/sql.go#L45 + strategy := dc.WaitStrategyMap[key+"_1"] + fmt.Printf("Strategy (%+v) to be applied to container: %v\n", strategy, key) + dockerProvider, _ := NewDockerProvider() + dockercontainer := &DockerContainer{ID: container.ID, WaitingFor: strategy, provider: dockerProvider} + err := strategy.WaitUntilReady(context.Background(), dockercontainer) + if err != nil { + failedStrategies[key] = strategy + fmt.Printf("Error trace: %s\n", err) + } } } } + if len(failedStrategies) > 0 { + fmt.Printf("List of wait strategies that were unsuccessful: (%v)", failedStrategies) + } } // Invoke invokes the docker compose @@ -152,11 +164,9 @@ func (dc *LocalDockerCompose) WithEnv(env map[string]string) DockerCompose { // WithExposedService sets the strategy for the service that is to be waited on. If multiple strategies // are given for a single service, the latest one will be applied -func (dc *LocalDockerCompose) WithExposedService(waitstrategymap map[string]interface{}) DockerCompose { +func (dc *LocalDockerCompose) WithExposedService(service string, strategy wait.Strategy) DockerCompose { dc.WaitStrategySupplied = true - for k, v := range waitstrategymap { - dc.WaitStrategyMap[k] = v - } + dc.WaitStrategyMap[service] = strategy return dc } diff --git a/compose_test.go b/compose_test.go index 1796915ae9..b1da3bcc65 100644 --- a/compose_test.go +++ b/compose_test.go @@ -109,7 +109,7 @@ func TestLocalDockerCompose(t *testing.T) { checkIfError(t, err) } -func TestDockerComposeWithWaitStrategy(t *testing.T) { +func TestDockerComposeWithWaitLogStrategy(t *testing.T) { path := "./testresources/docker-compose-complex.yml" identifier := strings.ToLower(uuid.New().String()) @@ -123,7 +123,26 @@ func TestDockerComposeWithWaitStrategy(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). - WithExposedService(map[string]interface{}{"mysql_1": wait.NewLogStrategy("started").WithStartupTimeout(100 * time.Microsecond)}). + WithExposedService("mysql_1", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). + Invoke() + checkIfError(t, err) +} + +func TestDockerComposeWithWaitHTTPStrategy(t *testing.T) { + path := "./testresources/docker-compose-complex.yml" + + identifier := strings.ToLower(uuid.New().String()) + + compose := NewLocalDockerCompose([]string{path}, identifier) + destroyFn := func() { + err := compose.Down() + checkIfError(t, err) + } + defer destroyFn() + + err := compose. + WithCommand([]string{"up", "-d"}). + WithExposedService("nginx_1", wait.NewHTTPStrategy("/").WithPort("9080/tcp").WithStartupTimeout(40*time.Second)). Invoke() checkIfError(t, err) } @@ -142,8 +161,8 @@ func TestDockerComposeWithMultipleWaitStrategies(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). - WithExposedService(map[string]interface{}{"mysql_1": wait.NewLogStrategy("started").WithStartupTimeout(100 * time.Microsecond)}). - WithExposedService(map[string]interface{}{"nginx_1": wait.ForHTTP("/").WithPort("9080/tcp")}). + WithExposedService("mysql_1", wait.NewLogStrategy("started").WithStartupTimeout(80*time.Second)). + WithExposedService("nginx_1", wait.NewHTTPStrategy("/").WithPort("9080/tcp").WithStartupTimeout(40*time.Second)). Invoke() checkIfError(t, err) } From 60a6b898befe23360f07a109805d4f7c3b424bbb Mon Sep 17 00:00:00 2001 From: shashank Date: Wed, 4 Nov 2020 15:24:26 -0500 Subject: [PATCH 007/219] Fixing test for the HTTP Strategy --- compose_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compose_test.go b/compose_test.go index b1da3bcc65..b0b27cd7ea 100644 --- a/compose_test.go +++ b/compose_test.go @@ -142,7 +142,7 @@ func TestDockerComposeWithWaitHTTPStrategy(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). - WithExposedService("nginx_1", wait.NewHTTPStrategy("/").WithPort("9080/tcp").WithStartupTimeout(40*time.Second)). + WithExposedService("nginx_1", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Invoke() checkIfError(t, err) } @@ -162,7 +162,7 @@ func TestDockerComposeWithMultipleWaitStrategies(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). WithExposedService("mysql_1", wait.NewLogStrategy("started").WithStartupTimeout(80*time.Second)). - WithExposedService("nginx_1", wait.NewHTTPStrategy("/").WithPort("9080/tcp").WithStartupTimeout(40*time.Second)). + WithExposedService("nginx_1", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Invoke() checkIfError(t, err) } From 0ad49fef75a552c69053232aa88eac9a52729e02 Mon Sep 17 00:00:00 2001 From: shashank Date: Fri, 6 Nov 2020 14:51:29 -0500 Subject: [PATCH 008/219] Cleaned up the code, added negative test case and removed nested for loop logic --- compose.go | 76 ++++++++++++++++++++++++++----------------------- compose_test.go | 47 +++++++++++++++++++++++++++--- 2 files changed, 83 insertions(+), 40 deletions(-) diff --git a/compose.go b/compose.go index 3dbc2eecdf..7f478a2a35 100644 --- a/compose.go +++ b/compose.go @@ -14,6 +14,7 @@ import ( "sync" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" "github.com/docker/docker/client" "github.com/testcontainers/testcontainers-go/wait" "gopkg.in/yaml.v2" @@ -43,7 +44,7 @@ type LocalDockerCompose struct { Cmd []string Env map[string]string Services map[string]interface{} - WaitStrategySupplied bool + waitStrategySupplied bool WaitStrategyMap map[string]wait.Strategy } @@ -73,7 +74,7 @@ func NewLocalDockerCompose(filePaths []string, identifier string) *LocalDockerCo dc.validate() dc.Identifier = strings.ToLower(identifier) - dc.WaitStrategySupplied = false + dc.waitStrategySupplied = false dc.WaitStrategyMap = make(map[string]wait.Strategy) return dc @@ -98,53 +99,51 @@ func (dc *LocalDockerCompose) getDockerComposeEnvironment() map[string]string { return environment } -func (dc *LocalDockerCompose) applyStrategyToRunningContainer() { - cli, err := client.NewClientWithOpts(client.FromEnv) - if err != nil { - panic(err) - } +func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { failedStrategies := make(map[string]wait.Strategy) - containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{}) + cli, err := client.NewClientWithOpts(client.FromEnv) if err != nil { - panic(err) + return err } - // Docker compose appends "_1" to every started service by default. Printing the services to verify that the right services have a wait strategy - keys := make([]string, 0, len(dc.WaitStrategyMap)) for k := range dc.WaitStrategyMap { - keys = append(keys, strings.TrimSuffix(k, "_1")) - } - fmt.Printf("List of Containers with Wait Strategy supplied: %v\n ", keys) - - // Iterate over all the wait strategies supplied, and apply them one by one - for _, container := range containers { - for _, key := range keys { - if strings.Contains(container.Image, key) { - fmt.Printf("Running containers to apply wait strategy: %v\n", container.Image) - // Retrieve the strategy for each container - strategy := dc.WaitStrategyMap[key+"_1"] - fmt.Printf("Strategy (%+v) to be applied to container: %v\n", strategy, key) - dockerProvider, _ := NewDockerProvider() - dockercontainer := &DockerContainer{ID: container.ID, WaitingFor: strategy, provider: dockerProvider} - err := strategy.WaitUntilReady(context.Background(), dockercontainer) - if err != nil { - failedStrategies[key] = strategy - fmt.Printf("Error trace: %s\n", err) - } + // Docker compose appends "_1" to every started service by default. Trimming to match running docker container + f := filters.NewArgs(filters.Arg("name", strings.TrimSuffix(k, "_1"))) + containerListOptions := types.ContainerListOptions{Filters: f} + containers, cErr := cli.ContainerList(context.Background(), containerListOptions) + if cErr != nil { + return cErr + } + if len(containers) > 0 { + // The length will always be a list of 1, since we are matching one service name at a time + container := containers[0] + strategy := dc.WaitStrategyMap[k] + dockerProvider, dpErr := NewDockerProvider() + if dpErr != nil { + fmt.Printf("Unable to create new Docker Provider") + return dpErr + } + dockercontainer := &DockerContainer{ID: container.ID, WaitingFor: strategy, provider: dockerProvider} + err := strategy.WaitUntilReady(context.Background(), dockercontainer) + if err != nil { + failedStrategies[container.Image] = strategy + fmt.Printf("Error trace: %s\n", err) } } } + if len(failedStrategies) > 0 { - fmt.Printf("List of wait strategies that were unsuccessful: (%v)", failedStrategies) + err := fmt.Errorf("List of wait strategies that were unsuccessful: (%v)", failedStrategies) + return err } + return nil } // Invoke invokes the docker compose func (dc *LocalDockerCompose) Invoke() ExecError { - if dc.WaitStrategySupplied { - fmt.Println("Wait Strategy(ies) supplied") + if dc.waitStrategySupplied { return executeCompose(dc, dc.Cmd) } return executeCompose(dc, dc.Cmd) @@ -165,7 +164,7 @@ func (dc *LocalDockerCompose) WithEnv(env map[string]string) DockerCompose { // WithExposedService sets the strategy for the service that is to be waited on. If multiple strategies // are given for a single service, the latest one will be applied func (dc *LocalDockerCompose) WithExposedService(service string, strategy wait.Strategy) DockerCompose { - dc.WaitStrategySupplied = true + dc.waitStrategySupplied = true dc.WaitStrategyMap[service] = strategy return dc } @@ -298,8 +297,13 @@ func executeCompose(dc *LocalDockerCompose, args []string) ExecError { } } - if dc.WaitStrategySupplied { - dc.applyStrategyToRunningContainer() + if dc.waitStrategySupplied { + err := dc.applyStrategyToRunningContainer() + if err != nil { + return ExecError{ + Error: fmt.Errorf("One or more wait strategies could not be applied to the running containers: %v", err), + } + } } return execErr diff --git a/compose_test.go b/compose_test.go index b0b27cd7ea..c592e7bc60 100644 --- a/compose_test.go +++ b/compose_test.go @@ -123,13 +123,18 @@ func TestDockerComposeWithWaitLogStrategy(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). + // Appending with _1 as given in the Java Test-Containers Example WithExposedService("mysql_1", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Invoke() checkIfError(t, err) + + assert.Equal(t, 2, len(compose.Services)) + assert.Contains(t, compose.Services, "nginx") + assert.Contains(t, compose.Services, "mysql") } func TestDockerComposeWithWaitHTTPStrategy(t *testing.T) { - path := "./testresources/docker-compose-complex.yml" + path := "./testresources/docker-compose-simple.yml" identifier := strings.ToLower(uuid.New().String()) @@ -142,9 +147,15 @@ func TestDockerComposeWithWaitHTTPStrategy(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). + WithEnv(map[string]string{ + "bar": "BAR", + }). WithExposedService("nginx_1", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Invoke() checkIfError(t, err) + + assert.Equal(t, 1, len(compose.Services)) + assert.Contains(t, compose.Services, "nginx") } func TestDockerComposeWithMultipleWaitStrategies(t *testing.T) { @@ -161,14 +172,42 @@ func TestDockerComposeWithMultipleWaitStrategies(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). - WithExposedService("mysql_1", wait.NewLogStrategy("started").WithStartupTimeout(80*time.Second)). + WithExposedService("mysql_1", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second)). WithExposedService("nginx_1", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Invoke() checkIfError(t, err) + + assert.Equal(t, 2, len(compose.Services)) + assert.Contains(t, compose.Services, "nginx") + assert.Contains(t, compose.Services, "mysql") } -// Add negative test case with Dockerfile that never starts up and a timeout period of 10-20 seconds -// Add test case for multiple wait strategies +func TestDockerComposeWithFailedStrategy(t *testing.T) { + path := "./testresources/docker-compose-simple.yml" + + identifier := strings.ToLower(uuid.New().String()) + + compose := NewLocalDockerCompose([]string{path}, identifier) + destroyFn := func() { + err := compose.Down() + checkIfError(t, err) + } + defer destroyFn() + + err := compose. + WithCommand([]string{"up", "-d"}). + WithEnv(map[string]string{ + "bar": "BAR", + }). + WithExposedService("nginx_1", wait.NewHTTPStrategy("/").WithPort("8080/tcp").WithStartupTimeout(5*time.Second)). + Invoke() + // Verify that an error is thrown and not nil + // A specific error message matcher is not asserted since the docker library can change the return message, breaking this test + assert.NotEqual(t, err.Error, nil, "Expected error to be thrown because of a wrong suplied wait strategy") + + assert.Equal(t, 1, len(compose.Services)) + assert.Contains(t, compose.Services, "nginx") +} func TestLocalDockerComposeComplex(t *testing.T) { path := "./testresources/docker-compose-complex.yml" From c1e9cb2a231ff4a9c9f349d387602957c580fd25 Mon Sep 17 00:00:00 2001 From: shashank Date: Sat, 7 Nov 2020 09:19:03 -0500 Subject: [PATCH 009/219] Addressing Comments from code review --- compose.go | 56 ++++++++++++++++++++++++++----------------------- compose_test.go | 22 +++++++++++++++++++ 2 files changed, 52 insertions(+), 26 deletions(-) diff --git a/compose.go b/compose.go index 7f478a2a35..f95882f13f 100644 --- a/compose.go +++ b/compose.go @@ -112,40 +112,43 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { // Docker compose appends "_1" to every started service by default. Trimming to match running docker container f := filters.NewArgs(filters.Arg("name", strings.TrimSuffix(k, "_1"))) containerListOptions := types.ContainerListOptions{Filters: f} - containers, cErr := cli.ContainerList(context.Background(), containerListOptions) - if cErr != nil { - return cErr + containers, err := cli.ContainerList(context.Background(), containerListOptions) + if err != nil { + return fmt.Errorf("there was an issue filtering the service %s by name", k) } - if len(containers) > 0 { - // The length will always be a list of 1, since we are matching one service name at a time - container := containers[0] - strategy := dc.WaitStrategyMap[k] - dockerProvider, dpErr := NewDockerProvider() - if dpErr != nil { - fmt.Printf("Unable to create new Docker Provider") - return dpErr - } - dockercontainer := &DockerContainer{ID: container.ID, WaitingFor: strategy, provider: dockerProvider} - err := strategy.WaitUntilReady(context.Background(), dockercontainer) - if err != nil { - failedStrategies[container.Image] = strategy - fmt.Printf("Error trace: %s\n", err) - } + + if len(containers) == 0 { + return fmt.Errorf("service with name %s not found in list of running containers", k) + } + + // The length should always be a list of 1, since we are matching one service name at a time + if l := len(containers); l > 1 { + return fmt.Errorf("expecting only one running container for %s but got %d", k, l) + } + container := containers[0] + strategy := dc.WaitStrategyMap[k] + dockerProvider, err := NewDockerProvider() + if err != nil { + return fmt.Errorf("unable to create new Docker Provider: %w", err) + } + dockercontainer := &DockerContainer{ID: container.ID, WaitingFor: strategy, provider: dockerProvider} + err = strategy.WaitUntilReady(context.Background(), dockercontainer) + if err != nil { + failedStrategies[container.Image] = strategy + // TODO: Revisit after chat with Michael + fmt.Printf("error trace: %s", err) } } if len(failedStrategies) > 0 { - err := fmt.Errorf("List of wait strategies that were unsuccessful: (%v)", failedStrategies) - return err + return fmt.Errorf("list of wait strategies that were unsuccessful: (%v)", failedStrategies) } + return nil } // Invoke invokes the docker compose func (dc *LocalDockerCompose) Invoke() ExecError { - if dc.waitStrategySupplied { - return executeCompose(dc, dc.Cmd) - } return executeCompose(dc, dc.Cmd) } @@ -298,10 +301,11 @@ func executeCompose(dc *LocalDockerCompose, args []string) ExecError { } if dc.waitStrategySupplied { - err := dc.applyStrategyToRunningContainer() - if err != nil { + // If the wait strategy has been executed once for all services during startup , disable it so that it is not invoked while tearing down + dc.waitStrategySupplied = false + if err := dc.applyStrategyToRunningContainer(); err != nil { return ExecError{ - Error: fmt.Errorf("One or more wait strategies could not be applied to the running containers: %v", err), + Error: fmt.Errorf("one or more wait strategies could not be applied to the running containers: %w", err), } } } diff --git a/compose_test.go b/compose_test.go index c592e7bc60..95b9210b4a 100644 --- a/compose_test.go +++ b/compose_test.go @@ -108,6 +108,28 @@ func TestLocalDockerCompose(t *testing.T) { Invoke() checkIfError(t, err) } +func TestDockerComposeStrategyForInvalidService(t *testing.T) { + path := "./testresources/docker-compose-simple.yml" + + identifier := strings.ToLower(uuid.New().String()) + + compose := NewLocalDockerCompose([]string{path}, identifier) + destroyFn := func() { + err := compose.Down() + checkIfError(t, err) + } + defer destroyFn() + + err := compose. + WithCommand([]string{"up", "-d"}). + // Appending with _1 as given in the Java Test-Containers Example + WithExposedService("mysql_1", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). + Invoke() + assert.NotEqual(t, err.Error, nil, "Expected error to be thrown because service with wait strategy is not running") + + assert.Equal(t, 1, len(compose.Services)) + assert.Contains(t, compose.Services, "nginx") +} func TestDockerComposeWithWaitLogStrategy(t *testing.T) { path := "./testresources/docker-compose-complex.yml" From cb40099113a3a857cbeda19429e9741f87a60567 Mon Sep 17 00:00:00 2001 From: shashank Date: Sun, 8 Nov 2020 17:13:26 -0500 Subject: [PATCH 010/219] Remove Failed Strategy map and error out as soon as any wait strategy fails with reason --- compose.go | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/compose.go b/compose.go index f95882f13f..24f28c7699 100644 --- a/compose.go +++ b/compose.go @@ -101,8 +101,6 @@ func (dc *LocalDockerCompose) getDockerComposeEnvironment() map[string]string { func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { - failedStrategies := make(map[string]wait.Strategy) - cli, err := client.NewClientWithOpts(client.FromEnv) if err != nil { return err @@ -134,16 +132,9 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { dockercontainer := &DockerContainer{ID: container.ID, WaitingFor: strategy, provider: dockerProvider} err = strategy.WaitUntilReady(context.Background(), dockercontainer) if err != nil { - failedStrategies[container.Image] = strategy - // TODO: Revisit after chat with Michael - fmt.Printf("error trace: %s", err) + return fmt.Errorf("Unable to apply wait strategy %v to service %s due to %w", strategy, container.Image, err) } } - - if len(failedStrategies) > 0 { - return fmt.Errorf("list of wait strategies that were unsuccessful: (%v)", failedStrategies) - } - return nil } From 002afe65e37a4209b3edf249ef40931352c457be Mon Sep 17 00:00:00 2001 From: shashank Date: Sun, 8 Nov 2020 18:25:26 -0500 Subject: [PATCH 011/219] Add ability to filter service by name and published port exactly like the Java client --- compose.go | 27 +++++++++++++++++---------- compose_test.go | 12 ++++++------ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/compose.go b/compose.go index 24f28c7699..b81eeedd0c 100644 --- a/compose.go +++ b/compose.go @@ -10,6 +10,7 @@ import ( "os/exec" "path/filepath" "runtime" + "strconv" "strings" "sync" @@ -31,7 +32,12 @@ type DockerCompose interface { Invoke() ExecError WithCommand([]string) DockerCompose WithEnv(map[string]string) DockerCompose - WithExposedService(string, wait.Strategy) DockerCompose + WithExposedService(string, int, wait.Strategy) DockerCompose +} + +type waitService struct { + service string + publishedPort int } // LocalDockerCompose represents a Docker Compose execution using local binary @@ -45,7 +51,7 @@ type LocalDockerCompose struct { Env map[string]string Services map[string]interface{} waitStrategySupplied bool - WaitStrategyMap map[string]wait.Strategy + WaitStrategyMap map[waitService]wait.Strategy } // NewLocalDockerCompose returns an instance of the local Docker Compose, using an @@ -75,7 +81,7 @@ func NewLocalDockerCompose(filePaths []string, identifier string) *LocalDockerCo dc.Identifier = strings.ToLower(identifier) dc.waitStrategySupplied = false - dc.WaitStrategyMap = make(map[string]wait.Strategy) + dc.WaitStrategyMap = make(map[waitService]wait.Strategy) return dc } @@ -108,20 +114,21 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { for k := range dc.WaitStrategyMap { // Docker compose appends "_1" to every started service by default. Trimming to match running docker container - f := filters.NewArgs(filters.Arg("name", strings.TrimSuffix(k, "_1"))) + f := filters.NewArgs(filters.Arg("name", strings.TrimSuffix(k.service, "_1")), + filters.Arg("publish", strconv.Itoa(k.publishedPort))) containerListOptions := types.ContainerListOptions{Filters: f} containers, err := cli.ContainerList(context.Background(), containerListOptions) if err != nil { - return fmt.Errorf("there was an issue filtering the service %s by name", k) + return fmt.Errorf("there was an issue filtering the service %s: %d by name and published port", k.service, k.publishedPort) } if len(containers) == 0 { - return fmt.Errorf("service with name %s not found in list of running containers", k) + return fmt.Errorf("service with name %s not found in list of running containers", k.service) } // The length should always be a list of 1, since we are matching one service name at a time if l := len(containers); l > 1 { - return fmt.Errorf("expecting only one running container for %s but got %d", k, l) + return fmt.Errorf("expecting only one running container for %s but got %d", k.service, l) } container := containers[0] strategy := dc.WaitStrategyMap[k] @@ -156,10 +163,10 @@ func (dc *LocalDockerCompose) WithEnv(env map[string]string) DockerCompose { } // WithExposedService sets the strategy for the service that is to be waited on. If multiple strategies -// are given for a single service, the latest one will be applied -func (dc *LocalDockerCompose) WithExposedService(service string, strategy wait.Strategy) DockerCompose { +// are given for a single service running on different ports, both strategies will be applied on the same container +func (dc *LocalDockerCompose) WithExposedService(service string, port int, strategy wait.Strategy) DockerCompose { dc.waitStrategySupplied = true - dc.WaitStrategyMap[service] = strategy + dc.WaitStrategyMap[waitService{service: service, publishedPort: port}] = strategy return dc } diff --git a/compose_test.go b/compose_test.go index 95b9210b4a..2abed9af31 100644 --- a/compose_test.go +++ b/compose_test.go @@ -123,7 +123,7 @@ func TestDockerComposeStrategyForInvalidService(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). // Appending with _1 as given in the Java Test-Containers Example - WithExposedService("mysql_1", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). + WithExposedService("mysql_1", 3306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Invoke() assert.NotEqual(t, err.Error, nil, "Expected error to be thrown because service with wait strategy is not running") @@ -146,7 +146,7 @@ func TestDockerComposeWithWaitLogStrategy(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). // Appending with _1 as given in the Java Test-Containers Example - WithExposedService("mysql_1", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). + WithExposedService("mysql_1", 3306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Invoke() checkIfError(t, err) @@ -172,7 +172,7 @@ func TestDockerComposeWithWaitHTTPStrategy(t *testing.T) { WithEnv(map[string]string{ "bar": "BAR", }). - WithExposedService("nginx_1", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). + WithExposedService("nginx_1", 80, wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Invoke() checkIfError(t, err) @@ -194,8 +194,8 @@ func TestDockerComposeWithMultipleWaitStrategies(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). - WithExposedService("mysql_1", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second)). - WithExposedService("nginx_1", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). + WithExposedService("mysql_1", 3306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second)). + WithExposedService("nginx_1", 80, wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Invoke() checkIfError(t, err) @@ -221,7 +221,7 @@ func TestDockerComposeWithFailedStrategy(t *testing.T) { WithEnv(map[string]string{ "bar": "BAR", }). - WithExposedService("nginx_1", wait.NewHTTPStrategy("/").WithPort("8080/tcp").WithStartupTimeout(5*time.Second)). + WithExposedService("nginx_1", 80, wait.NewHTTPStrategy("/").WithPort("8080/tcp").WithStartupTimeout(5*time.Second)). Invoke() // Verify that an error is thrown and not nil // A specific error message matcher is not asserted since the docker library can change the return message, breaking this test From 9c6fa547fa40b19b2190c27f182925f984865118 Mon Sep 17 00:00:00 2001 From: shashank Date: Sun, 8 Nov 2020 18:50:53 -0500 Subject: [PATCH 012/219] Add error message if filtered containers can't be found --- compose.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose.go b/compose.go index b81eeedd0c..f9ac6da34e 100644 --- a/compose.go +++ b/compose.go @@ -119,7 +119,7 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { containerListOptions := types.ContainerListOptions{Filters: f} containers, err := cli.ContainerList(context.Background(), containerListOptions) if err != nil { - return fmt.Errorf("there was an issue filtering the service %s: %d by name and published port", k.service, k.publishedPort) + return fmt.Errorf("error %w occured while filtering the service %s: %d by name and published port", err, k.service, k.publishedPort) } if len(containers) == 0 { From f72c8a8dbed6d4dd995c05a3ea8cb430ea5419d3 Mon Sep 17 00:00:00 2001 From: Shashank Gowdagiri Date: Tue, 10 Nov 2020 08:25:51 -0500 Subject: [PATCH 013/219] Update compose.go based on suggestion from @mdelapenya MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Indent line 118 in compose.go Co-authored-by: Manuel de la Peña --- compose.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose.go b/compose.go index f9ac6da34e..67cfb5991f 100644 --- a/compose.go +++ b/compose.go @@ -115,7 +115,7 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { for k := range dc.WaitStrategyMap { // Docker compose appends "_1" to every started service by default. Trimming to match running docker container f := filters.NewArgs(filters.Arg("name", strings.TrimSuffix(k.service, "_1")), - filters.Arg("publish", strconv.Itoa(k.publishedPort))) + filters.Arg("publish", strconv.Itoa(k.publishedPort))) containerListOptions := types.ContainerListOptions{Filters: f} containers, err := cli.ContainerList(context.Background(), containerListOptions) if err != nil { From edf5289a80d8001ee5a9f7f816fd3d5ac0046781 Mon Sep 17 00:00:00 2001 From: shashank Date: Tue, 10 Nov 2020 08:57:39 -0500 Subject: [PATCH 014/219] Revert changes because static analysis fails with indent --- compose.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose.go b/compose.go index 67cfb5991f..f9ac6da34e 100644 --- a/compose.go +++ b/compose.go @@ -115,7 +115,7 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { for k := range dc.WaitStrategyMap { // Docker compose appends "_1" to every started service by default. Trimming to match running docker container f := filters.NewArgs(filters.Arg("name", strings.TrimSuffix(k.service, "_1")), - filters.Arg("publish", strconv.Itoa(k.publishedPort))) + filters.Arg("publish", strconv.Itoa(k.publishedPort))) containerListOptions := types.ContainerListOptions{Filters: f} containers, err := cli.ContainerList(context.Background(), containerListOptions) if err != nil { From fc9e03841f6cfc841bda0415b00d9ee7a98b8664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Thu, 8 Apr 2021 11:51:08 +0200 Subject: [PATCH 015/219] chore: run go mod tidy --- go.mod | 6 +----- go.sum | 48 ++++++++++++++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index 23088c26e0..ecfc80fc2e 100644 --- a/go.mod +++ b/go.mod @@ -3,20 +3,16 @@ module github.com/testcontainers/testcontainers-go go 1.13 require ( - github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect - github.com/Microsoft/hcsshim v0.8.15 + github.com/Microsoft/hcsshim v0.8.15 // indirect github.com/cenkalti/backoff v2.2.1+incompatible github.com/docker/docker v20.10.5+incompatible github.com/docker/go-connections v0.4.0 github.com/go-redis/redis v6.15.9+incompatible github.com/go-sql-driver/mysql v1.6.0 github.com/google/uuid v1.2.0 - github.com/gorilla/context v1.1.1 // indirect github.com/moby/sys/mount v0.2.0 // indirect github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect - github.com/opencontainers/image-spec v1.0.1 github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.7.0 // indirect github.com/stretchr/testify v1.7.0 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c google.golang.org/grpc v1.33.2 // indirect diff --git a/go.sum b/go.sum index dd16efb152..b375dcee13 100644 --- a/go.sum +++ b/go.sum @@ -42,12 +42,9 @@ github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcy github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/go-winio v0.4.15-0.20200908182639-5b44b70ab3ab h1:9pygWVFqbY9lPxM0peffumuVDyMuIMzNLyO9uFjJuQo= -github.com/Microsoft/go-winio v0.4.15-0.20200908182639-5b44b70ab3ab/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/go-winio v0.4.15 h1:qkLXKzb1QoVatRyd/YlXZ/Kg0m5K3SPuoD82jjSOaBc= -github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3 h1:mw6pDQqv38/WGF1cO/jF5t/jyAJ2yi7CmtFLLO5tGFI= github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= @@ -56,9 +53,8 @@ github.com/Microsoft/hcsshim v0.8.7 h1:ptnOoufxGSzauVTsdE+wMYnCWA301PdoN4xg5oRdZ github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= github.com/Microsoft/hcsshim v0.8.9 h1:VrfodqvztU8YSOvygU+DN1BGaSGxmrNfqOv5oOuX2Bk= github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= -github.com/Microsoft/hcsshim v0.8.10 h1:k5wTrpnVU2/xv8ZuzGkbXVd3js5zJ8RnumPo5RxiIxU= -github.com/Microsoft/hcsshim v0.8.10/go.mod h1:g5uw8EV2mAlzqe94tfNBNdr89fnbD/n3HV0OhsddkmM= github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Microsoft/hcsshim v0.8.15 h1:Aof83YILRs2Vx3GhHqlvvfyx1asRJKMFIMeVlHsZKtI= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -107,6 +103,7 @@ github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmY github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102 h1:Qf4HiqfvmB7zS6scsmNgTLmByHbq8n9RTF39v+TzP7A= github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= @@ -118,8 +115,6 @@ github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.1 h1:pASeJT3R3YyVn+94qEPk0SnU1OQ20Jd/T+SPKy9xehY= -github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.5.0-beta.1 h1:IK6yirB4X7wpKyFSikWiT++nZsyIxGAAgNEv3fEGuls= github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8= @@ -183,11 +178,6 @@ github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v17.12.0-ce-rc1.0.20200916142827-bd33bbf0497b+incompatible h1:SiUATuP//KecDjpOK2tvZJgeScYAklvyjfK8JZlU6fo= -github.com/docker/docker v17.12.0-ce-rc1.0.20200916142827-bd33bbf0497b+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.3+incompatible h1:+HS4XO73J41FpA260ztGujJ+0WibrA2TPJEnWNSyGNE= -github.com/docker/docker v20.10.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.5+incompatible h1:o5WL5onN4awYGwrW7+oTn5x9AF2prw7V0Ox8ZEkoCdg= github.com/docker/docker v20.10.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= @@ -214,6 +204,7 @@ github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= @@ -236,8 +227,9 @@ github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL9 github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= @@ -247,7 +239,6 @@ github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -259,6 +250,7 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -289,6 +281,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -302,16 +295,14 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.4/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -326,6 +317,7 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -353,9 +345,11 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -375,11 +369,13 @@ github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7s github.com/moby/sys/mountinfo v0.4.0 h1:1KInV3Huv18akCu58V7lzNlt+jFmqlu1EaErnEHE/VM= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd h1:aY7OQNf2XqY/JQ6qREWamhI/81os/agb2BAGpcx5yWI= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= @@ -391,14 +387,14 @@ github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:v github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -431,6 +427,7 @@ github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -491,6 +488,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -524,6 +522,7 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -679,11 +678,13 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -725,6 +726,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -798,9 +800,11 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -808,6 +812,7 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -818,8 +823,11 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From e106c77d00ae9e6e14dafcad8e382414c7aba2e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Thu, 8 Apr 2021 12:24:59 +0200 Subject: [PATCH 016/219] chore: run go mod tidy again --- go.mod | 4 +--- go.sum | 10 ++++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1bafc41788..8fae857b4c 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,7 @@ module github.com/testcontainers/testcontainers-go go 1.13 require ( - github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect - github.com/Microsoft/hcsshim v0.8.16 + github.com/Microsoft/hcsshim v0.8.16 // indirect github.com/cenkalti/backoff v2.2.1+incompatible github.com/docker/docker v20.10.5+incompatible github.com/docker/go-connections v0.4.0 @@ -16,7 +15,6 @@ require ( github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.0 golang.org/x/sys v0.0.0-20210324051608-47abb6519492 - google.golang.org/grpc v1.33.2 // indirect gopkg.in/yaml.v2 v2.4.0 gotest.tools v2.2.0+incompatible ) diff --git a/go.sum b/go.sum index 1052bac3f9..c4061493aa 100644 --- a/go.sum +++ b/go.sum @@ -56,6 +56,7 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3 github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/Microsoft/hcsshim v0.8.15 h1:Aof83YILRs2Vx3GhHqlvvfyx1asRJKMFIMeVlHsZKtI= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim v0.8.16 h1:8/auA4LFIZFTGrqfKhGBSXwM6/4X1fHa/xniyEHu8ac= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= @@ -110,6 +111,7 @@ github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1 github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102 h1:Qf4HiqfvmB7zS6scsmNgTLmByHbq8n9RTF39v+TzP7A= github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68 h1:hkGVFjz+plgr5UfxZUTPFbUFIF/Km6/s+RVRIRHLrrY= github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= @@ -127,6 +129,7 @@ github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX github.com/containerd/containerd v1.5.0-beta.1 h1:IK6yirB4X7wpKyFSikWiT++nZsyIxGAAgNEv3fEGuls= github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= +github.com/containerd/containerd v1.5.0-beta.4 h1:zjz4MOAOFgdBlwid2nNUlJ3YLpVi/97L36lfMYJex60= github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -135,6 +138,7 @@ github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7 h1:6ejg6Lkk8dskcM7wQ28gONkukbQkM4qpj4RnYbpFzrI= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e h1:6JKvHHt396/qabvMhnhUZvWaHZzfVfldxE60TK8YLhg= github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= @@ -303,6 +307,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -391,6 +396,7 @@ github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= github.com/moby/sys/mountinfo v0.4.0 h1:1KInV3Huv18akCu58V7lzNlt+jFmqlu1EaErnEHE/VM= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd h1:aY7OQNf2XqY/JQ6qREWamhI/81os/agb2BAGpcx5yWI= @@ -646,6 +652,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -703,6 +710,7 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -845,6 +853,7 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -861,6 +870,7 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 602e9dfa362a5ae6ef25e07956d2cca0504f0365 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 13 Apr 2021 05:46:44 +0000 Subject: [PATCH 017/219] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 20.10.5+incompatible to 20.10.6+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Changelog](https://github.com/moby/moby/blob/master/CHANGELOG.md) - [Commits](https://github.com/docker/docker/compare/v20.10.5...v20.10.6) Signed-off-by: dependabot-preview[bot] --- go.mod | 2 +- go.sum | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 08c85b5735..2d2fc91b7e 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/Microsoft/hcsshim v0.8.16 github.com/cenkalti/backoff v2.2.1+incompatible - github.com/docker/docker v20.10.5+incompatible + github.com/docker/docker v20.10.6+incompatible github.com/docker/go-connections v0.4.0 github.com/go-redis/redis v6.15.9+incompatible github.com/go-sql-driver/mysql v1.6.0 diff --git a/go.sum b/go.sum index 39ed904d5e..02850b33ca 100644 --- a/go.sum +++ b/go.sum @@ -208,6 +208,7 @@ github.com/docker/docker v20.10.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05b github.com/docker/docker v20.10.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.5+incompatible h1:o5WL5onN4awYGwrW7+oTn5x9AF2prw7V0Ox8ZEkoCdg= github.com/docker/docker v20.10.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= From f30f0edf4458081b0d630fc1878cbdc888e41153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 28 Apr 2021 05:44:05 +0200 Subject: [PATCH 018/219] fix: use container name instead We are using the docker container API to retrieve the container --- compose.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compose.go b/compose.go index f9ac6da34e..64495606b0 100644 --- a/compose.go +++ b/compose.go @@ -113,9 +113,9 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { } for k := range dc.WaitStrategyMap { + containerName := dc.Identifier + "_" + k.service // Docker compose appends "_1" to every started service by default. Trimming to match running docker container - f := filters.NewArgs(filters.Arg("name", strings.TrimSuffix(k.service, "_1")), - filters.Arg("publish", strconv.Itoa(k.publishedPort))) + f := filters.NewArgs(filters.Arg("name", containerName), filters.Arg("publish", strconv.Itoa(k.publishedPort))) containerListOptions := types.ContainerListOptions{Filters: f} containers, err := cli.ContainerList(context.Background(), containerListOptions) if err != nil { From baeecfb6d98efdc43655c21396783a2fc6bc835d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 28 Apr 2021 05:46:12 +0200 Subject: [PATCH 019/219] fix: use exposed ports instead --- compose_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compose_test.go b/compose_test.go index 2abed9af31..1e970abcdd 100644 --- a/compose_test.go +++ b/compose_test.go @@ -123,7 +123,7 @@ func TestDockerComposeStrategyForInvalidService(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). // Appending with _1 as given in the Java Test-Containers Example - WithExposedService("mysql_1", 3306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). + WithExposedService("mysql_1", 13306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Invoke() assert.NotEqual(t, err.Error, nil, "Expected error to be thrown because service with wait strategy is not running") @@ -146,7 +146,7 @@ func TestDockerComposeWithWaitLogStrategy(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). // Appending with _1 as given in the Java Test-Containers Example - WithExposedService("mysql_1", 3306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). + WithExposedService("mysql_1", 13306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Invoke() checkIfError(t, err) @@ -194,8 +194,8 @@ func TestDockerComposeWithMultipleWaitStrategies(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). - WithExposedService("mysql_1", 3306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second)). - WithExposedService("nginx_1", 80, wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). + WithExposedService("mysql_1", 13306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second)). + WithExposedService("nginx_1", 9080, wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Invoke() checkIfError(t, err) From 0f52029fc8f5f23a230ef28dc0e7dd057cf56a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 28 Apr 2021 06:16:58 +0200 Subject: [PATCH 020/219] fix: use current service name in log --- compose.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose.go b/compose.go index 64495606b0..831036d634 100644 --- a/compose.go +++ b/compose.go @@ -139,7 +139,7 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { dockercontainer := &DockerContainer{ID: container.ID, WaitingFor: strategy, provider: dockerProvider} err = strategy.WaitUntilReady(context.Background(), dockercontainer) if err != nil { - return fmt.Errorf("Unable to apply wait strategy %v to service %s due to %w", strategy, container.Image, err) + return fmt.Errorf("Unable to apply wait strategy %v to service %s due to %w", strategy, k.service, err) } } return nil From 7b13630e07904b5607895ed29719effcb71e66ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 28 Apr 2021 06:17:28 +0200 Subject: [PATCH 021/219] fix: use exposed ports for simple compose file --- compose_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compose_test.go b/compose_test.go index 1e970abcdd..477b05d16b 100644 --- a/compose_test.go +++ b/compose_test.go @@ -172,7 +172,7 @@ func TestDockerComposeWithWaitHTTPStrategy(t *testing.T) { WithEnv(map[string]string{ "bar": "BAR", }). - WithExposedService("nginx_1", 80, wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). + WithExposedService("nginx_1", 9080, wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Invoke() checkIfError(t, err) @@ -221,7 +221,7 @@ func TestDockerComposeWithFailedStrategy(t *testing.T) { WithEnv(map[string]string{ "bar": "BAR", }). - WithExposedService("nginx_1", 80, wait.NewHTTPStrategy("/").WithPort("8080/tcp").WithStartupTimeout(5*time.Second)). + WithExposedService("nginx_1", 9080, wait.NewHTTPStrategy("/").WithPort("8080/tcp").WithStartupTimeout(5*time.Second)). Invoke() // Verify that an error is thrown and not nil // A specific error message matcher is not asserted since the docker library can change the return message, breaking this test From aac3e3adc9c279f99f28a33adcb8a7301f5f925f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 28 Apr 2021 06:45:19 +0200 Subject: [PATCH 022/219] chore: do not hardcode container name in tests --- compose_test.go | 6 ++++-- testresources/docker-compose-simple.yml | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compose_test.go b/compose_test.go index 477b05d16b..02e42a3d72 100644 --- a/compose_test.go +++ b/compose_test.go @@ -12,8 +12,6 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) -const containerNameNginx = "nginx-simple" - func ExampleNewLocalDockerCompose() { path := "/path/to/docker-compose.yml" @@ -276,6 +274,8 @@ func TestLocalDockerComposeWithEnvironment(t *testing.T) { assert.Equal(t, 1, len(compose.Services)) assert.Contains(t, compose.Services, "nginx") + containerNameNginx := compose.Identifier + "_nginx_1" + present := map[string]string{ "bar": "BAR", } @@ -311,6 +311,8 @@ func TestLocalDockerComposeWithMultipleComposeFiles(t *testing.T) { assert.Contains(t, compose.Services, "nginx") assert.Contains(t, compose.Services, "mysql") + containerNameNginx := compose.Identifier + "_nginx_1" + present := map[string]string{ "bar": "BAR", "foo": "FOO", diff --git a/testresources/docker-compose-simple.yml b/testresources/docker-compose-simple.yml index f2789f5c5e..347e25d159 100644 --- a/testresources/docker-compose-simple.yml +++ b/testresources/docker-compose-simple.yml @@ -2,7 +2,6 @@ version: '3' services: nginx: image: nginx:stable-alpine - container_name: nginx-simple environment: bar: ${bar} ports: From d6ac48bf464539c459a882a47b7a7ea4c90542d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 28 Apr 2021 06:48:06 +0200 Subject: [PATCH 023/219] chore: add a comment about container names --- compose.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compose.go b/compose.go index 831036d634..af1283661b 100644 --- a/compose.go +++ b/compose.go @@ -113,6 +113,8 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { } for k := range dc.WaitStrategyMap { + // TODO: if the compose file includes a container_name, this won't work, + // as we cannot delegate to the names generated by Docker Compose containerName := dc.Identifier + "_" + k.service // Docker compose appends "_1" to every started service by default. Trimming to match running docker container f := filters.NewArgs(filters.Arg("name", containerName), filters.Arg("publish", strconv.Itoa(k.publishedPort))) From 0de1cd8bf2ecd5014bab8694294bc142134d111d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 29 Apr 2021 15:20:17 +0000 Subject: [PATCH 024/219] Upgrade to GitHub-native Dependabot --- .dependabot/config.yaml | 6 ------ .github/dependabot.yml | 8 ++++++++ 2 files changed, 8 insertions(+), 6 deletions(-) delete mode 100644 .dependabot/config.yaml create mode 100644 .github/dependabot.yml diff --git a/.dependabot/config.yaml b/.dependabot/config.yaml deleted file mode 100644 index 223f6bdc91..0000000000 --- a/.dependabot/config.yaml +++ /dev/null @@ -1,6 +0,0 @@ -version: 1 -update_configs: - - - package_manager: 'go:modules' - directory: / - update_schedule: daily diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..3f02defd8f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: +- package-ecosystem: gomod + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 3 + rebase-strategy: disabled From 7e2e2a0d96d35c4c711e2440e98af04aa0a4748f Mon Sep 17 00:00:00 2001 From: Tobias Salzmann <796084+Eun@users.noreply.github.com> Date: Mon, 10 May 2021 16:07:08 +0200 Subject: [PATCH 025/219] close reaper if it was created --- docker.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker.go b/docker.go index f8a913b87e..61cc96f1ca 100644 --- a/docker.go +++ b/docker.go @@ -174,6 +174,11 @@ func (c *DockerContainer) Start(ctx context.Context) error { // Terminate is used to kill the container. It is usually triggered by as defer function. func (c *DockerContainer) Terminate(ctx context.Context) error { + select { + // close reaper if it was created + case c.terminationSignal <- true: + default: + } err := c.provider.client.ContainerRemove(ctx, c.GetContainerID(), types.ContainerRemoveOptions{ RemoveVolumes: true, Force: true, From 906b5b4f66fea1ee1876a11894bf1376b78096f4 Mon Sep 17 00:00:00 2001 From: Tobias Salzmann <796084+Eun@users.noreply.github.com> Date: Mon, 10 May 2021 16:09:14 +0200 Subject: [PATCH 026/219] close reaper if it was created --- docker.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker.go b/docker.go index 61cc96f1ca..1fdeaee20f 100644 --- a/docker.go +++ b/docker.go @@ -426,6 +426,11 @@ type DockerNetwork struct { // Remove is used to remove the network. It is usually triggered by as defer function. func (n *DockerNetwork) Remove(ctx context.Context) error { + select { + // close reaper if it was created + case n.terminationSignal <- true: + default: + } return n.provider.client.NetworkRemove(ctx, n.ID) } From 8ee50ce71baec092c793d8c2f34325655fcc91ea Mon Sep 17 00:00:00 2001 From: Xico Date: Tue, 13 Apr 2021 16:52:29 -0300 Subject: [PATCH 027/219] Add support for build args when using Dockerfile to create image --- container.go | 15 ++++++--- docker.go | 1 + docker_test.go | 61 +++++++++++++++++++++++++++++++++++ testresources/args.Dockerfile | 11 +++++++ testresources/argsserver.go | 31 ++++++++++++++++++ 5 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 testresources/args.Dockerfile create mode 100644 testresources/argsserver.go diff --git a/container.go b/container.go index 00c4ff0459..65e524a882 100644 --- a/container.go +++ b/container.go @@ -54,9 +54,10 @@ type Container interface { // ImageBuildInfo defines what is needed to build an image type ImageBuildInfo interface { - GetContext() (io.Reader, error) // the path to the build context - GetDockerfile() string // the relative path to the Dockerfile, including the fileitself - ShouldBuildImage() bool // return true if the image needs to be built + GetContext() (io.Reader, error) // the path to the build context + GetDockerfile() string // the relative path to the Dockerfile, including the fileitself + ShouldBuildImage() bool // return true if the image needs to be built + GetBuildArgs() map[string]*string // return the environment args used to build the from Dockerfile } // FromDockerfile represents the parameters needed to build an image from a Dockerfile @@ -90,7 +91,8 @@ type ContainerRequest struct { ReaperImage string // alternative reaper image AutoRemove bool // if set to true, the container will be removed from the host when stopped NetworkMode container.NetworkMode - AlwaysPullImage bool // Always pull image + AlwaysPullImage bool // Always pull image + BuildArgs map[string]*string // for specifying network aliases } // ProviderType is an enum for the possible providers @@ -148,6 +150,11 @@ func (c *ContainerRequest) GetContext() (io.Reader, error) { return buildContext, nil } +// GetBuildArgs returns the env args to be used when creating from Dockerfile +func (c *ContainerRequest) GetBuildArgs() map[string]*string { + return c.BuildArgs +} + // GetDockerfile returns the Dockerfile from the ContainerRequest, defaults to "Dockerfile" func (c *ContainerRequest) GetDockerfile() string { f := c.FromDockerfile.Dockerfile diff --git a/docker.go b/docker.go index f8a913b87e..7a83f7a70e 100644 --- a/docker.go +++ b/docker.go @@ -459,6 +459,7 @@ func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (st } buildOptions := types.ImageBuildOptions{ + BuildArgs: img.GetBuildArgs(), Dockerfile: img.GetDockerfile(), Context: buildContext, Tags: []string{repoTag}, diff --git a/docker_test.go b/docker_test.go index c54daf7900..f67a32226b 100644 --- a/docker_test.go +++ b/docker_test.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "github.com/stretchr/testify/assert" + "io/ioutil" "math/rand" "net/http" "os/exec" @@ -892,6 +893,66 @@ func Test_BuildContainerFromDockerfile(t *testing.T) { } } +func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { + t.Log("getting ctx") + ctx := context.Background() + + ba := "build args value" + + t.Log("got ctx, creating container request") + req := ContainerRequest{ + FromDockerfile: FromDockerfile{ + Context: "./testresources", + Dockerfile: "args.Dockerfile", + }, + BuildArgs: map[string]*string{ + "FOO": &ba, + }, + ExposedPorts: []string{"8080/tcp"}, + WaitingFor: wait.ForLog("ready"), + } + + genContainerReq := GenericContainerRequest{ + ContainerRequest: req, + Started: true, + } + + c, err := GenericContainer(ctx, genContainerReq) + + if err != nil { + t.Fatal(err) + } + + ep, err := c.Endpoint(ctx, "http") + if err != nil { + t.Fatal(err) + } + + resp, err := http.Get(ep + "/env") + + if err != nil { + t.Fatal(err) + } + + body, err := ioutil.ReadAll(resp.Body) + + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, 200, resp.StatusCode) + assert.Equal(t, ba, string(body)) + + defer func() { + t.Log("terminating container") + err := c.Terminate(ctx) + if err != nil { + t.Fatal(err) + } + t.Log("terminated container") + }() +} + func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { ctx := context.Background() req := ContainerRequest{ diff --git a/testresources/args.Dockerfile b/testresources/args.Dockerfile new file mode 100644 index 0000000000..79aee5a3ea --- /dev/null +++ b/testresources/args.Dockerfile @@ -0,0 +1,11 @@ +FROM golang:1.13-alpine + +ARG FOO + +ENV FOO=$FOO + +WORKDIR /app + +COPY argsserver.go . + +CMD go run argsserver.go diff --git a/testresources/argsserver.go b/testresources/argsserver.go new file mode 100644 index 0000000000..53ea1b6c9c --- /dev/null +++ b/testresources/argsserver.go @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + "net" + "net/http" + "os" +) + +func envHandler() http.HandlerFunc { + return func(rw http.ResponseWriter, req *http.Request) { + + rw.Write([]byte(os.Getenv("FOO"))) + + rw.WriteHeader(http.StatusAccepted) + } +} + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/env", envHandler()) + + ln, err := net.Listen("tcp", ":8080") + if err != nil { + panic(err) + } + + fmt.Println("ready") + + http.Serve(ln, mux) +} From e7b4a89707dcad624f747d448f1a18c413d5a1a3 Mon Sep 17 00:00:00 2001 From: Xico Date: Tue, 13 Apr 2021 17:03:10 -0300 Subject: [PATCH 028/219] rebase --- container.go | 4 ++-- testresources/args.Dockerfile | 4 ++-- testresources/argsserver.go | 31 ------------------------------- testresources/echoserver.go | 10 ++++++++++ 4 files changed, 14 insertions(+), 35 deletions(-) delete mode 100644 testresources/argsserver.go diff --git a/container.go b/container.go index 65e524a882..535ad041fd 100644 --- a/container.go +++ b/container.go @@ -91,8 +91,8 @@ type ContainerRequest struct { ReaperImage string // alternative reaper image AutoRemove bool // if set to true, the container will be removed from the host when stopped NetworkMode container.NetworkMode - AlwaysPullImage bool // Always pull image - BuildArgs map[string]*string // for specifying network aliases + AlwaysPullImage bool // Always pull image + BuildArgs map[string]*string } // ProviderType is an enum for the possible providers diff --git a/testresources/args.Dockerfile b/testresources/args.Dockerfile index 79aee5a3ea..0260639719 100644 --- a/testresources/args.Dockerfile +++ b/testresources/args.Dockerfile @@ -6,6 +6,6 @@ ENV FOO=$FOO WORKDIR /app -COPY argsserver.go . +COPY echoserver.go . -CMD go run argsserver.go +CMD go run echoserver.go diff --git a/testresources/argsserver.go b/testresources/argsserver.go deleted file mode 100644 index 53ea1b6c9c..0000000000 --- a/testresources/argsserver.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "fmt" - "net" - "net/http" - "os" -) - -func envHandler() http.HandlerFunc { - return func(rw http.ResponseWriter, req *http.Request) { - - rw.Write([]byte(os.Getenv("FOO"))) - - rw.WriteHeader(http.StatusAccepted) - } -} - -func main() { - mux := http.NewServeMux() - mux.HandleFunc("/env", envHandler()) - - ln, err := net.Listen("tcp", ":8080") - if err != nil { - panic(err) - } - - fmt.Println("ready") - - http.Serve(ln, mux) -} diff --git a/testresources/echoserver.go b/testresources/echoserver.go index dd9e1a863c..0ab8d5c31f 100644 --- a/testresources/echoserver.go +++ b/testresources/echoserver.go @@ -8,6 +8,15 @@ import ( "os" ) +func envHandler() http.HandlerFunc { + return func(rw http.ResponseWriter, req *http.Request) { + + rw.Write([]byte(os.Getenv("FOO"))) + + rw.WriteHeader(http.StatusAccepted) + } +} + func echoHandler(destination *os.File) http.HandlerFunc { return func(rw http.ResponseWriter, req *http.Request) { echo := req.URL.Query()["echo"][0] @@ -26,6 +35,7 @@ func main() { mux := http.NewServeMux() mux.HandleFunc("/stdout", echoHandler(os.Stdout)) mux.HandleFunc("/stderr", echoHandler(os.Stderr)) + mux.HandleFunc("/env", envHandler()) ln, err := net.Listen("tcp", ":8080") if err != nil { From 1bb9c4dcae2cc702d745470daa1663c023d001e3 Mon Sep 17 00:00:00 2001 From: Xico Date: Tue, 13 Apr 2021 18:32:11 -0300 Subject: [PATCH 029/219] moving BuildArgs inside FromDockerfile struct --- container.go | 4 ++-- docker_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/container.go b/container.go index 535ad041fd..671446e95d 100644 --- a/container.go +++ b/container.go @@ -66,6 +66,7 @@ type FromDockerfile struct { Context string // the path to the context of of the docker build ContextArchive io.Reader // the tar archive file to send to docker that contains the build context Dockerfile string // the path from the context to the Dockerfile for the image, defaults to "Dockerfile" + BuildArgs map[string]*string // } // ContainerRequest represents the parameters used to get a running container @@ -92,7 +93,6 @@ type ContainerRequest struct { AutoRemove bool // if set to true, the container will be removed from the host when stopped NetworkMode container.NetworkMode AlwaysPullImage bool // Always pull image - BuildArgs map[string]*string } // ProviderType is an enum for the possible providers @@ -152,7 +152,7 @@ func (c *ContainerRequest) GetContext() (io.Reader, error) { // GetBuildArgs returns the env args to be used when creating from Dockerfile func (c *ContainerRequest) GetBuildArgs() map[string]*string { - return c.BuildArgs + return c.FromDockerfile.BuildArgs } // GetDockerfile returns the Dockerfile from the ContainerRequest, defaults to "Dockerfile" diff --git a/docker_test.go b/docker_test.go index f67a32226b..3e772450b3 100644 --- a/docker_test.go +++ b/docker_test.go @@ -904,9 +904,9 @@ func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { FromDockerfile: FromDockerfile{ Context: "./testresources", Dockerfile: "args.Dockerfile", - }, - BuildArgs: map[string]*string{ - "FOO": &ba, + BuildArgs: map[string]*string{ + "FOO": &ba, + }, }, ExposedPorts: []string{"8080/tcp"}, WaitingFor: wait.ForLog("ready"), From 14513ceb8741336c9e9eb03c94e0ba2b1a8ba4a3 Mon Sep 17 00:00:00 2001 From: Xico Date: Tue, 13 Apr 2021 18:33:51 -0300 Subject: [PATCH 030/219] polish --- container.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/container.go b/container.go index 671446e95d..8d3a9a3077 100644 --- a/container.go +++ b/container.go @@ -63,9 +63,9 @@ type ImageBuildInfo interface { // FromDockerfile represents the parameters needed to build an image from a Dockerfile // rather than using a pre-built one type FromDockerfile struct { - Context string // the path to the context of of the docker build - ContextArchive io.Reader // the tar archive file to send to docker that contains the build context - Dockerfile string // the path from the context to the Dockerfile for the image, defaults to "Dockerfile" + Context string // the path to the context of of the docker build + ContextArchive io.Reader // the tar archive file to send to docker that contains the build context + Dockerfile string // the path from the context to the Dockerfile for the image, defaults to "Dockerfile" BuildArgs map[string]*string // } From ef6d7560707a1224a62df1357c5db204b432e198 Mon Sep 17 00:00:00 2001 From: Xico Date: Wed, 14 Apr 2021 12:27:03 -0300 Subject: [PATCH 031/219] documenting build args usecase --- docs/features/build_from_dockerfile.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/features/build_from_dockerfile.md b/docs/features/build_from_dockerfile.md index 96440f9fd5..d5378b0726 100644 --- a/docs/features/build_from_dockerfile.md +++ b/docs/features/build_from_dockerfile.md @@ -16,6 +16,27 @@ req := ContainerRequest{ } ``` +If your Dockerfile expects build args: + +```Dockerfile +FROM alpine + +ARG FOO + +``` +You can specify them like: + +```go +req := ContainerRequest{ + FromDockerfile: testcontainers.FromDockerfile{ + Context: "/path/to/build/context", + Dockerfile: "CustomDockerfile", + BuildArgs: map[string]*string { + "FOO": "BAR", + }, + }, + } +``` ## Dynamic Build Context If you would like to send a build context that you created in code (maybe you have a dynamic Dockerfile), you can From bb63b8ca1a713fc7dd7d7e55282af8b6b120a4c0 Mon Sep 17 00:00:00 2001 From: Xico Date: Tue, 20 Apr 2021 18:35:45 -0300 Subject: [PATCH 032/219] Add support for users to enable Dockerfile build log to be printed in stdout --- container.go | 8 +++++++- docker.go | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/container.go b/container.go index 8d3a9a3077..b7b5e55398 100644 --- a/container.go +++ b/container.go @@ -56,6 +56,7 @@ type Container interface { type ImageBuildInfo interface { GetContext() (io.Reader, error) // the path to the build context GetDockerfile() string // the relative path to the Dockerfile, including the fileitself + ShouldPrintBuildLog() bool // allow build log to be printed to stdout ShouldBuildImage() bool // return true if the image needs to be built GetBuildArgs() map[string]*string // return the environment args used to build the from Dockerfile } @@ -66,7 +67,8 @@ type FromDockerfile struct { Context string // the path to the context of of the docker build ContextArchive io.Reader // the tar archive file to send to docker that contains the build context Dockerfile string // the path from the context to the Dockerfile for the image, defaults to "Dockerfile" - BuildArgs map[string]*string // + BuildArgs map[string]*string // enable user to pass build args to docker daemon + PrintBuildLog bool // enable user to print build log } // ContainerRequest represents the parameters used to get a running container @@ -169,6 +171,10 @@ func (c *ContainerRequest) ShouldBuildImage() bool { return c.FromDockerfile.Context != "" || c.FromDockerfile.ContextArchive != nil } +func (c *ContainerRequest) ShouldPrintBuildLog() bool { + return c.FromDockerfile.PrintBuildLog +} + func (c *ContainerRequest) validateContextAndImage() error { if c.FromDockerfile.Context != "" && c.Image != "" { return errors.New("you cannot specify both an Image and Context in a ContainerRequest") diff --git a/docker.go b/docker.go index 7a83f7a70e..3b9c847e60 100644 --- a/docker.go +++ b/docker.go @@ -23,8 +23,10 @@ import ( "github.com/docker/docker/api/types/network" "github.com/docker/docker/client" "github.com/docker/docker/errdefs" + "github.com/docker/docker/pkg/jsonmessage" "github.com/docker/go-connections/nat" "github.com/google/uuid" + "github.com/moby/term" "github.com/pkg/errors" "github.com/testcontainers/testcontainers-go/wait" @@ -470,6 +472,14 @@ func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (st return "", err } + if img.ShouldPrintBuildLog() { + termFd, isTerm := term.GetFdInfo(os.Stderr) + err = jsonmessage.DisplayJSONMessagesStream(resp.Body, os.Stderr, termFd, isTerm, nil) + if err != nil { + return "", err + } + } + // need to read the response from Docker, I think otherwise the image // might not finish building before continuing to execute here buf := new(bytes.Buffer) From df36248f54ba50f3d5346432aeac3ddb5046b23f Mon Sep 17 00:00:00 2001 From: Xico Date: Wed, 21 Apr 2021 14:00:20 -0300 Subject: [PATCH 033/219] add test case --- docker_test.go | 49 +++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 4 +++ testresources/buildlog.Dockerfile | 1 + 4 files changed, 55 insertions(+) create mode 100644 testresources/buildlog.Dockerfile diff --git a/docker_test.go b/docker_test.go index 3e772450b3..3de0994687 100644 --- a/docker_test.go +++ b/docker_test.go @@ -9,6 +9,7 @@ import ( "io/ioutil" "math/rand" "net/http" + "os" "os/exec" "path/filepath" "strings" @@ -953,6 +954,54 @@ func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { }() } +func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { + rescueStdout := os.Stderr + r, w, _ := os.Pipe() + os.Stderr = w + + t.Log("getting ctx") + ctx := context.Background() + t.Log("got ctx, creating container request") + + req := ContainerRequest{ + FromDockerfile: FromDockerfile{ + Context: "./testresources", + Dockerfile: "buildlog.Dockerfile", + PrintBuildLog: true, + }, + } + + genContainerReq := GenericContainerRequest{ + ContainerRequest: req, + Started: true, + } + + c, err := GenericContainer(ctx, genContainerReq) + + if err != nil { + t.Fatal(err) + } + + defer func() { + t.Log("terminating container") + err := c.Terminate(ctx) + if err != nil { + t.Fatal(err) + } + t.Log("terminated container") + }() + + w.Close() + out, _ := ioutil.ReadAll(r) + os.Stdout = rescueStdout + temp := strings.Split(string(out), "\n") + + if temp[0] != "Step 1/1 : FROM alpine" { + t.Errorf("Expected stout firstline to be %s. Got '%s'.", "Step 1/2 : FROM alpine", temp[0]) + } + +} + func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { ctx := context.Background() req := ContainerRequest{ diff --git a/go.mod b/go.mod index bc5f964907..af7db08894 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/google/uuid v1.2.0 github.com/moby/sys/mount v0.2.0 // indirect + github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index 30fb3bc1db..50de4835b5 100644 --- a/go.sum +++ b/go.sum @@ -185,6 +185,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= @@ -402,6 +403,8 @@ github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2J github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd h1:aY7OQNf2XqY/JQ6qREWamhI/81os/agb2BAGpcx5yWI= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -701,6 +704,7 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/testresources/buildlog.Dockerfile b/testresources/buildlog.Dockerfile new file mode 100644 index 0000000000..67fd379018 --- /dev/null +++ b/testresources/buildlog.Dockerfile @@ -0,0 +1 @@ +FROM alpine From bc6fdab92dd3c623ad6654bf301b1a659efeb50e Mon Sep 17 00:00:00 2001 From: Ryan Fitzpatrick Date: Fri, 21 May 2021 14:03:19 +0000 Subject: [PATCH 034/219] Retry follow logs request on closed connection --- docker.go | 12 +++++++++++- logconsumer_test.go | 9 ++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/docker.go b/docker.go index f8a913b87e..e0ca5e6521 100644 --- a/docker.go +++ b/docker.go @@ -337,10 +337,14 @@ func (c *DockerContainer) CopyFileToContainer(ctx context.Context, hostFilePath // from the container and will send them to each added LogConsumer func (c *DockerContainer) StartLogProducer(ctx context.Context) error { go func() { + since := "" + // if the socket is closed we will make additional logs request with updated Since timestamp + BEGIN: options := types.ContainerLogsOptions{ ShowStdout: true, ShowStderr: true, Follow: true, + Since: since, } ctx, cancel := context.WithTimeout(ctx, time.Second*5) @@ -366,6 +370,12 @@ func (c *DockerContainer) StartLogProducer(ctx context.Context) error { h := make([]byte, 8) _, err := r.Read(h) if err != nil { + // proper type matching requires https://go-review.googlesource.com/c/go/+/250357/ (go 1.16) + if strings.Contains(err.Error(), "use of closed connection") { + now := time.Now() + since = fmt.Sprintf("%d.%09d", now.Unix(), int64(now.Nanosecond())) + goto BEGIN + } // this explicitly ignores errors // because we want to keep procesing even if one of our reads fails continue @@ -377,7 +387,7 @@ func (c *DockerContainer) StartLogProducer(ctx context.Context) error { } logType := h[0] if logType > 2 { - panic(fmt.Sprintf("received inavlid log type: %d", logType)) + panic(fmt.Sprintf("received invalid log type: %d", logType)) } // a map of the log type --> int representation in the header, notice the first is blank, this is stdin, but the go docker client doesn't allow following that in logs diff --git a/logconsumer_test.go b/logconsumer_test.go index 11f636b91d..0994cd552d 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "testing" + "time" "github.com/testcontainers/testcontainers-go/wait" "gotest.tools/assert" @@ -81,12 +82,18 @@ func Test_LogConsumerGetsCalled(t *testing.T) { t.Fatal(err) } + time.Sleep(10 * time.Second) + _, err = http.Get(ep + fmt.Sprintf("/stdout?echo=%s", lastMessage)) if err != nil { t.Fatal(err) } - <-g.Ack + select { + case <-g.Ack: + case <-time.After(5 * time.Second): + t.Fatal("never received final log message") + } c.StopLogProducer() // get rid of the server "ready" log From bcd260932996384bd67a30e9df73db9d23337e2b Mon Sep 17 00:00:00 2001 From: Mohammed Salman Date: Sat, 5 Jun 2021 21:25:23 +0300 Subject: [PATCH 035/219] Fix misspelling --- docs/quickstart/gotest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/quickstart/gotest.md b/docs/quickstart/gotest.md index 93186523c1..fce5ae7522 100644 --- a/docs/quickstart/gotest.md +++ b/docs/quickstart/gotest.md @@ -44,7 +44,7 @@ look. ready to receive any traffic. In this, case we check for the logs we know come from Redis, telling us that it is ready to accept requests. -When you use `ExposedPorts` you have to image yourself using `docker run -p +When you use `ExposedPorts` you have to imagine yourself using `docker run -p `. When you do so, `dockerd` maps the selected `` from inside the container to a random one available on your host. From 108656d8d56d78d2d0b0748328e6e28a52ed9b5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 11 Jun 2021 15:53:17 +0200 Subject: [PATCH 036/219] chore: add a test demonstrating the bug --- compose_test.go | 22 +++++++++++++++++++ .../docker-compose-no-exposed-ports.yml | 6 +++++ 2 files changed, 28 insertions(+) create mode 100644 testresources/docker-compose-no-exposed-ports.yml diff --git a/compose_test.go b/compose_test.go index 02e42a3d72..3045e7b79c 100644 --- a/compose_test.go +++ b/compose_test.go @@ -178,6 +178,28 @@ func TestDockerComposeWithWaitHTTPStrategy(t *testing.T) { assert.Contains(t, compose.Services, "nginx") } +func TestDockerComposeWithWaitStrategy_NoExposedPorts(t *testing.T) { + path := "./testresources/docker-compose-no-exposed-ports.yml" + + identifier := strings.ToLower(uuid.New().String()) + + compose := NewLocalDockerCompose([]string{path}, identifier) + destroyFn := func() { + err := compose.Down() + checkIfError(t, err) + } + defer destroyFn() + + err := compose. + WithCommand([]string{"up", "-d"}). + WithExposedService("nginx_1", 9080, wait.ForLog("Configuration complete; ready for start up")). + Invoke() + checkIfError(t, err) + + assert.Equal(t, 1, len(compose.Services)) + assert.Contains(t, compose.Services, "nginx") +} + func TestDockerComposeWithMultipleWaitStrategies(t *testing.T) { path := "./testresources/docker-compose-complex.yml" diff --git a/testresources/docker-compose-no-exposed-ports.yml b/testresources/docker-compose-no-exposed-ports.yml new file mode 100644 index 0000000000..ba8565c512 --- /dev/null +++ b/testresources/docker-compose-no-exposed-ports.yml @@ -0,0 +1,6 @@ +version: '3' +services: + nginx: + image: nginx:stable-alpine + ports: + - "80" From 847d29762ac83ee52518c75e115130e394d60840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 11 Jun 2021 15:53:47 +0200 Subject: [PATCH 037/219] fix: filter containers by compose service name --- compose.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compose.go b/compose.go index af1283661b..355b110823 100644 --- a/compose.go +++ b/compose.go @@ -10,7 +10,6 @@ import ( "os/exec" "path/filepath" "runtime" - "strconv" "strings" "sync" @@ -117,7 +116,7 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { // as we cannot delegate to the names generated by Docker Compose containerName := dc.Identifier + "_" + k.service // Docker compose appends "_1" to every started service by default. Trimming to match running docker container - f := filters.NewArgs(filters.Arg("name", containerName), filters.Arg("publish", strconv.Itoa(k.publishedPort))) + f := filters.NewArgs(filters.Arg("name", containerName)) containerListOptions := types.ContainerListOptions{Filters: f} containers, err := cli.ContainerList(context.Background(), containerListOptions) if err != nil { From 5a8a601a98ca210c866b91094bd95177002681cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 11 Jun 2021 15:54:09 +0200 Subject: [PATCH 038/219] chore: run go mod tidy --- go.mod | 2 +- go.sum | 33 ++------------------------------- 2 files changed, 3 insertions(+), 32 deletions(-) diff --git a/go.mod b/go.mod index af7db08894..d485066d23 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/google/uuid v1.2.0 github.com/moby/sys/mount v0.2.0 // indirect - github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect + github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index 50de4835b5..72f43f6c43 100644 --- a/go.sum +++ b/go.sum @@ -37,24 +37,18 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3 h1:mw6pDQqv38/WGF1cO/jF5t/jyAJ2yi7CmtFLLO5tGFI= github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7 h1:ptnOoufxGSzauVTsdE+wMYnCWA301PdoN4xg5oRdZpg= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= -github.com/Microsoft/hcsshim v0.8.9 h1:VrfodqvztU8YSOvygU+DN1BGaSGxmrNfqOv5oOuX2Bk= github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= -github.com/Microsoft/hcsshim v0.8.15 h1:Aof83YILRs2Vx3GhHqlvvfyx1asRJKMFIMeVlHsZKtI= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16 h1:8/auA4LFIZFTGrqfKhGBSXwM6/4X1fHa/xniyEHu8ac= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= @@ -105,11 +99,9 @@ github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s= github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102 h1:Qf4HiqfvmB7zS6scsmNgTLmByHbq8n9RTF39v+TzP7A= github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68 h1:hkGVFjz+plgr5UfxZUTPFbUFIF/Km6/s+RVRIRHLrrY= github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= @@ -123,20 +115,16 @@ github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.1 h1:pASeJT3R3YyVn+94qEPk0SnU1OQ20Jd/T+SPKy9xehY= github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.5.0-beta.1 h1:IK6yirB4X7wpKyFSikWiT++nZsyIxGAAgNEv3fEGuls= github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= github.com/containerd/containerd v1.5.0-beta.4 h1:zjz4MOAOFgdBlwid2nNUlJ3YLpVi/97L36lfMYJex60= github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7 h1:6ejg6Lkk8dskcM7wQ28gONkukbQkM4qpj4RnYbpFzrI= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e h1:6JKvHHt396/qabvMhnhUZvWaHZzfVfldxE60TK8YLhg= github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= @@ -185,6 +173,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= @@ -199,12 +188,10 @@ github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible h1:dvc1KSkIYTVjZgHf/CTC2diTYC8PzhaA5sFISRfNVrE= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.5+incompatible h1:o5WL5onN4awYGwrW7+oTn5x9AF2prw7V0Ox8ZEkoCdg= -github.com/docker/docker v20.10.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.6+incompatible h1:oXI3Vas8TI8Eu/EjH4srKHJBVqraSzJybhxY7Om9faQ= github.com/docker/docker v20.10.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= @@ -265,7 +252,6 @@ github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -294,7 +280,6 @@ github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:x github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= @@ -307,7 +292,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -343,7 +327,6 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -396,12 +379,10 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= -github.com/moby/sys/mountinfo v0.4.0 h1:1KInV3Huv18akCu58V7lzNlt+jFmqlu1EaErnEHE/VM= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= -github.com/moby/term v0.0.0-20200312100748-672ec06f55cd h1:aY7OQNf2XqY/JQ6qREWamhI/81os/agb2BAGpcx5yWI= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= @@ -432,7 +413,6 @@ github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -441,7 +421,6 @@ github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= @@ -556,7 +535,6 @@ go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= @@ -617,7 +595,6 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09 h1:KaQtG+aDELoNmXYas3TVkGNYRuq8JQ1aa7LJt8EXVyo= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= @@ -650,13 +627,10 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -713,7 +687,6 @@ golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -810,7 +783,6 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4 google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -873,7 +845,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= From 399c0a6a84439243fbc3b2daa1011f0283e5caeb Mon Sep 17 00:00:00 2001 From: DPR Date: Thu, 17 Jun 2021 10:21:13 +0430 Subject: [PATCH 039/219] [REN]: #271 inspectContainerFresh --- docker.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker.go b/docker.go index 1c658fc9f5..1f1966d480 100644 --- a/docker.go +++ b/docker.go @@ -187,7 +187,7 @@ func (c *DockerContainer) Terminate(ctx context.Context) error { } // update container raw info -func (c *DockerContainer) inspectContainerFresh(ctx context.Context) (*types.ContainerJSON, error) { +func (c *DockerContainer) inspectRawContainer(ctx context.Context) (*types.ContainerJSON, error) { inspect, err := c.provider.client.ContainerInspect(ctx, c.ID) if err != nil { return nil, err @@ -238,7 +238,7 @@ func (c *DockerContainer) Name(ctx context.Context) (string, error) { // State returns container's running state func (c *DockerContainer) State(ctx context.Context) (*types.ContainerState, error) { - inspect, err := c.inspectContainerFresh(ctx) + inspect, err := c.inspectRawContainer(ctx) if err != nil { return c.raw.State, err } From 4e380c2a17f9c47d690f3d197d64999fe4ad06b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Jun 2021 12:05:32 +0000 Subject: [PATCH 040/219] chore(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 20.10.6+incompatible to 20.10.7+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Changelog](https://github.com/moby/moby/blob/master/CHANGELOG.md) - [Commits](https://github.com/docker/docker/compare/v20.10.6...v20.10.7) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d485066d23..f9a9e86752 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.13 require ( github.com/Microsoft/hcsshim v0.8.16 // indirect github.com/cenkalti/backoff v2.2.1+incompatible - github.com/docker/docker v20.10.6+incompatible + github.com/docker/docker v20.10.7+incompatible github.com/docker/go-connections v0.4.0 github.com/go-redis/redis v6.15.9+incompatible github.com/go-sql-driver/mysql v1.6.0 diff --git a/go.sum b/go.sum index 72f43f6c43..f7ba7b649b 100644 --- a/go.sum +++ b/go.sum @@ -191,8 +191,8 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.6+incompatible h1:oXI3Vas8TI8Eu/EjH4srKHJBVqraSzJybhxY7Om9faQ= -github.com/docker/docker v20.10.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ= +github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= From 157eed356c73484f59c9b1cc37bceaa27f5ada57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 21 Jul 2021 12:09:52 +0200 Subject: [PATCH 041/219] fix: store raw information of a container --- docker.go | 1 + 1 file changed, 1 insertion(+) diff --git a/docker.go b/docker.go index db948604fd..12dc8fe8cd 100644 --- a/docker.go +++ b/docker.go @@ -52,6 +52,7 @@ type DockerContainer struct { terminationSignal chan bool skipReaper bool consumers []LogConsumer + raw *types.ContainerJSON stopProducer chan bool } From 3f7261c5991953ece67bbb7cd08aaf4f251376f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 21 Jul 2021 13:37:01 +0200 Subject: [PATCH 042/219] chore: skip flaky test --- logconsumer_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/logconsumer_test.go b/logconsumer_test.go index 0994cd552d..b251349e40 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -28,6 +28,7 @@ func (g *TestLogConsumer) Accept(l Log) { } func Test_LogConsumerGetsCalled(t *testing.T) { + t.Skip("This test is randomly failing for different versions of Go") /* send one request at a time to a server that will print whatever was sent in the "echo" parameter, the log From 4cc8593a9341bf500323ea665c52804a47ccdeb8 Mon Sep 17 00:00:00 2001 From: Jake Son Date: Sun, 25 Jul 2021 16:17:18 +0900 Subject: [PATCH 043/219] Update README.md - Add link to CI badge - Change link of GoDoc --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4884d805d0..da76151e0e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ -![Main pipeline](https://github.com/testcontainers/testcontainers-go/workflows/Main%20pipeline/badge.svg?branch=master) +[![Main pipeline](https://github.com/testcontainers/testcontainers-go/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/testcontainers/testcontainers-go/actions/workflows/ci.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/testcontainers/testcontainers-go)](https://goreportcard.com/report/github.com/testcontainers/testcontainers-go) -[![GoDoc Reference](https://camo.githubusercontent.com/8609cfcb531fa0f5598a3d4353596fae9336cce3/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f79616e6777656e6d61692f686f772d746f2d6164642d62616467652d696e2d6769746875622d726561646d653f7374617475732e737667)](https://godoc.org/github.com/testcontainers/testcontainers-go) - +[![GoDoc Reference](https://camo.githubusercontent.com/8609cfcb531fa0f5598a3d4353596fae9336cce3/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f79616e6777656e6d61692f686f772d746f2d6164642d62616467652d696e2d6769746875622d726561646d653f7374617475732e737667)](https://pkg.go.dev/github.com/testcontainers/testcontainers-go) When I was working on a Zipkin PR I discovered a nice Java library called [Testcontainers](https://www.testcontainers.org/). From d1fd5fc93b03079e285c89e76930f3338596b9a5 Mon Sep 17 00:00:00 2001 From: Brian Candler Date: Thu, 29 Jul 2021 10:50:39 +0100 Subject: [PATCH 044/219] Change t.Error() to t.Fatal() in example --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4884d805d0..8bc555dab5 100644 --- a/README.md +++ b/README.md @@ -39,20 +39,20 @@ func TestNginxLatestReturn(t *testing.T) { Started: true, }) if err != nil { - t.Error(err) + t.Fatal(err) } defer nginxC.Terminate(ctx) ip, err := nginxC.Host(ctx) if err != nil { - t.Error(err) + t.Fatal(err) } port, err := nginxC.MappedPort(ctx, "80") if err != nil { - t.Error(err) + t.Fatal(err) } resp, err := http.Get(fmt.Sprintf("http://%s:%s", ip, port.Port())) if resp.StatusCode != http.StatusOK { - t.Errorf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) + t.Fatalf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) } } ``` From 3296c238b66e22c96532ff9d3da4517f90acc923 Mon Sep 17 00:00:00 2001 From: Anthony Casagrande Date: Tue, 3 Aug 2021 22:23:14 -0700 Subject: [PATCH 045/219] fix: cache http wait request body See https://github.com/testcontainers/testcontainers-go/issues/338 Closes #338 Signed-off-by: Anthony Casagrande --- wait/http.go | 12 +++++++++++- wait/http_test.go | 5 +++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/wait/http.go b/wait/http.go index f882dca1a6..206f51afb3 100644 --- a/wait/http.go +++ b/wait/http.go @@ -1,6 +1,7 @@ package wait import ( + "bytes" "context" "crypto/tls" "errors" @@ -184,12 +185,21 @@ func (ws *HTTPStrategy) WaitUntilReady(ctx context.Context, target StrategyTarge address := net.JoinHostPort(ipAddress, strconv.Itoa(port.Int())) endpoint := fmt.Sprintf("%s://%s%s", proto, address, ws.Path) + // cache the body into a byte-slice so that it can be iterated over multiple times + var body []byte + if ws.Body != nil { + body, err = io.ReadAll(ws.Body) + if err != nil { + return + } + } + for { select { case <-ctx.Done(): return ctx.Err() case <-time.After(ws.PollInterval): - req, err := http.NewRequestWithContext(ctx, ws.Method, endpoint, ws.Body) + req, err := http.NewRequestWithContext(ctx, ws.Method, endpoint, bytes.NewReader(body)) if err != nil { return err } diff --git a/wait/http_test.go b/wait/http_test.go index a3a34431e1..9e0e3aa8b4 100644 --- a/wait/http_test.go +++ b/wait/http_test.go @@ -62,6 +62,7 @@ func TestHTTPStrategyWaitUntilReady(t *testing.T) { } tlsconfig := &tls.Config{RootCAs: certpool, ServerName: "testcontainer.go.test"} + var i int dockerReq := testcontainers.ContainerRequest{ FromDockerfile: testcontainers.FromDockerfile{ Context: workdir + "/testdata", @@ -73,6 +74,10 @@ func TestHTTPStrategyWaitUntilReady(t *testing.T) { data, _ := ioutil.ReadAll(body) return bytes.Equal(data, []byte("pong")) }). + WithStatusCodeMatcher(func(status int) bool { + i++ // always fail the first try in order to force the polling loop to be re-run + return i > 1 && status == 200 + }). WithMethod(http.MethodPost).WithBody(bytes.NewReader([]byte("ping"))), } From 9409b6f613fa4797dca60b99a0d5b89dda71b8c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Aug 2021 11:22:23 +0000 Subject: [PATCH 046/219] chore(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 20.10.7+incompatible to 20.10.8+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Changelog](https://github.com/moby/moby/blob/master/CHANGELOG.md) - [Commits](https://github.com/docker/docker/compare/v20.10.7...v20.10.8) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f9a9e86752..381c4789d5 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.13 require ( github.com/Microsoft/hcsshim v0.8.16 // indirect github.com/cenkalti/backoff v2.2.1+incompatible - github.com/docker/docker v20.10.7+incompatible + github.com/docker/docker v20.10.8+incompatible github.com/docker/go-connections v0.4.0 github.com/go-redis/redis v6.15.9+incompatible github.com/go-sql-driver/mysql v1.6.0 diff --git a/go.sum b/go.sum index f7ba7b649b..a3eea45e1a 100644 --- a/go.sum +++ b/go.sum @@ -191,8 +191,8 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ= -github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.8+incompatible h1:RVqD337BgQicVCzYrrlhLDWhq6OAD2PJDUg2LsEUvKM= +github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= From 993745537a00193a04501e87a7852a09eb168f37 Mon Sep 17 00:00:00 2001 From: Anthony Casagrande Date: Wed, 4 Aug 2021 09:22:28 -0700 Subject: [PATCH 047/219] fix: change io.ReadAll to ioutil.ReadAll Signed-off-by: Anthony Casagrande --- wait/http.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wait/http.go b/wait/http.go index 206f51afb3..9315991c51 100644 --- a/wait/http.go +++ b/wait/http.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "net" "net/http" "strconv" @@ -188,7 +189,7 @@ func (ws *HTTPStrategy) WaitUntilReady(ctx context.Context, target StrategyTarge // cache the body into a byte-slice so that it can be iterated over multiple times var body []byte if ws.Body != nil { - body, err = io.ReadAll(ws.Body) + body, err = ioutil.ReadAll(ws.Body) if err != nil { return } From 2af1d3a02f5572a51d010790304822c4ba7a537f Mon Sep 17 00:00:00 2001 From: Anthony Casagrande Date: Wed, 4 Aug 2021 11:14:12 -0700 Subject: [PATCH 048/219] fix: pin rabbitmq to version 3.8.19 in network_test Signed-off-by: Anthony Casagrande --- network_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network_test.go b/network_test.go index ab136b86b0..d2aaae971b 100644 --- a/network_test.go +++ b/network_test.go @@ -84,7 +84,7 @@ func Test_MultipleContainersInTheNewNetwork(t *testing.T) { hp := wait.ForListeningPort("5672/tcp") hp.WithStartupTimeout(3 * time.Minute) amqpRequest := ContainerRequest{ - Image: "rabbitmq:management-alpine", + Image: "rabbitmq:3.8.19-management-alpine", ExposedPorts: []string{"15672/tcp", "5672/tcp"}, Env: env, AutoRemove: true, From 6db66f017fd472f1e6586dd2d260bb4889afee35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Thu, 12 Aug 2021 13:08:25 +0200 Subject: [PATCH 049/219] chore: add WaitForService method to compose We are providing a simple API to wait for services by service name, only --- compose.go | 8 ++++++++ compose_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/compose.go b/compose.go index 355b110823..882cd0ad50 100644 --- a/compose.go +++ b/compose.go @@ -29,6 +29,7 @@ const ( type DockerCompose interface { Down() ExecError Invoke() ExecError + WaitForService(string, wait.Strategy) DockerCompose WithCommand([]string) DockerCompose WithEnv(map[string]string) DockerCompose WithExposedService(string, int, wait.Strategy) DockerCompose @@ -151,6 +152,13 @@ func (dc *LocalDockerCompose) Invoke() ExecError { return executeCompose(dc, dc.Cmd) } +// WaitForService sets the strategy for the service that is to be waited on +func (dc *LocalDockerCompose) WaitForService(service string, strategy wait.Strategy) DockerCompose { + dc.waitStrategySupplied = true + dc.WaitStrategyMap[waitService{service: service}] = strategy + return dc +} + // WithCommand assigns the command func (dc *LocalDockerCompose) WithCommand(cmd []string) DockerCompose { dc.Cmd = cmd diff --git a/compose_test.go b/compose_test.go index 3045e7b79c..106a035b1f 100644 --- a/compose_test.go +++ b/compose_test.go @@ -153,6 +153,31 @@ func TestDockerComposeWithWaitLogStrategy(t *testing.T) { assert.Contains(t, compose.Services, "mysql") } +func TestDockerComposeWithWaitForService(t *testing.T) { + path := "./testresources/docker-compose-simple.yml" + + identifier := strings.ToLower(uuid.New().String()) + + compose := NewLocalDockerCompose([]string{path}, identifier) + destroyFn := func() { + err := compose.Down() + checkIfError(t, err) + } + defer destroyFn() + + err := compose. + WithCommand([]string{"up", "-d"}). + WithEnv(map[string]string{ + "bar": "BAR", + }). + WaitForService("nginx_1", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). + Invoke() + checkIfError(t, err) + + assert.Equal(t, 1, len(compose.Services)) + assert.Contains(t, compose.Services, "nginx") +} + func TestDockerComposeWithWaitHTTPStrategy(t *testing.T) { path := "./testresources/docker-compose-simple.yml" From 6c124344d9f6f1d454f72706dcf47475fade3acb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Thu, 12 Aug 2021 13:27:12 +0200 Subject: [PATCH 050/219] docs: add users of testcontainers-go --- docs/index.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/index.md b/docs/index.md index cf096dbb36..83792d2f29 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,6 +16,9 @@ Inline documentation and docs where the code live is crucial for us. Go has a nice support for them and we use Examples as well. Check it out [pkg.go.dev/github.com/testcontainers/testcontainers-go](https://pkg.go.dev/github.com/testcontainers/testcontainers-go?tab=doc). +## Who is using Testcontainers Go? +* [Elastic](https://www.elastic.co) - Testing of the APM Server, and E2E testing for Beats + ## License See [LICENSE](https://github.com/testcontainers/testcontainers-go/blob/master/LICENSE). From 9369edb55707e2f83ade07b75e3a8e7f13e4a3bf Mon Sep 17 00:00:00 2001 From: Robson Roberto Souza Peixoto <124390+robsonpeixoto@users.noreply.github.com> Date: Mon, 16 Aug 2021 13:19:01 -0300 Subject: [PATCH 051/219] typo: 10 minutes -> 10 seconds --- docs/features/garbage_collector.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/garbage_collector.md b/docs/features/garbage_collector.md index 0f0be7afe7..1ffaa4051d 100644 --- a/docs/features/garbage_collector.md +++ b/docs/features/garbage_collector.md @@ -35,7 +35,7 @@ tests requires running, there is another one called `ryuk`. We refer to it as `Reaper` as well in this library. Based on container labels it removes resources created from testcontainers that -are running for more than 10 minutes. +are running for more than 10 seconds. !!!tip From 03594b367e9b26e22e7a054cde5fb98f7c3b8799 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Aug 2021 07:22:43 +0000 Subject: [PATCH 052/219] chore(deps): bump github.com/google/uuid from 1.2.0 to 1.3.0 Bumps [github.com/google/uuid](https://github.com/google/uuid) from 1.2.0 to 1.3.0. - [Release notes](https://github.com/google/uuid/releases) - [Commits](https://github.com/google/uuid/compare/v1.2.0...v1.3.0) --- updated-dependencies: - dependency-name: github.com/google/uuid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 381c4789d5..690270f2f4 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/docker/go-connections v0.4.0 github.com/go-redis/redis v6.15.9+incompatible github.com/go-sql-driver/mysql v1.6.0 - github.com/google/uuid v1.2.0 + github.com/google/uuid v1.3.0 github.com/moby/sys/mount v0.2.0 // indirect github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect diff --git a/go.sum b/go.sum index a3eea45e1a..9f42210d22 100644 --- a/go.sum +++ b/go.sum @@ -307,8 +307,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= From 8bc13326904d5337183fe4f8f3893c249cb87fe5 Mon Sep 17 00:00:00 2001 From: codepitbull Date: Tue, 17 Aug 2021 13:38:29 +0200 Subject: [PATCH 053/219] Added CopyFileFromContainer to DcokerContainer to allow retrieving files from a container --- container.go | 1 + docker.go | 24 ++++++++++++++++++++++++ docker_test.go | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/container.go b/container.go index 51b3d68927..b032151a23 100644 --- a/container.go +++ b/container.go @@ -52,6 +52,7 @@ type Container interface { Exec(ctx context.Context, cmd []string) (int, error) ContainerIP(context.Context) (string, error) // get container ip CopyFileToContainer(ctx context.Context, hostFilePath string, containerFilePath string, fileMode int64) error + CopyFileFromContainer(ctx context.Context, filePath string) ([]byte, error) } // ImageBuildInfo defines what is needed to build an image diff --git a/docker.go b/docker.go index 12dc8fe8cd..c1a531e99a 100644 --- a/docker.go +++ b/docker.go @@ -334,6 +334,30 @@ func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, error) { return exitCode, nil } +func (c *DockerContainer) CopyFileFromContainer(ctx context.Context, filePath string) ([]byte, error) { + r, _, err := c.provider.client.CopyFromContainer(ctx, c.ID, filePath) + if err != nil { + return nil, err + } + defer r.Close() + + tr := tar.NewReader(r) + for { + _, err := tr.Next() + if err == io.EOF { + // end of tar archive + return []byte{}, nil + } + if err != nil { + return nil, err + } + buf := new(bytes.Buffer) + buf.ReadFrom(tr) + + return buf.Bytes(), nil + } +} + func (c *DockerContainer) CopyFileToContainer(ctx context.Context, hostFilePath string, containerFilePath string, fileMode int64) error { fileContent, err := ioutil.ReadFile(hostFilePath) if err != nil { diff --git a/docker_test.go b/docker_test.go index 3de0994687..04bebf34c8 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1455,6 +1455,40 @@ func TestDockerContainerCopyFileToContainer(t *testing.T) { } } +func TestDockerContainerCopyFileFromContainer(t *testing.T) { + fileContent, err := ioutil.ReadFile("./testresources/hello.sh") + if err != nil { + t.Fatal(err) + } + ctx := context.Background() + + nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: ContainerRequest{ + Image: "nginx:1.17.6", + ExposedPorts: []string{"80/tcp"}, + WaitingFor: wait.ForListeningPort("80/tcp"), + }, + Started: true, + }) + defer nginxC.Terminate(ctx) + + copiedFileName := "hello_copy.sh" + nginxC.CopyFileToContainer(ctx, "./testresources/hello.sh", "/"+copiedFileName, 700) + c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) + if err != nil { + t.Fatal(err) + } + if c != 0 { + t.Fatalf("File %s should exist, expected return code 0, got %v", copiedFileName, c) + } + + fileContentFromContainer, err := nginxC.CopyFileFromContainer(ctx, "/"+copiedFileName) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, fileContent, fileContentFromContainer) +} + func TestContainerWithReaperNetwork(t *testing.T) { ctx := context.Background() networks := []string{ From 602d86c609a0c15cc182d036be25237fc5774ac8 Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Thu, 19 Aug 2021 12:13:48 +0800 Subject: [PATCH 054/219] Fix default network is not initialize when get gateway ip --- docker.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docker.go b/docker.go index 12dc8fe8cd..f6f63f7987 100644 --- a/docker.go +++ b/docker.go @@ -892,6 +892,13 @@ func (p *DockerProvider) GetNetwork(ctx context.Context, req NetworkRequest) (ty func (p *DockerProvider) GetGatewayIP(ctx context.Context) (string, error) { // Use a default network as defined in the DockerProvider + var err error + if p.defaultNetwork == "" { + p.defaultNetwork, err = getDefaultNetwork(ctx, p.client) + if err != nil { + return "", err + } + } nw, err := p.GetNetwork(ctx, NetworkRequest{Name: p.defaultNetwork}) if err != nil { return "", err From 5dfa6126641d46da9cc43a219c8bd4cf597edcd5 Mon Sep 17 00:00:00 2001 From: Mrproliu Date: Thu, 19 Aug 2021 14:54:50 +0800 Subject: [PATCH 055/219] fix issue --- docker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker.go b/docker.go index f6f63f7987..668b9d5f72 100644 --- a/docker.go +++ b/docker.go @@ -892,8 +892,8 @@ func (p *DockerProvider) GetNetwork(ctx context.Context, req NetworkRequest) (ty func (p *DockerProvider) GetGatewayIP(ctx context.Context) (string, error) { // Use a default network as defined in the DockerProvider - var err error if p.defaultNetwork == "" { + var err error p.defaultNetwork, err = getDefaultNetwork(ctx, p.client) if err != nil { return "", err From 0963bddbb383968c7dd6c88ea0bf721048ffa5eb Mon Sep 17 00:00:00 2001 From: dalekliuhan Date: Fri, 20 Aug 2021 16:55:45 +0800 Subject: [PATCH 056/219] Add UT --- docker_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docker_test.go b/docker_test.go index 3de0994687..ebbf122680 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1506,6 +1506,18 @@ func TestContainerWithReaperNetwork(t *testing.T) { assert.NotNil(t, cnt.NetworkSettings.Networks[networks[1]]) } +func TestGetGatewayIP(t *testing.T) { + // When using docker-compose with DinD mode, and using host port or http wait strategy + // It's need to invoke GetGatewayIP for get the host + provider, err := NewDockerProvider() + if err != nil { + t.Fatal(err) + } + if _, err := provider.GetGatewayIP(context.Background()); err != nil { + t.Fatal(err) + } +} + func randomString() string { rand.Seed(time.Now().UnixNano()) chars := []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + From 46cf72abc7a70529a1c372ad0f265f82f324af1e Mon Sep 17 00:00:00 2001 From: dalekliuhan Date: Fri, 20 Aug 2021 17:54:17 +0800 Subject: [PATCH 057/219] verify the ip address is not empty --- docker_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docker_test.go b/docker_test.go index ebbf122680..011e16b85f 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1513,9 +1513,13 @@ func TestGetGatewayIP(t *testing.T) { if err != nil { t.Fatal(err) } - if _, err := provider.GetGatewayIP(context.Background()); err != nil { + ip, err := provider.GetGatewayIP(context.Background()) + if err != nil { t.Fatal(err) } + if ip == "" { + t.Fatal("could not get gateway ip") + } } func randomString() string { From 3792295fdefdc8b545312e644db84d54ef7541d7 Mon Sep 17 00:00:00 2001 From: Jochen Mader Date: Tue, 24 Aug 2021 21:35:10 +0200 Subject: [PATCH 058/219] Changed siganture to return a ReadCloser --- container.go | 2 +- docker.go | 41 ++++++++++++++++++++++++++--------------- docker_test.go | 42 +++++++++++++++++++++++++++++++++++++++++- testresources/empty.sh | 0 4 files changed, 68 insertions(+), 17 deletions(-) create mode 100644 testresources/empty.sh diff --git a/container.go b/container.go index b032151a23..64ee0f2c08 100644 --- a/container.go +++ b/container.go @@ -52,7 +52,7 @@ type Container interface { Exec(ctx context.Context, cmd []string) (int, error) ContainerIP(context.Context) (string, error) // get container ip CopyFileToContainer(ctx context.Context, hostFilePath string, containerFilePath string, fileMode int64) error - CopyFileFromContainer(ctx context.Context, filePath string) ([]byte, error) + CopyFileFromContainer(ctx context.Context, filePath string) (io.ReadCloser, error) } // ImageBuildInfo defines what is needed to build an image diff --git a/docker.go b/docker.go index c1a531e99a..d931d4ca79 100644 --- a/docker.go +++ b/docker.go @@ -334,28 +334,39 @@ func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, error) { return exitCode, nil } -func (c *DockerContainer) CopyFileFromContainer(ctx context.Context, filePath string) ([]byte, error) { +type FileFromContainer struct { + underlying *io.ReadCloser + tarreader *tar.Reader +} + +func (fc *FileFromContainer) Read(b []byte) (int, error) { + return (*fc.tarreader).Read(b) +} + +func (fc *FileFromContainer) Close() error { + return (*fc.underlying).Close() +} + +func (c *DockerContainer) CopyFileFromContainer(ctx context.Context, filePath string) (io.ReadCloser, error) { r, _, err := c.provider.client.CopyFromContainer(ctx, c.ID, filePath) if err != nil { return nil, err } - defer r.Close() + tarReader := tar.NewReader(r) - tr := tar.NewReader(r) - for { - _, err := tr.Next() - if err == io.EOF { - // end of tar archive - return []byte{}, nil - } - if err != nil { - return nil, err - } - buf := new(bytes.Buffer) - buf.ReadFrom(tr) + //if we got here we have exactly one file in the TAR-stream + //so we advance the index by one so the next call to Read will start reading it + _, err = tarReader.Next() + if err != nil { + return nil, err + } - return buf.Bytes(), nil + ret := &FileFromContainer{ + underlying: &r, + tarreader: tarReader, } + + return ret, nil } func (c *DockerContainer) CopyFileToContainer(ctx context.Context, hostFilePath string, containerFilePath string, fileMode int64) error { diff --git a/docker_test.go b/docker_test.go index 04bebf34c8..ac521a0587 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1482,13 +1482,53 @@ func TestDockerContainerCopyFileFromContainer(t *testing.T) { t.Fatalf("File %s should exist, expected return code 0, got %v", copiedFileName, c) } - fileContentFromContainer, err := nginxC.CopyFileFromContainer(ctx, "/"+copiedFileName) + reader, err := nginxC.CopyFileFromContainer(ctx, "/"+copiedFileName) + if err != nil { + t.Fatal(err) + } + + fileContentFromContainer, err := ioutil.ReadAll(reader) if err != nil { t.Fatal(err) } assert.Equal(t, fileContent, fileContentFromContainer) } +func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { + ctx := context.Background() + + nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: ContainerRequest{ + Image: "nginx:1.17.6", + ExposedPorts: []string{"80/tcp"}, + WaitingFor: wait.ForListeningPort("80/tcp"), + }, + Started: true, + }) + defer nginxC.Terminate(ctx) + + copiedFileName := "hello_copy.sh" + nginxC.CopyFileToContainer(ctx, "./testresources/empty.sh", "/"+copiedFileName, 700) + c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) + if err != nil { + t.Fatal(err) + } + if c != 0 { + t.Fatalf("File %s should exist, expected return code 0, got %v", copiedFileName, c) + } + + reader, err := nginxC.CopyFileFromContainer(ctx, "/"+copiedFileName) + if err != nil { + t.Fatal(err) + } + + fileContentFromContainer, err := ioutil.ReadAll(reader) + if err != nil { + t.Fatal(err) + } + assert.Empty(t, fileContentFromContainer) +} + func TestContainerWithReaperNetwork(t *testing.T) { ctx := context.Background() networks := []string{ diff --git a/testresources/empty.sh b/testresources/empty.sh new file mode 100644 index 0000000000..e69de29bb2 From 28d20caa48630a79ce08e597f0fd73ccb1695238 Mon Sep 17 00:00:00 2001 From: Jochen Mader Date: Thu, 9 Sep 2021 22:33:02 +0200 Subject: [PATCH 059/219] go fmt --- docker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker.go b/docker.go index d931d4ca79..083a3ecc3a 100644 --- a/docker.go +++ b/docker.go @@ -336,7 +336,7 @@ func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, error) { type FileFromContainer struct { underlying *io.ReadCloser - tarreader *tar.Reader + tarreader *tar.Reader } func (fc *FileFromContainer) Read(b []byte) (int, error) { From ad31c406df92a3560329018732e29dee4cbfbc63 Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Fri, 10 Sep 2021 20:29:33 -0700 Subject: [PATCH 060/219] cleaned up readme --- README.md | 63 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index c175bf5008..0d8aa8cd36 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,11 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/testcontainers/testcontainers-go)](https://goreportcard.com/report/github.com/testcontainers/testcontainers-go) [![GoDoc Reference](https://camo.githubusercontent.com/8609cfcb531fa0f5598a3d4353596fae9336cce3/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f79616e6777656e6d61692f686f772d746f2d6164642d62616467652d696e2d6769746875622d726561646d653f7374617475732e737667)](https://pkg.go.dev/github.com/testcontainers/testcontainers-go) -When I was working on a Zipkin PR I discovered a nice Java library called -[Testcontainers](https://www.testcontainers.org/). +Testcontainers-Go is a package that makes it simple to set up container-based dependencies for automated +integration/smoke tests. The clean, easy-to-use API enables developers to programmatically define containers that should be +run as part of a test and clean up those resources when the test is done. -It provides an easy and clean API over the go docker sdk to run, terminate and -connect to containers in your tests. - -I found myself comfortable programmatically writing the containers I need to run -an integration/smoke tests. So I started porting this library in Go. - -This is an example: +Here's an example of a test that spins up an NGINX container and executes an HTTP request against it: ```go package main @@ -26,44 +21,62 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) -func TestNginxLatestReturn(t *testing.T) { - ctx := context.Background() +type nginxContainer struct { + testcontainer.Container + URI string +} + +func setupNginx(ctx context.Context) { req := testcontainers.ContainerRequest{ Image: "nginx", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/"), } - nginxC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, }) if err != nil { - t.Fatal(err) + return nil, err } - defer nginxC.Terminate(ctx) - ip, err := nginxC.Host(ctx) + + ip, err := container.Host(ctx) if err != nil { - t.Fatal(err) + return nil, err } - port, err := nginxC.MappedPort(ctx, "80") + + mappedPort, err := container.MappedPort(ctx, "80") if err != nil { + return nil, err + } + + uri := fmt.Sprintf("http://%s:%s", ip, mappedPort.Port()) + + return &nginxContainer{Container: container, URI: uri}, nil +} + +func TestNginxLatestReturn(t *testing.T) { + ctx := context.Background() + + nginxC, err := setupNginx(ctx) + if (err != nil) { t.Fatal(err) } - resp, err := http.Get(fmt.Sprintf("http://%s:%s", ip, port.Port())) + + // Clean up the container after the test is complete + defer nginxC.Terminate(ctx) + + resp, err := http.Get(nginxC.URI) if resp.StatusCode != http.StatusOK { t.Fatalf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) } } ``` -This is a simple example, you can create one container in my case using the -`nginx` image. You can get its IP `ip, err := nginxC.GetContainerIpAddress(ctx)` and you -can use it to make a GET: `resp, err := http.Get(fmt.Sprintf("http://%s", ip))` -To clean your environment you can defer the container termination `defer -nginxC.Terminate(ctx, t)`. `t` is `*testing.T` and it is used to notify is the -`defer` failed marking the test as failed. +Cleaning up your environment after test completion should be accomplished by deferring the container termination, e.g +`defer nginxC.Terminate(ctx)`. Ryuk (Reaper) is also enabled by default to help clean up. ## Documentation -The documentation lives in [./docs](./docs) and it is rendered at +More information about TestContainers-Go can be found in [./docs](./docs), which rendered at [golang.testcontainers.org](https://golang.testcontainers.org). From 25fc53e2585109a09188824c41b7c90b09716c93 Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Fri, 10 Sep 2021 21:50:03 -0700 Subject: [PATCH 061/219] added examples directory per #112 --- .gitignore | 1 + README.md | 14 ++-- docs/examples/cockroachdb.md | 142 +++++++++++++++++++++++++++++++++++ docs/examples/nginx.md | 69 +++++++++++++++++ docs/examples/redis.md | 97 ++++++++++++++++++++++++ docs/modules.md | 26 ------- mkdocs.yml | 5 +- 7 files changed, 322 insertions(+), 32 deletions(-) create mode 100644 docs/examples/cockroachdb.md create mode 100644 docs/examples/nginx.md create mode 100644 docs/examples/redis.md delete mode 100644 docs/modules.md diff --git a/.gitignore b/.gitignore index 5f986a390d..9c2bea3d5d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,6 @@ site/ src/mkdocs-codeinclude-plugin src/pip-delete-this-directory.txt .idea/ +.DS_Store cover.txt diff --git a/README.md b/README.md index 0d8aa8cd36..cfefeb14f9 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ import ( ) type nginxContainer struct { - testcontainer.Container + testcontainers.Container URI string } -func setupNginx(ctx context.Context) { +func setupNginx(ctx context.Context) (*nginxContainer, error) { req := testcontainers.ContainerRequest{ Image: "nginx", ExposedPorts: []string{"80/tcp"}, @@ -55,11 +55,15 @@ func setupNginx(ctx context.Context) { return &nginxContainer{Container: container, URI: uri}, nil } -func TestNginxLatestReturn(t *testing.T) { +func TestIntegrationNginxLatestReturn(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + ctx := context.Background() nginxC, err := setupNginx(ctx) - if (err != nil) { + if err != nil { t.Fatal(err) } @@ -74,7 +78,7 @@ func TestNginxLatestReturn(t *testing.T) { ``` Cleaning up your environment after test completion should be accomplished by deferring the container termination, e.g -`defer nginxC.Terminate(ctx)`. Ryuk (Reaper) is also enabled by default to help clean up. +`defer nginxC.Terminate(ctx)`. Reaper (Ryuk) is also enabled by default to help clean up. ## Documentation diff --git a/docs/examples/cockroachdb.md b/docs/examples/cockroachdb.md new file mode 100644 index 0000000000..802999de81 --- /dev/null +++ b/docs/examples/cockroachdb.md @@ -0,0 +1,142 @@ +# CockroachDB Container Example +```go +package main + +import ( + "context" + "database/sql" + "fmt" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" + _ "github.com/jackc/pgx/v4/stdlib" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +// Task represents a unit of work to complete. We're going to be using this in our example as a way to organize data +// that is being manipulated in the database. +type task struct { + ID string `json:"id"` + Description string `json:"description"` + DateDue *time.Time `json:"date_due,string"` + DateCreated time.Time `json:"date_created,string"` + DateUpdated time.Time `json:"date_updated"` +} + +type cockroachDBContainer struct { + testcontainers.Container + URI string +} + +func setupCockroachDB(ctx context.Context) (*cockroachDBContainer, error) { + req := testcontainers.ContainerRequest{ + Image: "cockroachdb/cockroach:latest-v21.1", + ExposedPorts: []string{"26257/tcp", "8080/tcp"}, + WaitingFor: wait.ForHTTP("/health").WithPort("8080"), + Cmd: []string{"start-single-node", "--insecure"}, + } + container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + return nil, err + } + + mappedPort, err := container.MappedPort(ctx, "26257") + if err != nil { + return nil, err + } + + hostIP, err := container.Host(ctx) + if err != nil { + return nil, err + } + + uri := fmt.Sprintf("postgres://root@%s:%s", hostIP, mappedPort.Port()) + + return &cockroachDBContainer{Container: container, URI: uri}, nil +} + +func initCockroachDB(ctx context.Context, db sql.DB) error { + // Actual SQL for initializing the database should probably live elsewhere; this is just an example + const query = `CREATE DATABASE projectmanagement; + CREATE TABLE projectmanagement.task( + id uuid primary key not null, + description varchar(255) not null, + date_due timestamp with time zone, + date_created timestamp with time zone not null, + date_updated timestamp with time zone not null);` + _, err := db.ExecContext(ctx, query) + + return err +} + +func truncateCockroachDB(ctx context.Context, db sql.DB) error { + const query = `TRUNCATE projectmanagement.task` + _, err := db.ExecContext(ctx, query) + return err +} + +func TestIntegrationDBInsertSelect(t *testing.T) { + if testing.Short() { + t.Skip("Skipping integration test") + } + + ctx := context.Background() + + cdbContainer, err := setupCockroachDB(ctx) + if err != nil { + t.Fatal(err) + } + defer cdbContainer.Terminate(ctx) + + db, err := sql.Open("pgx", cdbContainer.URI+"/projectmanagement") + if err != nil { + t.Fatal(err) + } + defer db.Close() + + err = initCockroachDB(ctx, *db) + if err != nil { + t.Fatal(err) + } + defer truncateCockroachDB(ctx, *db) + + now := time.Now() + + // Insert data + tsk := task{ID: uuid.NewString(), Description: "Update resumé", DateCreated: now, DateUpdated: now} + const insertQuery = `insert into "task" (id, description, date_due, date_created, date_updated) + values ($1, $2, $3, $4, $5)` + _, err = db.ExecContext( + ctx, + insertQuery, + tsk.ID, + tsk.Description, + tsk.DateDue, + tsk.DateCreated, + tsk.DateUpdated) + if err != nil { + t.Fatal(err) + } + + // Select data + savedTsk := task{ID: tsk.ID} + const findQuery = `select description, date_due, date_created, date_updated + from task + where id = $1` + row := db.QueryRowContext(ctx, findQuery, tsk.ID) + err = row.Scan(&savedTsk.Description, &savedTsk.DateDue, &savedTsk.DateCreated, &savedTsk.DateUpdated) + if err != nil { + t.Fatal(err) + } + + if !cmp.Equal(tsk, savedTsk) { + t.Fatalf("Saved task is not the same:\n%s", cmp.Diff(tsk, savedTsk)) + } +} +``` diff --git a/docs/examples/nginx.md b/docs/examples/nginx.md new file mode 100644 index 0000000000..27f21e0c00 --- /dev/null +++ b/docs/examples/nginx.md @@ -0,0 +1,69 @@ +# NGINX Container Example +```go +package main + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +type nginxContainer struct { + testcontainers.Container + URI string +} + +func setupNginx(ctx context.Context) (*nginxContainer, error) { + req := testcontainers.ContainerRequest{ + Image: "nginx", + ExposedPorts: []string{"80/tcp"}, + WaitingFor: wait.ForHTTP("/"), + } + container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + return nil, err + } + + ip, err := container.Host(ctx) + if err != nil { + return nil, err + } + + mappedPort, err := container.MappedPort(ctx, "80") + if err != nil { + return nil, err + } + + uri := fmt.Sprintf("http://%s:%s", ip, mappedPort.Port()) + + return &nginxContainer{Container: container, URI: uri}, nil +} + +func TestIntegrationNginxLatestReturn(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + + ctx := context.Background() + + nginxC, err := setupNginx(ctx) + if err != nil { + t.Fatal(err) + } + + // Clean up the container after the test is complete + defer nginxC.Terminate(ctx) + + resp, err := http.Get(nginxC.URI) + if resp.StatusCode != http.StatusOK { + t.Fatalf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) + } +} +``` diff --git a/docs/examples/redis.md b/docs/examples/redis.md new file mode 100644 index 0000000000..7a93024b74 --- /dev/null +++ b/docs/examples/redis.md @@ -0,0 +1,97 @@ +# Redis Container Example +```go +package main + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/google/uuid" + _ "github.com/jackc/pgx/v4/stdlib" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" + + "github.com/go-redis/redis/v8" +) + +type redisContainer struct { + testcontainers.Container + URI string +} + +func setupRedis(ctx context.Context) (*redisContainer, error) { + req := testcontainers.ContainerRequest{ + Image: "redis:6", + ExposedPorts: []string{"6379/tcp"}, + WaitingFor: wait.ForLog("* Ready to accept connections"), + } + container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + return nil, err + } + + mappedPort, err := container.MappedPort(ctx, "6379") + if err != nil { + return nil, err + } + + hostIP, err := container.Host(ctx) + if err != nil { + return nil, err + } + + uri := fmt.Sprintf("redis://%s:%s", hostIP, mappedPort.Port()) + + return &redisContainer{Container: container, URI: uri}, nil +} + +func flushRedis(ctx context.Context, client redis.Client) error { + return client.FlushAll(ctx).Err() +} + +func TestIntegrationSetGet(t *testing.T) { + if testing.Short() { + t.Skip("Skipping integration test") + } + + ctx := context.Background() + + redisContainer, err := setupRedis(ctx) + if err != nil { + t.Fatal(err) + } + defer redisContainer.Terminate(ctx) + + // You'd likely want to wrap your Redis package of choice in an interface to aid in unit testing and limit lock-in + // throughtout your codebase but that's out of scope for this example + options, err := redis.ParseURL(redisContainer.URI) + if err != nil { + t.Fatal(err) + } + client := redis.NewClient(options) + defer flushRedis(ctx, *client) + + // Set data + key := fmt.Sprintf("{user.%s}.favoritefood", uuid.NewString()) + value := "Cabbage Biscuits" + ttl, _ := time.ParseDuration("2h") + err = client.Set(ctx, key, value, ttl).Err() + if err != nil { + t.Fatal(err) + } + + // Get data + savedValue, err := client.Get(ctx, key).Result() + if err != nil { + t.Fatal(err) + } + if savedValue != value { + t.Fatalf("Expected value %s. Got %s.", savedValue, value) + } +} +``` diff --git a/docs/modules.md b/docs/modules.md deleted file mode 100644 index 615ea85893..0000000000 --- a/docs/modules.md +++ /dev/null @@ -1,26 +0,0 @@ -TestContainers Java has the concept of -[modules](https://www.testcontainers.org/modules/nginx/). - -Those modules are reusable and pre-defined Container for popular projects. - -I don't think we are ready to do the same for Go just yet. I proposed a similar -concept called `canned`, mainly to avoid misunderstanding with [Go -modules](https://blog.golang.org/using-go-modules). - -* [Canned postgres #98](https://github.com/testcontainers/testcontainers-go/pull/98) -* [Canned minio #105](https://github.com/testcontainers/testcontainers-go/pull/105) -* [Canned MongoDB #102](https://github.com/testcontainers/testcontainers-go/pull/102) - -Submodules in Go are not easy to maintain today and I want to keep -testcontainers dependencies under control and the project light. If we start -merging modules as part of the main repository we will get one dependency at -least for each of them. This will blow up quickly adding overheard to the -maintainers of this project as well. - -## Share your modules - -I know it is important to share code because it makes a project battle tested. -You can create your own modules and you can list them here, in this way other -users will be able to import and reuse your work and experience in the meantime -that we figure out a better solution based as well on how many modules we will -get. diff --git a/mkdocs.yml b/mkdocs.yml index 5936db4863..3b29c16cbb 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -31,7 +31,10 @@ nav: - features/docker_compose.md - features/follow_logs.md - features/override_container_command.md - - Modules: modules.md + - Examples: + - examples/cockroachdb.md + - examples/nginx.md + - examples/redis.md - Contributing: - contributing.md - contributing_docs.md From 10d4959abadc8170ff962872cd94a011a144f84e Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Fri, 10 Sep 2021 22:13:06 -0700 Subject: [PATCH 062/219] minor update to README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cfefeb14f9..49dbc39ca2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/testcontainers/testcontainers-go)](https://goreportcard.com/report/github.com/testcontainers/testcontainers-go) [![GoDoc Reference](https://camo.githubusercontent.com/8609cfcb531fa0f5598a3d4353596fae9336cce3/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f79616e6777656e6d61692f686f772d746f2d6164642d62616467652d696e2d6769746875622d726561646d653f7374617475732e737667)](https://pkg.go.dev/github.com/testcontainers/testcontainers-go) -Testcontainers-Go is a package that makes it simple to set up container-based dependencies for automated +Testcontainers-Go is a Go package that makes it simple to set up container-based dependencies for automated integration/smoke tests. The clean, easy-to-use API enables developers to programmatically define containers that should be run as part of a test and clean up those resources when the test is done. From 18b4534c0ae2dbe69c0f1c6133a42e454b9c56ed Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Fri, 10 Sep 2021 22:34:43 -0700 Subject: [PATCH 063/219] formatting and fixes to create container docs --- README.md | 8 +-- docs/examples/cockroachdb.md | 1 + docs/examples/nginx.md | 1 + docs/examples/redis.md | 1 + docs/features/creating_container.md | 85 +++++++++++++++++++---------- 5 files changed, 64 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 49dbc39ca2..415d18e4c5 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/testcontainers/testcontainers-go)](https://goreportcard.com/report/github.com/testcontainers/testcontainers-go) [![GoDoc Reference](https://camo.githubusercontent.com/8609cfcb531fa0f5598a3d4353596fae9336cce3/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f79616e6777656e6d61692f686f772d746f2d6164642d62616467652d696e2d6769746875622d726561646d653f7374617475732e737667)](https://pkg.go.dev/github.com/testcontainers/testcontainers-go) -Testcontainers-Go is a Go package that makes it simple to set up container-based dependencies for automated -integration/smoke tests. The clean, easy-to-use API enables developers to programmatically define containers that should be -run as part of a test and clean up those resources when the test is done. +Testcontainers-Go is a Go package that makes it simple to create and clean up container-based dependencies for +automated integration/smoke tests. The clean, easy-to-use API enables developers to programmatically define containers +that should be run as part of a test and clean up those resources when the test is done. -Here's an example of a test that spins up an NGINX container and executes an HTTP request against it: +Here's an example of a test that spins up an NGINX container validates that it returns 200 for the status code: ```go package main diff --git a/docs/examples/cockroachdb.md b/docs/examples/cockroachdb.md index 802999de81..c8550816a6 100644 --- a/docs/examples/cockroachdb.md +++ b/docs/examples/cockroachdb.md @@ -1,4 +1,5 @@ # CockroachDB Container Example + ```go package main diff --git a/docs/examples/nginx.md b/docs/examples/nginx.md index 27f21e0c00..237b3fab14 100644 --- a/docs/examples/nginx.md +++ b/docs/examples/nginx.md @@ -1,4 +1,5 @@ # NGINX Container Example + ```go package main diff --git a/docs/examples/redis.md b/docs/examples/redis.md index 7a93024b74..9d460be3fe 100644 --- a/docs/examples/redis.md +++ b/docs/examples/redis.md @@ -1,4 +1,5 @@ # Redis Container Example + ```go package main diff --git a/docs/features/creating_container.md b/docs/features/creating_container.md index 229e2e665b..3dc106ae40 100644 --- a/docs/features/creating_container.md +++ b/docs/features/creating_container.md @@ -1,54 +1,83 @@ # How to create a container -When I have to describe TestContainer I say: "it is a wrapper around the docker -daemon designed for tests." - -This libraries demands all the complexity of creating and managing container to -Docker to stay focused on usability in a testing environment. - -You can use this library to run everything you can run with docker: - -* NoSQL databases or other data stores (e.g. redis, elasticsearch, mongo) -* Web servers/proxies (e.g. nginx, apache) -* Log services (e.g. logstash, kibana) +Testcontainers are a wrapper around the Docker daemon designed for tests. Anything you can run in Docker, you can spin +up with Testcontainers and integrate into your tests: +* NoSQL databases or other data stores (e.g. Redis, ElasticSearch, MongoDB) +* Web servers/proxies (e.g. NGINX, Apache) +* Log services (e.g. Logstash, Kibana) * Other services developed by your team/organization which are already dockerized ## GenericContainer -`testcontainers.GenericContainer` identifies the ability to spin up a single -container, you can look at it as a different way to create a `docker run` -command. +`testcontainers.GenericContainer` defines the container that should be run, similar to the `docker run` command. + +The following test creates an NGINX container and validates that it returns 200 for the status code: ```go -func TestNginxLatestReturn(t *testing.T) { - ctx := context.Background() +package main + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +type nginxContainer struct { + testcontainers.Container + URI string +} + +func setupNginx(ctx context.Context) (*nginxContainer, error) { req := testcontainers.ContainerRequest{ Image: "nginx", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/"), } - nginxC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, }) if err != nil { - t.Error(err) + return nil, err } - defer nginxC.Terminate(ctx) - ip, err := nginxC.Host(ctx) + + ip, err := container.Host(ctx) if err != nil { - t.Error(err) + return nil, err } - port, err := nginxC.MappedPort(ctx, "80") + + mappedPort, err := container.MappedPort(ctx, "80") if err != nil { - t.Error(err) + return nil, err } - resp, err := http.Get(fmt.Sprintf("http://%s:%s", ip, port.Port())) + + uri := fmt.Sprintf("http://%s:%s", ip, mappedPort.Port()) + + return &nginxContainer{Container: container, URI: uri}, nil +} + +func TestIntegrationNginxLatestReturn(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + + ctx := context.Background() + + nginxC, err := setupNginx(ctx) + if err != nil { + t.Fatal(err) + } + + // Clean up the container after the test is complete + defer nginxC.Terminate(ctx) + + resp, err := http.Get(nginxC.URI) if resp.StatusCode != http.StatusOK { - t.Errorf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) + t.Fatalf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) } } ``` - -This test creates an Nginx container and it validates that it returns a 200 as -StatusCode. From f23b4f7f4802abbd47a01d3a0e69b257300c2355 Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Fri, 10 Sep 2021 22:35:42 -0700 Subject: [PATCH 064/219] fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 415d18e4c5..52e1eae300 100644 --- a/README.md +++ b/README.md @@ -82,5 +82,5 @@ Cleaning up your environment after test completion should be accomplished by def ## Documentation -More information about TestContainers-Go can be found in [./docs](./docs), which rendered at +More information about TestContainers-Go can be found in [./docs](./docs), which is rendered at [golang.testcontainers.org](https://golang.testcontainers.org). From 3d6fd1cbc71492f4eada72ef90476d19b1b702a3 Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Fri, 10 Sep 2021 22:39:56 -0700 Subject: [PATCH 065/219] updated headings --- docs/examples/cockroachdb.md | 2 +- docs/examples/nginx.md | 2 +- docs/examples/redis.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/examples/cockroachdb.md b/docs/examples/cockroachdb.md index c8550816a6..353deed602 100644 --- a/docs/examples/cockroachdb.md +++ b/docs/examples/cockroachdb.md @@ -1,4 +1,4 @@ -# CockroachDB Container Example +# CockroachDB ```go package main diff --git a/docs/examples/nginx.md b/docs/examples/nginx.md index 237b3fab14..59c2cd8985 100644 --- a/docs/examples/nginx.md +++ b/docs/examples/nginx.md @@ -1,4 +1,4 @@ -# NGINX Container Example +# NGINX ```go package main diff --git a/docs/examples/redis.md b/docs/examples/redis.md index 9d460be3fe..789eb2ca14 100644 --- a/docs/examples/redis.md +++ b/docs/examples/redis.md @@ -1,4 +1,4 @@ -# Redis Container Example +# Redis ```go package main From 552e00cac15dbf70f84984d2c188ed867b28b021 Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Fri, 10 Sep 2021 22:46:39 -0700 Subject: [PATCH 066/219] updated comments so that they fit better in the code pane --- docs/examples/cockroachdb.md | 7 ++++--- docs/examples/redis.md | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/examples/cockroachdb.md b/docs/examples/cockroachdb.md index 353deed602..7700bbd75a 100644 --- a/docs/examples/cockroachdb.md +++ b/docs/examples/cockroachdb.md @@ -17,8 +17,9 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) -// Task represents a unit of work to complete. We're going to be using this in our example as a way to organize data -// that is being manipulated in the database. +// Task represents a unit of work to complete. We're going to be using this in +// our example as a way to organize data that is being manipulated in +// the database. type task struct { ID string `json:"id"` Description string `json:"description"` @@ -63,7 +64,7 @@ func setupCockroachDB(ctx context.Context) (*cockroachDBContainer, error) { } func initCockroachDB(ctx context.Context, db sql.DB) error { - // Actual SQL for initializing the database should probably live elsewhere; this is just an example + // Actual SQL for initializing the database should probably live elsewhere const query = `CREATE DATABASE projectmanagement; CREATE TABLE projectmanagement.task( id uuid primary key not null, diff --git a/docs/examples/redis.md b/docs/examples/redis.md index 789eb2ca14..7085d572bc 100644 --- a/docs/examples/redis.md +++ b/docs/examples/redis.md @@ -68,8 +68,9 @@ func TestIntegrationSetGet(t *testing.T) { } defer redisContainer.Terminate(ctx) - // You'd likely want to wrap your Redis package of choice in an interface to aid in unit testing and limit lock-in - // throughtout your codebase but that's out of scope for this example + // You will likely want to wrap your Redis package of choice in an + // interface to aid in unit testing and limit lock-in throughtout your + // codebase but that's out of scope for this example options, err := redis.ParseURL(redisContainer.URI) if err != nil { t.Fatal(err) From 5e143ccb5d1fbce3c04de232438d4362b9c621ad Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Fri, 10 Sep 2021 22:53:15 -0700 Subject: [PATCH 067/219] improved import order for redis example after running through the formatter --- docs/examples/redis.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/examples/redis.md b/docs/examples/redis.md index 7085d572bc..290fba3a40 100644 --- a/docs/examples/redis.md +++ b/docs/examples/redis.md @@ -9,12 +9,11 @@ import ( "testing" "time" + "github.com/go-redis/redis/v8" "github.com/google/uuid" _ "github.com/jackc/pgx/v4/stdlib" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" - - "github.com/go-redis/redis/v8" ) type redisContainer struct { @@ -69,8 +68,8 @@ func TestIntegrationSetGet(t *testing.T) { defer redisContainer.Terminate(ctx) // You will likely want to wrap your Redis package of choice in an - // interface to aid in unit testing and limit lock-in throughtout your - // codebase but that's out of scope for this example + // interface to aid in unit testing and limit lock-in throughtout your + // codebase but that's out of scope for this example options, err := redis.ParseURL(redisContainer.URI) if err != nil { t.Fatal(err) From 8a1e71ed4dcfd5eec40473d0a91a51578b1680a3 Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Fri, 10 Sep 2021 22:55:11 -0700 Subject: [PATCH 068/219] switched to em dash --- docs/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.md b/docs/contributing.md index 2ec8e9cb94..e509eb0bff 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -1,4 +1,4 @@ # Contributing -We follow the same guidelines used by testcontainers-java - please [check them +We follow the same guidelines used by testcontainers-java -- please [check them out](https://www.testcontainers.org/contributing/). From c58a8d80254c3cf3fc4cde4cabcbcb8c1fce8206 Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Fri, 10 Sep 2021 23:02:01 -0700 Subject: [PATCH 069/219] updated index --- docs/index.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/index.md b/docs/index.md index cf096dbb36..c9729ab985 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,17 +4,18 @@ ## About -TestContainers is popular in Java, but there are other languages as well. This -is the Go implementation. +Testcontainers-Go is a Go package that makes it simple to create and clean up container-based dependencies for +automated integration/smoke tests. The clean, easy-to-use API enables developers to programmatically define containers +that should be run as part of a test and clean up those resources when the test is done. -The project is opensource and you can have a look at the code on +This project is opensource and you can have a look at the code on [GitHub](https://github.com/testcontainers/testcontainers-go). ## GoDoc -Inline documentation and docs where the code live is crucial for us. Go has a -nice support for them and we use Examples as well. Check it out -[pkg.go.dev/github.com/testcontainers/testcontainers-go](https://pkg.go.dev/github.com/testcontainers/testcontainers-go?tab=doc). +Inline documentation and docs where the code live is crucial for us. Go has nice support for them and we provide +examples as well. Check it out at +[pkg.go.dev/github.com/testcontainers/testcontainers-go](https://pkg.go.dev/github.com/testcontainers/testcontainers-go). ## License @@ -22,6 +23,5 @@ See [LICENSE](https://github.com/testcontainers/testcontainers-go/blob/master/LI ## Copyright -Copyright (c) 2018-2020 Gianluca Arbezzano and other authors. -Checkout our [lovely -contributors](https://github.com/testcontainers/testcontainers-go/graphs/contributors). +Copyright (c) 2018-2021 Gianluca Arbezzano and other authors. Check out our +[lovely contributors](https://github.com/testcontainers/testcontainers-go/graphs/contributors). From ab5d09a7803dd1697dd76e8e5c59dd9110d07ba4 Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Fri, 10 Sep 2021 23:08:57 -0700 Subject: [PATCH 070/219] trigger workflows From 223e7b67d5ee7652a2d5f44488916aec9a99e61c Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Fri, 10 Sep 2021 23:24:03 -0700 Subject: [PATCH 071/219] made a pass on garbage collector docs --- docs/features/garbage_collector.md | 36 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/features/garbage_collector.md b/docs/features/garbage_collector.md index 1ffaa4051d..4d37c82157 100644 --- a/docs/features/garbage_collector.md +++ b/docs/features/garbage_collector.md @@ -1,8 +1,8 @@ # Garbage Collector -Usually, one test creates at least one container. At the end it means a lot of -containers running. We need to have a way to keep the CI servers reliable -removing unused containers. +Typically, an integration test creates one or more containers. This can mean a +lot of containers running by the time everything is done. We need to have a way +to clean up after ourselves to keep our machines running smoothly. Containers can be unused because: @@ -13,8 +13,9 @@ Containers can be unused because: ## Terminate function As we saw previously there are at least two ways to remove unused containers. -The first one is to use the `Terminate(context.Conext)` function available when a -container is created. You can call it in your test or you use `defer` . +The primary method is to use the `Terminate(context.Conext)` function that is +available when a container is created. Use `defer` to ensure that it is called +on test completion. !!!tip @@ -24,22 +25,21 @@ container is created. You can call it in your test or you use `defer` . ## Ryuk -[https://github.com/testcontainers/moby-ryuk](ryuk) helps you to remove -containers/networks/volumes by given filter after specified delay. +[https://github.com/testcontainers/moby-ryuk](Ryuk) (also referred to as +`Reaper` in this package) removes containers/networks/volumes created by +Testcontainers-Go after a specified delay. It is a project developed by the +TestContainers organization and is used across the board for for many of the +different language implementations. -It is a project developed by TestContainers, and it is used across the board for -Java, Go and any more. - -When you run one test, you will see that there is not only the containers your -tests requires running, there is another one called `ryuk`. We refer to it as -`Reaper` as well in this library. - -Based on container labels it removes resources created from testcontainers that -are running for more than 10 seconds. +When you run one test, you will see an additional container called `ryuk` +alongside all of the containers that were specified in your test. It relies on +container labels to determine which resources were created by the package +to determine the entities that are safe to remove. If a container is running +for more than 10 seconds, it will be killed. !!!tip This feature can be disabled when creating a container -In this way even if you do not call Terminate, something will keep your -environment clean. It will also clean itself when there is nothing left to do. +Even if you do not call Terminate, Ryuk ensures that the environment will be +kept clean and even cleans itself when there is nothing left to do. From 3eed4e2a55fd21f75873ed4970bc7e9581cef189 Mon Sep 17 00:00:00 2001 From: Luca Berneking Date: Tue, 14 Sep 2021 17:41:04 +0200 Subject: [PATCH 072/219] Swap incorrect key and value of BindMounts and VolumeMounts It is currently not possible to mount a local path to multiple paths in the container. BindMounts are currently stored in a `map[string]string` with the hostPath being the key and containerPath as the value. This prevents me from mounting a hostPath to multiple paths in the container. Using a map actually makes sense because it is not possible to mount multiple host paths to the same path in the container. Key and value are just swapped. Same with VolumeMounts. Yes, i know, this a huge breaking change and probably not the best fix. We could also add an additional map like `BindMountsFixed` and deprecate the old one. But as this library is still in version 0, a breaking change might not be a problem? --- docker.go | 4 ++-- docker_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker.go b/docker.go index efb324aa54..17e20de694 100644 --- a/docker.go +++ b/docker.go @@ -679,14 +679,14 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque // prepare mounts mounts := []mount.Mount{} - for hostPath, innerPath := range req.BindMounts { + for innerPath, hostPath := range req.BindMounts { mounts = append(mounts, mount.Mount{ Type: mount.TypeBind, Source: hostPath, Target: innerPath, }) } - for volumeName, innerPath := range req.VolumeMounts { + for innerPath, volumeName := range req.VolumeMounts { mounts = append(mounts, mount.Mount{ Type: mount.TypeVolume, Source: volumeName, diff --git a/docker_test.go b/docker_test.go index 9349c4fedc..71039e863e 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1279,8 +1279,8 @@ func TestContainerCreationWithBindAndVolume(t *testing.T) { bashC, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: ContainerRequest{ Image: "bash", - BindMounts: map[string]string{absPath: "/hello.sh"}, - VolumeMounts: map[string]string{volumeName: "/data"}, + BindMounts: map[string]string{"/hello.sh": absPath}, + VolumeMounts: map[string]string{"/data": volumeName}, Cmd: []string{"bash", "/hello.sh"}, WaitingFor: wait.ForLog("done"), }, From a8ca2950cbb5dcd3fb62f1a1b446c8129b7e0971 Mon Sep 17 00:00:00 2001 From: Franklin Guimaraes Date: Sat, 25 Sep 2021 16:09:06 -0400 Subject: [PATCH 073/219] Add canned kafka to module doc --- docs/modules.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/modules.md b/docs/modules.md index 615ea85893..282c042fa5 100644 --- a/docs/modules.md +++ b/docs/modules.md @@ -10,6 +10,7 @@ modules](https://blog.golang.org/using-go-modules). * [Canned postgres #98](https://github.com/testcontainers/testcontainers-go/pull/98) * [Canned minio #105](https://github.com/testcontainers/testcontainers-go/pull/105) * [Canned MongoDB #102](https://github.com/testcontainers/testcontainers-go/pull/102) +* [Canned Kafka #356](https://github.com/testcontainers/testcontainers-go/pull/356) Submodules in Go are not easy to maintain today and I want to keep testcontainers dependencies under control and the project light. If we start From 2d2a7cf737d7425aea15035b48de020b9a3298bb Mon Sep 17 00:00:00 2001 From: anjmao Date: Fri, 1 Oct 2021 14:15:51 +0300 Subject: [PATCH 074/219] Close docker provider client on container terminate --- docker.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker.go b/docker.go index efb324aa54..f0c8a89d53 100644 --- a/docker.go +++ b/docker.go @@ -188,6 +188,9 @@ func (c *DockerContainer) Terminate(ctx context.Context) error { }) if err == nil { + if err := c.provider.client.Close(); err != nil { + return err + } c.sessionID = uuid.UUID{} } From cf7972574e098263387111aac9e228ad16a4e22e Mon Sep 17 00:00:00 2001 From: Jared Petersen Date: Sat, 2 Oct 2021 23:00:57 -0700 Subject: [PATCH 075/219] apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Manuel de la Peña --- docs/features/garbage_collector.md | 2 +- docs/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/features/garbage_collector.md b/docs/features/garbage_collector.md index 4d37c82157..b34cd8bb70 100644 --- a/docs/features/garbage_collector.md +++ b/docs/features/garbage_collector.md @@ -28,7 +28,7 @@ on test completion. [https://github.com/testcontainers/moby-ryuk](Ryuk) (also referred to as `Reaper` in this package) removes containers/networks/volumes created by Testcontainers-Go after a specified delay. It is a project developed by the -TestContainers organization and is used across the board for for many of the +TestContainers organization and is used across the board for many of the different language implementations. When you run one test, you will see an additional container called `ryuk` diff --git a/docs/index.md b/docs/index.md index c9729ab985..0650d3e7c8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -23,5 +23,5 @@ See [LICENSE](https://github.com/testcontainers/testcontainers-go/blob/master/LI ## Copyright -Copyright (c) 2018-2021 Gianluca Arbezzano and other authors. Check out our +Copyright (c) 2018-present Gianluca Arbezzano and other authors. Check out our [lovely contributors](https://github.com/testcontainers/testcontainers-go/graphs/contributors). From 7184053543be017dfb01ac4dd081e215cc46f466 Mon Sep 17 00:00:00 2001 From: Vladimir Romanko Date: Wed, 8 Sep 2021 18:14:25 +0300 Subject: [PATCH 076/219] bugfix for: panic: received invalid log type: 3 --- docker.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker.go b/docker.go index 668b9d5f72..bd33799195 100644 --- a/docker.go +++ b/docker.go @@ -414,7 +414,9 @@ func (c *DockerContainer) StartLogProducer(ctx context.Context) error { } logType := h[0] if logType > 2 { - panic(fmt.Sprintf("received invalid log type: %d", logType)) + fmt.Fprintf(os.Stderr, fmt.Sprintf("received invalid log type: %d", logType)) + // sometimes docker returns logType = 3 which is an undocumented log type, so treat it as stdout + logType = 1 } // a map of the log type --> int representation in the header, notice the first is blank, this is stdin, but the go docker client doesn't allow following that in logs From 2db996f7f3e03ebad84419d96deb21c07379f79a Mon Sep 17 00:00:00 2001 From: Travis Huddleston Date: Mon, 4 Oct 2021 13:46:43 -0400 Subject: [PATCH 077/219] support uid:gid specification --- container.go | 1 + docker.go | 1 + 2 files changed, 2 insertions(+) diff --git a/container.go b/container.go index 64ee0f2c08..9b7e024509 100644 --- a/container.go +++ b/container.go @@ -93,6 +93,7 @@ type ContainerRequest struct { Privileged bool // for starting privileged container Networks []string // for specifying network names NetworkAliases map[string][]string // for specifying network aliases + User string // for specifying uid:gid SkipReaper bool // indicates whether we skip setting up a reaper for this ReaperImage string // alternative reaper image AutoRemove bool // if set to true, the container will be removed from the host when stopped diff --git a/docker.go b/docker.go index efb324aa54..7d089cca2e 100644 --- a/docker.go +++ b/docker.go @@ -675,6 +675,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque Labels: req.Labels, Cmd: req.Cmd, Hostname: req.Hostname, + User: req.User, } // prepare mounts From cceef312f66146a351fe3b69853f03877d40e0d6 Mon Sep 17 00:00:00 2001 From: Rob Crowe Date: Mon, 4 Oct 2021 22:42:29 +0100 Subject: [PATCH 078/219] Expose configuration of logger --- container.go | 5 +++++ docker.go | 9 ++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/container.go b/container.go index 64ee0f2c08..517ce35f68 100644 --- a/container.go +++ b/container.go @@ -3,6 +3,8 @@ package testcontainers import ( "context" "io" + "log" + "os" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" @@ -14,6 +16,9 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) +// Logger is the default log instance +var Logger = log.New(os.Stderr, "", log.LstdFlags) + // DeprecatedContainer shows methods that were supported before, but are now deprecated // Deprecated: Use Container type DeprecatedContainer interface { diff --git a/docker.go b/docker.go index efb324aa54..5a69bf267d 100644 --- a/docker.go +++ b/docker.go @@ -8,7 +8,6 @@ import ( "fmt" "io" "io/ioutil" - "log" "net/url" "os" "os/exec" @@ -157,7 +156,7 @@ func (c *DockerContainer) SessionID() string { // Start will start an already created container func (c *DockerContainer) Start(ctx context.Context) error { shortID := c.ID[:12] - log.Printf("Starting container id: %s image: %s", shortID, c.Image) + Logger.Printf("Starting container id: %s image: %s", shortID, c.Image) if err := c.provider.client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}); err != nil { return err @@ -165,12 +164,12 @@ func (c *DockerContainer) Start(ctx context.Context) error { // if a Wait Strategy has been specified, wait before returning if c.WaitingFor != nil { - log.Printf("Waiting for container id %s image: %s", shortID, c.Image) + Logger.Printf("Waiting for container id %s image: %s", shortID, c.Image) if err := c.WaitingFor.WaitUntilReady(ctx, c); err != nil { return err } } - log.Printf("Container is ready id: %s image: %s", shortID, c.Image) + Logger.Printf("Container is ready id: %s image: %s", shortID, c.Image) return nil } @@ -777,7 +776,7 @@ func (p *DockerProvider) attemptToPullImage(ctx context.Context, tag string, pul if _, ok := err.(errdefs.ErrNotFound); ok { return backoff.Permanent(err) } - log.Printf("Failed to pull image: %s, will retry", err) + Logger.Printf("Failed to pull image: %s, will retry", err) return err } return nil From 9a345e3167c3120e8ded1a4aefa4874eda625f57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Oct 2021 11:37:56 +0000 Subject: [PATCH 079/219] chore(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 20.10.8+incompatible to 20.10.9+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Changelog](https://github.com/moby/moby/blob/master/CHANGELOG.md) - [Commits](https://github.com/docker/docker/compare/v20.10.8...v20.10.9) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 690270f2f4..ea4ff7b02f 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.13 require ( github.com/Microsoft/hcsshim v0.8.16 // indirect github.com/cenkalti/backoff v2.2.1+incompatible - github.com/docker/docker v20.10.8+incompatible + github.com/docker/docker v20.10.9+incompatible github.com/docker/go-connections v0.4.0 github.com/go-redis/redis v6.15.9+incompatible github.com/go-sql-driver/mysql v1.6.0 diff --git a/go.sum b/go.sum index 9f42210d22..91dac08ba6 100644 --- a/go.sum +++ b/go.sum @@ -191,8 +191,8 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.8+incompatible h1:RVqD337BgQicVCzYrrlhLDWhq6OAD2PJDUg2LsEUvKM= -github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.9+incompatible h1:JlsVnETOjM2RLQa0Cc1XCIspUdXW3Zenq9P54uXBm6k= +github.com/docker/docker v20.10.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= From d69086e679b3fd54bb594b644e2106859e6c88b5 Mon Sep 17 00:00:00 2001 From: Travis Huddleston Date: Tue, 5 Oct 2021 11:21:26 -0400 Subject: [PATCH 080/219] uid tests --- docker_test.go | 63 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/docker_test.go b/docker_test.go index 9349c4fedc..ed0a026b95 100644 --- a/docker_test.go +++ b/docker_test.go @@ -5,17 +5,19 @@ import ( "encoding/json" "errors" "fmt" - "github.com/stretchr/testify/assert" "io/ioutil" "math/rand" "net/http" "os" "os/exec" "path/filepath" + "regexp" "strings" "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/docker/docker/errdefs" "github.com/docker/docker/api/types/volume" @@ -1580,6 +1582,65 @@ func TestContainerWithReaperNetwork(t *testing.T) { assert.NotNil(t, cnt.NetworkSettings.Networks[networks[1]]) } +func TestContainerWithUserID(t *testing.T) { + ctx := context.Background() + req := ContainerRequest{ + Image: "alpine:latest", + User: "60125", + Cmd: []string{"sh", "-c", "id -u"}, + WaitingFor: wait.ForExit(), + } + container, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + defer container.Terminate(ctx) + + r, err := container.Logs(ctx) + if err != nil { + t.Fatal(err) + } + defer r.Close() + b, err := ioutil.ReadAll(r) + if err != nil { + t.Fatal(err) + } + actual := regexp.MustCompile(`\D+`).ReplaceAllString(string(b), "") + assert.Equal(t, req.User, actual) +} + +func TestContainerWithNoUserID(t *testing.T) { + ctx := context.Background() + req := ContainerRequest{ + Image: "alpine:latest", + Cmd: []string{"sh", "-c", "id -u"}, + WaitingFor: wait.ForExit(), + } + container, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + defer container.Terminate(ctx) + + r, err := container.Logs(ctx) + if err != nil { + t.Fatal(err) + } + defer r.Close() + b, err := ioutil.ReadAll(r) + if err != nil { + t.Fatal(err) + } + actual := regexp.MustCompile(`\D+`).ReplaceAllString(string(b), "") + assert.Equal(t, "0", actual) +} + func TestGetGatewayIP(t *testing.T) { // When using docker-compose with DinD mode, and using host port or http wait strategy // It's need to invoke GetGatewayIP for get the host From d9210037a1b189d614e39ae46b027afd35548788 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Oct 2021 08:03:07 +0000 Subject: [PATCH 081/219] chore(deps): bump mkdocs from 1.0.4 to 1.2.3 Bumps [mkdocs](https://github.com/mkdocs/mkdocs) from 1.0.4 to 1.2.3. - [Release notes](https://github.com/mkdocs/mkdocs/releases) - [Commits](https://github.com/mkdocs/mkdocs/compare/1.0.4...1.2.3) --- updated-dependencies: - dependency-name: mkdocs dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Pipfile.lock | 372 ++++++++++++++++++++++++++++----------------------- 1 file changed, 205 insertions(+), 167 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 5d2a511d8f..c3fe98bbd0 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -18,104 +18,118 @@ "default": { "click": { "hashes": [ - "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", - "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" + "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3", + "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b" ], - "version": "==7.1.2" + "markers": "python_version >= '3.6'", + "version": "==8.0.3" }, - "importlib-metadata": { + "ghp-import": { "hashes": [ - "sha256:742add720a20d0467df2f444ae41704000f50e1234f46174b51f9c6031a1bd71", - "sha256:b74159469b464a99cb8cc3e21973e4d96e05d3024d337313fedb618a6e86e6f4" + "sha256:5f8962b30b20652cdffa9c5a9812f7de6bcb56ec475acac579807719bf242c46", + "sha256:947b3771f11be850c852c64b561c600fdddf794bab363060854c1ee7ad05e071" ], - "markers": "python_version < '3.8'", - "version": "==3.7.3" + "version": "==2.0.2" }, - "jinja2": { + "importlib-metadata": { "hashes": [ - "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419", - "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6" + "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15", + "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1" ], - "index": "pypi", - "version": "==2.11.3" + "markers": "python_version < '3.8'", + "version": "==4.8.1" }, - "livereload": { + "jinja2": { "hashes": [ - "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869" + "sha256:827a0e32839ab1600d4eb1c4c33ec5a8edfbc5cb42dafa13b81f182f97784b45", + "sha256:8569982d3f0889eed11dd620c706d39b60c36d6d25843961f33f77fb6bc6b20c" ], - "version": "==2.6.3" + "markers": "python_version >= '3.6'", + "version": "==3.0.2" }, "markdown": { "hashes": [ "sha256:31b5b491868dcc87d6c24b7e3d19a0d730d59d3e46f4eea6430a321bed387a49", "sha256:96c3ba1261de2f7547b46a00ea8463832c921d3f9d6aba3f255a6f71386db20c" ], + "markers": "python_version >= '3.6'", "version": "==3.3.4" }, "markupsafe": { "hashes": [ - "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", - "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", - "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", - "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", - "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", - "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f", - "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39", - "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", - "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", - "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014", - "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f", - "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", - "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", - "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", - "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", - "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", - "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", - "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", - "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", - "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85", - "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1", - "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", - "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", - "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", - "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850", - "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0", - "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", - "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", - "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb", - "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", - "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", - "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", - "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1", - "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2", - "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", - "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", - "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", - "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7", - "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", - "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8", - "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", - "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193", - "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", - "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b", - "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", - "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", - "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5", - "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c", - "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032", - "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", - "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be", - "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621" - ], - "version": "==1.1.1" + "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298", + "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64", + "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b", + "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567", + "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff", + "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724", + "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74", + "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646", + "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35", + "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6", + "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6", + "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad", + "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26", + "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38", + "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac", + "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7", + "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6", + "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75", + "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f", + "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135", + "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8", + "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a", + "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a", + "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9", + "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864", + "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914", + "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18", + "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8", + "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2", + "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d", + "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b", + "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b", + "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f", + "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb", + "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833", + "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28", + "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415", + "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902", + "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d", + "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9", + "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d", + "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145", + "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066", + "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c", + "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1", + "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f", + "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53", + "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134", + "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85", + "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5", + "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94", + "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509", + "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51", + "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872" + ], + "markers": "python_version >= '3.6'", + "version": "==2.0.1" + }, + "mergedeep": { + "hashes": [ + "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8", + "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307" + ], + "markers": "python_version >= '3.6'", + "version": "==1.3.4" }, "mkdocs": { "hashes": [ - "sha256:17d34329aad75d5de604b9ed4e31df3a4d235afefdc46ce7b1964fddb2e1e939", - "sha256:8cc8b38325456b9e942c981a209eaeb1e9f3f77b493ad755bfef889b9c8d356a" + "sha256:89f5a094764381cda656af4298727c9f53dc3e602983087e1fe96ea1df24f4c1", + "sha256:a1fa8c2d0c1305d7fc2b9d9f607c71778572a8b110fb26642aa00296c9e6d072" ], "index": "pypi", - "version": "==1.0.4" + "version": "==1.2.3" }, "mkdocs-markdownextradata-plugin": { "hashes": [ @@ -132,122 +146,146 @@ "index": "pypi", "version": "==3.2.0" }, + "packaging": { + "hashes": [ + "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7", + "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14" + ], + "markers": "python_version >= '3.6'", + "version": "==21.0" + }, "pygments": { "hashes": [ - "sha256:2656e1a6edcdabf4275f9a3640db59fd5de107d88e8663c5d4e9a0fa62f77f94", - "sha256:534ef71d539ae97d4c3a4cf7d6f110f214b0e687e92f9cb9d2a3b0d3101289c8" + "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380", + "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6" ], - "version": "==2.8.1" + "markers": "python_version >= '3.5'", + "version": "==2.10.0" }, "pymdown-extensions": { "hashes": [ - "sha256:478b2c04513fbb2db61688d5f6e9030a92fb9be14f1f383535c43f7be9dff95b", - "sha256:632371fa3bf1b21a0e3f4063010da59b41db049f261f4c0b0872069a9b6d1735" + "sha256:01e4bec7f4b16beaba0087a74496401cf11afd69e3a11fe95cb593e5c698ef40", + "sha256:430cc2fbb30cef2df70edac0b4f62614a6a4d2b06462e32da4ca96098b7c1dfb" ], - "version": "==8.1.1" + "markers": "python_version >= '3.6'", + "version": "==9.0" + }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.7" + }, + "python-dateutil": { + "hashes": [ + "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", + "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.2" }, "pyyaml": { "hashes": [ - "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", - "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", - "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", - "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", - "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", - "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", - "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", - "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", - "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", - "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", - "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", - "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", - "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347", - "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", - "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541", - "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", - "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", - "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc", - "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", - "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa", - "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", - "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122", - "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", - "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", - "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", - "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc", - "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247", - "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6", - "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0" - ], - "version": "==5.4.1" + "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", + "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", + "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", + "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", + "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", + "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", + "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", + "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", + "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", + "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", + "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", + "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", + "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", + "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", + "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", + "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", + "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", + "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", + "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", + "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", + "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", + "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", + "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", + "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", + "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", + "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", + "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", + "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", + "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", + "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", + "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", + "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", + "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" + ], + "markers": "python_version >= '3.6'", + "version": "==6.0" + }, + "pyyaml-env-tag": { + "hashes": [ + "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb", + "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069" + ], + "markers": "python_version >= '3.6'", + "version": "==0.1" }, "six": { "hashes": [ - "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", - "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" - ], - "version": "==1.15.0" - }, - "tornado": { - "hashes": [ - "sha256:0a00ff4561e2929a2c37ce706cb8233b7907e0cdc22eab98888aca5dd3775feb", - "sha256:0d321a39c36e5f2c4ff12b4ed58d41390460f798422c4504e09eb5678e09998c", - "sha256:1e8225a1070cd8eec59a996c43229fe8f95689cb16e552d130b9793cb570a288", - "sha256:20241b3cb4f425e971cb0a8e4ffc9b0a861530ae3c52f2b0434e6c1b57e9fd95", - "sha256:25ad220258349a12ae87ede08a7b04aca51237721f63b1808d39bdb4b2164558", - "sha256:33892118b165401f291070100d6d09359ca74addda679b60390b09f8ef325ffe", - "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791", - "sha256:3447475585bae2e77ecb832fc0300c3695516a47d46cefa0528181a34c5b9d3d", - "sha256:34ca2dac9e4d7afb0bed4677512e36a52f09caa6fded70b4e3e1c89dbd92c326", - "sha256:3e63498f680547ed24d2c71e6497f24bca791aca2fe116dbc2bd0ac7f191691b", - "sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4", - "sha256:6196a5c39286cc37c024cd78834fb9345e464525d8991c21e908cc046d1cc02c", - "sha256:61b32d06ae8a036a6607805e6720ef00a3c98207038444ba7fd3d169cd998910", - "sha256:6286efab1ed6e74b7028327365cf7346b1d777d63ab30e21a0f4d5b275fc17d5", - "sha256:65d98939f1a2e74b58839f8c4dab3b6b3c1ce84972ae712be02845e65391ac7c", - "sha256:66324e4e1beede9ac79e60f88de548da58b1f8ab4b2f1354d8375774f997e6c0", - "sha256:6c77c9937962577a6a76917845d06af6ab9197702a42e1346d8ae2e76b5e3675", - "sha256:70dec29e8ac485dbf57481baee40781c63e381bebea080991893cd297742b8fd", - "sha256:7250a3fa399f08ec9cb3f7b1b987955d17e044f1ade821b32e5f435130250d7f", - "sha256:748290bf9112b581c525e6e6d3820621ff020ed95af6f17fedef416b27ed564c", - "sha256:7da13da6f985aab7f6f28debab00c67ff9cbacd588e8477034c0652ac141feea", - "sha256:8f959b26f2634a091bb42241c3ed8d3cedb506e7c27b8dd5c7b9f745318ddbb6", - "sha256:9de9e5188a782be6b1ce866e8a51bc76a0fbaa0e16613823fc38e4fc2556ad05", - "sha256:a48900ecea1cbb71b8c71c620dee15b62f85f7c14189bdeee54966fbd9a0c5bd", - "sha256:b87936fd2c317b6ee08a5741ea06b9d11a6074ef4cc42e031bc6403f82a32575", - "sha256:c77da1263aa361938476f04c4b6c8916001b90b2c2fdd92d8d535e1af48fba5a", - "sha256:cb5ec8eead331e3bb4ce8066cf06d2dfef1bfb1b2a73082dfe8a161301b76e37", - "sha256:cc0ee35043162abbf717b7df924597ade8e5395e7b66d18270116f8745ceb795", - "sha256:d14d30e7f46a0476efb0deb5b61343b1526f73ebb5ed84f23dc794bdb88f9d9f", - "sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32", - "sha256:d3d20ea5782ba63ed13bc2b8c291a053c8d807a8fa927d941bd718468f7b950c", - "sha256:d3f7594930c423fd9f5d1a76bee85a2c36fd8b4b16921cae7e965f22575e9c01", - "sha256:dcef026f608f678c118779cd6591c8af6e9b4155c44e0d1bc0c87c036fb8c8c4", - "sha256:e0791ac58d91ac58f694d8d2957884df8e4e2f6687cdf367ef7eb7497f79eaa2", - "sha256:e385b637ac3acaae8022e7e47dfa7b83d3620e432e3ecb9a3f7f58f150e50921", - "sha256:e519d64089b0876c7b467274468709dadf11e41d65f63bba207e04217f47c085", - "sha256:e7229e60ac41a1202444497ddde70a48d33909e484f96eb0da9baf8dc68541df", - "sha256:ed3ad863b1b40cd1d4bd21e7498329ccaece75db5a5bf58cd3c9f130843e7102", - "sha256:f0ba29bafd8e7e22920567ce0d232c26d4d47c8b5cf4ed7b562b5db39fa199c5", - "sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68", - "sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5" - ], - "version": "==6.1" + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.16.0" }, "typing-extensions": { "hashes": [ - "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918", - "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c", - "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f" + "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e", + "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7", + "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34" ], "markers": "python_version < '3.8'", - "version": "==3.7.4.3" + "version": "==3.10.0.2" + }, + "watchdog": { + "hashes": [ + "sha256:25fb5240b195d17de949588628fdf93032ebf163524ef08933db0ea1f99bd685", + "sha256:3386b367e950a11b0568062b70cc026c6f645428a698d33d39e013aaeda4cc04", + "sha256:3becdb380d8916c873ad512f1701f8a92ce79ec6978ffde92919fd18d41da7fb", + "sha256:4ae38bf8ba6f39d5b83f78661273216e7db5b00f08be7592062cb1fc8b8ba542", + "sha256:8047da932432aa32c515ec1447ea79ce578d0559362ca3605f8e9568f844e3c6", + "sha256:8f1c00aa35f504197561060ca4c21d3cc079ba29cf6dd2fe61024c70160c990b", + "sha256:922a69fa533cb0c793b483becaaa0845f655151e7256ec73630a1b2e9ebcb660", + "sha256:9693f35162dc6208d10b10ddf0458cc09ad70c30ba689d9206e02cd836ce28a3", + "sha256:a0f1c7edf116a12f7245be06120b1852275f9506a7d90227648b250755a03923", + "sha256:a36e75df6c767cbf46f61a91c70b3ba71811dfa0aca4a324d9407a06a8b7a2e7", + "sha256:aba5c812f8ee8a3ff3be51887ca2d55fb8e268439ed44110d3846e4229eb0e8b", + "sha256:ad6f1796e37db2223d2a3f302f586f74c72c630b48a9872c1e7ae8e92e0ab669", + "sha256:ae67501c95606072aafa865b6ed47343ac6484472a2f95490ba151f6347acfc2", + "sha256:b2fcf9402fde2672545b139694284dc3b665fd1be660d73eca6805197ef776a3", + "sha256:b52b88021b9541a60531142b0a451baca08d28b74a723d0c99b13c8c8d48d604", + "sha256:b7d336912853d7b77f9b2c24eeed6a5065d0a0cc0d3b6a5a45ad6d1d05fb8cd8", + "sha256:bd9ba4f332cf57b2c1f698be0728c020399ef3040577cde2939f2e045b39c1e5", + "sha256:be9be735f827820a06340dff2ddea1fb7234561fa5e6300a62fe7f54d40546a0", + "sha256:cca7741c0fcc765568350cb139e92b7f9f3c9a08c4f32591d18ab0a6ac9e71b6", + "sha256:d0d19fb2441947b58fbf91336638c2b9f4cc98e05e1045404d7a4cb7cddc7a65", + "sha256:e02794ac791662a5eafc6ffeaf9bcc149035a0e48eb0a9d40a8feb4622605a3d", + "sha256:e0f30db709c939cabf64a6dc5babb276e6d823fd84464ab916f9b9ba5623ca15", + "sha256:e92c2d33858c8f560671b448205a268096e17870dcf60a9bb3ac7bfbafb7f5f9" + ], + "markers": "python_version >= '3.6'", + "version": "==2.1.6" }, "zipp": { "hashes": [ - "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76", - "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098" + "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832", + "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc" ], - "version": "==3.4.1" + "markers": "python_version >= '3.6'", + "version": "==3.6.0" } }, "develop": {} From b95f8fe09a5f8ff196e2c2b0137c5e274f2d0113 Mon Sep 17 00:00:00 2001 From: Alexey Medvedchikov Date: Fri, 22 Oct 2021 23:05:23 +0100 Subject: [PATCH 082/219] Add wait.ExecStrategy to wait for successful command execution inside a container --- wait/exec.go | 77 +++++++++++++++++++++++++++++ wait/exec_test.go | 120 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 wait/exec.go create mode 100644 wait/exec_test.go diff --git a/wait/exec.go b/wait/exec.go new file mode 100644 index 0000000000..1255187808 --- /dev/null +++ b/wait/exec.go @@ -0,0 +1,77 @@ +package wait + +import ( + "context" + "time" +) + +// Implement interface +var _ Strategy = (*ExecStrategy)(nil) + +type ExecStrategy struct { + // all Strategies should have a startupTimeout to avoid waiting infinitely + startupTimeout time.Duration + cmd []string + + // additional properties + ExitCodeMatcher func(exitCode int) bool + PollInterval time.Duration +} + +// NewExecStrategy constructs an Exec strategy ... +func NewExecStrategy(cmd []string) *ExecStrategy { + return &ExecStrategy{ + startupTimeout: defaultStartupTimeout(), + cmd: cmd, + ExitCodeMatcher: defaultExitCodeMatcher, + PollInterval: defaultPollInterval(), + } +} + +func defaultExitCodeMatcher(exitCode int) bool { + return exitCode == 0 +} + +func (ws *ExecStrategy) WithStartupTimeout(startupTimeout time.Duration) *ExecStrategy { + ws.startupTimeout = startupTimeout + return ws +} + +func (ws *ExecStrategy) WithExitCodeMatcher(exitCodeMatcher func(exitCode int) bool) *ExecStrategy { + ws.ExitCodeMatcher = exitCodeMatcher + return ws +} + +// WithPollInterval can be used to override the default polling interval of 100 milliseconds +func (ws *ExecStrategy) WithPollInterval(pollInterval time.Duration) *ExecStrategy { + ws.PollInterval = pollInterval + return ws +} + +// ForExec is a convenience method to assign ExecStrategy +func ForExec(cmd []string) *ExecStrategy { + return NewExecStrategy(cmd) +} + +func (ws ExecStrategy) WaitUntilReady(ctx context.Context, target StrategyTarget) error { + // limit context to startupTimeout + ctx, cancelContext := context.WithTimeout(ctx, ws.startupTimeout) + defer cancelContext() + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(ws.PollInterval): + exitCode, err := target.Exec(ctx, ws.cmd) + if err != nil { + return err + } + if !ws.ExitCodeMatcher(exitCode) { + continue + } + + return nil + } + } +} diff --git a/wait/exec_test.go b/wait/exec_test.go new file mode 100644 index 0000000000..c4e6744f61 --- /dev/null +++ b/wait/exec_test.go @@ -0,0 +1,120 @@ +package wait_test + +import ( + "context" + "errors" + "io" + "testing" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/go-connections/nat" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +func ExampleExecStrategy() { + ctx := context.Background() + req := testcontainers.ContainerRequest{ + Image: "localstack/localstack:latest", + WaitingFor: wait.ForExec([]string{"awslocal", "dynamodb", "list-tables"}), + } + + localstack, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + panic(err) + } + + defer localstack.Terminate(ctx) // nolint: errcheck + // Here you have a running container +} + +type mockExecTarget struct { + waitDuration time.Duration + successAfter time.Time + exitCode int + failure error +} + +func (st mockExecTarget) Host(_ context.Context) (string, error) { + return "", errors.New("not implemented") +} + +func (st mockExecTarget) MappedPort(_ context.Context, n nat.Port) (nat.Port, error) { + return n, errors.New("not implemented") +} + +func (st mockExecTarget) Logs(_ context.Context) (io.ReadCloser, error) { + return nil, errors.New("not implemented") +} + +func (st mockExecTarget) Exec(ctx context.Context, _ []string) (int, error) { + time.Sleep(st.waitDuration) + + if err := ctx.Err(); err != nil { + return st.exitCode, err + } + + if !st.successAfter.IsZero() && time.Now().After(st.successAfter) { + return 0, st.failure + } + + return st.exitCode, st.failure +} + +func (st mockExecTarget) State(_ context.Context) (*types.ContainerState, error) { + return nil, errors.New("not implemented") +} + +func TestExecStrategyWaitUntilReady(t *testing.T) { + target := mockExecTarget{} + wg := wait.NewExecStrategy([]string{"true"}) + err := wg.WaitUntilReady(context.Background(), target) + if err != nil { + t.Fatal(err) + } +} + +func TestExecStrategyWaitUntilReady_MultipleChecks(t *testing.T) { + target := mockExecTarget{ + exitCode: 10, + successAfter: time.Now().Add(2 * time.Second), + } + wg := wait.NewExecStrategy([]string{"true"}). + WithPollInterval(500 * time.Millisecond) + err := wg.WaitUntilReady(context.Background(), target) + if err != nil { + t.Fatal(err) + } +} + +func TestExecStrategyWaitUntilReady_DeadlineExceeded(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) + defer cancel() + + target := mockExecTarget{ + waitDuration: 1 * time.Second, + } + wg := wait.NewExecStrategy([]string{"true"}) + err := wg.WaitUntilReady(ctx, target) + if err != context.DeadlineExceeded { + t.Fatal(err) + } +} + +func TestExecStrategyWaitUntilReady_CustomExitCode(t *testing.T) { + target := mockExecTarget{ + exitCode: 10, + } + wg := wait.NewExecStrategy([]string{"true"}).WithExitCodeMatcher(func(exitCode int) bool { + return exitCode == 10 + }) + err := wg.WaitUntilReady(context.Background(), target) + if err != nil { + t.Fatal(err) + } +} From 5b7ab5b2672fb7157d8f5d65d3f2a3ce6562f690 Mon Sep 17 00:00:00 2001 From: Chris Lee Date: Sat, 23 Oct 2021 10:52:56 -0600 Subject: [PATCH 083/219] fix with unit-test --- docker.go | 2 +- logconsumer_test.go | 101 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/docker.go b/docker.go index 0f869bf952..efc8439ad5 100644 --- a/docker.go +++ b/docker.go @@ -435,7 +435,7 @@ func (c *DockerContainer) StartLogProducer(ctx context.Context) error { _, err := r.Read(h) if err != nil { // proper type matching requires https://go-review.googlesource.com/c/go/+/250357/ (go 1.16) - if strings.Contains(err.Error(), "use of closed connection") { + if strings.Contains(err.Error(), "use of closed network connection") { now := time.Now() since = fmt.Sprintf("%d.%09d", now.Unix(), int64(now.Nanosecond())) goto BEGIN diff --git a/logconsumer_test.go b/logconsumer_test.go index b251349e40..854b449468 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/docker/docker/client" "github.com/testcontainers/testcontainers-go/wait" "gotest.tools/assert" ) @@ -181,3 +182,103 @@ func Test_ShouldRecognizeLogTypes(t *testing.T) { c.Terminate(ctx) } + +func TestContainerLogWithErrClosed(t *testing.T) { + // First spin up a docker-in-docker container, then spin up an inner container within that dind container + // Logs are being read from the inner container via the dind container's tcp port, which can be briefly + // closed to test behaviour in connection-closed situations. + ctx := context.Background() + + dind, err := GenericContainer(ctx, GenericContainerRequest{ + Started: true, + ContainerRequest: ContainerRequest{ + Image: "docker:dind", + ExposedPorts: []string{"2375/tcp"}, + Env: map[string]string{"DOCKER_TLS_CERTDIR": ""}, + WaitingFor: wait.ForListeningPort("2375/tcp"), + Privileged: true, + }, + }) + if err != nil { + t.Fatal(err) + } + defer dind.Terminate(ctx) + + remoteDocker, err := dind.Endpoint(ctx, "tcp") + if err != nil { + t.Fatal(err) + } + + client, err := client.NewClientWithOpts(client.WithHost(remoteDocker)) + if err != nil { + t.Fatal(err) + } + defer client.Close() + + client.NegotiateAPIVersion(ctx) + provider := &DockerProvider{client: client} + + nginx, err := provider.CreateContainer(ctx, ContainerRequest{Image: "nginx", ExposedPorts: []string{"80/tcp"}}) + if err != nil { + t.Fatal(err) + } + if err := nginx.Start(ctx); err != nil { + t.Fatal(err) + } + defer nginx.Terminate(ctx) + + port, err := nginx.MappedPort(ctx, "80/tcp") + if err != nil { + t.Fatal(err) + } + + var consumer TestLogConsumer + if err = nginx.StartLogProducer(ctx); err != nil { + t.Fatal(err) + } + defer nginx.StopLogProducer() + nginx.FollowOutput(&consumer) + + // Gather the initial container logs + time.Sleep(time.Second * 1) + existingLogs := len(consumer.Msgs) + + hitNginx := func() { + i, err := dind.Exec(ctx, []string{"wget", "--spider", "localhost:" + port.Port()}) + if err != nil || i > 0 { + t.Fatalf("Can't make request to nginx container from dind container") + } + } + + hitNginx() + time.Sleep(time.Second * 1) + if len(consumer.Msgs)-existingLogs != 1 { + t.Fatalf("logConsumer should have 1 new log message, instead has: %v", consumer.Msgs[existingLogs:]) + } + existingLogs = len(consumer.Msgs) + + iptableArgs := []string{ + "INPUT", "-p", "tcp", "--dport", "2375", + "-j", "REJECT", "--reject-with", "tcp-reset", + } + // Simulate a transient closed connection to the docker daemon + i, err := dind.Exec(ctx, append([]string{"iptables", "-A"}, iptableArgs...)) + if err != nil || i > 0 { + t.Fatalf("Failed to close connection to dind daemon") + } + i, err = dind.Exec(ctx, append([]string{"iptables", "-D"}, iptableArgs...)) + if err != nil || i > 0 { + t.Fatalf("Failed to re-open connection to dind daemon") + } + time.Sleep(time.Second * 3) + + hitNginx() + hitNginx() + time.Sleep(time.Second * 1) + if len(consumer.Msgs)-existingLogs != 2 { + t.Fatalf( + "LogConsumer should have 2 new log messages after detecting closed connection and"+ + " re-requesting logs. Instead has:\n%s", consumer.Msgs[existingLogs:], + ) + } +} From 05f3d4239f048b40dee5a6ce3b296c5a11bd5982 Mon Sep 17 00:00:00 2001 From: Alexey Medvedchikov Date: Sun, 24 Oct 2021 02:59:19 +0100 Subject: [PATCH 084/219] Increase test coverage --- wait/exec_test.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/wait/exec_test.go b/wait/exec_test.go index c4e6744f61..db45548274 100644 --- a/wait/exec_test.go +++ b/wait/exec_test.go @@ -72,7 +72,17 @@ func (st mockExecTarget) State(_ context.Context) (*types.ContainerState, error) func TestExecStrategyWaitUntilReady(t *testing.T) { target := mockExecTarget{} - wg := wait.NewExecStrategy([]string{"true"}) + wg := wait.NewExecStrategy([]string{"true"}). + WithStartupTimeout(30 * time.Second) + err := wg.WaitUntilReady(context.Background(), target) + if err != nil { + t.Fatal(err) + } +} + +func TestExecStrategyWaitUntilReadyForExec(t *testing.T) { + target := mockExecTarget{} + wg := wait.ForExec([]string{"true"}) err := wg.WaitUntilReady(context.Background(), target) if err != nil { t.Fatal(err) From 2d10a141a21fdc24100e4ed6c63ea2c539e5c922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Sun, 31 Oct 2021 09:45:37 +0100 Subject: [PATCH 085/219] chore: read `docker.host` from tc properties file in home dir if available --- docker.go | 36 ++++++++++++++++++++++++++++- docker_test.go | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/docker.go b/docker.go index 0f869bf952..a7ea66ebf3 100644 --- a/docker.go +++ b/docker.go @@ -11,7 +11,9 @@ import ( "net/url" "os" "os/exec" + "path" "path/filepath" + "regexp" "strings" "time" @@ -516,7 +518,15 @@ var _ ContainerProvider = (*DockerProvider)(nil) // NewDockerProvider creates a Docker provider with the EnvClient func NewDockerProvider() (*DockerProvider, error) { - client, err := client.NewEnvClient() + content := readTCPropsFile() + host := grepDockerhost(content) + + opts := []client.Opt{client.FromEnv} + if host != "" { + opts = append(opts, client.WithHost(host)) + } + + client, err := client.NewClientWithOpts(opts...) if err != nil { return nil, err } @@ -527,6 +537,30 @@ func NewDockerProvider() (*DockerProvider, error) { return p, nil } +// readTCPropsFile reads from testcontainers properties file, if it exists +func readTCPropsFile() string { + home, err := os.UserHomeDir() + if err != nil { + return "" + } + tcProp := path.Join(home, ".testcontainers.properties") + content, err := os.ReadFile(tcProp) + if err != nil { + return "" + } + return string(content) +} + +func grepDockerhost(content string) string { + regex := regexp.MustCompile(`(?m)^[^#]?\s*docker\.host\s*=\s*(\S*)\s*$`) + matches := regex.FindStringSubmatch(content) + if len(matches) < 2 { + return "" + } + + return matches[1] +} + // BuildImage will build and image from context and Dockerfile, then return the tag func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (string, error) { repo := uuid.New() diff --git a/docker_test.go b/docker_test.go index ed0a026b95..2ff4b7b9f6 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1187,6 +1187,69 @@ func TestEntrypoint(t *testing.T) { defer c.Terminate(ctx) } +func TestGrepDockerhost(t *testing.T) { + tests := []struct { + content string + expected string + }{ + { + "docker.host = tcp://127.0.0.1:33293", + "tcp://127.0.0.1:33293", + }, + { + "docker.host = tcp://127.0.0.1:33293", + "tcp://127.0.0.1:33293", + }, + { + `docker.host = tcp://127.0.0.1:33293 +docker.host = tcp://127.0.0.1:4711 +`, + "tcp://127.0.0.1:33293", + }, + {`docker.host = tcp://127.0.0.1:33293 +docker.host = tcp://127.0.0.1:4711 +docker.host = tcp://127.0.0.1:1234 +`, + "tcp://127.0.0.1:33293", + }, + { + "", + "", + }, + { + `foo = bar +docker.host = tcp://127.0.0.1:1234 + `, + "tcp://127.0.0.1:1234", + }, + { + "docker.host=tcp://127.0.0.1:33293", + "tcp://127.0.0.1:33293", + }, + { + `#docker.host=tcp://127.0.0.1:33293`, + "", + }, + { + `#docker.host = tcp://127.0.0.1:33293 +docker.host = tcp://127.0.0.1:4711 +docker.host = tcp://127.0.0.1:1234`, + "tcp://127.0.0.1:4711", + }, + } + + for _, tt := range tests { + t.Run(tt.expected, func(t *testing.T) { + host := grepDockerhost(tt.content) + + if host != tt.expected { + t.Errorf("'%s' is not equal '%s'", host, tt.expected) + } + }) + } + +} + func ExampleDockerProvider_CreateContainer() { ctx := context.Background() req := ContainerRequest{ From cebfe1d43330fb203813eac40b3dc068875235bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Sun, 31 Oct 2021 09:59:48 +0100 Subject: [PATCH 086/219] chore: add tests for reading TC props file --- docker_test.go | 38 ++++++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 3 +++ 3 files changed, 42 insertions(+) diff --git a/docker_test.go b/docker_test.go index 2ff4b7b9f6..2dd788a6e8 100644 --- a/docker_test.go +++ b/docker_test.go @@ -10,12 +10,14 @@ import ( "net/http" "os" "os/exec" + "path" "path/filepath" "regexp" "strings" "testing" "time" + "github.com/Flaque/filet" "github.com/stretchr/testify/assert" "github.com/docker/docker/errdefs" @@ -1250,6 +1252,42 @@ docker.host = tcp://127.0.0.1:1234`, } +func TestReadTCPropsFile(t *testing.T) { + t.Run("HOME does not contain TC props file", func(t *testing.T) { + oldHome := os.Getenv("HOME") + tmpDir := filet.TmpDir(t, "") + os.Setenv("HOME", tmpDir) + defer func() { + os.Setenv("HOME", oldHome) + filet.CleanUp(t) + }() + + content := readTCPropsFile() + + assert.Empty(t, content, "TC props file should not exist") + }) + + t.Run("HOME contains TC properties file", func(t *testing.T) { + oldHome := os.Getenv("HOME") + tmpDir := filet.TmpDir(t, "") + os.Setenv("HOME", tmpDir) + + properties := `#docker.host = tcp://127.0.0.1:33293 + docker.host = tcp://127.0.0.1:4711 + docker.host = tcp://127.0.0.1:1234` + _ = filet.File(t, path.Join(tmpDir, ".testcontainers.properties"), properties) + + defer func() { + os.Setenv("HOME", oldHome) + filet.CleanUp(t) + }() + + content := readTCPropsFile() + + assert.Equal(t, content, properties, "TC props file should exist with content") + }) +} + func ExampleDockerProvider_CreateContainer() { ctx := context.Background() req := ContainerRequest{ diff --git a/go.mod b/go.mod index ea4ff7b02f..71a0e20fef 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/testcontainers/testcontainers-go go 1.13 require ( + github.com/Flaque/filet v0.0.0-20201012163910-45f684403088 // indirect github.com/Microsoft/hcsshim v0.8.16 // indirect github.com/cenkalti/backoff v2.2.1+incompatible github.com/docker/docker v20.10.9+incompatible diff --git a/go.sum b/go.sum index 91dac08ba6..4ed0d8cc2a 100644 --- a/go.sum +++ b/go.sum @@ -37,6 +37,8 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Flaque/filet v0.0.0-20201012163910-45f684403088 h1:PnnQln5IGbhLeJOi6hVs+lCeF+B1dRfFKPGXUAez0Ww= +github.com/Flaque/filet v0.0.0-20201012163910-45f684403088/go.mod h1:TK+jB3mBs+8ZMWhU5BqZKnZWJ1MrLo8etNVg51ueTBo= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= @@ -485,6 +487,7 @@ github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= From 8f802cb199d22e45621707b1cce1ef699ee2c6cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Sun, 31 Oct 2021 10:05:54 +0100 Subject: [PATCH 087/219] chore: fallback to Docker client from env if docker.host one not accessible --- docker.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/docker.go b/docker.go index a7ea66ebf3..b9d2368100 100644 --- a/docker.go +++ b/docker.go @@ -526,13 +526,27 @@ func NewDockerProvider() (*DockerProvider, error) { opts = append(opts, client.WithHost(host)) } - client, err := client.NewClientWithOpts(opts...) + c, err := client.NewClientWithOpts(opts...) if err != nil { return nil, err } - client.NegotiateAPIVersion(context.Background()) + + _, err = c.Ping(context.TODO()) + if err != nil { + if host != "" { + // fallback to environment + c, err = client.NewClientWithOpts(client.FromEnv) + if err != nil { + return nil, err + } + } else { + return nil, err + } + } + + c.NegotiateAPIVersion(context.Background()) p := &DockerProvider{ - client: client, + client: c, } return p, nil } From f1c9b7e0584447c2bb975ad9c20a9c979aaac4bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 2 Nov 2021 12:43:21 +0100 Subject: [PATCH 088/219] fix: use a backwards compatible way to read files --- docker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker.go b/docker.go index b9d2368100..c218cf02a6 100644 --- a/docker.go +++ b/docker.go @@ -558,7 +558,7 @@ func readTCPropsFile() string { return "" } tcProp := path.Join(home, ".testcontainers.properties") - content, err := os.ReadFile(tcProp) + content, err := ioutil.ReadFile(tcProp) if err != nil { return "" } From 5852ca2bcf82b373ab69f01e0e512417e961dc9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 3 Nov 2021 17:48:44 +0100 Subject: [PATCH 089/219] chore: read TC file using a library This includes support for reading docker specific properties, as specified in https://www.testcontainers.org/features/configuration/#customizing-docker-host-detection --- docker.go | 36 ++++++----- docker_test.go | 164 ++++++++++++++++++++++++++----------------------- go.mod | 1 + go.sum | 2 + 4 files changed, 111 insertions(+), 92 deletions(-) diff --git a/docker.go b/docker.go index c218cf02a6..e534dae154 100644 --- a/docker.go +++ b/docker.go @@ -13,7 +13,6 @@ import ( "os/exec" "path" "path/filepath" - "regexp" "strings" "time" @@ -27,6 +26,7 @@ import ( "github.com/docker/docker/pkg/jsonmessage" "github.com/docker/go-connections/nat" "github.com/google/uuid" + "github.com/magiconair/properties" "github.com/moby/term" "github.com/pkg/errors" @@ -516,10 +516,17 @@ type DockerProvider struct { var _ ContainerProvider = (*DockerProvider)(nil) +// or through Decode +type TestContainersConfig struct { + Host string `properties:"docker.host"` + TLSVerify int `properties:"docker.tls.verify,default=0"` + CertPath string `properties:"docker.cert.path,default="` +} + // NewDockerProvider creates a Docker provider with the EnvClient func NewDockerProvider() (*DockerProvider, error) { - content := readTCPropsFile() - host := grepDockerhost(content) + tcConfig := readTCPropsFile() + host := tcConfig.Host opts := []client.Opt{client.FromEnv} if host != "" { @@ -552,27 +559,26 @@ func NewDockerProvider() (*DockerProvider, error) { } // readTCPropsFile reads from testcontainers properties file, if it exists -func readTCPropsFile() string { +func readTCPropsFile() TestContainersConfig { home, err := os.UserHomeDir() if err != nil { - return "" + return TestContainersConfig{} } + tcProp := path.Join(home, ".testcontainers.properties") - content, err := ioutil.ReadFile(tcProp) + // init from a file + properties, err := properties.LoadFile(tcProp, properties.UTF8) if err != nil { - return "" + return TestContainersConfig{} } - return string(content) -} -func grepDockerhost(content string) string { - regex := regexp.MustCompile(`(?m)^[^#]?\s*docker\.host\s*=\s*(\S*)\s*$`) - matches := regex.FindStringSubmatch(content) - if len(matches) < 2 { - return "" + var cfg TestContainersConfig + if err := properties.Decode(&cfg); err != nil { + fmt.Printf("invalid testcontainers properties file: %v", err) + return TestContainersConfig{} } - return matches[1] + return cfg } // BuildImage will build and image from context and Dockerfile, then return the tag diff --git a/docker_test.go b/docker_test.go index 2dd788a6e8..175e5978e8 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1189,69 +1189,6 @@ func TestEntrypoint(t *testing.T) { defer c.Terminate(ctx) } -func TestGrepDockerhost(t *testing.T) { - tests := []struct { - content string - expected string - }{ - { - "docker.host = tcp://127.0.0.1:33293", - "tcp://127.0.0.1:33293", - }, - { - "docker.host = tcp://127.0.0.1:33293", - "tcp://127.0.0.1:33293", - }, - { - `docker.host = tcp://127.0.0.1:33293 -docker.host = tcp://127.0.0.1:4711 -`, - "tcp://127.0.0.1:33293", - }, - {`docker.host = tcp://127.0.0.1:33293 -docker.host = tcp://127.0.0.1:4711 -docker.host = tcp://127.0.0.1:1234 -`, - "tcp://127.0.0.1:33293", - }, - { - "", - "", - }, - { - `foo = bar -docker.host = tcp://127.0.0.1:1234 - `, - "tcp://127.0.0.1:1234", - }, - { - "docker.host=tcp://127.0.0.1:33293", - "tcp://127.0.0.1:33293", - }, - { - `#docker.host=tcp://127.0.0.1:33293`, - "", - }, - { - `#docker.host = tcp://127.0.0.1:33293 -docker.host = tcp://127.0.0.1:4711 -docker.host = tcp://127.0.0.1:1234`, - "tcp://127.0.0.1:4711", - }, - } - - for _, tt := range tests { - t.Run(tt.expected, func(t *testing.T) { - host := grepDockerhost(tt.content) - - if host != tt.expected { - t.Errorf("'%s' is not equal '%s'", host, tt.expected) - } - }) - } - -} - func TestReadTCPropsFile(t *testing.T) { t.Run("HOME does not contain TC props file", func(t *testing.T) { oldHome := os.Getenv("HOME") @@ -1262,29 +1199,102 @@ func TestReadTCPropsFile(t *testing.T) { filet.CleanUp(t) }() - content := readTCPropsFile() + config := readTCPropsFile() - assert.Empty(t, content, "TC props file should not exist") + assert.Empty(t, config, "TC props file should not exist") }) t.Run("HOME contains TC properties file", func(t *testing.T) { oldHome := os.Getenv("HOME") - tmpDir := filet.TmpDir(t, "") - os.Setenv("HOME", tmpDir) - properties := `#docker.host = tcp://127.0.0.1:33293 - docker.host = tcp://127.0.0.1:4711 - docker.host = tcp://127.0.0.1:1234` - _ = filet.File(t, path.Join(tmpDir, ".testcontainers.properties"), properties) + tests := []struct { + content string + expectedHost string + expectedTLSVerify int + expectedCertPath string + }{ + { + "docker.host = tcp://127.0.0.1:33293", + "tcp://127.0.0.1:33293", + 0, + "", + }, + { + "docker.host = tcp://127.0.0.1:33293", + "tcp://127.0.0.1:33293", + 0, + "", + }, + { + `docker.host = tcp://127.0.0.1:33293 + docker.host = tcp://127.0.0.1:4711 + `, + "tcp://127.0.0.1:4711", + 0, + "", + }, + {`docker.host = tcp://127.0.0.1:33293 + docker.host = tcp://127.0.0.1:4711 + docker.host = tcp://127.0.0.1:1234 + docker.tls.verify = 1 + `, + "tcp://127.0.0.1:1234", + 1, + "", + }, + { + "", + "", + 0, + "", + }, + { + `foo = bar + docker.host = tcp://127.0.0.1:1234 + `, + "tcp://127.0.0.1:1234", + 0, + "", + }, + { + "docker.host=tcp://127.0.0.1:33293", + "tcp://127.0.0.1:33293", + 0, + "", + }, + { + `#docker.host=tcp://127.0.0.1:33293`, + "", + 0, + "", + }, + { + `#docker.host = tcp://127.0.0.1:33293 + docker.host = tcp://127.0.0.1:4711 + docker.host = tcp://127.0.0.1:1234 + docker.cert.path=/tmp/certs`, + "tcp://127.0.0.1:1234", + 0, + "/tmp/certs", + }, + } + for _, tt := range tests { + tmpDir := filet.TmpDir(t, "") + os.Setenv("HOME", tmpDir) - defer func() { - os.Setenv("HOME", oldHome) - filet.CleanUp(t) - }() + defer func() { + os.Setenv("HOME", oldHome) + filet.CleanUp(t) + }() - content := readTCPropsFile() + _ = filet.File(t, path.Join(tmpDir, ".testcontainers.properties"), tt.content) - assert.Equal(t, content, properties, "TC props file should exist with content") + config := readTCPropsFile() + + assert.Equal(t, tt.expectedHost, config.Host, "Hosts do not match") + assert.Equal(t, tt.expectedTLSVerify, config.TLSVerify, "TLS verifies do not match") + assert.Equal(t, tt.expectedCertPath, config.CertPath, "Cert paths do not match") + } }) } diff --git a/go.mod b/go.mod index 71a0e20fef..4ca568fe33 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/go-redis/redis v6.15.9+incompatible github.com/go-sql-driver/mysql v1.6.0 github.com/google/uuid v1.3.0 + github.com/magiconair/properties v1.8.5 // indirect github.com/moby/sys/mount v0.2.0 // indirect github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect diff --git a/go.sum b/go.sum index 4ed0d8cc2a..fa3ded8650 100644 --- a/go.sum +++ b/go.sum @@ -365,6 +365,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= From af1986a417a441e72963e27b370c61d3053105f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Thu, 4 Nov 2021 18:59:38 +0100 Subject: [PATCH 090/219] chore: use TLS config from TC properties --- docker.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docker.go b/docker.go index e534dae154..3a04cfa1f6 100644 --- a/docker.go +++ b/docker.go @@ -533,6 +533,15 @@ func NewDockerProvider() (*DockerProvider, error) { opts = append(opts, client.WithHost(host)) } + // for further informacion, read https://docs.docker.com/engine/security/protect-access/ + if tcConfig.TLSVerify == 1 { + cacertPath := path.Join(tcConfig.CertPath, "ca.pem") + certPath := path.Join(tcConfig.CertPath, "cert.pem") + keyPath := path.Join(tcConfig.CertPath, "key.pem") + + opts = append(opts, client.WithTLSClientConfig(cacertPath, certPath, keyPath)) + } + c, err := client.NewClientWithOpts(opts...) if err != nil { return nil, err From 6e34a4a8c3d61f37278ed9d3113034a080477ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Thu, 4 Nov 2021 19:00:41 +0100 Subject: [PATCH 091/219] chore: simplify for fallback --- docker.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/docker.go b/docker.go index 3a04cfa1f6..cd91f2a7b1 100644 --- a/docker.go +++ b/docker.go @@ -549,13 +549,9 @@ func NewDockerProvider() (*DockerProvider, error) { _, err = c.Ping(context.TODO()) if err != nil { - if host != "" { - // fallback to environment - c, err = client.NewClientWithOpts(client.FromEnv) - if err != nil { - return nil, err - } - } else { + // fallback to environment + c, err = client.NewClientWithOpts(client.FromEnv) + if err != nil { return nil, err } } From 246c93250bdbf21922a0c4703fbc5c1194a44f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 5 Nov 2021 12:32:34 +0100 Subject: [PATCH 092/219] chore: add endline to error message --- docker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker.go b/docker.go index cd91f2a7b1..d1e1958667 100644 --- a/docker.go +++ b/docker.go @@ -579,7 +579,7 @@ func readTCPropsFile() TestContainersConfig { var cfg TestContainersConfig if err := properties.Decode(&cfg); err != nil { - fmt.Printf("invalid testcontainers properties file: %v", err) + fmt.Printf("invalid testcontainers properties file: %v\n", err) return TestContainersConfig{} } From 589944e55c78d5ab1bae92a191c44bce2274b913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 5 Nov 2021 12:33:09 +0100 Subject: [PATCH 093/219] chore: enrich error message --- docker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker.go b/docker.go index d1e1958667..2564c9725d 100644 --- a/docker.go +++ b/docker.go @@ -579,7 +579,7 @@ func readTCPropsFile() TestContainersConfig { var cfg TestContainersConfig if err := properties.Decode(&cfg); err != nil { - fmt.Printf("invalid testcontainers properties file: %v\n", err) + fmt.Printf("invalid testcontainers properties file, returning an empty Testcontainers configuration: %v\n", err) return TestContainersConfig{} } From b8d4d9f4d80bfe99a13bf28f405eed483b5d70bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 5 Nov 2021 12:55:47 +0100 Subject: [PATCH 094/219] chore: add a test when HOME is not set --- docker_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docker_test.go b/docker_test.go index 175e5978e8..1d8482e0b6 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1190,6 +1190,18 @@ func TestEntrypoint(t *testing.T) { } func TestReadTCPropsFile(t *testing.T) { + t.Run("HOME is not set", func(t *testing.T) { + oldHome := os.Getenv("HOME") + os.Unsetenv("HOME") + defer func() { + os.Setenv("HOME", oldHome) + }() + + config := readTCPropsFile() + + assert.Empty(t, config, "TC props file should not exist") + }) + t.Run("HOME does not contain TC props file", func(t *testing.T) { oldHome := os.Getenv("HOME") tmpDir := filet.TmpDir(t, "") From da9ffc78eeed5c63dd51651194ea62966b43c11a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 5 Nov 2021 12:56:37 +0100 Subject: [PATCH 095/219] fix: make docker.host optional --- docker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker.go b/docker.go index 2564c9725d..16ebcf6381 100644 --- a/docker.go +++ b/docker.go @@ -518,7 +518,7 @@ var _ ContainerProvider = (*DockerProvider)(nil) // or through Decode type TestContainersConfig struct { - Host string `properties:"docker.host"` + Host string `properties:"docker.host,default="` TLSVerify int `properties:"docker.tls.verify,default=0"` CertPath string `properties:"docker.cert.path,default="` } From 59a295c5c337a81a41d8b4da211eb22974555f24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 5 Nov 2021 16:55:26 +0100 Subject: [PATCH 096/219] chore: check TLSVerify only if there is a host --- docker.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docker.go b/docker.go index 16ebcf6381..e8bad7c66d 100644 --- a/docker.go +++ b/docker.go @@ -531,15 +531,15 @@ func NewDockerProvider() (*DockerProvider, error) { opts := []client.Opt{client.FromEnv} if host != "" { opts = append(opts, client.WithHost(host)) - } - // for further informacion, read https://docs.docker.com/engine/security/protect-access/ - if tcConfig.TLSVerify == 1 { - cacertPath := path.Join(tcConfig.CertPath, "ca.pem") - certPath := path.Join(tcConfig.CertPath, "cert.pem") - keyPath := path.Join(tcConfig.CertPath, "key.pem") + // for further informacion, read https://docs.docker.com/engine/security/protect-access/ + if tcConfig.TLSVerify == 1 { + cacertPath := path.Join(tcConfig.CertPath, "ca.pem") + certPath := path.Join(tcConfig.CertPath, "cert.pem") + keyPath := path.Join(tcConfig.CertPath, "key.pem") - opts = append(opts, client.WithTLSClientConfig(cacertPath, certPath, keyPath)) + opts = append(opts, client.WithTLSClientConfig(cacertPath, certPath, keyPath)) + } } c, err := client.NewClientWithOpts(opts...) From 1f92709b27e1115f051d550cc1bf694e5d649b49 Mon Sep 17 00:00:00 2001 From: Ilia Beliaev Date: Mon, 8 Nov 2021 19:30:32 +0300 Subject: [PATCH 097/219] Updated default ryuk image to testcontainers/ryuk:0.3.3. --- reaper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reaper.go b/reaper.go index be9818f229..070c7ff7bd 100644 --- a/reaper.go +++ b/reaper.go @@ -19,7 +19,7 @@ const ( TestcontainerLabelSessionID = TestcontainerLabel + ".sessionId" TestcontainerLabelIsReaper = TestcontainerLabel + ".reaper" - ReaperDefaultImage = "quay.io/testcontainers/ryuk:0.2.3" + ReaperDefaultImage = "testcontainers/ryuk:0.3.3" ) var reaper *Reaper // We would like to create reaper only once From 8c799e6de38c1390f73ed269b463c5b946585fb6 Mon Sep 17 00:00:00 2001 From: Ben Moss Date: Tue, 9 Nov 2021 16:23:03 -0500 Subject: [PATCH 098/219] Bump runc Fixes #355 --- go.mod | 11 ++++++++--- go.sum | 45 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 4ca568fe33..c1fcf40459 100644 --- a/go.mod +++ b/go.mod @@ -3,21 +3,26 @@ module github.com/testcontainers/testcontainers-go go 1.13 require ( - github.com/Flaque/filet v0.0.0-20201012163910-45f684403088 // indirect + github.com/Flaque/filet v0.0.0-20201012163910-45f684403088 github.com/Microsoft/hcsshim v0.8.16 // indirect github.com/cenkalti/backoff v2.2.1+incompatible github.com/docker/docker v20.10.9+incompatible github.com/docker/go-connections v0.4.0 github.com/go-redis/redis v6.15.9+incompatible github.com/go-sql-driver/mysql v1.6.0 + github.com/golang/protobuf v1.5.2 // indirect github.com/google/uuid v1.3.0 - github.com/magiconair/properties v1.8.5 // indirect + github.com/magiconair/properties v1.8.5 github.com/moby/sys/mount v0.2.0 // indirect + github.com/moby/sys/mountinfo v0.5.0 // indirect github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect + github.com/opencontainers/runc v1.0.2 // indirect github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.0 - golang.org/x/sys v0.0.0-20210324051608-47abb6519492 + golang.org/x/net v0.0.0-20211108170745-6635138e15ea // indirect + golang.org/x/sys v0.0.0-20211109184856-51b60fd695b3 + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/yaml.v2 v2.4.0 gotest.tools v2.2.0+incompatible ) diff --git a/go.sum b/go.sum index fa3ded8650..fe7e7d40fd 100644 --- a/go.sum +++ b/go.sum @@ -73,6 +73,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= @@ -86,12 +87,14 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= +github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= @@ -111,6 +114,7 @@ github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= @@ -170,6 +174,7 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -218,6 +223,7 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -251,6 +257,7 @@ github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblf github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -284,8 +291,10 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -295,8 +304,9 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -359,8 +369,9 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -384,8 +395,9 @@ github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQ github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= @@ -428,16 +440,19 @@ github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5X github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc93 h1:x2UMpOOVf3kQ8arv/EsDGwim8PTNqzL1/EYDr/+scOM= github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg= +github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -484,8 +499,9 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -621,8 +637,9 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211108170745-6635138e15ea h1:FosBMXtOc8Tp9Hbo4ltl1WJSrTVewZU8MPnTPY2HdH8= +golang.org/x/net v0.0.0-20211108170745-6635138e15ea/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -693,16 +710,21 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211109184856-51b60fd695b3 h1:T6tyxxvHMj2L1R2kZg0uNMpS8ZhB9lRa9XRGTCSA65w= +golang.org/x/sys v0.0.0-20211109184856-51b60fd695b3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -815,8 +837,11 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 4bb8975f6f2b2da0972ce9f3fa4f8bc8c08e7530 Mon Sep 17 00:00:00 2001 From: Peter Evans <18365890+peter-evans@users.noreply.github.com> Date: Tue, 16 Nov 2021 09:31:28 +0900 Subject: [PATCH 099/219] feat: additionally remove volumes by default on compose down --- compose.go | 2 +- compose_test.go | 30 ++++++++++++++++++++++++- testresources/docker-compose-volume.yml | 17 ++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 testresources/docker-compose-volume.yml diff --git a/compose.go b/compose.go index 882cd0ad50..b7b7ddbd19 100644 --- a/compose.go +++ b/compose.go @@ -88,7 +88,7 @@ func NewLocalDockerCompose(filePaths []string, identifier string) *LocalDockerCo // Down executes docker-compose down func (dc *LocalDockerCompose) Down() ExecError { - return executeCompose(dc, []string{"down", "--remove-orphans"}) + return executeCompose(dc, []string{"down", "--remove-orphans", "--volumes"}) } func (dc *LocalDockerCompose) getDockerComposeEnvironment() map[string]string { diff --git a/compose_test.go b/compose_test.go index 106a035b1f..5d1d42d8dc 100644 --- a/compose_test.go +++ b/compose_test.go @@ -368,6 +368,34 @@ func TestLocalDockerComposeWithMultipleComposeFiles(t *testing.T) { assertContainerEnvironmentVariables(t, containerNameNginx, present, absent) } +func TestLocalDockerComposeWithVolume(t *testing.T) { + path := "./testresources/docker-compose-volume.yml" + + identifier := strings.ToLower(uuid.New().String()) + + compose := NewLocalDockerCompose([]string{path}, identifier) + destroyFn := func() { + err := compose.Down() + checkIfError(t, err) + assertVolumeDoesNotExist(t, fmt.Sprintf("%s_mydata", identifier)) + } + defer destroyFn() + + err := compose. + WithCommand([]string{"up", "-d"}). + Invoke() + checkIfError(t, err) +} + +func assertVolumeDoesNotExist(t *testing.T, volume string) { + args := []string{"volume", "inspect", volume} + + output, _ := executeAndGetOutput("docker", args) + if !strings.Contains(output, "No such volume") { + t.Fatalf("Expected volume %q to not exist", volume) + } +} + func assertContainerEnvironmentVariables(t *testing.T, containerName string, present map[string]string, absent map[string]string) { args := []string{"exec", containerName, "env"} @@ -403,7 +431,7 @@ func executeAndGetOutput(command string, args []string) (string, ExecError) { cmd := exec.Command(command, args...) out, err := cmd.CombinedOutput() if err != nil { - return "", ExecError{Error: err} + return string(out), ExecError{Error: err} } return string(out), ExecError{Error: nil} diff --git a/testresources/docker-compose-volume.yml b/testresources/docker-compose-volume.yml new file mode 100644 index 0000000000..df31ee2a33 --- /dev/null +++ b/testresources/docker-compose-volume.yml @@ -0,0 +1,17 @@ +version: '3' +services: + nginx: + image: nginx:stable-alpine + volumes: + - type: volume + source: mydata + target: /data + volume: + nocopy: true + environment: + bar: ${bar} + ports: + - "9080:80" + +volumes: + mydata: From fd0ca1bfa8115efc7f9c6d3349905ffedee77587 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Nov 2021 11:25:25 +0000 Subject: [PATCH 100/219] chore(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 20.10.9+incompatible to 20.10.11+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Changelog](https://github.com/moby/moby/blob/master/CHANGELOG.md) - [Commits](https://github.com/docker/docker/compare/v20.10.9...v20.10.11) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c1fcf40459..7f5a0b94d8 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Flaque/filet v0.0.0-20201012163910-45f684403088 github.com/Microsoft/hcsshim v0.8.16 // indirect github.com/cenkalti/backoff v2.2.1+incompatible - github.com/docker/docker v20.10.9+incompatible + github.com/docker/docker v20.10.11+incompatible github.com/docker/go-connections v0.4.0 github.com/go-redis/redis v6.15.9+incompatible github.com/go-sql-driver/mysql v1.6.0 diff --git a/go.sum b/go.sum index fe7e7d40fd..fab1ae7245 100644 --- a/go.sum +++ b/go.sum @@ -198,8 +198,8 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.9+incompatible h1:JlsVnETOjM2RLQa0Cc1XCIspUdXW3Zenq9P54uXBm6k= -github.com/docker/docker v20.10.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.11+incompatible h1:OqzI/g/W54LczvhnccGqniFoQghHx3pklbLuhfXpqGo= +github.com/docker/docker v20.10.11+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= From 21719b769696380cb410e99a6ce33b054da5bfd8 Mon Sep 17 00:00:00 2001 From: Daniel Huckins Date: Wed, 24 Nov 2021 13:33:05 -0500 Subject: [PATCH 101/219] added interface for logger --- container.go | 5 ----- logger.go | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 logger.go diff --git a/container.go b/container.go index e8a489ee23..9b7e024509 100644 --- a/container.go +++ b/container.go @@ -3,8 +3,6 @@ package testcontainers import ( "context" "io" - "log" - "os" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" @@ -16,9 +14,6 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) -// Logger is the default log instance -var Logger = log.New(os.Stderr, "", log.LstdFlags) - // DeprecatedContainer shows methods that were supported before, but are now deprecated // Deprecated: Use Container type DeprecatedContainer interface { diff --git a/logger.go b/logger.go new file mode 100644 index 0000000000..f74b175876 --- /dev/null +++ b/logger.go @@ -0,0 +1,14 @@ +package testcontainers + +import ( + "log" + "os" +) + +// Logger is the default log instance +var Logger Logging = log.New(os.Stderr, "", log.LstdFlags) + +// Logging defines the Logger interface +type Logging interface { + Printf(format string, v ...interface{}) +} \ No newline at end of file From b08975953ab5e852f2d8ac7d3887e2ab7614d38f Mon Sep 17 00:00:00 2001 From: "Ingyu Hwang (Evan)" Date: Thu, 2 Dec 2021 11:57:37 +0900 Subject: [PATCH 102/219] docs: fix ryuk link --- docs/features/garbage_collector.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/garbage_collector.md b/docs/features/garbage_collector.md index b34cd8bb70..54d1d9f007 100644 --- a/docs/features/garbage_collector.md +++ b/docs/features/garbage_collector.md @@ -25,7 +25,7 @@ on test completion. ## Ryuk -[https://github.com/testcontainers/moby-ryuk](Ryuk) (also referred to as +[Ryuk](https://github.com/testcontainers/moby-ryuk) (also referred to as `Reaper` in this package) removes containers/networks/volumes created by Testcontainers-Go after a specified delay. It is a project developed by the TestContainers organization and is used across the board for many of the From 4f808bd90cb4e8e27b7da6a0e92b074978bab8bd Mon Sep 17 00:00:00 2001 From: Ankan Anurag Date: Wed, 15 Dec 2021 14:18:36 +0100 Subject: [PATCH 103/219] remember service map from all docker compose files --- compose.go | 8 +++++++- compose_test.go | 4 +++- testresources/docker-compose-postgres.yml | 6 ++++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 testresources/docker-compose-postgres.yml diff --git a/compose.go b/compose.go index b7b7ddbd19..268cec302d 100644 --- a/compose.go +++ b/compose.go @@ -198,7 +198,13 @@ func (dc *LocalDockerCompose) validate() error { return err } - dc.Services = c.Services + if dc.Services == nil { + dc.Services = c.Services + } else { + for k, v := range c.Services { + dc.Services[k] = v + } + } } return nil diff --git a/compose_test.go b/compose_test.go index 5d1d42d8dc..364daab342 100644 --- a/compose_test.go +++ b/compose_test.go @@ -333,6 +333,7 @@ func TestLocalDockerComposeWithEnvironment(t *testing.T) { func TestLocalDockerComposeWithMultipleComposeFiles(t *testing.T) { composeFiles := []string{ "testresources/docker-compose-simple.yml", + "testresources/docker-compose-postgres.yml", "testresources/docker-compose-override.yml", } @@ -354,9 +355,10 @@ func TestLocalDockerComposeWithMultipleComposeFiles(t *testing.T) { Invoke() checkIfError(t, err) - assert.Equal(t, 2, len(compose.Services)) + assert.Equal(t, 3, len(compose.Services)) assert.Contains(t, compose.Services, "nginx") assert.Contains(t, compose.Services, "mysql") + assert.Contains(t, compose.Services, "postgres") containerNameNginx := compose.Identifier + "_nginx_1" diff --git a/testresources/docker-compose-postgres.yml b/testresources/docker-compose-postgres.yml new file mode 100644 index 0000000000..74041af503 --- /dev/null +++ b/testresources/docker-compose-postgres.yml @@ -0,0 +1,6 @@ +version: '3' +services: + postgres: + image: postgres:14 + ports: + - "15432:5432" From 2e1881284fc0b9e1322b708e0ff1d13c7506d2d1 Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Wed, 1 Dec 2021 21:06:33 +0100 Subject: [PATCH 104/219] Upgrade dependencies to latest versions - apply major upgrades for gopkg.in/yaml, gotest.tools and github.com/cenkalti/backoff - get rid of obsolete github.com/pkg/errors - replace github.com/Flaque/filet with standard library - make error ignores explicit where possible --- compose.go | 6 ++--- compose_test.go | 1 + container.go | 5 +++-- container_test.go | 2 +- docker.go | 29 ++++++++++++------------ docker_test.go | 54 ++++++++++++++++++--------------------------- generic.go | 9 ++++---- go.mod | 12 +++++----- go.sum | 19 +++++++++------- logconsumer_test.go | 13 ++++++----- reaper.go | 10 ++++----- wait/host_port.go | 7 +++--- 12 files changed, 78 insertions(+), 89 deletions(-) diff --git a/compose.go b/compose.go index b7b7ddbd19..120fbb5a36 100644 --- a/compose.go +++ b/compose.go @@ -16,8 +16,9 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/client" + "gopkg.in/yaml.v3" + "github.com/testcontainers/testcontainers-go/wait" - "gopkg.in/yaml.v2" ) const ( @@ -77,7 +78,7 @@ func NewLocalDockerCompose(filePaths []string, identifier string) *LocalDockerCo dc.absComposeFilePaths[i] = abs } - dc.validate() + _ = dc.validate() dc.Identifier = strings.ToLower(identifier) dc.waitStrategySupplied = false @@ -106,7 +107,6 @@ func (dc *LocalDockerCompose) getDockerComposeEnvironment() map[string]string { } func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { - cli, err := client.NewClientWithOpts(client.FromEnv) if err != nil { return err diff --git a/compose_test.go b/compose_test.go index 5d1d42d8dc..7530c575f1 100644 --- a/compose_test.go +++ b/compose_test.go @@ -9,6 +9,7 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" + "github.com/testcontainers/testcontainers-go/wait" ) diff --git a/container.go b/container.go index e8a489ee23..b458bc3563 100644 --- a/container.go +++ b/container.go @@ -2,6 +2,8 @@ package testcontainers import ( "context" + "errors" + "fmt" "io" "log" "os" @@ -11,7 +13,6 @@ import ( "github.com/docker/docker/pkg/archive" "github.com/docker/go-connections/nat" - "github.com/pkg/errors" "github.com/testcontainers/testcontainers-go/wait" ) @@ -120,7 +121,7 @@ func (t ProviderType) GetProvider() (GenericProvider, error) { case ProviderDocker: provider, err := NewDockerProvider() if err != nil { - return nil, errors.Wrap(err, "failed to create Docker provider") + return nil, fmt.Errorf("%w, failed to create Docker provider", err) } return provider, nil } diff --git a/container_test.go b/container_test.go index 6c140e104d..89db7e8b85 100644 --- a/container_test.go +++ b/container_test.go @@ -4,6 +4,7 @@ import ( "archive/tar" "bytes" "context" + "errors" "fmt" "io" "io/ioutil" @@ -11,7 +12,6 @@ import ( "testing" "time" - "github.com/pkg/errors" "github.com/testcontainers/testcontainers-go/wait" ) diff --git a/docker.go b/docker.go index 2a64dd473f..158556705b 100644 --- a/docker.go +++ b/docker.go @@ -5,18 +5,18 @@ import ( "bytes" "context" "encoding/binary" + "errors" "fmt" "io" "io/ioutil" "net/url" "os" "os/exec" - "path" "path/filepath" "strings" "time" - "github.com/cenkalti/backoff" + "github.com/cenkalti/backoff/v4" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/mount" @@ -28,7 +28,6 @@ import ( "github.com/google/uuid" "github.com/magiconair/properties" "github.com/moby/term" - "github.com/pkg/errors" "github.com/testcontainers/testcontainers-go/wait" ) @@ -453,7 +452,7 @@ func (c *DockerContainer) StartLogProducer(ctx context.Context) error { } logType := h[0] if logType > 2 { - fmt.Fprintf(os.Stderr, fmt.Sprintf("received invalid log type: %d", logType)) + _, _ = fmt.Fprintf(os.Stderr, "received invalid log type: %d", logType) // sometimes docker returns logType = 3 which is an undocumented log type, so treat it as stdout logType = 1 } @@ -465,7 +464,7 @@ func (c *DockerContainer) StartLogProducer(ctx context.Context) error { _, err = r.Read(b) if err != nil { // TODO: add-logger: use logger to log out this error - fmt.Fprintf(os.Stderr, "error occurred reading log with known length %s", err.Error()) + _, _ = fmt.Fprintf(os.Stderr, "error occurred reading log with known length %s", err.Error()) continue } for _, c := range c.consumers { @@ -534,9 +533,9 @@ func NewDockerProvider() (*DockerProvider, error) { // for further informacion, read https://docs.docker.com/engine/security/protect-access/ if tcConfig.TLSVerify == 1 { - cacertPath := path.Join(tcConfig.CertPath, "ca.pem") - certPath := path.Join(tcConfig.CertPath, "cert.pem") - keyPath := path.Join(tcConfig.CertPath, "key.pem") + cacertPath := filepath.Join(tcConfig.CertPath, "ca.pem") + certPath := filepath.Join(tcConfig.CertPath, "cert.pem") + keyPath := filepath.Join(tcConfig.CertPath, "key.pem") opts = append(opts, client.WithTLSClientConfig(cacertPath, certPath, keyPath)) } @@ -570,7 +569,7 @@ func readTCPropsFile() TestContainersConfig { return TestContainersConfig{} } - tcProp := path.Join(home, ".testcontainers.properties") + tcProp := filepath.Join(home, ".testcontainers.properties") // init from a file properties, err := properties.LoadFile(tcProp, properties.UTF8) if err != nil { @@ -626,7 +625,7 @@ func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (st return "", err } - resp.Body.Close() + _ = resp.Body.Close() return repoTag, nil } @@ -678,11 +677,11 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque if !req.SkipReaper { r, err := NewReaper(ctx, sessionID.String(), p, req.ReaperImage) if err != nil { - return nil, errors.Wrap(err, "creating reaper failed") + return nil, fmt.Errorf("%w: creating reaper failed", err) } termSignal, err = r.Connect() if err != nil { - return nil, errors.Wrap(err, "connecting to reaper failed") + return nil, fmt.Errorf("%w: connecting to reaper failed", err) } for k, v := range r.Labels() { if _, ok := req.Labels[k]; !ok { @@ -871,7 +870,7 @@ func (p *DockerProvider) RunContainer(ctx context.Context, req ContainerRequest) } if err := c.Start(ctx); err != nil { - return c, errors.Wrap(err, "could not start container") + return c, fmt.Errorf("%w: could not start container", err) } return c, nil @@ -948,11 +947,11 @@ func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) if !req.SkipReaper { r, err := NewReaper(ctx, sessionID.String(), p, req.ReaperImage) if err != nil { - return nil, errors.Wrap(err, "creating network reaper failed") + return nil, fmt.Errorf("%w: creating network reaper failed", err) } termSignal, err = r.Connect() if err != nil { - return nil, errors.Wrap(err, "connecting to network reaper failed") + return nil, fmt.Errorf("%w: connecting to network reaper failed", err) } for k, v := range r.Labels() { if _, ok := req.Labels[k]; !ok { diff --git a/docker_test.go b/docker_test.go index f888ca8279..0f5e36f1bc 100644 --- a/docker_test.go +++ b/docker_test.go @@ -2,6 +2,7 @@ package testcontainers import ( "context" + "database/sql" "encoding/json" "errors" "fmt" @@ -10,21 +11,20 @@ import ( "net/http" "os" "os/exec" - "path" "path/filepath" "regexp" "strings" "testing" "time" - "github.com/Flaque/filet" "github.com/stretchr/testify/assert" + "gotest.tools/v3/env" + "gotest.tools/v3/fs" "github.com/docker/docker/errdefs" "github.com/docker/docker/api/types/volume" - "database/sql" // Import mysql into the scope of this package (required) _ "github.com/go-sql-driver/mysql" @@ -33,6 +33,7 @@ import ( "github.com/docker/docker/client" "github.com/docker/go-connections/nat" "github.com/go-redis/redis" + "github.com/testcontainers/testcontainers-go/wait" ) @@ -288,7 +289,7 @@ func TestContainerStartsWithoutTheReaper(t *testing.T) { Image: "nginx", ExposedPorts: []string{ "80/tcp", - }, + "gotest.tools/assert"}, SkipReaper: true, }, Started: true, @@ -995,7 +996,7 @@ func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { t.Log("terminated container") }() - w.Close() + _ = w.Close() out, _ := ioutil.ReadAll(r) os.Stdout = rescueStdout temp := strings.Split(string(out), "\n") @@ -1191,11 +1192,8 @@ func TestEntrypoint(t *testing.T) { func TestReadTCPropsFile(t *testing.T) { t.Run("HOME is not set", func(t *testing.T) { - oldHome := os.Getenv("HOME") - os.Unsetenv("HOME") - defer func() { - os.Setenv("HOME", oldHome) - }() + tmpDir := fs.NewDir(t, os.TempDir()) + env.Patch(t, "HOME", tmpDir.Path()) config := readTCPropsFile() @@ -1203,13 +1201,8 @@ func TestReadTCPropsFile(t *testing.T) { }) t.Run("HOME does not contain TC props file", func(t *testing.T) { - oldHome := os.Getenv("HOME") - tmpDir := filet.TmpDir(t, "") - os.Setenv("HOME", tmpDir) - defer func() { - os.Setenv("HOME", oldHome) - filet.CleanUp(t) - }() + tmpDir := fs.NewDir(t, os.TempDir()) + env.Patch(t, "HOME", tmpDir.Path()) config := readTCPropsFile() @@ -1217,8 +1210,6 @@ func TestReadTCPropsFile(t *testing.T) { }) t.Run("HOME contains TC properties file", func(t *testing.T) { - oldHome := os.Getenv("HOME") - tests := []struct { content string expectedHost string @@ -1291,15 +1282,12 @@ func TestReadTCPropsFile(t *testing.T) { }, } for _, tt := range tests { - tmpDir := filet.TmpDir(t, "") - os.Setenv("HOME", tmpDir) - - defer func() { - os.Setenv("HOME", oldHome) - filet.CleanUp(t) - }() - - _ = filet.File(t, path.Join(tmpDir, ".testcontainers.properties"), tt.content) + tmpDir := fs.NewDir(t, os.TempDir()) + env.Patch(t, "HOME", tmpDir.Path()) + if err := ioutil.WriteFile(tmpDir.Join(".testcontainers.properties"), []byte(tt.content), 0o600); err != nil { + t.Errorf("Failed to create the file: %v", err) + return + } config := readTCPropsFile() @@ -1351,7 +1339,7 @@ func ExampleContainer_Start() { ContainerRequest: req, }) defer nginxC.Terminate(ctx) - nginxC.Start(ctx) + _ = nginxC.Start(ctx) } func ExampleContainer_MappedPort() { @@ -1368,7 +1356,7 @@ func ExampleContainer_MappedPort() { defer nginxC.Terminate(ctx) ip, _ := nginxC.Host(ctx) port, _ := nginxC.MappedPort(ctx, "80") - http.Get(fmt.Sprintf("http://%s:%s", ip, port.Port())) + _, _ = http.Get(fmt.Sprintf("http://%s:%s", ip, port.Port())) } func TestContainerCreationWithBindAndVolume(t *testing.T) { @@ -1570,7 +1558,7 @@ func TestDockerContainerCopyFileToContainer(t *testing.T) { defer nginxC.Terminate(ctx) copiedFileName := "hello_copy.sh" - nginxC.CopyFileToContainer(ctx, "./testresources/hello.sh", "/"+copiedFileName, 700) + _ = nginxC.CopyFileToContainer(ctx, "./testresources/hello.sh", "/"+copiedFileName, 700) c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) if err != nil { t.Fatal(err) @@ -1598,7 +1586,7 @@ func TestDockerContainerCopyFileFromContainer(t *testing.T) { defer nginxC.Terminate(ctx) copiedFileName := "hello_copy.sh" - nginxC.CopyFileToContainer(ctx, "./testresources/hello.sh", "/"+copiedFileName, 700) + _ = nginxC.CopyFileToContainer(ctx, "./testresources/hello.sh", "/"+copiedFileName, 700) c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) if err != nil { t.Fatal(err) @@ -1633,7 +1621,7 @@ func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { defer nginxC.Terminate(ctx) copiedFileName := "hello_copy.sh" - nginxC.CopyFileToContainer(ctx, "./testresources/empty.sh", "/"+copiedFileName, 700) + _ = nginxC.CopyFileToContainer(ctx, "./testresources/empty.sh", "/"+copiedFileName, 700) c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) if err != nil { t.Fatal(err) diff --git a/generic.go b/generic.go index 5c611e0905..2c21e7136c 100644 --- a/generic.go +++ b/generic.go @@ -2,8 +2,7 @@ package testcontainers import ( "context" - - "github.com/pkg/errors" + "fmt" ) // GenericContainerRequest represents parameters to a generic container @@ -27,7 +26,7 @@ func GenericNetwork(ctx context.Context, req GenericNetworkRequest) (Network, er } network, err := provider.CreateNetwork(ctx, req.NetworkRequest) if err != nil { - return nil, errors.Wrap(err, "failed to create network") + return nil, fmt.Errorf("%w: failed to create network", err) } return network, nil @@ -42,12 +41,12 @@ func GenericContainer(ctx context.Context, req GenericContainerRequest) (Contain c, err := provider.CreateContainer(ctx, req.ContainerRequest) if err != nil { - return nil, errors.Wrap(err, "failed to create container") + return nil, fmt.Errorf("%w: failed to create container", err) } if req.Started { if err := c.Start(ctx); err != nil { - return c, errors.Wrap(err, "failed to start container") + return c, fmt.Errorf("%w: failed to start container", err) } } diff --git a/go.mod b/go.mod index 7f5a0b94d8..e52a382795 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,8 @@ module github.com/testcontainers/testcontainers-go go 1.13 require ( - github.com/Flaque/filet v0.0.0-20201012163910-45f684403088 github.com/Microsoft/hcsshim v0.8.16 // indirect - github.com/cenkalti/backoff v2.2.1+incompatible + github.com/cenkalti/backoff/v4 v4.1.2 github.com/docker/docker v20.10.11+incompatible github.com/docker/go-connections v0.4.0 github.com/go-redis/redis v6.15.9+incompatible @@ -15,14 +14,13 @@ require ( github.com/magiconair/properties v1.8.5 github.com/moby/sys/mount v0.2.0 // indirect github.com/moby/sys/mountinfo v0.5.0 // indirect - github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 + github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect github.com/opencontainers/runc v1.0.2 // indirect - github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.0 golang.org/x/net v0.0.0-20211108170745-6635138e15ea // indirect - golang.org/x/sys v0.0.0-20211109184856-51b60fd695b3 + golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 google.golang.org/protobuf v1.27.1 // indirect - gopkg.in/yaml.v2 v2.4.0 - gotest.tools v2.2.0+incompatible + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b + gotest.tools/v3 v3.0.3 ) diff --git a/go.sum b/go.sum index fab1ae7245..1ea9e7b20d 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= @@ -37,8 +39,6 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Flaque/filet v0.0.0-20201012163910-45f684403088 h1:PnnQln5IGbhLeJOi6hVs+lCeF+B1dRfFKPGXUAez0Ww= -github.com/Flaque/filet v0.0.0-20201012163910-45f684403088/go.mod h1:TK+jB3mBs+8ZMWhU5BqZKnZWJ1MrLo8etNVg51ueTBo= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= @@ -82,8 +82,8 @@ github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7 github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= +github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= @@ -402,6 +402,8 @@ github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGq github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -505,7 +507,6 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= @@ -713,9 +714,10 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211109184856-51b60fd695b3 h1:T6tyxxvHMj2L1R2kZg0uNMpS8ZhB9lRa9XRGTCSA65w= -golang.org/x/sys v0.0.0-20211109184856-51b60fd695b3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -871,8 +873,9 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= diff --git a/logconsumer_test.go b/logconsumer_test.go index 854b449468..2a207e8f36 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -7,9 +7,11 @@ import ( "testing" "time" + "gotest.tools/v3/assert" + "github.com/docker/docker/client" + "github.com/testcontainers/testcontainers-go/wait" - "gotest.tools/assert" ) const lastMessage = "DONE" @@ -96,13 +98,13 @@ func Test_LogConsumerGetsCalled(t *testing.T) { case <-time.After(5 * time.Second): t.Fatal("never received final log message") } - c.StopLogProducer() + _ = c.StopLogProducer() // get rid of the server "ready" log g.Msgs = g.Msgs[1:] assert.DeepEqual(t, []string{"echo hello\n", "echo there\n"}, g.Msgs) - c.Terminate(ctx) + _ = c.Terminate(ctx) } type TestLogTypeConsumer struct { @@ -173,14 +175,13 @@ func Test_ShouldRecognizeLogTypes(t *testing.T) { } <-g.Ack - c.StopLogProducer() + _ = c.StopLogProducer() assert.DeepEqual(t, map[string]string{ StdoutLog: "echo this-is-stdout\n", StderrLog: "echo this-is-stderr\n", }, g.LogTypes) - c.Terminate(ctx) - + _ = c.Terminate(ctx) } func TestContainerLogWithErrClosed(t *testing.T) { diff --git a/reaper.go b/reaper.go index 070c7ff7bd..ba621db189 100644 --- a/reaper.go +++ b/reaper.go @@ -4,14 +4,14 @@ import ( "bufio" "context" "fmt" - "github.com/docker/go-connections/nat" - "github.com/testcontainers/testcontainers-go/wait" "net" "strings" "sync" "time" - "github.com/pkg/errors" + "github.com/docker/go-connections/nat" + + "github.com/testcontainers/testcontainers-go/wait" ) const ( @@ -19,7 +19,7 @@ const ( TestcontainerLabelSessionID = TestcontainerLabel + ".sessionId" TestcontainerLabelIsReaper = TestcontainerLabel + ".reaper" - ReaperDefaultImage = "testcontainers/ryuk:0.3.3" + ReaperDefaultImage = "docker.io/testcontainers/ryuk:0.3.3" ) var reaper *Reaper // We would like to create reaper only once @@ -101,7 +101,7 @@ func reaperImage(reaperImageName string) string { func (r *Reaper) Connect() (chan bool, error) { conn, err := net.DialTimeout("tcp", r.Endpoint, 10*time.Second) if err != nil { - return nil, errors.Wrap(err, "Connecting to Ryuk on "+r.Endpoint+" failed") + return nil, fmt.Errorf("%w: Connecting to Ryuk on %s failed", err, r.Endpoint) } terminationSignal := make(chan bool) diff --git a/wait/host_port.go b/wait/host_port.go index d862e9dcc4..d53218941e 100644 --- a/wait/host_port.go +++ b/wait/host_port.go @@ -2,14 +2,13 @@ package wait import ( "context" + "errors" "fmt" "net" "os" "strconv" "time" - "github.com/pkg/errors" - "github.com/docker/go-connections/nat" ) @@ -96,7 +95,7 @@ func (hp *HostPortStrategy) WaitUntilReady(ctx context.Context, target StrategyT } return err } else { - conn.Close() + _ = conn.Close() break } } @@ -109,7 +108,7 @@ func (hp *HostPortStrategy) WaitUntilReady(ctx context.Context, target StrategyT } exitCode, err := target.Exec(ctx, []string{"/bin/sh", "-c", command}) if err != nil { - return errors.Wrapf(err, "host port waiting failed") + return fmt.Errorf("%w, host port waiting failed", err) } if exitCode == 0 { From 287b9e3577829d95d28c6021507906429d500aac Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Wed, 24 Nov 2021 21:11:40 +0100 Subject: [PATCH 105/219] Replace BindMounts and VolumeMounts with Mounts - introduce specific types for different mount sources - support read-only mount - introduce convenience methods to support common mount scenarios - add validation to avoid duplicate mount targets --- container.go | 20 +++++- container_test.go | 75 +++++++++++++++++++- docker.go | 25 ++----- docker_test.go | 9 ++- mounts.go | 136 +++++++++++++++++++++++++++++++++++ mounts_test.go | 176 ++++++++++++++++++++++++++++++++++++++++++++++ reaper.go | 4 +- 7 files changed, 415 insertions(+), 30 deletions(-) create mode 100644 mounts.go create mode 100644 mounts_test.go diff --git a/container.go b/container.go index b458bc3563..c0b922d9b0 100644 --- a/container.go +++ b/container.go @@ -10,7 +10,6 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" - "github.com/docker/docker/pkg/archive" "github.com/docker/go-connections/nat" @@ -89,8 +88,7 @@ type ContainerRequest struct { ExposedPorts []string // allow specifying protocol info Cmd []string Labels map[string]string - BindMounts map[string]string - VolumeMounts map[string]string + Mounts ContainerMounts Tmpfs map[string]string RegistryCred string WaitingFor wait.Strategy @@ -135,6 +133,7 @@ func (c *ContainerRequest) Validate() error { validationMethods := []func() error{ c.validateContextAndImage, c.validateContextOrImageIsSpecified, + c.validateMounts, } var err error @@ -200,3 +199,18 @@ func (c *ContainerRequest) validateContextOrImageIsSpecified() error { return nil } + +func (c *ContainerRequest) validateMounts() error { + targets := make(map[string]bool, len(c.Mounts)) + + for idx := range c.Mounts { + m := c.Mounts[idx] + targetPath := m.Target.String() + if targets[targetPath] { + return fmt.Errorf("%w: %s", ErrDuplicateMountTarget, targetPath) + } else { + targets[targetPath] = true + } + } + return nil +} diff --git a/container_test.go b/container_test.go index 89db7e8b85..088481ac4b 100644 --- a/container_test.go +++ b/container_test.go @@ -12,6 +12,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/testcontainers/testcontainers-go/wait" ) @@ -50,6 +52,22 @@ func Test_ContainerValidation(t *testing.T) { }, }, }, + ContainerValidationTestCase{ + Name: "Can mount same source to multiple targets", + ExpectedError: nil, + ContainerRequest: ContainerRequest{ + Image: "redis:latest", + Mounts: Mounts(BindMount("/data", "/srv"), BindMount("/data", "/data")), + }, + }, + ContainerValidationTestCase{ + Name: "Cannot mount multiple sources to same target", + ExpectedError: errors.New("duplicate mount target detected: /data"), + ContainerRequest: ContainerRequest{ + Image: "redis:latest", + Mounts: Mounts(BindMount("/srv", "/data"), BindMount("/data", "/data")), + }, + }, } for _, testCase := range testTable { @@ -66,7 +84,6 @@ func Test_ContainerValidation(t *testing.T) { } }) } - } func Test_GetDockerfile(t *testing.T) { @@ -341,3 +358,59 @@ func createTestContainer(t *testing.T, ctx context.Context) int { return port.Int() } + +func TestBindMount(t *testing.T) { + type args struct { + hostPath string + mountTarget ContainerMountTarget + } + tests := []struct { + name string + args args + want ContainerMount + }{ + { + name: "/var/run/docker.sock:/var/run/docker.sock", + args: args{hostPath: "/var/run/docker.sock", mountTarget: "/var/run/docker.sock"}, + want: ContainerMount{Source: BindMountSource{HostPath: "/var/run/docker.sock"}, Target: "/var/run/docker.sock"}, + }, + { + name: "/var/lib/app/data:/data", + args: args{hostPath: "/var/lib/app/data", mountTarget: "/data"}, + want: ContainerMount{Source: BindMountSource{HostPath: "/var/lib/app/data"}, Target: "/data"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, BindMount(tt.args.hostPath, tt.args.mountTarget), "BindMount(%v, %v)", tt.args.hostPath, tt.args.mountTarget) + }) + } +} + +func TestVolumeMount(t *testing.T) { + type args struct { + volumeName string + mountTarget ContainerMountTarget + } + tests := []struct { + name string + args args + want ContainerMount + }{ + { + name: "sample-data:/data", + args: args{volumeName: "sample-data", mountTarget: "/data"}, + want: ContainerMount{Source: VolumeMountSource{Name: "sample-data"}, Target: "/data"}, + }, + { + name: "web:/var/nginx/html", + args: args{volumeName: "web", mountTarget: "/var/nginx/html"}, + want: ContainerMount{Source: VolumeMountSource{Name: "web"}, Target: "/var/nginx/html"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, VolumeMount(tt.args.volumeName, tt.args.mountTarget), "VolumeMount(%v, %v)", tt.args.volumeName, tt.args.mountTarget) + }) + } +} diff --git a/docker.go b/docker.go index 158556705b..b2d9f1ec26 100644 --- a/docker.go +++ b/docker.go @@ -19,7 +19,6 @@ import ( "github.com/cenkalti/backoff/v4" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/mount" "github.com/docker/docker/api/types/network" "github.com/docker/docker/client" "github.com/docker/docker/errdefs" @@ -32,8 +31,12 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) -// Implement interfaces -var _ Container = (*DockerContainer)(nil) +var ( + // Implement interfaces + _ Container = (*DockerContainer)(nil) + + ErrDuplicateMountTarget = errors.New("duplicate mount target detected") +) const ( Bridge = "bridge" // Bridge network name (as well as driver) @@ -741,21 +744,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque } // prepare mounts - mounts := []mount.Mount{} - for innerPath, hostPath := range req.BindMounts { - mounts = append(mounts, mount.Mount{ - Type: mount.TypeBind, - Source: hostPath, - Target: innerPath, - }) - } - for innerPath, volumeName := range req.VolumeMounts { - mounts = append(mounts, mount.Mount{ - Type: mount.TypeVolume, - Source: volumeName, - Target: innerPath, - }) - } + mounts := req.Mounts.PrepareMounts() hostConfig := &container.HostConfig{ PortBindings: exposedPortMap, diff --git a/docker_test.go b/docker_test.go index 0f5e36f1bc..ab8bc766bb 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1391,11 +1391,10 @@ func TestContainerCreationWithBindAndVolume(t *testing.T) { // Create the container that writes into the mounted volume. bashC, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: ContainerRequest{ - Image: "bash", - BindMounts: map[string]string{"/hello.sh": absPath}, - VolumeMounts: map[string]string{"/data": volumeName}, - Cmd: []string{"bash", "/hello.sh"}, - WaitingFor: wait.ForLog("done"), + Image: "bash", + Mounts: Mounts(BindMount(absPath, "/hello.sh"), VolumeMount(volumeName, "/data")), + Cmd: []string{"bash", "/hello.sh"}, + WaitingFor: wait.ForLog("done"), }, Started: true, }) diff --git a/mounts.go b/mounts.go new file mode 100644 index 0000000000..a9d5f6c01f --- /dev/null +++ b/mounts.go @@ -0,0 +1,136 @@ +package testcontainers + +import ( + "fmt" + + "github.com/docker/docker/api/types/mount" +) + +type BindMounter interface { + GetBindOptions() *mount.BindOptions +} + +type VolumeMounter interface { + GetVolumeOptions() *mount.VolumeOptions +} + +type TmpfsMounter interface { + GetTmpfsOptions() *mount.TmpfsOptions +} + +type ContainerMountSource interface { + fmt.Stringer + Type() mount.Type +} + +type BindMountSource struct { + *mount.BindOptions + HostPath string +} + +func (s BindMountSource) String() string { + return s.HostPath +} + +func (BindMountSource) Type() mount.Type { + return mount.TypeBind +} +func (s BindMountSource) GetBindOptions() *mount.BindOptions { + return s.BindOptions +} + +type VolumeMountSource struct { + *mount.VolumeOptions + Name string +} + +func (s VolumeMountSource) String() string { + return s.Name +} + +func (VolumeMountSource) Type() mount.Type { + return mount.TypeVolume +} + +func (s VolumeMountSource) GetVolumeOptions() *mount.VolumeOptions { + return s.VolumeOptions +} + +type TmpfsMountSource struct { + *mount.TmpfsOptions +} + +func (s TmpfsMountSource) String() string { + return "" +} + +func (TmpfsMountSource) Type() mount.Type { + return mount.TypeTmpfs +} + +func (s TmpfsMountSource) GetTmpfsOptions() *mount.TmpfsOptions { + return s.TmpfsOptions +} + +type ContainerMountTarget string + +func (t ContainerMountTarget) String() string { + return string(t) +} + +func BindMount(hostPath string, mountTarget ContainerMountTarget) ContainerMount { + return ContainerMount{ + Source: BindMountSource{HostPath: hostPath}, + Target: mountTarget, + } +} + +func VolumeMount(volumeName string, mountTarget ContainerMountTarget) ContainerMount { + return ContainerMount{ + Source: VolumeMountSource{Name: volumeName}, + Target: mountTarget, + } +} + +func Mounts(mounts ...ContainerMount) ContainerMounts { + return mounts +} + +// ContainerMount models a mount into a container +type ContainerMount struct { + // Source is typically either a BindMountSource or a VolumeMountSource + Source ContainerMountSource + // Target is the path where the mount should be mounted within the container + Target ContainerMountTarget + // ReadOnly determines if the mount should be read-only + ReadOnly bool +} + +type ContainerMounts []ContainerMount + +func (m ContainerMounts) PrepareMounts() []mount.Mount { + mounts := make([]mount.Mount, 0, len(m)) + + for idx := range m { + m := m[idx] + containerMount := mount.Mount{ + Type: m.Source.Type(), + Source: m.Source.String(), + ReadOnly: m.ReadOnly, + Target: m.Target.String(), + } + + switch typedMounter := m.Source.(type) { + case BindMounter: + containerMount.BindOptions = typedMounter.GetBindOptions() + case VolumeMounter: + containerMount.VolumeOptions = typedMounter.GetVolumeOptions() + case TmpfsMounter: + containerMount.TmpfsOptions = typedMounter.GetTmpfsOptions() + } + + mounts = append(mounts, containerMount) + } + + return mounts +} diff --git a/mounts_test.go b/mounts_test.go new file mode 100644 index 0000000000..61f22ac707 --- /dev/null +++ b/mounts_test.go @@ -0,0 +1,176 @@ +package testcontainers + +import ( + "testing" + + "github.com/docker/docker/api/types/mount" + "github.com/stretchr/testify/assert" +) + +func TestContainerMounts_PrepareMounts(t *testing.T) { + t.Parallel() + tests := []struct { + name string + mounts ContainerMounts + want []mount.Mount + }{ + { + name: "Empty", + mounts: nil, + want: make([]mount.Mount, 0), + }, + { + name: "Single bind mount", + mounts: ContainerMounts{{Source: BindMountSource{HostPath: "/var/lib/app/data"}, Target: "/data"}}, + want: []mount.Mount{ + { + Type: mount.TypeBind, + Source: "/var/lib/app/data", + Target: "/data", + }, + }, + }, + { + name: "Single bind mount - read-only", + mounts: ContainerMounts{{Source: BindMountSource{HostPath: "/var/lib/app/data"}, Target: "/data", ReadOnly: true}}, + want: []mount.Mount{ + { + Type: mount.TypeBind, + Source: "/var/lib/app/data", + Target: "/data", + ReadOnly: true, + }, + }, + }, + { + name: "Single bind mount - with options", + mounts: ContainerMounts{ + { + Source: BindMountSource{ + HostPath: "/var/lib/app/data", + BindOptions: &mount.BindOptions{ + Propagation: mount.PropagationPrivate, + }, + }, + Target: "/data", + }, + }, + want: []mount.Mount{ + { + Type: mount.TypeBind, + Source: "/var/lib/app/data", + Target: "/data", + BindOptions: &mount.BindOptions{ + Propagation: mount.PropagationPrivate, + }, + }, + }, + }, + { + name: "Single volume mount", + mounts: ContainerMounts{{Source: VolumeMountSource{Name: "app-data"}, Target: "/data"}}, + want: []mount.Mount{ + { + Type: mount.TypeVolume, + Source: "app-data", + Target: "/data", + }, + }, + }, + { + name: "Single volume mount - read-only", + mounts: ContainerMounts{{Source: VolumeMountSource{Name: "app-data"}, Target: "/data", ReadOnly: true}}, + want: []mount.Mount{ + { + Type: mount.TypeVolume, + Source: "app-data", + Target: "/data", + ReadOnly: true, + }, + }, + }, + { + name: "Single volume mount - with options", + mounts: ContainerMounts{ + { + Source: VolumeMountSource{ + Name: "app-data", + VolumeOptions: &mount.VolumeOptions{ + NoCopy: true, + Labels: map[string]string{ + "hello": "world", + }, + }, + }, + Target: "/data", + }, + }, + want: []mount.Mount{ + { + Type: mount.TypeVolume, + Source: "app-data", + Target: "/data", + VolumeOptions: &mount.VolumeOptions{ + NoCopy: true, + Labels: map[string]string{ + "hello": "world", + }, + }, + }, + }, + }, + + { + name: "Single tmpfs mount", + mounts: ContainerMounts{{Source: TmpfsMountSource{}, Target: "/data"}}, + want: []mount.Mount{ + { + Type: mount.TypeTmpfs, + Target: "/data", + }, + }, + }, + { + name: "Single volume mount - read-only", + mounts: ContainerMounts{{Source: TmpfsMountSource{}, Target: "/data", ReadOnly: true}}, + want: []mount.Mount{ + { + Type: mount.TypeTmpfs, + Target: "/data", + ReadOnly: true, + }, + }, + }, + { + name: "Single volume mount - with options", + mounts: ContainerMounts{ + { + Source: TmpfsMountSource{ + TmpfsOptions: &mount.TmpfsOptions{ + SizeBytes: 50 * 1024 * 1024, + Mode: 0o644, + }, + }, + Target: "/data", + }, + }, + want: []mount.Mount{ + { + Type: mount.TypeTmpfs, + Target: "/data", + TmpfsOptions: &mount.TmpfsOptions{ + SizeBytes: 50 * 1024 * 1024, + Mode: 0o644, + }, + }, + }, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + assert.Equalf(t, tt.want, tt.mounts.PrepareMounts(), "PrepareMounts()") + }) + } +} diff --git a/reaper.go b/reaper.go index ba621db189..2a84127e27 100644 --- a/reaper.go +++ b/reaper.go @@ -63,9 +63,7 @@ func NewReaper(ctx context.Context, sessionID string, provider ReaperProvider, r TestcontainerLabelIsReaper: "true", }, SkipReaper: true, - BindMounts: map[string]string{ - "/var/run/docker.sock": "/var/run/docker.sock", - }, + Mounts: Mounts(BindMount("/var/run/docker.sock", "/var/run/docker.sock")), AutoRemove: true, WaitingFor: wait.ForListeningPort(listeningPort), } From f95b5b239dcb90ac10a414e21f78ffc7d7e6725d Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Wed, 1 Dec 2021 20:19:36 +0100 Subject: [PATCH 106/219] Add some doc comments --- container.go | 2 +- mounts.go | 51 ++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/container.go b/container.go index c0b922d9b0..9d24161d0a 100644 --- a/container.go +++ b/container.go @@ -205,7 +205,7 @@ func (c *ContainerRequest) validateMounts() error { for idx := range c.Mounts { m := c.Mounts[idx] - targetPath := m.Target.String() + targetPath := m.Target.Target() if targets[targetPath] { return fmt.Errorf("%w: %s", ErrDuplicateMountTarget, targetPath) } else { diff --git a/mounts.go b/mounts.go index a9d5f6c01f..2a1beac8a9 100644 --- a/mounts.go +++ b/mounts.go @@ -1,50 +1,71 @@ package testcontainers import ( - "fmt" - "github.com/docker/docker/api/types/mount" ) +// BindMounter can optionally be implemented by mount sources +// to support advanced scenarios based on mount.BindOptions type BindMounter interface { GetBindOptions() *mount.BindOptions } +// VolumeMounter can optionally be implemented by mount sources +// to support advanced scenarios based on mount.VolumeOptions type VolumeMounter interface { GetVolumeOptions() *mount.VolumeOptions } +// TmpfsMounter can optionally be implemented by mount sources +// to support advanced scenarios based on mount.TmpfsOptions type TmpfsMounter interface { GetTmpfsOptions() *mount.TmpfsOptions } +// ContainerMountSource is the base for all mount sources type ContainerMountSource interface { - fmt.Stringer + // Source will be used as Source field in the final mount + // this might either be a volume name, a host path or might be empty e.g. for Tmpfs + Source() string + + // Type determines the final mount type + // possible options are limited by the Docker API Type() mount.Type } +// BindMountSource implements ContainerMountSource and represents a bind mount +// Optionally mount.BindOptions might be added for advanced scenarios type BindMountSource struct { *mount.BindOptions + + // HostPath is the path mounted into the container + // the same host path might be mounted to multiple locations withing a single container HostPath string } -func (s BindMountSource) String() string { +func (s BindMountSource) Source() string { return s.HostPath } func (BindMountSource) Type() mount.Type { return mount.TypeBind } + func (s BindMountSource) GetBindOptions() *mount.BindOptions { return s.BindOptions } +// VolumeMountSource implements ContainerMountSource and represents a volume mount +// Optionally mount.VolumeOptions might be added for advanced scenarios type VolumeMountSource struct { *mount.VolumeOptions + + // Name refers to the name of the volume to be mounted + // the same volume might be mounted to multiple locations within a single container Name string } -func (s VolumeMountSource) String() string { +func (s VolumeMountSource) Source() string { return s.Name } @@ -56,11 +77,13 @@ func (s VolumeMountSource) GetVolumeOptions() *mount.VolumeOptions { return s.VolumeOptions } +// TmpfsMountSource implements ContainerMountSource and represents a TmpFS mount +// Optionally mount.TmpfsOptions might be added for advanced scenarios type TmpfsMountSource struct { *mount.TmpfsOptions } -func (s TmpfsMountSource) String() string { +func (s TmpfsMountSource) Source() string { return "" } @@ -72,12 +95,16 @@ func (s TmpfsMountSource) GetTmpfsOptions() *mount.TmpfsOptions { return s.TmpfsOptions } +// ContainerMountTarget represents the target path within a container where the mount will be available +// Note that mount targets must be unique. It's not supported to mount different sources to the same target. type ContainerMountTarget string -func (t ContainerMountTarget) String() string { +func (t ContainerMountTarget) Target() string { return string(t) } +// BindMount returns a new ContainerMount with a BindMountSource as source +// This is a convenience method to cover typical use cases. func BindMount(hostPath string, mountTarget ContainerMountTarget) ContainerMount { return ContainerMount{ Source: BindMountSource{HostPath: hostPath}, @@ -85,6 +112,8 @@ func BindMount(hostPath string, mountTarget ContainerMountTarget) ContainerMount } } +// VolumeMount returns a new ContainerMount with a VolumeMountSource as source +// This is a convenience method to cover typical use cases. func VolumeMount(volumeName string, mountTarget ContainerMountTarget) ContainerMount { return ContainerMount{ Source: VolumeMountSource{Name: volumeName}, @@ -92,6 +121,7 @@ func VolumeMount(volumeName string, mountTarget ContainerMountTarget) ContainerM } } +// Mounts returns a ContainerMounts to support a more fluent API func Mounts(mounts ...ContainerMount) ContainerMounts { return mounts } @@ -106,8 +136,11 @@ type ContainerMount struct { ReadOnly bool } +// ContainerMounts represents a collection of mounts for a container type ContainerMounts []ContainerMount +// PrepareMounts maps the given []ContainerMount to the corresponding +// []mount.Mount for further processing func (m ContainerMounts) PrepareMounts() []mount.Mount { mounts := make([]mount.Mount, 0, len(m)) @@ -115,9 +148,9 @@ func (m ContainerMounts) PrepareMounts() []mount.Mount { m := m[idx] containerMount := mount.Mount{ Type: m.Source.Type(), - Source: m.Source.String(), + Source: m.Source.Source(), ReadOnly: m.ReadOnly, - Target: m.Target.String(), + Target: m.Target.Target(), } switch typedMounter := m.Source.(type) { From 57d25b2dc4e901b9de04b55915bbf84b1d95e552 Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Thu, 9 Dec 2021 08:54:02 +0100 Subject: [PATCH 107/219] Generify mount sources - introduce Docker specific mount sources and generic counterparts - move Docker specific code to mounts_docker.go --- container_test.go | 8 +-- docker.go | 2 +- docker_mounts.go | 116 ++++++++++++++++++++++++++++++++++++++++++ mounts.go | 125 +++++++++++++--------------------------------- mounts_test.go | 20 ++++---- 5 files changed, 167 insertions(+), 104 deletions(-) create mode 100644 docker_mounts.go diff --git a/container_test.go b/container_test.go index 088481ac4b..4961a81903 100644 --- a/container_test.go +++ b/container_test.go @@ -372,12 +372,12 @@ func TestBindMount(t *testing.T) { { name: "/var/run/docker.sock:/var/run/docker.sock", args: args{hostPath: "/var/run/docker.sock", mountTarget: "/var/run/docker.sock"}, - want: ContainerMount{Source: BindMountSource{HostPath: "/var/run/docker.sock"}, Target: "/var/run/docker.sock"}, + want: ContainerMount{Source: GenericBindMountSource{HostPath: "/var/run/docker.sock"}, Target: "/var/run/docker.sock"}, }, { name: "/var/lib/app/data:/data", args: args{hostPath: "/var/lib/app/data", mountTarget: "/data"}, - want: ContainerMount{Source: BindMountSource{HostPath: "/var/lib/app/data"}, Target: "/data"}, + want: ContainerMount{Source: GenericBindMountSource{HostPath: "/var/lib/app/data"}, Target: "/data"}, }, } for _, tt := range tests { @@ -400,12 +400,12 @@ func TestVolumeMount(t *testing.T) { { name: "sample-data:/data", args: args{volumeName: "sample-data", mountTarget: "/data"}, - want: ContainerMount{Source: VolumeMountSource{Name: "sample-data"}, Target: "/data"}, + want: ContainerMount{Source: GenericVolumeMountSource{Name: "sample-data"}, Target: "/data"}, }, { name: "web:/var/nginx/html", args: args{volumeName: "web", mountTarget: "/var/nginx/html"}, - want: ContainerMount{Source: VolumeMountSource{Name: "web"}, Target: "/var/nginx/html"}, + want: ContainerMount{Source: GenericVolumeMountSource{Name: "web"}, Target: "/var/nginx/html"}, }, } for _, tt := range tests { diff --git a/docker.go b/docker.go index b2d9f1ec26..e1d3c59074 100644 --- a/docker.go +++ b/docker.go @@ -744,7 +744,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque } // prepare mounts - mounts := req.Mounts.PrepareMounts() + mounts := mapToDockerMounts(req.Mounts) hostConfig := &container.HostConfig{ PortBindings: exposedPortMap, diff --git a/docker_mounts.go b/docker_mounts.go new file mode 100644 index 0000000000..cf7823ff77 --- /dev/null +++ b/docker_mounts.go @@ -0,0 +1,116 @@ +package testcontainers + +import "github.com/docker/docker/api/types/mount" + +var ( + mountTypeMapping = map[MountType]mount.Type{ + MountTypeBind: mount.TypeBind, + MountTypeVolume: mount.TypeVolume, + MountTypeTmpfs: mount.TypeTmpfs, + MountTypePipe: mount.TypeNamedPipe, + } +) + +// BindMounter can optionally be implemented by mount sources +// to support advanced scenarios based on mount.BindOptions +type BindMounter interface { + GetBindOptions() *mount.BindOptions +} + +// VolumeMounter can optionally be implemented by mount sources +// to support advanced scenarios based on mount.VolumeOptions +type VolumeMounter interface { + GetVolumeOptions() *mount.VolumeOptions +} + +// TmpfsMounter can optionally be implemented by mount sources +// to support advanced scenarios based on mount.TmpfsOptions +type TmpfsMounter interface { + GetTmpfsOptions() *mount.TmpfsOptions +} + +type DockerBindMountSource struct { + *mount.BindOptions + + // HostPath is the path mounted into the container + // the same host path might be mounted to multiple locations withing a single container + HostPath string +} + +func (s DockerBindMountSource) Source() string { + return s.HostPath +} + +func (DockerBindMountSource) Type() MountType { + return MountTypeBind +} + +func (s DockerBindMountSource) GetBindOptions() *mount.BindOptions { + return s.BindOptions +} + +type DockerVolumeMountSource struct { + *mount.VolumeOptions + + // Name refers to the name of the volume to be mounted + // the same volume might be mounted to multiple locations within a single container + Name string +} + +func (s DockerVolumeMountSource) Source() string { + return s.Name +} + +func (DockerVolumeMountSource) Type() MountType { + return MountTypeVolume +} + +func (s DockerVolumeMountSource) GetVolumeOptions() *mount.VolumeOptions { + return s.VolumeOptions +} + +type DockerTmpfsMountSource struct { + GenericTmpfsMountSource + *mount.TmpfsOptions +} + +func (s DockerTmpfsMountSource) GetTmpfsOptions() *mount.TmpfsOptions { + return s.TmpfsOptions +} + +// mapToDockerMounts maps the given []ContainerMount to the corresponding +// []mount.Mount for further processing +func mapToDockerMounts(containerMounts ContainerMounts) []mount.Mount { + mounts := make([]mount.Mount, 0, len(containerMounts)) + + for idx := range containerMounts { + m := containerMounts[idx] + + var mountType mount.Type + if mt, ok := mountTypeMapping[m.Source.Type()]; ok { + mountType = mt + } else { + continue + } + + containerMount := mount.Mount{ + Type: mountType, + Source: m.Source.Source(), + ReadOnly: m.ReadOnly, + Target: m.Target.Target(), + } + + switch typedMounter := m.Source.(type) { + case BindMounter: + containerMount.BindOptions = typedMounter.GetBindOptions() + case VolumeMounter: + containerMount.VolumeOptions = typedMounter.GetVolumeOptions() + case TmpfsMounter: + containerMount.TmpfsOptions = typedMounter.GetTmpfsOptions() + } + + mounts = append(mounts, containerMount) + } + + return mounts +} diff --git a/mounts.go b/mounts.go index 2a1beac8a9..47d08e6720 100644 --- a/mounts.go +++ b/mounts.go @@ -1,26 +1,23 @@ package testcontainers -import ( - "github.com/docker/docker/api/types/mount" +const ( + MountTypeBind MountType = iota + MountTypeVolume + MountTypeTmpfs + MountTypePipe ) -// BindMounter can optionally be implemented by mount sources -// to support advanced scenarios based on mount.BindOptions -type BindMounter interface { - GetBindOptions() *mount.BindOptions -} - -// VolumeMounter can optionally be implemented by mount sources -// to support advanced scenarios based on mount.VolumeOptions -type VolumeMounter interface { - GetVolumeOptions() *mount.VolumeOptions -} +var ( + _ ContainerMountSource = (*GenericBindMountSource)(nil) + _ ContainerMountSource = (*GenericVolumeMountSource)(nil) + _ ContainerMountSource = (*GenericTmpfsMountSource)(nil) +) -// TmpfsMounter can optionally be implemented by mount sources -// to support advanced scenarios based on mount.TmpfsOptions -type TmpfsMounter interface { - GetTmpfsOptions() *mount.TmpfsOptions -} +type ( + // ContainerMounts represents a collection of mounts for a container + ContainerMounts []ContainerMount + MountType uint +) // ContainerMountSource is the base for all mount sources type ContainerMountSource interface { @@ -30,69 +27,51 @@ type ContainerMountSource interface { // Type determines the final mount type // possible options are limited by the Docker API - Type() mount.Type + Type() MountType } -// BindMountSource implements ContainerMountSource and represents a bind mount +// GenericBindMountSource implements ContainerMountSource and represents a bind mount // Optionally mount.BindOptions might be added for advanced scenarios -type BindMountSource struct { - *mount.BindOptions - +type GenericBindMountSource struct { // HostPath is the path mounted into the container // the same host path might be mounted to multiple locations withing a single container HostPath string } -func (s BindMountSource) Source() string { +func (s GenericBindMountSource) Source() string { return s.HostPath } -func (BindMountSource) Type() mount.Type { - return mount.TypeBind +func (GenericBindMountSource) Type() MountType { + return MountTypeBind } -func (s BindMountSource) GetBindOptions() *mount.BindOptions { - return s.BindOptions -} - -// VolumeMountSource implements ContainerMountSource and represents a volume mount -// Optionally mount.VolumeOptions might be added for advanced scenarios -type VolumeMountSource struct { - *mount.VolumeOptions - +// GenericVolumeMountSource implements ContainerMountSource and represents a volume mount +type GenericVolumeMountSource struct { // Name refers to the name of the volume to be mounted // the same volume might be mounted to multiple locations within a single container Name string } -func (s VolumeMountSource) Source() string { +func (s GenericVolumeMountSource) Source() string { return s.Name } -func (VolumeMountSource) Type() mount.Type { - return mount.TypeVolume +func (GenericVolumeMountSource) Type() MountType { + return MountTypeVolume } -func (s VolumeMountSource) GetVolumeOptions() *mount.VolumeOptions { - return s.VolumeOptions -} - -// TmpfsMountSource implements ContainerMountSource and represents a TmpFS mount +// GenericTmpfsMountSource implements ContainerMountSource and represents a TmpFS mount // Optionally mount.TmpfsOptions might be added for advanced scenarios -type TmpfsMountSource struct { - *mount.TmpfsOptions +type GenericTmpfsMountSource struct { } -func (s TmpfsMountSource) Source() string { +func (s GenericTmpfsMountSource) Source() string { return "" } -func (TmpfsMountSource) Type() mount.Type { - return mount.TypeTmpfs -} - -func (s TmpfsMountSource) GetTmpfsOptions() *mount.TmpfsOptions { - return s.TmpfsOptions +func (GenericTmpfsMountSource) Type() MountType { + return MountTypeTmpfs } // ContainerMountTarget represents the target path within a container where the mount will be available @@ -103,20 +82,20 @@ func (t ContainerMountTarget) Target() string { return string(t) } -// BindMount returns a new ContainerMount with a BindMountSource as source +// BindMount returns a new ContainerMount with a GenericBindMountSource as source // This is a convenience method to cover typical use cases. func BindMount(hostPath string, mountTarget ContainerMountTarget) ContainerMount { return ContainerMount{ - Source: BindMountSource{HostPath: hostPath}, + Source: GenericBindMountSource{HostPath: hostPath}, Target: mountTarget, } } -// VolumeMount returns a new ContainerMount with a VolumeMountSource as source +// VolumeMount returns a new ContainerMount with a GenericVolumeMountSource as source // This is a convenience method to cover typical use cases. func VolumeMount(volumeName string, mountTarget ContainerMountTarget) ContainerMount { return ContainerMount{ - Source: VolumeMountSource{Name: volumeName}, + Source: GenericVolumeMountSource{Name: volumeName}, Target: mountTarget, } } @@ -128,42 +107,10 @@ func Mounts(mounts ...ContainerMount) ContainerMounts { // ContainerMount models a mount into a container type ContainerMount struct { - // Source is typically either a BindMountSource or a VolumeMountSource + // Source is typically either a GenericBindMountSource or a GenericVolumeMountSource Source ContainerMountSource // Target is the path where the mount should be mounted within the container Target ContainerMountTarget // ReadOnly determines if the mount should be read-only ReadOnly bool } - -// ContainerMounts represents a collection of mounts for a container -type ContainerMounts []ContainerMount - -// PrepareMounts maps the given []ContainerMount to the corresponding -// []mount.Mount for further processing -func (m ContainerMounts) PrepareMounts() []mount.Mount { - mounts := make([]mount.Mount, 0, len(m)) - - for idx := range m { - m := m[idx] - containerMount := mount.Mount{ - Type: m.Source.Type(), - Source: m.Source.Source(), - ReadOnly: m.ReadOnly, - Target: m.Target.Target(), - } - - switch typedMounter := m.Source.(type) { - case BindMounter: - containerMount.BindOptions = typedMounter.GetBindOptions() - case VolumeMounter: - containerMount.VolumeOptions = typedMounter.GetVolumeOptions() - case TmpfsMounter: - containerMount.TmpfsOptions = typedMounter.GetTmpfsOptions() - } - - mounts = append(mounts, containerMount) - } - - return mounts -} diff --git a/mounts_test.go b/mounts_test.go index 61f22ac707..952868b057 100644 --- a/mounts_test.go +++ b/mounts_test.go @@ -21,7 +21,7 @@ func TestContainerMounts_PrepareMounts(t *testing.T) { }, { name: "Single bind mount", - mounts: ContainerMounts{{Source: BindMountSource{HostPath: "/var/lib/app/data"}, Target: "/data"}}, + mounts: ContainerMounts{{Source: GenericBindMountSource{HostPath: "/var/lib/app/data"}, Target: "/data"}}, want: []mount.Mount{ { Type: mount.TypeBind, @@ -32,7 +32,7 @@ func TestContainerMounts_PrepareMounts(t *testing.T) { }, { name: "Single bind mount - read-only", - mounts: ContainerMounts{{Source: BindMountSource{HostPath: "/var/lib/app/data"}, Target: "/data", ReadOnly: true}}, + mounts: ContainerMounts{{Source: GenericBindMountSource{HostPath: "/var/lib/app/data"}, Target: "/data", ReadOnly: true}}, want: []mount.Mount{ { Type: mount.TypeBind, @@ -46,7 +46,7 @@ func TestContainerMounts_PrepareMounts(t *testing.T) { name: "Single bind mount - with options", mounts: ContainerMounts{ { - Source: BindMountSource{ + Source: DockerBindMountSource{ HostPath: "/var/lib/app/data", BindOptions: &mount.BindOptions{ Propagation: mount.PropagationPrivate, @@ -68,7 +68,7 @@ func TestContainerMounts_PrepareMounts(t *testing.T) { }, { name: "Single volume mount", - mounts: ContainerMounts{{Source: VolumeMountSource{Name: "app-data"}, Target: "/data"}}, + mounts: ContainerMounts{{Source: GenericVolumeMountSource{Name: "app-data"}, Target: "/data"}}, want: []mount.Mount{ { Type: mount.TypeVolume, @@ -79,7 +79,7 @@ func TestContainerMounts_PrepareMounts(t *testing.T) { }, { name: "Single volume mount - read-only", - mounts: ContainerMounts{{Source: VolumeMountSource{Name: "app-data"}, Target: "/data", ReadOnly: true}}, + mounts: ContainerMounts{{Source: GenericVolumeMountSource{Name: "app-data"}, Target: "/data", ReadOnly: true}}, want: []mount.Mount{ { Type: mount.TypeVolume, @@ -93,7 +93,7 @@ func TestContainerMounts_PrepareMounts(t *testing.T) { name: "Single volume mount - with options", mounts: ContainerMounts{ { - Source: VolumeMountSource{ + Source: DockerVolumeMountSource{ Name: "app-data", VolumeOptions: &mount.VolumeOptions{ NoCopy: true, @@ -122,7 +122,7 @@ func TestContainerMounts_PrepareMounts(t *testing.T) { { name: "Single tmpfs mount", - mounts: ContainerMounts{{Source: TmpfsMountSource{}, Target: "/data"}}, + mounts: ContainerMounts{{Source: GenericTmpfsMountSource{}, Target: "/data"}}, want: []mount.Mount{ { Type: mount.TypeTmpfs, @@ -132,7 +132,7 @@ func TestContainerMounts_PrepareMounts(t *testing.T) { }, { name: "Single volume mount - read-only", - mounts: ContainerMounts{{Source: TmpfsMountSource{}, Target: "/data", ReadOnly: true}}, + mounts: ContainerMounts{{Source: GenericTmpfsMountSource{}, Target: "/data", ReadOnly: true}}, want: []mount.Mount{ { Type: mount.TypeTmpfs, @@ -145,7 +145,7 @@ func TestContainerMounts_PrepareMounts(t *testing.T) { name: "Single volume mount - with options", mounts: ContainerMounts{ { - Source: TmpfsMountSource{ + Source: DockerTmpfsMountSource{ TmpfsOptions: &mount.TmpfsOptions{ SizeBytes: 50 * 1024 * 1024, Mode: 0o644, @@ -170,7 +170,7 @@ func TestContainerMounts_PrepareMounts(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - assert.Equalf(t, tt.want, tt.mounts.PrepareMounts(), "PrepareMounts()") + assert.Equalf(t, tt.want, mapToDockerMounts(tt.mounts), "PrepareMounts()") }) } } From acb198330e047bc6d27ca6e961f75886ab798829 Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Mon, 20 Dec 2021 17:22:48 +0100 Subject: [PATCH 108/219] Fix container_test.go with matching error string --- container_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/container_test.go b/container_test.go index 4961a81903..f0a3239f40 100644 --- a/container_test.go +++ b/container_test.go @@ -247,7 +247,7 @@ func Test_BuildImageWithContexts(t *testing.T) { ContextArchive: func() (io.Reader, error) { return nil, nil }, - ExpectedError: errors.New("failed to create container: you must specify either a build context or an image"), + ExpectedError: errors.New("you must specify either a build context or an image: failed to create container"), }, } @@ -299,7 +299,7 @@ func Test_GetLogsFromFailedContainer(t *testing.T) { Started: true, }) - if err != nil && err.Error() != "failed to start container: context deadline exceeded" { + if err != nil && !errors.Is(err, context.DeadlineExceeded) { t.Fatal(err) } else if err == nil { c.Terminate(ctx) From 77129bc82ef67f6b229e5473b984712035bd1058 Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Fri, 24 Dec 2021 11:14:26 +0100 Subject: [PATCH 109/219] Add TestLogger helper --- logger.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/logger.go b/logger.go index f74b175876..8a95081e00 100644 --- a/logger.go +++ b/logger.go @@ -3,6 +3,7 @@ package testcontainers import ( "log" "os" + "testing" ) // Logger is the default log instance @@ -11,4 +12,16 @@ var Logger Logging = log.New(os.Stderr, "", log.LstdFlags) // Logging defines the Logger interface type Logging interface { Printf(format string, v ...interface{}) -} \ No newline at end of file +} + +func TestLogger(tb testing.TB) Logging { + return testLogger{TB: tb} +} + +type testLogger struct { + testing.TB +} + +func (t testLogger) Printf(format string, v ...interface{}) { + t.Logf(format, v...) +} From 9ec3ed46ab7a2002cb76905190b2d1f9f5e5f227 Mon Sep 17 00:00:00 2001 From: Dave Henderson Date: Thu, 19 Aug 2021 07:03:53 +0000 Subject: [PATCH 110/219] Send optional platform spec when creating container Signed-off-by: Dave Henderson --- container.go | 3 +- docker.go | 25 ++++++++++-- docker_test.go | 58 ++++++++++++++++++++++++++ go.mod | 5 +-- go.sum | 108 ++++++++++++++++++++++++++++++++++++++++++------- 5 files changed, 178 insertions(+), 21 deletions(-) diff --git a/container.go b/container.go index 80c2df8c6c..e933c4d0ac 100644 --- a/container.go +++ b/container.go @@ -97,7 +97,8 @@ type ContainerRequest struct { ReaperImage string // alternative reaper image AutoRemove bool // if set to true, the container will be removed from the host when stopped NetworkMode container.NetworkMode - AlwaysPullImage bool // Always pull image + AlwaysPullImage bool // Always pull image + ImagePlatform string // ImagePlatform describes the platform which the image runs on. } // ProviderType is an enum for the possible providers diff --git a/docker.go b/docker.go index e1d3c59074..33c4b68a7d 100644 --- a/docker.go +++ b/docker.go @@ -17,6 +17,7 @@ import ( "time" "github.com/cenkalti/backoff/v4" + "github.com/containerd/containerd/platforms" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" @@ -28,6 +29,7 @@ import ( "github.com/magiconair/properties" "github.com/moby/term" + specs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/testcontainers/testcontainers-go/wait" ) @@ -698,6 +700,8 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque } var tag string + var platform *specs.Platform + if req.ShouldBuildImage() { tag, err = p.BuildImage(ctx, &req) if err != nil { @@ -705,12 +709,21 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque } } else { tag = req.Image + + if req.ImagePlatform != "" { + p, err := platforms.Parse(req.ImagePlatform) + if err != nil { + return nil, fmt.Errorf("invalid platform %s: %w", req.ImagePlatform, err) + } + platform = &p + } + var shouldPullImage bool if req.AlwaysPullImage { shouldPullImage = true // If requested always attempt to pull image } else { - _, _, err = p.client.ImageInspectWithRaw(ctx, tag) + image, _, err := p.client.ImageInspectWithRaw(ctx, tag) if err != nil { if client.IsErrNotFound(err) { shouldPullImage = true @@ -718,10 +731,16 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque return nil, err } } + if platform != nil && (image.Architecture != platform.Architecture || image.Os != platform.OS) { + shouldPullImage = true + } } if shouldPullImage { - pullOpt := types.ImagePullOptions{} + pullOpt := types.ImagePullOptions{ + Platform: req.ImagePlatform, // may be empty + } + if req.RegistryCred != "" { pullOpt.RegistryAuth = req.RegistryCred } @@ -779,7 +798,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque EndpointsConfig: endpointConfigs, } - resp, err := p.client.ContainerCreate(ctx, dockerInput, hostConfig, &networkingConfig, nil, req.Name) + resp, err := p.client.ContainerCreate(ctx, dockerInput, hostConfig, &networkingConfig, platform, req.Name) if err != nil { return nil, err } diff --git a/docker_test.go b/docker_test.go index ab8bc766bb..387d1f0413 100644 --- a/docker_test.go +++ b/docker_test.go @@ -18,6 +18,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gotest.tools/v3/env" "gotest.tools/v3/fs" @@ -1494,6 +1495,63 @@ func TestContainerNonExistentImage(t *testing.T) { }) } +func TestContainerCustomPlatformImage(t *testing.T) { + t.Run("error with a non-existent platform", func(t *testing.T) { + nonExistentPlatform := "windows/arm12" + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + c, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: ContainerRequest{ + Image: "redis:latest", + SkipReaper: true, + ImagePlatform: nonExistentPlatform, + }, + Started: false, + }) + + t.Cleanup(func() { + if c != nil { + c.Terminate(ctx) + } + }) + + assert.Error(t, err) + }) + + t.Run("specific platform should be propagated", func(t *testing.T) { + ctx := context.Background() + + c, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: ContainerRequest{ + Image: "mysql:5.7", + SkipReaper: true, + ImagePlatform: "linux/amd64", + }, + Started: false, + }) + + t.Cleanup(func() { + if c != nil { + c.Terminate(ctx) + } + }) + + assert.NoError(t, err) + + dockerCli, err := client.NewEnvClient() + require.NoError(t, err) + + dockerCli.NegotiateAPIVersion(ctx) + ctr, err := dockerCli.ContainerInspect(ctx, c.GetContainerID()) + assert.NoError(t, err) + + img, _, err := dockerCli.ImageInspectWithRaw(ctx, ctr.Image) + assert.NoError(t, err) + assert.Equal(t, "linux", img.Os) + assert.Equal(t, "amd64", img.Architecture) + }) +} + func TestContainerWithCustomHostname(t *testing.T) { ctx := context.Background() name := fmt.Sprintf("some-nginx-%s-%d", t.Name(), rand.Int()) diff --git a/go.mod b/go.mod index e52a382795..2bb54824ae 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/testcontainers/testcontainers-go go 1.13 require ( - github.com/Microsoft/hcsshim v0.8.16 // indirect github.com/cenkalti/backoff/v4 v4.1.2 + github.com/containerd/containerd v1.5.9 github.com/docker/docker v20.10.11+incompatible github.com/docker/go-connections v0.4.0 github.com/go-redis/redis v6.15.9+incompatible @@ -16,11 +16,10 @@ require ( github.com/moby/sys/mountinfo v0.5.0 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect - github.com/opencontainers/runc v1.0.2 // indirect + github.com/opencontainers/image-spec v1.0.2 github.com/stretchr/testify v1.7.0 golang.org/x/net v0.0.0-20211108170745-6635138e15ea // indirect golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 - google.golang.org/protobuf v1.27.1 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b gotest.tools/v3 v3.0.3 ) diff --git a/go.sum b/go.sum index 1ea9e7b20d..9e5a8c3138 100644 --- a/go.sum +++ b/go.sum @@ -23,7 +23,6 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= @@ -44,19 +43,23 @@ github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jB github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3 h1:mw6pDQqv38/WGF1cO/jF5t/jyAJ2yi7CmtFLLO5tGFI= github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w= +github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= -github.com/Microsoft/hcsshim v0.8.16 h1:8/auA4LFIZFTGrqfKhGBSXwM6/4X1fHa/xniyEHu8ac= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.23 h1:47MSwtKGXet80aIn+7h4YI6fwPmwIghAnsx2aOUrG2M= +github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= @@ -65,6 +68,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -82,9 +86,11 @@ github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7 github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= @@ -94,6 +100,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -101,15 +108,18 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68 h1:hkGVFjz+plgr5UfxZUTPFbUFIF/Km6/s+RVRIRHLrrY= github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ= +github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= @@ -123,49 +133,68 @@ github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= -github.com/containerd/containerd v1.5.0-beta.4 h1:zjz4MOAOFgdBlwid2nNUlJ3YLpVi/97L36lfMYJex60= github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= +github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= +github.com/containerd/containerd v1.5.9 h1:rs6Xg1gtIxaeyG+Smsb/0xaSDu1VgFhOCKBXxMxbsF4= +github.com/containerd/containerd v1.5.9/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= -github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e h1:6JKvHHt396/qabvMhnhUZvWaHZzfVfldxE60TK8YLhg= github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= +github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= +github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= +github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= +github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -193,6 +222,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= @@ -269,6 +299,7 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= @@ -319,6 +350,7 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -329,10 +361,13 @@ github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -340,13 +375,14 @@ github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1: github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -364,6 +400,7 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -376,6 +413,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -390,8 +428,10 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= @@ -400,8 +440,6 @@ github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9 github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= -github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= -github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -416,19 +454,24 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -436,8 +479,9 @@ github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go. github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= @@ -455,6 +499,8 @@ github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mo github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -466,6 +512,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -475,11 +522,14 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= @@ -488,6 +538,7 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -507,14 +558,20 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -533,25 +590,30 @@ github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= @@ -577,6 +639,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -636,9 +699,11 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211108170745-6635138e15ea h1:FosBMXtOc8Tp9Hbo4ltl1WJSrTVewZU8MPnTPY2HdH8= golang.org/x/net v0.0.0-20211108170745-6635138e15ea/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -677,6 +742,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -694,6 +760,7 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -701,12 +768,12 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -853,7 +920,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -888,12 +954,24 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= +k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= +k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= +k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= +k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= +k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= +k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= +k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= +k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= @@ -904,6 +982,8 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= From a1db3236e79c1974c63c3ce4edcb9702b591d36b Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Fri, 24 Dec 2021 11:46:49 +0100 Subject: [PATCH 111/219] Propagate logger from GenericContainerRequest to provider and container - Introduce options for GenericProvider, DockerProvider and LocalDockerCompose - DockerProvider should accept all generic options but could expose additional ones --- compose.go | 37 ++++++++++++++++++++++++--- compose_test.go | 24 +++++++++--------- container.go | 37 +++++++++++++++++++++++---- docker.go | 61 +++++++++++++++++++++++++++++++++++++++++---- docker_test.go | 12 ++++----- generic.go | 7 +++++- logconsumer_test.go | 5 ++-- logger.go | 29 +++++++++++++++++++++ 8 files changed, 177 insertions(+), 35 deletions(-) diff --git a/compose.go b/compose.go index 89c0984504..caabd61e4c 100644 --- a/compose.go +++ b/compose.go @@ -44,6 +44,7 @@ type waitService struct { // LocalDockerCompose represents a Docker Compose execution using local binary // docker-compose or docker-compose.exe, depending on the underlying platform type LocalDockerCompose struct { + *LocalDockerComposeOptions Executable string ComposeFilePaths []string absComposeFilePaths []string @@ -55,6 +56,26 @@ type LocalDockerCompose struct { WaitStrategyMap map[waitService]wait.Strategy } +type ( + // LocalDockerComposeOptions defines options applicable to LocalDockerCompose + LocalDockerComposeOptions struct { + Logger Logging + } + + // LocalDockerComposeOption defines a common interface to modify LocalDockerComposeOptions + // These options can be passed to NewLocalDockerCompose in a variadic way to customize the returned LocalDockerCompose instance + LocalDockerComposeOption interface { + ApplyToLocalCompose(opts *LocalDockerComposeOptions) + } + + // LocalDockerComposeOptionsFunc is a shorthand to implement the LocalDockerComposeOption interface + LocalDockerComposeOptionsFunc func(opts *LocalDockerComposeOptions) +) + +func (f LocalDockerComposeOptionsFunc) ApplyToLocalCompose(opts *LocalDockerComposeOptions) { + f(opts) +} + // NewLocalDockerCompose returns an instance of the local Docker Compose, using an // array of Docker Compose file paths and an identifier for the Compose execution. // @@ -62,8 +83,16 @@ type LocalDockerCompose struct { // Docker Compose execution. The identifier represents the name of the execution, // which will define the name of the underlying Docker network and the name of the // running Compose services. -func NewLocalDockerCompose(filePaths []string, identifier string) *LocalDockerCompose { - dc := &LocalDockerCompose{} +func NewLocalDockerCompose(filePaths []string, identifier string, opts ...LocalDockerComposeOption) *LocalDockerCompose { + dc := &LocalDockerCompose{ + LocalDockerComposeOptions: &LocalDockerComposeOptions{ + Logger: Logger, + }, + } + + for idx := range opts { + opts[idx].ApplyToLocalCompose(dc.LocalDockerComposeOptions) + } dc.Executable = "docker-compose" if runtime.GOOS == "windows" { @@ -134,11 +163,11 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { } container := containers[0] strategy := dc.WaitStrategyMap[k] - dockerProvider, err := NewDockerProvider() + dockerProvider, err := NewDockerProvider(WithLogger(dc.Logger)) if err != nil { return fmt.Errorf("unable to create new Docker Provider: %w", err) } - dockercontainer := &DockerContainer{ID: container.ID, WaitingFor: strategy, provider: dockerProvider} + dockercontainer := &DockerContainer{ID: container.ID, WaitingFor: strategy, provider: dockerProvider, logger: dc.Logger} err = strategy.WaitUntilReady(context.Background(), dockercontainer) if err != nil { return fmt.Errorf("Unable to apply wait strategy %v to service %s due to %w", strategy, k.service, err) diff --git a/compose_test.go b/compose_test.go index b4dbe02f70..c448c14d8b 100644 --- a/compose_test.go +++ b/compose_test.go @@ -95,7 +95,7 @@ func TestLocalDockerCompose(t *testing.T) { identifier := strings.ToLower(uuid.New().String()) - compose := NewLocalDockerCompose([]string{path}, identifier) + compose := NewLocalDockerCompose([]string{path}, identifier, WithLogger(TestLogger(t))) destroyFn := func() { err := compose.Down() checkIfError(t, err) @@ -112,7 +112,7 @@ func TestDockerComposeStrategyForInvalidService(t *testing.T) { identifier := strings.ToLower(uuid.New().String()) - compose := NewLocalDockerCompose([]string{path}, identifier) + compose := NewLocalDockerCompose([]string{path}, identifier, WithLogger(TestLogger(t))) destroyFn := func() { err := compose.Down() checkIfError(t, err) @@ -135,7 +135,7 @@ func TestDockerComposeWithWaitLogStrategy(t *testing.T) { identifier := strings.ToLower(uuid.New().String()) - compose := NewLocalDockerCompose([]string{path}, identifier) + compose := NewLocalDockerCompose([]string{path}, identifier, WithLogger(TestLogger(t))) destroyFn := func() { err := compose.Down() checkIfError(t, err) @@ -159,7 +159,7 @@ func TestDockerComposeWithWaitForService(t *testing.T) { identifier := strings.ToLower(uuid.New().String()) - compose := NewLocalDockerCompose([]string{path}, identifier) + compose := NewLocalDockerCompose([]string{path}, identifier, WithLogger(TestLogger(t))) destroyFn := func() { err := compose.Down() checkIfError(t, err) @@ -184,7 +184,7 @@ func TestDockerComposeWithWaitHTTPStrategy(t *testing.T) { identifier := strings.ToLower(uuid.New().String()) - compose := NewLocalDockerCompose([]string{path}, identifier) + compose := NewLocalDockerCompose([]string{path}, identifier, WithLogger(TestLogger(t))) destroyFn := func() { err := compose.Down() checkIfError(t, err) @@ -209,7 +209,7 @@ func TestDockerComposeWithWaitStrategy_NoExposedPorts(t *testing.T) { identifier := strings.ToLower(uuid.New().String()) - compose := NewLocalDockerCompose([]string{path}, identifier) + compose := NewLocalDockerCompose([]string{path}, identifier, WithLogger(TestLogger(t))) destroyFn := func() { err := compose.Down() checkIfError(t, err) @@ -231,7 +231,7 @@ func TestDockerComposeWithMultipleWaitStrategies(t *testing.T) { identifier := strings.ToLower(uuid.New().String()) - compose := NewLocalDockerCompose([]string{path}, identifier) + compose := NewLocalDockerCompose([]string{path}, identifier, WithLogger(TestLogger(t))) destroyFn := func() { err := compose.Down() checkIfError(t, err) @@ -255,7 +255,7 @@ func TestDockerComposeWithFailedStrategy(t *testing.T) { identifier := strings.ToLower(uuid.New().String()) - compose := NewLocalDockerCompose([]string{path}, identifier) + compose := NewLocalDockerCompose([]string{path}, identifier, WithLogger(TestLogger(t))) destroyFn := func() { err := compose.Down() checkIfError(t, err) @@ -282,7 +282,7 @@ func TestLocalDockerComposeComplex(t *testing.T) { identifier := strings.ToLower(uuid.New().String()) - compose := NewLocalDockerCompose([]string{path}, identifier) + compose := NewLocalDockerCompose([]string{path}, identifier, WithLogger(TestLogger(t))) destroyFn := func() { err := compose.Down() checkIfError(t, err) @@ -304,7 +304,7 @@ func TestLocalDockerComposeWithEnvironment(t *testing.T) { identifier := strings.ToLower(uuid.New().String()) - compose := NewLocalDockerCompose([]string{path}, identifier) + compose := NewLocalDockerCompose([]string{path}, identifier, WithLogger(TestLogger(t))) destroyFn := func() { err := compose.Down() checkIfError(t, err) @@ -340,7 +340,7 @@ func TestLocalDockerComposeWithMultipleComposeFiles(t *testing.T) { identifier := strings.ToLower(uuid.New().String()) - compose := NewLocalDockerCompose(composeFiles, identifier) + compose := NewLocalDockerCompose(composeFiles, identifier, WithLogger(TestLogger(t))) destroyFn := func() { err := compose.Down() checkIfError(t, err) @@ -376,7 +376,7 @@ func TestLocalDockerComposeWithVolume(t *testing.T) { identifier := strings.ToLower(uuid.New().String()) - compose := NewLocalDockerCompose([]string{path}, identifier) + compose := NewLocalDockerCompose([]string{path}, identifier, WithLogger(TestLogger(t))) destroyFn := func() { err := compose.Down() checkIfError(t, err) diff --git a/container.go b/container.go index 80c2df8c6c..10f49ea4d3 100644 --- a/container.go +++ b/container.go @@ -100,8 +100,28 @@ type ContainerRequest struct { AlwaysPullImage bool // Always pull image } -// ProviderType is an enum for the possible providers -type ProviderType int +type ( + // ProviderType is an enum for the possible providers + ProviderType int + + // GenericProviderOptions defines options applicable to all providers + GenericProviderOptions struct { + Logger Logging + } + + // GenericProviderOption defines a common interface to modify GenericProviderOptions + // These options can be passed to GetProvider in a variadic way to customize the returned GenericProvider instance + GenericProviderOption interface { + ApplyGenericTo(opts *GenericProviderOptions) + } + + // GenericProviderOptionFunc is a shorthand to implement the GenericProviderOption interface + GenericProviderOptionFunc func(opts *GenericProviderOptions) +) + +func (f GenericProviderOptionFunc) ApplyGenericTo(opts *GenericProviderOptions) { + f(opts) +} // possible provider types const ( @@ -109,10 +129,18 @@ const ( ) // GetProvider provides the provider implementation for a certain type -func (t ProviderType) GetProvider() (GenericProvider, error) { +func (t ProviderType) GetProvider(opts ...GenericProviderOption) (GenericProvider, error) { + opt := &GenericProviderOptions{ + Logger: Logger, + } + + for _, o := range opts { + o.ApplyGenericTo(opt) + } + switch t { case ProviderDocker: - provider, err := NewDockerProvider() + provider, err := NewDockerProvider(Generic2DockerOptions(opts...)...) if err != nil { return nil, fmt.Errorf("%w, failed to create Docker provider", err) } @@ -124,7 +152,6 @@ func (t ProviderType) GetProvider() (GenericProvider, error) { // Validate ensures that the ContainerRequest does not have invalid parameters configured to it // ex. make sure you are not specifying both an image as well as a context func (c *ContainerRequest) Validate() error { - validationMethods := []func() error{ c.validateContextAndImage, c.validateContextOrImageIsSpecified, diff --git a/docker.go b/docker.go index e1d3c59074..266c16a8ea 100644 --- a/docker.go +++ b/docker.go @@ -57,6 +57,7 @@ type DockerContainer struct { consumers []LogConsumer raw *types.ContainerJSON stopProducer chan bool + logger Logging } func (c *DockerContainer) GetContainerID() string { @@ -160,7 +161,7 @@ func (c *DockerContainer) SessionID() string { // Start will start an already created container func (c *DockerContainer) Start(ctx context.Context) error { shortID := c.ID[:12] - Logger.Printf("Starting container id: %s image: %s", shortID, c.Image) + c.logger.Printf("Starting container id: %s image: %s", shortID, c.Image) if err := c.provider.client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}); err != nil { return err @@ -168,12 +169,12 @@ func (c *DockerContainer) Start(ctx context.Context) error { // if a Wait Strategy has been specified, wait before returning if c.WaitingFor != nil { - Logger.Printf("Waiting for container id %s image: %s", shortID, c.Image) + c.logger.Printf("Waiting for container id %s image: %s", shortID, c.Image) if err := c.WaitingFor.WaitUntilReady(ctx, c); err != nil { return err } } - Logger.Printf("Container is ready id: %s image: %s", shortID, c.Image) + c.logger.Printf("Container is ready id: %s image: %s", shortID, c.Image) return nil } @@ -511,6 +512,7 @@ func (n *DockerNetwork) Remove(ctx context.Context) error { // DockerProvider implements the ContainerProvider interface type DockerProvider struct { + *DockerProviderOptions client *client.Client hostCache string defaultNetwork string // default container network @@ -525,11 +527,57 @@ type TestContainersConfig struct { CertPath string `properties:"docker.cert.path,default="` } +type ( + // DockerProviderOptions defines options applicable to DockerProvider + DockerProviderOptions struct { + *GenericProviderOptions + } + + // DockerProviderOption defines a common interface to modify DockerProviderOptions + // These can be passed to NewDockerProvider in a variadic way to customize the returned DockerProvider instance + DockerProviderOption interface { + ApplyDockerTo(opts *DockerProviderOptions) + } + + // DockerProviderOptionFunc is a shorthand to implement the DockerProviderOption interface + DockerProviderOptionFunc func(opts *DockerProviderOptions) +) + +func (f DockerProviderOptionFunc) ApplyDockerTo(opts *DockerProviderOptions) { + f(opts) +} + +func Generic2DockerOptions(opts ...GenericProviderOption) []DockerProviderOption { + converted := make([]DockerProviderOption, 0, len(opts)) + for _, o := range opts { + switch c := o.(type) { + case DockerProviderOption: + converted = append(converted, c) + default: + converted = append(converted, DockerProviderOptionFunc(func(opts *DockerProviderOptions) { + o.ApplyGenericTo(opts.GenericProviderOptions) + })) + } + } + + return converted +} + // NewDockerProvider creates a Docker provider with the EnvClient -func NewDockerProvider() (*DockerProvider, error) { +func NewDockerProvider(provOpts ...DockerProviderOption) (*DockerProvider, error) { tcConfig := readTCPropsFile() host := tcConfig.Host + o := &DockerProviderOptions{ + GenericProviderOptions: &GenericProviderOptions{ + Logger: Logger, + }, + } + + for idx := range provOpts { + provOpts[idx].ApplyDockerTo(o) + } + opts := []client.Opt{client.FromEnv} if host != "" { opts = append(opts, client.WithHost(host)) @@ -560,8 +608,10 @@ func NewDockerProvider() (*DockerProvider, error) { c.NegotiateAPIVersion(context.Background()) p := &DockerProvider{ - client: c, + DockerProviderOptions: o, + client: c, } + return p, nil } @@ -811,6 +861,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque terminationSignal: termSignal, skipReaper: req.SkipReaper, stopProducer: make(chan bool), + logger: p.Logger, } return c, nil diff --git a/docker_test.go b/docker_test.go index ab8bc766bb..7e7a71d236 100644 --- a/docker_test.go +++ b/docker_test.go @@ -279,7 +279,7 @@ func TestContainerReturnItsContainerID(t *testing.T) { func TestContainerStartsWithoutTheReaper(t *testing.T) { t.Skip("need to use the sessionID") ctx := context.Background() - client, err := client.NewEnvClient() + client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { t.Fatal(err) } @@ -315,7 +315,7 @@ func TestContainerStartsWithoutTheReaper(t *testing.T) { func TestContainerStartsWithTheReaper(t *testing.T) { ctx := context.Background() - client, err := client.NewEnvClient() + client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { t.Fatal(err) } @@ -350,7 +350,7 @@ func TestContainerStartsWithTheReaper(t *testing.T) { func TestContainerTerminationResetsState(t *testing.T) { ctx := context.Background() - client, err := client.NewEnvClient() + client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { t.Fatal(err) } @@ -384,7 +384,7 @@ func TestContainerTerminationResetsState(t *testing.T) { func TestContainerTerminationWithReaper(t *testing.T) { ctx := context.Background() - client, err := client.NewEnvClient() + client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { t.Fatal(err) } @@ -421,7 +421,7 @@ func TestContainerTerminationWithReaper(t *testing.T) { func TestContainerTerminationWithoutReaper(t *testing.T) { ctx := context.Background() - client, err := client.NewEnvClient() + client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { t.Fatal(err) } @@ -1754,7 +1754,7 @@ func TestContainerWithNoUserID(t *testing.T) { func TestGetGatewayIP(t *testing.T) { // When using docker-compose with DinD mode, and using host port or http wait strategy // It's need to invoke GetGatewayIP for get the host - provider, err := NewDockerProvider() + provider, err := NewDockerProvider(WithLogger(TestLogger(t))) if err != nil { t.Fatal(err) } diff --git a/generic.go b/generic.go index 2c21e7136c..fbfd8947c2 100644 --- a/generic.go +++ b/generic.go @@ -10,6 +10,7 @@ type GenericContainerRequest struct { ContainerRequest // embedded request for provider Started bool // whether to auto-start the container ProviderType ProviderType // which provider to use, Docker if empty + Logger Logging // provide a container specific Logging - use default global logger if empty } // GenericNetworkRequest represents parameters to a generic network @@ -34,7 +35,11 @@ func GenericNetwork(ctx context.Context, req GenericNetworkRequest) (Network, er // GenericContainer creates a generic container with parameters func GenericContainer(ctx context.Context, req GenericContainerRequest) (Container, error) { - provider, err := req.ProviderType.GetProvider() + logging := req.Logger + if logging == nil { + logging = Logger + } + provider, err := req.ProviderType.GetProvider(WithLogger(logging)) if err != nil { return nil, err } diff --git a/logconsumer_test.go b/logconsumer_test.go index 2a207e8f36..b9a06487f1 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -205,7 +205,7 @@ func TestContainerLogWithErrClosed(t *testing.T) { } defer dind.Terminate(ctx) - remoteDocker, err := dind.Endpoint(ctx, "tcp") + remoteDocker, err := dind.Endpoint(ctx, "2375/tcp") if err != nil { t.Fatal(err) } @@ -217,7 +217,8 @@ func TestContainerLogWithErrClosed(t *testing.T) { defer client.Close() client.NegotiateAPIVersion(ctx) - provider := &DockerProvider{client: client} + + provider := &DockerProvider{client: client, DockerProviderOptions: &DockerProviderOptions{GenericProviderOptions: &GenericProviderOptions{Logger: TestLogger(t)}}} nginx, err := provider.CreateContainer(ctx, ContainerRequest{Image: "nginx", ExposedPorts: []string{"80/tcp"}}) if err != nil { diff --git a/logger.go b/logger.go index 8a95081e00..5a77358e78 100644 --- a/logger.go +++ b/logger.go @@ -14,14 +14,43 @@ type Logging interface { Printf(format string, v ...interface{}) } +// TestLogger returns a Logging implementation for testing.TB +// This way logs from testcontainers are part of the test output of a test suite or test case func TestLogger(tb testing.TB) Logging { + tb.Helper() return testLogger{TB: tb} } +// WithLogger is a generic option that implements GenericProviderOption, DockerProviderOption and LocalDockerComposeOption +// It replaces the global Logging implementation with a user defined one e.g. to aggregate logs from testcontainers +// with the logs of specific test case +func WithLogger(logger Logging) LoggerOption { + return LoggerOption{ + logger: logger, + } +} + +type LoggerOption struct { + logger Logging +} + +func (o LoggerOption) ApplyGenericTo(opts *GenericProviderOptions) { + opts.Logger = o.logger +} + +func (o LoggerOption) ApplyDockerTo(opts *DockerProviderOptions) { + opts.Logger = o.logger +} + +func (o LoggerOption) ApplyToLocalCompose(opts *LocalDockerComposeOptions) { + opts.Logger = o.logger +} + type testLogger struct { testing.TB } func (t testLogger) Printf(format string, v ...interface{}) { + t.Helper() t.Logf(format, v...) } From cacaa87dd2c0b8d25322e7faab08ce2c489ab46a Mon Sep 17 00:00:00 2001 From: Dave Henderson Date: Tue, 1 Feb 2022 13:48:56 -0500 Subject: [PATCH 112/219] Fix some lint errors Signed-off-by: Dave Henderson --- logger.go | 2 +- wait/errors.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/logger.go b/logger.go index f74b175876..7c93aa9279 100644 --- a/logger.go +++ b/logger.go @@ -11,4 +11,4 @@ var Logger Logging = log.New(os.Stderr, "", log.LstdFlags) // Logging defines the Logger interface type Logging interface { Printf(format string, v ...interface{}) -} \ No newline at end of file +} diff --git a/wait/errors.go b/wait/errors.go index 59e9ad0313..f8a02a59bf 100644 --- a/wait/errors.go +++ b/wait/errors.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package wait From d74b3a3bc184f46f885bb16ed0cc811f47e292c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 2 Feb 2022 09:50:08 +0100 Subject: [PATCH 113/219] chore(ci): run tests for more recent Go versions --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d0b7aff0b..02c9a1bd5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: test: strategy: matrix: - go-version: [1.14.x, 1.15.x, 1.x] + go-version: [1.14.x, 1.15.x, 1.16.x, 1.17.x, 1.x] platform: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.platform }} steps: From bca538c035a13c7593eb0bec3ba48dcbcf3611c7 Mon Sep 17 00:00:00 2001 From: nhatthm Date: Wed, 2 Feb 2022 11:26:42 +0100 Subject: [PATCH 114/219] Expose HostConfig Resources --- container.go | 11 ++++++----- docker.go | 7 ++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/container.go b/container.go index 274171e564..322785125e 100644 --- a/container.go +++ b/container.go @@ -46,7 +46,7 @@ type Container interface { StartLogProducer(context.Context) error StopLogProducer() error Name(context.Context) (string, error) // get container name - State(context.Context) (*types.ContainerState, error) //returns container's running state + State(context.Context) (*types.ContainerState, error) // returns container's running state Networks(context.Context) ([]string, error) // get container networks NetworkAliases(context.Context) (map[string][]string, error) // get container network aliases for a network Exec(ctx context.Context, cmd []string) (int, error) @@ -92,11 +92,12 @@ type ContainerRequest struct { Privileged bool // for starting privileged container Networks []string // for specifying network names NetworkAliases map[string][]string // for specifying network aliases - User string // for specifying uid:gid - SkipReaper bool // indicates whether we skip setting up a reaper for this - ReaperImage string // alternative reaper image - AutoRemove bool // if set to true, the container will be removed from the host when stopped NetworkMode container.NetworkMode + Resources container.Resources + User string // for specifying uid:gid + SkipReaper bool // indicates whether we skip setting up a reaper for this + ReaperImage string // alternative reaper image + AutoRemove bool // if set to true, the container will be removed from the host when stopped AlwaysPullImage bool // Always pull image ImagePlatform string // ImagePlatform describes the platform which the image runs on. } diff --git a/docker.go b/docker.go index 8cb9d82b0d..dd50ed5c7b 100644 --- a/docker.go +++ b/docker.go @@ -28,8 +28,8 @@ import ( "github.com/google/uuid" "github.com/magiconair/properties" "github.com/moby/term" - specs "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/testcontainers/testcontainers-go/wait" ) @@ -363,8 +363,8 @@ func (c *DockerContainer) CopyFileFromContainer(ctx context.Context, filePath st } tarReader := tar.NewReader(r) - //if we got here we have exactly one file in the TAR-stream - //so we advance the index by one so the next call to Read will start reading it + // if we got here we have exactly one file in the TAR-stream + // so we advance the index by one so the next call to Read will start reading it _, err = tarReader.Next() if err != nil { return nil, err @@ -822,6 +822,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque AutoRemove: req.AutoRemove, Privileged: req.Privileged, NetworkMode: req.NetworkMode, + Resources: req.Resources, } endpointConfigs := map[string]*network.EndpointSettings{} From 25488a2477209a5f37199f7b101986c5f2d5ff3f Mon Sep 17 00:00:00 2001 From: nhatthm Date: Wed, 2 Feb 2022 15:49:57 +0100 Subject: [PATCH 115/219] Add tests --- docker_test.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/docker_test.go b/docker_test.go index 509aa8a48e..01fb061464 100644 --- a/docker_test.go +++ b/docker_test.go @@ -17,6 +17,8 @@ import ( "testing" "time" + "github.com/docker/docker/api/types/container" + "github.com/docker/go-units" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gotest.tools/v3/env" @@ -129,10 +131,10 @@ func TestContainerWithHostNetworkOptions(t *testing.T) { defer nginxC.Terminate(ctx) - //host, err := nginxC.Host(ctx) - //if err != nil { + // host, err := nginxC.Host(ctx) + // if err != nil { // t.Errorf("Expected host %s. Got '%d'.", host, err) - //} + // } // endpoint, err := nginxC.Endpoint(ctx, "http") if err != nil { @@ -1699,6 +1701,49 @@ func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { assert.Empty(t, fileContentFromContainer) } +func TestDockerContainerResources(t *testing.T) { + ctx := context.Background() + + expected := []*units.Ulimit{ + { + Name: "memlock", + Hard: -1, + Soft: -1, + }, + { + Name: "nofile", + Hard: 65536, + Soft: 65536, + }, + } + + nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: ContainerRequest{ + Image: "nginx", + ExposedPorts: []string{"80/tcp"}, + WaitingFor: wait.ForListeningPort("80/tcp"), + Resources: container.Resources{ + Ulimits: expected, + }, + }, + Started: true, + }) + require.NoError(t, err) + + defer nginxC.Terminate(ctx) + + c, err := client.NewClientWithOpts(client.FromEnv) + require.NoError(t, err) + + c.NegotiateAPIVersion(ctx) + containerID := nginxC.GetContainerID() + + resp, err := c.ContainerInspect(ctx, containerID) + require.NoError(t, err) + + assert.Equal(t, expected, resp.HostConfig.Ulimits) +} + func TestContainerWithReaperNetwork(t *testing.T) { ctx := context.Background() networks := []string{ From 107b95d95fae5f6e673edcc114e08bf77fa67006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Szak=C3=A1cs?= Date: Sun, 13 Feb 2022 12:15:05 +0100 Subject: [PATCH 116/219] Remove intermediate containers when building from Dockerfile --- docker.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker.go b/docker.go index dd50ed5c7b..1e086b763e 100644 --- a/docker.go +++ b/docker.go @@ -657,6 +657,8 @@ func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (st Dockerfile: img.GetDockerfile(), Context: buildContext, Tags: []string{repoTag}, + Remove: true, + ForceRemove: true, } resp, err := p.client.ImageBuild(ctx, buildContext, buildOptions) From 5f676b8ae0fbf39a71330a1a72a110fc6e53cddf Mon Sep 17 00:00:00 2001 From: Gabor Szakacs Date: Mon, 14 Feb 2022 18:18:11 +0100 Subject: [PATCH 117/219] Remove custom built docker image on container termination --- docker.go | 21 +++++++++--- docker_test.go | 90 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 92 insertions(+), 19 deletions(-) diff --git a/docker.go b/docker.go index dd50ed5c7b..d52a9e2216 100644 --- a/docker.go +++ b/docker.go @@ -52,6 +52,7 @@ type DockerContainer struct { WaitingFor wait.Strategy Image string + imageWasBuilt bool provider *DockerProvider sessionID uuid.UUID terminationSignal chan bool @@ -192,15 +193,26 @@ func (c *DockerContainer) Terminate(ctx context.Context) error { RemoveVolumes: true, Force: true, }) + if err != nil { + return err + } - if err == nil { - if err := c.provider.client.Close(); err != nil { + if c.imageWasBuilt { + _, err := c.provider.client.ImageRemove(ctx, c.Image, types.ImageRemoveOptions{ + Force: true, + PruneChildren: true, + }) + if err != nil { return err } - c.sessionID = uuid.UUID{} } - return err + if err := c.provider.client.Close(); err != nil { + return err + } + + c.sessionID = uuid.UUID{} + return nil } // update container raw info @@ -876,6 +888,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque ID: resp.ID, WaitingFor: req.WaitingFor, Image: tag, + imageWasBuilt: req.ShouldBuildImage(), sessionID: sessionID, provider: p, terminationSignal: termSignal, diff --git a/docker_test.go b/docker_test.go index 01fb061464..bbb902a000 100644 --- a/docker_test.go +++ b/docker_test.go @@ -66,7 +66,6 @@ func TestContainerAttachedToNewNetwork(t *testing.T) { CheckDuplicate: true, }, }) - if err != nil { t.Fatal(err) } @@ -292,7 +291,8 @@ func TestContainerStartsWithoutTheReaper(t *testing.T) { Image: "nginx", ExposedPorts: []string{ "80/tcp", - "gotest.tools/assert"}, + "gotest.tools/assert", + }, SkipReaper: true, }, Started: true, @@ -460,6 +460,76 @@ func TestContainerTerminationWithoutReaper(t *testing.T) { } } +func TestContainerTerminationRemovesDockerfileDockerImage(t *testing.T) { + t.Run("if not built from Dockerfile", func(t *testing.T) { + ctx := context.Background() + client, err := client.NewClientWithOpts(client.FromEnv) + if err != nil { + t.Fatal(err) + } + client.NegotiateAPIVersion(ctx) + container, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: ContainerRequest{ + Image: "nginx", + ExposedPorts: []string{ + "80/tcp", + }, + SkipReaper: true, + }, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + err = container.Terminate(ctx) + if err != nil { + t.Fatal(err) + } + _, _, err = client.ImageInspectWithRaw(ctx, "nginx") + if err != nil { + t.Fatal("nginx image should not have been removed") + } + }) + + t.Run("if built from Dockerfile", func(t *testing.T) { + ctx := context.Background() + client, err := client.NewClientWithOpts(client.FromEnv) + if err != nil { + t.Fatal(err) + } + client.NegotiateAPIVersion(ctx) + req := ContainerRequest{ + FromDockerfile: FromDockerfile{ + Context: "./testresources", + }, + ExposedPorts: []string{"6379/tcp"}, + WaitingFor: wait.ForLog("Ready to accept connections"), + } + container, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + containerID := container.GetContainerID() + resp, err := client.ContainerInspect(ctx, containerID) + if err != nil { + t.Fatal(err) + } + imageID := resp.Config.Image + + err = container.Terminate(ctx) + if err != nil { + t.Fatal(err) + } + _, _, err = client.ImageInspectWithRaw(ctx, imageID) + if err == nil { + t.Fatal("custom built image should have been removed") + } + }) +} + func TestTwoContainersExposingTheSamePort(t *testing.T) { ctx := context.Background() nginxA, err := GenericContainer(ctx, GenericContainerRequest{ @@ -927,7 +997,6 @@ func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { } c, err := GenericContainer(ctx, genContainerReq) - if err != nil { t.Fatal(err) } @@ -938,13 +1007,11 @@ func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { } resp, err := http.Get(ep + "/env") - if err != nil { t.Fatal(err) } body, err := ioutil.ReadAll(resp.Body) - if err != nil { t.Fatal(err) } @@ -985,7 +1052,6 @@ func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { } c, err := GenericContainer(ctx, genContainerReq) - if err != nil { t.Fatal(err) } @@ -1007,7 +1073,6 @@ func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { if temp[0] != "Step 1/1 : FROM alpine" { t.Errorf("Expected stout firstline to be %s. Got '%s'.", "Step 1/2 : FROM alpine", temp[0]) } - } func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { @@ -1032,7 +1097,6 @@ func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { if err == nil { t.Fatal("Expected timeout") } - } func TestContainerCreationWaitingForHostPort(t *testing.T) { @@ -1100,7 +1164,6 @@ func TestContainerCreationWaitsForLogAndPort(t *testing.T) { ContainerRequest: req, Started: true, }) - if err != nil { t.Fatal(err) } @@ -1120,7 +1183,6 @@ func TestContainerCreationWaitsForLogAndPort(t *testing.T) { "root", "password", host, port, "database") db, err := sql.Open("mysql", connectionString) - if err != nil { t.Fatal(err) } @@ -1130,7 +1192,6 @@ func TestContainerCreationWaitsForLogAndPort(t *testing.T) { if err = db.Ping(); err != nil { t.Errorf("error pinging db: %+v\n", err) } - } func TestCMD(t *testing.T) { @@ -1154,7 +1215,6 @@ func TestCMD(t *testing.T) { ContainerRequest: req, Started: true, }) - if err != nil { t.Fatal(err) } @@ -1184,7 +1244,6 @@ func TestEntrypoint(t *testing.T) { ContainerRequest: req, Started: true, }) - if err != nil { t.Fatal(err) } @@ -1239,7 +1298,8 @@ func TestReadTCPropsFile(t *testing.T) { 0, "", }, - {`docker.host = tcp://127.0.0.1:33293 + { + `docker.host = tcp://127.0.0.1:33293 docker.host = tcp://127.0.0.1:4711 docker.host = tcp://127.0.0.1:1234 docker.tls.verify = 1 @@ -1437,7 +1497,7 @@ func TestContainerWithTmpFs(t *testing.T) { } }() - var path = "/testtmpfs/test.file" + path := "/testtmpfs/test.file" c, err := container.Exec(ctx, []string{"ls", path}) if err != nil { From e98e4e1daccd0ef511ab1282097bab0dbb8a19ea Mon Sep 17 00:00:00 2001 From: Gabor Szakacs Date: Mon, 14 Feb 2022 18:24:06 +0100 Subject: [PATCH 118/219] Clarify test name --- docker_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker_test.go b/docker_test.go index bbb902a000..bc30977b1a 100644 --- a/docker_test.go +++ b/docker_test.go @@ -460,7 +460,7 @@ func TestContainerTerminationWithoutReaper(t *testing.T) { } } -func TestContainerTerminationRemovesDockerfileDockerImage(t *testing.T) { +func TestContainerTerminationRemovesDockerImage(t *testing.T) { t.Run("if not built from Dockerfile", func(t *testing.T) { ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) From e1be58a72d8ca23c8954d3b4a7085cdf1a45df20 Mon Sep 17 00:00:00 2001 From: Kirill Artamonov Date: Mon, 8 Nov 2021 21:26:06 +0100 Subject: [PATCH 119/219] Add support for Docker Compose V2 generated container names and compose-file specified container names --- compose.go | 9 ++++--- compose_test.go | 25 +++++++++++++++++++ .../docker-compose-container-name.yml | 9 +++++++ 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 testresources/docker-compose-container-name.yml diff --git a/compose.go b/compose.go index caabd61e4c..d5333d735e 100644 --- a/compose.go +++ b/compose.go @@ -142,11 +142,12 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { } for k := range dc.WaitStrategyMap { - // TODO: if the compose file includes a container_name, this won't work, - // as we cannot delegate to the names generated by Docker Compose containerName := dc.Identifier + "_" + k.service - // Docker compose appends "_1" to every started service by default. Trimming to match running docker container - f := filters.NewArgs(filters.Arg("name", containerName)) + composeV2ContainerName := strings.ReplaceAll(containerName, "_", "-") + f := filters.NewArgs( + filters.Arg("name", containerName), + filters.Arg("name", composeV2ContainerName), + filters.Arg("name", k.service)) containerListOptions := types.ContainerListOptions{Filters: f} containers, err := cli.ContainerList(context.Background(), containerListOptions) if err != nil { diff --git a/compose_test.go b/compose_test.go index c448c14d8b..835028430e 100644 --- a/compose_test.go +++ b/compose_test.go @@ -204,6 +204,31 @@ func TestDockerComposeWithWaitHTTPStrategy(t *testing.T) { assert.Contains(t, compose.Services, "nginx") } +func TestDockerComposeWithContainerName(t *testing.T) { + path := "./testresources/docker-compose-container-name.yml" + + identifier := strings.ToLower(uuid.New().String()) + + compose := NewLocalDockerCompose([]string{path}, identifier) + destroyFn := func() { + err := compose.Down() + checkIfError(t, err) + } + defer destroyFn() + + err := compose. + WithCommand([]string{"up", "-d"}). + WithEnv(map[string]string{ + "bar": "BAR", + }). + WithExposedService("nginxy", 9080, wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). + Invoke() + checkIfError(t, err) + + assert.Equal(t, 1, len(compose.Services)) + assert.Contains(t, compose.Services, "nginx") +} + func TestDockerComposeWithWaitStrategy_NoExposedPorts(t *testing.T) { path := "./testresources/docker-compose-no-exposed-ports.yml" diff --git a/testresources/docker-compose-container-name.yml b/testresources/docker-compose-container-name.yml new file mode 100644 index 0000000000..99525f7f7a --- /dev/null +++ b/testresources/docker-compose-container-name.yml @@ -0,0 +1,9 @@ +version: '3' +services: + nginx: + container_name: nginxy + image: nginx:stable-alpine + environment: + bar: ${bar} + ports: + - "9080:80" From 336d8881bdeb8ee2de8318fa47555f31635fecfe Mon Sep 17 00:00:00 2001 From: Gabor Szakacs Date: Tue, 15 Feb 2022 18:47:40 +0100 Subject: [PATCH 120/219] Fix formatting --- docker.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker.go b/docker.go index 1e086b763e..c9c26c70f8 100644 --- a/docker.go +++ b/docker.go @@ -653,10 +653,10 @@ func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (st } buildOptions := types.ImageBuildOptions{ - BuildArgs: img.GetBuildArgs(), - Dockerfile: img.GetDockerfile(), - Context: buildContext, - Tags: []string{repoTag}, + BuildArgs: img.GetBuildArgs(), + Dockerfile: img.GetDockerfile(), + Context: buildContext, + Tags: []string{repoTag}, Remove: true, ForceRemove: true, } From bd4c1b69d4a6c59e7e84f485618a56f702252396 Mon Sep 17 00:00:00 2001 From: Andre Soares Date: Mon, 21 Feb 2022 10:36:47 -0300 Subject: [PATCH 121/219] use var TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE --- reaper.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/reaper.go b/reaper.go index 2a84127e27..55c7ac2937 100644 --- a/reaper.go +++ b/reaper.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "net" + "os" "strings" "sync" "time" @@ -22,8 +23,10 @@ const ( ReaperDefaultImage = "docker.io/testcontainers/ryuk:0.3.3" ) -var reaper *Reaper // We would like to create reaper only once -var mutex sync.Mutex +var ( + reaper *Reaper // We would like to create reaper only once + mutex sync.Mutex +) // ReaperProvider represents a provider for the reaper to run itself with // The ContainerProvider interface should usually satisfy this as well, so it is pluggable @@ -63,7 +66,10 @@ func NewReaper(ctx context.Context, sessionID string, provider ReaperProvider, r TestcontainerLabelIsReaper: "true", }, SkipReaper: true, - Mounts: Mounts(BindMount("/var/run/docker.sock", "/var/run/docker.sock")), + Mounts: Mounts(BindMount( + coalesce(os.Getenv("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE"), "/var/run/docker.sock"), + "/var/run/docker.sock", + )), AutoRemove: true, WaitingFor: wait.ForListeningPort(listeningPort), } @@ -143,3 +149,10 @@ func (r *Reaper) Labels() map[string]string { TestcontainerLabelSessionID: r.SessionID, } } + +func coalesce(text, fallback string) string { + if text == "" { + return fallback + } + return text +} From b748ad72c9006523a27496a6218fcb25bcb7be62 Mon Sep 17 00:00:00 2001 From: Kevin Woo Date: Thu, 24 Feb 2022 16:27:08 -0800 Subject: [PATCH 122/219] add import statements to quick start --- docs/quickstart/gotest.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/quickstart/gotest.md b/docs/quickstart/gotest.md index fce5ae7522..51896d3c33 100644 --- a/docs/quickstart/gotest.md +++ b/docs/quickstart/gotest.md @@ -16,6 +16,11 @@ go get github.com/testcontainers/testcontainers-go ## 2. Spin up Redis ```go +import ( + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + func TestWithRedis(t *testing.T) { ctx := context.Background() req := testcontainers.ContainerRequest{ From c30da9e782312f32db67472b689148dbe3533b30 Mon Sep 17 00:00:00 2001 From: Kevin Woo Date: Fri, 25 Feb 2022 23:12:38 -0800 Subject: [PATCH 123/219] docs/gotests: fixed broken link for garbage collector --- docs/quickstart/gotest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/quickstart/gotest.md b/docs/quickstart/gotest.md index fce5ae7522..3826449548 100644 --- a/docs/quickstart/gotest.md +++ b/docs/quickstart/gotest.md @@ -65,7 +65,7 @@ terminated function: `defer redisC.Terminate(ctx)`. !!!tip - Look at [features/garbage_collector.md] to know the another way you have to + Look at [features/garbage_collector](/features/garbage_collector/) to know the another way you have to clean up. ## 3. Make your code to talk with the container From d4b09e0775af266256135b905a3d63522d441acc Mon Sep 17 00:00:00 2001 From: Zlatko Bratkovic Date: Sat, 19 Mar 2022 10:26:03 +0100 Subject: [PATCH 124/219] add ability to stop container --- container.go | 2 ++ docker.go | 22 ++++++++++++++++++ docker_test.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/container.go b/container.go index 322785125e..298930450b 100644 --- a/container.go +++ b/container.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "time" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" @@ -40,6 +41,7 @@ type Container interface { Ports(context.Context) (nat.PortMap, error) // get all exposed ports SessionID() string // get session id Start(context.Context) error // start the container + Stop(context.Context, *time.Duration) error // stop the container Terminate(context.Context) error // terminate the container Logs(context.Context) (io.ReadCloser, error) // Get logs of the container FollowOutput(LogConsumer) diff --git a/docker.go b/docker.go index f7c10df6f9..62921efcee 100644 --- a/docker.go +++ b/docker.go @@ -182,6 +182,28 @@ func (c *DockerContainer) Start(ctx context.Context) error { return nil } +// Stop will stop an already started container +// +// In case the container fails to stop +// gracefully within a time frame specified by the timeout argument, +// it is forcefully terminated (killed). +// +// If the timeout is nil, the container's StopTimeout value is used, if set, +// otherwise the engine default. A negative timeout value can be specified, +// meaning no timeout, i.e. no forceful termination is performed. +func (c *DockerContainer) Stop(ctx context.Context, timeout *time.Duration) error { + shortID := c.ID[:12] + c.logger.Printf("Stopping container id: %s image: %s", shortID, c.Image) + + if err := c.provider.client.ContainerStop(ctx, c.ID, timeout); err != nil { + return err + } + + c.logger.Printf("Container is stopped id: %s image: %s", shortID, c.Image) + + return nil +} + // Terminate is used to kill the container. It is usually triggered by as defer function. func (c *DockerContainer) Terminate(ctx context.Context) error { select { diff --git a/docker_test.go b/docker_test.go index bc30977b1a..d77e09f6f8 100644 --- a/docker_test.go +++ b/docker_test.go @@ -385,6 +385,53 @@ func TestContainerTerminationResetsState(t *testing.T) { } } +func TestContainerStopWithReaper(t *testing.T) { + ctx := context.Background() + client, err := client.NewClientWithOpts(client.FromEnv) + if err != nil { + t.Fatal(err) + } + client.NegotiateAPIVersion(ctx) + nginxA, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: ContainerRequest{ + Image: "nginx", + ExposedPorts: []string{ + "80/tcp", + }, + }, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + defer func() { + _ = nginxA.Terminate(ctx) + }() + containerID := nginxA.GetContainerID() + resp, err := client.ContainerInspect(ctx, containerID) + if err != nil { + t.Fatal(err) + } + if resp.State.Running != true { + t.Fatal("The container shoud be in running state") + } + stopTimeout := 10 * time.Second + err = nginxA.Stop(ctx, &stopTimeout) + if err != nil { + t.Fatal(err) + } + resp, err = client.ContainerInspect(ctx, containerID) + if err != nil { + t.Fatal(err) + } + if resp.State.Running != false { + t.Fatal("The container shoud not be running") + } + if resp.State.Status != "exited" { + t.Fatal("The container shoud be in exited state") + } +} + func TestContainerTerminationWithReaper(t *testing.T) { ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) @@ -1405,6 +1452,21 @@ func ExampleContainer_Start() { _ = nginxC.Start(ctx) } +func ExampleContainer_Stop() { + ctx := context.Background() + req := ContainerRequest{ + Image: "nginx", + ExposedPorts: []string{"80/tcp"}, + WaitingFor: wait.ForHTTP("/"), + } + nginxC, _ := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + }) + defer nginxC.Terminate(ctx) + timeout := 10 * time.Second + _ = nginxC.Stop(ctx, &timeout) +} + func ExampleContainer_MappedPort() { ctx := context.Background() req := ContainerRequest{ From 1703875dc0b0e1e4acc1a5721ff53c2e82c2ceac Mon Sep 17 00:00:00 2001 From: Zlatko Bratkovic Date: Sat, 19 Mar 2022 15:58:33 +0100 Subject: [PATCH 125/219] expose CopyToContainer so file can be created only in memory this is especially useful in tests, since we do not need to create a file for testing, we can just generate it in memory and then copy it to a container directly --- container.go | 1 + docker.go | 4 ++++ docker_test.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/container.go b/container.go index 322785125e..1f067c0bf5 100644 --- a/container.go +++ b/container.go @@ -51,6 +51,7 @@ type Container interface { NetworkAliases(context.Context) (map[string][]string, error) // get container network aliases for a network Exec(ctx context.Context, cmd []string) (int, error) ContainerIP(context.Context) (string, error) // get container ip + CopyToContainer(ctx context.Context, fileContent []byte, containerFilePath string, fileMode int64) error CopyFileToContainer(ctx context.Context, hostFilePath string, containerFilePath string, fileMode int64) error CopyFileFromContainer(ctx context.Context, filePath string) (io.ReadCloser, error) } diff --git a/docker.go b/docker.go index f7c10df6f9..1a0cd86593 100644 --- a/docker.go +++ b/docker.go @@ -395,7 +395,11 @@ func (c *DockerContainer) CopyFileToContainer(ctx context.Context, hostFilePath if err != nil { return err } + return c.CopyToContainer(ctx, fileContent, containerFilePath, fileMode) +} +// CopyToContainer copies fileContent data to a file in container +func (c *DockerContainer) CopyToContainer(ctx context.Context, fileContent []byte, containerFilePath string, fileMode int64) error { buffer := &bytes.Buffer{} tw := tar.NewWriter(buffer) diff --git a/docker_test.go b/docker_test.go index bc30977b1a..c3959865b0 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1687,6 +1687,35 @@ func TestDockerContainerCopyFileToContainer(t *testing.T) { } } +func TestDockerContainerCopyToContainer(t *testing.T) { + ctx := context.Background() + + nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: ContainerRequest{ + Image: "nginx:1.17.6", + ExposedPorts: []string{"80/tcp"}, + WaitingFor: wait.ForListeningPort("80/tcp"), + }, + Started: true, + }) + defer nginxC.Terminate(ctx) + + copiedFileName := "hello_copy.sh" + + fileContent, err := ioutil.ReadFile("./testresources/hello.sh") + if err != nil { + t.Fatal(err) + } + _ = nginxC.CopyToContainer(ctx, fileContent, "/"+copiedFileName, 700) + c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) + if err != nil { + t.Fatal(err) + } + if c != 0 { + t.Fatalf("File %s should exist, expected return code 0, got %v", copiedFileName, c) + } +} + func TestDockerContainerCopyFileFromContainer(t *testing.T) { fileContent, err := ioutil.ReadFile("./testresources/hello.sh") if err != nil { From cc3a9df3d575ef657600656754711b7c43a7d9db Mon Sep 17 00:00:00 2001 From: Ori Seri Date: Thu, 31 Mar 2022 11:13:51 +0300 Subject: [PATCH 126/219] Add the output of the command to the ExecError struct --- compose.go | 36 +++++++++++++++++++++++------------- compose_test.go | 3 +++ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/compose.go b/compose.go index d5333d735e..dcbceba326 100644 --- a/compose.go +++ b/compose.go @@ -243,10 +243,12 @@ func (dc *LocalDockerCompose) validate() error { // ExecError is super struct that holds any information about an execution error, so the client code // can handle the result type ExecError struct { - Command []string - Error error - Stdout error - Stderr error + Command []string + StdoutOutput []byte + StderrOutput []byte + Error error + Stdout error + Stderr error } // execute executes a program with arguments and environment variables inside a specific directory @@ -276,10 +278,12 @@ func execute( return ExecError{ // add information about the CMD and arguments used - Command: execCmd, - Error: err, - Stderr: errStderr, - Stdout: errStdout, + Command: execCmd, + StdoutOutput: stdout.Bytes(), + StderrOutput: stderr.Bytes(), + Error: err, + Stderr: errStderr, + Stdout: errStdout, } } @@ -300,10 +304,12 @@ func execute( execCmd = append(execCmd, args...) return ExecError{ - Command: execCmd, - Error: err, - Stderr: errStderr, - Stdout: errStdout, + Command: execCmd, + StdoutOutput: stdout.Bytes(), + StderrOutput: stderr.Bytes(), + Error: err, + Stderr: errStderr, + Stdout: errStdout, } } @@ -377,7 +383,11 @@ func (w *capturingPassThroughWriter) Write(d []byte) (int, error) { // Bytes returns bytes written to the writer func (w *capturingPassThroughWriter) Bytes() []byte { - return w.buf.Bytes() + b := w.buf.Bytes() + if b == nil { + b = []byte{} + } + return b } // Which checks if a binary is present in PATH diff --git a/compose_test.go b/compose_test.go index 835028430e..9f4581d04a 100644 --- a/compose_test.go +++ b/compose_test.go @@ -453,6 +453,9 @@ func checkIfError(t *testing.T, err ExecError) { if err.Stderr != nil { t.Fatalf("An error in Stderr happened when running %v: %v", err.Command, err.Stderr) } + + assert.NotNil(t, err.StdoutOutput) + assert.NotNil(t, err.StderrOutput) } func executeAndGetOutput(command string, args []string) (string, ExecError) { From 1c940408ea23b8bb2ff48cbe4820c1be99932ab0 Mon Sep 17 00:00:00 2001 From: Ori Seri Date: Thu, 31 Mar 2022 14:22:16 +0300 Subject: [PATCH 127/219] fix test --- compose_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compose_test.go b/compose_test.go index 9f4581d04a..792bd2950f 100644 --- a/compose_test.go +++ b/compose_test.go @@ -461,9 +461,10 @@ func checkIfError(t *testing.T, err ExecError) { func executeAndGetOutput(command string, args []string) (string, ExecError) { cmd := exec.Command(command, args...) out, err := cmd.CombinedOutput() - if err != nil { - return string(out), ExecError{Error: err} - } - return string(out), ExecError{Error: nil} + return string(out), ExecError{ + Error: err, + StderrOutput: out, + StdoutOutput: out, + } } From 8e35feb4f27b3eee6ee919b2163f88fc348cd5e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 4 Apr 2022 10:58:40 +0200 Subject: [PATCH 128/219] fix: use 1.18 format to install dependencies --- .github/workflows/ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d0b7aff0b..b55e157f3b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,10 +33,17 @@ jobs: uses: actions/checkout@v2 - name: Get dependencies + if: ${{ matrix.go-version != '1.x' }} run: | go get -v -t -d ./... go get gotest.tools/gotestsum + - name: Get dependencies for 1.18 + if: ${{ matrix.go-version == '1.x' }} + run: | + go install -v -t -d ./... + go install gotest.tools/gotestsum + - name: modVerify run: go mod verify From 872e1e071532c0701e5f912c93701ac6b4b997bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 4 Apr 2022 11:05:20 +0200 Subject: [PATCH 129/219] chore: remove unnecessary install go mod tidy will do the rest --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b55e157f3b..95b1e384c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,13 +35,11 @@ jobs: - name: Get dependencies if: ${{ matrix.go-version != '1.x' }} run: | - go get -v -t -d ./... go get gotest.tools/gotestsum - name: Get dependencies for 1.18 if: ${{ matrix.go-version == '1.x' }} run: | - go install -v -t -d ./... go install gotest.tools/gotestsum - name: modVerify From 7a21297eb397b314ff9bc761ae1d4c95fd1b1c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 4 Apr 2022 11:09:20 +0200 Subject: [PATCH 130/219] chore: add tools.go for build tools dependencies --- .github/workflows/ci.yml | 10 ---------- tools/tools.go | 11 +++++++++++ 2 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 tools/tools.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 95b1e384c9..3acecfca9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,16 +32,6 @@ jobs: - name: Check out code into the Go module directory uses: actions/checkout@v2 - - name: Get dependencies - if: ${{ matrix.go-version != '1.x' }} - run: | - go get gotest.tools/gotestsum - - - name: Get dependencies for 1.18 - if: ${{ matrix.go-version == '1.x' }} - run: | - go install gotest.tools/gotestsum - - name: modVerify run: go mod verify diff --git a/tools/tools.go b/tools/tools.go new file mode 100644 index 0000000000..724d23e17f --- /dev/null +++ b/tools/tools.go @@ -0,0 +1,11 @@ +//go:build tools +// +build tools + +// This package contains the tool dependencies of the project. + +package tools + +import ( + // Register gotestsum for pinning version + _ "gotest.tools/gotestsum" +) From 3ccd15a60585f0158653040b5b92710494856d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 4 Apr 2022 11:09:35 +0200 Subject: [PATCH 131/219] chore: run go mod tidy --- go.mod | 2 ++ go.sum | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/go.mod b/go.mod index 2bb54824ae..9038d1232c 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/containerd/containerd v1.5.9 github.com/docker/docker v20.10.11+incompatible github.com/docker/go-connections v0.4.0 + github.com/docker/go-units v0.4.0 github.com/go-redis/redis v6.15.9+incompatible github.com/go-sql-driver/mysql v1.6.0 github.com/golang/protobuf v1.5.2 // indirect @@ -21,5 +22,6 @@ require ( golang.org/x/net v0.0.0-20211108170745-6635138e15ea // indirect golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b + gotest.tools/gotestsum v1.7.0 gotest.tools/v3 v3.0.3 ) diff --git a/go.sum b/go.sum index 9e5a8c3138..e6778279ab 100644 --- a/go.sum +++ b/go.sum @@ -224,6 +224,8 @@ github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/dnephin/pflag v1.0.7 h1:oxONGlWxhmUct0YzKTgrpQv9AUA1wtPBn7zuSjJqptk= +github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= @@ -252,6 +254,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -347,6 +351,8 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -388,6 +394,8 @@ github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6t github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -421,7 +429,11 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -669,6 +681,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -719,6 +732,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -755,6 +769,7 @@ golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -777,14 +792,17 @@ golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -837,6 +855,8 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -944,6 +964,8 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/gotestsum v1.7.0 h1:RwpqwwFKBAa2h+F6pMEGpE707Edld0etUD3GhqqhDNc= +gotest.tools/gotestsum v1.7.0/go.mod h1:V1m4Jw3eBerhI/A6qCxUE07RnCg7ACkKj9BYcAm09V8= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= From 349e86f8cf0e6d967a7a10a315f2028d75728f01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 4 Apr 2022 11:12:42 +0200 Subject: [PATCH 132/219] fix: run gotestsum from go packages --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3acecfca9b..d77c6f39c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,7 @@ jobs: # we can't put Windows Server in "Linux Mode" in Github actions # another, host mode is only available on Linux, and we have tests around that, do we skip them? if: ${{ matrix.platform == 'ubuntu-latest' }} - run: gotestsum --format short-verbose -- -coverprofile=cover.txt ./... + run: go run gotest.tools/gotestsum --format short-verbose -- -coverprofile=cover.txt ./... # only report code coverage on linux - name: Upload coverage report From 4d19e56af26aafdb23f08f32d411b48a6461befe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 4 Apr 2022 12:40:39 +0200 Subject: [PATCH 133/219] fix: pin jinja2 See https://github.com/mkdocs/mkdocs/issues/2799 --- Pipfile | 1 + requirements.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/Pipfile b/Pipfile index 50123140d8..783612aea4 100644 --- a/Pipfile +++ b/Pipfile @@ -6,6 +6,7 @@ verify_ssl = true [dev-packages] [packages] +jinja2 = "3.0.0" mkdocs = "*" mkdocs-material = "*" mkdocs-markdownextradata-plugin = "*" diff --git a/requirements.txt b/requirements.txt index 81665380e7..b9617a8d55 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +jinja2==3.0.0 mkdocs==1.0.4 mkdocs-material==4.6.0 mkdocs-markdownextradata-plugin==0.1.1 From e04167fa2ad5f8c6910a349a2d93e099dee29849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 29 Mar 2022 10:33:32 +0200 Subject: [PATCH 134/219] docs: prepare for neutral branch name --- README.md | 2 +- docs/index.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 52e1eae300..0941011c8f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Main pipeline](https://github.com/testcontainers/testcontainers-go/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/testcontainers/testcontainers-go/actions/workflows/ci.yml) +[![Main pipeline](https://github.com/testcontainers/testcontainers-go/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/testcontainers/testcontainers-go/actions/workflows/ci.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/testcontainers/testcontainers-go)](https://goreportcard.com/report/github.com/testcontainers/testcontainers-go) [![GoDoc Reference](https://camo.githubusercontent.com/8609cfcb531fa0f5598a3d4353596fae9336cce3/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f79616e6777656e6d61692f686f772d746f2d6164642d62616467652d696e2d6769746875622d726561646d653f7374617475732e737667)](https://pkg.go.dev/github.com/testcontainers/testcontainers-go) diff --git a/docs/index.md b/docs/index.md index 986841f97a..182acd2408 100644 --- a/docs/index.md +++ b/docs/index.md @@ -23,7 +23,7 @@ examples as well. Check it out at ## License -See [LICENSE](https://github.com/testcontainers/testcontainers-go/blob/master/LICENSE). +See [LICENSE](https://github.com/testcontainers/testcontainers-go/blob/main/LICENSE). ## Copyright From a9743f872566c6c95fd5c9384d2193734bd51e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 4 Apr 2022 13:09:17 +0200 Subject: [PATCH 135/219] chore: update link to main --- docker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker.go b/docker.go index 2d4df4a2eb..d67708051b 100644 --- a/docker.go +++ b/docker.go @@ -1126,7 +1126,7 @@ func inAContainer() bool { } // deprecated -// see https://github.com/testcontainers/testcontainers-java/blob/master/core/src/main/java/org/testcontainers/dockerclient/DockerClientConfigUtils.java#L46 +// see https://github.com/testcontainers/testcontainers-java/blob/main/core/src/main/java/org/testcontainers/dockerclient/DockerClientConfigUtils.java#L46 func getDefaultGatewayIP() (string, error) { // see https://github.com/testcontainers/testcontainers-java/blob/3ad8d80e2484864e554744a4800a81f6b7982168/core/src/main/java/org/testcontainers/dockerclient/DockerClientConfigUtils.java#L27 cmd := exec.Command("sh", "-c", "ip route|awk '/default/ { print $3 }'") From d41ddd040b2db2b624516191b4bb76b9c551f91d Mon Sep 17 00:00:00 2001 From: Ori Seri Date: Thu, 7 Apr 2022 13:50:52 +0300 Subject: [PATCH 136/219] In compose name V2, replace only the seprator between the identifier and the service name --- compose.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose.go b/compose.go index d5333d735e..b549030650 100644 --- a/compose.go +++ b/compose.go @@ -143,7 +143,7 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { for k := range dc.WaitStrategyMap { containerName := dc.Identifier + "_" + k.service - composeV2ContainerName := strings.ReplaceAll(containerName, "_", "-") + composeV2ContainerName := dc.Identifier + "-" + k.service f := filters.NewArgs( filters.Arg("name", containerName), filters.Arg("name", composeV2ContainerName), From c53f9f9e7f98696fe736792ef21947f1136ddda9 Mon Sep 17 00:00:00 2001 From: Ori Seri Date: Thu, 7 Apr 2022 13:56:18 +0300 Subject: [PATCH 137/219] Move to a function --- compose.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compose.go b/compose.go index b549030650..70bb427853 100644 --- a/compose.go +++ b/compose.go @@ -135,6 +135,10 @@ func (dc *LocalDockerCompose) getDockerComposeEnvironment() map[string]string { return environment } +func (dc *LocalDockerCompose) containerNameFromServiceName(service, separator string) string { + return dc.Identifier + separator + service +} + func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { cli, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -142,8 +146,8 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { } for k := range dc.WaitStrategyMap { - containerName := dc.Identifier + "_" + k.service - composeV2ContainerName := dc.Identifier + "-" + k.service + containerName := dc.containerNameFromServiceName(k.service, "_") + composeV2ContainerName := dc.containerNameFromServiceName(k.service, "-") f := filters.NewArgs( filters.Arg("name", containerName), filters.Arg("name", composeV2ContainerName), From afe2deb2ec2b9680db6bc8cd830a1f8ff694fea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 19 Apr 2022 12:43:27 +0200 Subject: [PATCH 138/219] chore: update branding --- docs/css/extra.css | 12 +++--- docs/favicon.ico | Bin 15086 -> 15406 bytes docs/logo.png | Bin 51964 -> 84934 bytes docs/logo.svg | 99 +++++++++++++++++++++++++++++++++++++++++---- mkdocs.yml | 7 ++-- 5 files changed, 101 insertions(+), 17 deletions(-) diff --git a/docs/css/extra.css b/docs/css/extra.css index ae717a1c42..4c11e3df74 100644 --- a/docs/css/extra.css +++ b/docs/css/extra.css @@ -1,10 +1,10 @@ -@import url('https://fonts.googleapis.com/css?family=Inconsolata|Lato|Merriweather+Sans|Open+Sans|Source+Sans+Pro'); +@import url('https://fonts.googleapis.com/css?family=Rubik'); +h1, h2, h3, h4, h5, h6 { + font-family: 'Rubik', sans-serif; -body { - font-family: 'Lato', sans-serif; } -.md-typeset pre { - font-family: 'Inconsolata', monospace; - font-size: 100%; +[data-md-color-scheme="testcontainers"] { + --md-primary-fg-color: #291A3F; + --md-accent-fg-color: #291A3F; } diff --git a/docs/favicon.ico b/docs/favicon.ico index 004282385c3e9b51ece573d194b64693145dc2e1..311a0acaa373f197360673f8ac6bc1b3c38c7e7f 100644 GIT binary patch literal 15406 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 EAH!e_G5`Po diff --git a/docs/logo.png b/docs/logo.png index 696e03ad6ff360ce03647928910996169e329b4f..3d8f03fa0cf0fb98578e83d9b2ff71de3ead11c0 100644 GIT binary patch literal 84934 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 Gg8vr^t7`)Q diff --git a/docs/logo.svg b/docs/logo.svg index 3a8db707fc..bac0c391a5 100644 --- a/docs/logo.svg +++ b/docs/logo.svg @@ -1,9 +1,92 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mkdocs.yml b/mkdocs.yml index 3b29c16cbb..fad8727dea 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -5,9 +5,10 @@ plugins: theme: name: 'material' palette: - primary: 'blue' - accent: 'teal' - font: false + scheme: 'testcontainers' + font: + text: Roboto + code: Roboto Mono logo: 'logo.svg' favicon: 'favicon.ico' extra_css: From 9fefa66f6fe30a22f152da17e517272e679466a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 26 Apr 2022 13:36:19 +0200 Subject: [PATCH 139/219] chore: update pip dependencies for mkdocs This config file is cloning what the Java folks are doing --- Pipfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pipfile b/Pipfile index 783612aea4..2236de86da 100644 --- a/Pipfile +++ b/Pipfile @@ -6,8 +6,8 @@ verify_ssl = true [dev-packages] [packages] -jinja2 = "3.0.0" mkdocs = "*" +mkdocs-codeinclude-plugin = "*" mkdocs-material = "*" mkdocs-markdownextradata-plugin = "*" From fc1d1d4113eff9860555a709f3169fd2d27697da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 26 Apr 2022 13:45:18 +0200 Subject: [PATCH 140/219] chore: more updates --- mkdocs.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index fad8727dea..94a7ff09b4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,11 +1,13 @@ site_name: Testcontainers-Go plugins: - search + - codeinclude - markdownextradata theme: name: 'material' + custom_dir: 'docs/theme' palette: - scheme: 'testcontainers' + scheme: testcontainers font: text: Roboto code: Roboto Mono @@ -20,6 +22,8 @@ markdown_extensions: - codehilite: linenums: False - pymdownx.superfences + - pymdownx.tabbed: + alternate_style: true - pymdownx.snippets nav: - Home: index.md From 85d339dc6e752574d3a1643498ef3f13f8e66723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 26 Apr 2022 13:45:58 +0200 Subject: [PATCH 141/219] chore: update testcontainers-go version --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 94a7ff09b4..3e2fc56cc7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -45,4 +45,4 @@ nav: - contributing_docs.md - Getting help: getting_help.md extra: - latest_version: 1.14.1 + latest_version: 0.13.0 From b2d6e253df90bbb913d523f632be3a25bf8efb19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 26 Apr 2022 13:47:57 +0200 Subject: [PATCH 142/219] chore: sync python deps for mkdocs --- requirements.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/requirements.txt b/requirements.txt index b9617a8d55..f77d057b59 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ -jinja2==3.0.0 -mkdocs==1.0.4 -mkdocs-material==4.6.0 -mkdocs-markdownextradata-plugin==0.1.1 -markdown>=3.1,<3.2 +mkdocs==1.3.0 +mkdocs-codeinclude-plugin==0.2.0 +mkdocs-material==8.1.3 +mkdocs-markdownextradata-plugin==0.2.5 From 62b0bf0022ec097d9ea1586bf71d5c718876710d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 26 Apr 2022 13:50:27 +0200 Subject: [PATCH 143/219] fix: remove unused mkdocs setting --- mkdocs.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 3e2fc56cc7..90b01359a1 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -5,7 +5,6 @@ plugins: - markdownextradata theme: name: 'material' - custom_dir: 'docs/theme' palette: scheme: testcontainers font: From 23e196144ea4cf4bfd81017934a517da3126ee13 Mon Sep 17 00:00:00 2001 From: Rahul Muttineni Date: Mon, 25 Apr 2022 10:44:03 -0400 Subject: [PATCH 144/219] Negotiate client version for docker compose --- compose.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compose.go b/compose.go index 70bb427853..e151cc3bb5 100644 --- a/compose.go +++ b/compose.go @@ -145,6 +145,8 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { return err } + cli.NegotiateAPIVersion(context.Background()) + for k := range dc.WaitStrategyMap { containerName := dc.containerNameFromServiceName(k.service, "_") composeV2ContainerName := dc.containerNameFromServiceName(k.service, "-") From ca898456e50c3bfd78cef6a82bf2a34f56cacd8f Mon Sep 17 00:00:00 2001 From: Johan Oskarsson Date: Thu, 28 Apr 2022 10:50:57 -0700 Subject: [PATCH 145/219] Return a Reader from the Exec function that allows the user to read the logs of the command execution --- container.go | 2 +- docker.go | 21 ++++++++++++++------- docker_test.go | 14 +++++++------- logconsumer_test.go | 6 +++--- wait/exec.go | 2 +- wait/exec_test.go | 8 ++++---- wait/exit_test.go | 4 ++-- wait/host_port.go | 2 +- wait/log_test.go | 4 ++-- wait/wait.go | 2 +- 10 files changed, 36 insertions(+), 29 deletions(-) diff --git a/container.go b/container.go index 16fed83e36..efdd89b05e 100644 --- a/container.go +++ b/container.go @@ -51,7 +51,7 @@ type Container interface { State(context.Context) (*types.ContainerState, error) // returns container's running state Networks(context.Context) ([]string, error) // get container networks NetworkAliases(context.Context) (map[string][]string, error) // get container network aliases for a network - Exec(ctx context.Context, cmd []string) (int, error) + Exec(ctx context.Context, cmd []string) (int, io.Reader, error) ContainerIP(context.Context) (string, error) // get container ip CopyToContainer(ctx context.Context, fileContent []byte, containerFilePath string, fileMode int64) error CopyFileToContainer(ctx context.Context, hostFilePath string, containerFilePath string, fileMode int64) error diff --git a/docker.go b/docker.go index d67708051b..97407e7d89 100644 --- a/docker.go +++ b/docker.go @@ -342,28 +342,35 @@ func (c *DockerContainer) NetworkAliases(ctx context.Context) (map[string][]stri return a, nil } -func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, error) { +func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, io.Reader, error) { cli := c.provider.client response, err := cli.ContainerExecCreate(ctx, c.ID, types.ExecConfig{ - Cmd: cmd, - Detach: false, + Cmd: cmd, + Detach: false, + AttachStdout: true, + AttachStderr: true, }) if err != nil { - return 0, err + return 0, nil, err + } + + hijack, err := cli.ContainerExecAttach(ctx, response.ID, types.ExecStartCheck{}) + if err != nil { + return 0, nil, err } err = cli.ContainerExecStart(ctx, response.ID, types.ExecStartCheck{ Detach: false, }) if err != nil { - return 0, err + return 0, nil, err } var exitCode int for { execResp, err := cli.ContainerExecInspect(ctx, response.ID) if err != nil { - return 0, err + return 0, nil, err } if !execResp.Running { @@ -374,7 +381,7 @@ func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, error) { time.Sleep(100 * time.Millisecond) } - return exitCode, nil + return exitCode, hijack.Reader, nil } type FileFromContainer struct { diff --git a/docker_test.go b/docker_test.go index eb6f5bfd3d..08dc6f3787 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1561,7 +1561,7 @@ func TestContainerWithTmpFs(t *testing.T) { path := "/testtmpfs/test.file" - c, err := container.Exec(ctx, []string{"ls", path}) + c, _, err := container.Exec(ctx, []string{"ls", path}) if err != nil { t.Fatal(err) } @@ -1569,7 +1569,7 @@ func TestContainerWithTmpFs(t *testing.T) { t.Fatalf("File %s should not have existed, expected return code 1, got %v", path, c) } - c, err = container.Exec(ctx, []string{"touch", path}) + c, _, err = container.Exec(ctx, []string{"touch", path}) if err != nil { t.Fatal(err) } @@ -1577,7 +1577,7 @@ func TestContainerWithTmpFs(t *testing.T) { t.Fatalf("File %s should have been created successfully, expected return code 0, got %v", path, c) } - c, err = container.Exec(ctx, []string{"ls", path}) + c, _, err = container.Exec(ctx, []string{"ls", path}) if err != nil { t.Fatal(err) } @@ -1740,7 +1740,7 @@ func TestDockerContainerCopyFileToContainer(t *testing.T) { copiedFileName := "hello_copy.sh" _ = nginxC.CopyFileToContainer(ctx, "./testresources/hello.sh", "/"+copiedFileName, 700) - c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) + c, _, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) if err != nil { t.Fatal(err) } @@ -1769,7 +1769,7 @@ func TestDockerContainerCopyToContainer(t *testing.T) { t.Fatal(err) } _ = nginxC.CopyToContainer(ctx, fileContent, "/"+copiedFileName, 700) - c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) + c, _, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) if err != nil { t.Fatal(err) } @@ -1797,7 +1797,7 @@ func TestDockerContainerCopyFileFromContainer(t *testing.T) { copiedFileName := "hello_copy.sh" _ = nginxC.CopyFileToContainer(ctx, "./testresources/hello.sh", "/"+copiedFileName, 700) - c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) + c, _, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) if err != nil { t.Fatal(err) } @@ -1832,7 +1832,7 @@ func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { copiedFileName := "hello_copy.sh" _ = nginxC.CopyFileToContainer(ctx, "./testresources/empty.sh", "/"+copiedFileName, 700) - c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) + c, _, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) if err != nil { t.Fatal(err) } diff --git a/logconsumer_test.go b/logconsumer_test.go index b9a06487f1..bfc837f084 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -246,7 +246,7 @@ func TestContainerLogWithErrClosed(t *testing.T) { existingLogs := len(consumer.Msgs) hitNginx := func() { - i, err := dind.Exec(ctx, []string{"wget", "--spider", "localhost:" + port.Port()}) + i, _, err := dind.Exec(ctx, []string{"wget", "--spider", "localhost:" + port.Port()}) if err != nil || i > 0 { t.Fatalf("Can't make request to nginx container from dind container") } @@ -264,11 +264,11 @@ func TestContainerLogWithErrClosed(t *testing.T) { "-j", "REJECT", "--reject-with", "tcp-reset", } // Simulate a transient closed connection to the docker daemon - i, err := dind.Exec(ctx, append([]string{"iptables", "-A"}, iptableArgs...)) + i, _, err := dind.Exec(ctx, append([]string{"iptables", "-A"}, iptableArgs...)) if err != nil || i > 0 { t.Fatalf("Failed to close connection to dind daemon") } - i, err = dind.Exec(ctx, append([]string{"iptables", "-D"}, iptableArgs...)) + i, _, err = dind.Exec(ctx, append([]string{"iptables", "-D"}, iptableArgs...)) if err != nil || i > 0 { t.Fatalf("Failed to re-open connection to dind daemon") } diff --git a/wait/exec.go b/wait/exec.go index 1255187808..c034b3c166 100644 --- a/wait/exec.go +++ b/wait/exec.go @@ -63,7 +63,7 @@ func (ws ExecStrategy) WaitUntilReady(ctx context.Context, target StrategyTarget case <-ctx.Done(): return ctx.Err() case <-time.After(ws.PollInterval): - exitCode, err := target.Exec(ctx, ws.cmd) + exitCode, _, err := target.Exec(ctx, ws.cmd) if err != nil { return err } diff --git a/wait/exec_test.go b/wait/exec_test.go index db45548274..c5a932f40f 100644 --- a/wait/exec_test.go +++ b/wait/exec_test.go @@ -52,18 +52,18 @@ func (st mockExecTarget) Logs(_ context.Context) (io.ReadCloser, error) { return nil, errors.New("not implemented") } -func (st mockExecTarget) Exec(ctx context.Context, _ []string) (int, error) { +func (st mockExecTarget) Exec(ctx context.Context, _ []string) (int, io.Reader, error) { time.Sleep(st.waitDuration) if err := ctx.Err(); err != nil { - return st.exitCode, err + return st.exitCode, nil, err } if !st.successAfter.IsZero() && time.Now().After(st.successAfter) { - return 0, st.failure + return 0, nil, st.failure } - return st.exitCode, st.failure + return st.exitCode, nil, st.failure } func (st mockExecTarget) State(_ context.Context) (*types.ContainerState, error) { diff --git a/wait/exit_test.go b/wait/exit_test.go index cbfa4a6913..63563d640d 100644 --- a/wait/exit_test.go +++ b/wait/exit_test.go @@ -27,8 +27,8 @@ func (st exitStrategyTarget) Logs(ctx context.Context) (io.ReadCloser, error) { return nil, nil } -func (st exitStrategyTarget) Exec(ctx context.Context, cmd []string) (int, error) { - return 0, nil +func (st exitStrategyTarget) Exec(ctx context.Context, cmd []string) (int, io.Reader, error) { + return 0, nil, nil } func (st exitStrategyTarget) State(ctx context.Context) (*types.ContainerState, error) { diff --git a/wait/host_port.go b/wait/host_port.go index d53218941e..4c3a25fa41 100644 --- a/wait/host_port.go +++ b/wait/host_port.go @@ -106,7 +106,7 @@ func (hp *HostPortStrategy) WaitUntilReady(ctx context.Context, target StrategyT if ctx.Err() != nil { return ctx.Err() } - exitCode, err := target.Exec(ctx, []string{"/bin/sh", "-c", command}) + exitCode, _, err := target.Exec(ctx, []string{"/bin/sh", "-c", command}) if err != nil { return fmt.Errorf("%w, host port waiting failed", err) } diff --git a/wait/log_test.go b/wait/log_test.go index 85be13effa..add532eaca 100644 --- a/wait/log_test.go +++ b/wait/log_test.go @@ -28,8 +28,8 @@ func (st noopStrategyTarget) Logs(ctx context.Context) (io.ReadCloser, error) { return st.ioReaderCloser, nil } -func (st noopStrategyTarget) Exec(ctx context.Context, cmd []string) (int, error) { - return 0, nil +func (st noopStrategyTarget) Exec(ctx context.Context, cmd []string) (int, io.Reader, error) { + return 0, nil, nil } func (st noopStrategyTarget) State(ctx context.Context) (*types.ContainerState, error) { return nil, nil diff --git a/wait/wait.go b/wait/wait.go index 5fcc284ccc..914483b9ca 100644 --- a/wait/wait.go +++ b/wait/wait.go @@ -17,7 +17,7 @@ type StrategyTarget interface { Host(context.Context) (string, error) MappedPort(context.Context, nat.Port) (nat.Port, error) Logs(context.Context) (io.ReadCloser, error) - Exec(ctx context.Context, cmd []string) (int, error) + Exec(ctx context.Context, cmd []string) (int, io.Reader, error) State(context.Context) (*types.ContainerState, error) } From 1193b9e84b313dfa4f8d7ea0e96067a1d5c4838a Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Tue, 3 May 2022 16:59:14 +0200 Subject: [PATCH 146/219] Add extra_hosts to the container request --- container.go | 1 + docker.go | 1 + 2 files changed, 2 insertions(+) diff --git a/container.go b/container.go index 16fed83e36..4701796f79 100644 --- a/container.go +++ b/container.go @@ -92,6 +92,7 @@ type ContainerRequest struct { WaitingFor wait.Strategy Name string // for specifying container name Hostname string + ExtraHosts []string Privileged bool // for starting privileged container Networks []string // for specifying network names NetworkAliases map[string][]string // for specifying network aliases diff --git a/docker.go b/docker.go index d67708051b..3713e47ef4 100644 --- a/docker.go +++ b/docker.go @@ -856,6 +856,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque mounts := mapToDockerMounts(req.Mounts) hostConfig := &container.HostConfig{ + ExtraHosts: req.ExtraHosts, PortBindings: exposedPortMap, Mounts: mounts, Tmpfs: req.Tmpfs, From e9cf05c0dae8e25e42e9eef3880e76975d82ca66 Mon Sep 17 00:00:00 2001 From: Alexey Vinogradov Date: Tue, 4 Jan 2022 21:23:27 +0700 Subject: [PATCH 147/219] feat: add IPAM configs to `NetworkRequest` --- docker.go | 1 + network.go | 2 ++ network_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/docker.go b/docker.go index 911265bff0..466b538d30 100644 --- a/docker.go +++ b/docker.go @@ -1048,6 +1048,7 @@ func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) EnableIPv6: req.EnableIPv6, Attachable: req.Attachable, Labels: req.Labels, + IPAM: req.IPAM, } sessionID := uuid.New() diff --git a/network.go b/network.go index ce99a017e1..362d32a327 100644 --- a/network.go +++ b/network.go @@ -2,6 +2,7 @@ package testcontainers import ( "context" + "github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types" ) @@ -26,6 +27,7 @@ type NetworkRequest struct { Name string Labels map[string]string Attachable bool + IPAM *network.IPAM SkipReaper bool // indicates whether we skip setting up a reaper for this ReaperImage string //alternative reaper registry diff --git a/network_test.go b/network_test.go index d2aaae971b..953736dab3 100644 --- a/network_test.go +++ b/network_test.go @@ -3,6 +3,8 @@ package testcontainers import ( "context" "fmt" + "github.com/docker/docker/api/types/network" + "github.com/stretchr/testify/assert" "github.com/testcontainers/testcontainers-go/wait" "testing" "time" @@ -34,6 +36,51 @@ func ExampleNetworkProvider_CreateNetwork() { defer nginxC.Terminate(ctx) nginxC.GetContainerID() } +func Test_NetworkWithIPAM(t *testing.T) { + ctx := context.Background() + networkName := "test-network-with-ipam" + ipamConfig := network.IPAM{ + Config: []network.IPAMConfig{ + { + Subnet: "10.1.1.0/24", + Gateway: "10.1.1.254/24", + IPRange: "10.1.1.1-253", + }, + }, + } + net, _ := GenericNetwork(ctx, GenericNetworkRequest{ + NetworkRequest: NetworkRequest{ + Name: networkName, + CheckDuplicate: true, + IPAM: &ipamConfig, + }, + }) + defer net.Remove(ctx) + + nginxC, _ := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: ContainerRequest{ + Image: "nginx", + ExposedPorts: []string{ + "80/tcp", + }, + Networks: []string{ + networkName, + }, + }, + }) + defer nginxC.Terminate(ctx) + nginxC.GetContainerID() + + provider, err := ProviderDocker.GetProvider() + if err != nil { + t.Fatal("Cannot get Provider") + } + foundNetwork, err := provider.GetNetwork(ctx, NetworkRequest{Name: networkName}) + if err != nil { + t.Fatal("Cannot get created network by name") + } + assert.Equal(t, ipamConfig, foundNetwork.IPAM) +} func Test_MultipleContainersInTheNewNetwork(t *testing.T) { ctx := context.Background() From c77d94fbd05df80d3adb1684f34b6c0c99c22a86 Mon Sep 17 00:00:00 2001 From: Alexey Vinogradov Date: Sun, 5 Jun 2022 21:22:08 +0700 Subject: [PATCH 148/219] fix: use proper IPAM settings for the IPAM test --- network_test.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/network_test.go b/network_test.go index 953736dab3..14b214076b 100644 --- a/network_test.go +++ b/network_test.go @@ -40,21 +40,27 @@ func Test_NetworkWithIPAM(t *testing.T) { ctx := context.Background() networkName := "test-network-with-ipam" ipamConfig := network.IPAM{ + Driver: "default", Config: []network.IPAMConfig{ { Subnet: "10.1.1.0/24", - Gateway: "10.1.1.254/24", - IPRange: "10.1.1.1-253", + Gateway: "10.1.1.254", + IPRange: "10.1.1.1/25", }, }, } - net, _ := GenericNetwork(ctx, GenericNetworkRequest{ + net, err := GenericNetwork(ctx, GenericNetworkRequest{ NetworkRequest: NetworkRequest{ Name: networkName, CheckDuplicate: true, IPAM: &ipamConfig, }, }) + + if err != nil { + t.Fatal("cannot create network: ", err) + } + defer net.Remove(ctx) nginxC, _ := GenericContainer(ctx, GenericContainerRequest{ From 4297a584ca512e87d4717803054f3e5a4af086ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Jabes?= Date: Tue, 7 Jun 2022 10:11:05 -0300 Subject: [PATCH 149/219] chore: bump containerd version to v1.5.13 --- go.mod | 4 ++-- go.sum | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 9038d1232c..be46fd3f7b 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.13 require ( github.com/cenkalti/backoff/v4 v4.1.2 - github.com/containerd/containerd v1.5.9 + github.com/containerd/containerd v1.5.13 github.com/docker/docker v20.10.11+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.4.0 @@ -20,7 +20,7 @@ require ( github.com/opencontainers/image-spec v1.0.2 github.com/stretchr/testify v1.7.0 golang.org/x/net v0.0.0-20211108170745-6635138e15ea // indirect - golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b gotest.tools/gotestsum v1.7.0 gotest.tools/v3 v3.0.3 diff --git a/go.sum b/go.sum index e6778279ab..34e527753e 100644 --- a/go.sum +++ b/go.sum @@ -56,6 +56,8 @@ github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= github.com/Microsoft/hcsshim v0.8.23 h1:47MSwtKGXet80aIn+7h4YI6fwPmwIghAnsx2aOUrG2M= github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= +github.com/Microsoft/hcsshim v0.8.24 h1:jP+GMeRXIR1sH1kG4lJr9ShmSjVrua5jmFZDtfYGkn4= +github.com/Microsoft/hcsshim v0.8.24/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -77,6 +79,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= @@ -120,6 +123,8 @@ github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4S github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ= github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= +github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= @@ -140,6 +145,8 @@ github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09Zvgq github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= github.com/containerd/containerd v1.5.9 h1:rs6Xg1gtIxaeyG+Smsb/0xaSDu1VgFhOCKBXxMxbsF4= github.com/containerd/containerd v1.5.9/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ= +github.com/containerd/containerd v1.5.13 h1:XqvKw9i4P7/mFrC3TSM7yV5cwFZ9avXe6M3YANKnzEE= +github.com/containerd/containerd v1.5.13/go.mod h1:3AlCrzKROjIuP3JALsY14n8YtntaUDBu7vek+rPN5Vc= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -153,6 +160,7 @@ github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU= github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= @@ -173,10 +181,12 @@ github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDG github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lWI= github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= @@ -235,6 +245,7 @@ github.com/docker/docker v20.10.11+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05 github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= @@ -293,6 +304,7 @@ github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6 github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +github.com/gogo/googleapis v1.4.0 h1:zgVt4UpGxcqVOw97aRGxT4svlcmdK35fynLNctY32zI= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= @@ -408,6 +420,7 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13 h1:eSvu8Tmq6j2psUJqJrLcWH6K3w5Dwc+qipbaA6eVEN4= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -443,6 +456,7 @@ github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= @@ -506,10 +520,12 @@ github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/ github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= @@ -622,6 +638,7 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= @@ -637,6 +654,7 @@ go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -683,6 +701,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -717,6 +736,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211108170745-6635138e15ea h1:FosBMXtOc8Tp9Hbo4ltl1WJSrTVewZU8MPnTPY2HdH8= golang.org/x/net v0.0.0-20211108170745-6635138e15ea/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -734,6 +754,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -795,13 +817,17 @@ golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -857,6 +883,7 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From ab345fac84b7b58dbbed3d33fce078956d97704b Mon Sep 17 00:00:00 2001 From: Josh Powers Date: Tue, 7 Jun 2022 13:52:18 -0600 Subject: [PATCH 150/219] docs: add telegraf to users of testcontainers-go --- docs/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.md b/docs/index.md index 182acd2408..51e2bcc980 100644 --- a/docs/index.md +++ b/docs/index.md @@ -20,6 +20,7 @@ examples as well. Check it out at ## Who is using Testcontainers Go? * [Elastic](https://www.elastic.co) - Testing of the APM Server, and E2E testing for Beats +* [Telegraf](https://www.influxdata.com/time-series-platform/telegraf/) - Integration testing the plugin-driven server agent for collecting & reporting metrics ## License From f71aac3d61548b88ece4307d7ba71a80e1f71035 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Jun 2022 11:09:49 +0000 Subject: [PATCH 151/219] chore(deps): bump gotest.tools/v3 from 3.0.3 to 3.2.0 Bumps [gotest.tools/v3](https://github.com/gotestyourself/gotest.tools) from 3.0.3 to 3.2.0. - [Release notes](https://github.com/gotestyourself/gotest.tools/releases) - [Commits](https://github.com/gotestyourself/gotest.tools/compare/v3.0.3...v3.2.0) --- updated-dependencies: - dependency-name: gotest.tools/v3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 25 ++++--------------------- 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index be46fd3f7b..7a03515df9 100644 --- a/go.mod +++ b/go.mod @@ -23,5 +23,5 @@ require ( golang.org/x/sys v0.0.0-20220412211240-33da011f77ad gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b gotest.tools/gotestsum v1.7.0 - gotest.tools/v3 v3.0.3 + gotest.tools/v3 v3.2.0 ) diff --git a/go.sum b/go.sum index 34e527753e..9c4c8443f7 100644 --- a/go.sum +++ b/go.sum @@ -54,8 +54,6 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3 github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.23 h1:47MSwtKGXet80aIn+7h4YI6fwPmwIghAnsx2aOUrG2M= -github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim v0.8.24 h1:jP+GMeRXIR1sH1kG4lJr9ShmSjVrua5jmFZDtfYGkn4= github.com/Microsoft/hcsshim v0.8.24/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= @@ -79,7 +77,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= @@ -121,7 +118,6 @@ github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1 github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ= github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= @@ -143,8 +139,6 @@ github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7 github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.9 h1:rs6Xg1gtIxaeyG+Smsb/0xaSDu1VgFhOCKBXxMxbsF4= -github.com/containerd/containerd v1.5.9/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ= github.com/containerd/containerd v1.5.13 h1:XqvKw9i4P7/mFrC3TSM7yV5cwFZ9avXe6M3YANKnzEE= github.com/containerd/containerd v1.5.13/go.mod h1:3AlCrzKROjIuP3JALsY14n8YtntaUDBu7vek+rPN5Vc= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -160,7 +154,6 @@ github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU= github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= @@ -181,12 +174,10 @@ github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDG github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lWI= github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= -github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= @@ -245,7 +236,6 @@ github.com/docker/docker v20.10.11+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05 github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= @@ -304,7 +294,6 @@ github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6 github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= -github.com/gogo/googleapis v1.4.0 h1:zgVt4UpGxcqVOw97aRGxT4svlcmdK35fynLNctY32zI= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= @@ -420,7 +409,6 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.13 h1:eSvu8Tmq6j2psUJqJrLcWH6K3w5Dwc+qipbaA6eVEN4= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -456,7 +444,6 @@ github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= -github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= @@ -520,12 +507,10 @@ github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/ github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= @@ -699,8 +684,8 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -752,7 +737,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -824,8 +808,6 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= @@ -881,8 +863,8 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -994,8 +976,9 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81 gotest.tools/gotestsum v1.7.0 h1:RwpqwwFKBAa2h+F6pMEGpE707Edld0etUD3GhqqhDNc= gotest.tools/gotestsum v1.7.0/go.mod h1:V1m4Jw3eBerhI/A6qCxUE07RnCg7ACkKj9BYcAm09V8= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I= +gotest.tools/v3 v3.2.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 6133f5b39183d98ef0b722913e7d3db766fde7a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Jun 2022 12:06:40 +0000 Subject: [PATCH 152/219] chore(deps): bump github.com/magiconair/properties from 1.8.5 to 1.8.6 Bumps [github.com/magiconair/properties](https://github.com/magiconair/properties) from 1.8.5 to 1.8.6. - [Release notes](https://github.com/magiconair/properties/releases) - [Changelog](https://github.com/magiconair/properties/blob/main/CHANGELOG.md) - [Commits](https://github.com/magiconair/properties/compare/v1.8.5...v1.8.6) --- updated-dependencies: - dependency-name: github.com/magiconair/properties dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 29 ++++++----------------------- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index be46fd3f7b..3dd836f3c0 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/golang/protobuf v1.5.2 // indirect github.com/google/uuid v1.3.0 - github.com/magiconair/properties v1.8.5 + github.com/magiconair/properties v1.8.6 github.com/moby/sys/mount v0.2.0 // indirect github.com/moby/sys/mountinfo v0.5.0 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 @@ -23,5 +23,5 @@ require ( golang.org/x/sys v0.0.0-20220412211240-33da011f77ad gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b gotest.tools/gotestsum v1.7.0 - gotest.tools/v3 v3.0.3 + gotest.tools/v3 v3.2.0 ) diff --git a/go.sum b/go.sum index 34e527753e..b8de5a6b43 100644 --- a/go.sum +++ b/go.sum @@ -54,8 +54,6 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3 github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.23 h1:47MSwtKGXet80aIn+7h4YI6fwPmwIghAnsx2aOUrG2M= -github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim v0.8.24 h1:jP+GMeRXIR1sH1kG4lJr9ShmSjVrua5jmFZDtfYGkn4= github.com/Microsoft/hcsshim v0.8.24/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= @@ -79,7 +77,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= @@ -121,7 +118,6 @@ github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1 github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ= github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= @@ -143,8 +139,6 @@ github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7 github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.9 h1:rs6Xg1gtIxaeyG+Smsb/0xaSDu1VgFhOCKBXxMxbsF4= -github.com/containerd/containerd v1.5.9/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ= github.com/containerd/containerd v1.5.13 h1:XqvKw9i4P7/mFrC3TSM7yV5cwFZ9avXe6M3YANKnzEE= github.com/containerd/containerd v1.5.13/go.mod h1:3AlCrzKROjIuP3JALsY14n8YtntaUDBu7vek+rPN5Vc= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -160,7 +154,6 @@ github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU= github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= @@ -181,12 +174,10 @@ github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDG github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lWI= github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= -github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= @@ -245,7 +236,6 @@ github.com/docker/docker v20.10.11+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05 github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= @@ -304,7 +294,6 @@ github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6 github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= -github.com/gogo/googleapis v1.4.0 h1:zgVt4UpGxcqVOw97aRGxT4svlcmdK35fynLNctY32zI= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= @@ -420,7 +409,6 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.13 h1:eSvu8Tmq6j2psUJqJrLcWH6K3w5Dwc+qipbaA6eVEN4= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -435,8 +423,8 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= @@ -456,7 +444,6 @@ github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= -github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= @@ -520,12 +507,10 @@ github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/ github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= @@ -699,8 +684,8 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -752,7 +737,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -824,8 +808,6 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= @@ -881,8 +863,8 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -994,8 +976,9 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81 gotest.tools/gotestsum v1.7.0 h1:RwpqwwFKBAa2h+F6pMEGpE707Edld0etUD3GhqqhDNc= gotest.tools/gotestsum v1.7.0/go.mod h1:V1m4Jw3eBerhI/A6qCxUE07RnCg7ACkKj9BYcAm09V8= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I= +gotest.tools/v3 v3.2.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From b2f510a9fde1435cf5f4134958791c68ecb98657 Mon Sep 17 00:00:00 2001 From: "v.funtikov" Date: Mon, 13 Jun 2022 14:44:22 +0300 Subject: [PATCH 153/219] feature: custom ForSQL query --- wait/sql.go | 15 ++++++++++++--- wait/wait.go | 4 ++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/wait/sql.go b/wait/sql.go index 6fd8d9965d..0653850223 100644 --- a/wait/sql.go +++ b/wait/sql.go @@ -17,6 +17,7 @@ func ForSQL(port nat.Port, driver string, url func(nat.Port) string) *waitForSql Driver: driver, startupTimeout: defaultStartupTimeout(), PollInterval: defaultPollInterval(), + query: defaultQuery(), } } @@ -26,6 +27,7 @@ type waitForSql struct { Port nat.Port startupTimeout time.Duration PollInterval time.Duration + query string } //Timeout sets the maximum waiting time for the strategy after which it'll give up and return an error @@ -40,8 +42,15 @@ func (w *waitForSql) WithPollInterval(pollInterval time.Duration) *waitForSql { return w } -//WaitUntilReady repeatedly tries to run "SELECT 1" query on the given port using sql and driver. -// If the it doesn't succeed until the timeout value which defaults to 60 seconds, it will return an error +//WithQuery can be used to override the default query used in the strategy. +func (w *waitForSql) WithQuery(query string) *waitForSql { + w.query = query + return w +} + +//WaitUntilReady repeatedly tries to run "SELECT 1" or user defined query on the given port using sql and driver. +// +// If it doesn't succeed until the timeout value which defaults to 60 seconds, it will return an error. func (w *waitForSql) WaitUntilReady(ctx context.Context, target StrategyTarget) (err error) { ctx, cancel := context.WithTimeout(ctx, w.startupTimeout) defer cancel() @@ -72,7 +81,7 @@ func (w *waitForSql) WaitUntilReady(ctx context.Context, target StrategyTarget) return ctx.Err() case <-ticker.C: - if _, err := db.ExecContext(ctx, "SELECT 1"); err != nil { + if _, err := db.ExecContext(ctx, w.query); err != nil { continue } return nil diff --git a/wait/wait.go b/wait/wait.go index 914483b9ca..1f448ad459 100644 --- a/wait/wait.go +++ b/wait/wait.go @@ -28,3 +28,7 @@ func defaultStartupTimeout() time.Duration { func defaultPollInterval() time.Duration { return 100 * time.Millisecond } + +func defaultQuery() string { + return "SELECT 1" +} From 6b130f8dbde90f2109643dadf0a795f64ad5527c Mon Sep 17 00:00:00 2001 From: Zoran Regvart Date: Mon, 13 Jun 2022 14:38:37 +0200 Subject: [PATCH 154/219] feat: support binds in addition to mounts This is needed for providing additional options, such as SELinux label. --- container.go | 1 + docker.go | 1 + 2 files changed, 2 insertions(+) diff --git a/container.go b/container.go index 22d2d0609c..605d79f976 100644 --- a/container.go +++ b/container.go @@ -104,6 +104,7 @@ type ContainerRequest struct { AutoRemove bool // if set to true, the container will be removed from the host when stopped AlwaysPullImage bool // Always pull image ImagePlatform string // ImagePlatform describes the platform which the image runs on. + Binds []string } type ( diff --git a/docker.go b/docker.go index 466b538d30..5ae5cb4a62 100644 --- a/docker.go +++ b/docker.go @@ -865,6 +865,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque hostConfig := &container.HostConfig{ ExtraHosts: req.ExtraHosts, PortBindings: exposedPortMap, + Binds: req.Binds, Mounts: mounts, Tmpfs: req.Tmpfs, AutoRemove: req.AutoRemove, From acd657e4816426e59e19c6a53a5b192683df217a Mon Sep 17 00:00:00 2001 From: "v.funtikov" Date: Mon, 13 Jun 2022 15:45:42 +0300 Subject: [PATCH 155/219] tests added --- container_test.go | 79 +++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 ++ wait/sql_test.go | 30 ++++++++++++++++++ 4 files changed, 112 insertions(+) create mode 100644 wait/sql_test.go diff --git a/container_test.go b/container_test.go index f0a3239f40..39b2a25008 100644 --- a/container_test.go +++ b/container_test.go @@ -12,9 +12,12 @@ import ( "testing" "time" + "github.com/docker/go-connections/nat" "github.com/stretchr/testify/assert" "github.com/testcontainers/testcontainers-go/wait" + + _ "github.com/lib/pq" ) func Test_ContainerValidation(t *testing.T) { @@ -414,3 +417,79 @@ func TestVolumeMount(t *testing.T) { }) } } + +func TestContainerWithWaitForSQL(t *testing.T) { + const dbname = "postgres" + + ctx := context.Background() + + var env = map[string]string{ + "POSTGRES_PASSWORD": "password", + "POSTGRES_USER": "postgres", + "POSTGRES_DB": dbname, + } + var port = "5432/tcp" + dbURL := func(port nat.Port) string { + return fmt.Sprintf("postgres://postgres:password@localhost:%s/%s?sslmode=disable", port.Port(), dbname) + } + + t.Run("default query", func(t *testing.T) { + req := ContainerRequest{ + Image: "postgres:14.1-alpine", + ExposedPorts: []string{port}, + Cmd: []string{"postgres", "-c", "fsync=off"}, + Env: env, + WaitingFor: wait.ForSQL(nat.Port(port), "postgres", dbURL). + Timeout(time.Second * 5), + } + container, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + + defer container.Terminate(ctx) + }) + t.Run("custom query", func(t *testing.T) { + req := ContainerRequest{ + Image: "postgres:14.1-alpine", + ExposedPorts: []string{port}, + Cmd: []string{"postgres", "-c", "fsync=off"}, + Env: env, + WaitingFor: wait.ForSQL(nat.Port(port), "postgres", dbURL). + Timeout(time.Second * 5). + WithQuery("SELECT 10"), + } + container, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + + defer container.Terminate(ctx) + }) + t.Run("custom bad query", func(t *testing.T) { + req := ContainerRequest{ + Image: "postgres:14.1-alpine", + ExposedPorts: []string{port}, + Cmd: []string{"postgres", "-c", "fsync=off"}, + Env: env, + WaitingFor: wait.ForSQL(nat.Port(port), "postgres", dbURL). + Timeout(time.Second * 5). + WithQuery("SELECT 'a' from b"), + } + container, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err == nil { + t.Fatal("expected error, but got a nil") + } + + defer container.Terminate(ctx) + }) +} diff --git a/go.mod b/go.mod index 3dd836f3c0..c6bab43005 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/golang/protobuf v1.5.2 // indirect github.com/google/uuid v1.3.0 + github.com/lib/pq v1.10.6 github.com/magiconair/properties v1.8.6 github.com/moby/sys/mount v0.2.0 // indirect github.com/moby/sys/mountinfo v0.5.0 // indirect diff --git a/go.sum b/go.sum index b8de5a6b43..45a9cbb177 100644 --- a/go.sum +++ b/go.sum @@ -422,6 +422,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= +github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= diff --git a/wait/sql_test.go b/wait/sql_test.go new file mode 100644 index 0000000000..8280647e5b --- /dev/null +++ b/wait/sql_test.go @@ -0,0 +1,30 @@ +package wait + +import ( + "testing" + + "github.com/docker/go-connections/nat" +) + +func Test_waitForSql_WithQuery(t *testing.T) { + t.Run("default query", func(t *testing.T) { + w := ForSQL(nat.Port("5432/tcp"), "postgres", func(port nat.Port) string { + return "fake-url" + }) + + if got := w.query; got != defaultQuery() { + t.Fatalf("expected %s, got %s", defaultQuery(), got) + } + }) + t.Run("custom query", func(t *testing.T) { + const q = "SELECT 100;" + + w := ForSQL(nat.Port("5432/tcp"), "postgres", func(port nat.Port) string { + return "fake-url" + }).WithQuery(q) + + if got := w.query; got != q { + t.Fatalf("expected %s, got %s", defaultQuery(), got) + } + }) +} From b5bd0264855e4a740e3e05c8aba85b760e605f29 Mon Sep 17 00:00:00 2001 From: "v.funtikov" Date: Mon, 13 Jun 2022 15:50:49 +0300 Subject: [PATCH 156/219] use const for default query - Test failure message fixed. --- wait/sql.go | 4 +++- wait/sql_test.go | 10 +++++----- wait/wait.go | 4 ---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/wait/sql.go b/wait/sql.go index 0653850223..551464c7c5 100644 --- a/wait/sql.go +++ b/wait/sql.go @@ -9,6 +9,8 @@ import ( "github.com/docker/go-connections/nat" ) +const defaultForSqlQuery = "SELECT 1" + //ForSQL constructs a new waitForSql strategy for the given driver func ForSQL(port nat.Port, driver string, url func(nat.Port) string) *waitForSql { return &waitForSql{ @@ -17,7 +19,7 @@ func ForSQL(port nat.Port, driver string, url func(nat.Port) string) *waitForSql Driver: driver, startupTimeout: defaultStartupTimeout(), PollInterval: defaultPollInterval(), - query: defaultQuery(), + query: defaultForSqlQuery, } } diff --git a/wait/sql_test.go b/wait/sql_test.go index 8280647e5b..f9ec88525f 100644 --- a/wait/sql_test.go +++ b/wait/sql_test.go @@ -8,23 +8,23 @@ import ( func Test_waitForSql_WithQuery(t *testing.T) { t.Run("default query", func(t *testing.T) { - w := ForSQL(nat.Port("5432/tcp"), "postgres", func(port nat.Port) string { + w := ForSQL("5432/tcp", "postgres", func(port nat.Port) string { return "fake-url" }) - if got := w.query; got != defaultQuery() { - t.Fatalf("expected %s, got %s", defaultQuery(), got) + if got := w.query; got != defaultForSqlQuery { + t.Fatalf("expected %s, got %s", defaultForSqlQuery, got) } }) t.Run("custom query", func(t *testing.T) { const q = "SELECT 100;" - w := ForSQL(nat.Port("5432/tcp"), "postgres", func(port nat.Port) string { + w := ForSQL("5432/tcp", "postgres", func(port nat.Port) string { return "fake-url" }).WithQuery(q) if got := w.query; got != q { - t.Fatalf("expected %s, got %s", defaultQuery(), got) + t.Fatalf("expected %s, got %s", q, got) } }) } diff --git a/wait/wait.go b/wait/wait.go index 1f448ad459..914483b9ca 100644 --- a/wait/wait.go +++ b/wait/wait.go @@ -28,7 +28,3 @@ func defaultStartupTimeout() time.Duration { func defaultPollInterval() time.Duration { return 100 * time.Millisecond } - -func defaultQuery() string { - return "SELECT 1" -} From c8254c0b8f3f673ff47939b47500f022598fe521 Mon Sep 17 00:00:00 2001 From: "v.funtikov" Date: Mon, 13 Jun 2022 17:50:17 +0300 Subject: [PATCH 157/219] fix: strip stream headers from logs --- docker.go | 51 ++++++++++++++++++++++++++++++++++++++++++++- logconsumer_test.go | 31 ++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/docker.go b/docker.go index 466b538d30..778cec1f37 100644 --- a/docker.go +++ b/docker.go @@ -2,6 +2,7 @@ package testcontainers import ( "archive/tar" + "bufio" "bytes" "context" "encoding/binary" @@ -259,11 +260,59 @@ func (c *DockerContainer) inspectContainer(ctx context.Context) (*types.Containe // Logs will fetch both STDOUT and STDERR from the current container. Returns a // ReadCloser and leaves it up to the caller to extract what it wants. func (c *DockerContainer) Logs(ctx context.Context) (io.ReadCloser, error) { + + const streamHeaderSize = 8 + options := types.ContainerLogsOptions{ ShowStdout: true, ShowStderr: true, } - return c.provider.client.ContainerLogs(ctx, c.ID, options) + + rc, err := c.provider.client.ContainerLogs(ctx, c.ID, options) + if err != nil { + return nil, err + } + + pr, pw := io.Pipe() + r := bufio.NewReader(rc) + + go func() { + var ( + isPrefix = true + lineStarted = true + line []byte + ) + for err == nil { + line, isPrefix, err = r.ReadLine() + + if lineStarted && len(line) >= streamHeaderSize { + line = line[streamHeaderSize:] // trim stream header + lineStarted = false + } + if !isPrefix { + lineStarted = true + } + + _, errW := pw.Write(line) + if errW != nil { + return + } + + if !isPrefix { + _, errW := pw.Write([]byte("\n")) + if errW != nil { + return + } + } + + if err != nil { + _ = pw.CloseWithError(err) + return + } + } + }() + + return pr, nil } // FollowOutput adds a LogConsumer to be sent logs from the container's diff --git a/logconsumer_test.go b/logconsumer_test.go index bfc837f084..34c828add2 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -3,7 +3,9 @@ package testcontainers import ( "context" "fmt" + "io/ioutil" "net/http" + "strings" "testing" "time" @@ -141,6 +143,7 @@ func Test_ShouldRecognizeLogTypes(t *testing.T) { if err != nil { t.Fatal(err) } + defer func() { _ = c.Terminate(ctx) }() ep, err := c.Endpoint(ctx, "http") if err != nil { @@ -181,7 +184,6 @@ func Test_ShouldRecognizeLogTypes(t *testing.T) { StdoutLog: "echo this-is-stdout\n", StderrLog: "echo this-is-stderr\n", }, g.LogTypes) - _ = c.Terminate(ctx) } func TestContainerLogWithErrClosed(t *testing.T) { @@ -284,3 +286,30 @@ func TestContainerLogWithErrClosed(t *testing.T) { ) } } + +func TestContainerLogsShouldBeWithoutStreamHeader(t *testing.T) { + ctx := context.Background() + req := ContainerRequest{ + Image: "alpine:latest", + Cmd: []string{"sh", "-c", "id -u"}, + WaitingFor: wait.ForExit(), + } + container, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + defer container.Terminate(ctx) + r, err := container.Logs(ctx) + if err != nil { + t.Fatal(err) + } + defer r.Close() + b, err := ioutil.ReadAll(r) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, "0", strings.TrimSpace(string(b))) +} From 25da222bfcf6f818cc5bf8189adacae06f00464c Mon Sep 17 00:00:00 2001 From: "v.funtikov" Date: Mon, 13 Jun 2022 18:49:08 +0300 Subject: [PATCH 158/219] fix: temp fix of flaky test --- logconsumer_test.go | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/logconsumer_test.go b/logconsumer_test.go index bfc837f084..76cd616fe8 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -2,6 +2,7 @@ package testcontainers import ( "context" + "errors" "fmt" "net/http" "testing" @@ -201,13 +202,29 @@ func TestContainerLogWithErrClosed(t *testing.T) { }, }) if err != nil { - t.Fatal(err) + t.Fatal("create generic container:", err) } defer dind.Terminate(ctx) - remoteDocker, err := dind.Endpoint(ctx, "2375/tcp") + var remoteDocker string + + ctxEndpoint, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + // todo: remove this temporary fix (test is flaky). + for { + remoteDocker, err = dind.Endpoint(ctxEndpoint, "2375/tcp") + if err == nil { + break + } + if errors.Is(err, context.DeadlineExceeded) { + break + } + time.Sleep(100 * time.Microsecond) + t.Log("retrying get endpoint") + } if err != nil { - t.Fatal(err) + t.Fatal("get endpoint:", err) } client, err := client.NewClientWithOpts(client.WithHost(remoteDocker)) From cfb9bfc2adc26f47a4ead0cf1defdc531e680227 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Mon, 13 Jun 2022 22:10:54 +0600 Subject: [PATCH 159/219] implement parallel container runner --- generic.go | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/generic.go b/generic.go index fbfd8947c2..d5712deb97 100644 --- a/generic.go +++ b/generic.go @@ -3,8 +3,27 @@ package testcontainers import ( "context" "fmt" + "sync" ) +const ( + MaxGenericWorkers = 8 +) + +type GenericParallelErrors struct { + Errors []GenericContainerRequestError +} + +func (gpe GenericParallelErrors) Error() string { + return fmt.Sprintf("%v", gpe.Errors) +} + +// GenericContainerRequestError represents error from parallel request +type GenericContainerRequestError struct { + Request GenericContainerRequest + Error error +} + // GenericContainerRequest represents parameters to a generic container type GenericContainerRequest struct { ContainerRequest // embedded request for provider @@ -33,6 +52,92 @@ func GenericNetwork(ctx context.Context, req GenericNetworkRequest) (Network, er return network, nil } +func genericContainerRunner( + ctx context.Context, + requests <-chan GenericContainerRequest, + errors chan<- GenericContainerRequestError, + containers chan<- Container, + wg *sync.WaitGroup) { + for req := range requests { + c, err := GenericContainer(ctx, req) + if err != nil { + errors <- GenericContainerRequestError{ + Request: req, + Error: err, + } + continue + } + containers <- c + } + wg.Done() +} + +// GenericParallelContainers creates a generic containers with parameters in parallel mode +func GenericParallelContainers(ctx context.Context, reqs []GenericContainerRequest) ([]Container, error) { + tasksChanSize := MaxGenericWorkers + if tasksChanSize > len(reqs) { + tasksChanSize = len(reqs) + } + + tasksChan := make(chan GenericContainerRequest, tasksChanSize) + errsChan := make(chan GenericContainerRequestError) + resChan := make(chan Container) + waitRes := make(chan struct{}) + + containers := make([]Container, 0) + errors := make([]GenericContainerRequestError, 0) + + wg := sync.WaitGroup{} + wg.Add(tasksChanSize) + + // run workers + for i := 0; i < tasksChanSize; i++ { + go genericContainerRunner(ctx, tasksChan, errsChan, resChan, &wg) + } + + go func() { + for { + select { + case c, ok := <-resChan: + if !ok { + resChan = nil + } else { + containers = append(containers, c) + } + case e, ok := <-errsChan: + if !ok { + errsChan = nil + } else { + errors = append(errors, e) + } + } + + if resChan == nil && errsChan == nil { + waitRes <- struct{}{} + break + } + } + + }() + + for _, req := range reqs { + tasksChan <- req + } + close(tasksChan) + wg.Wait() + close(resChan) + close(errsChan) + + <-waitRes + + if len(errors) == 0 { + return containers, GenericParallelErrors{Errors: errors} + } + + return containers, nil + +} + // GenericContainer creates a generic container with parameters func GenericContainer(ctx context.Context, req GenericContainerRequest) (Container, error) { logging := req.Logger From e9cc2ac8bc8b0566cdf48a71196ecb3b0ac7da89 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Mon, 13 Jun 2022 22:11:31 +0600 Subject: [PATCH 160/219] add tests for container parallell runner --- generic_test.go | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 generic_test.go diff --git a/generic_test.go b/generic_test.go new file mode 100644 index 0000000000..a070aff50c --- /dev/null +++ b/generic_test.go @@ -0,0 +1,91 @@ +package testcontainers + +import ( + "context" + "testing" +) + +func TestGenericParallelContainers(t *testing.T) { + tests := []struct { + name string + reqs []GenericContainerRequest + resLen int + expErrors int + }{ + { + name: "running two containers (success)", + reqs: []GenericContainerRequest{ + { + ContainerRequest: ContainerRequest{ + + Image: "nginx", + ExposedPorts: []string{ + "10080/tcp", + }, + }, + Started: true, + }, + { + ContainerRequest: ContainerRequest{ + + Image: "nginx", + ExposedPorts: []string{ + "10081/tcp", + }, + }, + Started: true, + }, + }, + resLen: 2, + }, + { + name: "running two containers (one error)", + reqs: []GenericContainerRequest{ + { + ContainerRequest: ContainerRequest{ + + Image: "nginx", + ExposedPorts: []string{ + "10080/tcp", + }, + }, + Started: true, + }, + { + ContainerRequest: ContainerRequest{ + + Image: "bad bad bad", + ExposedPorts: []string{ + "10081/tcp", + }, + }, + Started: true, + }, + }, + resLen: 1, + expErrors: 1, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + res, err := GenericParallelContainers(context.Background(), tc.reqs) + + if err != nil && tc.expErrors > 0 { + e, _ := err.(GenericParallelErrors) + + if len(e.Errors) != tc.expErrors { + t.Fatalf("expected erorrs: %d, got: %d\n", tc.expErrors, len(e.Errors)) + } + } + + for _, c := range res { + defer c.Terminate(context.Background()) + } + + if len(res) != tc.resLen { + t.Fatalf("expected containers: %d, got: %d\n", tc.resLen, len(res)) + } + }) + } +} From a4edf7244b61b3e422dee033bbdc6df8c00dbcce Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Mon, 13 Jun 2022 22:38:40 +0600 Subject: [PATCH 161/219] move parallel implementation into single file --- generic.go | 105 -------------------------- parallel.go | 111 ++++++++++++++++++++++++++++ generic_test.go => parallel_test.go | 0 3 files changed, 111 insertions(+), 105 deletions(-) create mode 100644 parallel.go rename generic_test.go => parallel_test.go (100%) diff --git a/generic.go b/generic.go index d5712deb97..fbfd8947c2 100644 --- a/generic.go +++ b/generic.go @@ -3,27 +3,8 @@ package testcontainers import ( "context" "fmt" - "sync" ) -const ( - MaxGenericWorkers = 8 -) - -type GenericParallelErrors struct { - Errors []GenericContainerRequestError -} - -func (gpe GenericParallelErrors) Error() string { - return fmt.Sprintf("%v", gpe.Errors) -} - -// GenericContainerRequestError represents error from parallel request -type GenericContainerRequestError struct { - Request GenericContainerRequest - Error error -} - // GenericContainerRequest represents parameters to a generic container type GenericContainerRequest struct { ContainerRequest // embedded request for provider @@ -52,92 +33,6 @@ func GenericNetwork(ctx context.Context, req GenericNetworkRequest) (Network, er return network, nil } -func genericContainerRunner( - ctx context.Context, - requests <-chan GenericContainerRequest, - errors chan<- GenericContainerRequestError, - containers chan<- Container, - wg *sync.WaitGroup) { - for req := range requests { - c, err := GenericContainer(ctx, req) - if err != nil { - errors <- GenericContainerRequestError{ - Request: req, - Error: err, - } - continue - } - containers <- c - } - wg.Done() -} - -// GenericParallelContainers creates a generic containers with parameters in parallel mode -func GenericParallelContainers(ctx context.Context, reqs []GenericContainerRequest) ([]Container, error) { - tasksChanSize := MaxGenericWorkers - if tasksChanSize > len(reqs) { - tasksChanSize = len(reqs) - } - - tasksChan := make(chan GenericContainerRequest, tasksChanSize) - errsChan := make(chan GenericContainerRequestError) - resChan := make(chan Container) - waitRes := make(chan struct{}) - - containers := make([]Container, 0) - errors := make([]GenericContainerRequestError, 0) - - wg := sync.WaitGroup{} - wg.Add(tasksChanSize) - - // run workers - for i := 0; i < tasksChanSize; i++ { - go genericContainerRunner(ctx, tasksChan, errsChan, resChan, &wg) - } - - go func() { - for { - select { - case c, ok := <-resChan: - if !ok { - resChan = nil - } else { - containers = append(containers, c) - } - case e, ok := <-errsChan: - if !ok { - errsChan = nil - } else { - errors = append(errors, e) - } - } - - if resChan == nil && errsChan == nil { - waitRes <- struct{}{} - break - } - } - - }() - - for _, req := range reqs { - tasksChan <- req - } - close(tasksChan) - wg.Wait() - close(resChan) - close(errsChan) - - <-waitRes - - if len(errors) == 0 { - return containers, GenericParallelErrors{Errors: errors} - } - - return containers, nil - -} - // GenericContainer creates a generic container with parameters func GenericContainer(ctx context.Context, req GenericContainerRequest) (Container, error) { logging := req.Logger diff --git a/parallel.go b/parallel.go new file mode 100644 index 0000000000..5aa7dc0a7c --- /dev/null +++ b/parallel.go @@ -0,0 +1,111 @@ +package testcontainers + +import ( + "context" + "fmt" + "sync" +) + +const ( + MaxGenericWorkers = 8 +) + +type GenericParallelErrors struct { + Errors []GenericContainerRequestError +} + +func (gpe GenericParallelErrors) Error() string { + return fmt.Sprintf("%v", gpe.Errors) +} + +// GenericContainerRequestError represents error from parallel request +type GenericContainerRequestError struct { + Request GenericContainerRequest + Error error +} + +func genericContainerRunner( + ctx context.Context, + requests <-chan GenericContainerRequest, + errors chan<- GenericContainerRequestError, + containers chan<- Container, + wg *sync.WaitGroup) { + for req := range requests { + c, err := GenericContainer(ctx, req) + if err != nil { + errors <- GenericContainerRequestError{ + Request: req, + Error: err, + } + continue + } + containers <- c + } + wg.Done() +} + +// GenericParallelContainers creates a generic containers with parameters in parallel mode +func GenericParallelContainers(ctx context.Context, reqs []GenericContainerRequest) ([]Container, error) { + tasksChanSize := MaxGenericWorkers + if tasksChanSize > len(reqs) { + tasksChanSize = len(reqs) + } + + tasksChan := make(chan GenericContainerRequest, tasksChanSize) + errsChan := make(chan GenericContainerRequestError) + resChan := make(chan Container) + waitRes := make(chan struct{}) + + containers := make([]Container, 0) + errors := make([]GenericContainerRequestError, 0) + + wg := sync.WaitGroup{} + wg.Add(tasksChanSize) + + // run workers + for i := 0; i < tasksChanSize; i++ { + go genericContainerRunner(ctx, tasksChan, errsChan, resChan, &wg) + } + + go func() { + for { + select { + case c, ok := <-resChan: + if !ok { + resChan = nil + } else { + containers = append(containers, c) + } + case e, ok := <-errsChan: + if !ok { + errsChan = nil + } else { + errors = append(errors, e) + } + } + + if resChan == nil && errsChan == nil { + waitRes <- struct{}{} + break + } + } + + }() + + for _, req := range reqs { + tasksChan <- req + } + close(tasksChan) + wg.Wait() + close(resChan) + close(errsChan) + + <-waitRes + + if len(errors) == 0 { + return containers, GenericParallelErrors{Errors: errors} + } + + return containers, nil + +} diff --git a/generic_test.go b/parallel_test.go similarity index 100% rename from generic_test.go rename to parallel_test.go From 88d38fc798410fc49eee905711d17fb9e8b071d9 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Tue, 14 Jun 2022 00:13:48 +0600 Subject: [PATCH 162/219] check that environment is clean --- .github/workflows/ci.yml | 10 ++++++++++ scripts/check_environment.sh | 10 ++++++++++ 2 files changed, 20 insertions(+) create mode 100644 scripts/check_environment.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a64969ea6..e625376c83 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,3 +61,13 @@ jobs: with: file: ./cover.txt name: testcontainers-go-${{ matrix.go-version }} + + check-environment: + runs-on: [ ubuntu-latest ] + steps: + + - name: Check out code + uses: actions/checkout@v2 + - name: Run checker + run: | + ./scripts/check_environment.sh diff --git a/scripts/check_environment.sh b/scripts/check_environment.sh new file mode 100644 index 0000000000..86d598f870 --- /dev/null +++ b/scripts/check_environment.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + + +containers=$(docker ps --format "{{.ID}}" | wc -l) + +if [ "$containers" -eq "0" ]; then + exit 0 +fi +echo "environment is not clean" +exit -1; \ No newline at end of file From bfffc23899e52f1dc051adbd8f33dd45f58d268b Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Tue, 14 Jun 2022 00:35:24 +0600 Subject: [PATCH 163/219] fix return code after shellcheck warnings --- scripts/check_environment.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 scripts/check_environment.sh diff --git a/scripts/check_environment.sh b/scripts/check_environment.sh old mode 100644 new mode 100755 index 86d598f870..0bc5f6c1a6 --- a/scripts/check_environment.sh +++ b/scripts/check_environment.sh @@ -7,4 +7,4 @@ if [ "$containers" -eq "0" ]; then exit 0 fi echo "environment is not clean" -exit -1; \ No newline at end of file +exit 255; \ No newline at end of file From 2011543d448709a8f4221002a16709a03741f803 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Tue, 14 Jun 2022 10:26:50 +0600 Subject: [PATCH 164/219] update docs. add instruction for parallel running --- docs/features/creating_container.md | 45 +++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/docs/features/creating_container.md b/docs/features/creating_container.md index 3dc106ae40..c86ccc10fb 100644 --- a/docs/features/creating_container.md +++ b/docs/features/creating_container.md @@ -81,3 +81,48 @@ func TestIntegrationNginxLatestReturn(t *testing.T) { } } ``` + +# Parallel running + +`testcontainers.GenericParallelContainers` - defines the containers that should be run in parallel mode. + +```go +ctx := context.Background() + +requests := []GenericContainerRequest{ + { + ContainerRequest: ContainerRequest{ + + Image: "nginx", + ExposedPorts: []string{ + "10080/tcp", + }, + }, + Started: true, + }, + { + ContainerRequest: ContainerRequest{ + + Image: "nginx", + ExposedPorts: []string{ + "10081/tcp", + }, + }, + Started: true, + }, +} + +res, err := GenericParallelContainers(ctx, requests) + +if err != nil { + e, ok := err.(GenericParallelErrors) + if !ok { + log.Fatalf("unknown error: %v", err) + } + ... +} + +for _, c := range res { + defer c.Terminate(ctx) +} +``` \ No newline at end of file From c60a43a071ffcada7412b740f42d1a6e23b12809 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Tue, 14 Jun 2022 16:18:36 +0600 Subject: [PATCH 165/219] fix: check environment after tests --- .github/workflows/ci.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e625376c83..2b13f006bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,12 +62,7 @@ jobs: file: ./cover.txt name: testcontainers-go-${{ matrix.go-version }} - check-environment: - runs-on: [ ubuntu-latest ] - steps: - - - name: Check out code - uses: actions/checkout@v2 - name: Run checker run: | ./scripts/check_environment.sh + From 088ea218a4e90ae84ce268a7a79d333fec95256e Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Tue, 14 Jun 2022 21:31:55 +0600 Subject: [PATCH 166/219] print number of containers are still running --- scripts/check_environment.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/check_environment.sh b/scripts/check_environment.sh index 0bc5f6c1a6..815bf9ba46 100755 --- a/scripts/check_environment.sh +++ b/scripts/check_environment.sh @@ -6,5 +6,7 @@ containers=$(docker ps --format "{{.ID}}" | wc -l) if [ "$containers" -eq "0" ]; then exit 0 fi -echo "environment is not clean" + +echo "Number of containers are still running:" $containers + exit 255; \ No newline at end of file From f6cca3269cb871508c5bdb72d0611f99bd9eb1ac Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Tue, 14 Jun 2022 23:33:42 +0600 Subject: [PATCH 167/219] fix shellcheck warnings --- scripts/check_environment.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/check_environment.sh b/scripts/check_environment.sh index 815bf9ba46..6e9b45859f 100755 --- a/scripts/check_environment.sh +++ b/scripts/check_environment.sh @@ -7,6 +7,6 @@ if [ "$containers" -eq "0" ]; then exit 0 fi -echo "Number of containers are still running:" $containers +echo "Number of containers are still running:" "$containers" exit 255; \ No newline at end of file From bdc5c88d8daf1b3f142638b63d808cb03c3bd083 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Tue, 14 Jun 2022 23:42:11 +0600 Subject: [PATCH 168/219] add 'docker ps' output --- scripts/check_environment.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/check_environment.sh b/scripts/check_environment.sh index 6e9b45859f..b95bc844fe 100755 --- a/scripts/check_environment.sh +++ b/scripts/check_environment.sh @@ -1,12 +1,12 @@ #!/usr/bin/env bash - +docker_out="/tmp/dout.txt" containers=$(docker ps --format "{{.ID}}" | wc -l) if [ "$containers" -eq "0" ]; then exit 0 fi +echo "$(docker ps)" echo "Number of containers are still running:" "$containers" - exit 255; \ No newline at end of file From 927614b9e9107fd260e93f2589d301f25df5f193 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Tue, 14 Jun 2022 23:43:39 +0600 Subject: [PATCH 169/219] fix shellcheck errors --- scripts/check_environment.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/check_environment.sh b/scripts/check_environment.sh index b95bc844fe..26b151647a 100755 --- a/scripts/check_environment.sh +++ b/scripts/check_environment.sh @@ -7,6 +7,6 @@ if [ "$containers" -eq "0" ]; then exit 0 fi -echo "$(docker ps)" +docker ps echo "Number of containers are still running:" "$containers" exit 255; \ No newline at end of file From 7b18b66b580d52cfee8cb0c3988d941b0fd88633 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Tue, 14 Jun 2022 23:44:56 +0600 Subject: [PATCH 170/219] fix shellcheck errors. remove unused vaiable --- scripts/check_environment.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/check_environment.sh b/scripts/check_environment.sh index 26b151647a..b93f079c0c 100755 --- a/scripts/check_environment.sh +++ b/scripts/check_environment.sh @@ -1,6 +1,5 @@ #!/usr/bin/env bash -docker_out="/tmp/dout.txt" containers=$(docker ps --format "{{.ID}}" | wc -l) if [ "$containers" -eq "0" ]; then From 43d121db88e2bf05aa523881d8ec2b015223e8cb Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Tue, 14 Jun 2022 20:22:12 +0200 Subject: [PATCH 171/219] Add shm size --- container.go | 1 + docker.go | 1 + 2 files changed, 2 insertions(+) diff --git a/container.go b/container.go index 605d79f976..696e7c5937 100644 --- a/container.go +++ b/container.go @@ -105,6 +105,7 @@ type ContainerRequest struct { AlwaysPullImage bool // Always pull image ImagePlatform string // ImagePlatform describes the platform which the image runs on. Binds []string + ShmSize int64 // Amount of memory shared with the host (in MB) } type ( diff --git a/docker.go b/docker.go index 5ae5cb4a62..053e1c1814 100644 --- a/docker.go +++ b/docker.go @@ -872,6 +872,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque Privileged: req.Privileged, NetworkMode: req.NetworkMode, Resources: req.Resources, + ShmSize: req.ShmSize, } endpointConfigs := map[string]*network.EndpointSettings{} From 44e09ea08e04afea46023c292879c444409eb138 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Wed, 15 Jun 2022 08:51:07 +0600 Subject: [PATCH 172/219] add waiting loop --- scripts/check_environment.sh | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/scripts/check_environment.sh b/scripts/check_environment.sh index b93f079c0c..48eda903ec 100755 --- a/scripts/check_environment.sh +++ b/scripts/check_environment.sh @@ -1,10 +1,15 @@ #!/usr/bin/env bash -containers=$(docker ps --format "{{.ID}}" | wc -l) +i=0 +while [ $i -ne 15 ] +do + containers=$(docker ps --format "{{.ID}}" | wc -l) -if [ "$containers" -eq "0" ]; then - exit 0 -fi + if [ "$containers" -eq "0" ]; then + exit 0 + fi + sleep 2 +done docker ps echo "Number of containers are still running:" "$containers" From 2d8f8c5f3b115d9d89142751b2529802ba415af7 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Wed, 15 Jun 2022 09:01:35 +0600 Subject: [PATCH 173/219] add missing counter --- scripts/check_environment.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/check_environment.sh b/scripts/check_environment.sh index 48eda903ec..8d5a936129 100755 --- a/scripts/check_environment.sh +++ b/scripts/check_environment.sh @@ -3,12 +3,12 @@ i=0 while [ $i -ne 15 ] do - containers=$(docker ps --format "{{.ID}}" | wc -l) - - if [ "$containers" -eq "0" ]; then - exit 0 - fi - sleep 2 + containers=$(docker ps --format "{{.ID}}" | wc -l) + if [ "$containers" -eq "0" ]; then + exit 0 + fi + sleep 2 + i=$(($i+1)) done docker ps From fe3efaebf544700502569ecc72015897f527a55c Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Wed, 15 Jun 2022 09:08:08 +0600 Subject: [PATCH 174/219] fix shellcheck warnings --- scripts/check_environment.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/check_environment.sh b/scripts/check_environment.sh index 8d5a936129..6dc4c869ba 100755 --- a/scripts/check_environment.sh +++ b/scripts/check_environment.sh @@ -1,14 +1,14 @@ #!/usr/bin/env bash i=0 -while [ $i -ne 15 ] +while [ $i -ne 10 ] do containers=$(docker ps --format "{{.ID}}" | wc -l) if [ "$containers" -eq "0" ]; then exit 0 fi sleep 2 - i=$(($i+1)) + i=$((i + 1)) done docker ps From 2b6fba1c89313845940787d74f84113a55d2f518 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Wed, 15 Jun 2022 22:14:37 +0600 Subject: [PATCH 175/219] add options for GenericParallelContainers function --- parallel.go | 28 +++++++++++++++++++--------- parallel_test.go | 2 +- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/parallel.go b/parallel.go index 5aa7dc0a7c..ac57e56626 100644 --- a/parallel.go +++ b/parallel.go @@ -7,15 +7,13 @@ import ( ) const ( - MaxGenericWorkers = 8 + defaultWorkersCount = 8 ) -type GenericParallelErrors struct { - Errors []GenericContainerRequestError -} - -func (gpe GenericParallelErrors) Error() string { - return fmt.Sprintf("%v", gpe.Errors) +// GenericParallelOptions represents additional options for running +// * WorkersCount - count of parallel workers. if field empty(zero), default value will be 'defaultWorkersCount' +type GenericParallelOptions struct { + WorkersCount int } // GenericContainerRequestError represents error from parallel request @@ -24,6 +22,14 @@ type GenericContainerRequestError struct { Error error } +type GenericParallelErrors struct { + Errors []GenericContainerRequestError +} + +func (gpe GenericParallelErrors) Error() string { + return fmt.Sprintf("%v", gpe.Errors) +} + func genericContainerRunner( ctx context.Context, requests <-chan GenericContainerRequest, @@ -45,8 +51,12 @@ func genericContainerRunner( } // GenericParallelContainers creates a generic containers with parameters in parallel mode -func GenericParallelContainers(ctx context.Context, reqs []GenericContainerRequest) ([]Container, error) { - tasksChanSize := MaxGenericWorkers +func GenericParallelContainers(ctx context.Context, reqs []GenericContainerRequest, opt GenericParallelOptions) ([]Container, error) { + if opt.WorkersCount == 0 { + opt.WorkersCount = defaultWorkersCount + } + + tasksChanSize := opt.WorkersCount if tasksChanSize > len(reqs) { tasksChanSize = len(reqs) } diff --git a/parallel_test.go b/parallel_test.go index a070aff50c..1893d3dadb 100644 --- a/parallel_test.go +++ b/parallel_test.go @@ -69,7 +69,7 @@ func TestGenericParallelContainers(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - res, err := GenericParallelContainers(context.Background(), tc.reqs) + res, err := GenericParallelContainers(context.Background(), tc.reqs, GenericParallelOptions{}) if err != nil && tc.expErrors > 0 { e, _ := err.(GenericParallelErrors) From 33f0243cae99f01ece3aaae59f7b0e16426509d9 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Wed, 15 Jun 2022 22:23:51 +0600 Subject: [PATCH 176/219] update docs --- docs/features/creating_container.md | 2 +- parallel.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/features/creating_container.md b/docs/features/creating_container.md index c86ccc10fb..533061a13f 100644 --- a/docs/features/creating_container.md +++ b/docs/features/creating_container.md @@ -112,7 +112,7 @@ requests := []GenericContainerRequest{ }, } -res, err := GenericParallelContainers(ctx, requests) +res, err := GenericParallelContainers(ctx, requests, GenericParallelOptions{}) if err != nil { e, ok := err.(GenericParallelErrors) diff --git a/parallel.go b/parallel.go index ac57e56626..3c84d65039 100644 --- a/parallel.go +++ b/parallel.go @@ -50,7 +50,7 @@ func genericContainerRunner( wg.Done() } -// GenericParallelContainers creates a generic containers with parameters in parallel mode +// GenericParallelContainers creates a generic containers with parameters and run it in parallel mode func GenericParallelContainers(ctx context.Context, reqs []GenericContainerRequest, opt GenericParallelOptions) ([]Container, error) { if opt.WorkersCount == 0 { opt.WorkersCount = defaultWorkersCount From 4f15dd04aa48a366149be02103d30b5b2b4c3553 Mon Sep 17 00:00:00 2001 From: Jop Zitman Date: Thu, 16 Jun 2022 09:42:21 +0200 Subject: [PATCH 177/219] Fix docstring for ShmSize --- container.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container.go b/container.go index 696e7c5937..a82bbe8e8f 100644 --- a/container.go +++ b/container.go @@ -105,7 +105,7 @@ type ContainerRequest struct { AlwaysPullImage bool // Always pull image ImagePlatform string // ImagePlatform describes the platform which the image runs on. Binds []string - ShmSize int64 // Amount of memory shared with the host (in MB) + ShmSize int64 // Amount of memory shared with the host (in bytes) } type ( From 0d5b2abe20ad58ca372274144ae1b74bd786f08b Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Thu, 16 Jun 2022 17:08:47 +0600 Subject: [PATCH 178/219] refactoring: rename all methods and errors working with parallel containers --- docs/features/creating_container.md | 6 +++--- parallel.go | 33 ++++++++++++++--------------- parallel_test.go | 6 +++--- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/docs/features/creating_container.md b/docs/features/creating_container.md index 533061a13f..762312451e 100644 --- a/docs/features/creating_container.md +++ b/docs/features/creating_container.md @@ -84,7 +84,7 @@ func TestIntegrationNginxLatestReturn(t *testing.T) { # Parallel running -`testcontainers.GenericParallelContainers` - defines the containers that should be run in parallel mode. +`testcontainers.ParallelContainers` - defines the containers that should be run in parallel mode. ```go ctx := context.Background() @@ -112,10 +112,10 @@ requests := []GenericContainerRequest{ }, } -res, err := GenericParallelContainers(ctx, requests, GenericParallelOptions{}) +res, err := ParallelContainers(ctx, requests, ParallelContainersOptions{}) if err != nil { - e, ok := err.(GenericParallelErrors) + e, ok := err.(ParallelContainersError) if !ok { log.Fatalf("unknown error: %v", err) } diff --git a/parallel.go b/parallel.go index 3c84d65039..c319fbf3f5 100644 --- a/parallel.go +++ b/parallel.go @@ -10,36 +10,36 @@ const ( defaultWorkersCount = 8 ) -// GenericParallelOptions represents additional options for running +// ParallelContainersOptions represents additional options for parallel running // * WorkersCount - count of parallel workers. if field empty(zero), default value will be 'defaultWorkersCount' -type GenericParallelOptions struct { +type ParallelContainersOptions struct { WorkersCount int } -// GenericContainerRequestError represents error from parallel request -type GenericContainerRequestError struct { +// ParallelContainersRequestError represents error from parallel request +type ParallelContainersRequestError struct { Request GenericContainerRequest Error error } -type GenericParallelErrors struct { - Errors []GenericContainerRequestError +type ParallelContainersError struct { + Errors []ParallelContainersRequestError } -func (gpe GenericParallelErrors) Error() string { +func (gpe ParallelContainersError) Error() string { return fmt.Sprintf("%v", gpe.Errors) } -func genericContainerRunner( +func parallelContainersRunner( ctx context.Context, requests <-chan GenericContainerRequest, - errors chan<- GenericContainerRequestError, + errors chan<- ParallelContainersRequestError, containers chan<- Container, wg *sync.WaitGroup) { for req := range requests { c, err := GenericContainer(ctx, req) if err != nil { - errors <- GenericContainerRequestError{ + errors <- ParallelContainersRequestError{ Request: req, Error: err, } @@ -50,8 +50,8 @@ func genericContainerRunner( wg.Done() } -// GenericParallelContainers creates a generic containers with parameters and run it in parallel mode -func GenericParallelContainers(ctx context.Context, reqs []GenericContainerRequest, opt GenericParallelOptions) ([]Container, error) { +// ParallelContainers creates a generic containers with parameters and run it in parallel mode +func ParallelContainers(ctx context.Context, reqs []GenericContainerRequest, opt ParallelContainersOptions) ([]Container, error) { if opt.WorkersCount == 0 { opt.WorkersCount = defaultWorkersCount } @@ -62,19 +62,19 @@ func GenericParallelContainers(ctx context.Context, reqs []GenericContainerReque } tasksChan := make(chan GenericContainerRequest, tasksChanSize) - errsChan := make(chan GenericContainerRequestError) + errsChan := make(chan ParallelContainersRequestError) resChan := make(chan Container) waitRes := make(chan struct{}) containers := make([]Container, 0) - errors := make([]GenericContainerRequestError, 0) + errors := make([]ParallelContainersRequestError, 0) wg := sync.WaitGroup{} wg.Add(tasksChanSize) // run workers for i := 0; i < tasksChanSize; i++ { - go genericContainerRunner(ctx, tasksChan, errsChan, resChan, &wg) + go parallelContainersRunner(ctx, tasksChan, errsChan, resChan, &wg) } go func() { @@ -113,9 +113,8 @@ func GenericParallelContainers(ctx context.Context, reqs []GenericContainerReque <-waitRes if len(errors) == 0 { - return containers, GenericParallelErrors{Errors: errors} + return containers, ParallelContainersError{Errors: errors} } return containers, nil - } diff --git a/parallel_test.go b/parallel_test.go index 1893d3dadb..72ce0ffc32 100644 --- a/parallel_test.go +++ b/parallel_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func TestGenericParallelContainers(t *testing.T) { +func TestParallelContainers(t *testing.T) { tests := []struct { name string reqs []GenericContainerRequest @@ -69,10 +69,10 @@ func TestGenericParallelContainers(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - res, err := GenericParallelContainers(context.Background(), tc.reqs, GenericParallelOptions{}) + res, err := ParallelContainers(context.Background(), tc.reqs, ParallelContainersOptions{}) if err != nil && tc.expErrors > 0 { - e, _ := err.(GenericParallelErrors) + e, _ := err.(ParallelContainersError) if len(e.Errors) != tc.expErrors { t.Fatalf("expected erorrs: %d, got: %d\n", tc.expErrors, len(e.Errors)) From cae81c4ed32cf08eca6518f373baa8bd5d96d488 Mon Sep 17 00:00:00 2001 From: "v.funtikov" Date: Thu, 16 Jun 2022 21:12:10 +0300 Subject: [PATCH 179/219] fix: move test to e2e module --- container_test.go | 79 ---- e2e/Makefile | 8 + e2e/container_test.go | 90 ++++ e2e/doc.go | 2 + e2e/go.mod | 11 + e2e/go.sum | 1012 +++++++++++++++++++++++++++++++++++++++++ go.mod | 1 - go.sum | 2 - 8 files changed, 1123 insertions(+), 82 deletions(-) create mode 100644 e2e/Makefile create mode 100644 e2e/container_test.go create mode 100644 e2e/doc.go create mode 100644 e2e/go.mod create mode 100644 e2e/go.sum diff --git a/container_test.go b/container_test.go index 39b2a25008..f0a3239f40 100644 --- a/container_test.go +++ b/container_test.go @@ -12,12 +12,9 @@ import ( "testing" "time" - "github.com/docker/go-connections/nat" "github.com/stretchr/testify/assert" "github.com/testcontainers/testcontainers-go/wait" - - _ "github.com/lib/pq" ) func Test_ContainerValidation(t *testing.T) { @@ -417,79 +414,3 @@ func TestVolumeMount(t *testing.T) { }) } } - -func TestContainerWithWaitForSQL(t *testing.T) { - const dbname = "postgres" - - ctx := context.Background() - - var env = map[string]string{ - "POSTGRES_PASSWORD": "password", - "POSTGRES_USER": "postgres", - "POSTGRES_DB": dbname, - } - var port = "5432/tcp" - dbURL := func(port nat.Port) string { - return fmt.Sprintf("postgres://postgres:password@localhost:%s/%s?sslmode=disable", port.Port(), dbname) - } - - t.Run("default query", func(t *testing.T) { - req := ContainerRequest{ - Image: "postgres:14.1-alpine", - ExposedPorts: []string{port}, - Cmd: []string{"postgres", "-c", "fsync=off"}, - Env: env, - WaitingFor: wait.ForSQL(nat.Port(port), "postgres", dbURL). - Timeout(time.Second * 5), - } - container, err := GenericContainer(ctx, GenericContainerRequest{ - ContainerRequest: req, - Started: true, - }) - if err != nil { - t.Fatal(err) - } - - defer container.Terminate(ctx) - }) - t.Run("custom query", func(t *testing.T) { - req := ContainerRequest{ - Image: "postgres:14.1-alpine", - ExposedPorts: []string{port}, - Cmd: []string{"postgres", "-c", "fsync=off"}, - Env: env, - WaitingFor: wait.ForSQL(nat.Port(port), "postgres", dbURL). - Timeout(time.Second * 5). - WithQuery("SELECT 10"), - } - container, err := GenericContainer(ctx, GenericContainerRequest{ - ContainerRequest: req, - Started: true, - }) - if err != nil { - t.Fatal(err) - } - - defer container.Terminate(ctx) - }) - t.Run("custom bad query", func(t *testing.T) { - req := ContainerRequest{ - Image: "postgres:14.1-alpine", - ExposedPorts: []string{port}, - Cmd: []string{"postgres", "-c", "fsync=off"}, - Env: env, - WaitingFor: wait.ForSQL(nat.Port(port), "postgres", dbURL). - Timeout(time.Second * 5). - WithQuery("SELECT 'a' from b"), - } - container, err := GenericContainer(ctx, GenericContainerRequest{ - ContainerRequest: req, - Started: true, - }) - if err == nil { - t.Fatal("expected error, but got a nil") - } - - defer container.Terminate(ctx) - }) -} diff --git a/e2e/Makefile b/e2e/Makefile new file mode 100644 index 0000000000..e2035adad8 --- /dev/null +++ b/e2e/Makefile @@ -0,0 +1,8 @@ + +.PHONY: test +test: tools + go test ./... + +.PHONY: tools +tools: + go mod download \ No newline at end of file diff --git a/e2e/container_test.go b/e2e/container_test.go new file mode 100644 index 0000000000..3557f7c5f1 --- /dev/null +++ b/e2e/container_test.go @@ -0,0 +1,90 @@ +package e2e + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/docker/go-connections/nat" + . "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" + + _ "github.com/lib/pq" +) + +func TestContainerWithWaitForSQL(t *testing.T) { + const dbname = "postgres" + + ctx := context.Background() + + var env = map[string]string{ + "POSTGRES_PASSWORD": "password", + "POSTGRES_USER": "postgres", + "POSTGRES_DB": dbname, + } + var port = "5432/tcp" + dbURL := func(port nat.Port) string { + return fmt.Sprintf("postgres://postgres:password@localhost:%s/%s?sslmode=disable", port.Port(), dbname) + } + + t.Run("default query", func(t *testing.T) { + req := ContainerRequest{ + Image: "postgres:14.1-alpine", + ExposedPorts: []string{port}, + Cmd: []string{"postgres", "-c", "fsync=off"}, + Env: env, + WaitingFor: wait.ForSQL(nat.Port(port), "postgres", dbURL). + Timeout(time.Second * 5), + } + container, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + + defer container.Terminate(ctx) + }) + t.Run("custom query", func(t *testing.T) { + req := ContainerRequest{ + Image: "postgres:14.1-alpine", + ExposedPorts: []string{port}, + Cmd: []string{"postgres", "-c", "fsync=off"}, + Env: env, + WaitingFor: wait.ForSQL(nat.Port(port), "postgres", dbURL). + Timeout(time.Second * 5). + WithQuery("SELECT 10"), + } + container, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + + defer container.Terminate(ctx) + }) + t.Run("custom bad query", func(t *testing.T) { + req := ContainerRequest{ + Image: "postgres:14.1-alpine", + ExposedPorts: []string{port}, + Cmd: []string{"postgres", "-c", "fsync=off"}, + Env: env, + WaitingFor: wait.ForSQL(nat.Port(port), "postgres", dbURL). + Timeout(time.Second * 5). + WithQuery("SELECT 'a' from b"), + } + container, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err == nil { + t.Fatal("expected error, but got a nil") + } + + defer container.Terminate(ctx) + }) +} diff --git a/e2e/doc.go b/e2e/doc.go new file mode 100644 index 0000000000..16f30349a8 --- /dev/null +++ b/e2e/doc.go @@ -0,0 +1,2 @@ +// Package e2e contains end-to-end tests. +package e2e diff --git a/e2e/go.mod b/e2e/go.mod new file mode 100644 index 0000000000..f8a627997c --- /dev/null +++ b/e2e/go.mod @@ -0,0 +1,11 @@ +module e2e + +go 1.13 + +require ( + github.com/docker/go-connections v0.4.0 + github.com/lib/pq v1.10.6 + github.com/testcontainers/testcontainers-go v0.13.0 +) + +replace github.com/testcontainers/testcontainers-go => ../ diff --git a/e2e/go.sum b/e2e/go.sum new file mode 100644 index 0000000000..a7e857313f --- /dev/null +++ b/e2e/go.sum @@ -0,0 +1,1012 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w= +github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= +github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.24 h1:jP+GMeRXIR1sH1kG4lJr9ShmSjVrua5jmFZDtfYGkn4= +github.com/Microsoft/hcsshim v0.8.24/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= +github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= +github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= +github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= +github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= +github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= +github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= +github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= +github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= +github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= +github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= +github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= +github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= +github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= +github.com/containerd/containerd v1.5.13 h1:XqvKw9i4P7/mFrC3TSM7yV5cwFZ9avXe6M3YANKnzEE= +github.com/containerd/containerd v1.5.13/go.mod h1:3AlCrzKROjIuP3JALsY14n8YtntaUDBu7vek+rPN5Vc= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= +github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= +github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= +github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= +github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= +github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= +github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= +github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= +github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= +github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= +github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= +github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= +github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= +github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= +github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= +github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= +github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= +github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= +github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= +github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE= +github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v20.10.11+incompatible h1:OqzI/g/W54LczvhnccGqniFoQghHx3pklbLuhfXpqGo= +github.com/docker/docker v20.10.11+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= +github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= +github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE= +github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg= +github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20211108170745-6635138e15ea h1:FosBMXtOc8Tp9Hbo4ltl1WJSrTVewZU8MPnTPY2HdH8= +golang.org/x/net v0.0.0-20211108170745-6635138e15ea/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/gotestsum v1.7.0/go.mod h1:V1m4Jw3eBerhI/A6qCxUE07RnCg7ACkKj9BYcAm09V8= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I= +gotest.tools/v3 v3.2.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= +k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= +k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= +k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= +k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= +k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= +k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= +k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= +k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= +k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= +k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= +k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= +k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= +k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= +k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/go.mod b/go.mod index c6bab43005..3dd836f3c0 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/golang/protobuf v1.5.2 // indirect github.com/google/uuid v1.3.0 - github.com/lib/pq v1.10.6 github.com/magiconair/properties v1.8.6 github.com/moby/sys/mount v0.2.0 // indirect github.com/moby/sys/mountinfo v0.5.0 // indirect diff --git a/go.sum b/go.sum index 45a9cbb177..b8de5a6b43 100644 --- a/go.sum +++ b/go.sum @@ -422,8 +422,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= -github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= From ba1b99ab1acba4a914577a8cc1cb5171a7803f92 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Fri, 17 Jun 2022 21:26:02 +0600 Subject: [PATCH 180/219] feat: update 3d party packages --- go.mod | 28 ++-- go.sum | 501 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 520 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 3dd836f3c0..2341b7e16f 100644 --- a/go.mod +++ b/go.mod @@ -3,25 +3,35 @@ module github.com/testcontainers/testcontainers-go go 1.13 require ( + github.com/Microsoft/go-winio v0.5.2 // indirect + github.com/Microsoft/hcsshim v0.9.3 // indirect github.com/cenkalti/backoff/v4 v4.1.2 - github.com/containerd/containerd v1.5.13 - github.com/docker/docker v20.10.11+incompatible + github.com/containerd/cgroups v1.0.4 // indirect + github.com/containerd/containerd v1.6.2 + github.com/docker/docker v20.10.14+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.4.0 github.com/go-redis/redis v6.15.9+incompatible github.com/go-sql-driver/mysql v1.6.0 + github.com/gogo/googleapis v1.4.1 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/uuid v1.3.0 + github.com/klauspost/compress v1.15.6 // indirect github.com/magiconair/properties v1.8.6 - github.com/moby/sys/mount v0.2.0 // indirect - github.com/moby/sys/mountinfo v0.5.0 // indirect + github.com/moby/sys/mount v0.3.1 // indirect + github.com/moby/sys/mountinfo v0.6.1 // indirect + github.com/moby/sys/signal v0.7.0 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 - github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect github.com/opencontainers/image-spec v1.0.2 - github.com/stretchr/testify v1.7.0 - golang.org/x/net v0.0.0-20211108170745-6635138e15ea // indirect - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b + github.com/opencontainers/runc v1.1.3 // indirect + github.com/opencontainers/selinux v1.10.1 // indirect + github.com/stretchr/objx v0.4.0 // indirect + github.com/stretchr/testify v1.7.1 + golang.org/x/net v0.0.0-20220403103023-749bd193bc2b // indirect + golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect + golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb + google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad // indirect + gopkg.in/yaml.v3 v3.0.1 gotest.tools/gotestsum v1.7.0 gotest.tools/v3 v3.2.0 ) diff --git a/go.sum b/go.sum index b8de5a6b43..9d463174cd 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,5 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -10,31 +11,52 @@ cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6T cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -47,6 +69,9 @@ github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JP github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= @@ -54,23 +79,39 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3 github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim v0.8.24 h1:jP+GMeRXIR1sH1kG4lJr9ShmSjVrua5jmFZDtfYGkn4= github.com/Microsoft/hcsshim v0.8.24/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= +github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +github.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo= +github.com/Microsoft/hcsshim v0.9.3/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= +github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -78,11 +119,13 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= @@ -90,10 +133,14 @@ github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInq github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= +github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -102,9 +149,21 @@ github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLI github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= +github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= @@ -121,11 +180,14 @@ github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTF github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= +github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= +github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= @@ -139,8 +201,13 @@ github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7 github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= +github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= +github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= +github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= github.com/containerd/containerd v1.5.13 h1:XqvKw9i4P7/mFrC3TSM7yV5cwFZ9avXe6M3YANKnzEE= github.com/containerd/containerd v1.5.13/go.mod h1:3AlCrzKROjIuP3JALsY14n8YtntaUDBu7vek+rPN5Vc= +github.com/containerd/containerd v1.6.2 h1:pcaPUGbYW8kBw6OgIZwIVIeEhdWVrBzsoCfVJ5BjrLU= +github.com/containerd/containerd v1.6.2/go.mod h1:sidY30/InSE1j2vdD1ihtKoJz+lWdaXMdiAeIupaf+s= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -149,14 +216,20 @@ github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU= github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= +github.com/containerd/go-cni v1.1.0/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= +github.com/containerd/go-cni v1.1.3/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= @@ -166,18 +239,22 @@ github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4= github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lWI= github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= @@ -187,15 +264,20 @@ github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNR github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y= github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= +github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE= github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -210,9 +292,11 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= @@ -227,15 +311,21 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8 github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnephin/pflag v1.0.7 h1:oxONGlWxhmUct0YzKTgrpQv9AUA1wtPBn7zuSjJqptk= github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.11+incompatible h1:OqzI/g/W54LczvhnccGqniFoQghHx3pklbLuhfXpqGo= github.com/docker/docker v20.10.11+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.14+incompatible h1:+T9/PRYWNDo5SZl5qS1r9Mo/0Q8AwxKKPtu9S1yxM0w= +github.com/docker/docker v20.10.14+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= @@ -252,18 +342,28 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -272,29 +372,48 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -309,11 +428,17 @@ github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -329,28 +454,43 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -363,53 +503,86 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY= +github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -422,69 +595,115 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= +github.com/moby/sys/mount v0.3.1 h1:RX1K0x95oR8j5P1YefKDt7tE1C2kCCixV0H8Aza3GaI= +github.com/moby/sys/mount v0.3.1/go.mod h1:6IZknFQiqjLpwuYJD5Zk0qYEuJiws36M88MIXnZHya0= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/sys/mountinfo v0.6.0 h1:gUDhXQx58YNrpHlK4nSL+7y2pxFZkUcXqzFDKWdC0Oo= +github.com/moby/sys/mountinfo v0.6.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/sys/mountinfo v0.6.1 h1:+H/KnGEAGRpTrEAqNVQ2AM3SiwMgJUt/TXj+Z8cmCIc= +github.com/moby/sys/mountinfo v0.6.1/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= +github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= +github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= +github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU= +github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -493,6 +712,7 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= @@ -502,18 +722,28 @@ github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rm github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg= github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= +github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= +github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opencontainers/selinux v1.10.1 h1:09LIPVRP3uuZGQvgR+SgMSNBd1Eb3vlRbGqQpoHsF8w= +github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -522,6 +752,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -529,6 +760,7 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -540,6 +772,8 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -551,13 +785,22 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= +github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= @@ -570,7 +813,9 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -578,6 +823,7 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -585,24 +831,34 @@ github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -611,9 +867,11 @@ github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -621,7 +879,9 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= @@ -630,21 +890,59 @@ github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= +go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= +go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= +go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= +go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= +go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -654,7 +952,9 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -677,6 +977,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -685,13 +987,17 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -704,6 +1010,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -715,34 +1022,69 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211108170745-6635138e15ea h1:FosBMXtOc8Tp9Hbo4ltl1WJSrTVewZU8MPnTPY2HdH8= golang.org/x/net v0.0.0-20211108170745-6635138e15ea/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220403103023-749bd193bc2b h1:vI32FkLJNAWtGD4BwkThwEy6XS7ZLLMHkSkYfF8M0W0= +golang.org/x/net v0.0.0-20220403103023-749bd193bc2b/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220615171555-694bf12d69de h1:ogOG2+P6LjO2j55AkRScrkB2BFpd+Z8TY2wcM0Z3MGo= +golang.org/x/net v0.0.0-20220615171555-694bf12d69de/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -758,6 +1100,7 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -785,49 +1128,92 @@ golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb h1:PVGECzEo9Y3uOidtkHGdd347NjLtITfJFO9BxFpmRoo= +golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -843,9 +1229,12 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -860,10 +1249,31 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -881,12 +1291,25 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -907,10 +1330,39 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad h1:kqrS+lhvaMHCxul6sKQvKJ8nAAhlVItmZV822hYFH/U= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -923,9 +1375,25 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -940,6 +1408,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -947,11 +1417,14 @@ gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -962,6 +1435,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -969,14 +1443,19 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/gotestsum v1.7.0 h1:RwpqwwFKBAa2h+F6pMEGpE707Edld0etUD3GhqqhDNc= gotest.tools/gotestsum v1.7.0/go.mod h1:V1m4Jw3eBerhI/A6qCxUE07RnCg7ACkKj9BYcAm09V8= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gotest.tools/v3 v3.1.0 h1:rVV8Tcg/8jHUkPUorwjaMTtemIMVXfIPKiOqnhEhakk= +gotest.tools/v3 v3.1.0/go.mod h1:fHy7eyTmJFO5bQbUsEGQ1v4m2J3Jz9eWL54TP2/ZuYQ= gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I= gotest.tools/v3 v3.2.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -985,37 +1464,59 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= +k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= +k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= +k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= +k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= +k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y= +k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= +k8s.io/component-base v0.22.5/go.mod h1:VK3I+TjuF9eaa+Ln67dKxhGar5ynVbwnGrUiNF4MqCI= k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= +k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= +k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= From 42396fdce4fb3a4821b65c7c363d5fe295278752 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Fri, 17 Jun 2022 21:56:42 +0600 Subject: [PATCH 181/219] fix go vet warnigs --- go.mod | 29 +++++++++++++++++++++++++---- go.sum | 4 ++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 2341b7e16f..e636e3d4fb 100644 --- a/go.mod +++ b/go.mod @@ -3,35 +3,56 @@ module github.com/testcontainers/testcontainers-go go 1.13 require ( + bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512 // indirect + cloud.google.com/go v0.81.0 // indirect + github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect github.com/Microsoft/hcsshim v0.9.3 // indirect github.com/cenkalti/backoff/v4 v4.1.2 github.com/containerd/cgroups v1.0.4 // indirect - github.com/containerd/containerd v1.6.2 + github.com/containerd/containerd v1.5.9 + github.com/containerd/continuity v0.3.0 // indirect + github.com/containerd/go-cni v1.1.3 // indirect + github.com/containerd/imgcrypt v1.1.3 // indirect + github.com/containernetworking/plugins v1.0.1 // indirect github.com/docker/docker v20.10.14+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.4.0 + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-redis/redis v6.15.9+incompatible github.com/go-sql-driver/mysql v1.6.0 github.com/gogo/googleapis v1.4.1 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/uuid v1.3.0 + github.com/intel/goresctrl v0.2.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.15.6 // indirect github.com/magiconair/properties v1.8.6 github.com/moby/sys/mount v0.3.1 // indirect - github.com/moby/sys/mountinfo v0.6.1 // indirect + github.com/moby/sys/mountinfo v0.6.2 // indirect github.com/moby/sys/signal v0.7.0 // indirect + github.com/moby/sys/symlink v0.2.0 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 github.com/opencontainers/image-spec v1.0.2 github.com/opencontainers/runc v1.1.3 // indirect github.com/opencontainers/selinux v1.10.1 // indirect + github.com/pelletier/go-toml v1.9.3 // indirect github.com/stretchr/objx v0.4.0 // indirect github.com/stretchr/testify v1.7.1 - golang.org/x/net v0.0.0-20220403103023-749bd193bc2b // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0 // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/net v0.0.0-20220615171555-694bf12d69de // indirect + golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect - golang.org/x/sys v0.0.0-20220403205710-6acee93ad0eb + golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad // indirect gopkg.in/yaml.v3 v3.0.1 gotest.tools/gotestsum v1.7.0 gotest.tools/v3 v3.2.0 + k8s.io/apiserver v0.22.5 // indirect + k8s.io/cri-api v0.23.1 // indirect + k8s.io/klog/v2 v2.30.0 // indirect + k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b // indirect ) diff --git a/go.sum b/go.sum index 9d463174cd..4a66bbd463 100644 --- a/go.sum +++ b/go.sum @@ -204,6 +204,8 @@ github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoT github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= +github.com/containerd/containerd v1.5.9 h1:rs6Xg1gtIxaeyG+Smsb/0xaSDu1VgFhOCKBXxMxbsF4= +github.com/containerd/containerd v1.5.9/go.mod h1:fvQqCfadDGga5HZyn3j4+dx56qj2I9YwBrlSdalvJYQ= github.com/containerd/containerd v1.5.13 h1:XqvKw9i4P7/mFrC3TSM7yV5cwFZ9avXe6M3YANKnzEE= github.com/containerd/containerd v1.5.13/go.mod h1:3AlCrzKROjIuP3JALsY14n8YtntaUDBu7vek+rPN5Vc= github.com/containerd/containerd v1.6.2 h1:pcaPUGbYW8kBw6OgIZwIVIeEhdWVrBzsoCfVJ5BjrLU= @@ -472,6 +474,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -666,6 +669,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= From 07fba6d4f2d2438f2cd5414e0e0a78b49b69277e Mon Sep 17 00:00:00 2001 From: "v.funtikov" Date: Fri, 17 Jun 2022 20:48:28 +0300 Subject: [PATCH 182/219] fix: add e2e tests to github test strategy --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a64969ea6..1eaa5c901a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,9 @@ jobs: # we can't put Windows Server in "Linux Mode" in Github actions # another, host mode is only available on Linux, and we have tests around that, do we skip them? if: ${{ matrix.platform == 'ubuntu-latest' }} - run: go run gotest.tools/gotestsum --format short-verbose -- -coverprofile=cover.txt ./... + run: | + go run gotest.tools/gotestsum --format short-verbose -- -coverprofile=cover.txt ./... + cd ./e2e && make test # only report code coverage on linux - name: Upload coverage report From aa696e3d660c76604f0d7ca7895ace731a0192ad Mon Sep 17 00:00:00 2001 From: "v.funtikov" Date: Fri, 17 Jun 2022 20:53:10 +0300 Subject: [PATCH 183/219] feat: main Makefile --- Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..ea99fe7b5d --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ + +.PHONY: test +test: tools + go test ./... + echo "Running end-to-end tests..." && cd ./e2e && make + +.PHONY: tools +tools: + go mod download From e1a48f9a28d7c8e3f7d1e524e8e4ae5a7208f9ef Mon Sep 17 00:00:00 2001 From: "v.funtikov" Date: Fri, 17 Jun 2022 20:53:45 +0300 Subject: [PATCH 184/219] fix: use custom step for e2e tests --- .github/workflows/ci.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1eaa5c901a..56fb94eb6e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,9 +52,7 @@ jobs: # we can't put Windows Server in "Linux Mode" in Github actions # another, host mode is only available on Linux, and we have tests around that, do we skip them? if: ${{ matrix.platform == 'ubuntu-latest' }} - run: | - go run gotest.tools/gotestsum --format short-verbose -- -coverprofile=cover.txt ./... - cd ./e2e && make test + run: go run gotest.tools/gotestsum --format short-verbose -- -coverprofile=cover.txt ./... # only report code coverage on linux - name: Upload coverage report @@ -63,3 +61,7 @@ jobs: with: file: ./cover.txt name: testcontainers-go-${{ matrix.go-version }} + + - name: Run e2e tests + if: ${{ matrix.platform == 'ubuntu-latest' }} + run: cd ./e2e && make test From 6a1ad0a684d9cb1a6fcb7c79fe1c878d076b6e4e Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Sat, 18 Jun 2022 09:57:33 +0600 Subject: [PATCH 185/219] add missing terminate into docker_test --- docker_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker_test.go b/docker_test.go index 08dc6f3787..78781ab58c 100644 --- a/docker_test.go +++ b/docker_test.go @@ -158,11 +158,12 @@ func TestContainerWithNetworkModeAndNetworkTogether(t *testing.T) { Started: true, } - _, err := GenericContainer(ctx, gcr) + nginx, err := GenericContainer(ctx, gcr) if err != nil { // Error when NetworkMode = host and Network = []string{"bridge"} t.Logf("Can't use Network and NetworkMode together, %s", err) } + defer nginx.Terminate(ctx) } func TestContainerWithHostNetworkOptionsAndWaitStrategy(t *testing.T) { From fb4af74c56d82aadf6ea3ba0e00c4fec43575027 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Sat, 18 Jun 2022 10:05:15 +0600 Subject: [PATCH 186/219] add missing test for checking status code matcher --- docker_test.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docker_test.go b/docker_test.go index 08dc6f3787..c3d825b0f8 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1946,6 +1946,31 @@ func TestContainerWithReaperNetwork(t *testing.T) { assert.NotNil(t, cnt.NetworkSettings.Networks[networks[1]]) } +func TestContainerRunningCheckingStatusCode(t *testing.T) { + ctx := context.Background() + req := ContainerRequest{ + Image: "influxdb:1.8.3", + ExposedPorts: []string{"8086/tcp"}, + WaitingFor: wait.ForAll( + wait.ForHTTP("/ping").WithPort("8086/tcp").WithStatusCodeMatcher( + func(status int) bool { + return status == http.StatusNoContent + }, + ), + ), + } + + influx, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + + defer influx.Terminate(ctx) +} + func TestContainerWithUserID(t *testing.T) { ctx := context.Background() req := ContainerRequest{ From 9bfe3d3fee4eb14ce1528dcf39301fdc72877a2a Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Sat, 18 Jun 2022 10:59:37 +0600 Subject: [PATCH 187/219] get actual versions for packages --- go.mod | 8 ++++---- go.sum | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index e636e3d4fb..77303aca36 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/containerd/go-cni v1.1.3 // indirect github.com/containerd/imgcrypt v1.1.3 // indirect github.com/containernetworking/plugins v1.0.1 // indirect - github.com/docker/docker v20.10.14+incompatible + github.com/docker/docker v20.10.17+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.4.0 github.com/go-logr/stdr v1.2.2 // indirect @@ -28,7 +28,7 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.15.6 // indirect github.com/magiconair/properties v1.8.6 - github.com/moby/sys/mount v0.3.1 // indirect + github.com/moby/sys/mount v0.3.3 // indirect github.com/moby/sys/mountinfo v0.6.2 // indirect github.com/moby/sys/signal v0.7.0 // indirect github.com/moby/sys/symlink v0.2.0 // indirect @@ -38,12 +38,12 @@ require ( github.com/opencontainers/selinux v1.10.1 // indirect github.com/pelletier/go-toml v1.9.3 // indirect github.com/stretchr/objx v0.4.0 // indirect - github.com/stretchr/testify v1.7.1 + github.com/stretchr/testify v1.7.2 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0 // indirect golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect - golang.org/x/net v0.0.0-20220615171555-694bf12d69de // indirect + golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 // indirect golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c diff --git a/go.sum b/go.sum index 4a66bbd463..b4ca0dfee2 100644 --- a/go.sum +++ b/go.sum @@ -323,6 +323,8 @@ github.com/docker/docker v20.10.11+incompatible h1:OqzI/g/W54LczvhnccGqniFoQghHx github.com/docker/docker v20.10.11+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.14+incompatible h1:+T9/PRYWNDo5SZl5qS1r9Mo/0Q8AwxKKPtu9S1yxM0w= github.com/docker/docker v20.10.14+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE= +github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= @@ -643,6 +645,8 @@ github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM= github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= github.com/moby/sys/mount v0.3.1 h1:RX1K0x95oR8j5P1YefKDt7tE1C2kCCixV0H8Aza3GaI= github.com/moby/sys/mount v0.3.1/go.mod h1:6IZknFQiqjLpwuYJD5Zk0qYEuJiws36M88MIXnZHya0= +github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs= +github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= @@ -854,6 +858,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -1057,6 +1063,8 @@ golang.org/x/net v0.0.0-20220403103023-749bd193bc2b h1:vI32FkLJNAWtGD4BwkThwEy6X golang.org/x/net v0.0.0-20220403103023-749bd193bc2b/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220615171555-694bf12d69de h1:ogOG2+P6LjO2j55AkRScrkB2BFpd+Z8TY2wcM0Z3MGo= golang.org/x/net v0.0.0-20220615171555-694bf12d69de/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 h1:Yqz/iviulwKwAREEeUd3nbBFn0XuyJqkoft2IlrvOhc= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= From 31f431722e46971927da71b1067268b011b542b0 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Sun, 19 Jun 2022 10:28:42 +0600 Subject: [PATCH 188/219] some refactoring * add new type ParallelContainerRequest * update docs for parallel request --- docs/features/creating_container.md | 84 +++++++++++++++++------------ parallel.go | 7 +-- parallel_test.go | 6 +-- 3 files changed, 57 insertions(+), 40 deletions(-) diff --git a/docs/features/creating_container.md b/docs/features/creating_container.md index 762312451e..c1882e9d3f 100644 --- a/docs/features/creating_container.md +++ b/docs/features/creating_container.md @@ -87,42 +87,58 @@ func TestIntegrationNginxLatestReturn(t *testing.T) { `testcontainers.ParallelContainers` - defines the containers that should be run in parallel mode. ```go -ctx := context.Background() - -requests := []GenericContainerRequest{ - { - ContainerRequest: ContainerRequest{ - - Image: "nginx", - ExposedPorts: []string{ - "10080/tcp", - }, - }, - Started: true, - }, - { - ContainerRequest: ContainerRequest{ - - Image: "nginx", - ExposedPorts: []string{ - "10081/tcp", - }, - }, - Started: true, - }, -} +package main -res, err := ParallelContainers(ctx, requests, ParallelContainersOptions{}) +import ( + "context" + "fmt" + "log" -if err != nil { - e, ok := err.(ParallelContainersError) - if !ok { - log.Fatalf("unknown error: %v", err) - } - ... -} + "github.com/testcontainers/testcontainers-go" +) -for _, c := range res { - defer c.Terminate(ctx) +func main() { + ctx := context.Background() + + requests := testcontainers.ParallelContainerRequest{ + { + ContainerRequest: testcontainers.ContainerRequest{ + + Image: "nginx", + ExposedPorts: []string{ + "10080/tcp", + }, + }, + Started: true, + }, + { + ContainerRequest: testcontainers.ContainerRequest{ + + Image: "nginx", + ExposedPorts: []string{ + "10081/tcp", + }, + }, + Started: true, + }, + } + + res, err := testcontainers.ParallelContainers(ctx, requests, testcontainers.ParallelContainersOptions{}) + + if err != nil { + e, ok := err.(testcontainers.ParallelContainersError) + if !ok { + log.Fatalf("unknown error: %v", err) + } + + for _, pe := range e.Errors { + fmt.Println(pe.Request, pe.Error) + } + return + } + + for _, c := range res { + defer c.Terminate(ctx) + } } ``` \ No newline at end of file diff --git a/parallel.go b/parallel.go index c319fbf3f5..f6d371dbb3 100644 --- a/parallel.go +++ b/parallel.go @@ -10,10 +10,11 @@ const ( defaultWorkersCount = 8 ) +type ParallelContainerRequest []GenericContainerRequest + // ParallelContainersOptions represents additional options for parallel running -// * WorkersCount - count of parallel workers. if field empty(zero), default value will be 'defaultWorkersCount' type ParallelContainersOptions struct { - WorkersCount int + WorkersCount int // count of parallel workers. If field empty(zero), default value will be 'defaultWorkersCount' } // ParallelContainersRequestError represents error from parallel request @@ -51,7 +52,7 @@ func parallelContainersRunner( } // ParallelContainers creates a generic containers with parameters and run it in parallel mode -func ParallelContainers(ctx context.Context, reqs []GenericContainerRequest, opt ParallelContainersOptions) ([]Container, error) { +func ParallelContainers(ctx context.Context, reqs ParallelContainerRequest, opt ParallelContainersOptions) ([]Container, error) { if opt.WorkersCount == 0 { opt.WorkersCount = defaultWorkersCount } diff --git a/parallel_test.go b/parallel_test.go index 72ce0ffc32..390bd5892d 100644 --- a/parallel_test.go +++ b/parallel_test.go @@ -8,13 +8,13 @@ import ( func TestParallelContainers(t *testing.T) { tests := []struct { name string - reqs []GenericContainerRequest + reqs ParallelContainerRequest resLen int expErrors int }{ { name: "running two containers (success)", - reqs: []GenericContainerRequest{ + reqs: ParallelContainerRequest{ { ContainerRequest: ContainerRequest{ @@ -40,7 +40,7 @@ func TestParallelContainers(t *testing.T) { }, { name: "running two containers (one error)", - reqs: []GenericContainerRequest{ + reqs: ParallelContainerRequest{ { ContainerRequest: ContainerRequest{ From c20116780464afda4a35353607229627eb34d65b Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Mon, 20 Jun 2022 17:12:29 +0600 Subject: [PATCH 189/219] add alpine image into TestContainerRunningCheckingStatusCode --- docker_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker_test.go b/docker_test.go index c3d825b0f8..6f408c8741 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1949,7 +1949,7 @@ func TestContainerWithReaperNetwork(t *testing.T) { func TestContainerRunningCheckingStatusCode(t *testing.T) { ctx := context.Background() req := ContainerRequest{ - Image: "influxdb:1.8.3", + Image: "influxdb:1.8.10-alpine", ExposedPorts: []string{"8086/tcp"}, WaitingFor: wait.ForAll( wait.ForHTTP("/ping").WithPort("8086/tcp").WithStatusCodeMatcher( From f873db8a5bfe7fa6c9da9374a08a144a603d1a09 Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Tue, 8 Mar 2022 20:55:58 +0100 Subject: [PATCH 190/219] Improve Podman compatibility - allow configuring the default network name - it's podman for Podman instead of bridge and 'bridge' is not a valid network name with Podman - allow configuring an alternative Docker socket path for the reaper - this is also useful for rootless Docker --- container.go | 3 ++- docker.go | 43 +++++++++++++++++++------------ docker_test.go | 66 +++++++++++++++++++++++++++++++++++++++--------- network.go | 10 ++++++++ reaper.go | 68 ++++++++++++++++++++++++++++++++++---------------- 5 files changed, 139 insertions(+), 51 deletions(-) diff --git a/container.go b/container.go index a82bbe8e8f..5a26798c7d 100644 --- a/container.go +++ b/container.go @@ -114,7 +114,8 @@ type ( // GenericProviderOptions defines options applicable to all providers GenericProviderOptions struct { - Logger Logging + Logger Logging + DefaultNetwork string } // GenericProviderOption defines a common interface to modify GenericProviderOptions diff --git a/docker.go b/docker.go index 053e1c1814..e3984a22f8 100644 --- a/docker.go +++ b/docker.go @@ -560,9 +560,9 @@ func (n *DockerNetwork) Remove(ctx context.Context) error { // DockerProvider implements the ContainerProvider interface type DockerProvider struct { *DockerProviderOptions - client *client.Client - hostCache string - defaultNetwork string // default container network + client *client.Client + host string + hostCache string } var _ ContainerProvider = (*DockerProvider)(nil) @@ -637,6 +637,10 @@ func NewDockerProvider(provOpts ...DockerProviderOption) (*DockerProvider, error opts = append(opts, client.WithTLSClientConfig(cacertPath, certPath, keyPath)) } + } else if dockerHostEnv := os.Getenv("DOCKER_HOST"); dockerHostEnv != "" { + host = dockerHostEnv + } else { + host = "unix:///var/run/docker.sock" } c, err := client.NewClientWithOpts(opts...) @@ -656,6 +660,7 @@ func NewDockerProvider(provOpts ...DockerProviderOption) (*DockerProvider, error c.NegotiateAPIVersion(context.Background()) p := &DockerProvider{ DockerProviderOptions: o, + host: host, client: c, } @@ -738,24 +743,26 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque // Make sure that bridge network exists // In case it is disabled we will create reaper_default network - p.defaultNetwork, err = getDefaultNetwork(ctx, p.client) - if err != nil { - return nil, err + if p.DefaultNetwork == "" { + p.DefaultNetwork, err = getDefaultNetwork(ctx, p.client) + if err != nil { + return nil, err + } } // If default network is not bridge make sure it is attached to the request // as container won't be attached to it automatically - if p.defaultNetwork != Bridge { + if p.DefaultNetwork != Bridge { isAttached := false for _, net := range req.Networks { - if net == p.defaultNetwork { + if net == p.DefaultNetwork { isAttached = true break } } if !isAttached { - req.Networks = append(req.Networks, p.defaultNetwork) + req.Networks = append(req.Networks, p.DefaultNetwork) } } @@ -777,7 +784,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque var termSignal chan bool if !req.SkipReaper { - r, err := NewReaper(ctx, sessionID.String(), p, req.ReaperImage) + r, err := NewReaper(context.WithValue(ctx, dockerHostContextKey, p.host), sessionID.String(), p, req.ReaperImage) if err != nil { return nil, fmt.Errorf("%w: creating reaper failed", err) } @@ -1037,7 +1044,11 @@ func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) // Make sure that bridge network exists // In case it is disabled we will create reaper_default network - p.defaultNetwork, err = getDefaultNetwork(ctx, p.client) + if p.DefaultNetwork == "" { + if p.DefaultNetwork, err = getDefaultNetwork(ctx, p.client); err != nil { + return nil, err + } + } if req.Labels == nil { req.Labels = make(map[string]string) @@ -1057,7 +1068,7 @@ func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) var termSignal chan bool if !req.SkipReaper { - r, err := NewReaper(ctx, sessionID.String(), p, req.ReaperImage) + r, err := NewReaper(context.WithValue(ctx, dockerHostContextKey, p.host), sessionID.String(), p, req.ReaperImage) if err != nil { return nil, fmt.Errorf("%w: creating network reaper failed", err) } @@ -1102,14 +1113,14 @@ func (p *DockerProvider) GetNetwork(ctx context.Context, req NetworkRequest) (ty func (p *DockerProvider) GetGatewayIP(ctx context.Context) (string, error) { // Use a default network as defined in the DockerProvider - if p.defaultNetwork == "" { + if p.DefaultNetwork == "" { var err error - p.defaultNetwork, err = getDefaultNetwork(ctx, p.client) + p.DefaultNetwork, err = getDefaultNetwork(ctx, p.client) if err != nil { return "", err } } - nw, err := p.GetNetwork(ctx, NetworkRequest{Name: p.defaultNetwork}) + nw, err := p.GetNetwork(ctx, NetworkRequest{Name: p.DefaultNetwork}) if err != nil { return "", err } @@ -1149,7 +1160,7 @@ func getDefaultGatewayIP() (string, error) { if len(ip) == 0 { return "", errors.New("Failed to parse default gateway IP") } - return string(ip), nil + return ip, nil } func getDefaultNetwork(ctx context.Context, cli *client.Client) (string, error) { diff --git a/docker_test.go b/docker_test.go index dd69833eb9..0aea7e621b 100644 --- a/docker_test.go +++ b/docker_test.go @@ -41,6 +41,7 @@ import ( ) func TestContainerAttachedToNewNetwork(t *testing.T) { + t.Parallel() networkName := "new-network" ctx := context.Background() gcr := GenericContainerRequest{ @@ -108,6 +109,7 @@ func TestContainerAttachedToNewNetwork(t *testing.T) { } func TestContainerWithHostNetworkOptions(t *testing.T) { + t.Parallel() ctx := context.Background() gcr := GenericContainerRequest{ ContainerRequest: ContainerRequest{ @@ -147,6 +149,7 @@ func TestContainerWithHostNetworkOptions(t *testing.T) { } func TestContainerWithNetworkModeAndNetworkTogether(t *testing.T) { + t.Parallel() ctx := context.Background() gcr := GenericContainerRequest{ ContainerRequest: ContainerRequest{ @@ -167,6 +170,7 @@ func TestContainerWithNetworkModeAndNetworkTogether(t *testing.T) { } func TestContainerWithHostNetworkOptionsAndWaitStrategy(t *testing.T) { + t.Parallel() ctx := context.Background() gcr := GenericContainerRequest{ ContainerRequest: ContainerRequest{ @@ -197,6 +201,7 @@ func TestContainerWithHostNetworkOptionsAndWaitStrategy(t *testing.T) { } func TestContainerWithHostNetworkAndEndpoint(t *testing.T) { + t.Parallel() nginxPort := "80/tcp" ctx := context.Background() gcr := GenericContainerRequest{ @@ -229,6 +234,7 @@ func TestContainerWithHostNetworkAndEndpoint(t *testing.T) { } func TestContainerWithHostNetworkAndPortEndpoint(t *testing.T) { + t.Parallel() nginxPort := "80/tcp" ctx := context.Background() gcr := GenericContainerRequest{ @@ -261,6 +267,7 @@ func TestContainerWithHostNetworkAndPortEndpoint(t *testing.T) { } func TestContainerReturnItsContainerID(t *testing.T) { + t.Parallel() ctx := context.Background() nginxA, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: ContainerRequest{ @@ -280,19 +287,19 @@ func TestContainerReturnItsContainerID(t *testing.T) { } func TestContainerStartsWithoutTheReaper(t *testing.T) { - t.Skip("need to use the sessionID") + t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { t.Fatal(err) } client.NegotiateAPIVersion(ctx) - _, err = GenericContainer(ctx, GenericContainerRequest{ + var container Container + container, err = GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: ContainerRequest{ Image: "nginx", ExposedPorts: []string{ "80/tcp", - "gotest.tools/assert", }, SkipReaper: true, }, @@ -301,13 +308,9 @@ func TestContainerStartsWithoutTheReaper(t *testing.T) { if err != nil { t.Fatal(err) } - filtersJSON := fmt.Sprintf(`{"label":{"%s":true}}`, TestcontainerLabelIsReaper) - f, err := filters.FromJSON(filtersJSON) - if err != nil { - t.Fatal(err) - } + resp, err := client.ContainerList(ctx, types.ContainerListOptions{ - Filters: f, + Filters: filters.NewArgs(filters.Arg("label", fmt.Sprintf("%s=%s", TestcontainerLabelSessionID, container.SessionID()))), }) if err != nil { t.Fatal(err) @@ -318,6 +321,7 @@ func TestContainerStartsWithoutTheReaper(t *testing.T) { } func TestContainerStartsWithTheReaper(t *testing.T) { + t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -353,6 +357,7 @@ func TestContainerStartsWithTheReaper(t *testing.T) { } func TestContainerTerminationResetsState(t *testing.T) { + t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -434,6 +439,7 @@ func TestContainerStopWithReaper(t *testing.T) { } func TestContainerTerminationWithReaper(t *testing.T) { + t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -471,6 +477,7 @@ func TestContainerTerminationWithReaper(t *testing.T) { } func TestContainerTerminationWithoutReaper(t *testing.T) { + t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -509,7 +516,9 @@ func TestContainerTerminationWithoutReaper(t *testing.T) { } func TestContainerTerminationRemovesDockerImage(t *testing.T) { + t.Parallel() t.Run("if not built from Dockerfile", func(t *testing.T) { + t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -540,6 +549,7 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { }) t.Run("if built from Dockerfile", func(t *testing.T) { + t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -579,6 +589,7 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { } func TestTwoContainersExposingTheSamePort(t *testing.T) { + t.Parallel() ctx := context.Background() nginxA, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: ContainerRequest{ @@ -654,6 +665,7 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { } func TestContainerCreation(t *testing.T) { + t.Parallel() ctx := context.Background() nginxPort := "80/tcp" @@ -712,6 +724,7 @@ func TestContainerCreation(t *testing.T) { } func TestContainerCreationWithName(t *testing.T) { + t.Parallel() ctx := context.Background() creationName := fmt.Sprintf("%s_%d", "test_container", time.Now().Unix()) @@ -774,6 +787,7 @@ func TestContainerCreationWithName(t *testing.T) { } func TestContainerCreationAndWaitForListeningPortLongEnough(t *testing.T) { + t.Parallel() ctx := context.Background() nginxPort := "80/tcp" @@ -811,7 +825,7 @@ func TestContainerCreationAndWaitForListeningPortLongEnough(t *testing.T) { } func TestContainerCreationTimesOut(t *testing.T) { - t.Skip("Wait needs to be fixed") + t.Parallel() ctx := context.Background() // delayed-nginx will wait 2s before opening port nginxC, err := GenericContainer(ctx, GenericContainerRequest{ @@ -834,7 +848,7 @@ func TestContainerCreationTimesOut(t *testing.T) { } func TestContainerRespondsWithHttp200ForIndex(t *testing.T) { - t.Skip("Wait needs to be fixed") + t.Parallel() ctx := context.Background() nginxPort := "80/tcp" @@ -873,7 +887,7 @@ func TestContainerRespondsWithHttp200ForIndex(t *testing.T) { } func TestContainerCreationTimesOutWithHttp(t *testing.T) { - t.Skip("Wait needs to be fixed") + t.Parallel() ctx := context.Background() // delayed-nginx will wait 2s before opening port nginxC, err := GenericContainer(ctx, GenericContainerRequest{ @@ -899,6 +913,7 @@ func TestContainerCreationTimesOutWithHttp(t *testing.T) { } func TestContainerCreationWaitsForLogContextTimeout(t *testing.T) { + t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "mysql:latest", @@ -920,6 +935,7 @@ func TestContainerCreationWaitsForLogContextTimeout(t *testing.T) { } func TestContainerCreationWaitsForLog(t *testing.T) { + t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "mysql:latest", @@ -965,6 +981,7 @@ func TestContainerCreationWaitsForLog(t *testing.T) { } func Test_BuildContainerFromDockerfile(t *testing.T) { + t.Parallel() t.Log("getting context") context := context.Background() t.Log("got context, creating container request") @@ -1021,6 +1038,7 @@ func Test_BuildContainerFromDockerfile(t *testing.T) { } func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { + t.Parallel() t.Log("getting ctx") ctx := context.Background() @@ -1078,6 +1096,7 @@ func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { } func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { + t.Parallel() rescueStdout := os.Stderr r, w, _ := os.Pipe() os.Stderr = w @@ -1124,6 +1143,7 @@ func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { } func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { + t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "mysql:latest", @@ -1148,6 +1168,7 @@ func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { } func TestContainerCreationWaitingForHostPort(t *testing.T) { + t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "nginx:1.17.6", @@ -1171,6 +1192,7 @@ func TestContainerCreationWaitingForHostPort(t *testing.T) { } func TestContainerCreationWaitingForHostPortWithoutBashThrowsAnError(t *testing.T) { + t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "nginx:1.17.6-alpine", @@ -1194,6 +1216,7 @@ func TestContainerCreationWaitingForHostPortWithoutBashThrowsAnError(t *testing. } func TestContainerCreationWaitsForLogAndPort(t *testing.T) { + t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "mysql:latest", @@ -1249,6 +1272,7 @@ func TestCMD(t *testing.T) { and it will be run when we run the container */ + t.Parallel() ctx := context.Background() req := ContainerRequest{ @@ -1278,6 +1302,7 @@ func TestEntrypoint(t *testing.T) { and it will be run when we run the container */ + t.Parallel() ctx := context.Background() req := ContainerRequest{ @@ -1486,6 +1511,7 @@ func ExampleContainer_MappedPort() { } func TestContainerCreationWithBindAndVolume(t *testing.T) { + t.Parallel() absPath, err := filepath.Abs("./testresources/hello.sh") if err != nil { t.Fatal(err) @@ -1538,6 +1564,7 @@ func TestContainerCreationWithBindAndVolume(t *testing.T) { } func TestContainerWithTmpFs(t *testing.T) { + t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "busybox", @@ -1588,7 +1615,9 @@ func TestContainerWithTmpFs(t *testing.T) { } func TestContainerNonExistentImage(t *testing.T) { + t.Parallel() t.Run("if the image not found don't propagate the error", func(t *testing.T) { + t.Parallel() _, err := GenericContainer(context.Background(), GenericContainerRequest{ ContainerRequest: ContainerRequest{ Image: "postgres:nonexistent-version", @@ -1604,6 +1633,7 @@ func TestContainerNonExistentImage(t *testing.T) { }) t.Run("the context cancellation is propagated to container creation", func(t *testing.T) { + t.Parallel() ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() _, err := GenericContainer(ctx, GenericContainerRequest{ @@ -1621,7 +1651,9 @@ func TestContainerNonExistentImage(t *testing.T) { } func TestContainerCustomPlatformImage(t *testing.T) { + t.Parallel() t.Run("error with a non-existent platform", func(t *testing.T) { + t.Parallel() nonExistentPlatform := "windows/arm12" ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() @@ -1644,6 +1676,7 @@ func TestContainerCustomPlatformImage(t *testing.T) { }) t.Run("specific platform should be propagated", func(t *testing.T) { + t.Parallel() ctx := context.Background() c, err := GenericContainer(ctx, GenericContainerRequest{ @@ -1678,6 +1711,7 @@ func TestContainerCustomPlatformImage(t *testing.T) { } func TestContainerWithCustomHostname(t *testing.T) { + t.Parallel() ctx := context.Background() name := fmt.Sprintf("some-nginx-%s-%d", t.Name(), rand.Int()) hostname := fmt.Sprintf("my-nginx-%s-%d", t.Name(), rand.Int()) @@ -1727,6 +1761,7 @@ func readHostname(t *testing.T, containerId string) string { } func TestDockerContainerCopyFileToContainer(t *testing.T) { + t.Parallel() ctx := context.Background() nginxC, err := GenericContainer(ctx, GenericContainerRequest{ @@ -1780,6 +1815,7 @@ func TestDockerContainerCopyToContainer(t *testing.T) { } func TestDockerContainerCopyFileFromContainer(t *testing.T) { + t.Parallel() fileContent, err := ioutil.ReadFile("./testresources/hello.sh") if err != nil { t.Fatal(err) @@ -1819,6 +1855,7 @@ func TestDockerContainerCopyFileFromContainer(t *testing.T) { } func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { + t.Parallel() ctx := context.Background() nginxC, err := GenericContainer(ctx, GenericContainerRequest{ @@ -1854,6 +1891,7 @@ func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { } func TestDockerContainerResources(t *testing.T) { + t.Parallel() ctx := context.Background() expected := []*units.Ulimit{ @@ -1897,6 +1935,7 @@ func TestDockerContainerResources(t *testing.T) { } func TestContainerWithReaperNetwork(t *testing.T) { + t.Parallel() ctx := context.Background() networks := []string{ "test_network_" + randomString(), @@ -1973,6 +2012,7 @@ func TestContainerRunningCheckingStatusCode(t *testing.T) { } func TestContainerWithUserID(t *testing.T) { + t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "alpine:latest", @@ -2003,6 +2043,7 @@ func TestContainerWithUserID(t *testing.T) { } func TestContainerWithNoUserID(t *testing.T) { + t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "alpine:latest", @@ -2034,6 +2075,7 @@ func TestContainerWithNoUserID(t *testing.T) { func TestGetGatewayIP(t *testing.T) { // When using docker-compose with DinD mode, and using host port or http wait strategy // It's need to invoke GetGatewayIP for get the host + t.Parallel() provider, err := NewDockerProvider(WithLogger(TestLogger(t))) if err != nil { t.Fatal(err) diff --git a/network.go b/network.go index 362d32a327..eac39a5cad 100644 --- a/network.go +++ b/network.go @@ -18,6 +18,16 @@ type Network interface { Remove(context.Context) error // removes the network } +type DefaultNetwork string + +func (n DefaultNetwork) ApplyGenericTo(opts *GenericProviderOptions) { + opts.DefaultNetwork = string(n) +} + +func (n DefaultNetwork) ApplyDockerTo(opts *DockerProviderOptions) { + opts.DefaultNetwork = string(n) +} + // NetworkRequest represents the parameters used to get a network type NetworkRequest struct { Driver string diff --git a/reaper.go b/reaper.go index 55c7ac2937..332c7e8f7e 100644 --- a/reaper.go +++ b/reaper.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "net" + "net/url" "os" "strings" "sync" @@ -23,7 +24,10 @@ const ( ReaperDefaultImage = "docker.io/testcontainers/ryuk:0.3.3" ) +type reaperContextKey string + var ( + dockerHostContextKey = reaperContextKey("docker_host") reaper *Reaper // We would like to create reaper only once mutex sync.Mutex ) @@ -34,13 +38,6 @@ type ReaperProvider interface { RunContainer(ctx context.Context, req ContainerRequest) (Container, error) } -// Reaper is used to start a sidecar container that cleans up resources -type Reaper struct { - Provider ReaperProvider - SessionID string - Endpoint string -} - // NewReaper creates a Reaper with a sessionID to identify containers and a provider to use func NewReaper(ctx context.Context, sessionID string, provider ReaperProvider, reaperImageName string) (*Reaper, error) { mutex.Lock() @@ -50,6 +47,8 @@ func NewReaper(ctx context.Context, sessionID string, provider ReaperProvider, r return reaper, nil } + dockerHost := extractDockerHost(ctx) + // Otherwise create a new one reaper = &Reaper{ Provider: provider, @@ -61,22 +60,20 @@ func NewReaper(ctx context.Context, sessionID string, provider ReaperProvider, r req := ContainerRequest{ Image: reaperImage(reaperImageName), ExposedPorts: []string{string(listeningPort)}, + NetworkMode: Bridge, Labels: map[string]string{ TestcontainerLabel: "true", TestcontainerLabelIsReaper: "true", }, SkipReaper: true, - Mounts: Mounts(BindMount( - coalesce(os.Getenv("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE"), "/var/run/docker.sock"), - "/var/run/docker.sock", - )), + Mounts: Mounts(BindMount(dockerHost, "/var/run/docker.sock")), AutoRemove: true, WaitingFor: wait.ForListeningPort(listeningPort), } // Attach reaper container to a requested network if it is specified if p, ok := provider.(*DockerProvider); ok { - req.Networks = append(req.Networks, p.defaultNetwork) + req.Networks = append(req.Networks, p.DefaultNetwork) } c, err := provider.RunContainer(ctx, req) @@ -93,12 +90,11 @@ func NewReaper(ctx context.Context, sessionID string, provider ReaperProvider, r return reaper, nil } -func reaperImage(reaperImageName string) string { - if reaperImageName == "" { - return ReaperDefaultImage - } else { - return reaperImageName - } +// Reaper is used to start a sidecar container that cleans up resources +type Reaper struct { + Provider ReaperProvider + SessionID string + Endpoint string } // Connect runs a goroutine which can be terminated by sending true into the returned channel @@ -150,9 +146,37 @@ func (r *Reaper) Labels() map[string]string { } } -func coalesce(text, fallback string) string { - if text == "" { - return fallback +func extractDockerHost(ctx context.Context) (dockerHostPath string) { + if dockerHostPath = os.Getenv("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE"); dockerHostPath != "" { + return dockerHostPath + } + + dockerHostPath = "/var/run/docker.sock" + + var hostRawURL string + if h, ok := ctx.Value(dockerHostContextKey).(string); !ok || h == "" { + return dockerHostPath + } else { + hostRawURL = h + } + var hostURL *url.URL + if u, err := url.Parse(hostRawURL); err != nil { + return dockerHostPath + } else { + hostURL = u + } + + switch hostURL.Scheme { + case "unix": + return hostURL.Path + default: + return dockerHostPath } - return text } + +func reaperImage(reaperImageName string) string { + if reaperImageName == "" { + return ReaperDefaultImage + } + return reaperImageName +} \ No newline at end of file From 9566d48dbf1e0c4f9cbfa3999241e7bcdb6fd611 Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Fri, 8 Apr 2022 10:28:28 +0200 Subject: [PATCH 191/219] Introduce Podman ProviderType to be able to set some provider specific defaults Set provider type for all docker_test.go test cases --- container.go | 11 +++- docker.go | 25 +++++--- docker_test.go | 160 ++++++++++++++++++++++++++++++++++--------------- 3 files changed, 139 insertions(+), 57 deletions(-) diff --git a/container.go b/container.go index 5a26798c7d..c1b425683d 100644 --- a/container.go +++ b/container.go @@ -135,6 +135,7 @@ func (f GenericProviderOptionFunc) ApplyGenericTo(opts *GenericProviderOptions) // possible provider types const ( ProviderDocker ProviderType = iota // Docker is default = 0 + ProviderPodman ) // GetProvider provides the provider implementation for a certain type @@ -149,7 +150,15 @@ func (t ProviderType) GetProvider(opts ...GenericProviderOption) (GenericProvide switch t { case ProviderDocker: - provider, err := NewDockerProvider(Generic2DockerOptions(opts...)...) + providerOptions := append(Generic2DockerOptions(opts...), WithDefaultBridgeNetwork(Bridge)) + provider, err := NewDockerProvider(providerOptions...) + if err != nil { + return nil, fmt.Errorf("%w, failed to create Docker provider", err) + } + return provider, nil + case ProviderPodman: + providerOptions := append(Generic2DockerOptions(opts...), WithDefaultBridgeNetwork(Podman)) + provider, err := NewDockerProvider(providerOptions...) if err != nil { return nil, fmt.Errorf("%w, failed to create Docker provider", err) } diff --git a/docker.go b/docker.go index e3984a22f8..9757d06aae 100644 --- a/docker.go +++ b/docker.go @@ -41,7 +41,8 @@ var ( ) const ( - Bridge = "bridge" // Bridge network name (as well as driver) + Bridge = "bridge" // Bridge network name (as well as driver) + Podman = "podman" ReaperDefault = "reaper_default" // Default network name when bridge is not available ) @@ -577,6 +578,7 @@ type TestContainersConfig struct { type ( // DockerProviderOptions defines options applicable to DockerProvider DockerProviderOptions struct { + defaultBridgeNetworkName string *GenericProviderOptions } @@ -610,6 +612,12 @@ func Generic2DockerOptions(opts ...GenericProviderOption) []DockerProviderOption return converted } +func WithDefaultBridgeNetwork(bridgeNetworkName string) DockerProviderOption { + return DockerProviderOptionFunc(func(opts *DockerProviderOptions) { + opts.defaultBridgeNetworkName = bridgeNetworkName + }) +} + // NewDockerProvider creates a Docker provider with the EnvClient func NewDockerProvider(provOpts ...DockerProviderOption) (*DockerProvider, error) { tcConfig := readTCPropsFile() @@ -744,7 +752,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque // Make sure that bridge network exists // In case it is disabled we will create reaper_default network if p.DefaultNetwork == "" { - p.DefaultNetwork, err = getDefaultNetwork(ctx, p.client) + p.DefaultNetwork, err = p.getDefaultNetwork(ctx, p.client) if err != nil { return nil, err } @@ -752,7 +760,8 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque // If default network is not bridge make sure it is attached to the request // as container won't be attached to it automatically - if p.DefaultNetwork != Bridge { + // in case of Podman the bridge network is called 'podman' as 'bridge' would conflict + if p.DefaultNetwork != p.defaultBridgeNetworkName { isAttached := false for _, net := range req.Networks { if net == p.DefaultNetwork { @@ -1045,7 +1054,7 @@ func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) // Make sure that bridge network exists // In case it is disabled we will create reaper_default network if p.DefaultNetwork == "" { - if p.DefaultNetwork, err = getDefaultNetwork(ctx, p.client); err != nil { + if p.DefaultNetwork, err = p.getDefaultNetwork(ctx, p.client); err != nil { return nil, err } } @@ -1115,7 +1124,7 @@ func (p *DockerProvider) GetGatewayIP(ctx context.Context) (string, error) { // Use a default network as defined in the DockerProvider if p.DefaultNetwork == "" { var err error - p.DefaultNetwork, err = getDefaultNetwork(ctx, p.client) + p.DefaultNetwork, err = p.getDefaultNetwork(ctx, p.client) if err != nil { return "", err } @@ -1163,7 +1172,7 @@ func getDefaultGatewayIP() (string, error) { return ip, nil } -func getDefaultNetwork(ctx context.Context, cli *client.Client) (string, error) { +func (p *DockerProvider) getDefaultNetwork(ctx context.Context, cli *client.Client) (string, error) { // Get list of available networks networkResources, err := cli.NetworkList(ctx, types.NetworkListOptions{}) if err != nil { @@ -1175,8 +1184,8 @@ func getDefaultNetwork(ctx context.Context, cli *client.Client) (string, error) reaperNetworkExists := false for _, net := range networkResources { - if net.Name == Bridge { - return Bridge, nil + if net.Name == p.defaultBridgeNetworkName { + return p.defaultBridgeNetworkName, nil } if net.Name == reaperNetwork { diff --git a/docker_test.go b/docker_test.go index 0aea7e621b..36c6061b74 100644 --- a/docker_test.go +++ b/docker_test.go @@ -40,13 +40,27 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) +const ( + nginxImage = "docker.io/nginx" + nginxAlpineImage = "docker.io/nginx:alpine" +) + +var providerType = ProviderDocker + +func init() { + if strings.Contains(os.Getenv("DOCKER_HOST"), "podman.sock") { + providerType = ProviderPodman + } +} + func TestContainerAttachedToNewNetwork(t *testing.T) { t.Parallel() networkName := "new-network" ctx := context.Background() gcr := GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ "80/tcp", }, @@ -62,6 +76,7 @@ func TestContainerAttachedToNewNetwork(t *testing.T) { } newNetwork, err := GenericNetwork(ctx, GenericNetworkRequest{ + ProviderType: providerType, NetworkRequest: NetworkRequest{ Name: networkName, CheckDuplicate: true, @@ -112,8 +127,9 @@ func TestContainerWithHostNetworkOptions(t *testing.T) { t.Parallel() ctx := context.Background() gcr := GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, Privileged: true, SkipReaper: true, NetworkMode: "host", @@ -152,8 +168,9 @@ func TestContainerWithNetworkModeAndNetworkTogether(t *testing.T) { t.Parallel() ctx := context.Background() gcr := GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, SkipReaper: true, NetworkMode: "host", Networks: []string{"new-network"}, @@ -172,9 +189,11 @@ func TestContainerWithNetworkModeAndNetworkTogether(t *testing.T) { func TestContainerWithHostNetworkOptionsAndWaitStrategy(t *testing.T) { t.Parallel() ctx := context.Background() + gcr := GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, SkipReaper: true, NetworkMode: "host", WaitingFor: wait.ForListeningPort("80/tcp"), @@ -205,8 +224,9 @@ func TestContainerWithHostNetworkAndEndpoint(t *testing.T) { nginxPort := "80/tcp" ctx := context.Background() gcr := GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, SkipReaper: true, NetworkMode: "host", WaitingFor: wait.ForListeningPort(nat.Port(nginxPort)), @@ -238,8 +258,9 @@ func TestContainerWithHostNetworkAndPortEndpoint(t *testing.T) { nginxPort := "80/tcp" ctx := context.Background() gcr := GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, SkipReaper: true, NetworkMode: "host", WaitingFor: wait.ForListeningPort(nat.Port(nginxPort)), @@ -270,8 +291,9 @@ func TestContainerReturnItsContainerID(t *testing.T) { t.Parallel() ctx := context.Background() nginxA, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ "80/tcp", }, @@ -296,8 +318,9 @@ func TestContainerStartsWithoutTheReaper(t *testing.T) { client.NegotiateAPIVersion(ctx) var container Container container, err = GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ "80/tcp", }, @@ -329,8 +352,9 @@ func TestContainerStartsWithTheReaper(t *testing.T) { } client.NegotiateAPIVersion(ctx) _, err = GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ "80/tcp", }, @@ -365,8 +389,9 @@ func TestContainerTerminationResetsState(t *testing.T) { } client.NegotiateAPIVersion(ctx) nginxA, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ "80/tcp", }, @@ -399,8 +424,9 @@ func TestContainerStopWithReaper(t *testing.T) { } client.NegotiateAPIVersion(ctx) nginxA, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ "80/tcp", }, @@ -447,8 +473,9 @@ func TestContainerTerminationWithReaper(t *testing.T) { } client.NegotiateAPIVersion(ctx) nginxA, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ "80/tcp", }, @@ -485,8 +512,9 @@ func TestContainerTerminationWithoutReaper(t *testing.T) { } client.NegotiateAPIVersion(ctx) nginxA, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ "80/tcp", }, @@ -526,8 +554,9 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { } client.NegotiateAPIVersion(ctx) container, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ "80/tcp", }, @@ -564,6 +593,7 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { WaitingFor: wait.ForLog("Ready to accept connections"), } container, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -592,8 +622,9 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { t.Parallel() ctx := context.Background() nginxA, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ "80/tcp", }, @@ -611,8 +642,9 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { }() nginxB, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ "80/tcp", }, @@ -670,8 +702,9 @@ func TestContainerCreation(t *testing.T) { nginxPort := "80/tcp" nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ nginxPort, }, @@ -731,8 +764,9 @@ func TestContainerCreationWithName(t *testing.T) { expectedName := "/" + creationName // inspect adds '/' in the beginning nginxPort := "80/tcp" nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ nginxPort, }, @@ -793,8 +827,9 @@ func TestContainerCreationAndWaitForListeningPortLongEnough(t *testing.T) { nginxPort := "80/tcp" // delayed-nginx will wait 2s before opening port nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "menedev/delayed-nginx:1.15.2", + Image: "docker.io/menedev/delayed-nginx:1.15.2", ExposedPorts: []string{ nginxPort, }, @@ -829,8 +864,9 @@ func TestContainerCreationTimesOut(t *testing.T) { ctx := context.Background() // delayed-nginx will wait 2s before opening port nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "menedev/delayed-nginx:1.15.2", + Image: "docker.io/menedev/delayed-nginx:1.15.2", ExposedPorts: []string{ "80/tcp", }, @@ -854,8 +890,9 @@ func TestContainerRespondsWithHttp200ForIndex(t *testing.T) { nginxPort := "80/tcp" // delayed-nginx will wait 2s before opening port nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{ nginxPort, }, @@ -891,8 +928,9 @@ func TestContainerCreationTimesOutWithHttp(t *testing.T) { ctx := context.Background() // delayed-nginx will wait 2s before opening port nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "menedev/delayed-nginx:1.15.2", + Image: "docker.io/menedev/delayed-nginx:1.15.2", ExposedPorts: []string{ "80/tcp", }, @@ -916,7 +954,7 @@ func TestContainerCreationWaitsForLogContextTimeout(t *testing.T) { t.Parallel() ctx := context.Background() req := ContainerRequest{ - Image: "mysql:latest", + Image: "docker.io/mysql:latest", ExposedPorts: []string{"3306/tcp", "33060/tcp"}, Env: map[string]string{ "MYSQL_ROOT_PASSWORD": "password", @@ -925,6 +963,7 @@ func TestContainerCreationWaitsForLogContextTimeout(t *testing.T) { WaitingFor: wait.ForLog("test context timeout").WithStartupTimeout(1 * time.Second), } _, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -938,7 +977,7 @@ func TestContainerCreationWaitsForLog(t *testing.T) { t.Parallel() ctx := context.Background() req := ContainerRequest{ - Image: "mysql:latest", + Image: "docker.io/mysql:latest", ExposedPorts: []string{"3306/tcp", "33060/tcp"}, Env: map[string]string{ "MYSQL_ROOT_PASSWORD": "password", @@ -947,6 +986,7 @@ func TestContainerCreationWaitsForLog(t *testing.T) { WaitingFor: wait.ForLog("port: 3306 MySQL Community Server - GPL"), } mysqlC, _ := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -996,6 +1036,7 @@ func Test_BuildContainerFromDockerfile(t *testing.T) { t.Log("creating generic container request from container request") genContainerReq := GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, } @@ -1058,6 +1099,7 @@ func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { } genContainerReq := GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, } @@ -1114,6 +1156,7 @@ func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { } genContainerReq := GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, } @@ -1146,7 +1189,7 @@ func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { t.Parallel() ctx := context.Background() req := ContainerRequest{ - Image: "mysql:latest", + Image: "docker.io/mysql:latest", ExposedPorts: []string{"3306/tcp", "33060/tcp"}, Env: map[string]string{ "MYSQL_ROOT_PASSWORD": "password", @@ -1158,6 +1201,7 @@ func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { ), } _, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -1171,11 +1215,12 @@ func TestContainerCreationWaitingForHostPort(t *testing.T) { t.Parallel() ctx := context.Background() req := ContainerRequest{ - Image: "nginx:1.17.6", + Image: nginxImage, ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForListeningPort("80/tcp"), } nginx, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -1195,11 +1240,12 @@ func TestContainerCreationWaitingForHostPortWithoutBashThrowsAnError(t *testing. t.Parallel() ctx := context.Background() req := ContainerRequest{ - Image: "nginx:1.17.6-alpine", + Image: nginxAlpineImage, ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForListeningPort("80/tcp"), } nginx, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -1219,7 +1265,7 @@ func TestContainerCreationWaitsForLogAndPort(t *testing.T) { t.Parallel() ctx := context.Background() req := ContainerRequest{ - Image: "mysql:latest", + Image: "docker.io/mysql:latest", ExposedPorts: []string{"3306/tcp", "33060/tcp"}, Env: map[string]string{ "MYSQL_ROOT_PASSWORD": "password", @@ -1232,6 +1278,7 @@ func TestContainerCreationWaitsForLogAndPort(t *testing.T) { } mysqlC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -1276,7 +1323,7 @@ func TestCMD(t *testing.T) { ctx := context.Background() req := ContainerRequest{ - Image: "alpine", + Image: "docker.io/alpine", WaitingFor: wait.ForAll( wait.ForLog("command override!"), ), @@ -1284,6 +1331,7 @@ func TestCMD(t *testing.T) { } c, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -1306,7 +1354,7 @@ func TestEntrypoint(t *testing.T) { ctx := context.Background() req := ContainerRequest{ - Image: "alpine", + Image: "docker.io/alpine", WaitingFor: wait.ForAll( wait.ForLog("entrypoint override!"), ), @@ -1314,6 +1362,7 @@ func TestEntrypoint(t *testing.T) { } c, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -1437,7 +1486,7 @@ func TestReadTCPropsFile(t *testing.T) { func ExampleDockerProvider_CreateContainer() { ctx := context.Background() req := ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/"), } @@ -1451,7 +1500,7 @@ func ExampleDockerProvider_CreateContainer() { func ExampleContainer_Host() { ctx := context.Background() req := ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/"), } @@ -1467,7 +1516,7 @@ func ExampleContainer_Host() { func ExampleContainer_Start() { ctx := context.Background() req := ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/"), } @@ -1481,7 +1530,7 @@ func ExampleContainer_Start() { func ExampleContainer_Stop() { ctx := context.Background() req := ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/"), } @@ -1496,7 +1545,7 @@ func ExampleContainer_Stop() { func ExampleContainer_MappedPort() { ctx := context.Background() req := ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/"), } @@ -1542,8 +1591,9 @@ func TestContainerCreationWithBindAndVolume(t *testing.T) { }() // Create the container that writes into the mounted volume. bashC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "bash", + Image: "docker.io/bash", Mounts: Mounts(BindMount(absPath, "/hello.sh"), VolumeMount(volumeName, "/data")), Cmd: []string{"bash", "/hello.sh"}, WaitingFor: wait.ForLog("done"), @@ -1567,12 +1617,13 @@ func TestContainerWithTmpFs(t *testing.T) { t.Parallel() ctx := context.Background() req := ContainerRequest{ - Image: "busybox", + Image: "docker.io/busybox", Cmd: []string{"sleep", "10"}, Tmpfs: map[string]string{"/testtmpfs": "rw"}, } container, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -1637,8 +1688,9 @@ func TestContainerNonExistentImage(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() _, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "postgres:12", + Image: "docker.io/postgres:12", WaitingFor: wait.ForLog("log"), SkipReaper: true, }, @@ -1658,8 +1710,9 @@ func TestContainerCustomPlatformImage(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() c, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "redis:latest", + Image: "docker.io/redis:latest", SkipReaper: true, ImagePlatform: nonExistentPlatform, }, @@ -1680,8 +1733,9 @@ func TestContainerCustomPlatformImage(t *testing.T) { ctx := context.Background() c, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "mysql:5.7", + Image: "docker.io/mysql:5.7", SkipReaper: true, ImagePlatform: "linux/amd64", }, @@ -1717,10 +1771,11 @@ func TestContainerWithCustomHostname(t *testing.T) { hostname := fmt.Sprintf("my-nginx-%s-%d", t.Name(), rand.Int()) req := ContainerRequest{ Name: name, - Image: "nginx", + Image: nginxImage, Hostname: hostname, } container, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -1765,8 +1820,9 @@ func TestDockerContainerCopyFileToContainer(t *testing.T) { ctx := context.Background() nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx:1.17.6", + Image: nginxImage, ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForListeningPort("80/tcp"), }, @@ -1789,8 +1845,9 @@ func TestDockerContainerCopyToContainer(t *testing.T) { ctx := context.Background() nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx:1.17.6", + Image: nginxImage, ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForListeningPort("80/tcp"), }, @@ -1823,8 +1880,9 @@ func TestDockerContainerCopyFileFromContainer(t *testing.T) { ctx := context.Background() nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx:1.17.6", + Image: nginxImage, ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForListeningPort("80/tcp"), }, @@ -1859,8 +1917,9 @@ func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { ctx := context.Background() nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx:1.17.6", + Image: nginxImage, ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForListeningPort("80/tcp"), }, @@ -1908,6 +1967,7 @@ func TestDockerContainerResources(t *testing.T) { } nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: ContainerRequest{ Image: "nginx", ExposedPorts: []string{"80/tcp"}, @@ -1948,13 +2008,14 @@ func TestContainerWithReaperNetwork(t *testing.T) { Attachable: true, } _, err := GenericNetwork(ctx, GenericNetworkRequest{ + ProviderType: providerType, NetworkRequest: nr, }) assert.Nil(t, err) } req := ContainerRequest{ - Image: "nginx", + Image: nginxImage, ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForAll( wait.ForListeningPort("80/tcp"), @@ -1964,6 +2025,7 @@ func TestContainerWithReaperNetwork(t *testing.T) { } nginxC, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -2015,12 +2077,13 @@ func TestContainerWithUserID(t *testing.T) { t.Parallel() ctx := context.Background() req := ContainerRequest{ - Image: "alpine:latest", + Image: "docker.io/alpine:latest", User: "60125", Cmd: []string{"sh", "-c", "id -u"}, WaitingFor: wait.ForExit(), } container, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) @@ -2046,11 +2109,12 @@ func TestContainerWithNoUserID(t *testing.T) { t.Parallel() ctx := context.Background() req := ContainerRequest{ - Image: "alpine:latest", + Image: "docker.io/alpine:latest", Cmd: []string{"sh", "-c", "id -u"}, WaitingFor: wait.ForExit(), } container, err := GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, ContainerRequest: req, Started: true, }) From 3bac82c7a29bab87a2649f47f13c3db5fcec795c Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Fri, 8 Apr 2022 10:30:45 +0200 Subject: [PATCH 192/219] Add Podman pipeline Failures during test execution are ignored for now. Passing all tests can be achieved over time. --- .github/workflows/ci-podman.yml | 69 +++++++++++++++++++++++++++++++++ .github/workflows/ci.yml | 12 +++--- 2 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/ci-podman.yml diff --git a/.github/workflows/ci-podman.yml b/.github/workflows/ci-podman.yml new file mode 100644 index 0000000000..65a3385c8a --- /dev/null +++ b/.github/workflows/ci-podman.yml @@ -0,0 +1,69 @@ +name: Podman pipeline + +on: [push, pull_request] + +jobs: + build: + strategy: + matrix: + go-version: [1.14.x, 1.15.x, 1.16.x, 1.17.x, 1.x] + runs-on: ubuntu-latest + steps: + - name: Set up Go 1.x + uses: actions/setup-go@v3 + with: + go-version: ${{ matrix.go-version }} + id: go + + - name: Check out code into the Go module directory + uses: actions/checkout@v3 + + - name: modVerify + run: go mod verify + + - name: modTidy + run: go mod tidy + + - name: ensure compilation + env: + GOOS: linux + run: go build + + - name: Enable systemd user process + run: | + loginctl enable-linger $(whoami) + sleep 1 + + - name: Set XDG_RUNTIME_DIR + run: echo "XDG_RUNTIME_DIR=/run/user/$UID" >> $GITHUB_ENV + + - name: Install Podman + run: | + set -x + sudo apt-get remove -y podman docker-ce docker docker-engine docker.io containerd runc ||: + curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_$( lsb_release -rs )/Release.key | sudo apt-key add - + echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_$( lsb_release -rs )/ /" | sudo tee /etc/apt/sources.list.d/podman.list /dev/null + sudo apt-get update + sudo apt-get install -y podman + sudo systemctl start podman + systemctl --user enable --now podman.socket + systemctl --user status podman.socket + podman info + + - name: Set DOCKER_HOST + run: echo "DOCKER_HOST=unix:///$XDG_RUNTIME_DIR/podman/podman.sock" >> $GITHUB_ENV + + - name: gotestsum + # only run tests on linux, there are a number of things that won't allow the tests to run on anything else + # many (maybe, all?) images used can only be build on Linux, they don't have Windows in their manifest, and + # we can't put Windows Server in "Linux Mode" in Github actions + # another, host mode is only available on Linux, and we have tests around that, do we skip them? + run: go run gotest.tools/gotestsum --format short-verbose -- -coverprofile=cover.txt ./... + continue-on-error: true + + # only report code coverage on linux + - name: Upload coverage report + uses: codecov/codecov-action@v2 + with: + files: ./cover.txt + name: testcontainers-podman-go-${{ matrix.go-version }} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b13f006bc..ad33843de0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,10 +4,10 @@ on: [push, pull_request] jobs: static-analysis: - runs-on: [ubuntu-latest] + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Run ShellCheck run: | shellcheck scripts/*.sh @@ -24,13 +24,13 @@ jobs: steps: - name: Set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: go-version: ${{ matrix.go-version }} id: go - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: modVerify run: go mod verify @@ -57,9 +57,9 @@ jobs: # only report code coverage on linux - name: Upload coverage report if: ${{ matrix.platform == 'ubuntu-latest' }} - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v2 with: - file: ./cover.txt + files: ./cover.txt name: testcontainers-go-${{ matrix.go-version }} - name: Run checker From fb47fbab52fe1ee3bd2e4b17064e7ec32285a8fd Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Fri, 8 Apr 2022 15:47:55 +0200 Subject: [PATCH 193/219] Make tests compatible with Podman --- .github/workflows/ci-podman.yml | 36 +- compose_test.go | 97 ++- container_test.go | 53 +- docker.go | 47 +- docker_test.go | 704 +++++++----------- logconsumer_test.go | 13 +- reaper.go | 6 +- testresources/Dockerfile | 2 +- testresources/args.Dockerfile | 2 +- testresources/buildlog.Dockerfile | 2 +- testresources/docker-compose-complex.yml | 4 +- .../docker-compose-container-name.yml | 2 +- .../docker-compose-no-exposed-ports.yml | 2 +- testresources/docker-compose-override.yml | 4 +- testresources/docker-compose-postgres.yml | 2 +- testresources/docker-compose-simple.yml | 2 +- testresources/docker-compose-volume.yml | 2 +- testresources/echo.Dockerfile | 2 +- testresources/echoserver.Dockerfile | 2 +- testresources/nginx-highport.conf | 43 ++ 20 files changed, 489 insertions(+), 538 deletions(-) create mode 100644 testresources/nginx-highport.conf diff --git a/.github/workflows/ci-podman.yml b/.github/workflows/ci-podman.yml index 65a3385c8a..b6e9e9b947 100644 --- a/.github/workflows/ci-podman.yml +++ b/.github/workflows/ci-podman.yml @@ -7,7 +7,7 @@ jobs: strategy: matrix: go-version: [1.14.x, 1.15.x, 1.16.x, 1.17.x, 1.x] - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Set up Go 1.x uses: actions/setup-go@v3 @@ -18,17 +18,6 @@ jobs: - name: Check out code into the Go module directory uses: actions/checkout@v3 - - name: modVerify - run: go mod verify - - - name: modTidy - run: go mod tidy - - - name: ensure compilation - env: - GOOS: linux - run: go build - - name: Enable systemd user process run: | loginctl enable-linger $(whoami) @@ -41,25 +30,26 @@ jobs: run: | set -x sudo apt-get remove -y podman docker-ce docker docker-engine docker.io containerd runc ||: - curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_$( lsb_release -rs )/Release.key | sudo apt-key add - - echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_$( lsb_release -rs )/ /" | sudo tee /etc/apt/sources.list.d/podman.list /dev/null - sudo apt-get update - sudo apt-get install -y podman - sudo systemctl start podman - systemctl --user enable --now podman.socket - systemctl --user status podman.socket - podman info + sudo apt update + sudo apt install -y software-properties-common debian-archive-keyring dirmngr + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 0E98404D386FA1D9 + sudo add-apt-repository -y "deb http://deb.debian.org/debian experimental main" + sudo apt update + sudo apt -y -t experimental install podman crun docker-compose + sudo systemctl daemon-reload + sleep 5 + sudo systemctl start podman.socket + sudo podman info - name: Set DOCKER_HOST - run: echo "DOCKER_HOST=unix:///$XDG_RUNTIME_DIR/podman/podman.sock" >> $GITHUB_ENV + run: echo "DOCKER_HOST=unix:///run/podman/podman.sock" >> $GITHUB_ENV - name: gotestsum # only run tests on linux, there are a number of things that won't allow the tests to run on anything else # many (maybe, all?) images used can only be build on Linux, they don't have Windows in their manifest, and # we can't put Windows Server in "Linux Mode" in Github actions # another, host mode is only available on Linux, and we have tests around that, do we skip them? - run: go run gotest.tools/gotestsum --format short-verbose -- -coverprofile=cover.txt ./... - continue-on-error: true + run: sudo go run gotest.tools/gotestsum --format short-verbose --rerun-fails=5 --packages="./..." -- -coverprofile=cover.txt # only report code coverage on linux - name: Upload coverage report diff --git a/compose_test.go b/compose_test.go index 792bd2950f..49d39c7f7d 100644 --- a/compose_test.go +++ b/compose_test.go @@ -1,12 +1,15 @@ package testcontainers import ( + "context" "fmt" - "os/exec" + "regexp" "strings" "testing" "time" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" "github.com/google/uuid" "github.com/stretchr/testify/assert" @@ -347,13 +350,11 @@ func TestLocalDockerComposeWithEnvironment(t *testing.T) { assert.Equal(t, 1, len(compose.Services)) assert.Contains(t, compose.Services, "nginx") - containerNameNginx := compose.Identifier + "_nginx_1" - present := map[string]string{ "bar": "BAR", } absent := map[string]string{} - assertContainerEnvironmentVariables(t, containerNameNginx, present, absent) + assertContainerEnvironmentVariables(t, compose.Identifier, "nginx", present, absent) } func TestLocalDockerComposeWithMultipleComposeFiles(t *testing.T) { @@ -386,17 +387,18 @@ func TestLocalDockerComposeWithMultipleComposeFiles(t *testing.T) { assert.Contains(t, compose.Services, "mysql") assert.Contains(t, compose.Services, "postgres") - containerNameNginx := compose.Identifier + "_nginx_1" - present := map[string]string{ "bar": "BAR", "foo": "FOO", } absent := map[string]string{} - assertContainerEnvironmentVariables(t, containerNameNginx, present, absent) + assertContainerEnvironmentVariables(t, compose.Identifier, "nginx", present, absent) } func TestLocalDockerComposeWithVolume(t *testing.T) { + if providerType == ProviderPodman { + t.Skip("fails for some reason with Podman") + } path := "./testresources/docker-compose-volume.yml" identifier := strings.ToLower(uuid.New().String()) @@ -405,7 +407,7 @@ func TestLocalDockerComposeWithVolume(t *testing.T) { destroyFn := func() { err := compose.Down() checkIfError(t, err) - assertVolumeDoesNotExist(t, fmt.Sprintf("%s_mydata", identifier)) + assertVolumeDoesNotExist(t, identifier, "mydata") } defer destroyFn() @@ -415,33 +417,79 @@ func TestLocalDockerComposeWithVolume(t *testing.T) { checkIfError(t, err) } -func assertVolumeDoesNotExist(t *testing.T, volume string) { - args := []string{"volume", "inspect", volume} +func assertVolumeDoesNotExist(tb testing.TB, composeIdentifier, volume string) { + containerClient, _, err := NewDockerClient() + if err != nil { + tb.Fatalf("Failed to get provider: %v", err) + } + + volumeList, err := containerClient.VolumeList(context.Background(), filters.NewArgs()) + if err != nil { + tb.Fatalf("Failed to list volumes: %v", err) + } - output, _ := executeAndGetOutput("docker", args) - if !strings.Contains(output, "No such volume") { - t.Fatalf("Expected volume %q to not exist", volume) + if len(volumeList.Warnings) > 0 { + tb.Logf("Volume list warnings: %v", volumeList.Warnings) + } + + volumeNameRegexp := regexp.MustCompile(fmt.Sprintf(`^\/?%s(_|-)%s$`, composeIdentifier, volume)) + + for i := range volumeList.Volumes { + if volumeNameRegexp.MatchString(volumeList.Volumes[i].Name) { + tb.Fatalf("Volume should not be present") + } } } -func assertContainerEnvironmentVariables(t *testing.T, containerName string, present map[string]string, absent map[string]string) { - args := []string{"exec", containerName, "env"} +func assertContainerEnvironmentVariables( + tb testing.TB, + composeIdentifier, serviceName string, + present map[string]string, + absent map[string]string, +) { + containerClient, _, err := NewDockerClient() + if err != nil { + tb.Fatalf("Failed to get provider: %v", err) + } + + containers, err := containerClient.ContainerList(context.Background(), types.ContainerListOptions{}) + if err != nil { + tb.Fatalf("Failed to list containers: %v", err) + } else if len(containers) == 0 { + tb.Fatalf("container list empty") + } - output, err := executeAndGetOutput("docker", args) - checkIfError(t, err) + containerNameRegexp := regexp.MustCompile(fmt.Sprintf(`^\/?%s(_|-)%s(_|-)\d$`, composeIdentifier, serviceName)) + var containerID string +containerLoop: + for i := range containers { + c := containers[i] + for j := range c.Names { + if containerNameRegexp.MatchString(c.Names[j]) { + containerID = c.ID + break containerLoop + } + } + } + + details, err := containerClient.ContainerInspect(context.Background(), containerID) + if err != nil { + tb.Fatalf("Failed to inspect container: %v", err) + } for k, v := range present { keyVal := k + "=" + v - assert.Contains(t, output, keyVal) + assert.Contains(tb, details.Config.Env, keyVal) } for k, v := range absent { keyVal := k + "=" + v - assert.NotContains(t, output, keyVal) + assert.NotContains(tb, details.Config.Env, keyVal) } } func checkIfError(t *testing.T, err ExecError) { + t.Helper() if err.Error != nil { t.Fatalf("Failed when running %v: %v", err.Command, err.Error) } @@ -457,14 +505,3 @@ func checkIfError(t *testing.T, err ExecError) { assert.NotNil(t, err.StdoutOutput) assert.NotNil(t, err.StderrOutput) } - -func executeAndGetOutput(command string, args []string) (string, ExecError) { - cmd := exec.Command(command, args...) - out, err := cmd.CombinedOutput() - - return string(out), ExecError{ - Error: err, - StderrOutput: out, - StdoutOutput: out, - } -} diff --git a/container_test.go b/container_test.go index f0a3239f40..4c43e489a7 100644 --- a/container_test.go +++ b/container_test.go @@ -26,7 +26,7 @@ func Test_ContainerValidation(t *testing.T) { } testTable := []ContainerValidationTestCase{ - ContainerValidationTestCase{ + { Name: "cannot set both context and image", ExpectedError: errors.New("you cannot specify both an Image and Context in a ContainerRequest"), ContainerRequest: ContainerRequest{ @@ -36,14 +36,14 @@ func Test_ContainerValidation(t *testing.T) { Image: "redis:latest", }, }, - ContainerValidationTestCase{ + { Name: "can set image without context", ExpectedError: nil, ContainerRequest: ContainerRequest{ Image: "redis:latest", }, }, - ContainerValidationTestCase{ + { Name: "can set context without image", ExpectedError: nil, ContainerRequest: ContainerRequest{ @@ -52,7 +52,7 @@ func Test_ContainerValidation(t *testing.T) { }, }, }, - ContainerValidationTestCase{ + { Name: "Can mount same source to multiple targets", ExpectedError: nil, ContainerRequest: ContainerRequest{ @@ -60,7 +60,7 @@ func Test_ContainerValidation(t *testing.T) { Mounts: Mounts(BindMount("/data", "/srv"), BindMount("/data", "/data")), }, }, - ContainerValidationTestCase{ + { Name: "Cannot mount multiple sources to same target", ExpectedError: errors.New("duplicate mount target detected: /data"), ContainerRequest: ContainerRequest{ @@ -128,6 +128,7 @@ func Test_GetDockerfile(t *testing.T) { } func Test_BuildImageWithContexts(t *testing.T) { + t.Parallel() type TestCase struct { Name string ContextPath string @@ -138,7 +139,7 @@ func Test_BuildImageWithContexts(t *testing.T) { } testCases := []TestCase{ - TestCase{ + { Name: "test build from context archive", ContextArchive: func() (io.Reader, error) { var buf bytes.Buffer @@ -149,8 +150,8 @@ func Test_BuildImageWithContexts(t *testing.T) { }{ { Name: "Dockerfile", - Contents: `FROM alpine - CMD ["echo", "this is from the archive"]`, + Contents: `FROM docker.io/alpine + CMD ["echo", "this is from the archive"]`, }, } @@ -182,7 +183,7 @@ func Test_BuildImageWithContexts(t *testing.T) { }, ExpectedEchoOutput: "this is from the archive", }, - TestCase{ + { Name: "test build from context archive and be able to use files in it", ContextArchive: func() (io.Reader, error) { var buf bytes.Buffer @@ -197,17 +198,17 @@ func Test_BuildImageWithContexts(t *testing.T) { }, { Name: "Dockerfile", - Contents: `FROM alpine - WORKDIR /app - COPY . . - CMD ["sh", "./say_hi.sh"]`, + Contents: `FROM docker.io/alpine + WORKDIR /app + COPY . . + CMD ["sh", "./say_hi.sh"]`, }, } for _, f := range files { header := tar.Header{ Name: f.Name, - Mode: 0777, + Mode: 0o0777, Size: int64(len(f.Contents)), Typeflag: tar.TypeReg, Format: tar.FormatGNU, @@ -232,7 +233,7 @@ func Test_BuildImageWithContexts(t *testing.T) { }, ExpectedEchoOutput: "hi this is from the say_hi.sh file!", }, - TestCase{ + { Name: "test buildling from a context on the filesystem", ContextPath: "./testresources", Dockerfile: "echo.Dockerfile", @@ -241,7 +242,7 @@ func Test_BuildImageWithContexts(t *testing.T) { return nil, nil }, }, - TestCase{ + { Name: "it should error if neither a context nor a context archive are specified", ContextPath: "", ContextArchive: func() (io.Reader, error) { @@ -252,7 +253,9 @@ func Test_BuildImageWithContexts(t *testing.T) { } for _, testCase := range testCases { + testCase := testCase t.Run(testCase.Name, func(t *testing.T) { + t.Parallel() ctx := context.Background() a, err := testCase.ContextArchive() if err != nil { @@ -280,16 +283,15 @@ func Test_BuildImageWithContexts(t *testing.T) { } else { c.Terminate(ctx) } - }) - } } func Test_GetLogsFromFailedContainer(t *testing.T) { + t.Parallel() ctx := context.Background() req := ContainerRequest{ - Image: "alpine", + Image: "docker.io/alpine", Cmd: []string{"echo", "-n", "I was not expecting this"}, WaitingFor: wait.ForLog("I was expecting this").WithStartupTimeout(5 * time.Second), } @@ -323,6 +325,7 @@ func Test_GetLogsFromFailedContainer(t *testing.T) { } func TestShouldStartContainersInParallel(t *testing.T) { + t.Parallel() ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) t.Cleanup(cancel) @@ -336,8 +339,8 @@ func TestShouldStartContainersInParallel(t *testing.T) { func createTestContainer(t *testing.T, ctx context.Context) int { req := ContainerRequest{ - Image: "nginx", - ExposedPorts: []string{"80/tcp"}, + Image: nginxAlpineImage, + ExposedPorts: []string{nginxDefaultPort}, WaitingFor: wait.ForHTTP("/"), } container, err := GenericContainer(ctx, GenericContainerRequest{ @@ -347,7 +350,7 @@ func createTestContainer(t *testing.T, ctx context.Context) int { if err != nil { t.Fatalf("could not start container: %v", err) } - port, err := container.MappedPort(ctx, "80") + port, err := container.MappedPort(ctx, nginxDefaultPort) if err != nil { t.Fatalf("could not get mapped port: %v", err) } @@ -360,6 +363,7 @@ func createTestContainer(t *testing.T, ctx context.Context) int { } func TestBindMount(t *testing.T) { + t.Parallel() type args struct { hostPath string mountTarget ContainerMountTarget @@ -381,13 +385,16 @@ func TestBindMount(t *testing.T) { }, } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() assert.Equalf(t, tt.want, BindMount(tt.args.hostPath, tt.args.mountTarget), "BindMount(%v, %v)", tt.args.hostPath, tt.args.mountTarget) }) } } func TestVolumeMount(t *testing.T) { + t.Parallel() type args struct { volumeName string mountTarget ContainerMountTarget @@ -409,7 +416,9 @@ func TestVolumeMount(t *testing.T) { }, } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { + t.Parallel() assert.Equalf(t, tt.want, VolumeMount(tt.args.volumeName, tt.args.mountTarget), "VolumeMount(%v, %v)", tt.args.volumeName, tt.args.mountTarget) }) } diff --git a/docker.go b/docker.go index 9757d06aae..754eb9fdb0 100644 --- a/docker.go +++ b/docker.go @@ -360,13 +360,6 @@ func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, io.Reade return 0, nil, err } - err = cli.ContainerExecStart(ctx, response.ID, types.ExecStartCheck{ - Detach: false, - }) - if err != nil { - return 0, nil, err - } - var exitCode int for { execResp, err := cli.ContainerExecInspect(ctx, response.ID) @@ -618,20 +611,9 @@ func WithDefaultBridgeNetwork(bridgeNetworkName string) DockerProviderOption { }) } -// NewDockerProvider creates a Docker provider with the EnvClient -func NewDockerProvider(provOpts ...DockerProviderOption) (*DockerProvider, error) { +func NewDockerClient() (cli *client.Client, host string, err error) { tcConfig := readTCPropsFile() - host := tcConfig.Host - - o := &DockerProviderOptions{ - GenericProviderOptions: &GenericProviderOptions{ - Logger: Logger, - }, - } - - for idx := range provOpts { - provOpts[idx].ApplyDockerTo(o) - } + host = tcConfig.Host opts := []client.Opt{client.FromEnv} if host != "" { @@ -651,7 +633,30 @@ func NewDockerProvider(provOpts ...DockerProviderOption) (*DockerProvider, error host = "unix:///var/run/docker.sock" } - c, err := client.NewClientWithOpts(opts...) + cli, err = client.NewClientWithOpts(opts...) + + if err != nil { + return nil, "", err + } + + cli.NegotiateAPIVersion(context.Background()) + + return cli, host, nil +} + +// NewDockerProvider creates a Docker provider with the EnvClient +func NewDockerProvider(provOpts ...DockerProviderOption) (*DockerProvider, error) { + o := &DockerProviderOptions{ + GenericProviderOptions: &GenericProviderOptions{ + Logger: Logger, + }, + } + + for idx := range provOpts { + provOpts[idx].ApplyDockerTo(o) + } + + c, host, err := NewDockerClient() if err != nil { return nil, err } diff --git a/docker_test.go b/docker_test.go index 36c6061b74..fa9d2f7f5e 100644 --- a/docker_test.go +++ b/docker_test.go @@ -3,14 +3,12 @@ package testcontainers import ( "context" "database/sql" - "encoding/json" "errors" "fmt" "io/ioutil" "math/rand" "net/http" "os" - "os/exec" "path/filepath" "regexp" "strings" @@ -34,7 +32,6 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/client" - "github.com/docker/go-connections/nat" "github.com/go-redis/redis" "github.com/testcontainers/testcontainers-go/wait" @@ -43,6 +40,8 @@ import ( const ( nginxImage = "docker.io/nginx" nginxAlpineImage = "docker.io/nginx:alpine" + nginxDefaultPort = "80/tcp" + nginxHighPort = "8080/tcp" ) var providerType = ProviderDocker @@ -54,23 +53,21 @@ func init() { } func TestContainerAttachedToNewNetwork(t *testing.T) { - t.Parallel() + aliases := []string{"alias1", "alias2", "alias3"} networkName := "new-network" ctx := context.Background() gcr := GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, Networks: []string{ networkName, }, NetworkAliases: map[string][]string{ - networkName: { - "alias1", "alias2", "alias3", - }, + networkName: aliases, }, }, } @@ -85,13 +82,14 @@ func TestContainerAttachedToNewNetwork(t *testing.T) { if err != nil { t.Fatal(err) } - defer newNetwork.Remove(ctx) + t.Cleanup(func() { + require.NoError(t, newNetwork.Remove(ctx)) + }) nginx, err := GenericContainer(ctx, gcr) - if err != nil { - t.Fatal(err) - } - defer nginx.Terminate(ctx) + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginx) networks, err := nginx.Networks(ctx) if err != nil { @@ -112,48 +110,49 @@ func TestContainerAttachedToNewNetwork(t *testing.T) { if len(networkAliases) != 1 { t.Errorf("Expected network aliases for 1 network. Got '%d'.", len(networkAliases)) } + networkAlias := networkAliases[networkName] - if len(networkAlias) != 3 { - t.Errorf("Expected network aliases %d. Got '%d'.", 3, len(networkAlias)) - } - if networkAlias[0] != "alias1" || networkAlias[1] != "alias2" || networkAlias[2] != "alias3" { - t.Errorf( - "Expected network aliases '%s', '%s' and '%s'. Got '%s', '%s' and '%s'.", - "alias1", "alias2", "alias3", networkAlias[0], networkAlias[1], networkAlias[2]) + + require.NotEmpty(t, networkAlias) + + for _, alias := range aliases { + require.Contains(t, networkAlias, alias) } } func TestContainerWithHostNetworkOptions(t *testing.T) { - t.Parallel() + absPath, err := filepath.Abs("./testresources/nginx-highport.conf") + if err != nil { + t.Fatal(err) + } + ctx := context.Background() gcr := GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, Privileged: true, SkipReaper: true, NetworkMode: "host", + Mounts: Mounts(BindMount(absPath, "/etc/nginx/conf.d/default.conf")), ExposedPorts: []string{ - "80/tcp", + nginxHighPort, }, - WaitingFor: wait.ForListeningPort("80/tcp"), + WaitingFor: wait.ForListeningPort(nginxHighPort), }, Started: true, } nginxC, err := GenericContainer(ctx, gcr) - if err != nil { - t.Fatal(err) - } - - defer nginxC.Terminate(ctx) + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) // host, err := nginxC.Host(ctx) // if err != nil { // t.Errorf("Expected host %s. Got '%d'.", host, err) // } // - endpoint, err := nginxC.Endpoint(ctx, "http") + endpoint, err := nginxC.PortEndpoint(ctx, nginxHighPort, "http") if err != nil { t.Errorf("Expected server endpoint. Got '%v'.", err) } @@ -187,95 +186,104 @@ func TestContainerWithNetworkModeAndNetworkTogether(t *testing.T) { } func TestContainerWithHostNetworkOptionsAndWaitStrategy(t *testing.T) { - t.Parallel() ctx := context.Background() + absPath, err := filepath.Abs("./testresources/nginx-highport.conf") + if err != nil { + t.Fatal(err) + } + gcr := GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, SkipReaper: true, NetworkMode: "host", - WaitingFor: wait.ForListeningPort("80/tcp"), + WaitingFor: wait.ForListeningPort(nginxHighPort), + Mounts: Mounts(BindMount(absPath, "/etc/nginx/conf.d/default.conf")), }, Started: true, } nginxC, err := GenericContainer(ctx, gcr) - if err != nil { - t.Fatal(err) - } - defer nginxC.Terminate(ctx) + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) host, err := nginxC.Host(ctx) if err != nil { t.Errorf("Expected host %s. Got '%d'.", host, err) } - _, err = http.Get("http://" + host + ":80") + _, err = http.Get("http://" + host + ":8080") if err != nil { - t.Errorf("Expected OK response. Got '%d'.", err) + t.Errorf("Expected OK response. Got '%v'.", err) } } func TestContainerWithHostNetworkAndEndpoint(t *testing.T) { - t.Parallel() - nginxPort := "80/tcp" ctx := context.Background() + + absPath, err := filepath.Abs("./testresources/nginx-highport.conf") + if err != nil { + t.Fatal(err) + } + gcr := GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, SkipReaper: true, NetworkMode: "host", - WaitingFor: wait.ForListeningPort(nat.Port(nginxPort)), + WaitingFor: wait.ForListeningPort(nginxHighPort), + Mounts: Mounts(BindMount(absPath, "/etc/nginx/conf.d/default.conf")), }, Started: true, } nginxC, err := GenericContainer(ctx, gcr) - if err != nil { - t.Fatal(err) - } - defer nginxC.Terminate(ctx) + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) - hostN, err := nginxC.Endpoint(ctx, "") + hostN, err := nginxC.PortEndpoint(ctx, nginxHighPort, "http") if err != nil { t.Errorf("Expected host %s. Got '%d'.", hostN, err) } t.Log(hostN) - _, err = http.Get("http://" + hostN) + _, err = http.Get(hostN) if err != nil { - t.Errorf("Expected OK response. Got '%d'.", err) + t.Errorf("Expected OK response. Got '%v'.", err) } } func TestContainerWithHostNetworkAndPortEndpoint(t *testing.T) { - t.Parallel() - nginxPort := "80/tcp" ctx := context.Background() + + absPath, err := filepath.Abs("./testresources/nginx-highport.conf") + if err != nil { + t.Fatal(err) + } + gcr := GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, SkipReaper: true, NetworkMode: "host", - WaitingFor: wait.ForListeningPort(nat.Port(nginxPort)), + WaitingFor: wait.ForListeningPort(nginxHighPort), + Mounts: Mounts(BindMount(absPath, "/etc/nginx/conf.d/default.conf")), }, Started: true, } nginxC, err := GenericContainer(ctx, gcr) - if err != nil { - t.Fatal(err) - } - defer nginxC.Terminate(ctx) + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) - origin, err := nginxC.PortEndpoint(ctx, nat.Port(nginxPort), "http") + origin, err := nginxC.PortEndpoint(ctx, nginxHighPort, "http") if err != nil { t.Errorf("Expected host %s. Got '%d'.", origin, err) } @@ -288,28 +296,26 @@ func TestContainerWithHostNetworkAndPortEndpoint(t *testing.T) { } func TestContainerReturnItsContainerID(t *testing.T) { - t.Parallel() ctx := context.Background() nginxA, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, }, }) - if err != nil { - t.Fatal(err) - } - defer nginxA.Terminate(ctx) + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxA) + if nginxA.GetContainerID() == "" { t.Errorf("expected a containerID but we got an empty string.") } } func TestContainerStartsWithoutTheReaper(t *testing.T) { - t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -320,17 +326,17 @@ func TestContainerStartsWithoutTheReaper(t *testing.T) { container, err = GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, SkipReaper: true, }, Started: true, }) - if err != nil { - t.Fatal(err) - } + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, container) resp, err := client.ContainerList(ctx, types.ContainerListOptions{ Filters: filters.NewArgs(filters.Arg("label", fmt.Sprintf("%s=%s", TestcontainerLabelSessionID, container.SessionID()))), @@ -344,7 +350,6 @@ func TestContainerStartsWithoutTheReaper(t *testing.T) { } func TestContainerStartsWithTheReaper(t *testing.T) { - t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -354,9 +359,9 @@ func TestContainerStartsWithTheReaper(t *testing.T) { _, err = GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, }, Started: true, @@ -381,19 +386,14 @@ func TestContainerStartsWithTheReaper(t *testing.T) { } func TestContainerTerminationResetsState(t *testing.T) { - t.Parallel() ctx := context.Background() - client, err := client.NewClientWithOpts(client.FromEnv) - if err != nil { - t.Fatal(err) - } - client.NegotiateAPIVersion(ctx) + nginxA, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, SkipReaper: true, }, @@ -426,19 +426,17 @@ func TestContainerStopWithReaper(t *testing.T) { nginxA, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, }, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - _ = nginxA.Terminate(ctx) - }() + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxA) + containerID := nginxA.GetContainerID() resp, err := client.ContainerInspect(ctx, containerID) if err != nil { @@ -475,9 +473,9 @@ func TestContainerTerminationWithReaper(t *testing.T) { nginxA, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, }, Started: true, @@ -514,9 +512,9 @@ func TestContainerTerminationWithoutReaper(t *testing.T) { nginxA, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, SkipReaper: true, }, @@ -544,9 +542,7 @@ func TestContainerTerminationWithoutReaper(t *testing.T) { } func TestContainerTerminationRemovesDockerImage(t *testing.T) { - t.Parallel() t.Run("if not built from Dockerfile", func(t *testing.T) { - t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -556,9 +552,9 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { container, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, SkipReaper: true, }, @@ -571,14 +567,13 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { if err != nil { t.Fatal(err) } - _, _, err = client.ImageInspectWithRaw(ctx, "nginx") + _, _, err = client.ImageInspectWithRaw(ctx, nginxAlpineImage) if err != nil { t.Fatal("nginx image should not have been removed") } }) t.Run("if built from Dockerfile", func(t *testing.T) { - t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -619,58 +614,40 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { } func TestTwoContainersExposingTheSamePort(t *testing.T) { - t.Parallel() ctx := context.Background() nginxA, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, }, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - err := nginxA.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - }() + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxA) nginxB, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, - WaitingFor: wait.ForListeningPort("80/tcp"), + WaitingFor: wait.ForListeningPort(nginxDefaultPort), }, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - err := nginxB.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - }() - ipA, err := nginxA.Host(ctx) - if err != nil { - t.Fatal(err) - } - portA, err := nginxA.MappedPort(ctx, "80/tcp") - if err != nil { - t.Fatal(err) - } - resp, err := http.Get(fmt.Sprintf("http://%s:%s", ipA, portA.Port())) + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxB) + + endpointA, err := nginxA.PortEndpoint(ctx, nginxDefaultPort, "http") + require.NoError(t, err) + + resp, err := http.Get(endpointA) if err != nil { t.Fatal(err) } @@ -678,16 +655,9 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { t.Errorf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) } - ipB, err := nginxB.Host(ctx) - if err != nil { - t.Fatal(err) - } - portB, err := nginxB.MappedPort(ctx, "80") - if err != nil { - t.Fatal(err) - } + endpointB, err := nginxB.PortEndpoint(ctx, nginxDefaultPort, "http") - resp, err = http.Get(fmt.Sprintf("http://%s:%s", ipB, portB.Port())) + resp, err = http.Get(endpointB) if err != nil { t.Fatal(err) } @@ -700,36 +670,25 @@ func TestContainerCreation(t *testing.T) { t.Parallel() ctx := context.Background() - nginxPort := "80/tcp" nginxC, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - nginxPort, + nginxDefaultPort, }, - WaitingFor: wait.ForListeningPort("80/tcp"), + WaitingFor: wait.ForListeningPort(nginxDefaultPort), }, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - err := nginxC.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - }() - ip, err := nginxC.Host(ctx) - if err != nil { - t.Fatal(err) - } - port, err := nginxC.MappedPort(ctx, "80") - if err != nil { - t.Fatal(err) - } - resp, err := http.Get(fmt.Sprintf("http://%s:%s", ip, port.Port())) + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) + + endpoint, err := nginxC.PortEndpoint(ctx, nginxDefaultPort, "http") + require.NoError(t, err) + + resp, err := http.Get(endpoint) if err != nil { t.Fatal(err) } @@ -762,29 +721,24 @@ func TestContainerCreationWithName(t *testing.T) { creationName := fmt.Sprintf("%s_%d", "test_container", time.Now().Unix()) expectedName := "/" + creationName // inspect adds '/' in the beginning - nginxPort := "80/tcp" + nginxC, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - nginxPort, + nginxDefaultPort, }, - WaitingFor: wait.ForListeningPort("80/tcp"), + WaitingFor: wait.ForListeningPort(nginxDefaultPort), Name: creationName, Networks: []string{"bridge"}, }, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - err := nginxC.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - }() + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) + name, err := nginxC.Name(ctx) if err != nil { t.Fatal(err) @@ -800,18 +754,21 @@ func TestContainerCreationWithName(t *testing.T) { t.Errorf("Expected networks 1. Got '%d'.", len(networks)) } network := networks[0] - if network != "bridge" { - t.Errorf("Expected network name '%s'. Got '%s'.", "bridge", network) - } - ip, err := nginxC.Host(ctx) - if err != nil { - t.Fatal(err) - } - port, err := nginxC.MappedPort(ctx, "80") - if err != nil { - t.Fatal(err) + switch providerType { + case ProviderDocker: + if network != Bridge { + t.Errorf("Expected network name '%s'. Got '%s'.", Bridge, network) + } + case ProviderPodman: + if network != Podman { + t.Errorf("Expected network name '%s'. Got '%s'.", Podman, network) + } } - resp, err := http.Get(fmt.Sprintf("http://%s:%s", ip, port.Port())) + + endpoint, err := nginxC.PortEndpoint(ctx, nginxDefaultPort, "http") + require.NoError(t, err) + + resp, err := http.Get(endpoint) if err != nil { t.Fatal(err) } @@ -824,29 +781,23 @@ func TestContainerCreationAndWaitForListeningPortLongEnough(t *testing.T) { t.Parallel() ctx := context.Background() - nginxPort := "80/tcp" // delayed-nginx will wait 2s before opening port nginxC, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ Image: "docker.io/menedev/delayed-nginx:1.15.2", ExposedPorts: []string{ - nginxPort, + nginxDefaultPort, }, - WaitingFor: wait.ForListeningPort("80"), // default startupTimeout is 60s + WaitingFor: wait.ForListeningPort(nginxDefaultPort), // default startupTimeout is 60s }, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - err := nginxC.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - }() - origin, err := nginxC.PortEndpoint(ctx, nat.Port(nginxPort), "http") + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) + + origin, err := nginxC.PortEndpoint(ctx, nginxDefaultPort, "http") if err != nil { t.Fatal(err) } @@ -868,9 +819,9 @@ func TestContainerCreationTimesOut(t *testing.T) { ContainerRequest: ContainerRequest{ Image: "docker.io/menedev/delayed-nginx:1.15.2", ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, - WaitingFor: wait.ForListeningPort("80").WithStartupTimeout(1 * time.Second), + WaitingFor: wait.ForListeningPort(nginxDefaultPort).WithStartupTimeout(1 * time.Second), }, Started: true, }) @@ -884,33 +835,25 @@ func TestContainerCreationTimesOut(t *testing.T) { } func TestContainerRespondsWithHttp200ForIndex(t *testing.T) { - t.Parallel() ctx := context.Background() - nginxPort := "80/tcp" // delayed-nginx will wait 2s before opening port nginxC, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: nginxImage, + Image: nginxAlpineImage, ExposedPorts: []string{ - nginxPort, + nginxDefaultPort, }, WaitingFor: wait.ForHTTP("/"), }, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - err := nginxC.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - }() - origin, err := nginxC.PortEndpoint(ctx, nat.Port(nginxPort), "http") + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) + + origin, err := nginxC.PortEndpoint(ctx, nginxDefaultPort, "http") if err != nil { t.Fatal(err) } @@ -932,18 +875,13 @@ func TestContainerCreationTimesOutWithHttp(t *testing.T) { ContainerRequest: ContainerRequest{ Image: "docker.io/menedev/delayed-nginx:1.15.2", ExposedPorts: []string{ - "80/tcp", + nginxDefaultPort, }, WaitingFor: wait.ForHTTP("/").WithStartupTimeout(1 * time.Second), }, Started: true, }) - defer func() { - err := nginxC.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - }() + terminateContainerOnEnd(t, ctx, nginxC) if err == nil { t.Error("Expected timeout") @@ -985,18 +923,14 @@ func TestContainerCreationWaitsForLog(t *testing.T) { }, WaitingFor: wait.ForLog("port: 3306 MySQL Community Server - GPL"), } - mysqlC, _ := GenericContainer(ctx, GenericContainerRequest{ + mysqlC, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: req, Started: true, }) - defer func() { - t.Log("terminating container") - err := mysqlC.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - }() + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, mysqlC) host, _ := mysqlC.Host(ctx) p, _ := mysqlC.MappedPort(ctx, "3306/tcp") @@ -1023,7 +957,7 @@ func TestContainerCreationWaitsForLog(t *testing.T) { func Test_BuildContainerFromDockerfile(t *testing.T) { t.Parallel() t.Log("getting context") - context := context.Background() + ctx := context.Background() t.Log("got context, creating container request") req := ContainerRequest{ FromDockerfile: FromDockerfile{ @@ -1043,21 +977,14 @@ func Test_BuildContainerFromDockerfile(t *testing.T) { t.Log("creating redis container") - redisC, err := GenericContainer(context, genContainerReq) + redisC, err := GenericContainer(ctx, genContainerReq) + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, redisC) t.Log("created redis container") - defer func() { - t.Log("terminating redis container") - err := redisC.Terminate(context) - if err != nil { - t.Fatal(err) - } - t.Log("terminated redis container") - }() - t.Log("getting redis container endpoint") - endpoint, err := redisC.Endpoint(context, "") + endpoint, err := redisC.Endpoint(ctx, "") if err != nil { t.Fatal(err) } @@ -1070,6 +997,7 @@ func Test_BuildContainerFromDockerfile(t *testing.T) { t.Log("pinging redis") pong, err := client.Ping().Result() + require.NoError(t, err) t.Log("received response from redis") @@ -1105,9 +1033,9 @@ func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { } c, err := GenericContainer(ctx, genContainerReq) - if err != nil { - t.Fatal(err) - } + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, c) ep, err := c.Endpoint(ctx, "http") if err != nil { @@ -1126,19 +1054,9 @@ func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { assert.Equal(t, 200, resp.StatusCode) assert.Equal(t, ba, string(body)) - - defer func() { - t.Log("terminating container") - err := c.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - t.Log("terminated container") - }() } func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { - t.Parallel() rescueStdout := os.Stderr r, w, _ := os.Pipe() os.Stderr = w @@ -1162,26 +1080,17 @@ func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { } c, err := GenericContainer(ctx, genContainerReq) - if err != nil { - t.Fatal(err) - } - defer func() { - t.Log("terminating container") - err := c.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - t.Log("terminated container") - }() + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, c) _ = w.Close() out, _ := ioutil.ReadAll(r) os.Stdout = rescueStdout temp := strings.Split(string(out), "\n") - if temp[0] != "Step 1/1 : FROM alpine" { - t.Errorf("Expected stout firstline to be %s. Got '%s'.", "Step 1/2 : FROM alpine", temp[0]) + if !regexp.MustCompile(`(?i)^Step\s*1/1\s*:\s*FROM docker.io/alpine$`).MatchString(temp[0]) { + t.Errorf("Expected stdout firstline to be %s. Got '%s'.", "Step 1/1 : FROM docker.io/alpine", temp[0]) } } @@ -1215,25 +1124,18 @@ func TestContainerCreationWaitingForHostPort(t *testing.T) { t.Parallel() ctx := context.Background() req := ContainerRequest{ - Image: nginxImage, - ExposedPorts: []string{"80/tcp"}, - WaitingFor: wait.ForListeningPort("80/tcp"), + Image: nginxAlpineImage, + ExposedPorts: []string{nginxDefaultPort}, + WaitingFor: wait.ForListeningPort(nginxDefaultPort), } nginx, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: req, Started: true, }) - defer func() { - err := nginx.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - t.Log("terminated nginx container") - }() - if err != nil { - t.Fatal(err) - } + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginx) } func TestContainerCreationWaitingForHostPortWithoutBashThrowsAnError(t *testing.T) { @@ -1241,24 +1143,17 @@ func TestContainerCreationWaitingForHostPortWithoutBashThrowsAnError(t *testing. ctx := context.Background() req := ContainerRequest{ Image: nginxAlpineImage, - ExposedPorts: []string{"80/tcp"}, - WaitingFor: wait.ForListeningPort("80/tcp"), + ExposedPorts: []string{nginxDefaultPort}, + WaitingFor: wait.ForListeningPort(nginxDefaultPort), } nginx, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: req, Started: true, }) - defer func() { - err := nginx.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - t.Log("terminated nginx container") - }() - if err != nil { - t.Fatal(err) - } + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginx) } func TestContainerCreationWaitsForLogAndPort(t *testing.T) { @@ -1282,17 +1177,9 @@ func TestContainerCreationWaitsForLogAndPort(t *testing.T) { ContainerRequest: req, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - t.Log("terminating container") - err := mysqlC.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - }() + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, mysqlC) host, _ := mysqlC.Host(ctx) p, _ := mysqlC.MappedPort(ctx, "3306/tcp") @@ -1335,12 +1222,9 @@ func TestCMD(t *testing.T) { ContainerRequest: req, Started: true, }) - if err != nil { - t.Fatal(err) - } - // defer not needed, but keeping it in for consistency - defer c.Terminate(ctx) + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, c) } func TestEntrypoint(t *testing.T) { @@ -1366,12 +1250,9 @@ func TestEntrypoint(t *testing.T) { ContainerRequest: req, Started: true, }) - if err != nil { - t.Fatal(err) - } - // defer not needed, but keeping it in for consistency - defer c.Terminate(ctx) + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, c) } func TestReadTCPropsFile(t *testing.T) { @@ -1486,7 +1367,7 @@ func TestReadTCPropsFile(t *testing.T) { func ExampleDockerProvider_CreateContainer() { ctx := context.Background() req := ContainerRequest{ - Image: nginxImage, + Image: "docker.io/nginx:alpine", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/"), } @@ -1500,7 +1381,7 @@ func ExampleDockerProvider_CreateContainer() { func ExampleContainer_Host() { ctx := context.Background() req := ContainerRequest{ - Image: nginxImage, + Image: "docker.io/nginx:alpine", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/"), } @@ -1516,7 +1397,7 @@ func ExampleContainer_Host() { func ExampleContainer_Start() { ctx := context.Background() req := ContainerRequest{ - Image: nginxImage, + Image: "docker.io/nginx:alpine", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/"), } @@ -1530,7 +1411,7 @@ func ExampleContainer_Start() { func ExampleContainer_Stop() { ctx := context.Background() req := ContainerRequest{ - Image: nginxImage, + Image: "docker.io/nginx:alpine", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/"), } @@ -1545,7 +1426,7 @@ func ExampleContainer_Stop() { func ExampleContainer_MappedPort() { ctx := context.Background() req := ContainerRequest{ - Image: nginxImage, + Image: "docker.io/nginx:alpine", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/"), } @@ -1568,11 +1449,11 @@ func TestContainerCreationWithBindAndVolume(t *testing.T) { ctx, cnl := context.WithTimeout(context.Background(), 30*time.Second) defer cnl() // Create a Docker client. - dockerCli, err := client.NewClientWithOpts(client.FromEnv) + dockerCli, _, err := NewDockerClient() if err != nil { t.Fatal(err) } - dockerCli.NegotiateAPIVersion(ctx) + // Create the volume. vol, err := dockerCli.VolumeCreate(ctx, volume.VolumeCreateBody{ Driver: "local", @@ -1581,14 +1462,14 @@ func TestContainerCreationWithBindAndVolume(t *testing.T) { t.Fatal(err) } volumeName := vol.Name - defer func() { + t.Cleanup(func() { ctx, cnl := context.WithTimeout(context.Background(), 5*time.Second) defer cnl() err := dockerCli.VolumeRemove(ctx, volumeName, true) if err != nil { t.Fatal(err) } - }() + }) // Create the container that writes into the mounted volume. bashC, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, @@ -1600,17 +1481,9 @@ func TestContainerCreationWithBindAndVolume(t *testing.T) { }, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - ctx, cnl := context.WithTimeout(context.Background(), 5*time.Second) - defer cnl() - err := bashC.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - }() + + require.NoError(t, err) + require.NoError(t, bashC.Terminate(ctx)) } func TestContainerWithTmpFs(t *testing.T) { @@ -1627,16 +1500,9 @@ func TestContainerWithTmpFs(t *testing.T) { ContainerRequest: req, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - t.Log("terminating container") - err := container.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - }() + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, container) path := "/testtmpfs/test.file" @@ -1666,9 +1532,7 @@ func TestContainerWithTmpFs(t *testing.T) { } func TestContainerNonExistentImage(t *testing.T) { - t.Parallel() t.Run("if the image not found don't propagate the error", func(t *testing.T) { - t.Parallel() _, err := GenericContainer(context.Background(), GenericContainerRequest{ ContainerRequest: ContainerRequest{ Image: "postgres:nonexistent-version", @@ -1684,7 +1548,6 @@ func TestContainerNonExistentImage(t *testing.T) { }) t.Run("the context cancellation is propagated to container creation", func(t *testing.T) { - t.Parallel() ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() _, err := GenericContainer(ctx, GenericContainerRequest{ @@ -1703,6 +1566,9 @@ func TestContainerNonExistentImage(t *testing.T) { } func TestContainerCustomPlatformImage(t *testing.T) { + if providerType == ProviderPodman { + t.Skip("Incompatible Docker API version for Podman") + } t.Parallel() t.Run("error with a non-existent platform", func(t *testing.T) { t.Parallel() @@ -1742,15 +1608,10 @@ func TestContainerCustomPlatformImage(t *testing.T) { Started: false, }) - t.Cleanup(func() { - if c != nil { - c.Terminate(ctx) - } - }) - - assert.NoError(t, err) + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, c) - dockerCli, err := client.NewEnvClient() + dockerCli, _, err := NewDockerClient() require.NoError(t, err) dockerCli.NegotiateAPIVersion(ctx) @@ -1779,40 +1640,27 @@ func TestContainerWithCustomHostname(t *testing.T) { ContainerRequest: req, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - t.Log("terminating container") - err := container.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - }() + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, container) + if actualHostname := readHostname(t, container.GetContainerID()); actualHostname != hostname { t.Fatalf("expected hostname %s, got %s", hostname, actualHostname) } } -// TODO: replace with proper API call -func readHostname(t *testing.T, containerId string) string { - command := exec.Command("curl", - "--silent", - "--unix-socket", - "/var/run/docker.sock", - fmt.Sprintf("http://localhost/containers/%s/json", containerId)) - - output, err := command.CombinedOutput() +func readHostname(tb testing.TB, containerId string) string { + containerClient, _, err := NewDockerClient() if err != nil { - t.Fatal(err) + tb.Fatalf("Failed to create Docker client: %v", err) } - var data map[string]interface{} - err = json.Unmarshal(output, &data) + + containerDetails, err := containerClient.ContainerInspect(context.Background(), containerId) if err != nil { - t.Fatal(err) + tb.Fatalf("Failed to inspect container: %v", err) } - config := data["Config"].(map[string]interface{}) - return config["Hostname"].(string) + + return containerDetails.Config.Hostname } func TestDockerContainerCopyFileToContainer(t *testing.T) { @@ -1823,12 +1671,14 @@ func TestDockerContainerCopyFileToContainer(t *testing.T) { ProviderType: providerType, ContainerRequest: ContainerRequest{ Image: nginxImage, - ExposedPorts: []string{"80/tcp"}, - WaitingFor: wait.ForListeningPort("80/tcp"), + ExposedPorts: []string{nginxDefaultPort}, + WaitingFor: wait.ForListeningPort(nginxDefaultPort), }, Started: true, }) - defer nginxC.Terminate(ctx) + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) copiedFileName := "hello_copy.sh" _ = nginxC.CopyFileToContainer(ctx, "./testresources/hello.sh", "/"+copiedFileName, 700) @@ -1848,12 +1698,14 @@ func TestDockerContainerCopyToContainer(t *testing.T) { ProviderType: providerType, ContainerRequest: ContainerRequest{ Image: nginxImage, - ExposedPorts: []string{"80/tcp"}, - WaitingFor: wait.ForListeningPort("80/tcp"), + ExposedPorts: []string{nginxDefaultPort}, + WaitingFor: wait.ForListeningPort(nginxDefaultPort), }, Started: true, }) - defer nginxC.Terminate(ctx) + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) copiedFileName := "hello_copy.sh" @@ -1883,12 +1735,14 @@ func TestDockerContainerCopyFileFromContainer(t *testing.T) { ProviderType: providerType, ContainerRequest: ContainerRequest{ Image: nginxImage, - ExposedPorts: []string{"80/tcp"}, - WaitingFor: wait.ForListeningPort("80/tcp"), + ExposedPorts: []string{nginxDefaultPort}, + WaitingFor: wait.ForListeningPort(nginxDefaultPort), }, Started: true, }) - defer nginxC.Terminate(ctx) + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) copiedFileName := "hello_copy.sh" _ = nginxC.CopyFileToContainer(ctx, "./testresources/hello.sh", "/"+copiedFileName, 700) @@ -1913,19 +1767,20 @@ func TestDockerContainerCopyFileFromContainer(t *testing.T) { } func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { - t.Parallel() ctx := context.Background() nginxC, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ Image: nginxImage, - ExposedPorts: []string{"80/tcp"}, - WaitingFor: wait.ForListeningPort("80/tcp"), + ExposedPorts: []string{nginxDefaultPort}, + WaitingFor: wait.ForListeningPort(nginxDefaultPort), }, Started: true, }) - defer nginxC.Terminate(ctx) + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) copiedFileName := "hello_copy.sh" _ = nginxC.CopyFileToContainer(ctx, "./testresources/empty.sh", "/"+copiedFileName, 700) @@ -1950,6 +1805,10 @@ func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { } func TestDockerContainerResources(t *testing.T) { + if providerType == ProviderPodman { + t.Skip("Rootless Podman does not support setting rlimit") + } + t.Parallel() ctx := context.Background() @@ -1969,18 +1828,18 @@ func TestDockerContainerResources(t *testing.T) { nginxC, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "nginx", - ExposedPorts: []string{"80/tcp"}, - WaitingFor: wait.ForListeningPort("80/tcp"), + Image: nginxAlpineImage, + ExposedPorts: []string{nginxDefaultPort}, + WaitingFor: wait.ForListeningPort(nginxDefaultPort), Resources: container.Resources{ Ulimits: expected, }, }, Started: true, }) - require.NoError(t, err) - defer nginxC.Terminate(ctx) + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) c, err := client.NewClientWithOpts(client.FromEnv) require.NoError(t, err) @@ -2015,10 +1874,10 @@ func TestContainerWithReaperNetwork(t *testing.T) { } req := ContainerRequest{ - Image: nginxImage, - ExposedPorts: []string{"80/tcp"}, + Image: nginxAlpineImage, + ExposedPorts: []string{nginxDefaultPort}, WaitingFor: wait.ForAll( - wait.ForListeningPort("80/tcp"), + wait.ForListeningPort(nginxDefaultPort), wait.ForLog("Configuration complete; ready for start up"), ), Networks: networks, @@ -2030,13 +1889,9 @@ func TestContainerWithReaperNetwork(t *testing.T) { Started: true, }) - defer func() { - t.Log("terminating container") - err := nginxC.Terminate(ctx) - assert.Nil(t, err) - }() + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, nginxC) - assert.Nil(t, err) containerId := nginxC.GetContainerID() cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) @@ -2087,10 +1942,9 @@ func TestContainerWithUserID(t *testing.T) { ContainerRequest: req, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer container.Terminate(ctx) + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, container) r, err := container.Logs(ctx) if err != nil { @@ -2118,10 +1972,9 @@ func TestContainerWithNoUserID(t *testing.T) { ContainerRequest: req, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer container.Terminate(ctx) + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, container) r, err := container.Logs(ctx) if err != nil { @@ -2140,11 +1993,11 @@ func TestGetGatewayIP(t *testing.T) { // When using docker-compose with DinD mode, and using host port or http wait strategy // It's need to invoke GetGatewayIP for get the host t.Parallel() - provider, err := NewDockerProvider(WithLogger(TestLogger(t))) + provider, err := providerType.GetProvider(WithLogger(TestLogger(t))) if err != nil { t.Fatal(err) } - ip, err := provider.GetGatewayIP(context.Background()) + ip, err := provider.(*DockerProvider).GetGatewayIP(context.Background()) if err != nil { t.Fatal(err) } @@ -2153,6 +2006,17 @@ func TestGetGatewayIP(t *testing.T) { } } +func terminateContainerOnEnd(tb testing.TB, ctx context.Context, ctr Container) { + tb.Helper() + if ctr == nil { + return + } + tb.Cleanup(func() { + tb.Log("terminating container") + require.NoError(tb, ctr.Terminate(ctx)) + }) +} + func randomString() string { rand.Seed(time.Now().UnixNano()) chars := []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + diff --git a/logconsumer_test.go b/logconsumer_test.go index 76cd616fe8..d5383fbbd1 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" "gotest.tools/v3/assert" "github.com/docker/docker/client" @@ -186,6 +187,9 @@ func Test_ShouldRecognizeLogTypes(t *testing.T) { } func TestContainerLogWithErrClosed(t *testing.T) { + if providerType == ProviderPodman { + t.Skip("Docker-in-Docker does not work with rootless Podman") + } // First spin up a docker-in-docker container, then spin up an inner container within that dind container // Logs are being read from the inner container via the dind container's tcp port, which can be briefly // closed to test behaviour in connection-closed situations. @@ -194,17 +198,16 @@ func TestContainerLogWithErrClosed(t *testing.T) { dind, err := GenericContainer(ctx, GenericContainerRequest{ Started: true, ContainerRequest: ContainerRequest{ - Image: "docker:dind", + Image: "docker.io/docker:dind", ExposedPorts: []string{"2375/tcp"}, Env: map[string]string{"DOCKER_TLS_CERTDIR": ""}, WaitingFor: wait.ForListeningPort("2375/tcp"), Privileged: true, }, }) - if err != nil { - t.Fatal("create generic container:", err) - } - defer dind.Terminate(ctx) + + require.NoError(t, err) + terminateContainerOnEnd(t, ctx, dind) var remoteDocker string diff --git a/reaper.go b/reaper.go index 332c7e8f7e..aaab2508f3 100644 --- a/reaper.go +++ b/reaper.go @@ -28,8 +28,8 @@ type reaperContextKey string var ( dockerHostContextKey = reaperContextKey("docker_host") - reaper *Reaper // We would like to create reaper only once - mutex sync.Mutex + reaper *Reaper // We would like to create reaper only once + mutex sync.Mutex ) // ReaperProvider represents a provider for the reaper to run itself with @@ -179,4 +179,4 @@ func reaperImage(reaperImageName string) string { return ReaperDefaultImage } return reaperImageName -} \ No newline at end of file +} diff --git a/testresources/Dockerfile b/testresources/Dockerfile index 9bc1feaac6..bf302c6240 100644 --- a/testresources/Dockerfile +++ b/testresources/Dockerfile @@ -1 +1 @@ -FROM redis:5.0-alpine \ No newline at end of file +FROM docker.io/redis:5.0-alpine \ No newline at end of file diff --git a/testresources/args.Dockerfile b/testresources/args.Dockerfile index 0260639719..984ef51eee 100644 --- a/testresources/args.Dockerfile +++ b/testresources/args.Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.13-alpine +FROM docker.io/golang:1.13-alpine ARG FOO diff --git a/testresources/buildlog.Dockerfile b/testresources/buildlog.Dockerfile index 67fd379018..0a9bc82c98 100644 --- a/testresources/buildlog.Dockerfile +++ b/testresources/buildlog.Dockerfile @@ -1 +1 @@ -FROM alpine +FROM docker.io/alpine diff --git a/testresources/docker-compose-complex.yml b/testresources/docker-compose-complex.yml index c2ea772466..7694a467ac 100644 --- a/testresources/docker-compose-complex.yml +++ b/testresources/docker-compose-complex.yml @@ -1,11 +1,11 @@ version: '3' services: nginx: - image: nginx:stable-alpine + image: docker.io/nginx:stable-alpine ports: - "9080:80" mysql: - image: mysql:5.7 + image: docker.io/mysql:5.7 environment: - MYSQL_DATABASE=db - MYSQL_ROOT_PASSWORD=my-secret-pw diff --git a/testresources/docker-compose-container-name.yml b/testresources/docker-compose-container-name.yml index 99525f7f7a..db54e1d82f 100644 --- a/testresources/docker-compose-container-name.yml +++ b/testresources/docker-compose-container-name.yml @@ -2,7 +2,7 @@ version: '3' services: nginx: container_name: nginxy - image: nginx:stable-alpine + image: docker.io/nginx:stable-alpine environment: bar: ${bar} ports: diff --git a/testresources/docker-compose-no-exposed-ports.yml b/testresources/docker-compose-no-exposed-ports.yml index ba8565c512..d1e27913e1 100644 --- a/testresources/docker-compose-no-exposed-ports.yml +++ b/testresources/docker-compose-no-exposed-ports.yml @@ -1,6 +1,6 @@ version: '3' services: nginx: - image: nginx:stable-alpine + image: docker.io/nginx:stable-alpine ports: - "80" diff --git a/testresources/docker-compose-override.yml b/testresources/docker-compose-override.yml index 36727f0e30..87cc7e4722 100644 --- a/testresources/docker-compose-override.yml +++ b/testresources/docker-compose-override.yml @@ -1,13 +1,13 @@ version: '3' services: nginx: - image: nginx:stable-alpine + image: docker.io/nginx:stable-alpine environment: bar: ${bar} foo: ${foo} ports: - "9080:80" mysql: - image: mysql:5.6 + image: docker.io/mysql:5.6 ports: - "13306:3306" diff --git a/testresources/docker-compose-postgres.yml b/testresources/docker-compose-postgres.yml index 74041af503..47c720560d 100644 --- a/testresources/docker-compose-postgres.yml +++ b/testresources/docker-compose-postgres.yml @@ -1,6 +1,6 @@ version: '3' services: postgres: - image: postgres:14 + image: docker.io/postgres:14 ports: - "15432:5432" diff --git a/testresources/docker-compose-simple.yml b/testresources/docker-compose-simple.yml index 347e25d159..104f6c7484 100644 --- a/testresources/docker-compose-simple.yml +++ b/testresources/docker-compose-simple.yml @@ -1,7 +1,7 @@ version: '3' services: nginx: - image: nginx:stable-alpine + image: docker.io/nginx:stable-alpine environment: bar: ${bar} ports: diff --git a/testresources/docker-compose-volume.yml b/testresources/docker-compose-volume.yml index df31ee2a33..cc14090c53 100644 --- a/testresources/docker-compose-volume.yml +++ b/testresources/docker-compose-volume.yml @@ -1,7 +1,7 @@ version: '3' services: nginx: - image: nginx:stable-alpine + image: docker.io/nginx:stable-alpine volumes: - type: volume source: mydata diff --git a/testresources/echo.Dockerfile b/testresources/echo.Dockerfile index 36951e1aa6..10ab9febf4 100644 --- a/testresources/echo.Dockerfile +++ b/testresources/echo.Dockerfile @@ -1,3 +1,3 @@ -FROM alpine +FROM docker.io/alpine CMD ["echo", "this is from the echo test Dockerfile"] \ No newline at end of file diff --git a/testresources/echoserver.Dockerfile b/testresources/echoserver.Dockerfile index aaf835f35a..546489ffac 100644 --- a/testresources/echoserver.Dockerfile +++ b/testresources/echoserver.Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.13-alpine +FROM docker.io/golang:1.13-alpine WORKDIR /app diff --git a/testresources/nginx-highport.conf b/testresources/nginx-highport.conf new file mode 100644 index 0000000000..557e63f044 --- /dev/null +++ b/testresources/nginx-highport.conf @@ -0,0 +1,43 @@ +server { + listen 8080; + server_name localhost; + + #access_log /var/log/nginx/host.access.log main; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + #location ~ \.php$ { + # root html; + # fastcgi_pass 127.0.0.1:9000; + # fastcgi_index index.php; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + # include fastcgi_params; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} +} \ No newline at end of file From 321494d4e537466ef8d8ee32771d75adf5379302 Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Tue, 21 Jun 2022 18:43:43 +0200 Subject: [PATCH 194/219] ci: don't upload coverage for podman pipeline --- .github/workflows/ci-podman.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/ci-podman.yml b/.github/workflows/ci-podman.yml index b6e9e9b947..748b9ac28d 100644 --- a/.github/workflows/ci-podman.yml +++ b/.github/workflows/ci-podman.yml @@ -49,11 +49,4 @@ jobs: # many (maybe, all?) images used can only be build on Linux, they don't have Windows in their manifest, and # we can't put Windows Server in "Linux Mode" in Github actions # another, host mode is only available on Linux, and we have tests around that, do we skip them? - run: sudo go run gotest.tools/gotestsum --format short-verbose --rerun-fails=5 --packages="./..." -- -coverprofile=cover.txt - - # only report code coverage on linux - - name: Upload coverage report - uses: codecov/codecov-action@v2 - with: - files: ./cover.txt - name: testcontainers-podman-go-${{ matrix.go-version }} \ No newline at end of file + run: sudo go run gotest.tools/gotestsum --format short-verbose --rerun-fails=5 --packages="./..." -- -coverprofile=cover.txt \ No newline at end of file From 763a8705486c053dae9fe242e699ed1cca33f3e9 Mon Sep 17 00:00:00 2001 From: "v.funtikov" Date: Tue, 21 Jun 2022 20:09:52 +0300 Subject: [PATCH 195/219] split goals --- Makefile | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index ea99fe7b5d..a1366bf79f 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,16 @@ -.PHONY: test -test: tools +.PHONY: test-all +test-all: tools test-unit test-e2e + +.PHONY: test-unit +test-unit: + @echo "Running unit tests..." go test ./... - echo "Running end-to-end tests..." && cd ./e2e && make + +.PHONY: test-e2e +test-e2e: + @echo "Running end-to-end tests..." + cd ./e2e && make .PHONY: tools tools: From 13fbe0d6f8ba95b069b38c636506c201993b292e Mon Sep 17 00:00:00 2001 From: "v.funtikov" Date: Tue, 21 Jun 2022 20:19:56 +0300 Subject: [PATCH 196/219] doc: e2e readme --- e2e/README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 e2e/README.md diff --git a/e2e/README.md b/e2e/README.md new file mode 100644 index 0000000000..161750ef94 --- /dev/null +++ b/e2e/README.md @@ -0,0 +1,4 @@ +End-to-end tests module. + +Main purpose of this module is to have a separated module to avoid pushing +unexpected external dependencies like `github.com/lib/pq` into main module. \ No newline at end of file From 6dcd2d6dfe05a1cd8d779463f4043e232125d014 Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Tue, 21 Jun 2022 21:54:32 +0200 Subject: [PATCH 197/219] ci: retry Docker tests to work around flaky tests --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad33843de0..f1b96f51fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,7 @@ jobs: # we can't put Windows Server in "Linux Mode" in Github actions # another, host mode is only available on Linux, and we have tests around that, do we skip them? if: ${{ matrix.platform == 'ubuntu-latest' }} - run: go run gotest.tools/gotestsum --format short-verbose -- -coverprofile=cover.txt ./... + run: go run gotest.tools/gotestsum --format short-verbose --rerun-fails=5 --packages="./..." -- -coverprofile=cover.txt # only report code coverage on linux - name: Upload coverage report From c6e480f8403de517741dd717193b119e91c1e8ff Mon Sep 17 00:00:00 2001 From: Peter Kurfer Date: Tue, 21 Jun 2022 22:13:38 +0200 Subject: [PATCH 198/219] feat: introduce ComposeVersion abstraction ComposeVersion allows to format service names, volume names,... compatible to the installed docker-compose version. Also parallel execution of tests is removed again as it makes more trouble than it helps, apparently. --- compose.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++- compose_test.go | 28 ++++++++++------------ container_test.go | 3 --- docker_test.go | 29 ----------------------- network_test.go | 11 ++++++--- 5 files changed, 78 insertions(+), 52 deletions(-) diff --git a/compose.go b/compose.go index 160decbc27..961ce6ce0f 100644 --- a/compose.go +++ b/compose.go @@ -10,6 +10,7 @@ import ( "os/exec" "path/filepath" "runtime" + "strconv" "strings" "sync" @@ -26,6 +27,29 @@ const ( envComposeFile = "COMPOSE_FILE" ) +var ( + _ ComposeVersion = (*composeVersion1)(nil) + _ ComposeVersion = (*composeVersion2)(nil) +) + +type ComposeVersion interface { + Format(parts ...string) string +} + +type composeVersion1 struct { +} + +func (c composeVersion1) Format(parts ...string) string { + return strings.Join(parts, "_") +} + +type composeVersion2 struct { +} + +func (c composeVersion2) Format(parts ...string) string { + return strings.Join(parts, "-") +} + // DockerCompose defines the contract for running Docker Compose type DockerCompose interface { Down() ExecError @@ -44,6 +68,7 @@ type waitService struct { // LocalDockerCompose represents a Docker Compose execution using local binary // docker-compose or docker-compose.exe, depending on the underlying platform type LocalDockerCompose struct { + ComposeVersion *LocalDockerComposeOptions Executable string ComposeFilePaths []string @@ -107,6 +132,7 @@ func NewLocalDockerCompose(filePaths []string, identifier string, opts ...LocalD dc.absComposeFilePaths[i] = abs } + _ = dc.determineVersion() _ = dc.validate() dc.Identifier = strings.ToLower(identifier) @@ -215,6 +241,37 @@ func (dc *LocalDockerCompose) WithExposedService(service string, port int, strat return dc } +// determineVersion checks which version of docker-compose is installed +// depending on the version services names are composed in a different way +func (dc *LocalDockerCompose) determineVersion() error { + execErr := executeCompose(dc, []string{"version", "--short"}) + + if err := execErr.Error; err != nil { + return err + } + + components := bytes.Split(execErr.StdoutOutput, []byte(".")) + if componentsLen := len(components); componentsLen != 3 { + return fmt.Errorf("expected 3 version components in %s", execErr.StdoutOutput) + } + + majorVersion, err := strconv.ParseInt(string(components[0]), 10, 8) + if err != nil { + return err + } + + switch majorVersion { + case 1: + dc.ComposeVersion = composeVersion1{} + case 2: + dc.ComposeVersion = composeVersion2{} + default: + return fmt.Errorf("unexpected compose version %d", majorVersion) + } + + return nil +} + // validate checks if the files to be run in the compose are valid YAML files, setting up // references to all services in them func (dc *LocalDockerCompose) validate() error { @@ -332,7 +389,7 @@ func executeCompose(dc *LocalDockerCompose, args []string) ExecError { environment[k] = v } - cmds := []string{} + var cmds []string pwd := "." if len(dc.absComposeFilePaths) > 0 { pwd, _ = filepath.Split(dc.absComposeFilePaths[0]) diff --git a/compose_test.go b/compose_test.go index 49d39c7f7d..1471d7d225 100644 --- a/compose_test.go +++ b/compose_test.go @@ -125,7 +125,7 @@ func TestDockerComposeStrategyForInvalidService(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). // Appending with _1 as given in the Java Test-Containers Example - WithExposedService("mysql_1", 13306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). + WithExposedService(compose.Format("mysql", "1"), 13306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Invoke() assert.NotEqual(t, err.Error, nil, "Expected error to be thrown because service with wait strategy is not running") @@ -148,7 +148,7 @@ func TestDockerComposeWithWaitLogStrategy(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). // Appending with _1 as given in the Java Test-Containers Example - WithExposedService("mysql_1", 13306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). + WithExposedService(compose.Format("mysql", "1"), 13306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Invoke() checkIfError(t, err) @@ -174,7 +174,7 @@ func TestDockerComposeWithWaitForService(t *testing.T) { WithEnv(map[string]string{ "bar": "BAR", }). - WaitForService("nginx_1", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). + WaitForService(compose.Format("nginx", "1"), wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Invoke() checkIfError(t, err) @@ -199,7 +199,7 @@ func TestDockerComposeWithWaitHTTPStrategy(t *testing.T) { WithEnv(map[string]string{ "bar": "BAR", }). - WithExposedService("nginx_1", 9080, wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). + WithExposedService(compose.Format("nginx", "1"), 9080, wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Invoke() checkIfError(t, err) @@ -246,7 +246,7 @@ func TestDockerComposeWithWaitStrategy_NoExposedPorts(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). - WithExposedService("nginx_1", 9080, wait.ForLog("Configuration complete; ready for start up")). + WithExposedService(compose.Format("nginx", "1"), 9080, wait.ForLog("Configuration complete; ready for start up")). Invoke() checkIfError(t, err) @@ -268,8 +268,8 @@ func TestDockerComposeWithMultipleWaitStrategies(t *testing.T) { err := compose. WithCommand([]string{"up", "-d"}). - WithExposedService("mysql_1", 13306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second)). - WithExposedService("nginx_1", 9080, wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). + WithExposedService(compose.Format("mysql", "1"), 13306, wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second)). + WithExposedService(compose.Format("nginx", "1"), 9080, wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Invoke() checkIfError(t, err) @@ -407,7 +407,7 @@ func TestLocalDockerComposeWithVolume(t *testing.T) { destroyFn := func() { err := compose.Down() checkIfError(t, err) - assertVolumeDoesNotExist(t, identifier, "mydata") + assertVolumeDoesNotExist(t, compose.Format(identifier, "mydata")) } defer destroyFn() @@ -417,13 +417,13 @@ func TestLocalDockerComposeWithVolume(t *testing.T) { checkIfError(t, err) } -func assertVolumeDoesNotExist(tb testing.TB, composeIdentifier, volume string) { +func assertVolumeDoesNotExist(tb testing.TB, volumeName string) { containerClient, _, err := NewDockerClient() if err != nil { tb.Fatalf("Failed to get provider: %v", err) } - volumeList, err := containerClient.VolumeList(context.Background(), filters.NewArgs()) + volumeList, err := containerClient.VolumeList(context.Background(), filters.NewArgs(filters.Arg("name", volumeName))) if err != nil { tb.Fatalf("Failed to list volumes: %v", err) } @@ -432,12 +432,8 @@ func assertVolumeDoesNotExist(tb testing.TB, composeIdentifier, volume string) { tb.Logf("Volume list warnings: %v", volumeList.Warnings) } - volumeNameRegexp := regexp.MustCompile(fmt.Sprintf(`^\/?%s(_|-)%s$`, composeIdentifier, volume)) - - for i := range volumeList.Volumes { - if volumeNameRegexp.MatchString(volumeList.Volumes[i].Name) { - tb.Fatalf("Volume should not be present") - } + if len(volumeList.Volumes) > 0 { + tb.Fatalf("Volume list is not empty") } } diff --git a/container_test.go b/container_test.go index 4c43e489a7..88953d21bc 100644 --- a/container_test.go +++ b/container_test.go @@ -128,7 +128,6 @@ func Test_GetDockerfile(t *testing.T) { } func Test_BuildImageWithContexts(t *testing.T) { - t.Parallel() type TestCase struct { Name string ContextPath string @@ -288,7 +287,6 @@ func Test_BuildImageWithContexts(t *testing.T) { } func Test_GetLogsFromFailedContainer(t *testing.T) { - t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "docker.io/alpine", @@ -325,7 +323,6 @@ func Test_GetLogsFromFailedContainer(t *testing.T) { } func TestShouldStartContainersInParallel(t *testing.T) { - t.Parallel() ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) t.Cleanup(cancel) diff --git a/docker_test.go b/docker_test.go index fa9d2f7f5e..b9cca09b60 100644 --- a/docker_test.go +++ b/docker_test.go @@ -164,7 +164,6 @@ func TestContainerWithHostNetworkOptions(t *testing.T) { } func TestContainerWithNetworkModeAndNetworkTogether(t *testing.T) { - t.Parallel() ctx := context.Background() gcr := GenericContainerRequest{ ProviderType: providerType, @@ -463,7 +462,6 @@ func TestContainerStopWithReaper(t *testing.T) { } func TestContainerTerminationWithReaper(t *testing.T) { - t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -502,7 +500,6 @@ func TestContainerTerminationWithReaper(t *testing.T) { } func TestContainerTerminationWithoutReaper(t *testing.T) { - t.Parallel() ctx := context.Background() client, err := client.NewClientWithOpts(client.FromEnv) if err != nil { @@ -667,7 +664,6 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { } func TestContainerCreation(t *testing.T) { - t.Parallel() ctx := context.Background() nginxC, err := GenericContainer(ctx, GenericContainerRequest{ @@ -716,7 +712,6 @@ func TestContainerCreation(t *testing.T) { } func TestContainerCreationWithName(t *testing.T) { - t.Parallel() ctx := context.Background() creationName := fmt.Sprintf("%s_%d", "test_container", time.Now().Unix()) @@ -778,7 +773,6 @@ func TestContainerCreationWithName(t *testing.T) { } func TestContainerCreationAndWaitForListeningPortLongEnough(t *testing.T) { - t.Parallel() ctx := context.Background() // delayed-nginx will wait 2s before opening port @@ -811,7 +805,6 @@ func TestContainerCreationAndWaitForListeningPortLongEnough(t *testing.T) { } func TestContainerCreationTimesOut(t *testing.T) { - t.Parallel() ctx := context.Background() // delayed-nginx will wait 2s before opening port nginxC, err := GenericContainer(ctx, GenericContainerRequest{ @@ -867,7 +860,6 @@ func TestContainerRespondsWithHttp200ForIndex(t *testing.T) { } func TestContainerCreationTimesOutWithHttp(t *testing.T) { - t.Parallel() ctx := context.Background() // delayed-nginx will wait 2s before opening port nginxC, err := GenericContainer(ctx, GenericContainerRequest{ @@ -889,7 +881,6 @@ func TestContainerCreationTimesOutWithHttp(t *testing.T) { } func TestContainerCreationWaitsForLogContextTimeout(t *testing.T) { - t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "docker.io/mysql:latest", @@ -912,7 +903,6 @@ func TestContainerCreationWaitsForLogContextTimeout(t *testing.T) { } func TestContainerCreationWaitsForLog(t *testing.T) { - t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "docker.io/mysql:latest", @@ -955,7 +945,6 @@ func TestContainerCreationWaitsForLog(t *testing.T) { } func Test_BuildContainerFromDockerfile(t *testing.T) { - t.Parallel() t.Log("getting context") ctx := context.Background() t.Log("got context, creating container request") @@ -1007,7 +996,6 @@ func Test_BuildContainerFromDockerfile(t *testing.T) { } func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { - t.Parallel() t.Log("getting ctx") ctx := context.Background() @@ -1095,7 +1083,6 @@ func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { } func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { - t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "docker.io/mysql:latest", @@ -1121,7 +1108,6 @@ func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { } func TestContainerCreationWaitingForHostPort(t *testing.T) { - t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: nginxAlpineImage, @@ -1139,7 +1125,6 @@ func TestContainerCreationWaitingForHostPort(t *testing.T) { } func TestContainerCreationWaitingForHostPortWithoutBashThrowsAnError(t *testing.T) { - t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: nginxAlpineImage, @@ -1157,7 +1142,6 @@ func TestContainerCreationWaitingForHostPortWithoutBashThrowsAnError(t *testing. } func TestContainerCreationWaitsForLogAndPort(t *testing.T) { - t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "docker.io/mysql:latest", @@ -1206,7 +1190,6 @@ func TestCMD(t *testing.T) { and it will be run when we run the container */ - t.Parallel() ctx := context.Background() req := ContainerRequest{ @@ -1234,7 +1217,6 @@ func TestEntrypoint(t *testing.T) { and it will be run when we run the container */ - t.Parallel() ctx := context.Background() req := ContainerRequest{ @@ -1441,7 +1423,6 @@ func ExampleContainer_MappedPort() { } func TestContainerCreationWithBindAndVolume(t *testing.T) { - t.Parallel() absPath, err := filepath.Abs("./testresources/hello.sh") if err != nil { t.Fatal(err) @@ -1487,7 +1468,6 @@ func TestContainerCreationWithBindAndVolume(t *testing.T) { } func TestContainerWithTmpFs(t *testing.T) { - t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "docker.io/busybox", @@ -1569,7 +1549,6 @@ func TestContainerCustomPlatformImage(t *testing.T) { if providerType == ProviderPodman { t.Skip("Incompatible Docker API version for Podman") } - t.Parallel() t.Run("error with a non-existent platform", func(t *testing.T) { t.Parallel() nonExistentPlatform := "windows/arm12" @@ -1626,7 +1605,6 @@ func TestContainerCustomPlatformImage(t *testing.T) { } func TestContainerWithCustomHostname(t *testing.T) { - t.Parallel() ctx := context.Background() name := fmt.Sprintf("some-nginx-%s-%d", t.Name(), rand.Int()) hostname := fmt.Sprintf("my-nginx-%s-%d", t.Name(), rand.Int()) @@ -1664,7 +1642,6 @@ func readHostname(tb testing.TB, containerId string) string { } func TestDockerContainerCopyFileToContainer(t *testing.T) { - t.Parallel() ctx := context.Background() nginxC, err := GenericContainer(ctx, GenericContainerRequest{ @@ -1724,7 +1701,6 @@ func TestDockerContainerCopyToContainer(t *testing.T) { } func TestDockerContainerCopyFileFromContainer(t *testing.T) { - t.Parallel() fileContent, err := ioutil.ReadFile("./testresources/hello.sh") if err != nil { t.Fatal(err) @@ -1809,7 +1785,6 @@ func TestDockerContainerResources(t *testing.T) { t.Skip("Rootless Podman does not support setting rlimit") } - t.Parallel() ctx := context.Background() expected := []*units.Ulimit{ @@ -1854,7 +1829,6 @@ func TestDockerContainerResources(t *testing.T) { } func TestContainerWithReaperNetwork(t *testing.T) { - t.Parallel() ctx := context.Background() networks := []string{ "test_network_" + randomString(), @@ -1929,7 +1903,6 @@ func TestContainerRunningCheckingStatusCode(t *testing.T) { } func TestContainerWithUserID(t *testing.T) { - t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "docker.io/alpine:latest", @@ -1960,7 +1933,6 @@ func TestContainerWithUserID(t *testing.T) { } func TestContainerWithNoUserID(t *testing.T) { - t.Parallel() ctx := context.Background() req := ContainerRequest{ Image: "docker.io/alpine:latest", @@ -1992,7 +1964,6 @@ func TestContainerWithNoUserID(t *testing.T) { func TestGetGatewayIP(t *testing.T) { // When using docker-compose with DinD mode, and using host port or http wait strategy // It's need to invoke GetGatewayIP for get the host - t.Parallel() provider, err := providerType.GetProvider(WithLogger(TestLogger(t))) if err != nil { t.Fatal(err) diff --git a/network_test.go b/network_test.go index 14b214076b..39888e51b5 100644 --- a/network_test.go +++ b/network_test.go @@ -3,11 +3,13 @@ package testcontainers import ( "context" "fmt" + "testing" + "time" + "github.com/docker/docker/api/types/network" "github.com/stretchr/testify/assert" + "github.com/testcontainers/testcontainers-go/wait" - "testing" - "time" ) // Create a network using a provider. By default it is Docker. @@ -36,6 +38,7 @@ func ExampleNetworkProvider_CreateNetwork() { defer nginxC.Terminate(ctx) nginxC.GetContainerID() } + func Test_NetworkWithIPAM(t *testing.T) { ctx := context.Background() networkName := "test-network-with-ipam" @@ -45,9 +48,11 @@ func Test_NetworkWithIPAM(t *testing.T) { { Subnet: "10.1.1.0/24", Gateway: "10.1.1.254", - IPRange: "10.1.1.1/25", }, }, + Options: map[string]string{ + "driver": "host-local", + }, } net, err := GenericNetwork(ctx, GenericNetworkRequest{ NetworkRequest: NetworkRequest{ From bbda9150a048952136b00b2af912027cf8fe9975 Mon Sep 17 00:00:00 2001 From: doodot Date: Sun, 26 Jun 2022 22:50:05 +0900 Subject: [PATCH 199/219] docs: remove unused import in redis example --- docs/examples/redis.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/examples/redis.md b/docs/examples/redis.md index 290fba3a40..39eaa729ed 100644 --- a/docs/examples/redis.md +++ b/docs/examples/redis.md @@ -11,7 +11,6 @@ import ( "github.com/go-redis/redis/v8" "github.com/google/uuid" - _ "github.com/jackc/pgx/v4/stdlib" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" ) From d568919bb3d30cc2747ee39675a9ad1076445138 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 28 Jun 2022 19:23:48 +0600 Subject: [PATCH 200/219] Update docs/features/creating_container.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Manuel de la Peña --- docs/features/creating_container.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/features/creating_container.md b/docs/features/creating_container.md index c1882e9d3f..e2c54636ab 100644 --- a/docs/features/creating_container.md +++ b/docs/features/creating_container.md @@ -86,6 +86,8 @@ func TestIntegrationNginxLatestReturn(t *testing.T) { `testcontainers.ParallelContainers` - defines the containers that should be run in parallel mode. +The following test creates two NGINX containers in parallel: + ```go package main From 6a46d221f374ccb0dbaa3a864c7ff26c24c3637e Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Tue, 28 Jun 2022 19:26:13 +0600 Subject: [PATCH 201/219] refactor: fix readability --- parallel.go | 1 + 1 file changed, 1 insertion(+) diff --git a/parallel.go b/parallel.go index f6d371dbb3..d101d57802 100644 --- a/parallel.go +++ b/parallel.go @@ -37,6 +37,7 @@ func parallelContainersRunner( errors chan<- ParallelContainersRequestError, containers chan<- Container, wg *sync.WaitGroup) { + for req := range requests { c, err := GenericContainer(ctx, req) if err != nil { From 89fd84a5843f5dde7d77d480f2f66f2cbf357701 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Tue, 28 Jun 2022 19:37:26 +0600 Subject: [PATCH 202/219] test: add new test for checking containers running (all errors) --- parallel_test.go | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/parallel_test.go b/parallel_test.go index 390bd5892d..87a7fa971c 100644 --- a/parallel_test.go +++ b/parallel_test.go @@ -13,7 +13,7 @@ func TestParallelContainers(t *testing.T) { expErrors int }{ { - name: "running two containers (success)", + name: "running two containers (one error)", reqs: ParallelContainerRequest{ { ContainerRequest: ContainerRequest{ @@ -28,7 +28,7 @@ func TestParallelContainers(t *testing.T) { { ContainerRequest: ContainerRequest{ - Image: "nginx", + Image: "bad bad bad", ExposedPorts: []string{ "10081/tcp", }, @@ -36,10 +36,38 @@ func TestParallelContainers(t *testing.T) { Started: true, }, }, - resLen: 2, + resLen: 1, + expErrors: 1, }, { - name: "running two containers (one error)", + name: "running two containers (all errors)", + reqs: ParallelContainerRequest{ + { + ContainerRequest: ContainerRequest{ + + Image: "bad bad bad", + ExposedPorts: []string{ + "10081/tcp", + }, + }, + Started: true, + }, + { + ContainerRequest: ContainerRequest{ + + Image: "bad bad bad", + ExposedPorts: []string{ + "10081/tcp", + }, + }, + Started: true, + }, + }, + resLen: 0, + expErrors: 2, + }, + { + name: "running two containers (success)", reqs: ParallelContainerRequest{ { ContainerRequest: ContainerRequest{ @@ -54,7 +82,7 @@ func TestParallelContainers(t *testing.T) { { ContainerRequest: ContainerRequest{ - Image: "bad bad bad", + Image: "nginx", ExposedPorts: []string{ "10081/tcp", }, @@ -62,8 +90,8 @@ func TestParallelContainers(t *testing.T) { Started: true, }, }, - resLen: 1, - expErrors: 1, + resLen: 2, + expErrors: 0, }, } From 2682d2fdcca67e6f13d4d37c577ed8a0358a31b7 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanov Date: Tue, 28 Jun 2022 19:40:09 +0600 Subject: [PATCH 203/219] refactor: parallel_test refactoring --- parallel_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parallel_test.go b/parallel_test.go index 87a7fa971c..261efc21e1 100644 --- a/parallel_test.go +++ b/parallel_test.go @@ -99,7 +99,7 @@ func TestParallelContainers(t *testing.T) { t.Run(tc.name, func(t *testing.T) { res, err := ParallelContainers(context.Background(), tc.reqs, ParallelContainersOptions{}) - if err != nil && tc.expErrors > 0 { + if err != nil { e, _ := err.(ParallelContainersError) if len(e.Errors) != tc.expErrors { From dd2f7f4314d9d8131eac88420d1cfb89d9171ca5 Mon Sep 17 00:00:00 2001 From: Vitaliy F Date: Tue, 28 Jun 2022 17:52:27 +0300 Subject: [PATCH 204/219] chore: Makefile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Manuel de la Peña --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a1366bf79f..417d7c7e2d 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ test-unit: .PHONY: test-e2e test-e2e: @echo "Running end-to-end tests..." - cd ./e2e && make + make -C e2e test .PHONY: tools tools: From f460e5e12bcf063e8fdbcf2e1dd7f7b0d5ad368b Mon Sep 17 00:00:00 2001 From: Vitaliy F Date: Tue, 28 Jun 2022 17:53:21 +0300 Subject: [PATCH 205/219] doc: readme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Manuel de la Peña --- e2e/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/README.md b/e2e/README.md index 161750ef94..cdc01c9637 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -1,4 +1,4 @@ -End-to-end tests module. +# End-to-end tests module. Main purpose of this module is to have a separated module to avoid pushing -unexpected external dependencies like `github.com/lib/pq` into main module. \ No newline at end of file +unexpected external dependencies like `github.com/lib/pq` into the main module. \ No newline at end of file From c186f02cb3b3bdd0f13e12974f834e10e5d02b26 Mon Sep 17 00:00:00 2001 From: "v.funtikov" Date: Tue, 28 Jun 2022 18:20:52 +0300 Subject: [PATCH 206/219] fix: use gotestsum in Makefiles for testing; use make test* in CI --- .github/workflows/ci.yml | 4 ++-- Makefile | 6 +++++- e2e/Makefile | 6 +++++- e2e/go.mod | 1 + e2e/go.sum | 11 +++++++++++ e2e/tools/tools.go | 11 +++++++++++ 6 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 e2e/tools/tools.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a486f09b5f..648738244f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,7 @@ jobs: # we can't put Windows Server in "Linux Mode" in Github actions # another, host mode is only available on Linux, and we have tests around that, do we skip them? if: ${{ matrix.platform == 'ubuntu-latest' }} - run: go run gotest.tools/gotestsum --format short-verbose --rerun-fails=5 --packages="./..." -- -coverprofile=cover.txt + run: make test-unit # only report code coverage on linux - name: Upload coverage report @@ -64,7 +64,7 @@ jobs: - name: Run e2e tests if: ${{ matrix.platform == 'ubuntu-latest' }} - run: cd ./e2e && make test + run: make test-e2e - name: Run checker run: | diff --git a/Makefile b/Makefile index 417d7c7e2d..2ae3f799f9 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,11 @@ test-all: tools test-unit test-e2e .PHONY: test-unit test-unit: @echo "Running unit tests..." - go test ./... + go run gotest.tools/gotestsum \ + --format short-verbose \ + --rerun-fails=5 \ + --packages="./..." \ + -- -coverprofile=cover.txt .PHONY: test-e2e test-e2e: diff --git a/e2e/Makefile b/e2e/Makefile index e2035adad8..9e65d3d8a3 100644 --- a/e2e/Makefile +++ b/e2e/Makefile @@ -1,7 +1,11 @@ .PHONY: test test: tools - go test ./... + go run gotest.tools/gotestsum \ + --format short-verbose \ + --rerun-fails=5 \ + --packages="./..." \ + .PHONY: tools tools: diff --git a/e2e/go.mod b/e2e/go.mod index f8a627997c..4c982d5e98 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -6,6 +6,7 @@ require ( github.com/docker/go-connections v0.4.0 github.com/lib/pq v1.10.6 github.com/testcontainers/testcontainers-go v0.13.0 + gotest.tools/gotestsum v1.7.0 ) replace github.com/testcontainers/testcontainers-go => ../ diff --git a/e2e/go.sum b/e2e/go.sum index a7e857313f..45a9cbb177 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -225,6 +225,7 @@ github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/dnephin/pflag v1.0.7 h1:oxONGlWxhmUct0YzKTgrpQv9AUA1wtPBn7zuSjJqptk= github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= @@ -254,6 +255,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= @@ -350,6 +352,7 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -392,6 +395,7 @@ github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6t github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -428,8 +432,10 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= @@ -681,6 +687,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -733,6 +740,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -804,6 +812,7 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -857,6 +866,7 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -965,6 +975,7 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/gotestsum v1.7.0 h1:RwpqwwFKBAa2h+F6pMEGpE707Edld0etUD3GhqqhDNc= gotest.tools/gotestsum v1.7.0/go.mod h1:V1m4Jw3eBerhI/A6qCxUE07RnCg7ACkKj9BYcAm09V8= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= diff --git a/e2e/tools/tools.go b/e2e/tools/tools.go new file mode 100644 index 0000000000..724d23e17f --- /dev/null +++ b/e2e/tools/tools.go @@ -0,0 +1,11 @@ +//go:build tools +// +build tools + +// This package contains the tool dependencies of the project. + +package tools + +import ( + // Register gotestsum for pinning version + _ "gotest.tools/gotestsum" +) From 476cafb750b7b5160621cb58bca3ab6c097ad255 Mon Sep 17 00:00:00 2001 From: Zoran Regvart Date: Fri, 10 Jun 2022 12:16:45 +0200 Subject: [PATCH 207/219] feat: ability to configure running privileged Ryuk Adds support for running the Ryuk (reaper) container in privileged mode either by setting `ryuk.container.privileged=true` in `$HOME/.testcontainers.properties` or by setting `TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED=true` environment variable. --- compose_test.go | 4 +-- container.go | 1 + docker.go | 25 ++++++++----- docker_test.go | 15 ++++++-- reaper.go | 6 ++++ reaper_test.go | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 reaper_test.go diff --git a/compose_test.go b/compose_test.go index 1471d7d225..45b758638a 100644 --- a/compose_test.go +++ b/compose_test.go @@ -418,7 +418,7 @@ func TestLocalDockerComposeWithVolume(t *testing.T) { } func assertVolumeDoesNotExist(tb testing.TB, volumeName string) { - containerClient, _, err := NewDockerClient() + containerClient, _, _, err := NewDockerClient() if err != nil { tb.Fatalf("Failed to get provider: %v", err) } @@ -443,7 +443,7 @@ func assertContainerEnvironmentVariables( present map[string]string, absent map[string]string, ) { - containerClient, _, err := NewDockerClient() + containerClient, _, _, err := NewDockerClient() if err != nil { tb.Fatalf("Failed to get provider: %v", err) } diff --git a/container.go b/container.go index c1b425683d..607c408503 100644 --- a/container.go +++ b/container.go @@ -29,6 +29,7 @@ type ContainerProvider interface { CreateContainer(context.Context, ContainerRequest) (Container, error) // create a container without starting it RunContainer(context.Context, ContainerRequest) (Container, error) // create a container and start it Health(context.Context) error + Config() TestContainersConfig } // Container allows getting info about and controlling a single container instance diff --git a/docker.go b/docker.go index 32ea7a2a81..ea8b7eeb56 100644 --- a/docker.go +++ b/docker.go @@ -606,15 +606,17 @@ type DockerProvider struct { client *client.Client host string hostCache string + config TestContainersConfig } var _ ContainerProvider = (*DockerProvider)(nil) // or through Decode type TestContainersConfig struct { - Host string `properties:"docker.host,default="` - TLSVerify int `properties:"docker.tls.verify,default=0"` - CertPath string `properties:"docker.cert.path,default="` + Host string `properties:"docker.host,default="` + TLSVerify int `properties:"docker.tls.verify,default=0"` + CertPath string `properties:"docker.cert.path,default="` + RyukPrivileged bool `properties:"ryuk.container.privileged,default=false"` } type ( @@ -660,8 +662,8 @@ func WithDefaultBridgeNetwork(bridgeNetworkName string) DockerProviderOption { }) } -func NewDockerClient() (cli *client.Client, host string, err error) { - tcConfig := readTCPropsFile() +func NewDockerClient() (cli *client.Client, host string, tcConfig TestContainersConfig, err error) { + tcConfig = readTCPropsFile() host = tcConfig.Host opts := []client.Opt{client.FromEnv} @@ -685,12 +687,12 @@ func NewDockerClient() (cli *client.Client, host string, err error) { cli, err = client.NewClientWithOpts(opts...) if err != nil { - return nil, "", err + return nil, "", TestContainersConfig{}, err } cli.NegotiateAPIVersion(context.Background()) - return cli, host, nil + return cli, host, tcConfig, nil } // NewDockerProvider creates a Docker provider with the EnvClient @@ -705,7 +707,7 @@ func NewDockerProvider(provOpts ...DockerProviderOption) (*DockerProvider, error provOpts[idx].ApplyDockerTo(o) } - c, host, err := NewDockerClient() + c, host, tcConfig, err := NewDockerClient() if err != nil { return nil, err } @@ -724,6 +726,7 @@ func NewDockerProvider(provOpts ...DockerProviderOption) (*DockerProvider, error DockerProviderOptions: o, host: host, client: c, + config: tcConfig, } return p, nil @@ -1057,6 +1060,12 @@ func (p *DockerProvider) RunContainer(ctx context.Context, req ContainerRequest) return c, nil } +// Config provides the TestContainersConfig read from $HOME/.testcontainers.properties or +// the environment variables +func (p *DockerProvider) Config() TestContainersConfig { + return p.config +} + // daemonHost gets the host or ip of the Docker daemon where ports are exposed on // Warning: this is based on your Docker host setting. Will fail if using an SSH tunnel // You can use the "TC_HOST" env variable to set this yourself diff --git a/docker_test.go b/docker_test.go index b9cca09b60..0d8a9bebb1 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1430,7 +1430,7 @@ func TestContainerCreationWithBindAndVolume(t *testing.T) { ctx, cnl := context.WithTimeout(context.Background(), 30*time.Second) defer cnl() // Create a Docker client. - dockerCli, _, err := NewDockerClient() + dockerCli, _, _, err := NewDockerClient() if err != nil { t.Fatal(err) } @@ -1590,7 +1590,7 @@ func TestContainerCustomPlatformImage(t *testing.T) { require.NoError(t, err) terminateContainerOnEnd(t, ctx, c) - dockerCli, _, err := NewDockerClient() + dockerCli, _, _, err := NewDockerClient() require.NoError(t, err) dockerCli.NegotiateAPIVersion(ctx) @@ -1628,7 +1628,7 @@ func TestContainerWithCustomHostname(t *testing.T) { } func readHostname(tb testing.TB, containerId string) string { - containerClient, _, err := NewDockerClient() + containerClient, _, _, err := NewDockerClient() if err != nil { tb.Fatalf("Failed to create Docker client: %v", err) } @@ -1977,6 +1977,15 @@ func TestGetGatewayIP(t *testing.T) { } } +func TestProviderHasConfig(t *testing.T) { + provider, err := NewDockerProvider(WithLogger(TestLogger(t))) + if err != nil { + t.Fatal(err) + } + + assert.NotNil(t, provider.Config(), "expecting DockerProvider to provide the configuration") +} + func terminateContainerOnEnd(tb testing.TB, ctx context.Context, ctr Container) { tb.Helper() if ctr == nil { diff --git a/reaper.go b/reaper.go index aaab2508f3..d198695c85 100644 --- a/reaper.go +++ b/reaper.go @@ -36,6 +36,7 @@ var ( // The ContainerProvider interface should usually satisfy this as well, so it is pluggable type ReaperProvider interface { RunContainer(ctx context.Context, req ContainerRequest) (Container, error) + Config() TestContainersConfig } // NewReaper creates a Reaper with a sessionID to identify containers and a provider to use @@ -71,6 +72,11 @@ func NewReaper(ctx context.Context, sessionID string, provider ReaperProvider, r WaitingFor: wait.ForListeningPort(listeningPort), } + tcConfig := provider.Config() + if tcConfig.RyukPrivileged || os.Getenv("TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED") == "true" { + req.Privileged = true + } + // Attach reaper container to a requested network if it is specified if p, ok := provider.(*DockerProvider); ok { req.Networks = append(req.Networks, p.DefaultNetwork) diff --git a/reaper_test.go b/reaper_test.go new file mode 100644 index 0000000000..161646f04a --- /dev/null +++ b/reaper_test.go @@ -0,0 +1,95 @@ +package testcontainers + +import ( + "context" + "errors" + "testing" + + "github.com/docker/go-connections/nat" + "github.com/stretchr/testify/assert" + "github.com/testcontainers/testcontainers-go/wait" +) + +type mockReaperProvider struct { + req ContainerRequest + config TestContainersConfig +} + +var errExpected = errors.New("expected") + +func (m *mockReaperProvider) RunContainer(ctx context.Context, req ContainerRequest) (Container, error) { + m.req = req + + // we're only interested in the request, so instead of mocking the Docker client + // we'll error out here + return nil, errExpected +} + +func (m *mockReaperProvider) Config() TestContainersConfig { + return m.config +} + +// createContainerRequest creates the expected request and allows for customization +func createContainerRequest(customize func(ContainerRequest) ContainerRequest) ContainerRequest { + req := ContainerRequest{ + Image: "reaperImage", + ExposedPorts: []string{"8080/tcp"}, + Labels: map[string]string{ + TestcontainerLabel: "true", + TestcontainerLabelIsReaper: "true", + }, + SkipReaper: true, + Mounts: Mounts(BindMount("/var/run/docker.sock", "/var/run/docker.sock")), + AutoRemove: true, + WaitingFor: wait.ForListeningPort(nat.Port("8080/tcp")), + NetworkMode: "bridge", + } + if customize == nil { + return req + } + + return customize(req) +} + +func Test_NewReaper(t *testing.T) { + + type cases struct { + name string + req ContainerRequest + config TestContainersConfig + } + + tests := []cases{ + { + name: "non-privileged", + req: createContainerRequest(nil), + config: TestContainersConfig{}, + }, + { + name: "privileged", + req: createContainerRequest(func(req ContainerRequest) ContainerRequest { + req.Privileged = true + return req + }), + config: TestContainersConfig{ + RyukPrivileged: true, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + // make sure we re-initialize the singleton + reaper = nil + provider := &mockReaperProvider{ + config: test.config, + } + + _, err := NewReaper(context.TODO(), "sessionId", provider, "reaperImage") + // we should have errored out see mockReaperProvider.RunContainer + assert.EqualError(t, err, "expected") + + assert.Equal(t, test.req, provider.req, "expected ContainerRequest doesn't match the submitted request") + }) + } +} From 8b0fb5c2a096957fb96b9a50aec18215d5ae814f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Thu, 30 Jun 2022 18:09:34 +0200 Subject: [PATCH 208/219] chore: tell dependabot about the new module --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3f02defd8f..8e1f61a045 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,3 +6,9 @@ updates: interval: daily open-pull-requests-limit: 3 rebase-strategy: disabled +- package-ecosystem: gomod + directory: "/e2e/" + schedule: + interval: daily + open-pull-requests-limit: 3 + rebase-strategy: disabled From 07106d7351e8ae263c7b08c50c201153544f69f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 1 Jul 2022 07:50:36 +0200 Subject: [PATCH 209/219] chore: remove extra slash --- .github/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8e1f61a045..9e6517e9ab 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,7 +7,7 @@ updates: open-pull-requests-limit: 3 rebase-strategy: disabled - package-ecosystem: gomod - directory: "/e2e/" + directory: "/e2e" schedule: interval: daily open-pull-requests-limit: 3 From d28f363f8482148f74925028e43dbeb843ab02a0 Mon Sep 17 00:00:00 2001 From: Zoran Regvart Date: Fri, 1 Jul 2022 10:43:21 +0200 Subject: [PATCH 210/219] refactor: read RYUK_CONTAINER_PRIVILEGED once Now the environment variable `TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED` is read only once in the `configureTC` function that reads the `.testcontainers.properties` file and accesses the environment variable. --- docker.go | 13 +++- docker_test.go | 171 ++++++++++++++++++++++++++++++++++++++----------- reaper.go | 4 +- 3 files changed, 145 insertions(+), 43 deletions(-) diff --git a/docker.go b/docker.go index ea8b7eeb56..1a63a21584 100644 --- a/docker.go +++ b/docker.go @@ -663,7 +663,8 @@ func WithDefaultBridgeNetwork(bridgeNetworkName string) DockerProviderOption { } func NewDockerClient() (cli *client.Client, host string, tcConfig TestContainersConfig, err error) { - tcConfig = readTCPropsFile() + tcConfig = configureTC() + host = tcConfig.Host opts := []client.Opt{client.FromEnv} @@ -732,8 +733,9 @@ func NewDockerProvider(provOpts ...DockerProviderOption) (*DockerProvider, error return p, nil } -// readTCPropsFile reads from testcontainers properties file, if it exists -func readTCPropsFile() TestContainersConfig { +// configureTC reads from testcontainers properties file, if it exists +// it is possible that certain values get overridden when set as environment variables +func configureTC() TestContainersConfig { home, err := os.UserHomeDir() if err != nil { return TestContainersConfig{} @@ -752,6 +754,11 @@ func readTCPropsFile() TestContainersConfig { return TestContainersConfig{} } + ryukPrivilegedEnv := os.Getenv("TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED") + if ryukPrivilegedEnv != "" { + cfg.RyukPrivileged = ryukPrivilegedEnv == "true" + } + return cfg } diff --git a/docker_test.go b/docker_test.go index 0d8a9bebb1..5c1b31449d 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1242,7 +1242,7 @@ func TestReadTCPropsFile(t *testing.T) { tmpDir := fs.NewDir(t, os.TempDir()) env.Patch(t, "HOME", tmpDir.Path()) - config := readTCPropsFile() + config := configureTC() assert.Empty(t, config, "TC props file should not exist") }) @@ -1251,37 +1251,45 @@ func TestReadTCPropsFile(t *testing.T) { tmpDir := fs.NewDir(t, os.TempDir()) env.Patch(t, "HOME", tmpDir.Path()) - config := readTCPropsFile() + config := configureTC() assert.Empty(t, config, "TC props file should not exist") }) t.Run("HOME contains TC properties file", func(t *testing.T) { tests := []struct { - content string - expectedHost string - expectedTLSVerify int - expectedCertPath string + content string + env map[string]string + expected TestContainersConfig }{ { "docker.host = tcp://127.0.0.1:33293", - "tcp://127.0.0.1:33293", - 0, - "", + map[string]string{}, + TestContainersConfig{ + Host: "tcp://127.0.0.1:33293", + TLSVerify: 0, + CertPath: "", + }, }, { "docker.host = tcp://127.0.0.1:33293", - "tcp://127.0.0.1:33293", - 0, - "", + map[string]string{}, + TestContainersConfig{ + Host: "tcp://127.0.0.1:33293", + TLSVerify: 0, + CertPath: "", + }, }, { `docker.host = tcp://127.0.0.1:33293 docker.host = tcp://127.0.0.1:4711 `, - "tcp://127.0.0.1:4711", - 0, - "", + map[string]string{}, + TestContainersConfig{ + Host: "tcp://127.0.0.1:4711", + TLSVerify: 0, + CertPath: "", + }, }, { `docker.host = tcp://127.0.0.1:33293 @@ -1289,59 +1297,148 @@ func TestReadTCPropsFile(t *testing.T) { docker.host = tcp://127.0.0.1:1234 docker.tls.verify = 1 `, - "tcp://127.0.0.1:1234", - 1, - "", + map[string]string{}, + TestContainersConfig{ + Host: "tcp://127.0.0.1:1234", + TLSVerify: 1, + CertPath: "", + }, }, { "", - "", - 0, - "", + map[string]string{}, + TestContainersConfig{ + Host: "", + TLSVerify: 0, + CertPath: "", + }, }, { `foo = bar docker.host = tcp://127.0.0.1:1234 `, - "tcp://127.0.0.1:1234", - 0, - "", + map[string]string{}, + TestContainersConfig{ + Host: "tcp://127.0.0.1:1234", + TLSVerify: 0, + CertPath: "", + }, }, { "docker.host=tcp://127.0.0.1:33293", - "tcp://127.0.0.1:33293", - 0, - "", + map[string]string{}, + TestContainersConfig{ + Host: "tcp://127.0.0.1:33293", + TLSVerify: 0, + CertPath: "", + }, }, { `#docker.host=tcp://127.0.0.1:33293`, - "", - 0, - "", + map[string]string{}, + TestContainersConfig{ + Host: "", + TLSVerify: 0, + CertPath: "", + }, }, { `#docker.host = tcp://127.0.0.1:33293 docker.host = tcp://127.0.0.1:4711 docker.host = tcp://127.0.0.1:1234 docker.cert.path=/tmp/certs`, - "tcp://127.0.0.1:1234", - 0, - "/tmp/certs", + map[string]string{}, + TestContainersConfig{ + Host: "tcp://127.0.0.1:1234", + TLSVerify: 0, + CertPath: "/tmp/certs", + }, + }, + { + `ryuk.container.privileged=true`, + map[string]string{}, + TestContainersConfig{ + Host: "", + TLSVerify: 0, + CertPath: "", + RyukPrivileged: true, + }, + }, + { + ``, + map[string]string{ + "TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED": "true", + }, + TestContainersConfig{ + Host: "", + TLSVerify: 0, + CertPath: "", + RyukPrivileged: true, + }, + }, + { + `ryuk.container.privileged=true`, + map[string]string{ + "TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED": "true", + }, + TestContainersConfig{ + Host: "", + TLSVerify: 0, + CertPath: "", + RyukPrivileged: true, + }, + }, + { + `ryuk.container.privileged=false`, + map[string]string{ + "TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED": "true", + }, + TestContainersConfig{ + Host: "", + TLSVerify: 0, + CertPath: "", + RyukPrivileged: true, + }, + }, + { + `ryuk.container.privileged=true`, + map[string]string{ + "TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED": "false", + }, + TestContainersConfig{ + Host: "", + TLSVerify: 0, + CertPath: "", + RyukPrivileged: false, + }, + }, + { + `ryuk.container.privileged=false`, + map[string]string{ + "TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED": "false", + }, + TestContainersConfig{ + Host: "", + TLSVerify: 0, + CertPath: "", + RyukPrivileged: false, + }, }, } for _, tt := range tests { tmpDir := fs.NewDir(t, os.TempDir()) env.Patch(t, "HOME", tmpDir.Path()) + for k, v := range tt.env { + env.Patch(t, k, v) + } if err := ioutil.WriteFile(tmpDir.Join(".testcontainers.properties"), []byte(tt.content), 0o600); err != nil { t.Errorf("Failed to create the file: %v", err) return } - config := readTCPropsFile() + config := configureTC() - assert.Equal(t, tt.expectedHost, config.Host, "Hosts do not match") - assert.Equal(t, tt.expectedTLSVerify, config.TLSVerify, "TLS verifies do not match") - assert.Equal(t, tt.expectedCertPath, config.CertPath, "Cert paths do not match") + assert.Equal(t, tt.expected, config, "Configuration doesn't not match") } }) } diff --git a/reaper.go b/reaper.go index d198695c85..10c35978ef 100644 --- a/reaper.go +++ b/reaper.go @@ -73,9 +73,7 @@ func NewReaper(ctx context.Context, sessionID string, provider ReaperProvider, r } tcConfig := provider.Config() - if tcConfig.RyukPrivileged || os.Getenv("TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED") == "true" { - req.Privileged = true - } + req.Privileged = tcConfig.RyukPrivileged // Attach reaper container to a requested network if it is specified if p, ok := provider.(*DockerProvider); ok { From d003e9ad9e7b631a57a8f3cd443b8179450b1933 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Jul 2022 05:53:17 +0000 Subject: [PATCH 211/219] chore(deps): bump gotest.tools/gotestsum from 1.7.0 to 1.8.1 in /e2e Bumps [gotest.tools/gotestsum](https://github.com/gotestyourself/gotestsum) from 1.7.0 to 1.8.1. - [Release notes](https://github.com/gotestyourself/gotestsum/releases) - [Changelog](https://github.com/gotestyourself/gotestsum/blob/main/.goreleaser.yml) - [Commits](https://github.com/gotestyourself/gotestsum/compare/v1.7.0...v1.8.1) --- updated-dependencies: - dependency-name: gotest.tools/gotestsum dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- e2e/go.mod | 2 +- e2e/go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/e2e/go.mod b/e2e/go.mod index 4c982d5e98..366dc8ee3c 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/go-connections v0.4.0 github.com/lib/pq v1.10.6 github.com/testcontainers/testcontainers-go v0.13.0 - gotest.tools/gotestsum v1.7.0 + gotest.tools/gotestsum v1.8.1 ) replace github.com/testcontainers/testcontainers-go => ../ diff --git a/e2e/go.sum b/e2e/go.sum index 45a9cbb177..7c0eef991e 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -975,8 +975,9 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/gotestsum v1.7.0 h1:RwpqwwFKBAa2h+F6pMEGpE707Edld0etUD3GhqqhDNc= gotest.tools/gotestsum v1.7.0/go.mod h1:V1m4Jw3eBerhI/A6qCxUE07RnCg7ACkKj9BYcAm09V8= +gotest.tools/gotestsum v1.8.1 h1:C6dYd5K39WAv52jikEUuWgyMqJDhY90eauUjsFzwluc= +gotest.tools/gotestsum v1.8.1/go.mod h1:ctqdxBSCPv80kAFjYvFNpPntBrE5HAQnLiOKBGLmOBs= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I= From 1715fb0af75c5e39b80d0ac8a23c1ec81c54036e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 5 Jul 2022 06:14:33 +0200 Subject: [PATCH 212/219] chore(ci): check environment in podman pipeline --- .github/workflows/ci-podman.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-podman.yml b/.github/workflows/ci-podman.yml index 748b9ac28d..184302f7e9 100644 --- a/.github/workflows/ci-podman.yml +++ b/.github/workflows/ci-podman.yml @@ -49,4 +49,8 @@ jobs: # many (maybe, all?) images used can only be build on Linux, they don't have Windows in their manifest, and # we can't put Windows Server in "Linux Mode" in Github actions # another, host mode is only available on Linux, and we have tests around that, do we skip them? - run: sudo go run gotest.tools/gotestsum --format short-verbose --rerun-fails=5 --packages="./..." -- -coverprofile=cover.txt \ No newline at end of file + run: sudo go run gotest.tools/gotestsum --format short-verbose --rerun-fails=5 --packages="./..." -- -coverprofile=cover.txt + + - name: Run checker + run: | + ./scripts/check_environment.sh From 23de2c3c9550b5027a5127fc207884be9fc95376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 5 Jul 2022 06:15:50 +0200 Subject: [PATCH 213/219] chore(ci): use make goals in podman pipeline --- .github/workflows/ci-podman.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-podman.yml b/.github/workflows/ci-podman.yml index 184302f7e9..b11173a614 100644 --- a/.github/workflows/ci-podman.yml +++ b/.github/workflows/ci-podman.yml @@ -49,7 +49,11 @@ jobs: # many (maybe, all?) images used can only be build on Linux, they don't have Windows in their manifest, and # we can't put Windows Server in "Linux Mode" in Github actions # another, host mode is only available on Linux, and we have tests around that, do we skip them? - run: sudo go run gotest.tools/gotestsum --format short-verbose --rerun-fails=5 --packages="./..." -- -coverprofile=cover.txt + run: make test-unit + + - name: Run e2e tests + if: ${{ matrix.platform == 'ubuntu-latest' }} + run: make test-e2e - name: Run checker run: | From 333ccdc2598ab5c3748684a8ac1d343a2a25aecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 5 Jul 2022 06:16:32 +0200 Subject: [PATCH 214/219] chore(ci): adjust go modules for each Go version --- .github/workflows/ci-podman.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci-podman.yml b/.github/workflows/ci-podman.yml index b11173a614..d2f6917b51 100644 --- a/.github/workflows/ci-podman.yml +++ b/.github/workflows/ci-podman.yml @@ -44,6 +44,12 @@ jobs: - name: Set DOCKER_HOST run: echo "DOCKER_HOST=unix:///run/podman/podman.sock" >> $GITHUB_ENV + - name: modVerify + run: go mod verify + + - name: modTidy + run: go mod tidy + - name: gotestsum # only run tests on linux, there are a number of things that won't allow the tests to run on anything else # many (maybe, all?) images used can only be build on Linux, they don't have Windows in their manifest, and From 63bad05b882e3d2b0ca65f066cc412b6d3734cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 5 Jul 2022 06:24:44 +0200 Subject: [PATCH 215/219] chore: add Make goal to run mod tidy in the e2e module --- .github/workflows/ci-podman.yml | 3 +++ .github/workflows/ci.yml | 4 ++++ e2e/Makefile | 7 +++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-podman.yml b/.github/workflows/ci-podman.yml index d2f6917b51..98d3b82a11 100644 --- a/.github/workflows/ci-podman.yml +++ b/.github/workflows/ci-podman.yml @@ -57,6 +57,9 @@ jobs: # another, host mode is only available on Linux, and we have tests around that, do we skip them? run: make test-unit + - name: modTidy e2e tests + run: make -C tools-tidy + - name: Run e2e tests if: ${{ matrix.platform == 'ubuntu-latest' }} run: make test-e2e diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 648738244f..e0a484608e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,6 +62,10 @@ jobs: files: ./cover.txt name: testcontainers-go-${{ matrix.go-version }} + - name: modTidy e2e tests + if: ${{ matrix.platform == 'ubuntu-latest' }} + run: make -C tools-tidy + - name: Run e2e tests if: ${{ matrix.platform == 'ubuntu-latest' }} run: make test-e2e diff --git a/e2e/Makefile b/e2e/Makefile index 9e65d3d8a3..7f811e09ed 100644 --- a/e2e/Makefile +++ b/e2e/Makefile @@ -6,7 +6,10 @@ test: tools --rerun-fails=5 \ --packages="./..." \ - .PHONY: tools tools: - go mod download \ No newline at end of file + go mod download + +.PHONY: tools-tidy +tools-tidy: + go mod tidy From 68c533da7fbc5fcf71bc3579b543a39273791e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 5 Jul 2022 06:25:09 +0200 Subject: [PATCH 216/219] chore: remove not needed if --- .github/workflows/ci-podman.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci-podman.yml b/.github/workflows/ci-podman.yml index 98d3b82a11..e10dc8dfb8 100644 --- a/.github/workflows/ci-podman.yml +++ b/.github/workflows/ci-podman.yml @@ -61,7 +61,6 @@ jobs: run: make -C tools-tidy - name: Run e2e tests - if: ${{ matrix.platform == 'ubuntu-latest' }} run: make test-e2e - name: Run checker From 5dfcb8b48b250944bfadb8557cb09e59f2153cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 5 Jul 2022 06:26:08 +0200 Subject: [PATCH 217/219] fix: run podman commands with sudo --- .github/workflows/ci-podman.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-podman.yml b/.github/workflows/ci-podman.yml index e10dc8dfb8..04865edd5d 100644 --- a/.github/workflows/ci-podman.yml +++ b/.github/workflows/ci-podman.yml @@ -58,10 +58,10 @@ jobs: run: make test-unit - name: modTidy e2e tests - run: make -C tools-tidy + run: sudo make -C tools-tidy - name: Run e2e tests - run: make test-e2e + run: sudo make test-e2e - name: Run checker run: | From c67b99252a636a4f3ca1a3318f2624a79392a7b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 5 Jul 2022 06:38:44 +0200 Subject: [PATCH 218/219] fix: wrong sudo --- .github/workflows/ci-podman.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-podman.yml b/.github/workflows/ci-podman.yml index 04865edd5d..c125fdd7a3 100644 --- a/.github/workflows/ci-podman.yml +++ b/.github/workflows/ci-podman.yml @@ -55,10 +55,10 @@ jobs: # many (maybe, all?) images used can only be build on Linux, they don't have Windows in their manifest, and # we can't put Windows Server in "Linux Mode" in Github actions # another, host mode is only available on Linux, and we have tests around that, do we skip them? - run: make test-unit + run: sudo make test-unit - name: modTidy e2e tests - run: sudo make -C tools-tidy + run: make -C tools-tidy - name: Run e2e tests run: sudo make test-e2e From 804fbc028bc698d9846c5f3a2e67cc39213149c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 5 Jul 2022 06:39:33 +0200 Subject: [PATCH 219/219] fix: wrong positioning in Make --- .github/workflows/ci-podman.yml | 2 +- .github/workflows/ci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-podman.yml b/.github/workflows/ci-podman.yml index c125fdd7a3..46967e1095 100644 --- a/.github/workflows/ci-podman.yml +++ b/.github/workflows/ci-podman.yml @@ -58,7 +58,7 @@ jobs: run: sudo make test-unit - name: modTidy e2e tests - run: make -C tools-tidy + run: make -C e2e tools-tidy - name: Run e2e tests run: sudo make test-e2e diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0a484608e..5886b45e80 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: - name: modTidy e2e tests if: ${{ matrix.platform == 'ubuntu-latest' }} - run: make -C tools-tidy + run: make -C e2e tools-tidy - name: Run e2e tests if: ${{ matrix.platform == 'ubuntu-latest' }}