From 4c5f1bd12eae6877d084ce89375f38c4fb2756b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 5 Aug 2024 09:48:43 +0200 Subject: [PATCH 001/126] feat: add grafana-lgtm module (#2660) * feat: init grafana module * chore: refactor layout * chore: add connection methods to the container * chore: a comprenhensive example using Otel libraries * feat<: add option for credentials * fix: lint * docs: mark version for the grafana methods * fix: mod tidy * fix: lint * fix: lint * fix: include schema --- .github/workflows/ci.yml | 2 +- .vscode/.testcontainers-go.code-workspace | 4 + docs/modules/grafana-lgtm.md | 115 +++++++++++ mkdocs.yml | 1 + modules/grafana-lgtm/Makefile | 5 + modules/grafana-lgtm/examples_test.go | 233 ++++++++++++++++++++++ modules/grafana-lgtm/go.mod | 81 ++++++++ modules/grafana-lgtm/go.sum | 209 +++++++++++++++++++ modules/grafana-lgtm/grafana.go | 204 +++++++++++++++++++ modules/grafana-lgtm/grafana_test.go | 64 ++++++ sonar-project.properties | 2 +- 11 files changed, 918 insertions(+), 2 deletions(-) create mode 100644 docs/modules/grafana-lgtm.md create mode 100644 modules/grafana-lgtm/Makefile create mode 100644 modules/grafana-lgtm/examples_test.go create mode 100644 modules/grafana-lgtm/go.mod create mode 100644 modules/grafana-lgtm/go.sum create mode 100644 modules/grafana-lgtm/grafana.go create mode 100644 modules/grafana-lgtm/grafana_test.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90777b871a..5ca90727cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: matrix: go-version: [1.21.x, 1.x] platform: [ubuntu-latest] - module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, dolt, elasticsearch, gcloud, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate] + module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, dolt, elasticsearch, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate] uses: ./.github/workflows/ci-test-go.yml with: go-version: ${{ matrix.go-version }} diff --git a/.vscode/.testcontainers-go.code-workspace b/.vscode/.testcontainers-go.code-workspace index 36ea2777fe..156da3891d 100644 --- a/.vscode/.testcontainers-go.code-workspace +++ b/.vscode/.testcontainers-go.code-workspace @@ -61,6 +61,10 @@ "name": "module / gcloud", "path": "../modules/gcloud" }, + { + "name": "module / grafana-lgtm", + "path": "../modules/grafana-lgtm" + }, { "name": "module / inbucket", "path": "../modules/inbucket" diff --git a/docs/modules/grafana-lgtm.md b/docs/modules/grafana-lgtm.md new file mode 100644 index 0000000000..56e263aac0 --- /dev/null +++ b/docs/modules/grafana-lgtm.md @@ -0,0 +1,115 @@ +# Grafana LGTM + +Not available until the next release of testcontainers-go :material-tag: main + +## Introduction + +The Testcontainers module for Grafana LGTM. + +## Adding this module to your project dependencies + +Please run the following command to add the Grafana module to your Go dependencies: + +``` +go get github.com/testcontainers/testcontainers-go/modules/grafanalgtm +``` + +## Usage example + + +[Creating a Grafana LGTM container](../../modules/grafana-lgtm/examples_test.go) inside_block:runGrafanaLGTMContainer + + +## Module Reference + +### Run function + +- Not available until the next release of testcontainers-go :material-tag: main + +!!!info + The `RunContainer(ctx, opts...)` function is deprecated and will be removed in the next major release of _Testcontainers for Go_. + +The Grafana LGTM module exposes one entrypoint function to create the Grafana LGTM container, and this function receives three parameters: + +```golang +func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*GrafanaLGTMContainer, error) +``` + +- `context.Context`, the Go context. +- `string`, the Docker image to use. +- `testcontainers.ContainerCustomizer`, a variadic argument for passing options. + +### Container Options + +When starting the Grafana LGTM container, you can pass options in a variadic way to configure it. + +#### Image + +If you need to set a different Grafana LGTM Docker image, you can set a valid Docker image as the second argument in the `Run` function. +E.g. `Run(context.Background(), "grafana/otel-lgtm:0.6.0")`. + +#### Admin Credentials + +- Not available until the next release of testcontainers-go :material-tag: main + +If you need to set different admin credentials in the Grafana LGTM container, you can set them using the `WithAdminCredentials(user, password)` option. + +{% include "../features/common_functional_options.md" %} + +### Container Methods + +The Grafana LGTM container exposes the following methods: + +!!!info + All the endpoint methods return their endpoints in the format `:`, so please use them accordingly to configure your client. + +#### Grafana Endpoint + +- Not available until the next release of testcontainers-go :material-tag: main + +The `HttpEndpoint(ctx)` method returns the HTTP endpoint to connect to Grafana, using the default `3000` port. The same method with the `Must` prefix returns just the endpoing, and panics if an error occurs. + +#### Loki Endpoint + +- Not available until the next release of testcontainers-go :material-tag: main + +The `LokiEndpoint(ctx)` method returns the HTTP endpoint to connect to Loki, using the default `3100` port. The same method with the `Must` prefix returns just the endpoing, and panics if an error occurs. + +#### Tempo Endpoint + +- Not available until the next release of testcontainers-go :material-tag: main + +The `TempoEndpoint(ctx)` method returns the HTTP endpoint to connect to Tempo, using the default `3200` port. The same method with the `Must` prefix returns just the endpoing, and panics if an error occurs. + +#### Otel HTTP Endpoint + +- Not available until the next release of testcontainers-go :material-tag: main + +The `OtelHTTPEndpoint(ctx)` method returns the endpoint to connect to Otel using HTTP, using the default `4318` port. The same method with the `Must` prefix returns just the endpoing, and panics if an error occurs. + +#### Otel gRPC Endpoint + +- Not available until the next release of testcontainers-go :material-tag: main + +The `OtelGRPCEndpoint(ctx)` method returns the endpoint to connect to Otel using gRPC, using the default `4317` port. The same method with the `Must` prefix returns just the endpoing, and panics if an error occurs. + +#### Prometheus Endpoint + +- Not available until the next release of testcontainers-go :material-tag: main + +The `PrometheusHttpEndpoint(ctx)` method returns the endpoint to connect to Prometheus, using the default `9090` port. The same method with the `Must` prefix returns just the endpoing, and panics if an error occurs. + +## Examples + +### Traces, Logs and Prometheus metrics for a simple Go process + +In this example, a simple application is created to generate traces, logs, and Prometheus metrics. +The application sends data to Grafana LGTM, and the Otel SDK is used to send the data. +The example demonstrates how to set up the Otel SDK and run the Grafana LGTM module, +configuring the Otel library to send data to Grafana LGTM thanks to the endpoints provided by the Grafana LGTM container. + + +[App sending Otel data](../../modules/grafana-lgtm/examples_test.go) inside_block:rollDiceApp +[Setup Otel SDK](../../modules/grafana-lgtm/examples_test.go) inside_block:setupOTelSDK +[Run the Grafana LGTM container](../../modules/grafana-lgtm/examples_test.go) inside_block:ExampleRun_otelCollector + \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 8309c97871..1494555b0c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -76,6 +76,7 @@ nav: - modules/dolt.md - modules/elasticsearch.md - modules/gcloud.md + - modules/grafana-lgtm.md - modules/inbucket.md - modules/influxdb.md - modules/k3s.md diff --git a/modules/grafana-lgtm/Makefile b/modules/grafana-lgtm/Makefile new file mode 100644 index 0000000000..a49c12c337 --- /dev/null +++ b/modules/grafana-lgtm/Makefile @@ -0,0 +1,5 @@ +include ../../commons-test.mk + +.PHONY: test +test: + $(MAKE) test-grafanalgtm diff --git a/modules/grafana-lgtm/examples_test.go b/modules/grafana-lgtm/examples_test.go new file mode 100644 index 0000000000..c13f1bbd62 --- /dev/null +++ b/modules/grafana-lgtm/examples_test.go @@ -0,0 +1,233 @@ +package grafanalgtm_test + +import ( + "context" + "errors" + "fmt" + golog "log" + "log/slog" + "math/rand" + "sync" + "time" + + "go.opentelemetry.io/contrib/bridges/otelslog" + "go.opentelemetry.io/contrib/instrumentation/runtime" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/otel/exporters/prometheus" + "go.opentelemetry.io/otel/log/global" + metricsapi "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/log" + "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/trace" + + "github.com/testcontainers/testcontainers-go/modules/grafanalgtm" +) + +func ExampleRun() { + // runGrafanaLGTMContainer { + ctx := context.Background() + + grafanaLgtmContainer, err := grafanalgtm.Run(ctx, "grafana/otel-lgtm:0.6.0") + if err != nil { + golog.Fatalf("failed to start container: %s", err) + } + + // Clean up the container + defer func() { + if err := grafanaLgtmContainer.Terminate(ctx); err != nil { + golog.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + } + }() + // } + + state, err := grafanaLgtmContainer.State(ctx) + if err != nil { + golog.Fatalf("failed to get container state: %s", err) // nolint:gocritic + } + + fmt.Println(state.Running) + + // Output: + // true +} + +func ExampleRun_otelCollector() { + ctx := context.Background() + + ctr, err := grafanalgtm.Run(ctx, "grafana/otel-lgtm:0.6.0", grafanalgtm.WithAdminCredentials("admin", "123456789")) + if err != nil { + golog.Fatalf("failed to start Grafana LGTM container: %s", err) + } + defer func() { + if err := ctr.Terminate(ctx); err != nil { + golog.Fatalf("failed to terminate Grafana LGTM container: %s", err) + } + }() + + // Set up OpenTelemetry. + otelShutdown, err := setupOTelSDK(ctx, ctr) + if err != nil { + return + } + // Handle shutdown properly so nothing leaks. + defer func() { + err = errors.Join(err, otelShutdown(context.Background())) + }() + + // roll dice 10000 times, concurrently + max := 10_000 + wg := sync.WaitGroup{} + for i := 0; i < max; i++ { + wg.Add(1) + + go func() { + defer wg.Done() + rolldice(ctx) + }() + } + + wg.Wait() + + // Output: + // shutdown errors: +} + +// setupOTelSDK bootstraps the OpenTelemetry pipeline. +// If it does not return an error, make sure to call shutdown for proper cleanup. +func setupOTelSDK(ctx context.Context, ctr *grafanalgtm.GrafanaLGTMContainer) (shutdown func(context.Context) error, err error) { // nolint:nonamedreturns // this is a pattern in the OpenTelemetry Go SDK + var shutdownFuncs []func(context.Context) error + + // shutdown calls cleanup functions registered via shutdownFuncs. + // The errors from the calls are joined. + // Each registered cleanup will be invoked once. + shutdown = func(ctx context.Context) error { + var err error + for _, fn := range shutdownFuncs { + err = errors.Join(err, fn(ctx)) + } + shutdownFuncs = nil + fmt.Println("shutdown errors:", err) + return err + } + + // handleErr calls shutdown for cleanup and makes sure that all errors are returned. + handleErr := func(inErr error) { + err = errors.Join(inErr, shutdown(ctx)) + } + + prop := propagation.NewCompositeTextMapPropagator( + propagation.TraceContext{}, + propagation.Baggage{}, + ) + otel.SetTextMapPropagator(prop) + + otlpHttpEndpoint := ctr.MustOtlpHttpEndpoint(ctx) + + traceExporter, err := otlptrace.New(ctx, + otlptracehttp.NewClient( + // adding schema to avoid this error: + // 2024/07/19 13:16:30 internal_logging.go:50: "msg"="otlptrace: parse endpoint url" "error"="parse \"127.0.0.1:33007\": first path segment in URL cannot contain colon" "url"="127.0.0.1:33007" + // it does not happen with the logs and metrics exporters + otlptracehttp.WithEndpointURL("http://"+otlpHttpEndpoint), + otlptracehttp.WithInsecure(), + ), + ) + if err != nil { + return nil, err + } + + tracerProvider := trace.NewTracerProvider(trace.WithBatcher(traceExporter)) + if err != nil { + handleErr(err) + return + } + shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) + otel.SetTracerProvider(tracerProvider) + + metricExporter, err := otlpmetrichttp.New(ctx, + otlpmetrichttp.WithInsecure(), + otlpmetrichttp.WithEndpoint(otlpHttpEndpoint), + ) + if err != nil { + return nil, err + } + + // The exporter embeds a default OpenTelemetry Reader and + // implements prometheus.Collector, allowing it to be used as + // both a Reader and Collector. + prometheusExporter, err := prometheus.New() + if err != nil { + return nil, err + } + + meterProvider := metric.NewMeterProvider( + metric.WithReader(metric.NewPeriodicReader(metricExporter)), + metric.WithReader(prometheusExporter), + ) + if err != nil { + handleErr(err) + return + } + shutdownFuncs = append(shutdownFuncs, meterProvider.Shutdown) + otel.SetMeterProvider(meterProvider) + + logExporter, err := otlploghttp.New(ctx, + otlploghttp.WithInsecure(), + otlploghttp.WithEndpoint(otlpHttpEndpoint), + ) + if err != nil { + return nil, err + } + + loggerProvider := log.NewLoggerProvider(log.WithProcessor(log.NewBatchProcessor(logExporter))) + if err != nil { + handleErr(err) + return + } + shutdownFuncs = append(shutdownFuncs, loggerProvider.Shutdown) + global.SetLoggerProvider(loggerProvider) + + err = runtime.Start(runtime.WithMinimumReadMemStatsInterval(time.Second)) + if err != nil { + logger.ErrorContext(ctx, "otel runtime instrumentation failed:", err) // nolint:all // this is a pattern in the OpenTelemetry Go SDK + } + + return +} + +// rollDiceApp { +const schemaName = "https://github.com/grafana/docker-otel-lgtm" + +var ( + tracer = otel.Tracer(schemaName) + logger = otelslog.NewLogger(schemaName) + meter = otel.Meter(schemaName) +) + +func rolldice(ctx context.Context) { + ctx, span := tracer.Start(ctx, "roll") + defer span.End() + + // 20-sided dice + roll := 1 + rand.Intn(20) + logger.InfoContext(ctx, fmt.Sprintf("Rolled a dice: %d\n", roll), slog.Int("result", roll)) + + opt := metricsapi.WithAttributes( + attribute.Key("sides").Int(roll), + ) + + // This is the equivalent of prometheus.NewCounterVec + counter, err := meter.Int64Counter("rolldice-counter", metricsapi.WithDescription("a 20-sided dice")) + if err != nil { + golog.Fatal(err) + } + counter.Add(ctx, int64(roll), opt) +} + +// } diff --git a/modules/grafana-lgtm/go.mod b/modules/grafana-lgtm/go.mod new file mode 100644 index 0000000000..908a5ac70d --- /dev/null +++ b/modules/grafana-lgtm/go.mod @@ -0,0 +1,81 @@ +module github.com/testcontainers/testcontainers-go/modules/grafanalgtm + +go 1.21 + +require ( + github.com/docker/go-connections v0.5.0 + github.com/testcontainers/testcontainers-go v0.32.0 + go.opentelemetry.io/contrib/bridges/otelslog v0.3.0 + go.opentelemetry.io/contrib/instrumentation/runtime v0.53.0 + go.opentelemetry.io/otel v1.28.0 + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.4.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 + go.opentelemetry.io/otel/exporters/prometheus v0.50.0 + go.opentelemetry.io/otel/log v0.4.0 + go.opentelemetry.io/otel/metric v1.28.0 + go.opentelemetry.io/otel/sdk v1.28.0 + go.opentelemetry.io/otel/sdk/log v0.4.0 + go.opentelemetry.io/otel/sdk/metric v1.28.0 +) + +require ( + dario.cat/mergo v1.0.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/containerd/containerd v1.7.18 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/grpc v1.64.1 // indirect + google.golang.org/protobuf v1.34.2 // indirect +) + +replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/grafana-lgtm/go.sum b/modules/grafana-lgtm/go.sum new file mode 100644 index 0000000000..edfa8433f5 --- /dev/null +++ b/modules/grafana-lgtm/go.sum @@ -0,0 +1,209 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +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/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= +github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= +github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= +github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +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.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +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.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/contrib/bridges/otelslog v0.3.0 h1:Kf8NK4WW/pn3f9Gwx6XJAB2zlaW2M3VLQ4sQ3TKJhA8= +go.opentelemetry.io/contrib/bridges/otelslog v0.3.0/go.mod h1:JV00+So1cv6GIYNUeO0xFfl/qE+DUtS3hpBlLIyOFUE= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/contrib/instrumentation/runtime v0.53.0 h1:nOlJEAJyrcy8hexK65M+dsCHIx7CVVbybcFDNkcTcAc= +go.opentelemetry.io/contrib/instrumentation/runtime v0.53.0/go.mod h1:u79lGGIlkg3Ryw425RbMjEkGYNxSnXRyR286O840+u4= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.4.0 h1:zBPZAISA9NOc5cE8zydqDiS0itvg/P/0Hn9m72a5gvM= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.4.0/go.mod h1:gcj2fFjEsqpV3fXuzAA+0Ze1p2/4MJ4T7d77AmkvueQ= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0 h1:aLmmtjRke7LPDQ3lvpFz+kNEH43faFhzW7v8BFIEydg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0/go.mod h1:TC1pyCt6G9Sjb4bQpShH+P5R53pO6ZuGnHuuln9xMeE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 h1:j9+03ymgYhPKmeXGk5Zu+cIZOlVzd9Zv7QIiyItjFBU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0/go.mod h1:Y5+XiUG4Emn1hTfciPzGPJaSI+RpDts6BnCIir0SLqk= +go.opentelemetry.io/otel/exporters/prometheus v0.50.0 h1:2Ewsda6hejmbhGFyUvWZjUThC98Cf8Zy6g0zkIimOng= +go.opentelemetry.io/otel/exporters/prometheus v0.50.0/go.mod h1:pMm5PkUo5YwbLiuEf7t2xg4wbP0/eSJrMxIMxKosynY= +go.opentelemetry.io/otel/log v0.4.0 h1:/vZ+3Utqh18e8TPjuc3ecg284078KWrR8BRz+PQAj3o= +go.opentelemetry.io/otel/log v0.4.0/go.mod h1:DhGnQvky7pHy82MIRV43iXh3FlKN8UUKftn0KbLOq6I= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/sdk/log v0.4.0 h1:1mMI22L82zLqf6KtkjrRy5BbagOTWdJsqMY/HSqILAA= +go.opentelemetry.io/otel/sdk/log v0.4.0/go.mod h1:AYJ9FVF0hNOgAVzUG/ybg/QttnXhUePWAupmCqtdESo= +go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= +go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +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/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/modules/grafana-lgtm/grafana.go b/modules/grafana-lgtm/grafana.go new file mode 100644 index 0000000000..1e2f33adba --- /dev/null +++ b/modules/grafana-lgtm/grafana.go @@ -0,0 +1,204 @@ +package grafanalgtm + +import ( + "context" + "fmt" + + "github.com/docker/go-connections/nat" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +const ( + GrafanaPort = "3000/tcp" + LokiPort = "3100/tcp" + TempoPort = "3200/tcp" + OtlpGrpcPort = "4317/tcp" + OtlpHttpPort = "4318/tcp" + PrometheusPort = "9090/tcp" +) + +// GrafanaLGTMContainer represents the Grafana LGTM container type used in the module +type GrafanaLGTMContainer struct { + testcontainers.Container +} + +// Run creates an instance of the Grafana LGTM container type +func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*GrafanaLGTMContainer, error) { + req := testcontainers.ContainerRequest{ + Image: img, + ExposedPorts: []string{GrafanaPort, LokiPort, TempoPort, OtlpGrpcPort, OtlpHttpPort, PrometheusPort}, + WaitingFor: wait.ForLog(".*The OpenTelemetry collector and the Grafana LGTM stack are up and running.*\\s").AsRegexp().WithOccurrence(1), + } + + genericContainerReq := testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + } + + for _, opt := range opts { + if err := opt.Customize(&genericContainerReq); err != nil { + return nil, fmt.Errorf("customize: %w", err) + } + } + + container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + if err != nil { + return nil, err + } + + c := &GrafanaLGTMContainer{Container: container} + + url, err := c.OtlpHttpEndpoint(ctx) + if err != nil { + // return the container instance to allow the caller to clean up + return c, err + } + + testcontainers.Logger.Printf("Access to the Grafana dashboard: %s", url) + + return c, nil +} + +// WithAdminCredentials sets the admin credentials for the Grafana LGTM container +func WithAdminCredentials(user, password string) testcontainers.ContainerCustomizer { + return testcontainers.WithEnv(map[string]string{ + "GF_SECURITY_ADMIN_USER": user, + "GF_SECURITY_ADMIN_PASSWORD": password, + }) +} + +// LokiEndpoint returns the Loki endpoint +func (c *GrafanaLGTMContainer) LokiEndpoint(ctx context.Context) (string, error) { + url, err := baseEndpoint(ctx, c, LokiPort) + if err != nil { + return "", err + } + + return url, nil +} + +// MustLokiEndpoint returns the Loki endpoint or panics if an error occurs +func (c *GrafanaLGTMContainer) MustLokiEndpoint(ctx context.Context) string { + url, err := c.LokiEndpoint(ctx) + if err != nil { + panic(err) + } + + return url +} + +// TempoEndpoint returns the Tempo endpoint +func (c *GrafanaLGTMContainer) TempoEndpoint(ctx context.Context) (string, error) { + url, err := baseEndpoint(ctx, c, TempoPort) + if err != nil { + return "", err + } + + return url, nil +} + +// MustTempoEndpoint returns the Tempo endpoint or panics if an error occurs +func (c *GrafanaLGTMContainer) MustTempoEndpoint(ctx context.Context) string { + url, err := c.TempoEndpoint(ctx) + if err != nil { + panic(err) + } + + return url +} + +// HttpEndpoint returns the HTTP URL +func (c *GrafanaLGTMContainer) HttpEndpoint(ctx context.Context) (string, error) { + url, err := baseEndpoint(ctx, c, GrafanaPort) + if err != nil { + return "", err + } + + return url, nil +} + +// MustHttpEndpoint returns the HTTP endpoint or panics if an error occurs +func (c *GrafanaLGTMContainer) MustHttpEndpoint(ctx context.Context) string { + url, err := c.HttpEndpoint(ctx) + if err != nil { + panic(err) + } + + return url +} + +// OtlpHttpEndpoint returns the OTLP HTTP endpoint +func (c *GrafanaLGTMContainer) OtlpHttpEndpoint(ctx context.Context) (string, error) { + url, err := baseEndpoint(ctx, c, OtlpHttpPort) + if err != nil { + return "", err + } + + return url, nil +} + +// MustOtlpHttpEndpoint returns the OTLP HTTP endpoint or panics if an error occurs +func (c *GrafanaLGTMContainer) MustOtlpHttpEndpoint(ctx context.Context) string { + url, err := c.OtlpHttpEndpoint(ctx) + if err != nil { + panic(err) + } + + return url +} + +// OtlpGrpcEndpoint returns the OTLP gRPC endpoint +func (c *GrafanaLGTMContainer) OtlpGrpcEndpoint(ctx context.Context) (string, error) { + url, err := baseEndpoint(ctx, c, OtlpGrpcPort) + if err != nil { + return "", err + } + + return url, nil +} + +// MustOtlpGrpcEndpoint returns the OTLP gRPC endpoint or panics if an error occurs +func (c *GrafanaLGTMContainer) MustOtlpGrpcEndpoint(ctx context.Context) string { + url, err := c.OtlpGrpcEndpoint(ctx) + if err != nil { + panic(err) + } + + return url +} + +// PrometheusHttpEndpoint returns the Prometheus HTTP endpoint +func (c *GrafanaLGTMContainer) PrometheusHttpEndpoint(ctx context.Context) (string, error) { + url, err := baseEndpoint(ctx, c, PrometheusPort) + if err != nil { + return "", err + } + + return url, nil +} + +// MustPrometheusHttpEndpoint returns the Prometheus HTTP endpoint or panics if an error occurs +func (c *GrafanaLGTMContainer) MustPrometheusHttpEndpoint(ctx context.Context) string { + url, err := c.PrometheusHttpEndpoint(ctx) + if err != nil { + panic(err) + } + + return url +} + +func baseEndpoint(ctx context.Context, c *GrafanaLGTMContainer, port nat.Port) (string, error) { + host, err := c.Host(ctx) + if err != nil { + return "", err + } + + mappedPort, err := c.MappedPort(ctx, port) + if err != nil { + return "", err + } + + return fmt.Sprintf("%s:%s", host, mappedPort.Port()), nil +} diff --git a/modules/grafana-lgtm/grafana_test.go b/modules/grafana-lgtm/grafana_test.go new file mode 100644 index 0000000000..b0a4960616 --- /dev/null +++ b/modules/grafana-lgtm/grafana_test.go @@ -0,0 +1,64 @@ +package grafanalgtm_test + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "net/url" + "testing" + + "github.com/testcontainers/testcontainers-go/modules/grafanalgtm" +) + +func TestGrafanaLGTM(t *testing.T) { + ctx := context.Background() + + grafanaLgtmContainer, err := grafanalgtm.Run(ctx, "grafana/otel-lgtm:0.6.0") + if err != nil { + t.Fatal(err) + } + + // Clean up the container after the test is complete + t.Cleanup(func() { + if err := grafanaLgtmContainer.Terminate(ctx); err != nil { + t.Fatalf("failed to terminate container: %s", err) + } + }) + + // perform assertions + + t.Run("container is running with right version", func(t *testing.T) { + healthURL, err := url.Parse(fmt.Sprintf("http://%s/api/health", grafanaLgtmContainer.MustHttpEndpoint(ctx))) + if err != nil { + t.Fatal(err) + } + + httpReq := http.Request{ + Method: http.MethodGet, + URL: healthURL, + } + + httpClient := http.Client{} + + httpResp, err := httpClient.Do(&httpReq) + if err != nil { + t.Fatal(err) + } + defer httpResp.Body.Close() + + if httpResp.StatusCode != http.StatusOK { + t.Fatalf("expected status code %d, got %d", http.StatusOK, httpResp.StatusCode) + } + + body := make(map[string]interface{}) + err = json.NewDecoder(httpResp.Body).Decode(&body) + if err != nil { + t.Fatal(err) + } + + if body["version"] != "11.0.0" { + t.Fatalf("expected version %q, got %q", "11.0.0", body["version"]) + } + }) +} diff --git a/sonar-project.properties b/sonar-project.properties index ca7f011398..d93e935f5f 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -18,4 +18,4 @@ sonar.test.inclusions=**/*_test.go sonar.test.exclusions=**/vendor/** sonar.go.coverage.reportPaths=**/coverage.out -sonar.go.tests.reportPaths=TEST-unit.xml,examples/nginx/TEST-unit.xml,examples/toxiproxy/TEST-unit.xml,modulegen/TEST-unit.xml,modules/artemis/TEST-unit.xml,modules/azurite/TEST-unit.xml,modules/cassandra/TEST-unit.xml,modules/chroma/TEST-unit.xml,modules/clickhouse/TEST-unit.xml,modules/cockroachdb/TEST-unit.xml,modules/compose/TEST-unit.xml,modules/consul/TEST-unit.xml,modules/couchbase/TEST-unit.xml,modules/dolt/TEST-unit.xml,modules/elasticsearch/TEST-unit.xml,modules/gcloud/TEST-unit.xml,modules/inbucket/TEST-unit.xml,modules/influxdb/TEST-unit.xml,modules/k3s/TEST-unit.xml,modules/k6/TEST-unit.xml,modules/kafka/TEST-unit.xml,modules/localstack/TEST-unit.xml,modules/mariadb/TEST-unit.xml,modules/milvus/TEST-unit.xml,modules/minio/TEST-unit.xml,modules/mockserver/TEST-unit.xml,modules/mongodb/TEST-unit.xml,modules/mssql/TEST-unit.xml,modules/mysql/TEST-unit.xml,modules/nats/TEST-unit.xml,modules/neo4j/TEST-unit.xml,modules/ollama/TEST-unit.xml,modules/openfga/TEST-unit.xml,modules/openldap/TEST-unit.xml,modules/opensearch/TEST-unit.xml,modules/postgres/TEST-unit.xml,modules/pulsar/TEST-unit.xml,modules/qdrant/TEST-unit.xml,modules/rabbitmq/TEST-unit.xml,modules/redis/TEST-unit.xml,modules/redpanda/TEST-unit.xml,modules/registry/TEST-unit.xml,modules/surrealdb/TEST-unit.xml,modules/valkey/TEST-unit.xml,modules/vault/TEST-unit.xml,modules/vearch/TEST-unit.xml,modules/weaviate/TEST-unit.xml +sonar.go.tests.reportPaths=TEST-unit.xml,examples/nginx/TEST-unit.xml,examples/toxiproxy/TEST-unit.xml,modulegen/TEST-unit.xml,modules/artemis/TEST-unit.xml,modules/azurite/TEST-unit.xml,modules/cassandra/TEST-unit.xml,modules/chroma/TEST-unit.xml,modules/clickhouse/TEST-unit.xml,modules/cockroachdb/TEST-unit.xml,modules/compose/TEST-unit.xml,modules/consul/TEST-unit.xml,modules/couchbase/TEST-unit.xml,modules/dolt/TEST-unit.xml,modules/elasticsearch/TEST-unit.xml,modules/gcloud/TEST-unit.xml,modules/grafana-lgtm/TEST-unit.xml,modules/inbucket/TEST-unit.xml,modules/influxdb/TEST-unit.xml,modules/k3s/TEST-unit.xml,modules/k6/TEST-unit.xml,modules/kafka/TEST-unit.xml,modules/localstack/TEST-unit.xml,modules/mariadb/TEST-unit.xml,modules/milvus/TEST-unit.xml,modules/minio/TEST-unit.xml,modules/mockserver/TEST-unit.xml,modules/mongodb/TEST-unit.xml,modules/mssql/TEST-unit.xml,modules/mysql/TEST-unit.xml,modules/nats/TEST-unit.xml,modules/neo4j/TEST-unit.xml,modules/ollama/TEST-unit.xml,modules/openfga/TEST-unit.xml,modules/openldap/TEST-unit.xml,modules/opensearch/TEST-unit.xml,modules/postgres/TEST-unit.xml,modules/pulsar/TEST-unit.xml,modules/qdrant/TEST-unit.xml,modules/rabbitmq/TEST-unit.xml,modules/redis/TEST-unit.xml,modules/redpanda/TEST-unit.xml,modules/registry/TEST-unit.xml,modules/surrealdb/TEST-unit.xml,modules/valkey/TEST-unit.xml,modules/vault/TEST-unit.xml,modules/vearch/TEST-unit.xml,modules/weaviate/TEST-unit.xml From 9e8d4e7b9d9e1e7fb404a5bce045dd5808ddac95 Mon Sep 17 00:00:00 2001 From: Robin Vanderstraeten Date: Mon, 5 Aug 2024 16:05:36 +0200 Subject: [PATCH 002/126] fix: incorrect parsing of exposedPorts in readiness check (#2658) * Fix incorrect parsing of exposedPorts in readiness check * Add tests for port mapping check in lifecycle.go * Apply suggestions from code review * Apply review comments * Add testcase with explicit ipv4 binding --- lifecycle.go | 49 ++++++++++++++++++++-------------- lifecycle_test.go | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 20 deletions(-) diff --git a/lifecycle.go b/lifecycle.go index a40ebc0fac..a0c6b99b88 100644 --- a/lifecycle.go +++ b/lifecycle.go @@ -198,6 +198,34 @@ var defaultLogConsumersHook = func(cfg *LogConsumerConfig) ContainerLifecycleHoo } } +func checkPortsMapped(exposedAndMappedPorts nat.PortMap, exposedPorts []string) error { + portMap, _, err := nat.ParsePortSpecs(exposedPorts) + if err != nil { + return fmt.Errorf("parse exposed ports: %w", err) + } + + for exposedPort := range portMap { + // having entries in exposedAndMappedPorts, where the key is the exposed port, + // and the value is the mapped port, means that the port has been already mapped. + if _, ok := exposedAndMappedPorts[exposedPort]; ok { + continue + } + + // check if the port is mapped with the protocol (default is TCP) + if strings.Contains(string(exposedPort), "/") { + return fmt.Errorf("port %s is not mapped yet", exposedPort) + } + + // Port didn't have a type, default to tcp and retry. + exposedPort += "/tcp" + if _, ok := exposedAndMappedPorts[exposedPort]; !ok { + return fmt.Errorf("port %s is not mapped yet", exposedPort) + } + } + + return nil +} + // defaultReadinessHook is a hook that will wait for the container to be ready var defaultReadinessHook = func() ContainerLifecycleHooks { return ContainerLifecycleHooks{ @@ -222,26 +250,7 @@ var defaultReadinessHook = func() ContainerLifecycleHooks { return err } - exposedAndMappedPorts := jsonRaw.NetworkSettings.Ports - - for _, exposedPort := range dockerContainer.exposedPorts { - portMap := nat.Port(exposedPort) - // having entries in exposedAndMappedPorts, where the key is the exposed port, - // and the value is the mapped port, means that the port has been already mapped. - if _, ok := exposedAndMappedPorts[portMap]; !ok { - // check if the port is mapped with the protocol (default is TCP) - if !strings.Contains(exposedPort, "/") { - portMap = nat.Port(fmt.Sprintf("%s/tcp", exposedPort)) - if _, ok := exposedAndMappedPorts[portMap]; !ok { - return fmt.Errorf("port %s is not mapped yet", exposedPort) - } - } else { - return fmt.Errorf("port %s is not mapped yet", exposedPort) - } - } - } - - return nil + return checkPortsMapped(jsonRaw.NetworkSettings.Ports, dockerContainer.exposedPorts) }, b, func(err error, duration time.Duration) { diff --git a/lifecycle_test.go b/lifecycle_test.go index 95ee4c5f5a..f4b0a2ae37 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -456,6 +456,73 @@ func TestMergePortBindings(t *testing.T) { } } +func TestPortMappingCheck(t *testing.T) { + makePortMap := func(ports ...string) nat.PortMap { + out := make(nat.PortMap) + for _, port := range ports { + // We don't care about the actual binding in this test + out[nat.Port(port)] = nil + } + return out + } + + tests := map[string]struct { + exposedAndMappedPorts nat.PortMap + exposedPorts []string + expectError bool + }{ + "no-protocol": { + exposedAndMappedPorts: makePortMap("1024/tcp"), + exposedPorts: []string{"1024"}, + }, + "protocol": { + exposedAndMappedPorts: makePortMap("1024/tcp"), + exposedPorts: []string{"1024/tcp"}, + }, + "protocol-target-port": { + exposedAndMappedPorts: makePortMap("1024/tcp"), + exposedPorts: []string{"1024:1024/tcp"}, + }, + "target-port": { + exposedAndMappedPorts: makePortMap("1024/tcp"), + exposedPorts: []string{"1024:1024"}, + }, + "multiple-ports": { + exposedAndMappedPorts: makePortMap("1024/tcp", "1025/tcp", "1026/tcp"), + exposedPorts: []string{"1024", "25:1025/tcp", "1026:1026"}, + }, + "only-ipv4": { + exposedAndMappedPorts: makePortMap("1024/tcp"), + exposedPorts: []string{"0.0.0.0::1024/tcp"}, + }, + "no-mapped-ports": { + exposedAndMappedPorts: makePortMap(), + exposedPorts: []string{"1024"}, + expectError: true, + }, + "wrong-mapped-port": { + exposedAndMappedPorts: makePortMap("1023/tcp"), + exposedPorts: []string{"1024"}, + expectError: true, + }, + "subset-mapped-ports": { + exposedAndMappedPorts: makePortMap("1024/tcp", "1025/tcp"), + exposedPorts: []string{"1024", "1025", "1026"}, + expectError: true, + }, + } + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + err := checkPortsMapped(tt.exposedAndMappedPorts, tt.exposedPorts) + if tt.expectError { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} + func TestLifecycleHooks(t *testing.T) { tests := []struct { name string From b78a3512ff1e76f90f9b0bbd8b1795fb6be51345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 5 Aug 2024 16:31:47 +0200 Subject: [PATCH 003/126] chore: print Docker Info labels in banner (#2681) --- docker_client.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docker_client.go b/docker_client.go index 105b994e4f..c8e8e825b0 100644 --- a/docker_client.go +++ b/docker_client.go @@ -57,17 +57,27 @@ func (c *DockerClient) Info(ctx context.Context) (system.Info, error) { Server Version: %v API Version: %v Operating System: %v - Total Memory: %v MB + Total Memory: %v MB%s Testcontainers for Go Version: v%s Resolved Docker Host: %s Resolved Docker Socket Path: %s Test SessionID: %s Test ProcessID: %s ` + infoLabels := "" + if len(dockerInfo.Labels) > 0 { + infoLabels = ` + Labels:` + for _, lb := range dockerInfo.Labels { + infoLabels += "\n " + lb + } + } Logger.Printf(infoMessage, packagePath, - dockerInfo.ServerVersion, c.Client.ClientVersion(), + dockerInfo.ServerVersion, + c.Client.ClientVersion(), dockerInfo.OperatingSystem, dockerInfo.MemTotal/1024/1024, + infoLabels, internal.Version, core.ExtractDockerHost(ctx), core.ExtractDockerSocket(ctx), From 8b421435f0ddd5c4b64e30834f94c2550751c9ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 6 Aug 2024 17:42:55 +0200 Subject: [PATCH 004/126] chore(deps): bump github.com/docker/docker from 27.0.3+incompatible to 27.1.0+incompatible (#2682) --- examples/nginx/go.mod | 2 +- examples/nginx/go.sum | 4 ++-- examples/toxiproxy/go.mod | 2 +- examples/toxiproxy/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- modules/artemis/go.mod | 2 +- modules/artemis/go.sum | 4 ++-- modules/azurite/go.mod | 2 +- modules/azurite/go.sum | 4 ++-- modules/cassandra/go.mod | 2 +- modules/cassandra/go.sum | 4 ++-- modules/chroma/go.mod | 2 +- modules/chroma/go.sum | 4 ++-- modules/clickhouse/go.mod | 2 +- modules/clickhouse/go.sum | 4 ++-- modules/cockroachdb/go.mod | 2 +- modules/cockroachdb/go.sum | 4 ++-- modules/compose/go.mod | 2 +- modules/compose/go.sum | 4 ++-- modules/consul/go.mod | 2 +- modules/consul/go.sum | 4 ++-- modules/couchbase/go.mod | 2 +- modules/couchbase/go.sum | 4 ++-- modules/dolt/go.mod | 2 +- modules/dolt/go.sum | 4 ++-- modules/elasticsearch/go.mod | 2 +- modules/elasticsearch/go.sum | 4 ++-- modules/gcloud/go.mod | 2 +- modules/gcloud/go.sum | 4 ++-- modules/grafana-lgtm/go.mod | 2 +- modules/grafana-lgtm/go.sum | 4 ++-- modules/inbucket/go.mod | 2 +- modules/inbucket/go.sum | 4 ++-- modules/influxdb/go.mod | 2 +- modules/influxdb/go.sum | 4 ++-- modules/k3s/go.mod | 2 +- modules/k3s/go.sum | 4 ++-- modules/k6/go.mod | 2 +- modules/k6/go.sum | 4 ++-- modules/kafka/go.mod | 2 +- modules/kafka/go.sum | 4 ++-- modules/localstack/go.mod | 2 +- modules/localstack/go.sum | 4 ++-- modules/mariadb/go.mod | 2 +- modules/mariadb/go.sum | 4 ++-- modules/milvus/go.mod | 2 +- modules/milvus/go.sum | 4 ++-- modules/minio/go.mod | 2 +- modules/minio/go.sum | 4 ++-- modules/mockserver/go.mod | 2 +- modules/mockserver/go.sum | 4 ++-- modules/mongodb/go.mod | 2 +- modules/mongodb/go.sum | 4 ++-- modules/mssql/go.mod | 2 +- modules/mssql/go.sum | 4 ++-- modules/mysql/go.mod | 2 +- modules/mysql/go.sum | 4 ++-- modules/nats/go.mod | 2 +- modules/nats/go.sum | 4 ++-- modules/neo4j/go.mod | 2 +- modules/neo4j/go.sum | 4 ++-- modules/ollama/go.mod | 2 +- modules/ollama/go.sum | 4 ++-- modules/openfga/go.mod | 2 +- modules/openfga/go.sum | 4 ++-- modules/openldap/go.mod | 2 +- modules/openldap/go.sum | 4 ++-- modules/opensearch/go.mod | 2 +- modules/opensearch/go.sum | 4 ++-- modules/postgres/go.mod | 2 +- modules/postgres/go.sum | 4 ++-- modules/pulsar/go.mod | 2 +- modules/pulsar/go.sum | 4 ++-- modules/qdrant/go.mod | 2 +- modules/qdrant/go.sum | 4 ++-- modules/rabbitmq/go.mod | 2 +- modules/rabbitmq/go.sum | 4 ++-- modules/redis/go.mod | 2 +- modules/redis/go.sum | 4 ++-- modules/redpanda/go.mod | 2 +- modules/redpanda/go.sum | 4 ++-- modules/registry/go.mod | 2 +- modules/registry/go.sum | 4 ++-- modules/surrealdb/go.mod | 2 +- modules/surrealdb/go.sum | 4 ++-- modules/valkey/go.mod | 2 +- modules/valkey/go.sum | 5 ++--- modules/vault/go.mod | 2 +- modules/vault/go.sum | 4 ++-- modules/vearch/go.mod | 2 +- modules/vearch/go.sum | 4 ++-- modules/weaviate/go.mod | 2 +- modules/weaviate/go.sum | 4 ++-- 94 files changed, 141 insertions(+), 142 deletions(-) diff --git a/examples/nginx/go.mod b/examples/nginx/go.mod index d75ec5ab02..a9aea2bea1 100644 --- a/examples/nginx/go.mod +++ b/examples/nginx/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/examples/nginx/go.sum b/examples/nginx/go.sum index a9ce8a33e4..4de62e95bc 100644 --- a/examples/nginx/go.sum +++ b/examples/nginx/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/examples/toxiproxy/go.mod b/examples/toxiproxy/go.mod index c406242001..1b0f4663da 100644 --- a/examples/toxiproxy/go.mod +++ b/examples/toxiproxy/go.mod @@ -21,7 +21,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/examples/toxiproxy/go.sum b/examples/toxiproxy/go.sum index 4436859612..d659cb13a3 100644 --- a/examples/toxiproxy/go.sum +++ b/examples/toxiproxy/go.sum @@ -29,8 +29,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/go.mod b/go.mod index 18c8786236..2ed17ab739 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 github.com/containerd/platforms v0.2.1 github.com/cpuguy83/dockercfg v0.3.1 - github.com/docker/docker v27.0.3+incompatible + github.com/docker/docker v27.1.0+incompatible github.com/docker/go-connections v0.5.0 github.com/google/uuid v1.6.0 github.com/magiconair/properties v1.8.7 diff --git a/go.sum b/go.sum index 2348e9e39e..02f7ebe239 100644 --- a/go.sum +++ b/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/artemis/go.mod b/modules/artemis/go.mod index feb41d93e8..e1fcc9958e 100644 --- a/modules/artemis/go.mod +++ b/modules/artemis/go.mod @@ -20,7 +20,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/artemis/go.sum b/modules/artemis/go.sum index e64a943d75..1db6255fae 100644 --- a/modules/artemis/go.sum +++ b/modules/artemis/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/azurite/go.mod b/modules/azurite/go.mod index 42fd1a48f5..e18fad7050 100644 --- a/modules/azurite/go.mod +++ b/modules/azurite/go.mod @@ -22,7 +22,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/azurite/go.sum b/modules/azurite/go.sum index c1f9336e48..64bfb07809 100644 --- a/modules/azurite/go.sum +++ b/modules/azurite/go.sum @@ -41,8 +41,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/cassandra/go.mod b/modules/cassandra/go.mod index e62008917e..28207451e7 100644 --- a/modules/cassandra/go.mod +++ b/modules/cassandra/go.mod @@ -20,7 +20,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/cassandra/go.sum b/modules/cassandra/go.sum index a6779dad28..f939709a99 100644 --- a/modules/cassandra/go.sum +++ b/modules/cassandra/go.sum @@ -27,8 +27,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/chroma/go.mod b/modules/chroma/go.mod index 08abc8839b..4908b5b85b 100644 --- a/modules/chroma/go.mod +++ b/modules/chroma/go.mod @@ -20,7 +20,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/chroma/go.sum b/modules/chroma/go.sum index a79ea2cd12..916290f592 100644 --- a/modules/chroma/go.sum +++ b/modules/chroma/go.sum @@ -28,8 +28,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/clickhouse/go.mod b/modules/clickhouse/go.mod index 88ff270687..ea35c63b57 100644 --- a/modules/clickhouse/go.mod +++ b/modules/clickhouse/go.mod @@ -22,7 +22,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-faster/city v1.0.1 // indirect diff --git a/modules/clickhouse/go.sum b/modules/clickhouse/go.sum index 41d1b5dcb3..8923b01965 100644 --- a/modules/clickhouse/go.sum +++ b/modules/clickhouse/go.sum @@ -29,8 +29,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/cockroachdb/go.mod b/modules/cockroachdb/go.mod index e97cb6374e..561f247d29 100644 --- a/modules/cockroachdb/go.mod +++ b/modules/cockroachdb/go.mod @@ -26,7 +26,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/cockroachdb/go.sum b/modules/cockroachdb/go.sum index d46fd15723..7f47c1bc1c 100644 --- a/modules/cockroachdb/go.sum +++ b/modules/cockroachdb/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/compose/go.mod b/modules/compose/go.mod index 3949c1e86e..2e076ed60e 100644 --- a/modules/compose/go.mod +++ b/modules/compose/go.mod @@ -8,7 +8,7 @@ require ( github.com/compose-spec/compose-go/v2 v2.1.3 github.com/docker/cli v27.0.3+incompatible github.com/docker/compose/v2 v2.28.1 - github.com/docker/docker v27.0.3+incompatible + github.com/docker/docker v27.1.0+incompatible github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.32.0 diff --git a/modules/compose/go.sum b/modules/compose/go.sum index 568ca8dc24..8eec100162 100644 --- a/modules/compose/go.sum +++ b/modules/compose/go.sum @@ -135,8 +135,8 @@ github.com/docker/compose/v2 v2.28.1/go.mod h1:wDtGQFHe99sPLCHXeVbCkc+Wsl4Y/2Zxi github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= diff --git a/modules/consul/go.mod b/modules/consul/go.mod index 53717b86e4..abff142961 100644 --- a/modules/consul/go.mod +++ b/modules/consul/go.mod @@ -20,7 +20,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/fatih/color v1.14.1 // indirect diff --git a/modules/consul/go.sum b/modules/consul/go.sum index 347b5c34eb..e497d639f3 100644 --- a/modules/consul/go.sum +++ b/modules/consul/go.sum @@ -42,8 +42,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/couchbase/go.mod b/modules/couchbase/go.mod index d899c2e7db..03a0563970 100644 --- a/modules/couchbase/go.mod +++ b/modules/couchbase/go.mod @@ -25,7 +25,7 @@ require ( github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20230515165046-68b522a21131 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/couchbase/go.sum b/modules/couchbase/go.sum index 107d31c3ed..e1ce1bbbce 100644 --- a/modules/couchbase/go.sum +++ b/modules/couchbase/go.sum @@ -42,8 +42,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/dolt/go.mod b/modules/dolt/go.mod index 4491748fe6..d259079a24 100644 --- a/modules/dolt/go.mod +++ b/modules/dolt/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/dolt/go.sum b/modules/dolt/go.sum index 87012342fc..5edb490b56 100644 --- a/modules/dolt/go.sum +++ b/modules/dolt/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/elasticsearch/go.mod b/modules/elasticsearch/go.mod index 8e145f140c..35f0f4af03 100644 --- a/modules/elasticsearch/go.mod +++ b/modules/elasticsearch/go.mod @@ -20,7 +20,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/elastic/elastic-transport-go/v8 v8.4.0 // indirect diff --git a/modules/elasticsearch/go.sum b/modules/elasticsearch/go.sum index 3a75a7a654..5c238b73f5 100644 --- a/modules/elasticsearch/go.sum +++ b/modules/elasticsearch/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/gcloud/go.mod b/modules/gcloud/go.mod index 22fb675212..825dcfeed0 100644 --- a/modules/gcloud/go.mod +++ b/modules/gcloud/go.mod @@ -34,7 +34,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/envoyproxy/go-control-plane v0.12.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect diff --git a/modules/gcloud/go.sum b/modules/gcloud/go.sum index 9bcba12093..f1d231f03a 100644 --- a/modules/gcloud/go.sum +++ b/modules/gcloud/go.sum @@ -64,8 +64,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/grafana-lgtm/go.mod b/modules/grafana-lgtm/go.mod index 908a5ac70d..30f96bce2a 100644 --- a/modules/grafana-lgtm/go.mod +++ b/modules/grafana-lgtm/go.mod @@ -32,7 +32,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect diff --git a/modules/grafana-lgtm/go.sum b/modules/grafana-lgtm/go.sum index edfa8433f5..8a6e413e91 100644 --- a/modules/grafana-lgtm/go.sum +++ b/modules/grafana-lgtm/go.sum @@ -27,8 +27,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/inbucket/go.mod b/modules/inbucket/go.mod index d15183a36b..f6f7ba6f96 100644 --- a/modules/inbucket/go.mod +++ b/modules/inbucket/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/inbucket/go.sum b/modules/inbucket/go.sum index b9d1903fbc..0f998df7df 100644 --- a/modules/inbucket/go.sum +++ b/modules/inbucket/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/influxdb/go.mod b/modules/influxdb/go.mod index faec63e405..a8c0be530a 100644 --- a/modules/influxdb/go.mod +++ b/modules/influxdb/go.mod @@ -19,7 +19,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/influxdb/go.sum b/modules/influxdb/go.sum index 6d8662274b..52e9ccd448 100644 --- a/modules/influxdb/go.sum +++ b/modules/influxdb/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/k3s/go.mod b/modules/k3s/go.mod index 4ff4335a93..f92938778d 100644 --- a/modules/k3s/go.mod +++ b/modules/k3s/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/k3s go 1.21 require ( - github.com/docker/docker v27.0.3+incompatible + github.com/docker/docker v27.1.0+incompatible github.com/docker/go-connections v0.5.0 github.com/testcontainers/testcontainers-go v0.32.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/modules/k3s/go.sum b/modules/k3s/go.sum index cb1b428ec9..01ba28c4f0 100644 --- a/modules/k3s/go.sum +++ b/modules/k3s/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/k6/go.mod b/modules/k6/go.mod index 0586fa06b3..1c752f3db2 100644 --- a/modules/k6/go.mod +++ b/modules/k6/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/k6 go 1.21 require ( - github.com/docker/docker v27.0.3+incompatible + github.com/docker/docker v27.1.0+incompatible github.com/testcontainers/testcontainers-go v0.32.0 ) diff --git a/modules/k6/go.sum b/modules/k6/go.sum index a9ce8a33e4..4de62e95bc 100644 --- a/modules/k6/go.sum +++ b/modules/k6/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/kafka/go.mod b/modules/kafka/go.mod index 8dc77c41e0..6545097462 100644 --- a/modules/kafka/go.mod +++ b/modules/kafka/go.mod @@ -20,7 +20,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/eapache/go-resiliency v1.4.0 // indirect github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect diff --git a/modules/kafka/go.sum b/modules/kafka/go.sum index f7dc2c69e9..1c5d061e6f 100644 --- a/modules/kafka/go.sum +++ b/modules/kafka/go.sum @@ -25,8 +25,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/localstack/go.mod b/modules/localstack/go.mod index 3abbd4cf9e..b6324b8740 100644 --- a/modules/localstack/go.mod +++ b/modules/localstack/go.mod @@ -8,7 +8,7 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.27.5 github.com/aws/aws-sdk-go-v2/credentials v1.17.5 github.com/aws/aws-sdk-go-v2/service/s3 v1.51.2 - github.com/docker/docker v27.0.3+incompatible + github.com/docker/docker v27.1.0+incompatible github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.32.0 diff --git a/modules/localstack/go.sum b/modules/localstack/go.sum index 3f321b88ba..c12b81d9f5 100644 --- a/modules/localstack/go.sum +++ b/modules/localstack/go.sum @@ -62,8 +62,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/mariadb/go.mod b/modules/mariadb/go.mod index 0adcb34137..375e6a8171 100644 --- a/modules/mariadb/go.mod +++ b/modules/mariadb/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/mariadb/go.sum b/modules/mariadb/go.sum index 87012342fc..5edb490b56 100644 --- a/modules/mariadb/go.sum +++ b/modules/mariadb/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/milvus/go.mod b/modules/milvus/go.mod index 1e422dfbbd..35ef7ea219 100644 --- a/modules/milvus/go.mod +++ b/modules/milvus/go.mod @@ -20,7 +20,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/milvus/go.sum b/modules/milvus/go.sum index fe4e49142c..a3486fbfea 100644 --- a/modules/milvus/go.sum +++ b/modules/milvus/go.sum @@ -52,8 +52,8 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/minio/go.mod b/modules/minio/go.mod index c15829afcd..275258590a 100644 --- a/modules/minio/go.mod +++ b/modules/minio/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect diff --git a/modules/minio/go.sum b/modules/minio/go.sum index 18f7c6e65f..31363a9d8a 100644 --- a/modules/minio/go.sum +++ b/modules/minio/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/mockserver/go.mod b/modules/mockserver/go.mod index aee68d38d2..694cb582ad 100644 --- a/modules/mockserver/go.mod +++ b/modules/mockserver/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/mockserver/go.sum b/modules/mockserver/go.sum index 78e52785d9..3356838f8b 100644 --- a/modules/mockserver/go.sum +++ b/modules/mockserver/go.sum @@ -25,8 +25,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/mongodb/go.mod b/modules/mongodb/go.mod index db3b7818aa..8ab7f9cbd8 100644 --- a/modules/mongodb/go.mod +++ b/modules/mongodb/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/mongodb/go.sum b/modules/mongodb/go.sum index 65bebba91e..070b75e61f 100644 --- a/modules/mongodb/go.sum +++ b/modules/mongodb/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/mssql/go.mod b/modules/mssql/go.mod index 9e242f0df5..d2a0fa1c88 100644 --- a/modules/mssql/go.mod +++ b/modules/mssql/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/mssql/go.sum b/modules/mssql/go.sum index 53c28f5dc2..850c4d56cb 100644 --- a/modules/mssql/go.sum +++ b/modules/mssql/go.sum @@ -35,8 +35,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/mysql/go.mod b/modules/mysql/go.mod index 5c38a7b17e..75bb50428e 100644 --- a/modules/mysql/go.mod +++ b/modules/mysql/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/mysql/go.sum b/modules/mysql/go.sum index 87012342fc..5edb490b56 100644 --- a/modules/mysql/go.sum +++ b/modules/mysql/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/nats/go.mod b/modules/nats/go.mod index 62af72086e..1aad992b23 100644 --- a/modules/nats/go.mod +++ b/modules/nats/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/nats/go.sum b/modules/nats/go.sum index 81345e4a87..153b357491 100644 --- a/modules/nats/go.sum +++ b/modules/nats/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/neo4j/go.mod b/modules/neo4j/go.mod index 1f0b1ba5f4..c40ca91f0e 100644 --- a/modules/neo4j/go.mod +++ b/modules/neo4j/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/neo4j/go.sum b/modules/neo4j/go.sum index f46b333664..65b9f7c873 100644 --- a/modules/neo4j/go.sum +++ b/modules/neo4j/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/ollama/go.mod b/modules/ollama/go.mod index c9c8d00c3a..0e7193c540 100644 --- a/modules/ollama/go.mod +++ b/modules/ollama/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/ollama go 1.21 require ( - github.com/docker/docker v27.0.3+incompatible + github.com/docker/docker v27.1.0+incompatible github.com/google/uuid v1.6.0 github.com/testcontainers/testcontainers-go v0.32.0 github.com/tmc/langchaingo v0.1.5 diff --git a/modules/ollama/go.sum b/modules/ollama/go.sum index 18076bdeed..3b2564fd3b 100644 --- a/modules/ollama/go.sum +++ b/modules/ollama/go.sum @@ -25,8 +25,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.8.1 h1:6Lcdwya6GjPUNsBct8Lg/yRPwMhABj269AAzdGSiR+0= github.com/dlclark/regexp2 v1.8.1/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/openfga/go.mod b/modules/openfga/go.mod index 2f671a352f..98be0b4cc3 100644 --- a/modules/openfga/go.mod +++ b/modules/openfga/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/openfga/go.sum b/modules/openfga/go.sum index cd2ab47083..e83875640f 100644 --- a/modules/openfga/go.sum +++ b/modules/openfga/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/openldap/go.mod b/modules/openldap/go.mod index 50fe9f3adc..5f5daaf971 100644 --- a/modules/openldap/go.mod +++ b/modules/openldap/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/openldap/go.sum b/modules/openldap/go.sum index 38bade094b..799277ab69 100644 --- a/modules/openldap/go.sum +++ b/modules/openldap/go.sum @@ -27,8 +27,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/opensearch/go.mod b/modules/opensearch/go.mod index 85532dd657..310e35be63 100644 --- a/modules/opensearch/go.mod +++ b/modules/opensearch/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/opensearch go 1.21 require ( - github.com/docker/docker v27.0.3+incompatible + github.com/docker/docker v27.1.0+incompatible github.com/docker/go-units v0.5.0 github.com/testcontainers/testcontainers-go v0.32.0 ) diff --git a/modules/opensearch/go.sum b/modules/opensearch/go.sum index a9ce8a33e4..4de62e95bc 100644 --- a/modules/opensearch/go.sum +++ b/modules/opensearch/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/postgres/go.mod b/modules/postgres/go.mod index a2693f76d3..56e8ec9a17 100644 --- a/modules/postgres/go.mod +++ b/modules/postgres/go.mod @@ -22,7 +22,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/postgres/go.sum b/modules/postgres/go.sum index d6092cfc0f..292324c223 100644 --- a/modules/postgres/go.sum +++ b/modules/postgres/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/pulsar/go.mod b/modules/pulsar/go.mod index f48abfe02e..67796255bf 100644 --- a/modules/pulsar/go.mod +++ b/modules/pulsar/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/apache/pulsar-client-go v0.10.0 - github.com/docker/docker v27.0.3+incompatible + github.com/docker/docker v27.1.0+incompatible github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.32.0 diff --git a/modules/pulsar/go.sum b/modules/pulsar/go.sum index e8eaf5f2ff..a38890a005 100644 --- a/modules/pulsar/go.sum +++ b/modules/pulsar/go.sum @@ -98,8 +98,8 @@ github.com/dimfeld/httptreemux v5.0.1+incompatible h1:Qj3gVcDNoOthBAqftuD596rm4w github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/qdrant/go.mod b/modules/qdrant/go.mod index e9b17b30b5..187209855e 100644 --- a/modules/qdrant/go.mod +++ b/modules/qdrant/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/qdrant/go.sum b/modules/qdrant/go.sum index 34c1ce69b0..2d9e4c62ca 100644 --- a/modules/qdrant/go.sum +++ b/modules/qdrant/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/rabbitmq/go.mod b/modules/rabbitmq/go.mod index 12c5f48db2..ba23d16112 100644 --- a/modules/rabbitmq/go.mod +++ b/modules/rabbitmq/go.mod @@ -25,7 +25,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/rabbitmq/go.sum b/modules/rabbitmq/go.sum index efb0fa578a..250c71bee6 100644 --- a/modules/rabbitmq/go.sum +++ b/modules/rabbitmq/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/redis/go.mod b/modules/redis/go.mod index 30cd3a34c3..6f6c5eb625 100644 --- a/modules/redis/go.mod +++ b/modules/redis/go.mod @@ -25,7 +25,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/redis/go.sum b/modules/redis/go.sum index 3828ee6963..786b36ccd8 100644 --- a/modules/redis/go.sum +++ b/modules/redis/go.sum @@ -28,8 +28,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/redpanda/go.mod b/modules/redpanda/go.mod index 72c515585a..732f26140f 100644 --- a/modules/redpanda/go.mod +++ b/modules/redpanda/go.mod @@ -28,7 +28,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/redpanda/go.sum b/modules/redpanda/go.sum index 44c64e0489..e993beb0b6 100644 --- a/modules/redpanda/go.sum +++ b/modules/redpanda/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/registry/go.mod b/modules/registry/go.mod index 0f6bdb51c4..47e546cd22 100644 --- a/modules/registry/go.mod +++ b/modules/registry/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/registry go 1.21 require ( - github.com/docker/docker v27.0.3+incompatible + github.com/docker/docker v27.1.0+incompatible github.com/testcontainers/testcontainers-go v0.32.0 ) diff --git a/modules/registry/go.sum b/modules/registry/go.sum index a9ce8a33e4..4de62e95bc 100644 --- a/modules/registry/go.sum +++ b/modules/registry/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/surrealdb/go.mod b/modules/surrealdb/go.mod index 26378fccbf..dca93f7a97 100644 --- a/modules/surrealdb/go.mod +++ b/modules/surrealdb/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/surrealdb/go.sum b/modules/surrealdb/go.sum index e2b0ff48c1..0b708c46c3 100644 --- a/modules/surrealdb/go.sum +++ b/modules/surrealdb/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/valkey/go.mod b/modules/valkey/go.mod index 365d296586..a92530c576 100644 --- a/modules/valkey/go.mod +++ b/modules/valkey/go.mod @@ -22,7 +22,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/valkey/go.sum b/modules/valkey/go.sum index 4979b048ac..18eacee2e9 100644 --- a/modules/valkey/go.sum +++ b/modules/valkey/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -99,7 +99,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/testcontainers/testcontainers-go v0.32.0/go.mod h1:CRHrzHLQhlXUsa5gXjTOfqIEJcrK5+xMDmBr/WMI88E= github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= diff --git a/modules/vault/go.mod b/modules/vault/go.mod index 3b34613a86..f3086a358b 100644 --- a/modules/vault/go.mod +++ b/modules/vault/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/vault go 1.21 require ( - github.com/docker/docker v27.0.3+incompatible + github.com/docker/docker v27.1.0+incompatible github.com/hashicorp/vault-client-go v0.4.3 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.32.0 diff --git a/modules/vault/go.sum b/modules/vault/go.sum index 32d8fbad8f..4cf0f339d1 100644 --- a/modules/vault/go.sum +++ b/modules/vault/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/vearch/go.mod b/modules/vearch/go.mod index 1063a08d39..2d385f6648 100644 --- a/modules/vearch/go.mod +++ b/modules/vearch/go.mod @@ -14,7 +14,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/vearch/go.sum b/modules/vearch/go.sum index a9ce8a33e4..4de62e95bc 100644 --- a/modules/vearch/go.sum +++ b/modules/vearch/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/weaviate/go.mod b/modules/weaviate/go.mod index 5baa3c2dab..9cd6cafa72 100644 --- a/modules/weaviate/go.mod +++ b/modules/weaviate/go.mod @@ -21,7 +21,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.0.3+incompatible // indirect + github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/weaviate/go.sum b/modules/weaviate/go.sum index 6cf347ec5d..b65325ee65 100644 --- a/modules/weaviate/go.sum +++ b/modules/weaviate/go.sum @@ -32,8 +32,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= From ab3a0f58d9cc2dfb1ffc982d7bd65309bf0f0d6c Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 7 Aug 2024 10:40:21 +0100 Subject: [PATCH 005/126] test: fix image label test (#2689) Fix test for image label setting which could fail if the volume already existed. --- mounts_test.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/mounts_test.go b/mounts_test.go index ecf91943dd..533b584feb 100644 --- a/mounts_test.go +++ b/mounts_test.go @@ -217,6 +217,15 @@ func TestMountsReceiveRyukLabels(t *testing.T) { } ctx := context.Background() + client, err := testcontainers.NewDockerClientWithOpts(ctx) + require.NoError(t, err) + defer client.Close() + + // Ensure the volume is removed before creating the container + // otherwise the volume will be reused and the labels won't be set. + err = client.VolumeRemove(ctx, "app-data", true) + require.NoError(t, err) + c, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, @@ -224,12 +233,8 @@ func TestMountsReceiveRyukLabels(t *testing.T) { require.NoError(t, err) terminateContainerOnEnd(t, ctx, c) - // Check if volume is created with the expected labels - client, err := testcontainers.NewDockerClientWithOpts(ctx) - require.NoError(t, err) - defer client.Close() - + // Check if volume is created with the expected labels. volume, err := client.VolumeInspect(ctx, "app-data") require.NoError(t, err) - assert.Equal(t, testcontainers.GenericLabels(), volume.Labels) + require.Equal(t, testcontainers.GenericLabels(), volume.Labels) } From 82838e21aef61dc7eec7628a8e66fa32dfa4177b Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 7 Aug 2024 10:42:44 +0100 Subject: [PATCH 006/126] fix: missing image build errors (#2651) Ensure build errors are returned to the caller when PrintBuildLog is not set to true. DisplayJSONMessagesStream and JSONMessage.Display performs processing of the stream to catch command failures, so needs to always be called. --- container_test.go | 23 +++++++++++------------ docker.go | 26 ++++++++++++-------------- from_dockerfile_test.go | 23 +++++++++++++++++++++++ generic.go | 2 +- testdata/error.Dockerfile | 4 ++++ 5 files changed, 51 insertions(+), 27 deletions(-) create mode 100644 testdata/error.Dockerfile diff --git a/container_test.go b/container_test.go index 1d25c4d661..0da1b967f8 100644 --- a/container_test.go +++ b/container_test.go @@ -151,7 +151,7 @@ func Test_BuildImageWithContexts(t *testing.T) { ContextArchive func() (io.Reader, error) ExpectedEchoOutput string Dockerfile string - ExpectedError error + ExpectedError string } testCases := []TestCase{ @@ -252,7 +252,7 @@ func Test_BuildImageWithContexts(t *testing.T) { ExpectedEchoOutput: "hi this is from the say_hi.sh file!", }, { - Name: "test buildling from a context on the filesystem", + Name: "test building from a context on the filesystem", ContextPath: "./testdata", Dockerfile: "echo.Dockerfile", ExpectedEchoOutput: "this is from the echo test Dockerfile", @@ -266,7 +266,7 @@ func Test_BuildImageWithContexts(t *testing.T) { ContextArchive: func() (io.Reader, error) { return nil, nil }, - ExpectedError: errors.New("you must specify either a build context or an image: failed to create container"), + ExpectedError: "create container: you must specify either a build context or an image", }, } @@ -292,16 +292,15 @@ func Test_BuildImageWithContexts(t *testing.T) { ContainerRequest: req, Started: true, }) - switch { - case testCase.ExpectedError != nil && err != nil: - if testCase.ExpectedError.Error() != err.Error() { - t.Fatalf("unexpected error: %s, was expecting %s", err.Error(), testCase.ExpectedError.Error()) - } - case err != nil: - t.Fatal(err) - default: - terminateContainerOnEnd(t, ctx, c) + + defer terminateContainerOnEnd(t, ctx, c) + + if testCase.ExpectedError != "" { + require.EqualError(t, err, testCase.ExpectedError) + return } + + require.NoError(t, err) }) } } diff --git a/docker.go b/docker.go index e89b9f4649..c3dfcb8da2 100644 --- a/docker.go +++ b/docker.go @@ -887,14 +887,14 @@ func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (st var err error buildOptions, err = img.BuildOptions() if err != nil { - return types.ImageBuildResponse{}, backoff.Permanent(err) + return types.ImageBuildResponse{}, backoff.Permanent(fmt.Errorf("build options: %w", err)) } defer tryClose(buildOptions.Context) // release resources in any case resp, err := p.client.ImageBuild(ctx, buildOptions.Context, buildOptions) if err != nil { if isPermanentClientError(err) { - return types.ImageBuildResponse{}, backoff.Permanent(err) + return types.ImageBuildResponse{}, backoff.Permanent(fmt.Errorf("build image: %w", err)) } return types.ImageBuildResponse{}, err } @@ -908,30 +908,28 @@ func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (st }, ) if err != nil { - return "", err + return "", err // Error is already wrapped. } defer resp.Body.Close() + output := io.Discard if img.ShouldPrintBuildLog() { - termFd, isTerm := term.GetFdInfo(os.Stderr) - err = jsonmessage.DisplayJSONMessagesStream(resp.Body, os.Stderr, termFd, isTerm, nil) - if err != nil { - return "", err - } + output = os.Stderr } - // need to read the response from Docker, I think otherwise the image - // might not finish building before continuing to execute here - _, err = io.Copy(io.Discard, resp.Body) - if err != nil { - return "", err + // Always process the output, even if it is not printed + // to ensure that errors during the build process are + // correctly handled. + termFd, isTerm := term.GetFdInfo(output) + if err = jsonmessage.DisplayJSONMessagesStream(resp.Body, output, termFd, isTerm, nil); err != nil { + return "", fmt.Errorf("build image: %w", err) } // the first tag is the one we want return buildOptions.Tags[0], nil } -// CreateContainer fulfills a request for a container without starting it +// CreateContainer fulfils a request for a container without starting it func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerRequest) (Container, error) { var err error diff --git a/from_dockerfile_test.go b/from_dockerfile_test.go index ab25ae6dee..fc1d4052ea 100644 --- a/from_dockerfile_test.go +++ b/from_dockerfile_test.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "log" + "path/filepath" "strings" "testing" "time" @@ -88,6 +89,28 @@ func TestBuildImageFromDockerfile_NoRepo(t *testing.T) { }) } +func TestBuildImageFromDockerfile_BuildError(t *testing.T) { + ctx := context.Background() + dockerClient, err := NewDockerClientWithOpts(ctx) + require.NoError(t, err) + + defer dockerClient.Close() + + req := ContainerRequest{ + FromDockerfile: FromDockerfile{ + Dockerfile: "error.Dockerfile", + Context: filepath.Join(".", "testdata"), + }, + } + _, err = GenericContainer(ctx, GenericContainerRequest{ + ProviderType: providerType, + ContainerRequest: req, + Started: true, + }) + + require.EqualError(t, err, `create container: build image: The command '/bin/sh -c exit 1' returned a non-zero code: 1`) +} + func TestBuildImageFromDockerfile_NoTag(t *testing.T) { provider, err := NewDockerProvider() if err != nil { diff --git a/generic.go b/generic.go index 65fec35c88..f0cda13407 100644 --- a/generic.go +++ b/generic.go @@ -74,7 +74,7 @@ func GenericContainer(ctx context.Context, req GenericContainerRequest) (Contain } if err != nil { // At this point `c` might not be nil. Give the caller an opportunity to call Destroy on the container. - return c, fmt.Errorf("%w: failed to create container", err) + return c, fmt.Errorf("create container: %w", err) } if req.Started && !c.IsRunning() { diff --git a/testdata/error.Dockerfile b/testdata/error.Dockerfile new file mode 100644 index 0000000000..1284e7285f --- /dev/null +++ b/testdata/error.Dockerfile @@ -0,0 +1,4 @@ +FROM docker.io/alpine + +RUN exit 1 + From cbb47fbeddd0c473a2f7eb9768af20cff7a9ca6b Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 7 Aug 2024 13:03:48 +0100 Subject: [PATCH 007/126] fix: port forwarding race condition (#2686) Fix port forwarding race condition by waiting for the exposed port which was causing random test failures. Make errors and parameters more consumable while there. --- port_forwarding.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/port_forwarding.go b/port_forwarding.go index 89aac10dd7..1d86a8cdd5 100644 --- a/port_forwarding.go +++ b/port_forwarding.go @@ -13,6 +13,7 @@ import ( "golang.org/x/crypto/ssh" "github.com/testcontainers/testcontainers-go/internal/core/network" + "github.com/testcontainers/testcontainers-go/wait" ) const ( @@ -37,10 +38,10 @@ var sshPassword = uuid.NewString() // 1. Create a new SSHD container. // 2. Expose the host ports to the container after the container is ready. // 3. Close the SSH sessions before killing the container. -func exposeHostPorts(ctx context.Context, req *ContainerRequest, p ...int) (ContainerLifecycleHooks, error) { +func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) (ContainerLifecycleHooks, error) { var sshdConnectHook ContainerLifecycleHooks - if len(p) == 0 { + if len(ports) == 0 { return sshdConnectHook, fmt.Errorf("no ports to expose") } @@ -59,7 +60,7 @@ func exposeHostPorts(ctx context.Context, req *ContainerRequest, p ...int) (Cont // get the first network of the container to connect the SSHD container to it. nw, err := network.GetByName(ctx, sshdFirstNetwork) if err != nil { - return sshdConnectHook, fmt.Errorf("failed to get the network: %w", err) + return sshdConnectHook, fmt.Errorf("get network %q: %w", sshdFirstNetwork, err) } dockerNw := DockerNetwork{ @@ -91,13 +92,13 @@ func exposeHostPorts(ctx context.Context, req *ContainerRequest, p ...int) (Cont // start the SSHD container with the provided options sshdContainer, err := newSshdContainer(ctx, opts...) if err != nil { - return sshdConnectHook, fmt.Errorf("failed to create the SSH server: %w", err) + return sshdConnectHook, fmt.Errorf("new sshd container: %w", err) } // IP in the first network of the container sshdIP, err := sshdContainer.ContainerIP(context.Background()) if err != nil { - return sshdConnectHook, fmt.Errorf("failed to get IP for the SSHD container: %w", err) + return sshdConnectHook, fmt.Errorf("get sshd container IP: %w", err) } if req.HostConfigModifier == nil { @@ -155,6 +156,7 @@ func newSshdContainer(ctx context.Context, opts ...ContainerCustomizer) (*sshdCo HostAccessPorts: []int{}, // empty list because it does not need any port ExposedPorts: []string{sshPort}, Env: map[string]string{"PASSWORD": sshPassword}, + WaitingFor: wait.ForListeningPort(sshPort), }, Started: true, } From 40098cf32c8aeddac9db414c9ac7e027d90b2b9e Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 7 Aug 2024 13:28:57 +0100 Subject: [PATCH 008/126] test: racy port creation in port forwarding tests (#2688) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: racy port creation in port forwarding tests Fix racy creation of free ports in port forwarding tests which were causing random failures. * chore: apply feedback suggestions Apply PR feedback suggestions to use a single line error check. Co-authored-by: Manuel de la Peña --------- Co-authored-by: Manuel de la Peña --- port_forwarding_test.go | 66 ++++++++--------------------------------- 1 file changed, 12 insertions(+), 54 deletions(-) diff --git a/port_forwarding_test.go b/port_forwarding_test.go index 46a1917a52..471736150b 100644 --- a/port_forwarding_test.go +++ b/port_forwarding_test.go @@ -6,9 +6,12 @@ import ( "io" "net" "net/http" + "net/http/httptest" "testing" "time" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" tcexec "github.com/testcontainers/testcontainers-go/exec" "github.com/testcontainers/testcontainers-go/network" @@ -52,21 +55,10 @@ func TestExposeHostPorts(t *testing.T) { t.Run(tc.name, func(tt *testing.T) { freePorts := make([]int, tc.numberOfPorts) for i := range freePorts { - freePort, err := getFreePort() - if err != nil { - tt.Fatal(err) - } - - freePorts[i] = freePort - - // create an http server for each port - server, err := createHttpServer(freePort) - if err != nil { - tt.Fatal(err) - } - go func() { - _ = server.ListenAndServe() - }() + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, expectedResponse) + })) + freePorts[i] = server.Listener.Addr().(*net.TCPAddr).Port tt.Cleanup(func() { server.Close() }) @@ -87,13 +79,10 @@ func TestExposeHostPorts(t *testing.T) { if tc.hasNetwork { var err error nw, err = network.New(context.Background()) - if err != nil { - tt.Fatal(err) - } + require.NoError(tt, err) + tt.Cleanup(func() { - if err := nw.Remove(context.Background()); err != nil { - tt.Fatal(err) - } + require.NoError(tt, nw.Remove(context.Background())) }) req.Networks = []string{nw.Name} @@ -108,13 +97,9 @@ func TestExposeHostPorts(t *testing.T) { } c, err := testcontainers.GenericContainer(ctx, req) - if err != nil { - tt.Fatal(err) - } + require.NoError(tt, err) tt.Cleanup(func() { - if err := c.Terminate(context.Background()); err != nil { - tt.Fatal(err) - } + require.NoError(tt, c.Terminate(context.Background())) }) if tc.hasHostAccess { @@ -174,30 +159,3 @@ func assertContainerHasNoHostAccess(t *testing.T, c testcontainers.Container, po } } } - -func createHttpServer(port int) (*http.Server, error) { - server := &http.Server{ - Addr: fmt.Sprintf(":%d", port), - } - - server.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, expectedResponse) - }) - - return server, nil -} - -// getFreePort asks the kernel for a free open port that is ready to use. -func getFreePort() (int, error) { - addr, err := net.ResolveTCPAddr("tcp", "localhost:0") - if err != nil { - return 0, err - } - - l, err := net.ListenTCP("tcp", addr) - if err != nil { - return 0, err - } - defer l.Close() - return l.Addr().(*net.TCPAddr).Port, nil -} From 8f90dcf74ecfd3fc21c45c6974a47c993442c20c Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 7 Aug 2024 13:30:33 +0100 Subject: [PATCH 009/126] fix(mongodb): replica test failures (#2699) Fix mongodb replica test failures due to client using the internal container addresses when direct connection is not requested. Fix invalid use of log.Fatal instead of tt.Fatal which was causing failures to no be output correctly due to os.Exit. --- modules/mongodb/mongodb.go | 2 +- modules/mongodb/mongodb_test.go | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/mongodb/mongodb.go b/modules/mongodb/mongodb.go index c27a5a4bf4..188c55e85b 100644 --- a/modules/mongodb/mongodb.go +++ b/modules/mongodb/mongodb.go @@ -92,7 +92,7 @@ func WithReplicaSet(replSetName string) testcontainers.CustomizeRequestOption { func(ctx context.Context, c testcontainers.Container) error { ip, err := c.ContainerIP(ctx) if err != nil { - return err + return fmt.Errorf("container ip: %w", err) } cmd := eval("rs.initiate({ _id: '%s', members: [ { _id: 0, host: '%s:27017' } ] })", replSetName, ip) diff --git a/modules/mongodb/mongodb_test.go b/modules/mongodb/mongodb_test.go index 36bd907e32..ead2b1818b 100644 --- a/modules/mongodb/mongodb_test.go +++ b/modules/mongodb/mongodb_test.go @@ -2,7 +2,6 @@ package mongodb_test import ( "context" - "log" "testing" "go.mongodb.org/mongo-driver/mongo" @@ -73,14 +72,17 @@ func TestMongoDB(t *testing.T) { tt.Fatalf("failed to get connection string: %s", err) } - mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(endpoint)) + // Force direct connection to the container to avoid the replica set + // connection string that is returned by the container itself when + // using the replica set option. + mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(endpoint+"/?connect=direct")) if err != nil { tt.Fatalf("failed to connect to MongoDB: %s", err) } err = mongoClient.Ping(ctx, nil) if err != nil { - log.Fatalf("failed to ping MongoDB: %s", err) + tt.Fatalf("failed to ping MongoDB: %s", err) } if mongoClient.Database("test").Name() != "test" { From f333902a69899c7f61351329fc5f5e0ab0608227 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 7 Aug 2024 15:15:17 +0100 Subject: [PATCH 010/126] fix(milvus): racy container setup (#2693) Fix race in container setup caused by copying the files into the container manually. While here update tests to use require so they are easier to follow. --- modules/milvus/go.mod | 4 +++ modules/milvus/go.sum | 5 ++- modules/milvus/milvus.go | 67 ++++++++++++----------------------- modules/milvus/milvus_test.go | 23 +++++------- 4 files changed, 39 insertions(+), 60 deletions(-) diff --git a/modules/milvus/go.mod b/modules/milvus/go.mod index 35ef7ea219..e6820f71f2 100644 --- a/modules/milvus/go.mod +++ b/modules/milvus/go.mod @@ -4,6 +4,7 @@ go 1.21 require ( github.com/milvus-io/milvus-sdk-go/v2 v2.3.6 + github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.32.0 ) @@ -19,6 +20,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -47,6 +49,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect @@ -69,6 +72,7 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/grpc v1.64.1 // indirect google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/milvus/go.sum b/modules/milvus/go.sum index a3486fbfea..a91219667c 100644 --- a/modules/milvus/go.sum +++ b/modules/milvus/go.sum @@ -270,8 +270,9 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM 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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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= @@ -482,6 +483,8 @@ google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 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/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/modules/milvus/milvus.go b/modules/milvus/milvus.go index 85af5aac04..9b944f6160 100644 --- a/modules/milvus/milvus.go +++ b/modules/milvus/milvus.go @@ -6,7 +6,7 @@ import ( _ "embed" "fmt" "html/template" - "os" + "io" "time" "github.com/testcontainers/testcontainers-go" @@ -16,7 +16,11 @@ import ( //go:embed mounts/embedEtcd.yaml.tpl var embedEtcdConfigTpl string -const embedEtcdContainerPath string = "/milvus/configs/embedEtcd.yaml" +const ( + embedEtcdContainerPath = "/milvus/configs/embedEtcd.yaml" + defaultClientPort = 2379 + grpcPort = "19530/tcp" +) // MilvusContainer represents the Milvus container type used in the module type MilvusContainer struct { @@ -30,7 +34,7 @@ func (c *MilvusContainer) ConnectionString(ctx context.Context) (string, error) if err != nil { return "", err } - port, err := c.MappedPort(ctx, "19530/tcp") + port, err := c.MappedPort(ctx, grpcPort) if err != nil { return "", err } @@ -45,6 +49,11 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize // Run creates an instance of the Milvus container type func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*MilvusContainer, error) { + config, err := renderEmbedEtcdConfig(defaultClientPort) + if err != nil { + return nil, fmt.Errorf("render config: %w", err) + } + req := testcontainers.ContainerRequest{ Image: img, ExposedPorts: []string{"19530/tcp", "9091/tcp", "2379/tcp"}, @@ -54,16 +63,13 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom "ETCD_CONFIG_PATH": embedEtcdContainerPath, "COMMON_STORAGETYPE": "local", }, - Cmd: []string{"milvus", "run", "standalone"}, - WaitingFor: wait.ForHTTP("/healthz").WithPort("9091").WithStartupTimeout(60 * time.Second).WithPollInterval(30 * time.Second), - LifecycleHooks: []testcontainers.ContainerLifecycleHooks{ - { - PostCreates: []testcontainers.ContainerHook{ - // Copy the default embed etcd config to container after it's created. - // Otherwise the milvus container will panic on startup. - createDefaultEmbedEtcdConfig, - }, - }, + Cmd: []string{"milvus", "run", "standalone"}, + WaitingFor: wait.ForHTTP("/healthz"). + WithPort("9091"). + WithStartupTimeout(time.Minute). + WithPollInterval(time.Second), + Files: []testcontainers.ContainerFile{ + {ContainerFilePath: embedEtcdContainerPath, Reader: config}, }, } @@ -90,7 +96,9 @@ type embedEtcdConfigTplParams struct { Port int } -func renderEmbedEtcdConfig(port int) ([]byte, error) { +// renderEmbedEtcdConfig renders the embed etcd config template with the given port +// and returns it as an io.Reader. +func renderEmbedEtcdConfig(port int) (io.Reader, error) { tplParams := embedEtcdConfigTplParams{ Port: port, } @@ -105,34 +113,5 @@ func renderEmbedEtcdConfig(port int) ([]byte, error) { return nil, fmt.Errorf("failed to render embed etcd config template: %w", err) } - return embedEtcdYaml.Bytes(), nil -} - -// createDefaultEmbedEtcdConfig creates a default embed etcd config file, -// using the default port 2379 as the advertised port. The file is then copied to the container. -func createDefaultEmbedEtcdConfig(ctx context.Context, c testcontainers.Container) error { - // Otherwise the milvus container will panic on startup. - defaultEmbedEtcdConfig, err := renderEmbedEtcdConfig(2379) - if err != nil { - return fmt.Errorf("failed to render default config: %w", err) - } - - tmpDir := os.TempDir() - defaultEmbedEtcdConfigPath := fmt.Sprintf("%s/embedEtcd.yaml", tmpDir) - - if err := os.WriteFile(defaultEmbedEtcdConfigPath, defaultEmbedEtcdConfig, 0o644); err != nil { - return fmt.Errorf("failed to write default embed etcd config to a temporary dir: %w", err) - } - - if err != nil { - return fmt.Errorf("can't create default embed etcd config: %w", err) - } - defer os.Remove(defaultEmbedEtcdConfigPath) - - err = c.CopyFileToContainer(ctx, defaultEmbedEtcdConfigPath, embedEtcdContainerPath, 0o644) - if err != nil { - return fmt.Errorf("can't copy %s to container: %w", defaultEmbedEtcdConfigPath, err) - } - - return nil + return &embedEtcdYaml, nil } diff --git a/modules/milvus/milvus_test.go b/modules/milvus/milvus_test.go index 849722ba90..c49f37c92f 100644 --- a/modules/milvus/milvus_test.go +++ b/modules/milvus/milvus_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/milvus-io/milvus-sdk-go/v2/client" + "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go/modules/milvus" ) @@ -13,35 +14,27 @@ func TestMilvus(t *testing.T) { ctx := context.Background() container, err := milvus.Run(ctx, "milvusdb/milvus:v2.3.9") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // Clean up the container after the test is complete t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } + err = container.Terminate(ctx) + require.NoError(t, err) }) t.Run("Connect to Milvus with gRPC", func(tt *testing.T) { // connectionString { connectionStr, err := container.ConnectionString(ctx) // } - if err != nil { - tt.Fatal(err) - } + require.NoError(t, err) milvusClient, err := client.NewGrpcClient(context.Background(), connectionStr) - if err != nil { - tt.Fatal("failed to connect to Milvus:", err.Error()) - } + require.NoError(t, err) + defer milvusClient.Close() v, err := milvusClient.GetVersion(ctx) - if err != nil { - tt.Fatal("failed to get version:", err.Error()) - } + require.NoError(t, err) tt.Logf("Milvus version: %s", v) }) From 5924b38fee65632619055c635171e57d543d2361 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Thu, 8 Aug 2024 00:12:39 +0100 Subject: [PATCH 011/126] fix(wait): data race in test (#2698) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(wait): data race in test Fix the data race on access to health in TestWaitForHealthSucceeds. * chore: use deferred unlock Switch to a deferred unlock to ensure safety. Co-authored-by: Manuel de la Peña --------- Co-authored-by: Manuel de la Peña --- wait/health_test.go | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/wait/health_test.go b/wait/health_test.go index e1d67809de..8a06ab07f8 100644 --- a/wait/health_test.go +++ b/wait/health_test.go @@ -3,6 +3,7 @@ package wait import ( "context" "io" + "sync" "testing" "time" @@ -15,41 +16,54 @@ import ( type healthStrategyTarget struct { state *types.ContainerState + mtx sync.Mutex } -func (st healthStrategyTarget) Host(ctx context.Context) (string, error) { +func (st *healthStrategyTarget) Host(ctx context.Context) (string, error) { return "", nil } -func (st healthStrategyTarget) Inspect(ctx context.Context) (*types.ContainerJSON, error) { +func (st *healthStrategyTarget) Inspect(ctx context.Context) (*types.ContainerJSON, error) { return nil, nil } // Deprecated: use Inspect instead -func (st healthStrategyTarget) Ports(ctx context.Context) (nat.PortMap, error) { +func (st *healthStrategyTarget) Ports(ctx context.Context) (nat.PortMap, error) { return nil, nil } -func (st healthStrategyTarget) MappedPort(ctx context.Context, n nat.Port) (nat.Port, error) { +func (st *healthStrategyTarget) MappedPort(ctx context.Context, n nat.Port) (nat.Port, error) { return n, nil } -func (st healthStrategyTarget) Logs(ctx context.Context) (io.ReadCloser, error) { +func (st *healthStrategyTarget) Logs(ctx context.Context) (io.ReadCloser, error) { return nil, nil } -func (st healthStrategyTarget) Exec(ctx context.Context, cmd []string, options ...tcexec.ProcessOption) (int, io.Reader, error) { +func (st *healthStrategyTarget) Exec(ctx context.Context, cmd []string, options ...tcexec.ProcessOption) (int, io.Reader, error) { return 0, nil, nil } -func (st healthStrategyTarget) State(ctx context.Context) (*types.ContainerState, error) { - return st.state, nil +func (st *healthStrategyTarget) State(ctx context.Context) (*types.ContainerState, error) { + st.mtx.Lock() + defer st.mtx.Unlock() + + // Return a copy to prevent data race. + state := *st.state + + return &state, nil +} + +func (st *healthStrategyTarget) setState(health *types.Health) { + st.mtx.Lock() + defer st.mtx.Unlock() + st.state.Health = health } // TestWaitForHealthTimesOutForUnhealthy confirms that an unhealthy container will eventually // time out. func TestWaitForHealthTimesOutForUnhealthy(t *testing.T) { - target := healthStrategyTarget{ + target := &healthStrategyTarget{ state: &types.ContainerState{ Running: true, Health: &types.Health{Status: types.Unhealthy}, @@ -64,7 +78,7 @@ func TestWaitForHealthTimesOutForUnhealthy(t *testing.T) { // TestWaitForHealthSucceeds ensures that a healthy container always succeeds. func TestWaitForHealthSucceeds(t *testing.T) { - target := healthStrategyTarget{ + target := &healthStrategyTarget{ state: &types.ContainerState{ Running: true, Health: &types.Health{Status: types.Healthy}, @@ -93,7 +107,7 @@ func TestWaitForHealthWithNil(t *testing.T) { // wait a bit to simulate startup time and give check time to at least // try a few times with a nil Health time.Sleep(200 * time.Millisecond) - target.state.Health = &types.Health{Status: types.Healthy} + target.setState(&types.Health{Status: types.Healthy}) }(target) err := wg.WaitUntilReady(context.Background(), target) From db119f6fba65b89c150ccbee6ed6145f6f57c3e7 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Thu, 8 Aug 2024 11:28:02 +0100 Subject: [PATCH 012/126] feat(inbucket): expose POP3 and wait for all ports (#2690) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(inbucket): expose POP3 and wait for all ports Expose the POP3 port and wait for all ports which fixes the race condition in the tests. * chore: use listen port instead of host port Use ForListeningPort instead of NewHostPortStrategy as it's more readable. Co-authored-by: Manuel de la Peña --------- Co-authored-by: Manuel de la Peña --- modules/inbucket/go.mod | 5 ++++ modules/inbucket/go.sum | 9 ++++++ modules/inbucket/inbucket.go | 8 ++++-- modules/inbucket/inbucket_test.go | 46 +++++++++---------------------- 4 files changed, 33 insertions(+), 35 deletions(-) diff --git a/modules/inbucket/go.mod b/modules/inbucket/go.mod index f6f7ba6f96..89851c357e 100644 --- a/modules/inbucket/go.mod +++ b/modules/inbucket/go.mod @@ -4,6 +4,7 @@ go 1.21 require ( github.com/inbucket/inbucket v2.0.0+incompatible + github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.32.0 ) @@ -16,6 +17,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.0+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -28,6 +30,7 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/jhillyerd/inbucket v2.0.0+incompatible // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -39,6 +42,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -55,6 +59,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/inbucket/go.sum b/modules/inbucket/go.sum index 0f998df7df..8236abef2f 100644 --- a/modules/inbucket/go.sum +++ b/modules/inbucket/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -56,6 +57,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -82,6 +87,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -176,6 +183,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/inbucket/inbucket.go b/modules/inbucket/inbucket.go index 214e1c619c..beae784557 100644 --- a/modules/inbucket/inbucket.go +++ b/modules/inbucket/inbucket.go @@ -57,8 +57,12 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*InbucketContainer, error) { req := testcontainers.ContainerRequest{ Image: img, - ExposedPorts: []string{"2500/tcp", "9000/tcp"}, - WaitingFor: wait.ForLog("SMTP listening on tcp4"), + ExposedPorts: []string{"2500/tcp", "9000/tcp", "1100/tcp"}, + WaitingFor: wait.ForAll( + wait.ForListeningPort("2500/tcp"), + wait.ForListeningPort("9000/tcp"), + wait.ForListeningPort("1100/tcp"), + ), } genericContainerReq := testcontainers.GenericContainerRequest{ diff --git a/modules/inbucket/inbucket_test.go b/modules/inbucket/inbucket_test.go index 8c2c479aed..eb6dc3c493 100644 --- a/modules/inbucket/inbucket_test.go +++ b/modules/inbucket/inbucket_test.go @@ -6,65 +6,45 @@ import ( "testing" "github.com/inbucket/inbucket/pkg/rest/client" + "github.com/stretchr/testify/require" ) func TestInbucket(t *testing.T) { ctx := context.Background() container, err := Run(ctx, "inbucket/inbucket:sha-2d409bb") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // Clean up the container after the test is complete t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } + err := container.Terminate(ctx) + require.NoError(t, err) }) // smtpConnection { smtpUrl, err := container.SmtpConnection(ctx) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // webInterface { webInterfaceUrl, err := container.WebInterface(ctx) // } - if err != nil { - t.Fatal(err) - } - + require.NoError(t, err) restClient, err := client.New(webInterfaceUrl) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) headers, err := restClient.ListMailbox("to@example.org") - if err != nil { - t.Fatal(err) - } - if len(headers) != 0 { - t.Fatalf("expected 0 messages, got %d", len(headers)) - } + require.NoError(t, err) + require.Empty(t, headers) msg := []byte("To: to@example.org\r\n" + "Subject: Testcontainers test!\r\n" + "\r\n" + "This is a Testcontainers test.\r\n") - if err = smtp.SendMail(smtpUrl, nil, "from@example.org", []string{"to@example.org"}, msg); err != nil { - t.Fatal(err) - } + err = smtp.SendMail(smtpUrl, nil, "from@example.org", []string{"to@example.org"}, msg) + require.NoError(t, err) headers, err = restClient.ListMailbox("to@example.org") - if err != nil { - t.Fatal(err) - } - - if len(headers) != 1 { - t.Fatalf("expected 1 message, got %d", len(headers)) - } - // perform assertions + require.NoError(t, err) + require.Len(t, headers, 1) } From 81007d6e1237c26b4f95195ebaa53c3cb2945e1c Mon Sep 17 00:00:00 2001 From: Oren Leiman <1635704+oleiman@users.noreply.github.com> Date: Thu, 8 Aug 2024 03:30:47 -0700 Subject: [PATCH 013/126] Redpanda Module: Add option for arbitrary bootstrap config (#2666) WithBootstrapConfig adds an arbitrary config kvp to the Redpanda container. Per the name, this config will be interpolated into the generated bootstrap config file, which is particularly useful for configs requiring a restart when otherwise applied to a running Redpanda instance. Includes a test that sets a couple of restart-requiring cluster configs and checks a) that the values are reflected in the config state at run time AND b) that the cluster does not need a restart. (b) demonstrates that the configs were bootstrapped rather than applied to a live cluster. Signed-off-by: Oren Leiman --- modules/redpanda/examples_test.go | 2 + modules/redpanda/mounts/bootstrap.yaml.tpl | 5 ++ modules/redpanda/options.go | 15 ++++++ modules/redpanda/redpanda.go | 2 + modules/redpanda/redpanda_test.go | 56 ++++++++++++++++++++++ 5 files changed, 80 insertions(+) diff --git a/modules/redpanda/examples_test.go b/modules/redpanda/examples_test.go index 822522255c..68cb314418 100644 --- a/modules/redpanda/examples_test.go +++ b/modules/redpanda/examples_test.go @@ -17,6 +17,8 @@ func ExampleRun() { redpanda.WithEnableSASL(), redpanda.WithEnableKafkaAuthorization(), redpanda.WithEnableWasmTransform(), + redpanda.WithBootstrapConfig("data_transforms_per_core_memory_reservation", 33554432), + redpanda.WithBootstrapConfig("data_transforms_per_function_memory_limit", 16777216), redpanda.WithNewServiceAccount("superuser-1", "test"), redpanda.WithNewServiceAccount("superuser-2", "test"), redpanda.WithNewServiceAccount("no-superuser", "test"), diff --git a/modules/redpanda/mounts/bootstrap.yaml.tpl b/modules/redpanda/mounts/bootstrap.yaml.tpl index 643236bbef..cf5bb6ea5f 100644 --- a/modules/redpanda/mounts/bootstrap.yaml.tpl +++ b/modules/redpanda/mounts/bootstrap.yaml.tpl @@ -22,3 +22,8 @@ data_transforms_enabled: true {{- if .AutoCreateTopics }} auto_create_topics_enabled: true {{- end }} + +{{- range $key, $value := .ExtraBootstrapConfig }} +{{ $key }}: {{ $value }} +{{- end }} + diff --git a/modules/redpanda/options.go b/modules/redpanda/options.go index f78766115b..ae15e33001 100644 --- a/modules/redpanda/options.go +++ b/modules/redpanda/options.go @@ -43,6 +43,10 @@ type options struct { // Listeners is a list of custom listeners that can be provided to access the // containers form within docker networks Listeners []listener + + // ExtraBootstrapConfig is a map of configs to be interpolated into the + // container's bootstrap.yml + ExtraBootstrapConfig map[string]any } func defaultOptions() options { @@ -55,6 +59,7 @@ func defaultOptions() options { AutoCreateTopics: false, EnableTLS: false, Listeners: make([]listener, 0), + ExtraBootstrapConfig: make(map[string]any, 0), } } @@ -155,3 +160,13 @@ func WithListener(lis string) Option { }) } } + +// WithBootstrapConfig adds an arbitrary config kvp to the Redpanda container. +// Per the name, this config will be interpolated into the generated bootstrap +// config file, which is particularly useful for configs requiring a restart +// when otherwise applied to a running Redpanda instance. +func WithBootstrapConfig(cfg string, val any) Option { + return func(o *options) { + o.ExtraBootstrapConfig[cfg] = val + } +} diff --git a/modules/redpanda/redpanda.go b/modules/redpanda/redpanda.go index 608396ec29..7f46617536 100644 --- a/modules/redpanda/redpanda.go +++ b/modules/redpanda/redpanda.go @@ -281,6 +281,7 @@ func renderBootstrapConfig(settings options) ([]byte, error) { KafkaAPIEnableAuthorization: settings.KafkaEnableAuthorization, AutoCreateTopics: settings.AutoCreateTopics, EnableWasmTransform: settings.EnableWasmTransform, + ExtraBootstrapConfig: settings.ExtraBootstrapConfig, } tpl, err := template.New("bootstrap.yaml").Parse(bootstrapConfigTpl) @@ -355,6 +356,7 @@ type redpandaBootstrapConfigTplParams struct { KafkaAPIEnableAuthorization bool AutoCreateTopics bool EnableWasmTransform bool + ExtraBootstrapConfig map[string]any } type redpandaConfigTplParams struct { diff --git a/modules/redpanda/redpanda_test.go b/modules/redpanda/redpanda_test.go index 948ea4c741..09bad2c0d0 100644 --- a/modules/redpanda/redpanda_test.go +++ b/modules/redpanda/redpanda_test.go @@ -2,6 +2,7 @@ package redpanda_test import ( "context" + "encoding/json" "fmt" "io" "net/http" @@ -573,3 +574,58 @@ func TestRedpandaListener_NoNetwork(t *testing.T) { require.Contains(t, err.Error(), "container must be attached to at least one network") } + +func TestRedpandaBootstrapConfig(t *testing.T) { + ctx := context.Background() + + container, err := redpanda.RunContainer(ctx, + redpanda.WithEnableWasmTransform(), + // These configs would require a restart if applied to a live Redpanda instance + redpanda.WithBootstrapConfig("data_transforms_per_core_memory_reservation", 33554432), + redpanda.WithBootstrapConfig("data_transforms_per_function_memory_limit", 16777216), + ) + require.NoError(t, err) + + httpCl := &http.Client{ + Timeout: 5 * time.Second, + Transport: &http.Transport{ + ForceAttemptHTTP2: true, + TLSHandshakeTimeout: 10 * time.Second, + }, + } + adminAPIUrl, err := container.AdminAPIAddress(ctx) + require.NoError(t, err) + + { + // Check that the configs reflect specified values + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v1/cluster_config", adminAPIUrl), nil) + require.NoError(t, err) + resp, err := httpCl.Do(req) + require.NoError(t, err) + defer resp.Body.Close() + require.Equal(t, http.StatusOK, resp.StatusCode) + var data map[string]any + err = json.NewDecoder(resp.Body).Decode(&data) + require.NoError(t, err) + reservation := int(data["data_transforms_per_core_memory_reservation"].(float64)) + require.Equal(t, 33554432, reservation) + pf_limit := int(data["data_transforms_per_function_memory_limit"].(float64)) + require.Equal(t, 16777216, pf_limit) + } + + { + // Check that no restart is required. i.e. that the configs were applied via bootstrap config + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v1/cluster_config/status", adminAPIUrl), nil) + require.NoError(t, err) + resp, err := httpCl.Do(req) + require.NoError(t, err) + defer resp.Body.Close() + require.Equal(t, http.StatusOK, resp.StatusCode) + var data []map[string]any + err = json.NewDecoder(resp.Body).Decode(&data) + require.NoError(t, err) + require.Len(t, data, 1) + needs_restart := data[0]["restart"].(bool) + require.False(t, needs_restart) + } +} From e4ce806d340dcff40e6aefa8bb81894e185786af Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Thu, 8 Aug 2024 12:52:38 +0100 Subject: [PATCH 014/126] test: add retry on system error test (#2687) Add a test to cover the retry on system error test. Update test to use empty context to prevent knock on failures being logged confusing the output and check the error returned. --- docker_test.go | 17 +++++++++++++++-- testdata/retry/Dockerfile | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 testdata/retry/Dockerfile diff --git a/docker_test.go b/docker_test.go index 38ab7fec2a..0da11ef7f9 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1973,7 +1973,6 @@ func terminateContainerOnEnd(tb testing.TB, ctx context.Context, ctr Container) return } tb.Cleanup(func() { - tb.Log("terminating container") require.NoError(tb, ctr.Terminate(ctx)) }) } @@ -2141,6 +2140,11 @@ func TestDockerProvider_BuildImage_Retries(t *testing.T) { errReturned: errdefs.NotImplemented(errors.New("unknown method")), shouldRetry: false, }, + { + name: "no retry on system error", + errReturned: errdefs.System(errors.New("system error")), + shouldRetry: false, + }, { name: "retry on non-permanent error", errReturned: errors.New("whoops"), @@ -2158,7 +2162,16 @@ func TestDockerProvider_BuildImage_Retries(t *testing.T) { // give a chance to retry ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() - _, _ = p.BuildImage(ctx, &ContainerRequest{}) + _, err = p.BuildImage(ctx, &ContainerRequest{ + FromDockerfile: FromDockerfile{ + Context: filepath.Join(".", "testdata", "retry"), + }, + }) + if tt.errReturned != nil { + require.Error(t, err) + } else { + require.NoError(t, err) + } assert.Positive(t, m.imageBuildCount) assert.Equal(t, tt.shouldRetry, m.imageBuildCount > 1) diff --git a/testdata/retry/Dockerfile b/testdata/retry/Dockerfile new file mode 100644 index 0000000000..c35f1b5f5e --- /dev/null +++ b/testdata/retry/Dockerfile @@ -0,0 +1 @@ +FROM scratch From 150a48c691bc790e3be83211c4c59aa89c8849b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Thu, 8 Aug 2024 14:19:26 +0200 Subject: [PATCH 015/126] docs: add consistent snippets for network creation (#2703) * docs: add consistent snippets for network creation * fix: lint --- docs/features/creating_networks.md | 4 +- network/examples_test.go | 76 ++++++++++++++++++++++++++++++ network/network_test.go | 49 +++++-------------- 3 files changed, 89 insertions(+), 40 deletions(-) create mode 100644 network/examples_test.go diff --git a/docs/features/creating_networks.md b/docs/features/creating_networks.md index 09be152a55..7ee490104d 100644 --- a/docs/features/creating_networks.md +++ b/docs/features/creating_networks.md @@ -25,6 +25,6 @@ It's important to mention that the name of the network is automatically generate ## Usage example -[Creating a network](../../network/network_test.go) inside_block:createNetwork -[Creating a network with options](../../network/network_test.go) inside_block:newNetworkWithOptions +[Creating a network](../../network/examples_test.go) inside_block:createNetwork +[Creating a network with options](../../network/examples_test.go) inside_block:newNetworkWithOptions \ No newline at end of file diff --git a/network/examples_test.go b/network/examples_test.go new file mode 100644 index 0000000000..7335b85564 --- /dev/null +++ b/network/examples_test.go @@ -0,0 +1,76 @@ +package network_test + +import ( + "context" + "fmt" + "log" + + dockernetwork "github.com/docker/docker/api/types/network" + + "github.com/testcontainers/testcontainers-go/network" +) + +func ExampleNew() { + // createNetwork { + ctx := context.Background() + + net, err := network.New(ctx) + if err != nil { + fmt.Println(err) + return + } + defer func() { + if err := net.Remove(ctx); err != nil { + log.Fatalf("failed to remove network: %s", err) + } + }() + // } + + fmt.Println(net.ID != "") + fmt.Println(net.Driver) + + // Output: + // true + // bridge +} + +func ExampleNew_withOptions() { + // newNetworkWithOptions { + ctx := context.Background() + + // dockernetwork is the alias used for github.com/docker/docker/api/types/network + ipamConfig := dockernetwork.IPAM{ + Driver: "default", + Config: []dockernetwork.IPAMConfig{ + { + Subnet: "10.1.1.0/24", + Gateway: "10.1.1.254", + }, + }, + Options: map[string]string{ + "driver": "host-local", + }, + } + net, err := network.New(ctx, + network.WithIPAM(&ipamConfig), + network.WithAttachable(), + network.WithDriver("bridge"), + ) + if err != nil { + fmt.Println(err) + return + } + defer func() { + if err := net.Remove(ctx); err != nil { + log.Fatalf("failed to remove network: %s", err) + } + }() + // } + + fmt.Println(net.ID != "") + fmt.Println(net.Driver) + + // Output: + // true + // bridge +} diff --git a/network/network_test.go b/network/network_test.go index ddc92f36c7..4ff80e2bed 100644 --- a/network/network_test.go +++ b/network/network_test.go @@ -2,8 +2,6 @@ package network_test import ( "context" - "fmt" - "log" "testing" "time" @@ -23,9 +21,7 @@ const ( nginxDefaultPort = "80/tcp" ) -// Create a network. -func ExampleNew() { - // createNetwork { +func TestNew(t *testing.T) { ctx := context.Background() net, err := network.New(ctx, @@ -35,18 +31,14 @@ func ExampleNew() { network.WithInternal(), network.WithLabels(map[string]string{"this-is-a-test": "value"}), ) - if err != nil { - fmt.Println(err) - return - } + require.NoError(t, err) defer func() { if err := net.Remove(ctx); err != nil { - log.Fatalf("failed to remove network: %s", err) + t.Fatalf("failed to remove network: %s", err) } }() networkName := net.Name - // } nginxC, _ := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ @@ -62,49 +54,30 @@ func ExampleNew() { }) defer func() { if err := nginxC.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + t.Fatalf("failed to terminate container: %s", err) } }() client, err := testcontainers.NewDockerClientWithOpts(context.Background()) - if err != nil { - fmt.Println(err) - return - } + require.NoError(t, err) resources, err := client.NetworkList(context.Background(), dockernetwork.ListOptions{ Filters: filters.NewArgs(filters.Arg("name", networkName)), }) - if err != nil { - fmt.Println(err) - return - } + require.NoError(t, err) - fmt.Println(len(resources)) + assert.Len(t, resources, 1) newNetwork := resources[0] expectedLabels := testcontainers.GenericLabels() expectedLabels["this-is-a-test"] = "true" - fmt.Println(newNetwork.Attachable) - fmt.Println(newNetwork.Internal) - fmt.Println(newNetwork.Labels["this-is-a-test"]) - - state, err := nginxC.State(ctx) - if err != nil { - fmt.Println(err) - return - } - - fmt.Println(state.Running) + assert.True(t, newNetwork.Attachable) + assert.True(t, newNetwork.Internal) + assert.Equal(t, "value", newNetwork.Labels["this-is-a-test"]) - // Output: - // 1 - // true - // true - // value - // true + require.NoError(t, err) } // testNetworkAliases { From c88e776a00a79cf1acd3a161bf77e6f4fc0ca2df Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 9 Aug 2024 10:46:22 +0100 Subject: [PATCH 016/126] chore: improve lifecycle errors (#2708) Improve the lifecycle errors with wrapping so that its easier to determine the cause of an error. --- container_test.go | 23 ++++++----------------- docker.go | 8 ++++---- lifecycle.go | 2 +- options_test.go | 17 ++++++----------- wait/wait.go | 2 +- 5 files changed, 18 insertions(+), 34 deletions(-) diff --git a/container_test.go b/container_test.go index 0da1b967f8..d2a070f2de 100644 --- a/container_test.go +++ b/container_test.go @@ -8,7 +8,6 @@ import ( "fmt" "io" "log" - "strings" "testing" "time" @@ -319,28 +318,18 @@ func Test_GetLogsFromFailedContainer(t *testing.T) { ContainerRequest: req, Started: true, }) - - if err != nil && err.Error() != "failed to start container: container exited with code 0" { - t.Fatal(err) - } else if err == nil { - terminateContainerOnEnd(t, ctx, c) - t.Fatal("was expecting error starting container") - } + terminateContainerOnEnd(t, ctx, c) + require.Error(t, err) + require.Contains(t, err.Error(), "container exited with code 0") logs, logErr := c.Logs(ctx) - if logErr != nil { - t.Fatal(logErr) - } + require.NoError(t, logErr) b, err := io.ReadAll(logs) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) log := string(b) - if strings.Contains(log, "I was not expecting this") == false { - t.Fatalf("could not find expected log in %s", log) - } + require.Contains(t, log, "I was not expecting this") } // dockerImageSubstitutor { diff --git a/docker.go b/docker.go index c3dfcb8da2..bc99cbc2dd 100644 --- a/docker.go +++ b/docker.go @@ -221,24 +221,24 @@ func (c *DockerContainer) SessionID() string { func (c *DockerContainer) Start(ctx context.Context) error { err := c.startingHook(ctx) if err != nil { - return err + return fmt.Errorf("starting hook: %w", err) } if err := c.provider.client.ContainerStart(ctx, c.ID, container.StartOptions{}); err != nil { - return err + return fmt.Errorf("container start: %w", err) } defer c.provider.Close() err = c.startedHook(ctx) if err != nil { - return err + return fmt.Errorf("started hook: %w", err) } c.isRunning = true err = c.readiedHook(ctx) if err != nil { - return err + return fmt.Errorf("readied hook: %w", err) } return nil diff --git a/lifecycle.go b/lifecycle.go index a0c6b99b88..ce46a77916 100644 --- a/lifecycle.go +++ b/lifecycle.go @@ -274,7 +274,7 @@ var defaultReadinessHook = func() ContainerLifecycleHooks { dockerContainer.ID[:12], dockerContainer.Image, dockerContainer.WaitingFor, ) if err := dockerContainer.WaitingFor.WaitUntilReady(ctx, c); err != nil { - return err + return fmt.Errorf("wait until ready: %w", err) } } diff --git a/options_test.go b/options_test.go index 13717f1da0..e19ecde96e 100644 --- a/options_test.go +++ b/options_test.go @@ -91,19 +91,14 @@ func TestWithLogConsumers(t *testing.T) { err := testcontainers.WithLogConsumers(lc)(&req) require.NoError(t, err) - c, err := testcontainers.GenericContainer(context.Background(), req) + ctx := context.Background() + c, err := testcontainers.GenericContainer(ctx, req) + terminateContainerOnEnd(t, ctx, c) // we expect an error because the MySQL environment variables are not set // but this is expected because we just want to test the log consumer - require.EqualError(t, err, "failed to start container: container exited with code 1") - // c might be not nil even on error - if c != nil { - defer func() { - err = c.Terminate(context.Background()) - require.NoError(t, err) - }() - } - - assert.NotEmpty(t, lc.msgs) + require.Error(t, err) + require.Contains(t, err.Error(), "container exited with code 1") + require.NotEmpty(t, lc.msgs) } func TestWithStartupCommand(t *testing.T) { diff --git a/wait/wait.go b/wait/wait.go index c9bc0606f6..ccfd4735e2 100644 --- a/wait/wait.go +++ b/wait/wait.go @@ -36,7 +36,7 @@ type StrategyTarget interface { func checkTarget(ctx context.Context, target StrategyTarget) error { state, err := target.State(ctx) if err != nil { - return err + return fmt.Errorf("get state: %w", err) } return checkState(state) From 3c052bf6db415cb7bf2f88620cce74834e4edd2a Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 9 Aug 2024 10:50:10 +0100 Subject: [PATCH 017/126] chore: remove obsolete compose version (#2710) Remove the obsolete version field from all docker compose files to stop it warning. --- modules/compose/compose_api_test.go | 4 ++-- modules/compose/testdata/docker-compose-build.yml | 3 +-- modules/compose/testdata/docker-compose-complex.yml | 3 +-- modules/compose/testdata/docker-compose-container-name.yml | 1 - modules/compose/testdata/docker-compose-no-exposed-ports.yml | 1 - modules/compose/testdata/docker-compose-override.yml | 1 - modules/compose/testdata/docker-compose-postgres.yml | 1 - modules/compose/testdata/docker-compose-short-lifespan.yml | 1 - modules/compose/testdata/docker-compose-simple.yml | 1 - modules/compose/testdata/docker-compose-volume.yml | 1 - 10 files changed, 4 insertions(+), 13 deletions(-) diff --git a/modules/compose/compose_api_test.go b/modules/compose/compose_api_test.go index e4dff06cfd..303d2bf814 100644 --- a/modules/compose/compose_api_test.go +++ b/modules/compose/compose_api_test.go @@ -435,7 +435,7 @@ func TestDockerComposeAPIComplex(t *testing.T) { func TestDockerComposeAPIWithStackReader(t *testing.T) { identifier := testNameHash(t.Name()) - composeContent := `version: '3.7' + composeContent := ` services: api-nginx: image: docker.io/nginx:stable-alpine @@ -475,7 +475,7 @@ services: func TestDockerComposeAPIWithStackReaderAndComposeFile(t *testing.T) { identifier := testNameHash(t.Name()) simple, _ := RenderComposeSimple(t) - composeContent := `version: '3.7' + composeContent := ` services: api-postgres: image: docker.io/postgres:14 diff --git a/modules/compose/testdata/docker-compose-build.yml b/modules/compose/testdata/docker-compose-build.yml index 88c6ccda40..d2210d3153 100644 --- a/modules/compose/testdata/docker-compose-build.yml +++ b/modules/compose/testdata/docker-compose-build.yml @@ -1,4 +1,3 @@ -version: '3' services: {{ .ServiceType }}-echo: build: @@ -8,4 +7,4 @@ services: ports: - target: 8080 published: {{ .Port_0 }} - protocol: tcp \ No newline at end of file + protocol: tcp diff --git a/modules/compose/testdata/docker-compose-complex.yml b/modules/compose/testdata/docker-compose-complex.yml index f2eacf026a..fe0636dff2 100644 --- a/modules/compose/testdata/docker-compose-complex.yml +++ b/modules/compose/testdata/docker-compose-complex.yml @@ -1,4 +1,3 @@ -version: '3' services: {{ .ServiceType }}-nginx: image: docker.io/nginx:stable-alpine @@ -10,4 +9,4 @@ services: - MYSQL_DATABASE=db - MYSQL_ROOT_PASSWORD=my-secret-pw ports: - - "{{ .Port_1 }}:3306" \ No newline at end of file + - "{{ .Port_1 }}:3306" diff --git a/modules/compose/testdata/docker-compose-container-name.yml b/modules/compose/testdata/docker-compose-container-name.yml index b7e497fd84..c46ca68888 100644 --- a/modules/compose/testdata/docker-compose-container-name.yml +++ b/modules/compose/testdata/docker-compose-container-name.yml @@ -1,4 +1,3 @@ -version: '3' services: {{ .ServiceType }}-nginx: container_name: {{ .ServiceType }}-nginxy diff --git a/modules/compose/testdata/docker-compose-no-exposed-ports.yml b/modules/compose/testdata/docker-compose-no-exposed-ports.yml index 58da1351f4..3f487156c3 100644 --- a/modules/compose/testdata/docker-compose-no-exposed-ports.yml +++ b/modules/compose/testdata/docker-compose-no-exposed-ports.yml @@ -1,4 +1,3 @@ -version: '3' services: {{ .ServiceType }}-nginx: image: docker.io/nginx:stable-alpine diff --git a/modules/compose/testdata/docker-compose-override.yml b/modules/compose/testdata/docker-compose-override.yml index 8a44e78631..c8714256e0 100644 --- a/modules/compose/testdata/docker-compose-override.yml +++ b/modules/compose/testdata/docker-compose-override.yml @@ -1,4 +1,3 @@ -version: '3' services: {{ .ServiceType }}-nginx: image: docker.io/nginx:stable-alpine diff --git a/modules/compose/testdata/docker-compose-postgres.yml b/modules/compose/testdata/docker-compose-postgres.yml index 7988a43266..9671a7bdb5 100644 --- a/modules/compose/testdata/docker-compose-postgres.yml +++ b/modules/compose/testdata/docker-compose-postgres.yml @@ -1,4 +1,3 @@ -version: '3' services: {{ .ServiceType }}-postgres: image: docker.io/postgres:14 diff --git a/modules/compose/testdata/docker-compose-short-lifespan.yml b/modules/compose/testdata/docker-compose-short-lifespan.yml index 2deb847d85..47fd1314bb 100644 --- a/modules/compose/testdata/docker-compose-short-lifespan.yml +++ b/modules/compose/testdata/docker-compose-short-lifespan.yml @@ -1,4 +1,3 @@ -version: '3' services: tzatziki: image: docker.io/alpine:latest diff --git a/modules/compose/testdata/docker-compose-simple.yml b/modules/compose/testdata/docker-compose-simple.yml index 90b9a4be87..ebf8a64b6f 100644 --- a/modules/compose/testdata/docker-compose-simple.yml +++ b/modules/compose/testdata/docker-compose-simple.yml @@ -1,4 +1,3 @@ -version: '3' services: {{ .ServiceType }}-nginx: image: docker.io/nginx:stable-alpine diff --git a/modules/compose/testdata/docker-compose-volume.yml b/modules/compose/testdata/docker-compose-volume.yml index 81add904d0..f284a71452 100644 --- a/modules/compose/testdata/docker-compose-volume.yml +++ b/modules/compose/testdata/docker-compose-volume.yml @@ -1,4 +1,3 @@ -version: '3' services: {{ .ServiceType }}-nginx: image: docker.io/nginx:stable-alpine From 7646ccf6d54090fa8f2e9df7f50096150c7900b5 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 9 Aug 2024 11:25:43 +0100 Subject: [PATCH 018/126] chore(registry): disable build log (#2711) Disable build log so its easier to see where failures occur. --- modules/registry/registry_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/registry/registry_test.go b/modules/registry/registry_test.go index 1b6849ebbe..dd071ef5be 100644 --- a/modules/registry/registry_test.go +++ b/modules/registry/registry_test.go @@ -144,7 +144,6 @@ func TestRunContainer_authenticated(t *testing.T) { BuildArgs: map[string]*string{ "REGISTRY_PORT": &strPort, }, - PrintBuildLog: true, }, AlwaysPullImage: true, // make sure the authentication takes place ExposedPorts: []string{"6379/tcp"}, @@ -190,7 +189,6 @@ func TestRunContainer_authenticated(t *testing.T) { BuildArgs: map[string]*string{ "REGISTRY_PORT": &strPort, }, - PrintBuildLog: true, }, AlwaysPullImage: true, // make sure the authentication takes place ExposedPorts: []string{"6379/tcp"}, @@ -302,7 +300,6 @@ func TestRunContainer_wrongData(t *testing.T) { BuildArgs: map[string]*string{ "REGISTRY_PORT": &strPort, }, - PrintBuildLog: true, }, AlwaysPullImage: true, // make sure the authentication takes place ExposedPorts: []string{"6379/tcp"}, From 125698c6056dfd86d95d93b62aca98d128ec135e Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 9 Aug 2024 11:32:15 +0100 Subject: [PATCH 019/126] docs: improve docs for container methods (#2713) Improve the documentation for container Terminate and IsRunning methods. --- container.go | 7 +++++-- docker.go | 13 +++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/container.go b/container.go index b772ba948f..6f17a7e3ff 100644 --- a/container.go +++ b/container.go @@ -43,10 +43,13 @@ type Container interface { MappedPort(context.Context, nat.Port) (nat.Port, error) // get externally mapped port for a container port Ports(context.Context) (nat.PortMap, error) // Deprecated: Use c.Inspect(ctx).NetworkSettings.Ports instead SessionID() string // get session id - IsRunning() bool + IsRunning() bool // IsRunning returns true if the container is running, false otherwise. Start(context.Context) error // start the container Stop(context.Context, *time.Duration) error // stop the container - Terminate(context.Context) error // terminate the container + + // Terminate stops and removes the container and its image if it was built and not flagged as kept. + Terminate(ctx context.Context) error + Logs(context.Context) (io.ReadCloser, error) // Get logs of the container FollowOutput(LogConsumer) // Deprecated: it will be removed in the next major release StartLogProducer(context.Context, ...LogProductionOption) error // Deprecated: Use the ContainerRequest instead diff --git a/docker.go b/docker.go index bc99cbc2dd..f6308f1d33 100644 --- a/docker.go +++ b/docker.go @@ -244,15 +244,20 @@ func (c *DockerContainer) Start(ctx context.Context) error { return nil } -// Stop will stop an already started container +// Stop stops the container. // -// In case the container fails to stop -// gracefully within a time frame specified by the timeout argument, -// it is forcefully terminated (killed). +// 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. +// +// All hooks are called in the following order: +// - [ContainerLifecycleHooks.PreStops] +// - [ContainerLifecycleHooks.PostStops] +// +// If the container is already stopped, the method is a no-op. func (c *DockerContainer) Stop(ctx context.Context, timeout *time.Duration) error { err := c.stoppingHook(ctx) if err != nil { From c0c24f834134ccaca0505ead1dde231585b056d4 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 9 Aug 2024 12:05:07 +0100 Subject: [PATCH 020/126] chore: remove unused params from defaultPreCreateHook (#2714) Remove unused parameters from the defaultPreCreateHook function. --- docker.go | 2 +- lifecycle.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker.go b/docker.go index f6308f1d33..3ee1a658fc 100644 --- a/docker.go +++ b/docker.go @@ -1091,7 +1091,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque // default hooks include logger hook and pre-create hook defaultHooks := []ContainerLifecycleHooks{ DefaultLoggingHook(p.Logger), - defaultPreCreateHook(ctx, p, req, dockerInput, hostConfig, networkingConfig), + defaultPreCreateHook(p, dockerInput, hostConfig, networkingConfig), defaultCopyFileToContainerHook(req.Files), defaultLogConsumersHook(req.LogConsumerCfg), defaultReadinessHook(), diff --git a/lifecycle.go b/lifecycle.go index ce46a77916..d263f5ca27 100644 --- a/lifecycle.go +++ b/lifecycle.go @@ -115,7 +115,7 @@ var DefaultLoggingHook = func(logger Logging) ContainerLifecycleHooks { } // defaultPreCreateHook is a hook that will apply the default configuration to the container -var defaultPreCreateHook = func(ctx context.Context, p *DockerProvider, req ContainerRequest, dockerInput *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig) ContainerLifecycleHooks { +var defaultPreCreateHook = func(p *DockerProvider, dockerInput *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig) ContainerLifecycleHooks { return ContainerLifecycleHooks{ PreCreates: []ContainerRequestHook{ func(ctx context.Context, req ContainerRequest) error { From b36f59ff0c9f34376a7a34cd28c0c19d9ce7b8fe Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 9 Aug 2024 13:08:49 +0100 Subject: [PATCH 021/126] chore(mysql): add missing error check in example (#2707) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(mysql): add missing error check in example Add a missing error check in the mysql example for connection setup. * chore: address gocritic Add gocritic no lint. Co-authored-by: Manuel de la Peña --------- Co-authored-by: Manuel de la Peña --- modules/mysql/examples_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/mysql/examples_test.go b/modules/mysql/examples_test.go index 6872415fbe..bf203c9018 100644 --- a/modules/mysql/examples_test.go +++ b/modules/mysql/examples_test.go @@ -66,7 +66,10 @@ func ExampleRun_connect() { } }() - connectionString, _ := mysqlContainer.ConnectionString(ctx) + connectionString, err := mysqlContainer.ConnectionString(ctx) + if err != nil { + log.Fatalf("failed to get connection string: %s", err) // nolint:gocritic + } db, err := sql.Open("mysql", connectionString) if err != nil { From dbc0ba988c66b008838285babd48829c80508ea6 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 9 Aug 2024 13:12:15 +0100 Subject: [PATCH 022/126] fix(compose): remove test volumes (#2712) Remove test volumes so that we don't leave orphaned resources after tests have run. Remove really unused code as there is no need for it. Add missing error checks on pipe setup. --- modules/compose/compose_api.go | 8 -- modules/compose/compose_api_test.go | 145 +++++++++------------------- modules/compose/compose_local.go | 20 +++- 3 files changed, 60 insertions(+), 113 deletions(-) diff --git a/modules/compose/compose_api.go b/modules/compose/compose_api.go index a4bbf0d5cd..ba29c070b1 100644 --- a/modules/compose/compose_api.go +++ b/modules/compose/compose_api.go @@ -32,14 +32,6 @@ func (f stackUpOptionFunc) applyToStackUp(o *stackUpOptions) { f(o) } -//nolint:unused -type stackDownOptionFunc func(do *api.DownOptions) - -//nolint:unused -func (f stackDownOptionFunc) applyToStackDown(do *api.DownOptions) { - f(do) -} - // RunServices is comparable to 'docker compose run' as it only creates a subset of containers // instead of all services defined by the project func RunServices(serviceNames ...string) StackUpOption { diff --git a/modules/compose/compose_api_test.go b/modules/compose/compose_api_test.go index 303d2bf814..6771454347 100644 --- a/modules/compose/compose_api_test.go +++ b/modules/compose/compose_api_test.go @@ -27,14 +27,12 @@ func TestDockerComposeAPI(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) - require.NoError(t, compose.Up(ctx, Wait(true)), "compose.Up()") + err = compose.Up(ctx, Wait(true)) + cleanup(t, compose) + require.NoError(t, err, "compose.Up()") } func TestDockerComposeAPIStrategyForInvalidService(t *testing.T) { @@ -42,10 +40,6 @@ func TestDockerComposeAPIStrategyForInvalidService(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -53,7 +47,7 @@ func TestDockerComposeAPIStrategyForInvalidService(t *testing.T) { // Appending with _1 as given in the Java Test-Containers Example WaitForService("non-existent-srv-1", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Up(ctx, Wait(true)) - + cleanup(t, compose) require.Error(t, err, "Expected error to be thrown because service with wait strategy is not running") require.Equal(t, "no container found for service name non-existent-srv-1", err.Error()) @@ -68,17 +62,13 @@ func TestDockerComposeAPIWithWaitLogStrategy(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) err = compose. WaitForService("api-mysql", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Up(ctx, Wait(true)) - + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -93,17 +83,13 @@ func TestDockerComposeAPIWithRunServices(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) err = compose. WaitForService("api-nginx", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Up(ctx, Wait(true), RunServices("api-nginx")) - + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -120,17 +106,13 @@ func TestDockerComposeAPI_TestcontainersLabelsArePresent(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) err = compose. WaitForService("api-mysql", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Up(ctx, Wait(true)) - + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -173,7 +155,7 @@ func TestDockerComposeAPI_WithReaper(t *testing.T) { err = compose. WaitForService("api-mysql", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Up(ctx, Wait(true)) - + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -193,10 +175,6 @@ func TestDockerComposeAPI_WithoutReaper(t *testing.T) { path, _ := RenderComposeComplex(t) compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - // because reaper is disabled, we need to manually stop the containers - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -204,7 +182,7 @@ func TestDockerComposeAPI_WithoutReaper(t *testing.T) { err = compose. WaitForService("api-mysql", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Up(ctx, Wait(true)) - + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -221,14 +199,12 @@ func TestDockerComposeAPIWithStopServices(t *testing.T) { WithLogger(testcontainers.TestLogger(t))) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) - require.NoError(t, compose.Up(ctx, Wait(true)), "compose.Up()") + err = compose.Up(ctx, Wait(true)) + cleanup(t, compose) + require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -256,10 +232,6 @@ func TestDockerComposeAPIWithWaitForService(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -269,7 +241,7 @@ func TestDockerComposeAPIWithWaitForService(t *testing.T) { }). WaitForService("api-nginx", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Up(ctx, Wait(true)) - + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -283,10 +255,6 @@ func TestDockerComposeAPIWithWaitHTTPStrategy(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -296,7 +264,7 @@ func TestDockerComposeAPIWithWaitHTTPStrategy(t *testing.T) { }). WaitForService("api-nginx", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Up(ctx, Wait(true)) - + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -310,10 +278,6 @@ func TestDockerComposeAPIWithContainerName(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -323,7 +287,7 @@ func TestDockerComposeAPIWithContainerName(t *testing.T) { }). WaitForService("api-nginx", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Up(ctx, Wait(true)) - + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -337,17 +301,13 @@ func TestDockerComposeAPIWithWaitStrategy_NoExposedPorts(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) err = compose. WaitForService("api-nginx", wait.ForLog("Configuration complete; ready for start up")). Up(ctx, Wait(true)) - + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -361,10 +321,6 @@ func TestDockerComposeAPIWithMultipleWaitStrategies(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -372,7 +328,7 @@ func TestDockerComposeAPIWithMultipleWaitStrategies(t *testing.T) { WaitForService("api-mysql", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second)). WaitForService("api-nginx", wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)). Up(ctx, Wait(true)) - + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -387,10 +343,6 @@ func TestDockerComposeAPIWithFailedStrategy(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -400,7 +352,7 @@ func TestDockerComposeAPIWithFailedStrategy(t *testing.T) { }). WaitForService("api-nginx_1", wait.NewHTTPStrategy("/").WithPort("8080/tcp").WithStartupTimeout(5*time.Second)). Up(ctx, Wait(true)) - + cleanup(t, compose) // 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 require.Error(t, err, "Expected error to be thrown because of a wrong suplied wait strategy") @@ -416,14 +368,12 @@ func TestDockerComposeAPIComplex(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) - require.NoError(t, compose.Up(ctx, Wait(true)), "compose.Up()") + err = compose.Up(ctx, Wait(true)) + cleanup(t, compose) + require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -456,6 +406,7 @@ services: "bar": "BAR", }). Up(ctx, Wait(true)) + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -463,7 +414,7 @@ services: assert.Len(t, serviceNames, 1) assert.Contains(t, serviceNames, "api-nginx") - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") + require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveVolumes(true), RemoveImagesLocal), "compose.Down()") // check files where removed f, err := os.Stat(compose.configs[0]) @@ -490,10 +441,6 @@ services: ) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -503,6 +450,7 @@ services: "foo": "FOO", }). Up(ctx, Wait(true)) + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -527,10 +475,6 @@ func TestDockerComposeAPIWithEnvironment(t *testing.T) { compose, err := NewDockerComposeWith(WithStackFiles(path), identifier) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -539,6 +483,7 @@ func TestDockerComposeAPIWithEnvironment(t *testing.T) { "bar": "BAR", }). Up(ctx, Wait(true)) + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -566,10 +511,6 @@ func TestDockerComposeAPIWithMultipleComposeFiles(t *testing.T) { compose, err := NewDockerComposeWith(composeFiles, identifier) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -579,6 +520,7 @@ func TestDockerComposeAPIWithMultipleComposeFiles(t *testing.T) { "foo": "FOO", }). Up(ctx, Wait(true)) + cleanup(t, compose) require.NoError(t, err, "compose.Up()") serviceNames := compose.Services() @@ -601,9 +543,7 @@ func TestDockerComposeAPIWithVolume(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) + cleanup(t, compose) ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -617,14 +557,11 @@ func TestDockerComposeAPIWithRecreate(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) err = compose.Up(ctx, WithRecreate(api.RecreateNever), WithRecreateDependencies(api.RecreateNever), Wait(true)) + cleanup(t, compose) require.NoError(t, err, "compose.Up()") } @@ -639,6 +576,7 @@ func TestDockerComposeAPIVolumesDeletedOnDown(t *testing.T) { t.Cleanup(cancel) err = compose.Up(ctx, Wait(true)) + cleanup(t, compose) require.NoError(t, err, "compose.Up()") err = compose.Down(context.Background(), RemoveOrphans(true), RemoveVolumes(true), RemoveImagesLocal) @@ -660,17 +598,13 @@ func TestDockerComposeAPIWithBuild(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) err = compose. WaitForService("api-echo", wait.ForHTTP("/env").WithPort("8080/tcp")). Up(ctx, Wait(true)) - + cleanup(t, compose) require.NoError(t, err, "compose.Up()") } @@ -679,10 +613,6 @@ func TestDockerComposeApiWithWaitForShortLifespanService(t *testing.T) { compose, err := NewDockerCompose(path) require.NoError(t, err, "NewDockerCompose()") - t.Cleanup(func() { - require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveImagesLocal), "compose.Down()") - }) - ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -691,7 +621,7 @@ func TestDockerComposeApiWithWaitForShortLifespanService(t *testing.T) { WaitForService("tzatziki", wait.ForExit().WithExitTimeout(10*time.Second)). WaitForService("falafel", wait.ForExit().WithExitTimeout(10*time.Second)). Up(ctx) - + cleanup(t, compose) require.NoError(t, err, "compose.Up()") services := compose.Services() @@ -704,3 +634,16 @@ func TestDockerComposeApiWithWaitForShortLifespanService(t *testing.T) { func testNameHash(name string) StackIdentifier { return StackIdentifier(fmt.Sprintf("%x", fnv.New32a().Sum([]byte(name)))) } + +// cleanup is a helper function that schedules the compose stack to be stopped when the test ends. +func cleanup(t *testing.T, compose *dockerCompose) { + t.Helper() + t.Cleanup(func() { + require.NoError(t, compose.Down( + context.Background(), + RemoveOrphans(true), + RemoveVolumes(true), + RemoveImagesLocal, + ), "compose.Down()") + }) +} diff --git a/modules/compose/compose_local.go b/modules/compose/compose_local.go index 19b0ce379a..cb818dbc94 100644 --- a/modules/compose/compose_local.go +++ b/modules/compose/compose_local.go @@ -307,14 +307,26 @@ func execute( cmd.Env = append(cmd.Env, key+"="+value) } - stdoutIn, _ := cmd.StdoutPipe() - stderrIn, _ := cmd.StderrPipe() + stdoutIn, err := cmd.StdoutPipe() + if err != nil { + return ExecError{ + Command: cmd.Args, + Error: fmt.Errorf("stdout: %w", err), + } + } + + stderrIn, err := cmd.StderrPipe() + if err != nil { + return ExecError{ + Command: cmd.Args, + Error: fmt.Errorf("stderr: %w", err), + } + } stdout := newCapturingPassThroughWriter(os.Stdout) stderr := newCapturingPassThroughWriter(os.Stderr) - err := cmd.Start() - if err != nil { + if err = cmd.Start(); err != nil { execCmd := []string{"Starting command", dirContext, binary} execCmd = append(execCmd, args...) From 3c326f89e4886744f18726fb6da1628d6be529cd Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 9 Aug 2024 15:55:10 +0100 Subject: [PATCH 023/126] fix: filter context errors from log production (#2715) Don't return context errors from log production as it's confusing to callers which cancel, making it harder to understand any actual errors that occurred. --- docker.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docker.go b/docker.go index 3ee1a658fc..6bd80c39c4 100644 --- a/docker.go +++ b/docker.go @@ -819,7 +819,16 @@ func (c *DockerContainer) stopLogProduction() error { c.logProductionWaitGroup.Wait() - return <-c.logProductionError + if err := <-c.logProductionError; err != nil { + if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) { + // Returning context errors is not useful for the consumer. + return nil + } + + return err + } + + return nil } // GetLogProductionErrorChannel exposes the only way for the consumer From fc4b264e76f914849b35589ac1c0dd355519e4ed Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 9 Aug 2024 16:03:29 +0100 Subject: [PATCH 024/126] fix: skip unhealthy (#2717) Pass the right variable to skip unhealthy function in tests, so it actually functions. --- reaper_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reaper_test.go b/reaper_test.go index 225d1f882e..c757fbb3ea 100644 --- a/reaper_test.go +++ b/reaper_test.go @@ -467,7 +467,7 @@ func Test_ReaperReusedIfHealthy(t *testing.T) { testProvider := newMockReaperProvider(t) t.Cleanup(testProvider.RestoreReaperState) - SkipIfProviderIsNotHealthy(&testing.T{}) + SkipIfProviderIsNotHealthy(t) ctx := context.Background() // As other integration tests run with the (shared) Reaper as well, re-use the instance to not interrupt other tests @@ -507,7 +507,7 @@ func Test_RecreateReaperIfTerminated(t *testing.T) { mockProvider := newMockReaperProvider(t) t.Cleanup(mockProvider.RestoreReaperState) - SkipIfProviderIsNotHealthy(&testing.T{}) + SkipIfProviderIsNotHealthy(t) provider, _ := ProviderDocker.GetProvider() ctx := context.Background() @@ -552,7 +552,7 @@ func TestReaper_reuseItFromOtherTestProgramUsingDocker(t *testing.T) { reaperInstance = nil reaperOnce = sync.Once{} - SkipIfProviderIsNotHealthy(&testing.T{}) + SkipIfProviderIsNotHealthy(t) ctx := context.Background() // As other integration tests run with the (shared) Reaper as well, re-use the instance to not interrupt other tests From 8dbd4cdc120197eb472d0a860f8d60d2b26653ea Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 12 Aug 2024 09:41:22 +0100 Subject: [PATCH 025/126] fix: readiness hook back off (#2718) Fix the definition of readiness hook back off which had the wrong MaxElapsedTime resulting in some flaky tests. --- lifecycle.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lifecycle.go b/lifecycle.go index d263f5ca27..2a8ae949ab 100644 --- a/lifecycle.go +++ b/lifecycle.go @@ -233,15 +233,15 @@ var defaultReadinessHook = func() ContainerLifecycleHooks { func(ctx context.Context, c Container) error { // wait until all the exposed ports are mapped: // it will be ready when all the exposed ports are mapped, - // checking every 50ms, up to 5s, and failing if all the - // exposed ports are not mapped in that time. + // checking every 50ms, up to 1s, and failing if all the + // exposed ports are not mapped in 5s. dockerContainer := c.(*DockerContainer) b := backoff.NewExponentialBackOff() b.InitialInterval = 50 * time.Millisecond - b.MaxElapsedTime = 1 * time.Second - b.MaxInterval = 5 * time.Second + b.MaxElapsedTime = 5 * time.Second + b.MaxInterval = time.Duration(float64(time.Second) * backoff.DefaultRandomizationFactor) err := backoff.RetryNotify( func() error { From 4e9cb66eb079454b3f800c2e1a25cae4013d1d85 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 12 Aug 2024 11:20:56 +0100 Subject: [PATCH 026/126] feat(wait): skip internal host port check (#2691) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(wait): skip internal host port check Add the ability to skip the internal host port check when performing as HostPortStrategy check. This is useful when a container does bind to the internal port until additional conditions are met. Also improve wait for port function documentation while there. * docs: document skip internal check --------- Co-authored-by: Manuel de la Peña --- docs/features/wait/host_port.md | 21 +++++++++++++++++++ wait/host_port.go | 37 +++++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/docs/features/wait/host_port.md b/docs/features/wait/host_port.md index edfad5a188..1b6090b584 100644 --- a/docs/features/wait/host_port.md +++ b/docs/features/wait/host_port.md @@ -6,6 +6,7 @@ The host-port wait strategy will check if the container is listening to a specif - alternatively, wait for the lowest exposed port in the container. - the startup timeout to be used, default is 60 seconds. - the poll interval to be used, default is 100 milliseconds. +- skip the internal check. Variations on the HostPort wait strategy are supported, including: @@ -39,3 +40,23 @@ req := ContainerRequest{ WaitingFor: wait.ForExposedPort(), } ``` + +## Skipping the internal check + +_Testcontainers for Go_ checks if the container is listening to the port internally before returning the control to the caller. For that it uses a shell command to check the port status: + + +[Internal check](../../../wait/host_port.go) inside_block:buildInternalCheckCommand + + +But there are cases where this internal check is not needed, for example when a shell is not available in the container or +when the container doesn't bind the port internally until additional conditions are met. +In this case, the `wait.ForExposedPort.SkipInternalCheck` can be used to skip the internal check. + +```golang +req := ContainerRequest{ + Image: "docker.io/nginx:alpine", + ExposedPorts: []string{"80/tcp", "9080/tcp"}, + WaitingFor: wait.ForExposedPort().SkipInternalCheck(), +} +``` diff --git a/wait/host_port.go b/wait/host_port.go index 9d47a0b39d..b349cc0371 100644 --- a/wait/host_port.go +++ b/wait/host_port.go @@ -28,9 +28,15 @@ type HostPortStrategy struct { // all WaitStrategies should have a startupTimeout to avoid waiting infinitely timeout *time.Duration PollInterval time.Duration + + // skipInternalCheck is a flag to skip the internal check, which is useful when + // a shell is not available in the container or when the container doesn't bind + // the port internally until additional conditions are met. + skipInternalCheck bool } -// NewHostPortStrategy constructs a default host port strategy +// NewHostPortStrategy constructs a default host port strategy that waits for the given +// port to be exposed. The default startup timeout is 60 seconds. func NewHostPortStrategy(port nat.Port) *HostPortStrategy { return &HostPortStrategy{ Port: port, @@ -42,18 +48,28 @@ func NewHostPortStrategy(port nat.Port) *HostPortStrategy { // 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 -// ForListeningPort is a helper similar to those in Wait.java -// https://github.com/testcontainers/testcontainers-java/blob/1d85a3834bd937f80aad3a4cec249c027f31aeb4/core/src/main/java/org/testcontainers/containers/wait/strategy/Wait.java +// ForListeningPort returns a host port strategy that waits for the given port +// to be exposed and bound internally the container. +// Alias for `NewHostPortStrategy(port)`. func ForListeningPort(port nat.Port) *HostPortStrategy { return NewHostPortStrategy(port) } -// ForExposedPort constructs an exposed port strategy. Alias for `NewHostPortStrategy("")`. -// This strategy waits for the first port exposed in the Docker container. +// ForExposedPort returns a host port strategy that waits for the first port +// to be exposed and bound internally the container. func ForExposedPort() *HostPortStrategy { return NewHostPortStrategy("") } +// SkipInternalCheck changes the host port strategy to skip the internal check, +// which is useful when a shell is not available in the container or when the +// container doesn't bind the port internally until additional conditions are met. +func (hp *HostPortStrategy) SkipInternalCheck() *HostPortStrategy { + hp.skipInternalCheck = true + + return hp +} + // WithStartupTimeout can be used to change the default startup timeout func (hp *HostPortStrategy) WithStartupTimeout(startupTimeout time.Duration) *HostPortStrategy { hp.timeout = &startupTimeout @@ -130,6 +146,10 @@ func (hp *HostPortStrategy) WaitUntilReady(ctx context.Context, target StrategyT return err } + if hp.skipInternalCheck { + return nil + } + err = internalCheck(ctx, internalPort, target) if err != nil && errors.Is(errShellNotExecutable, err) { log.Println("Shell not executable in container, only external port check will be performed") @@ -164,12 +184,11 @@ func externalCheck(ctx context.Context, ipAddress string, port nat.Port, target } } return err - } else { - _ = conn.Close() - break } + + conn.Close() + return nil } - return nil } func internalCheck(ctx context.Context, internalPort nat.Port, target StrategyTarget) error { From e17af548ed9113075ed4fece37dd372a1691f665 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 12 Aug 2024 12:44:22 +0100 Subject: [PATCH 027/126] chore(mockserver): silence warning about internal port (#2730) Silence the warning about being unable to check internal port by switching to SkipInternalCheck. Ensure that container is returned on error. --- modules/mockserver/mockserver.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/mockserver/mockserver.go b/modules/mockserver/mockserver.go index 7fb5674755..b53f164e86 100644 --- a/modules/mockserver/mockserver.go +++ b/modules/mockserver/mockserver.go @@ -26,7 +26,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom ExposedPorts: []string{"1080/tcp"}, WaitingFor: wait.ForAll( wait.ForLog("started on port: 1080"), - wait.ForListeningPort("1080/tcp"), + wait.ForListeningPort("1080/tcp").SkipInternalCheck(), ), Env: map[string]string{}, } @@ -43,11 +43,15 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *MockServerContainer + if container != nil { + c = &MockServerContainer{Container: container} + } if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &MockServerContainer{Container: container}, nil + return c, nil } // GetURL returns the URL of the MockServer container From 3bc72175f2eacd6423da733b7cc6d312d9bc0490 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 12 Aug 2024 13:47:01 +0100 Subject: [PATCH 028/126] chore: remove unused parameters (#2721) Remove unused parameters from private functions. --- internal/core/docker_host.go | 4 ++-- internal/core/docker_host_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/core/docker_host.go b/internal/core/docker_host.go index 0b55ec01c8..b9d2d60d51 100644 --- a/internal/core/docker_host.go +++ b/internal/core/docker_host.go @@ -160,7 +160,7 @@ func extractDockerSocketFromClient(ctx context.Context, cli client.APIClient) st return checkDockerSocketFn(tcHost) } - testcontainersDockerSocket, err := dockerSocketOverridePath(ctx) + testcontainersDockerSocket, err := dockerSocketOverridePath() if err == nil { return checkDockerSocketFn(testcontainersDockerSocket) } @@ -220,7 +220,7 @@ func dockerHostFromProperties(ctx context.Context) (string, error) { // dockerSocketOverridePath returns the docker socket from the TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE environment variable, // if it's not empty -func dockerSocketOverridePath(ctx context.Context) (string, error) { +func dockerSocketOverridePath() (string, error) { if dockerHostPath, exists := os.LookupEnv("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE"); exists { return dockerHostPath, nil } diff --git a/internal/core/docker_host_test.go b/internal/core/docker_host_test.go index dbdbaa31fe..23d8e1e1fa 100644 --- a/internal/core/docker_host_test.go +++ b/internal/core/docker_host_test.go @@ -189,7 +189,7 @@ func TestExtractDockerHost(t *testing.T) { err := createTmpDockerSocket(tmpDir) require.NoError(t, err) - socket, err := dockerSocketOverridePath(context.Background()) + socket, err := dockerSocketOverridePath() require.NoError(t, err) assert.Equal(t, tmpSocket, socket) }) @@ -199,7 +199,7 @@ func TestExtractDockerHost(t *testing.T) { os.Unsetenv("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE") - socket, err := dockerSocketOverridePath(context.Background()) + socket, err := dockerSocketOverridePath() require.ErrorIs(t, err, ErrDockerSocketOverrideNotSet) assert.Empty(t, socket) }) From bbd4d2c37b9561dff69901d9c6e9b6b66f83bab8 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 12 Aug 2024 13:49:44 +0100 Subject: [PATCH 029/126] chore: increase timeout values (#2719) Increase timeout values from microseconds to milliseconds as the former can lead to failures depending on hardware. --- logconsumer_test.go | 2 +- wait/log_test.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/logconsumer_test.go b/logconsumer_test.go index dec0d5aeb7..401e7a158f 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -276,7 +276,7 @@ func TestContainerLogWithErrClosed(t *testing.T) { if errors.Is(err, context.DeadlineExceeded) { break } - time.Sleep(100 * time.Microsecond) + time.Sleep(10 * time.Millisecond) t.Log("retrying get endpoint") } if err != nil { diff --git a/wait/log_test.go b/wait/log_test.go index 78c5019ae8..295efd3ba1 100644 --- a/wait/log_test.go +++ b/wait/log_test.go @@ -26,7 +26,7 @@ func TestWaitForLog(t *testing.T) { target := NopStrategyTarget{ ReaderCloser: io.NopCloser(bytes.NewReader([]byte("docker"))), } - wg := NewLogStrategy("docker").WithStartupTimeout(100 * time.Microsecond) + wg := NewLogStrategy("docker").WithStartupTimeout(100 * time.Millisecond) err := wg.WaitUntilReady(context.Background(), target) if err != nil { t.Fatal(err) @@ -39,7 +39,7 @@ func TestWaitForLog(t *testing.T) { } // get all words that start with "ip", end with "m" and has a whitespace before the "ip" - wg := NewLogStrategy(`\sip[\w]+m`).WithStartupTimeout(100 * time.Microsecond).AsRegexp() + wg := NewLogStrategy(`\sip[\w]+m`).WithStartupTimeout(100 * time.Millisecond).AsRegexp() err := wg.WaitUntilReady(context.Background(), target) if err != nil { t.Fatal(err) @@ -53,7 +53,7 @@ func TestWaitWithExactNumberOfOccurrences(t *testing.T) { ReaderCloser: io.NopCloser(bytes.NewReader([]byte("kubernetes\r\ndocker\n\rdocker"))), } wg := NewLogStrategy("docker"). - WithStartupTimeout(100 * time.Microsecond). + WithStartupTimeout(100 * time.Millisecond). WithOccurrence(2) err := wg.WaitUntilReady(context.Background(), target) if err != nil { @@ -69,7 +69,7 @@ func TestWaitWithExactNumberOfOccurrences(t *testing.T) { // get texts from "ip" to the next "m". // there are three occurrences of this pattern in the string: // one "ipsum mauris" and two "ipsum dolor sit am" - wg := NewLogStrategy(`ip(.*)m`).WithStartupTimeout(100 * time.Microsecond).AsRegexp().WithOccurrence(3) + wg := NewLogStrategy(`ip(.*)m`).WithStartupTimeout(100 * time.Millisecond).AsRegexp().WithOccurrence(3) err := wg.WaitUntilReady(context.Background(), target) if err != nil { t.Fatal(err) @@ -98,7 +98,7 @@ func TestWaitWithExactNumberOfOccurrencesButItWillNeverHappen(t *testing.T) { // get texts from "ip" to the next "m". // there are only three occurrences matching - wg := NewLogStrategy(`do(.*)ck.+`).WithStartupTimeout(100 * time.Microsecond).AsRegexp().WithOccurrence(4) + wg := NewLogStrategy(`do(.*)ck.+`).WithStartupTimeout(100 * time.Millisecond).AsRegexp().WithOccurrence(4) err := wg.WaitUntilReady(context.Background(), target) if err == nil { t.Fatal("expected error") @@ -127,7 +127,7 @@ func TestWaitShouldFailWithExactNumberOfOccurrences(t *testing.T) { // get "Maecenas". // there are only one occurrence matching - wg := NewLogStrategy(`^Mae[\w]?enas\s`).WithStartupTimeout(100 * time.Microsecond).AsRegexp().WithOccurrence(2) + wg := NewLogStrategy(`^Mae[\w]?enas\s`).WithStartupTimeout(100 * time.Millisecond).AsRegexp().WithOccurrence(2) err := wg.WaitUntilReady(context.Background(), target) if err == nil { t.Fatal("expected error") From dd36a31e5072d963af5491eeda144747407b36ff Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 12 Aug 2024 13:50:42 +0100 Subject: [PATCH 030/126] fix(wait): log test timeout (#2716) Increase the log test timeout to avoid random test failures on slow machines. Convert to require to make tests easier to read / understand. --- wait/log_test.go | 141 +++++++++++++---------------------------------- 1 file changed, 37 insertions(+), 104 deletions(-) diff --git a/wait/log_test.go b/wait/log_test.go index 295efd3ba1..7c767c0e25 100644 --- a/wait/log_test.go +++ b/wait/log_test.go @@ -8,8 +8,11 @@ import ( "time" "github.com/docker/docker/api/types" + "github.com/stretchr/testify/require" ) +const logTimeout = time.Second + const loremIpsum = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. @@ -28,9 +31,7 @@ func TestWaitForLog(t *testing.T) { } wg := NewLogStrategy("docker").WithStartupTimeout(100 * time.Millisecond) err := wg.WaitUntilReady(context.Background(), target) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) }) t.Run("no regexp", func(t *testing.T) { @@ -41,9 +42,7 @@ func TestWaitForLog(t *testing.T) { // get all words that start with "ip", end with "m" and has a whitespace before the "ip" wg := NewLogStrategy(`\sip[\w]+m`).WithStartupTimeout(100 * time.Millisecond).AsRegexp() err := wg.WaitUntilReady(context.Background(), target) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) }) } @@ -56,9 +55,7 @@ func TestWaitWithExactNumberOfOccurrences(t *testing.T) { WithStartupTimeout(100 * time.Millisecond). WithOccurrence(2) err := wg.WaitUntilReady(context.Background(), target) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) }) t.Run("as regexp", func(t *testing.T) { @@ -71,9 +68,7 @@ func TestWaitWithExactNumberOfOccurrences(t *testing.T) { // one "ipsum mauris" and two "ipsum dolor sit am" wg := NewLogStrategy(`ip(.*)m`).WithStartupTimeout(100 * time.Millisecond).AsRegexp().WithOccurrence(3) err := wg.WaitUntilReady(context.Background(), target) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) }) } @@ -83,12 +78,10 @@ func TestWaitWithExactNumberOfOccurrencesButItWillNeverHappen(t *testing.T) { ReaderCloser: io.NopCloser(bytes.NewReader([]byte("kubernetes\r\ndocker"))), } wg := NewLogStrategy("containerd"). - WithStartupTimeout(100 * time.Microsecond). + WithStartupTimeout(logTimeout). WithOccurrence(2) err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("expected error") - } + require.Error(t, err) }) t.Run("as regexp", func(t *testing.T) { @@ -100,9 +93,7 @@ func TestWaitWithExactNumberOfOccurrencesButItWillNeverHappen(t *testing.T) { // there are only three occurrences matching wg := NewLogStrategy(`do(.*)ck.+`).WithStartupTimeout(100 * time.Millisecond).AsRegexp().WithOccurrence(4) err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("expected error") - } + require.Error(t, err) }) } @@ -112,12 +103,10 @@ func TestWaitShouldFailWithExactNumberOfOccurrences(t *testing.T) { ReaderCloser: io.NopCloser(bytes.NewReader([]byte("kubernetes\r\ndocker"))), } wg := NewLogStrategy("docker"). - WithStartupTimeout(100 * time.Microsecond). + WithStartupTimeout(logTimeout). WithOccurrence(2) err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("expected error") - } + require.Error(t, err) }) t.Run("as regexp", func(t *testing.T) { @@ -129,9 +118,7 @@ func TestWaitShouldFailWithExactNumberOfOccurrences(t *testing.T) { // there are only one occurrence matching wg := NewLogStrategy(`^Mae[\w]?enas\s`).WithStartupTimeout(100 * time.Millisecond).AsRegexp().WithOccurrence(2) err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("expected error") - } + require.Error(t, err) }) } @@ -148,37 +135,19 @@ func TestWaitForLogFailsDueToOOMKilledContainer(t *testing.T) { } t.Run("no regexp", func(t *testing.T) { - wg := ForLog("docker"). - WithStartupTimeout(100 * time.Microsecond) + wg := ForLog("docker").WithStartupTimeout(logTimeout) - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "container crashed with out-of-memory (OOMKilled)" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "container crashed with out-of-memory (OOMKilled)" + require.EqualError(t, err, expected) }) t.Run("as regexp", func(t *testing.T) { - wg := ForLog("docker"). - WithStartupTimeout(100 * time.Microsecond).AsRegexp() - - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } + wg := ForLog("docker").WithStartupTimeout(logTimeout).AsRegexp() - expected := "container crashed with out-of-memory (OOMKilled)" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "container crashed with out-of-memory (OOMKilled)" + require.EqualError(t, err, expected) }) } @@ -196,37 +165,19 @@ func TestWaitForLogFailsDueToExitedContainer(t *testing.T) { } t.Run("no regexp", func(t *testing.T) { - wg := ForLog("docker"). - WithStartupTimeout(100 * time.Microsecond) - - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } + wg := ForLog("docker").WithStartupTimeout(logTimeout) - expected := "container exited with code 1" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "container exited with code 1" + require.EqualError(t, err, expected) }) t.Run("as regexp", func(t *testing.T) { - wg := ForLog("docker"). - WithStartupTimeout(100 * time.Microsecond).AsRegexp() + wg := ForLog("docker").WithStartupTimeout(logTimeout).AsRegexp() - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "container exited with code 1" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "container exited with code 1" + require.EqualError(t, err, expected) }) } @@ -243,36 +194,18 @@ func TestWaitForLogFailsDueToUnexpectedContainerStatus(t *testing.T) { } t.Run("no regexp", func(t *testing.T) { - wg := ForLog("docker"). - WithStartupTimeout(100 * time.Microsecond) + wg := ForLog("docker").WithStartupTimeout(logTimeout) - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "unexpected container status \"dead\"" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "unexpected container status \"dead\"" + require.EqualError(t, err, expected) }) t.Run("as regexp", func(t *testing.T) { - wg := ForLog("docker"). - WithStartupTimeout(100 * time.Microsecond).AsRegexp() + wg := ForLog("docker").WithStartupTimeout(logTimeout).AsRegexp() - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "unexpected container status \"dead\"" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "unexpected container status \"dead\"" + require.EqualError(t, err, expected) }) } From cf3db628477107216844994c18b286086de02224 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 12 Aug 2024 15:45:00 +0100 Subject: [PATCH 031/126] fix(compose): container locking (#2722) Fix container locking which was duplicated and held for the duration of the concurrent operation so preventing any concurrency. --- modules/compose/compose_api.go | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/modules/compose/compose_api.go b/modules/compose/compose_api.go index ba29c070b1..426715f0d5 100644 --- a/modules/compose/compose_api.go +++ b/modules/compose/compose_api.go @@ -192,8 +192,8 @@ type dockerCompose struct { // only one strategy can be added to a service, to use multiple use wait.ForAll(...) waitStrategies map[string]wait.Strategy - // used to synchronise writes to the containers map - containersLock sync.RWMutex + // Used to synchronise writes to the containers. + containersLock sync.Mutex // cache for containers that are part of the stack // used in ServiceContainer(...) function to avoid calls to the Docker API @@ -362,10 +362,6 @@ func (d *dockerCompose) Up(ctx context.Context, opts ...StackUpOption) error { }() } - d.containersLock.Lock() - defer d.containersLock.Unlock() - d.containers[srv.Name] = dc - return nil }) } @@ -391,11 +387,6 @@ func (d *dockerCompose) Up(ctx context.Context, opts ...StackUpOption) error { return err } - // cache all the containers on compose.up - d.containersLock.Lock() - defer d.containersLock.Unlock() - d.containers[svc] = target - return strategy.WaitUntilReady(errGrpCtx, target) }) } @@ -427,12 +418,20 @@ func (d *dockerCompose) WithOsEnv() ComposeStack { return d } -func (d *dockerCompose) lookupContainer(ctx context.Context, svcName string) (*testcontainers.DockerContainer, error) { +// cachedContainer returns the cached container for svcName or nil if it doesn't exist. +func (d *dockerCompose) cachedContainer(svcName string) *testcontainers.DockerContainer { d.containersLock.Lock() defer d.containersLock.Unlock() - if ctr, ok := d.containers[svcName]; ok { - return ctr, nil + return d.containers[svcName] +} + +// lookupContainer is used to retrieve the container instance from the cache or the Docker API. +// +// Safe for concurrent calls. +func (d *dockerCompose) lookupContainer(ctx context.Context, svcName string) (*testcontainers.DockerContainer, error) { + if c := d.cachedContainer(svcName); c != nil { + return c, nil } containers, err := d.dockerClient.ContainerList(ctx, container.ListOptions{ @@ -466,15 +465,14 @@ func (d *dockerCompose) lookupContainer(ctx context.Context, svcName string) (*t ctr.SetProvider(dockerProvider) + d.containersLock.Lock() + defer d.containersLock.Unlock() d.containers[svcName] = ctr return ctr, nil } func (d *dockerCompose) lookupNetworks(ctx context.Context) error { - d.containersLock.Lock() - defer d.containersLock.Unlock() - networks, err := d.dockerClient.NetworkList(ctx, dockernetwork.ListOptions{ Filters: filters.NewArgs( filters.Arg("label", fmt.Sprintf("%s=%s", api.ProjectLabel, d.name)), From 4d0e738e35218876345f1af8249fffd73f498473 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Tue, 13 Aug 2024 13:26:52 +0100 Subject: [PATCH 032/126] fix: nginx request failures (#2723) Fix tests which make http requests to nginx container by switching to http startup check, which avoids issues on nginx being able to respond to requests. --- docker_test.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docker_test.go b/docker_test.go index 0da11ef7f9..9e6cb3fb34 100644 --- a/docker_test.go +++ b/docker_test.go @@ -73,7 +73,7 @@ func TestContainerWithHostNetworkOptions(t *testing.T) { nginxHighPort, }, Privileged: true, - WaitingFor: wait.ForListeningPort(nginxHighPort), + WaitingFor: wait.ForHTTP("/").WithPort(nginxHighPort), HostConfigModifier: func(hc *container.HostConfig) { hc.NetworkMode = "host" }, @@ -182,7 +182,7 @@ func TestContainerWithHostNetwork(t *testing.T) { ProviderType: providerType, ContainerRequest: ContainerRequest{ Image: nginxAlpineImage, - WaitingFor: wait.ForListeningPort(nginxHighPort), + WaitingFor: wait.ForHTTP("/").WithPort(nginxHighPort), Files: []ContainerFile{ { HostFilePath: absPath, @@ -414,6 +414,7 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { ExposedPorts: []string{ nginxDefaultPort, }, + WaitingFor: wait.ForHTTP("/").WithPort(nginxDefaultPort), }, Started: true, }) @@ -428,7 +429,7 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { ExposedPorts: []string{ nginxDefaultPort, }, - WaitingFor: wait.ForListeningPort(nginxDefaultPort), + WaitingFor: wait.ForHTTP("/").WithPort(nginxDefaultPort), }, Started: true, }) @@ -475,7 +476,7 @@ func TestContainerCreation(t *testing.T) { ExposedPorts: []string{ nginxDefaultPort, }, - WaitingFor: wait.ForListeningPort(nginxDefaultPort), + WaitingFor: wait.ForHTTP("/").WithPort(nginxDefaultPort), }, Started: true, }) @@ -529,7 +530,7 @@ func TestContainerCreationWithName(t *testing.T) { ExposedPorts: []string{ nginxDefaultPort, }, - WaitingFor: wait.ForListeningPort(nginxDefaultPort), + WaitingFor: wait.ForHTTP("/").WithPort(nginxDefaultPort), Name: creationName, Networks: []string{"bridge"}, }, @@ -592,7 +593,7 @@ func TestContainerCreationAndWaitForListeningPortLongEnough(t *testing.T) { ExposedPorts: []string{ nginxDefaultPort, }, - WaitingFor: wait.ForListeningPort(nginxDefaultPort), // default startupTimeout is 60s + WaitingFor: wait.ForHTTP("/").WithPort(nginxDefaultPort), // default startupTimeout is 60s }, Started: true, }) From c5ceb263bda49c9dfd67600c18457b91694de938 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 14 Aug 2024 11:03:44 +0100 Subject: [PATCH 033/126] docs: fix broken doc tags (#2732) A missing block start in vearch for runVearchContainer. Remove duplicate block end in exec test. --- modules/vearch/examples_test.go | 1 + wait/exec_test.go | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/vearch/examples_test.go b/modules/vearch/examples_test.go index 116484c583..d75bd8e66a 100644 --- a/modules/vearch/examples_test.go +++ b/modules/vearch/examples_test.go @@ -9,6 +9,7 @@ import ( ) func ExampleRun() { + // runVearchContainer { ctx := context.Background() vearchContainer, err := vearch.Run(ctx, "vearch/vearch:3.5.1") diff --git a/wait/exec_test.go b/wait/exec_test.go index f6723a317c..f81a3ffa01 100644 --- a/wait/exec_test.go +++ b/wait/exec_test.go @@ -209,5 +209,4 @@ func TestExecStrategyWaitUntilReady_CustomResponseMatcher(t *testing.T) { t.Fatalf("failed to terminate container: %s", err) } }) - // } } From 4545c292e7b8720e521988fd4e385f68d96a120b Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 14 Aug 2024 12:07:19 +0100 Subject: [PATCH 034/126] fix(kafka): port race on start (#2696) Fix the port race on start up by explicitly waiting for the port to be exposed. Once this is successful run the wait, this prevents the wait always being run due to way hooks are processed. --- modules/kafka/kafka.go | 63 +++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/modules/kafka/kafka.go b/modules/kafka/kafka.go index b2b0e831b5..c0c02890d4 100644 --- a/modules/kafka/kafka.go +++ b/modules/kafka/kafka.go @@ -71,31 +71,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom LifecycleHooks: []testcontainers.ContainerLifecycleHooks{ { PostStarts: []testcontainers.ContainerHook{ - // 1. copy the starter script into the container + // Use a single hook to copy the starter script and wait for + // the Kafka server to be ready. This prevents the wait running + // if the starter script fails to copy. func(ctx context.Context, c testcontainers.Container) error { - host, err := c.Host(ctx) - if err != nil { - return err + // 1. copy the starter script into the container + if err := copyStarterScript(ctx, c); err != nil { + return fmt.Errorf("copy starter script: %w", err) } - inspect, err := c.Inspect(ctx) - if err != nil { - return err - } - - hostname := inspect.Config.Hostname - - port, err := c.MappedPort(ctx, publicPort) - if err != nil { - return err - } - - scriptContent := fmt.Sprintf(starterScriptContent, host, port.Int(), hostname) - - return c.CopyToContainer(ctx, []byte(scriptContent), starterScript, 0o755) - }, - // 2. wait for the Kafka server to be ready - func(ctx context.Context, c testcontainers.Container) error { + // 2. wait for the Kafka server to be ready return wait.ForLog(".*Transitioning from RECOVERY to RUNNING.*").AsRegexp().WaitUntilReady(ctx, c) }, }, @@ -131,6 +116,40 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom return &KafkaContainer{Container: container, ClusterID: clusterID}, nil } +// copyStarterScript copies the starter script into the container. +func copyStarterScript(ctx context.Context, c testcontainers.Container) error { + if err := wait.ForListeningPort(publicPort). + SkipInternalCheck(). + WaitUntilReady(ctx, c); err != nil { + return fmt.Errorf("wait for exposed port: %w", err) + } + + host, err := c.Host(ctx) + if err != nil { + return fmt.Errorf("host: %w", err) + } + + inspect, err := c.Inspect(ctx) + if err != nil { + return fmt.Errorf("inspect: %w", err) + } + + hostname := inspect.Config.Hostname + + port, err := c.MappedPort(ctx, publicPort) + if err != nil { + return fmt.Errorf("mapped port: %w", err) + } + + scriptContent := fmt.Sprintf(starterScriptContent, host, port.Int(), hostname) + + if err := c.CopyToContainer(ctx, []byte(scriptContent), starterScript, 0o755); err != nil { + return fmt.Errorf("copy to container: %w", err) + } + + return nil +} + func WithClusterID(clusterID string) testcontainers.CustomizeRequestOption { return func(req *testcontainers.GenericContainerRequest) error { req.Env["CLUSTER_ID"] = clusterID From 9f4d46dcf7495ab0db0968ce6a567edf436ac6f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 14 Aug 2024 16:59:30 +0200 Subject: [PATCH 035/126] chore(deps): bump github.com/docker/docker from 27.1.0+incompatible to 27.1.1+incompatible (#2733) --- examples/nginx/go.mod | 2 +- examples/nginx/go.sum | 4 ++-- examples/toxiproxy/go.mod | 2 +- examples/toxiproxy/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- modules/artemis/go.mod | 2 +- modules/artemis/go.sum | 4 ++-- modules/azurite/go.mod | 2 +- modules/azurite/go.sum | 4 ++-- modules/cassandra/go.mod | 2 +- modules/cassandra/go.sum | 4 ++-- modules/chroma/go.mod | 2 +- modules/chroma/go.sum | 4 ++-- modules/clickhouse/go.mod | 2 +- modules/clickhouse/go.sum | 4 ++-- modules/cockroachdb/go.mod | 2 +- modules/cockroachdb/go.sum | 4 ++-- modules/compose/go.mod | 2 +- modules/compose/go.sum | 4 ++-- modules/consul/go.mod | 2 +- modules/consul/go.sum | 4 ++-- modules/couchbase/go.mod | 2 +- modules/couchbase/go.sum | 4 ++-- modules/dolt/go.mod | 2 +- modules/dolt/go.sum | 4 ++-- modules/elasticsearch/go.mod | 2 +- modules/elasticsearch/go.sum | 4 ++-- modules/gcloud/go.mod | 2 +- modules/gcloud/go.sum | 4 ++-- modules/grafana-lgtm/go.mod | 2 +- modules/grafana-lgtm/go.sum | 4 ++-- modules/inbucket/go.mod | 2 +- modules/inbucket/go.sum | 4 ++-- modules/influxdb/go.mod | 2 +- modules/influxdb/go.sum | 4 ++-- modules/k3s/go.mod | 2 +- modules/k3s/go.sum | 4 ++-- modules/k6/go.mod | 2 +- modules/k6/go.sum | 4 ++-- modules/kafka/go.mod | 2 +- modules/kafka/go.sum | 4 ++-- modules/localstack/go.mod | 2 +- modules/localstack/go.sum | 4 ++-- modules/mariadb/go.mod | 2 +- modules/mariadb/go.sum | 4 ++-- modules/milvus/go.mod | 2 +- modules/milvus/go.sum | 4 ++-- modules/minio/go.mod | 2 +- modules/minio/go.sum | 4 ++-- modules/mockserver/go.mod | 2 +- modules/mockserver/go.sum | 4 ++-- modules/mongodb/go.mod | 2 +- modules/mongodb/go.sum | 4 ++-- modules/mssql/go.mod | 2 +- modules/mssql/go.sum | 4 ++-- modules/mysql/go.mod | 2 +- modules/mysql/go.sum | 4 ++-- modules/nats/go.mod | 2 +- modules/nats/go.sum | 4 ++-- modules/neo4j/go.mod | 2 +- modules/neo4j/go.sum | 4 ++-- modules/ollama/go.mod | 2 +- modules/ollama/go.sum | 4 ++-- modules/openfga/go.mod | 2 +- modules/openfga/go.sum | 4 ++-- modules/openldap/go.mod | 2 +- modules/openldap/go.sum | 4 ++-- modules/opensearch/go.mod | 2 +- modules/opensearch/go.sum | 4 ++-- modules/postgres/go.mod | 2 +- modules/postgres/go.sum | 4 ++-- modules/pulsar/go.mod | 2 +- modules/pulsar/go.sum | 4 ++-- modules/qdrant/go.mod | 2 +- modules/qdrant/go.sum | 4 ++-- modules/rabbitmq/go.mod | 2 +- modules/rabbitmq/go.sum | 4 ++-- modules/redis/go.mod | 2 +- modules/redis/go.sum | 4 ++-- modules/redpanda/go.mod | 2 +- modules/redpanda/go.sum | 4 ++-- modules/registry/go.mod | 2 +- modules/registry/go.sum | 4 ++-- modules/surrealdb/go.mod | 2 +- modules/surrealdb/go.sum | 4 ++-- modules/valkey/go.mod | 2 +- modules/valkey/go.sum | 4 ++-- modules/vault/go.mod | 2 +- modules/vault/go.sum | 4 ++-- modules/vearch/go.mod | 2 +- modules/vearch/go.sum | 4 ++-- modules/weaviate/go.mod | 2 +- modules/weaviate/go.sum | 4 ++-- 94 files changed, 141 insertions(+), 141 deletions(-) diff --git a/examples/nginx/go.mod b/examples/nginx/go.mod index a9aea2bea1..4852b9d133 100644 --- a/examples/nginx/go.mod +++ b/examples/nginx/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/examples/nginx/go.sum b/examples/nginx/go.sum index 4de62e95bc..85338720c8 100644 --- a/examples/nginx/go.sum +++ b/examples/nginx/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/examples/toxiproxy/go.mod b/examples/toxiproxy/go.mod index 1b0f4663da..10f1c0c193 100644 --- a/examples/toxiproxy/go.mod +++ b/examples/toxiproxy/go.mod @@ -21,7 +21,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/examples/toxiproxy/go.sum b/examples/toxiproxy/go.sum index d659cb13a3..c62c0ac532 100644 --- a/examples/toxiproxy/go.sum +++ b/examples/toxiproxy/go.sum @@ -29,8 +29,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/go.mod b/go.mod index 2ed17ab739..fd6a023cb8 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 github.com/containerd/platforms v0.2.1 github.com/cpuguy83/dockercfg v0.3.1 - github.com/docker/docker v27.1.0+incompatible + github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/google/uuid v1.6.0 github.com/magiconair/properties v1.8.7 diff --git a/go.sum b/go.sum index 02f7ebe239..563862022b 100644 --- a/go.sum +++ b/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/artemis/go.mod b/modules/artemis/go.mod index e1fcc9958e..f89d49fe30 100644 --- a/modules/artemis/go.mod +++ b/modules/artemis/go.mod @@ -20,7 +20,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/artemis/go.sum b/modules/artemis/go.sum index 1db6255fae..69f6d52997 100644 --- a/modules/artemis/go.sum +++ b/modules/artemis/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/azurite/go.mod b/modules/azurite/go.mod index e18fad7050..209c4a066f 100644 --- a/modules/azurite/go.mod +++ b/modules/azurite/go.mod @@ -22,7 +22,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/azurite/go.sum b/modules/azurite/go.sum index 64bfb07809..90f8568088 100644 --- a/modules/azurite/go.sum +++ b/modules/azurite/go.sum @@ -41,8 +41,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/cassandra/go.mod b/modules/cassandra/go.mod index 28207451e7..ed211d6cd1 100644 --- a/modules/cassandra/go.mod +++ b/modules/cassandra/go.mod @@ -20,7 +20,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/cassandra/go.sum b/modules/cassandra/go.sum index f939709a99..775e48ecf5 100644 --- a/modules/cassandra/go.sum +++ b/modules/cassandra/go.sum @@ -27,8 +27,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/chroma/go.mod b/modules/chroma/go.mod index 4908b5b85b..2497b2687d 100644 --- a/modules/chroma/go.mod +++ b/modules/chroma/go.mod @@ -20,7 +20,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/chroma/go.sum b/modules/chroma/go.sum index 916290f592..e7d70f0539 100644 --- a/modules/chroma/go.sum +++ b/modules/chroma/go.sum @@ -28,8 +28,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/clickhouse/go.mod b/modules/clickhouse/go.mod index ea35c63b57..fcb4bb180e 100644 --- a/modules/clickhouse/go.mod +++ b/modules/clickhouse/go.mod @@ -22,7 +22,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-faster/city v1.0.1 // indirect diff --git a/modules/clickhouse/go.sum b/modules/clickhouse/go.sum index 8923b01965..2f09c4daae 100644 --- a/modules/clickhouse/go.sum +++ b/modules/clickhouse/go.sum @@ -29,8 +29,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/cockroachdb/go.mod b/modules/cockroachdb/go.mod index 561f247d29..9189455d27 100644 --- a/modules/cockroachdb/go.mod +++ b/modules/cockroachdb/go.mod @@ -26,7 +26,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/cockroachdb/go.sum b/modules/cockroachdb/go.sum index 7f47c1bc1c..c051f94433 100644 --- a/modules/cockroachdb/go.sum +++ b/modules/cockroachdb/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/compose/go.mod b/modules/compose/go.mod index 2e076ed60e..df034fb4b5 100644 --- a/modules/compose/go.mod +++ b/modules/compose/go.mod @@ -8,7 +8,7 @@ require ( github.com/compose-spec/compose-go/v2 v2.1.3 github.com/docker/cli v27.0.3+incompatible github.com/docker/compose/v2 v2.28.1 - github.com/docker/docker v27.1.0+incompatible + github.com/docker/docker v27.1.1+incompatible github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.32.0 diff --git a/modules/compose/go.sum b/modules/compose/go.sum index 8eec100162..c05580192e 100644 --- a/modules/compose/go.sum +++ b/modules/compose/go.sum @@ -135,8 +135,8 @@ github.com/docker/compose/v2 v2.28.1/go.mod h1:wDtGQFHe99sPLCHXeVbCkc+Wsl4Y/2Zxi github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= diff --git a/modules/consul/go.mod b/modules/consul/go.mod index abff142961..be56e58272 100644 --- a/modules/consul/go.mod +++ b/modules/consul/go.mod @@ -20,7 +20,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/fatih/color v1.14.1 // indirect diff --git a/modules/consul/go.sum b/modules/consul/go.sum index e497d639f3..d82d1cb435 100644 --- a/modules/consul/go.sum +++ b/modules/consul/go.sum @@ -42,8 +42,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/couchbase/go.mod b/modules/couchbase/go.mod index 03a0563970..7ceb5b8660 100644 --- a/modules/couchbase/go.mod +++ b/modules/couchbase/go.mod @@ -25,7 +25,7 @@ require ( github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20230515165046-68b522a21131 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/couchbase/go.sum b/modules/couchbase/go.sum index e1ce1bbbce..737e1e5236 100644 --- a/modules/couchbase/go.sum +++ b/modules/couchbase/go.sum @@ -42,8 +42,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/dolt/go.mod b/modules/dolt/go.mod index d259079a24..f85df4fdab 100644 --- a/modules/dolt/go.mod +++ b/modules/dolt/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/dolt/go.sum b/modules/dolt/go.sum index 5edb490b56..7784d0b833 100644 --- a/modules/dolt/go.sum +++ b/modules/dolt/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/elasticsearch/go.mod b/modules/elasticsearch/go.mod index 35f0f4af03..d062972128 100644 --- a/modules/elasticsearch/go.mod +++ b/modules/elasticsearch/go.mod @@ -20,7 +20,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/elastic/elastic-transport-go/v8 v8.4.0 // indirect diff --git a/modules/elasticsearch/go.sum b/modules/elasticsearch/go.sum index 5c238b73f5..59647a3793 100644 --- a/modules/elasticsearch/go.sum +++ b/modules/elasticsearch/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/gcloud/go.mod b/modules/gcloud/go.mod index 825dcfeed0..32088e2962 100644 --- a/modules/gcloud/go.mod +++ b/modules/gcloud/go.mod @@ -34,7 +34,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/envoyproxy/go-control-plane v0.12.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect diff --git a/modules/gcloud/go.sum b/modules/gcloud/go.sum index f1d231f03a..31d286e7d0 100644 --- a/modules/gcloud/go.sum +++ b/modules/gcloud/go.sum @@ -64,8 +64,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/grafana-lgtm/go.mod b/modules/grafana-lgtm/go.mod index 30f96bce2a..a1cba21836 100644 --- a/modules/grafana-lgtm/go.mod +++ b/modules/grafana-lgtm/go.mod @@ -32,7 +32,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect diff --git a/modules/grafana-lgtm/go.sum b/modules/grafana-lgtm/go.sum index 8a6e413e91..9eb14f31cb 100644 --- a/modules/grafana-lgtm/go.sum +++ b/modules/grafana-lgtm/go.sum @@ -27,8 +27,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/inbucket/go.mod b/modules/inbucket/go.mod index 89851c357e..68be24e81a 100644 --- a/modules/inbucket/go.mod +++ b/modules/inbucket/go.mod @@ -19,7 +19,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/inbucket/go.sum b/modules/inbucket/go.sum index 8236abef2f..2e403c06ad 100644 --- a/modules/inbucket/go.sum +++ b/modules/inbucket/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/influxdb/go.mod b/modules/influxdb/go.mod index a8c0be530a..abf0e25a9a 100644 --- a/modules/influxdb/go.mod +++ b/modules/influxdb/go.mod @@ -19,7 +19,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/influxdb/go.sum b/modules/influxdb/go.sum index 52e9ccd448..ad81df94f6 100644 --- a/modules/influxdb/go.sum +++ b/modules/influxdb/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/k3s/go.mod b/modules/k3s/go.mod index f92938778d..2c2fa952a0 100644 --- a/modules/k3s/go.mod +++ b/modules/k3s/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/k3s go 1.21 require ( - github.com/docker/docker v27.1.0+incompatible + github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/testcontainers/testcontainers-go v0.32.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/modules/k3s/go.sum b/modules/k3s/go.sum index 01ba28c4f0..e08a07dd42 100644 --- a/modules/k3s/go.sum +++ b/modules/k3s/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/k6/go.mod b/modules/k6/go.mod index 1c752f3db2..d9eda1b043 100644 --- a/modules/k6/go.mod +++ b/modules/k6/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/k6 go 1.21 require ( - github.com/docker/docker v27.1.0+incompatible + github.com/docker/docker v27.1.1+incompatible github.com/testcontainers/testcontainers-go v0.32.0 ) diff --git a/modules/k6/go.sum b/modules/k6/go.sum index 4de62e95bc..85338720c8 100644 --- a/modules/k6/go.sum +++ b/modules/k6/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/kafka/go.mod b/modules/kafka/go.mod index 6545097462..66d66e3663 100644 --- a/modules/kafka/go.mod +++ b/modules/kafka/go.mod @@ -20,7 +20,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/eapache/go-resiliency v1.4.0 // indirect github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect diff --git a/modules/kafka/go.sum b/modules/kafka/go.sum index 1c5d061e6f..778434567d 100644 --- a/modules/kafka/go.sum +++ b/modules/kafka/go.sum @@ -25,8 +25,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/localstack/go.mod b/modules/localstack/go.mod index b6324b8740..5394a23978 100644 --- a/modules/localstack/go.mod +++ b/modules/localstack/go.mod @@ -8,7 +8,7 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.27.5 github.com/aws/aws-sdk-go-v2/credentials v1.17.5 github.com/aws/aws-sdk-go-v2/service/s3 v1.51.2 - github.com/docker/docker v27.1.0+incompatible + github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.32.0 diff --git a/modules/localstack/go.sum b/modules/localstack/go.sum index c12b81d9f5..532bf9e05b 100644 --- a/modules/localstack/go.sum +++ b/modules/localstack/go.sum @@ -62,8 +62,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/mariadb/go.mod b/modules/mariadb/go.mod index 375e6a8171..5840823acf 100644 --- a/modules/mariadb/go.mod +++ b/modules/mariadb/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/mariadb/go.sum b/modules/mariadb/go.sum index 5edb490b56..7784d0b833 100644 --- a/modules/mariadb/go.sum +++ b/modules/mariadb/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/milvus/go.mod b/modules/milvus/go.mod index e6820f71f2..09b76b3c02 100644 --- a/modules/milvus/go.mod +++ b/modules/milvus/go.mod @@ -22,7 +22,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/milvus/go.sum b/modules/milvus/go.sum index a91219667c..cba09d80d3 100644 --- a/modules/milvus/go.sum +++ b/modules/milvus/go.sum @@ -52,8 +52,8 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/minio/go.mod b/modules/minio/go.mod index 275258590a..5b3d42070b 100644 --- a/modules/minio/go.mod +++ b/modules/minio/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect diff --git a/modules/minio/go.sum b/modules/minio/go.sum index 31363a9d8a..55013e4221 100644 --- a/modules/minio/go.sum +++ b/modules/minio/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/mockserver/go.mod b/modules/mockserver/go.mod index 694cb582ad..c956c7af92 100644 --- a/modules/mockserver/go.mod +++ b/modules/mockserver/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/mockserver/go.sum b/modules/mockserver/go.sum index 3356838f8b..e752fd0812 100644 --- a/modules/mockserver/go.sum +++ b/modules/mockserver/go.sum @@ -25,8 +25,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/mongodb/go.mod b/modules/mongodb/go.mod index 8ab7f9cbd8..626023da8d 100644 --- a/modules/mongodb/go.mod +++ b/modules/mongodb/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/mongodb/go.sum b/modules/mongodb/go.sum index 070b75e61f..0f2d5d5336 100644 --- a/modules/mongodb/go.sum +++ b/modules/mongodb/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/mssql/go.mod b/modules/mssql/go.mod index d2a0fa1c88..561ab41aed 100644 --- a/modules/mssql/go.mod +++ b/modules/mssql/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/mssql/go.sum b/modules/mssql/go.sum index 850c4d56cb..4160a61ee2 100644 --- a/modules/mssql/go.sum +++ b/modules/mssql/go.sum @@ -35,8 +35,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/mysql/go.mod b/modules/mysql/go.mod index 75bb50428e..420d1fa56e 100644 --- a/modules/mysql/go.mod +++ b/modules/mysql/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/mysql/go.sum b/modules/mysql/go.sum index 5edb490b56..7784d0b833 100644 --- a/modules/mysql/go.sum +++ b/modules/mysql/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/nats/go.mod b/modules/nats/go.mod index 1aad992b23..7de187bb61 100644 --- a/modules/nats/go.mod +++ b/modules/nats/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/nats/go.sum b/modules/nats/go.sum index 153b357491..11a786d5d4 100644 --- a/modules/nats/go.sum +++ b/modules/nats/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/neo4j/go.mod b/modules/neo4j/go.mod index c40ca91f0e..01cae82a7f 100644 --- a/modules/neo4j/go.mod +++ b/modules/neo4j/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/neo4j/go.sum b/modules/neo4j/go.sum index 65b9f7c873..2576f66232 100644 --- a/modules/neo4j/go.sum +++ b/modules/neo4j/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/ollama/go.mod b/modules/ollama/go.mod index 0e7193c540..73fd510df4 100644 --- a/modules/ollama/go.mod +++ b/modules/ollama/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/ollama go 1.21 require ( - github.com/docker/docker v27.1.0+incompatible + github.com/docker/docker v27.1.1+incompatible github.com/google/uuid v1.6.0 github.com/testcontainers/testcontainers-go v0.32.0 github.com/tmc/langchaingo v0.1.5 diff --git a/modules/ollama/go.sum b/modules/ollama/go.sum index 3b2564fd3b..07f9ef689f 100644 --- a/modules/ollama/go.sum +++ b/modules/ollama/go.sum @@ -25,8 +25,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.8.1 h1:6Lcdwya6GjPUNsBct8Lg/yRPwMhABj269AAzdGSiR+0= github.com/dlclark/regexp2 v1.8.1/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/openfga/go.mod b/modules/openfga/go.mod index 98be0b4cc3..d9ce4b4efd 100644 --- a/modules/openfga/go.mod +++ b/modules/openfga/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/openfga/go.sum b/modules/openfga/go.sum index e83875640f..a2fe09d6b4 100644 --- a/modules/openfga/go.sum +++ b/modules/openfga/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/openldap/go.mod b/modules/openldap/go.mod index 5f5daaf971..69ec47711c 100644 --- a/modules/openldap/go.mod +++ b/modules/openldap/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/openldap/go.sum b/modules/openldap/go.sum index 799277ab69..57de498077 100644 --- a/modules/openldap/go.sum +++ b/modules/openldap/go.sum @@ -27,8 +27,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/opensearch/go.mod b/modules/opensearch/go.mod index 310e35be63..c65559d3e1 100644 --- a/modules/opensearch/go.mod +++ b/modules/opensearch/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/opensearch go 1.21 require ( - github.com/docker/docker v27.1.0+incompatible + github.com/docker/docker v27.1.1+incompatible github.com/docker/go-units v0.5.0 github.com/testcontainers/testcontainers-go v0.32.0 ) diff --git a/modules/opensearch/go.sum b/modules/opensearch/go.sum index 4de62e95bc..85338720c8 100644 --- a/modules/opensearch/go.sum +++ b/modules/opensearch/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/postgres/go.mod b/modules/postgres/go.mod index 56e8ec9a17..83677326b7 100644 --- a/modules/postgres/go.mod +++ b/modules/postgres/go.mod @@ -22,7 +22,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/postgres/go.sum b/modules/postgres/go.sum index 292324c223..4293379353 100644 --- a/modules/postgres/go.sum +++ b/modules/postgres/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/pulsar/go.mod b/modules/pulsar/go.mod index 67796255bf..20fd5455bf 100644 --- a/modules/pulsar/go.mod +++ b/modules/pulsar/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/apache/pulsar-client-go v0.10.0 - github.com/docker/docker v27.1.0+incompatible + github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.32.0 diff --git a/modules/pulsar/go.sum b/modules/pulsar/go.sum index a38890a005..e8aa08578a 100644 --- a/modules/pulsar/go.sum +++ b/modules/pulsar/go.sum @@ -98,8 +98,8 @@ github.com/dimfeld/httptreemux v5.0.1+incompatible h1:Qj3gVcDNoOthBAqftuD596rm4w github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/qdrant/go.mod b/modules/qdrant/go.mod index 187209855e..d3fbac9f76 100644 --- a/modules/qdrant/go.mod +++ b/modules/qdrant/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/qdrant/go.sum b/modules/qdrant/go.sum index 2d9e4c62ca..c4425e8182 100644 --- a/modules/qdrant/go.sum +++ b/modules/qdrant/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/rabbitmq/go.mod b/modules/rabbitmq/go.mod index ba23d16112..c5b5784ccb 100644 --- a/modules/rabbitmq/go.mod +++ b/modules/rabbitmq/go.mod @@ -25,7 +25,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/rabbitmq/go.sum b/modules/rabbitmq/go.sum index 250c71bee6..f57610f497 100644 --- a/modules/rabbitmq/go.sum +++ b/modules/rabbitmq/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/redis/go.mod b/modules/redis/go.mod index 6f6c5eb625..0c655fe5c4 100644 --- a/modules/redis/go.mod +++ b/modules/redis/go.mod @@ -25,7 +25,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/redis/go.sum b/modules/redis/go.sum index 786b36ccd8..1698de2ecf 100644 --- a/modules/redis/go.sum +++ b/modules/redis/go.sum @@ -28,8 +28,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/redpanda/go.mod b/modules/redpanda/go.mod index 732f26140f..deb901ccaa 100644 --- a/modules/redpanda/go.mod +++ b/modules/redpanda/go.mod @@ -28,7 +28,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/modules/redpanda/go.sum b/modules/redpanda/go.sum index e993beb0b6..cf26162896 100644 --- a/modules/redpanda/go.sum +++ b/modules/redpanda/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/registry/go.mod b/modules/registry/go.mod index 47e546cd22..90513dc043 100644 --- a/modules/registry/go.mod +++ b/modules/registry/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/registry go 1.21 require ( - github.com/docker/docker v27.1.0+incompatible + github.com/docker/docker v27.1.1+incompatible github.com/testcontainers/testcontainers-go v0.32.0 ) diff --git a/modules/registry/go.sum b/modules/registry/go.sum index 4de62e95bc..85338720c8 100644 --- a/modules/registry/go.sum +++ b/modules/registry/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/surrealdb/go.mod b/modules/surrealdb/go.mod index dca93f7a97..8411ee4e79 100644 --- a/modules/surrealdb/go.mod +++ b/modules/surrealdb/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/surrealdb/go.sum b/modules/surrealdb/go.sum index 0b708c46c3..4a82bd3217 100644 --- a/modules/surrealdb/go.sum +++ b/modules/surrealdb/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/valkey/go.mod b/modules/valkey/go.mod index a92530c576..6d394c5c16 100644 --- a/modules/valkey/go.mod +++ b/modules/valkey/go.mod @@ -22,7 +22,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/valkey/go.sum b/modules/valkey/go.sum index 18eacee2e9..f92f0dbcc7 100644 --- a/modules/valkey/go.sum +++ b/modules/valkey/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/vault/go.mod b/modules/vault/go.mod index f3086a358b..6e04cb687e 100644 --- a/modules/vault/go.mod +++ b/modules/vault/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/vault go 1.21 require ( - github.com/docker/docker v27.1.0+incompatible + github.com/docker/docker v27.1.1+incompatible github.com/hashicorp/vault-client-go v0.4.3 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.32.0 diff --git a/modules/vault/go.sum b/modules/vault/go.sum index 4cf0f339d1..5bed30736e 100644 --- a/modules/vault/go.sum +++ b/modules/vault/go.sum @@ -24,8 +24,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/vearch/go.mod b/modules/vearch/go.mod index 2d385f6648..026ba37349 100644 --- a/modules/vearch/go.mod +++ b/modules/vearch/go.mod @@ -14,7 +14,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/vearch/go.sum b/modules/vearch/go.sum index 4de62e95bc..85338720c8 100644 --- a/modules/vearch/go.sum +++ b/modules/vearch/go.sum @@ -23,8 +23,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= diff --git a/modules/weaviate/go.mod b/modules/weaviate/go.mod index 9cd6cafa72..83e386cdfe 100644 --- a/modules/weaviate/go.mod +++ b/modules/weaviate/go.mod @@ -21,7 +21,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/docker v27.1.0+incompatible // indirect + github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect diff --git a/modules/weaviate/go.sum b/modules/weaviate/go.sum index b65325ee65..4d55fd59af 100644 --- a/modules/weaviate/go.sum +++ b/modules/weaviate/go.sum @@ -32,8 +32,8 @@ 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= From c3b05edcf3e755d3bf1968a42d0542d52ce93818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 14 Aug 2024 17:15:02 +0200 Subject: [PATCH 036/126] chore: run make tests in verbose mode (#2734) --- commons-test.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/commons-test.mk b/commons-test.mk index a4553c6f9c..04d0a6e70c 100644 --- a/commons-test.mk +++ b/commons-test.mk @@ -37,6 +37,7 @@ test-%: $(GOBIN)/gotestsum --packages="./..." \ --junitfile TEST-unit.xml \ -- \ + -v \ -coverprofile=coverage.out \ -timeout=30m From c8ec4559ba79b9ca1eba7d2798f55bc86dcf697c Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 16 Aug 2024 06:40:33 +0100 Subject: [PATCH 037/126] chore: improve error wrapping (#2720) Improve error wrapping to help detect failures in compose and wait tests. --- docker.go | 12 ++++++------ generic.go | 4 ++-- modules/compose/compose.go | 6 +++--- modules/compose/compose_api.go | 20 ++++++++++---------- modules/compose/compose_local.go | 25 +++++++++++++------------ 5 files changed, 34 insertions(+), 33 deletions(-) diff --git a/docker.go b/docker.go index 6bd80c39c4..5650f88612 100644 --- a/docker.go +++ b/docker.go @@ -508,12 +508,12 @@ func (c *DockerContainer) Exec(ctx context.Context, cmd []string, options ...tce response, err := cli.ContainerExecCreate(ctx, c.ID, processOptions.ExecConfig) if err != nil { - return 0, nil, err + return 0, nil, fmt.Errorf("container exec create: %w", err) } hijack, err := cli.ContainerExecAttach(ctx, response.ID, container.ExecAttachOptions{}) if err != nil { - return 0, nil, err + return 0, nil, fmt.Errorf("container exec attach: %w", err) } processOptions.Reader = hijack.Reader @@ -528,7 +528,7 @@ func (c *DockerContainer) Exec(ctx context.Context, cmd []string, options ...tce for { execResp, err := cli.ContainerExecInspect(ctx, response.ID) if err != nil { - return 0, nil, err + return 0, nil, fmt.Errorf("container exec inspect: %w", err) } if !execResp.Running { @@ -1129,7 +1129,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque resp, err := p.client.ContainerCreate(ctx, dockerInput, hostConfig, networkingConfig, platform, req.Name) if err != nil { - return nil, err + return nil, fmt.Errorf("container create: %w", err) } // #248: If there is more than one network specified in the request attach newly created container to them one by one @@ -1144,7 +1144,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque } err = p.client.NetworkConnect(ctx, nw.ID, resp.ID, &endpointSetting) if err != nil { - return nil, err + return nil, fmt.Errorf("network connect: %w", err) } } } @@ -1245,7 +1245,7 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain if !p.config.RyukDisabled { r, err := reuseOrCreateReaper(context.WithValue(ctx, core.DockerHostContextKey, p.host), sessionID, p) if err != nil { - return nil, fmt.Errorf("%w: creating reaper failed", err) + return nil, fmt.Errorf("reaper: %w", err) } termSignal, err = r.Connect() if err != nil { diff --git a/generic.go b/generic.go index f0cda13407..4c214744e7 100644 --- a/generic.go +++ b/generic.go @@ -57,7 +57,7 @@ func GenericContainer(ctx context.Context, req GenericContainerRequest) (Contain } provider, err := req.ProviderType.GetProvider(WithLogger(logging)) if err != nil { - return nil, err + return nil, fmt.Errorf("get provider: %w", err) } defer provider.Close() @@ -79,7 +79,7 @@ func GenericContainer(ctx context.Context, req GenericContainerRequest) (Contain if req.Started && !c.IsRunning() { if err := c.Start(ctx); err != nil { - return c, fmt.Errorf("failed to start container: %w", err) + return c, fmt.Errorf("start container: %w", err) } } return c, nil diff --git a/modules/compose/compose.go b/modules/compose/compose.go index 38adfafd2f..b0f26370cb 100644 --- a/modules/compose/compose.go +++ b/modules/compose/compose.go @@ -129,7 +129,7 @@ func NewDockerComposeWith(opts ...ComposeStackOption) (*dockerCompose, error) { for i := range opts { if err := opts[i].applyToComposeStack(&composeOptions); err != nil { - return nil, err + return nil, fmt.Errorf("apply compose stack option: %w", err) } } @@ -139,11 +139,11 @@ func NewDockerComposeWith(opts ...ComposeStackOption) (*dockerCompose, error) { dockerCli, err := command.NewDockerCli() if err != nil { - return nil, err + return nil, fmt.Errorf("new docker client: %w", err) } if err = dockerCli.Initialize(flags.NewClientOptions(), command.WithInitializeClient(makeClient)); err != nil { - return nil, err + return nil, fmt.Errorf("initialize docker client: %w", err) } reaperProvider, err := testcontainers.NewDockerProvider() diff --git a/modules/compose/compose_api.go b/modules/compose/compose_api.go index 426715f0d5..129f55897e 100644 --- a/modules/compose/compose_api.go +++ b/modules/compose/compose_api.go @@ -120,19 +120,19 @@ func (r ComposeStackReaders) applyToComposeStack(o *composeStackOptions) error { tmp = filepath.Join(tmp, strconv.FormatInt(time.Now().UnixNano(), 10)) err := os.MkdirAll(tmp, 0o755) if err != nil { - return fmt.Errorf("failed to create temporary directory: %w", err) + return fmt.Errorf("create temporary directory: %w", err) } name := fmt.Sprintf(baseName, i) bs, err := io.ReadAll(reader) if err != nil { - return fmt.Errorf("failed to read from reader: %w", err) + return fmt.Errorf("read from reader: %w", err) } err = os.WriteFile(filepath.Join(tmp, name), bs, 0o644) if err != nil { - return fmt.Errorf("failed to write to temporary file: %w", err) + return fmt.Errorf("write to temporary file: %w", err) } f[i] = filepath.Join(tmp, name) @@ -311,7 +311,7 @@ func (d *dockerCompose) Up(ctx context.Context, opts ...StackUpOption) error { }, }) if err != nil { - return err + return fmt.Errorf("compose up: %w", err) } err = d.lookupNetworks(ctx) @@ -442,7 +442,7 @@ func (d *dockerCompose) lookupContainer(ctx context.Context, svcName string) (*t ), }) if err != nil { - return nil, err + return nil, fmt.Errorf("container list: %w", err) } if len(containers) == 0 { @@ -458,7 +458,7 @@ func (d *dockerCompose) lookupContainer(ctx context.Context, svcName string) (*t dockerProvider, err := testcontainers.NewDockerProvider(testcontainers.WithLogger(d.logger)) if err != nil { - return nil, err + return nil, fmt.Errorf("new docker provider: %w", err) } dockerProvider.SetClient(d.dockerClient) @@ -479,7 +479,7 @@ func (d *dockerCompose) lookupNetworks(ctx context.Context) error { ), }) if err != nil { - return err + return fmt.Errorf("network list: %w", err) } for _, n := range networks { @@ -504,12 +504,12 @@ func (d *dockerCompose) compileProject(ctx context.Context) (*types.Project, err compiledOptions, err := cli.NewProjectOptions(d.configs, projectOptions...) if err != nil { - return nil, err + return nil, fmt.Errorf("new project options: %w", err) } proj, err := compiledOptions.LoadProject(ctx) if err != nil { - return nil, err + return nil, fmt.Errorf("load project: %w", err) } for i, s := range proj.Services { @@ -568,7 +568,7 @@ func withEnv(env map[string]string) func(*cli.ProjectOptions) error { func makeClient(*command.DockerCli) (client.APIClient, error) { dockerClient, err := testcontainers.NewDockerClientWithOpts(context.Background()) if err != nil { - return nil, err + return nil, fmt.Errorf("new docker client: %w", err) } return dockerClient, nil } diff --git a/modules/compose/compose_local.go b/modules/compose/compose_local.go index cb818dbc94..964547bae7 100644 --- a/modules/compose/compose_local.go +++ b/modules/compose/compose_local.go @@ -136,7 +136,7 @@ func (dc *LocalDockerCompose) containerNameFromServiceName(service, separator st func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { cli, err := testcontainers.NewDockerClientWithOpts(context.Background()) if err != nil { - return err + return fmt.Errorf("new docker client: %w", err) } defer cli.Close() @@ -150,22 +150,22 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { containerListOptions := container.ListOptions{Filters: f, All: true} containers, err := cli.ContainerList(context.Background(), containerListOptions) if err != nil { - return fmt.Errorf("error %w occurred while filtering the service %s: %d by name and published port", err, k.service, k.publishedPort) + return fmt.Errorf("container list service %q: %w", k.service, err) } if len(containers) == 0 { - return fmt.Errorf("service with name %s not found in list of running containers", k.service) + return fmt.Errorf("service with name %q 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.service, l) + return fmt.Errorf("expecting only one running container for %q but got %d", k.service, l) } container := containers[0] strategy := dc.WaitStrategyMap[k] dockerProvider, err := testcontainers.NewDockerProvider(testcontainers.WithLogger(dc.Logger)) if err != nil { - return fmt.Errorf("unable to create new Docker Provider: %w", err) + return fmt.Errorf("new docker provider: %w", err) } defer dockerProvider.Close() @@ -175,7 +175,7 @@ func (dc *LocalDockerCompose) applyStrategyToRunningContainer() error { 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) + return fmt.Errorf("wait until ready %v to service %q due: %w", strategy, k.service, err) } } return nil @@ -223,7 +223,6 @@ func (dc *LocalDockerCompose) WithExposedService(service string, port int, strat // 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 } @@ -235,7 +234,7 @@ func (dc *LocalDockerCompose) determineVersion() error { majorVersion, err := strconv.ParseInt(string(components[0]), 10, 8) if err != nil { - return err + return fmt.Errorf("parsing major version: %w", err) } switch majorVersion { @@ -263,11 +262,11 @@ func (dc *LocalDockerCompose) validate() error { yamlFile, err := os.ReadFile(abs) if err != nil { - return err + return fmt.Errorf("read compose file %q: %w", abs, err) } err = yaml.Unmarshal(yamlFile, &c) if err != nil { - return err + return fmt.Errorf("unmarshalling file %q: %w", abs, err) } if dc.Services == nil { @@ -448,7 +447,9 @@ func (w *capturingPassThroughWriter) Bytes() []byte { // Which checks if a binary is present in PATH func which(binary string) error { - _, err := exec.LookPath(binary) + if _, err := exec.LookPath(binary); err != nil { + return fmt.Errorf("lookup: %w", err) + } - return err + return nil } From 5024e266f5e30a9c27e288d2deda5f75c8137dcd Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 16 Aug 2024 07:27:06 +0100 Subject: [PATCH 038/126] fix!: docker authentication setup (#2727) Check and return errors in the process of determining authentication configs so that unexpected failures don't occur latter in the process of build an image or creating a container. BuildOptions will now return an empty result on error instead of an incomplete one, to ensure that consumers don't use partial data. Fix builds with different config or override environments failing when the authentication configuration changes, which was introduced by #2646. Report errors from GetRegistryCredentials calls to avoid unexpected failures latter on in the authentication process. Split out the functionality to read a Dockerfile from an io.Reader into ExtractImagesFromReader, as required when processing from a tar archive. Deprecated function ContainerRequest.GetAuthConfigs will now panic if an error occurs, so that callers understand that an failure occurred. Remove unused parameter t from prepareRedisImage. BREAKING CHANGE Add support for determining the required authentication in when building an image from a ContextArchive, this requires ContextArchive support io.Seeker. --- container.go | 90 +++++++++++++++++++---- container_test.go | 15 ++-- docker.go | 6 +- docker_auth.go | 155 +++++++++++++++++++++++++++++++++------- docker_auth_test.go | 39 ++++++++-- internal/core/images.go | 12 +++- 6 files changed, 262 insertions(+), 55 deletions(-) diff --git a/container.go b/container.go index 6f17a7e3ff..8747335a28 100644 --- a/container.go +++ b/container.go @@ -1,6 +1,7 @@ package testcontainers import ( + "archive/tar" "context" "errors" "fmt" @@ -10,6 +11,7 @@ import ( "strings" "time" + "github.com/cpuguy83/dockercfg" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" @@ -85,7 +87,7 @@ type ImageBuildInfo interface { // rather than using a pre-built one type FromDockerfile struct { Context string // the path to the context of the docker build - ContextArchive io.Reader // the tar archive file to send to docker that contains the build context + ContextArchive io.ReadSeeker // 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" Repo string // the repo label for image, defaults to UUID Tag string // the tag label for image, defaults to UUID @@ -305,30 +307,90 @@ func (c *ContainerRequest) GetTag() string { return strings.ToLower(t) } -// Deprecated: Testcontainers will detect registry credentials automatically, and it will be removed in the next major release -// GetAuthConfigs returns the auth configs to be able to pull from an authenticated docker registry +// Deprecated: Testcontainers will detect registry credentials automatically, and it will be removed in the next major release. +// GetAuthConfigs returns the auth configs to be able to pull from an authenticated docker registry. +// Panics if an error occurs. func (c *ContainerRequest) GetAuthConfigs() map[string]registry.AuthConfig { - return getAuthConfigsFromDockerfile(c) + auth, err := getAuthConfigsFromDockerfile(c) + if err != nil { + panic(fmt.Sprintf("failed to get auth configs from Dockerfile: %v", err)) + } + return auth +} + +// dockerFileImages returns the images from the request Dockerfile. +func (c *ContainerRequest) dockerFileImages() ([]string, error) { + if c.ContextArchive == nil { + // Source is a directory, we can read the Dockerfile directly. + images, err := core.ExtractImagesFromDockerfile(filepath.Join(c.Context, c.GetDockerfile()), c.GetBuildArgs()) + if err != nil { + return nil, fmt.Errorf("extract images from Dockerfile: %w", err) + } + + return images, nil + } + + // Source is an archive, we need to read it to get the Dockerfile. + dockerFile := c.GetDockerfile() + tr := tar.NewReader(c.FromDockerfile.ContextArchive) + + for { + hdr, err := tr.Next() + if err != nil { + if errors.Is(err, io.EOF) { + return nil, fmt.Errorf("Dockerfile %q not found in context archive", dockerFile) + } + + return nil, fmt.Errorf("reading tar archive: %w", err) + } + + if hdr.Name != dockerFile { + continue + } + + images, err := core.ExtractImagesFromReader(tr, c.GetBuildArgs()) + if err != nil { + return nil, fmt.Errorf("extract images from Dockerfile: %w", err) + } + + // Reset the archive to the beginning. + if _, err := c.ContextArchive.Seek(0, io.SeekStart); err != nil { + return nil, fmt.Errorf("seek context archive to start: %w", err) + } + + return images, nil + } } // getAuthConfigsFromDockerfile returns the auth configs to be able to pull from an authenticated docker registry -func getAuthConfigsFromDockerfile(c *ContainerRequest) map[string]registry.AuthConfig { - images, err := core.ExtractImagesFromDockerfile(filepath.Join(c.Context, c.GetDockerfile()), c.GetBuildArgs()) +func getAuthConfigsFromDockerfile(c *ContainerRequest) (map[string]registry.AuthConfig, error) { + images, err := c.dockerFileImages() if err != nil { - return map[string]registry.AuthConfig{} + return nil, fmt.Errorf("docker file images: %w", err) + } + + // Get the auth configs once for all images as it can be a time-consuming operation. + configs, err := getDockerAuthConfigs() + if err != nil { + return nil, err } authConfigs := map[string]registry.AuthConfig{} for _, image := range images { - registry, authConfig, err := DockerImageAuth(context.Background(), image) + registry, authConfig, err := dockerImageAuth(context.Background(), image, configs) if err != nil { + if !errors.Is(err, dockercfg.ErrCredentialsNotFound) { + return nil, fmt.Errorf("docker image auth %q: %w", image, err) + } + + // Credentials not found no config to add. continue } authConfigs[registry] = authConfig } - return authConfigs + return authConfigs, nil } func (c *ContainerRequest) ShouldBuildImage() bool { @@ -361,7 +423,10 @@ func (c *ContainerRequest) BuildOptions() (types.ImageBuildOptions, error) { buildOptions.Dockerfile = c.GetDockerfile() // Make sure the auth configs from the Dockerfile are set right after the user-defined build options. - authsFromDockerfile := getAuthConfigsFromDockerfile(c) + authsFromDockerfile, err := getAuthConfigsFromDockerfile(c) + if err != nil { + return types.ImageBuildOptions{}, fmt.Errorf("auth configs from Dockerfile: %w", err) + } if buildOptions.AuthConfigs == nil { buildOptions.AuthConfigs = map[string]registry.AuthConfig{} @@ -378,7 +443,7 @@ func (c *ContainerRequest) BuildOptions() (types.ImageBuildOptions, error) { for _, is := range c.ImageSubstitutors { modifiedTag, err := is.Substitute(tag) if err != nil { - return buildOptions, fmt.Errorf("failed to substitute image %s with %s: %w", tag, is.Description(), err) + return types.ImageBuildOptions{}, fmt.Errorf("failed to substitute image %s with %s: %w", tag, is.Description(), err) } if modifiedTag != tag { @@ -401,8 +466,9 @@ func (c *ContainerRequest) BuildOptions() (types.ImageBuildOptions, error) { // Do this as late as possible to ensure we don't leak the context on error/panic. buildContext, err := c.GetContext() if err != nil { - return buildOptions, err + return types.ImageBuildOptions{}, err } + buildOptions.Context = buildContext return buildOptions, nil diff --git a/container_test.go b/container_test.go index d2a070f2de..3cb14ac296 100644 --- a/container_test.go +++ b/container_test.go @@ -147,7 +147,7 @@ func Test_BuildImageWithContexts(t *testing.T) { type TestCase struct { Name string ContextPath string - ContextArchive func() (io.Reader, error) + ContextArchive func() (io.ReadSeeker, error) ExpectedEchoOutput string Dockerfile string ExpectedError string @@ -157,7 +157,7 @@ func Test_BuildImageWithContexts(t *testing.T) { { Name: "test build from context archive", // fromDockerfileWithContextArchive { - ContextArchive: func() (io.Reader, error) { + ContextArchive: func() (io.ReadSeeker, error) { var buf bytes.Buffer tarWriter := tar.NewWriter(&buf) files := []struct { @@ -202,7 +202,7 @@ func Test_BuildImageWithContexts(t *testing.T) { }, { Name: "test build from context archive and be able to use files in it", - ContextArchive: func() (io.Reader, error) { + ContextArchive: func() (io.ReadSeeker, error) { var buf bytes.Buffer tarWriter := tar.NewWriter(&buf) files := []struct { @@ -255,14 +255,14 @@ func Test_BuildImageWithContexts(t *testing.T) { ContextPath: "./testdata", Dockerfile: "echo.Dockerfile", ExpectedEchoOutput: "this is from the echo test Dockerfile", - ContextArchive: func() (io.Reader, error) { + ContextArchive: func() (io.ReadSeeker, error) { return nil, nil }, }, { Name: "it should error if neither a context nor a context archive are specified", ContextPath: "", - ContextArchive: func() (io.Reader, error) { + ContextArchive: func() (io.ReadSeeker, error) { return nil, nil }, ExpectedError: "create container: you must specify either a build context or an image", @@ -275,9 +275,8 @@ func Test_BuildImageWithContexts(t *testing.T) { t.Parallel() ctx := context.Background() a, err := testCase.ContextArchive() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + req := testcontainers.ContainerRequest{ FromDockerfile: testcontainers.FromDockerfile{ ContextArchive: a, diff --git a/docker.go b/docker.go index 5650f88612..5f6c415627 100644 --- a/docker.go +++ b/docker.go @@ -1114,7 +1114,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque // forward the host ports to the container ports. sshdForwardPortsHook, err := exposeHostPorts(ctx, &req, req.HostAccessPorts...) if err != nil { - return nil, fmt.Errorf("failed to expose host ports: %w", err) + return nil, fmt.Errorf("expose host ports: %w", err) } defaultHooks = append(defaultHooks, sshdForwardPortsHook) @@ -1292,12 +1292,12 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain func (p *DockerProvider) attemptToPullImage(ctx context.Context, tag string, pullOpt image.PullOptions) error { registry, imageAuth, err := DockerImageAuth(ctx, tag) if err != nil { - p.Logger.Printf("Failed to get image auth for %s. Setting empty credentials for the image: %s. Error is:%s", registry, tag, err) + p.Logger.Printf("Failed to get image auth for %s. Setting empty credentials for the image: %s. Error is: %s", registry, tag, err) } else { // see https://github.com/docker/docs/blob/e8e1204f914767128814dca0ea008644709c117f/engine/api/sdk/examples.md?plain=1#L649-L657 encodedJSON, err := json.Marshal(imageAuth) if err != nil { - p.Logger.Printf("Failed to marshal image auth. Setting empty credentials for the image: %s. Error is:%s", tag, err) + p.Logger.Printf("Failed to marshal image auth. Setting empty credentials for the image: %s. Error is: %s", tag, err) } else { pullOpt.RegistryAuth = base64.URLEncoding.EncodeToString(encodedJSON) } diff --git a/docker_auth.go b/docker_auth.go index d45393f325..99e2d2fdba 100644 --- a/docker_auth.go +++ b/docker_auth.go @@ -2,8 +2,13 @@ package testcontainers import ( "context" + "crypto/md5" "encoding/base64" + "encoding/hex" "encoding/json" + "errors" + "fmt" + "io" "net/url" "os" "sync" @@ -21,15 +26,21 @@ var defaultRegistryFn = defaultRegistry // Finally, it will use the credential helpers to extract the information from the docker config file // for that registry, if it exists. func DockerImageAuth(ctx context.Context, image string) (string, registry.AuthConfig, error) { - defaultRegistry := defaultRegistryFn(ctx) - reg := core.ExtractRegistry(image, defaultRegistry) - - cfgs, err := getDockerAuthConfigs() + configs, err := getDockerAuthConfigs() if err != nil { + reg := core.ExtractRegistry(image, defaultRegistryFn(ctx)) return reg, registry.AuthConfig{}, err } - if cfg, ok := getRegistryAuth(reg, cfgs); ok { + return dockerImageAuth(ctx, image, configs) +} + +// dockerImageAuth returns the auth config for the given Docker image. +func dockerImageAuth(ctx context.Context, image string, configs map[string]registry.AuthConfig) (string, registry.AuthConfig, error) { + defaultRegistry := defaultRegistryFn(ctx) + reg := core.ExtractRegistry(image, defaultRegistry) + + if cfg, ok := getRegistryAuth(reg, configs); ok { return reg, cfg, nil } @@ -80,24 +91,93 @@ func defaultRegistry(ctx context.Context) string { return info.IndexServerAddress } -// authConfig represents the details of the auth config for a registry. -type authConfig struct { +// authConfigResult is a result looking up auth details for key. +type authConfigResult struct { key string cfg registry.AuthConfig + err error +} + +// credentialsCache is a cache for registry credentials. +type credentialsCache struct { + entries map[string]credentials + mtx sync.RWMutex +} + +// credentials represents the username and password for a registry. +type credentials struct { + username string + password string +} + +var creds = &credentialsCache{entries: map[string]credentials{}} + +// Get returns the username and password for the given hostname +// as determined by the details in configPath. +func (c *credentialsCache) Get(hostname, configKey string) (string, string, error) { + key := configKey + ":" + hostname + c.mtx.RLock() + entry, ok := c.entries[key] + c.mtx.RUnlock() + + if ok { + return entry.username, entry.password, nil + } + + // No entry found, request and cache. + user, password, err := dockercfg.GetRegistryCredentials(hostname) + if err != nil { + return "", "", fmt.Errorf("getting credentials for %s: %w", hostname, err) + } + + c.mtx.Lock() + c.entries[key] = credentials{username: user, password: password} + c.mtx.Unlock() + + return user, password, nil +} + +// configFileKey returns a key to use for caching credentials based on +// the contents of the currently active config. +func configFileKey() (string, error) { + configPath, err := dockercfg.ConfigPath() + if err != nil { + return "", err + } + + f, err := os.Open(configPath) + if err != nil { + return "", fmt.Errorf("open config file: %w", err) + } + + defer f.Close() + + h := md5.New() + if _, err := io.Copy(h, f); err != nil { + return "", fmt.Errorf("copying config file: %w", err) + } + + return hex.EncodeToString(h.Sum(nil)), nil } // getDockerAuthConfigs returns a map with the auth configs from the docker config file // using the registry as the key -var getDockerAuthConfigs = sync.OnceValues(func() (map[string]registry.AuthConfig, error) { +func getDockerAuthConfigs() (map[string]registry.AuthConfig, error) { cfg, err := getDockerConfig() if err != nil { return nil, err } - cfgs := map[string]registry.AuthConfig{} - results := make(chan authConfig, len(cfg.AuthConfigs)+len(cfg.CredentialHelpers)) + configKey, err := configFileKey() + if err != nil { + return nil, err + } + + size := len(cfg.AuthConfigs) + len(cfg.CredentialHelpers) + cfgs := make(map[string]registry.AuthConfig, size) + results := make(chan authConfigResult, size) var wg sync.WaitGroup - wg.Add(len(cfg.AuthConfigs) + len(cfg.CredentialHelpers)) + wg.Add(size) for k, v := range cfg.AuthConfigs { go func(k string, v dockercfg.AuthConfig) { defer wg.Done() @@ -112,16 +192,23 @@ var getDockerAuthConfigs = sync.OnceValues(func() (map[string]registry.AuthConfi Username: v.Username, } - if v.Username == "" && v.Password == "" { - u, p, _ := dockercfg.GetRegistryCredentials(k) + switch { + case ac.Username == "" && ac.Password == "": + // Look up credentials from the credential store. + u, p, err := creds.Get(k, configKey) + if err != nil { + results <- authConfigResult{err: err} + return + } + ac.Username = u ac.Password = p - } - - if v.Auth == "" { + case ac.Auth == "": + // Create auth from the username and password encoding. ac.Auth = base64.StdEncoding.EncodeToString([]byte(ac.Username + ":" + ac.Password)) } - results <- authConfig{key: k, cfg: ac} + + results <- authConfigResult{key: k, cfg: ac} }(k, v) } @@ -131,11 +218,19 @@ var getDockerAuthConfigs = sync.OnceValues(func() (map[string]registry.AuthConfi go func(k string) { defer wg.Done() - ac := registry.AuthConfig{} - u, p, _ := dockercfg.GetRegistryCredentials(k) - ac.Username = u - ac.Password = p - results <- authConfig{key: k, cfg: ac} + u, p, err := creds.Get(k, configKey) + if err != nil { + results <- authConfigResult{err: err} + return + } + + results <- authConfigResult{ + key: k, + cfg: registry.AuthConfig{ + Username: u, + Password: p, + }, + } }(k) } @@ -144,12 +239,22 @@ var getDockerAuthConfigs = sync.OnceValues(func() (map[string]registry.AuthConfi close(results) }() - for ac := range results { - cfgs[ac.key] = ac.cfg + var errs []error + for result := range results { + if result.err != nil { + errs = append(errs, result.err) + continue + } + + cfgs[result.key] = result.cfg + } + + if len(errs) > 0 { + return nil, errors.Join(errs...) } return cfgs, nil -}) +} // getDockerConfig returns the docker config file. It will internally check, in this particular order: // 1. the DOCKER_AUTH_CONFIG environment variable, unmarshalling it into a dockercfg.Config diff --git a/docker_auth_test.go b/docker_auth_test.go index 1f8df17c09..5b3e1e1067 100644 --- a/docker_auth_test.go +++ b/docker_auth_test.go @@ -2,6 +2,7 @@ package testcontainers import ( "context" + _ "embed" "fmt" "os" "path/filepath" @@ -9,6 +10,7 @@ import ( "github.com/cpuguy83/dockercfg" "github.com/docker/docker/api/types/image" + "github.com/docker/docker/api/types/registry" "github.com/docker/docker/client" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -198,7 +200,7 @@ func TestBuildContainerFromDockerfile(t *testing.T) { WaitingFor: wait.ForLog("Ready to accept connections"), } - redisC, err := prepareRedisImage(ctx, req, t) + redisC, err := prepareRedisImage(ctx, req) require.NoError(t, err) terminateContainerOnEnd(t, ctx, redisC) } @@ -249,7 +251,7 @@ func TestBuildContainerFromDockerfileWithDockerAuthConfig(t *testing.T) { WaitingFor: wait.ForLog("Ready to accept connections"), } - redisC, err := prepareRedisImage(ctx, req, t) + redisC, err := prepareRedisImage(ctx, req) require.NoError(t, err) terminateContainerOnEnd(t, ctx, redisC) } @@ -281,7 +283,7 @@ func TestBuildContainerFromDockerfileShouldFailWithWrongDockerAuthConfig(t *test WaitingFor: wait.ForLog("Ready to accept connections"), } - redisC, err := prepareRedisImage(ctx, req, t) + redisC, err := prepareRedisImage(ctx, req) require.Error(t, err) terminateContainerOnEnd(t, ctx, redisC) } @@ -369,7 +371,7 @@ func prepareLocalRegistryWithAuth(t *testing.T) string { return mp } -func prepareRedisImage(ctx context.Context, req ContainerRequest, t *testing.T) (Container, error) { +func prepareRedisImage(ctx context.Context, req ContainerRequest) (Container, error) { genContainerReq := GenericContainerRequest{ ProviderType: providerType, ContainerRequest: req, @@ -380,3 +382,32 @@ func prepareRedisImage(ctx context.Context, req ContainerRequest, t *testing.T) return redisC, err } + +//go:embed testdata/.docker/config.json +var dockerConfig string + +func Test_getDockerAuthConfigs(t *testing.T) { + t.Run("file", func(t *testing.T) { + got, err := getDockerAuthConfigs() + require.NoError(t, err) + require.NotNil(t, got) + }) + + t.Run("env", func(t *testing.T) { + t.Setenv("DOCKER_AUTH_CONFIG", dockerConfig) + + got, err := getDockerAuthConfigs() + require.NoError(t, err) + + // We can only check the keys as the values are not deterministic. + expected := map[string]registry.AuthConfig{ + "https://index.docker.io/v1/": {}, + "https://example.com": {}, + "https://my.private.registry": {}, + } + for k := range got { + got[k] = registry.AuthConfig{} + } + require.Equal(t, expected, got) + }) +} diff --git a/internal/core/images.go b/internal/core/images.go index 6c7213f12c..2892267e9c 100644 --- a/internal/core/images.go +++ b/internal/core/images.go @@ -2,6 +2,7 @@ package core import ( "bufio" + "io" "net/url" "os" "regexp" @@ -25,17 +26,22 @@ const ( var rxURL = regexp.MustCompile(URL) +// ExtractImagesFromDockerfile extracts images from the Dockerfile sourced from dockerfile. func ExtractImagesFromDockerfile(dockerfile string, buildArgs map[string]*string) ([]string, error) { - var images []string - file, err := os.Open(dockerfile) if err != nil { return nil, err } defer file.Close() + return ExtractImagesFromReader(file, buildArgs) +} + +// ExtractImagesFromReader extracts images from the Dockerfile sourced from r. +func ExtractImagesFromReader(r io.Reader, buildArgs map[string]*string) ([]string, error) { + var images []string var lines []string - scanner := bufio.NewScanner(file) + scanner := bufio.NewScanner(r) for scanner.Scan() { lines = append(lines, scanner.Text()) } From 17b178f85a5046ac51b66be46fb87e3447763adc Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 16 Aug 2024 15:52:42 +0100 Subject: [PATCH 039/126] fix: logging restart (#2697) Fix being able to stop and restart a container by moving the stop processing from PreTerminates to PostStops hooks. Fix log consumer being duplicated when restarting. Fix race condition in log consumer test, cleaning up to flow to validate correctly. --- lifecycle.go | 19 ++++++------ logconsumer_test.go | 74 +++++++++++++++++++++++++++++++-------------- 2 files changed, 61 insertions(+), 32 deletions(-) diff --git a/lifecycle.go b/lifecycle.go index 2a8ae949ab..40360a4c0b 100644 --- a/lifecycle.go +++ b/lifecycle.go @@ -165,26 +165,25 @@ var defaultCopyFileToContainerHook = func(files []ContainerFile) ContainerLifecy var defaultLogConsumersHook = func(cfg *LogConsumerConfig) ContainerLifecycleHooks { return ContainerLifecycleHooks{ PostStarts: []ContainerHook{ - // first post-start hook is to produce logs and start log consumers + // Produce logs sending details to the log consumers. + // See combineContainerHooks for the order of execution. func(ctx context.Context, c Container) error { - dockerContainer := c.(*DockerContainer) - - if cfg == nil { + if cfg == nil || len(cfg.Consumers) == 0 { return nil } + dockerContainer := c.(*DockerContainer) + dockerContainer.consumers = dockerContainer.consumers[:0] for _, consumer := range cfg.Consumers { dockerContainer.followOutput(consumer) } - if len(cfg.Consumers) > 0 { - return dockerContainer.startLogProduction(ctx, cfg.Opts...) - } - return nil + return dockerContainer.startLogProduction(ctx, cfg.Opts...) }, }, - PreTerminates: []ContainerHook{ - // first pre-terminate hook is to stop the log production + PostStops: []ContainerHook{ + // Stop the log production. + // See combineContainerHooks for the order of execution. func(ctx context.Context, c Container) error { if cfg == nil || len(cfg.Consumers) == 0 { return nil diff --git a/logconsumer_test.go b/logconsumer_test.go index 401e7a158f..6265f0a578 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -639,23 +639,54 @@ func Test_MultiContainerLogConsumer_CancelledContext(t *testing.T) { assert.False(t, strings.Contains(actual, logStoppedForOutOfSyncMessage)) } +// FooLogConsumer is a test log consumer that accepts logs from the +// "hello-world" Docker image, which prints out the "Hello from Docker!" +// log message. type FooLogConsumer struct { LogChannel chan string + t *testing.T } +// Accept receives a log message and sends it to the log channel if it +// contains the "Hello from Docker!" message. func (c FooLogConsumer) Accept(rawLog Log) { log := string(rawLog.Content) - c.LogChannel <- log + if strings.Contains(log, "Hello from Docker!") { + select { + case c.LogChannel <- log: + default: + } + } +} + +// AssertRead waits for a log message to be received. +func (c FooLogConsumer) AssertRead() { + select { + case <-c.LogChannel: + case <-time.After(5 * time.Second): + c.t.Fatal("receive timeout") + } +} + +// SlurpOne reads a value from the channel if it is available. +func (c FooLogConsumer) SlurpOne() { + select { + case <-c.LogChannel: + default: + } } -func NewFooLogConsumer() *FooLogConsumer { +func NewFooLogConsumer(t *testing.T) *FooLogConsumer { + t.Helper() + return &FooLogConsumer{ - LogChannel: make(chan string), + t: t, + LogChannel: make(chan string, 2), } } func TestRestartContainerWithLogConsumer(t *testing.T) { - logConsumer := NewFooLogConsumer() + logConsumer := NewFooLogConsumer(t) ctx := context.Background() container, err := GenericContainer(ctx, GenericContainerRequest{ @@ -668,28 +699,27 @@ func TestRestartContainerWithLogConsumer(t *testing.T) { }, Started: false, }) - if err != nil { - t.Fatalf("Cant create container: %s", err.Error()) - } + terminateContainerOnEnd(t, ctx, container) + require.NoError(t, err) + // Start and confirm that the log consumer receives the log message. err = container.Start(ctx) - if err != nil { - t.Fatalf("Cant start container: %s", err.Error()) - } + require.NoError(t, err) + + logConsumer.AssertRead() - d := 30 * time.Second + // Stop the container and clear any pending message. + d := 5 * time.Second err = container.Stop(ctx, &d) - if err != nil { - t.Fatalf("Cant stop container: %s", err.Error()) - } + require.NoError(t, err) + + logConsumer.SlurpOne() + + // Restart the container and confirm that the log consumer receives new log messages. err = container.Start(ctx) - if err != nil { - t.Fatalf("Cant start container: %s", err.Error()) - } + require.NoError(t, err) - for s := range logConsumer.LogChannel { - if strings.Contains(s, "Hello from Docker!") { - break - } - } + // First message is from the first start. + logConsumer.AssertRead() + logConsumer.AssertRead() } From 5ec00648428cfa8d8cb4cce2dbc72b0a95d5cb72 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 16 Aug 2024 15:57:30 +0100 Subject: [PATCH 040/126] fix(redpanda): race condition on port check (#2692) Use SkipInternalCheck to wait for ports to be bound externally only before trying to get the mapped port. This fixes a race condition in the setup of the container which was causing random test failures. --- modules/redpanda/redpanda.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/modules/redpanda/redpanda.go b/modules/redpanda/redpanda.go index 7f46617536..3ed3932066 100644 --- a/modules/redpanda/redpanda.go +++ b/modules/redpanda/redpanda.go @@ -86,6 +86,13 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom "--smp=1", "--memory=1G", }, + WaitingFor: wait.ForAll( + // Wait for the ports to be exposed only as the container needs configuration + // before it will bind to the ports and be ready to serve requests. + wait.ForListeningPort(defaultKafkaAPIPort).SkipInternalCheck(), + wait.ForListeningPort(defaultAdminAPIPort).SkipInternalCheck(), + wait.ForListeningPort(defaultSchemaRegistryPort).SkipInternalCheck(), + ), }, Started: true, } @@ -119,7 +126,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom // 4. Register extra kafka listeners if provided, network aliases will be // set - if err := registerListeners(ctx, settings, req); err != nil { + if err := registerListeners(settings, req); err != nil { return nil, fmt.Errorf("failed to register listeners: %w", err) } @@ -200,11 +207,13 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom return nil, fmt.Errorf("failed to copy redpanda.yaml into container: %w", err) } - // 8. Wait until Redpanda is ready to serve requests + // 8. Wait until Redpanda is ready to serve requests. err = wait.ForAll( wait.ForListeningPort(defaultKafkaAPIPort), - wait.ForLog("Successfully started Redpanda!").WithPollInterval(100*time.Millisecond)). - WaitUntilReady(ctx, container) + wait.ForListeningPort(defaultAdminAPIPort), + wait.ForListeningPort(defaultSchemaRegistryPort), + wait.ForLog("Successfully started Redpanda!"), + ).WaitUntilReady(ctx, container) if err != nil { return nil, fmt.Errorf("failed to wait for Redpanda readiness: %w", err) } @@ -299,7 +308,7 @@ func renderBootstrapConfig(settings options) ([]byte, error) { // registerListeners validates that the provided listeners are valid and set network aliases for the provided addresses. // The container must be attached to at least one network. -func registerListeners(ctx context.Context, settings options, req testcontainers.GenericContainerRequest) error { +func registerListeners(settings options, req testcontainers.GenericContainerRequest) error { if len(settings.Listeners) == 0 { return nil } From c44b1b2ed935455fa222f122a7474efe309f641c Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 16 Aug 2024 16:05:02 +0100 Subject: [PATCH 041/126] fix: config via environment (#2725) Fix the ability to set the configuration of testcontainers using an environment variable set by a caller before the use of testcontainers. This removes the warning about disabling the reaper which is actually safe when done correctly. Optimise verbose check. Improve Config struct and field documentation. Fixes: #2701 #2636 --- internal/config/config.go | 73 +++++++++++++++++++++++++++++++++------ logger.go | 20 ++--------- 2 files changed, 66 insertions(+), 27 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index 7f0039cecb..f1d702ec36 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -20,18 +20,71 @@ var ( // testcontainersConfig { -// Config represents the configuration for Testcontainers +// Config represents the configuration for Testcontainers. +// User values are read from ~/.testcontainers.properties file which can be overridden +// using the specified environment variables. For more information, see [Custom Configuration]. +// +// The Ryuk prefixed fields controls the [Garbage Collector] feature, which ensures that +// resources are cleaned up after the test execution. +// +// [Garbage Collector]: https://golang.testcontainers.org/features/garbage_collector/ +// [Custom Configuration]: https://golang.testcontainers.org/features/configuration/ type Config struct { - Host string `properties:"docker.host,default="` - TLSVerify int `properties:"docker.tls.verify,default=0"` - CertPath string `properties:"docker.cert.path,default="` - HubImageNamePrefix string `properties:"hub.image.name.prefix,default="` - RyukDisabled bool `properties:"ryuk.disabled,default=false"` - RyukPrivileged bool `properties:"ryuk.container.privileged,default=false"` + // Host is the address of the Docker daemon. + // + // Environment variable: DOCKER_HOST + Host string `properties:"docker.host,default="` + + // TLSVerify is a flag to enable or disable TLS verification when connecting to a Docker daemon. + // + // Environment variable: DOCKER_TLS_VERIFY + TLSVerify int `properties:"docker.tls.verify,default=0"` + + // CertPath is the path to the directory containing the Docker certificates. + // This is used when connecting to a Docker daemon over TLS. + // + // Environment variable: DOCKER_CERT_PATH + CertPath string `properties:"docker.cert.path,default="` + + // HubImageNamePrefix is the prefix used for the images pulled from the Docker Hub. + // This is useful when running tests in environments with restricted internet access. + // + // Environment variable: TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX + HubImageNamePrefix string `properties:"hub.image.name.prefix,default="` + + // RyukDisabled is a flag to enable or disable the Garbage Collector. + // Setting this to true will prevent testcontainers from automatically cleaning up + // resources, which is particularly important in tests which timeout as they + // don't run test clean up. + // + // Environment variable: TESTCONTAINERS_RYUK_DISABLED + RyukDisabled bool `properties:"ryuk.disabled,default=false"` + + // RyukPrivileged is a flag to enable or disable the privileged mode for the Garbage Collector container. + // Setting this to true will run the Garbage Collector container in privileged mode. + // + // Environment variable: TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED + RyukPrivileged bool `properties:"ryuk.container.privileged,default=false"` + + // RyukReconnectionTimeout is the time to wait before attempting to reconnect to the Garbage Collector container. + // + // Environment variable: TESTCONTAINERS_RYUK_RECONNECTION_TIMEOUT RyukReconnectionTimeout time.Duration `properties:"ryuk.reconnection.timeout,default=10s"` - RyukConnectionTimeout time.Duration `properties:"ryuk.connection.timeout,default=1m"` - RyukVerbose bool `properties:"ryuk.verbose,default=false"` - TestcontainersHost string `properties:"tc.host,default="` + + // RyukConnectionTimeout is the time to wait before timing out when connecting to the Garbage Collector container. + // + // Environment variable: TESTCONTAINERS_RYUK_CONNECTION_TIMEOUT + RyukConnectionTimeout time.Duration `properties:"ryuk.connection.timeout,default=1m"` + + // RyukVerbose is a flag to enable or disable verbose logging for the Garbage Collector. + // + // Environment variable: TESTCONTAINERS_RYUK_VERBOSE + RyukVerbose bool `properties:"ryuk.verbose,default=false"` + + // TestcontainersHost is the address of the Testcontainers host. + // + // Environment variable: TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE + TestcontainersHost string `properties:"tc.host,default="` } // } diff --git a/logger.go b/logger.go index cfc851ad7e..fca5da5398 100644 --- a/logger.go +++ b/logger.go @@ -8,34 +8,20 @@ import ( "testing" "github.com/docker/docker/client" - - "github.com/testcontainers/testcontainers-go/internal/config" ) // Logger is the default log instance var Logger Logging = log.New(os.Stderr, "", log.LstdFlags) func init() { - verbose := false for _, arg := range os.Args { if strings.EqualFold(arg, "-test.v=true") || strings.EqualFold(arg, "-v") { - verbose = true - break + return } } - if !verbose { - Logger = &noopLogger{} - } - - if config.Read().RyukDisabled { - ryukDisabledMessage := ` -********************************************************************************************** -Ryuk has been disabled for the current execution. This can cause unexpected behavior in your environment. -More on this: https://golang.testcontainers.org/features/garbage_collector/ -**********************************************************************************************` - Logger.Printf(ryukDisabledMessage) - } + // If we are not running in verbose mode, we configure a noop logger by default. + Logger = &noopLogger{} } // Validate our types implement the required interfaces. From aaa88d20fea42734712bb22b646af33a47ed2f53 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 19 Aug 2024 13:21:45 +0100 Subject: [PATCH 042/126] fix(registry): compatibility with WSL (#2705) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(registry): compatibility with WSL Use local IP instead of localhost to access registry container to address failures under WSL where the docker daemon can't access localhost. Refactor tests to use helpers and require reducing code and simplifying the flow. Add a default image which can be used be consumers. Add HostAddress which returns host : port compatible with WSL. Add SetDockerAuthConfig and DockerAuthConfig methods that can be used to easily configure authentication via DOCKER_AUTH_CONFIG environment variable. Fix container clean up which was missed in a number of case. * docs: document new functions * docs: wording * docs: wording Co-authored-by: Steven Hartland --------- Co-authored-by: Manuel de la Peña Co-authored-by: Manuel de la Peña --- docs/modules/registry.md | 18 +- modules/registry/examples_test.go | 73 ++---- modules/registry/go.mod | 7 +- modules/registry/go.sum | 9 + modules/registry/registry.go | 112 ++++++++- modules/registry/registry_test.go | 269 +++++++-------------- modules/registry/testdata/redis/Dockerfile | 4 +- 7 files changed, 258 insertions(+), 234 deletions(-) diff --git a/docs/modules/registry.md b/docs/modules/registry.md index ced274a2b6..94e7f4dc84 100644 --- a/docs/modules/registry.md +++ b/docs/modules/registry.md @@ -39,6 +39,17 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom - `string`, the Docker image to use. - `testcontainers.ContainerCustomizer`, a variadic argument for passing options. +### Docker Auth Config + +The module exposes a way to set the Docker Auth Config for the Registry container, thanks to the `SetDockerAuthConfig` function. +This is useful when you need to pull images from a private registry. It basically sets the `DOCKER_AUTH_CONFIG` environment variable +with authentication for the given host, username and password sets. It returns a function to reset the environment back to the previous state, +which is helpful when you need to reset the environment after a test. + +On the same hand, the module also exposes a way to build a Docker Auth Config for the Registry container, thanks to the `DockerAuthConfig` helper function. +This function returns a map of `AuthConfigs` including base64 encoded Auth field for the provided details. +It also accepts additional host, username and password triples to add more auth configurations. + ### Container Options When starting the Registry container, you can pass options in a variadic way to configure it. @@ -80,10 +91,15 @@ Otherwise, the Registry will start but you won't be able to read any images from The Registry container exposes the following methods: +#### HostAddress + +This method returns the returns the host address including port of the Distribution Registry. +E.g. `localhost:32878`. + #### Address This method returns the HTTP address string to connect to the Distribution Registry, so that you can use to connect to the Registry. -E.g. `http://localhost:32878/v2/_catalog`. +E.g. `http://localhost:32878`. [HTTP Address](../../modules/registry/registry_test.go) inside_block:httpAddress diff --git a/modules/registry/examples_test.go b/modules/registry/examples_test.go index 3b9f55099d..ada7e33b85 100644 --- a/modules/registry/examples_test.go +++ b/modules/registry/examples_test.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "log" - "os" "path/filepath" "github.com/testcontainers/testcontainers-go" @@ -40,8 +39,9 @@ func ExampleRun() { func ExampleRun_withAuthentication() { // htpasswdFile { + ctx := context.Background() registryContainer, err := registry.Run( - context.Background(), + ctx, "registry:2.8.3", registry.WithHtpasswdFile(filepath.Join("testdata", "auth", "htpasswd")), registry.WithData(filepath.Join("testdata", "data")), @@ -51,33 +51,21 @@ func ExampleRun_withAuthentication() { log.Fatalf("failed to start container: %s", err) } defer func() { - if err := registryContainer.Terminate(context.Background()); err != nil { + if err := registryContainer.Terminate(ctx); err != nil { log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic } }() - registryPort, err := registryContainer.MappedPort(context.Background(), "5000/tcp") + registryHost, err := registryContainer.HostAddress(ctx) if err != nil { - log.Fatalf("failed to get mapped port: %s", err) // nolint:gocritic + log.Fatalf("failed to get host: %s", err) // nolint:gocritic } - strPort := registryPort.Port() - - previousAuthConfig := os.Getenv("DOCKER_AUTH_CONFIG") - // make sure the Docker Auth credentials are set - // using the same as in the Docker Registry - // testuser:testpassword - os.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "localhost:`+strPort+`": { "username": "testuser", "password": "testpassword", "auth": "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk" } - }, - "credsStore": "desktop" - }`) - defer func() { - // reset the original state after the example. - os.Unsetenv("DOCKER_AUTH_CONFIG") - os.Setenv("DOCKER_AUTH_CONFIG", previousAuthConfig) - }() + cleanup, err := registry.SetDockerAuthConfig(registryHost, "testuser", "testpassword") + if err != nil { + log.Fatalf("failed to set docker auth config: %s", err) // nolint:gocritic + } + defer cleanup() // build a custom redis image from the private registry, // using RegistryName of the container as the registry. @@ -87,7 +75,7 @@ func ExampleRun_withAuthentication() { FromDockerfile: testcontainers.FromDockerfile{ Context: filepath.Join("testdata", "redis"), BuildArgs: map[string]*string{ - "REGISTRY_PORT": &strPort, + "REGISTRY_HOST": ®istryHost, }, PrintBuildLog: true, }, @@ -118,9 +106,10 @@ func ExampleRun_withAuthentication() { } func ExampleRun_pushImage() { + ctx := context.Background() registryContainer, err := registry.Run( - context.Background(), - "registry:2.8.3", + ctx, + registry.DefaultImage, registry.WithHtpasswdFile(filepath.Join("testdata", "auth", "htpasswd")), registry.WithData(filepath.Join("testdata", "data")), ) @@ -128,37 +117,27 @@ func ExampleRun_pushImage() { log.Fatalf("failed to start container: %s", err) } defer func() { - if err := registryContainer.Terminate(context.Background()); err != nil { + if err := registryContainer.Terminate(ctx); err != nil { log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic } }() - registryPort, err := registryContainer.MappedPort(context.Background(), "5000/tcp") + registryHost, err := registryContainer.HostAddress(ctx) if err != nil { - log.Fatalf("failed to get mapped port: %s", err) // nolint:gocritic + log.Fatalf("failed to get host: %s", err) // nolint:gocritic } - strPort := registryPort.Port() - - previousAuthConfig := os.Getenv("DOCKER_AUTH_CONFIG") - // make sure the Docker Auth credentials are set - // using the same as in the Docker Registry - // testuser:testpassword // Besides, we are also setting the authentication // for both the registry and localhost to make sure // the image is pushed to the private registry. - os.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "localhost:`+strPort+`": { "username": "testuser", "password": "testpassword", "auth": "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk" }, - "`+registryContainer.RegistryName+`": { "username": "testuser", "password": "testpassword", "auth": "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk" } - }, - "credsStore": "desktop" - }`) - defer func() { - // reset the original state after the example. - os.Unsetenv("DOCKER_AUTH_CONFIG") - os.Setenv("DOCKER_AUTH_CONFIG", previousAuthConfig) - }() + cleanup, err := registry.SetDockerAuthConfig( + registryHost, "testuser", "testpassword", + registryContainer.RegistryName, "testuser", "testpassword", + ) + if err != nil { + log.Fatalf("failed to set docker auth config: %s", err) // nolint:gocritic + } + defer cleanup() // build a custom redis image from the private registry, // using RegistryName of the container as the registry. @@ -174,7 +153,7 @@ func ExampleRun_pushImage() { FromDockerfile: testcontainers.FromDockerfile{ Context: filepath.Join("testdata", "redis"), BuildArgs: map[string]*string{ - "REGISTRY_PORT": &strPort, + "REGISTRY_HOST": ®istryHost, }, Repo: repo, Tag: tag, diff --git a/modules/registry/go.mod b/modules/registry/go.mod index 90513dc043..6aa887050c 100644 --- a/modules/registry/go.mod +++ b/modules/registry/go.mod @@ -3,7 +3,9 @@ module github.com/testcontainers/testcontainers-go/modules/registry go 1.21 require ( + github.com/cpuguy83/dockercfg v0.3.1 github.com/docker/docker v27.1.1+incompatible + github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.32.0 ) @@ -15,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect @@ -26,6 +28,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -37,6 +40,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -53,6 +57,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/registry/go.sum b/modules/registry/go.sum index 85338720c8..5583e9b0fc 100644 --- a/modules/registry/go.sum +++ b/modules/registry/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -52,6 +53,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -78,6 +83,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -172,6 +179,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/registry/registry.go b/modules/registry/registry.go index 22e1aa1532..b554f8dcc7 100644 --- a/modules/registry/registry.go +++ b/modules/registry/registry.go @@ -5,10 +5,13 @@ import ( "encoding/base64" "encoding/json" "fmt" + "net" "net/http" + "os" "strings" "time" + "github.com/cpuguy83/dockercfg" "github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/registry" @@ -16,6 +19,14 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) +const ( + // registryPort is the default port used by the Registry container. + registryPort = "5000/tcp" + + // DefaultImage is the default image used by the Registry container. + DefaultImage = "registry:2.8.3" +) + // RegistryContainer represents the Registry container type used in the module type RegistryContainer struct { testcontainers.Container @@ -24,17 +35,56 @@ type RegistryContainer struct { // Address returns the address of the Registry container, using the HTTP protocol func (c *RegistryContainer) Address(ctx context.Context) (string, error) { - port, err := c.MappedPort(ctx, "5000") + host, err := c.HostAddress(ctx) if err != nil { return "", err } - ipAddress, err := c.Host(ctx) + return "http://" + host, nil +} + +// HostAddress returns the host address including port of the Registry container. +func (c *RegistryContainer) HostAddress(ctx context.Context) (string, error) { + port, err := c.MappedPort(ctx, registryPort) + if err != nil { + return "", fmt.Errorf("mapped port: %w", err) + } + + host, err := c.Container.Host(ctx) if err != nil { - return "", err + return "", fmt.Errorf("host: %w", err) + } + + if host == "localhost" { + // This is a workaround for WSL, where localhost is not reachable from Docker. + host, err = localAddress(ctx) + if err != nil { + return "", fmt.Errorf("local ip: %w", err) + } + } + + return net.JoinHostPort(host, port.Port()), nil +} + +// localAddress returns the local address of the machine +// which can be used to connect to the local registry. +// This avoids the issues with localhost on WSL. +func localAddress(ctx context.Context) (string, error) { + if os.Getenv("WSL_DISTRO_NAME") == "" { + return "localhost", nil } - return fmt.Sprintf("http://%s:%s", ipAddress, port.Port()), nil + var d net.Dialer + conn, err := d.DialContext(ctx, "udp", "golang.org:80") + if err != nil { + return "", fmt.Errorf("dial: %w", err) + } + + defer conn.Close() + + localAddr := conn.LocalAddr().(*net.UDPAddr) + + return localAddr.IP.String(), nil } // getEndpointWithAuth returns the HTTP endpoint of the Registry container, along with the image auth @@ -165,7 +215,7 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*RegistryContainer, error) { req := testcontainers.ContainerRequest{ Image: img, - ExposedPorts: []string{"5000/tcp"}, + ExposedPorts: []string{registryPort}, Env: map[string]string{ // convenient for testing "REGISTRY_STORAGE_DELETE_ENABLED": "true", @@ -203,3 +253,55 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom return c, nil } + +// SetDockerAuthConfig sets the DOCKER_AUTH_CONFIG environment variable with +// authentication for the given host, username and password sets. +// It returns a function to reset the environment back to the previous state. +func SetDockerAuthConfig(host, username, password string, additional ...string) (func(), error) { + authConfigs, err := DockerAuthConfig(host, username, password, additional...) + if err != nil { + return nil, fmt.Errorf("docker auth config: %w", err) + } + + auth, err := json.Marshal(dockercfg.Config{AuthConfigs: authConfigs}) + if err != nil { + return nil, fmt.Errorf("marshal auth config: %w", err) + } + + previousAuthConfig := os.Getenv("DOCKER_AUTH_CONFIG") + os.Setenv("DOCKER_AUTH_CONFIG", string(auth)) + + return func() { + if previousAuthConfig == "" { + os.Unsetenv("DOCKER_AUTH_CONFIG") + return + } + os.Setenv("DOCKER_AUTH_CONFIG", previousAuthConfig) + }, nil +} + +// DockerAuthConfig returns a map of AuthConfigs including base64 encoded Auth field +// for the provided details. It also accepts additional host, username and password +// triples to add more auth configurations. +func DockerAuthConfig(host, username, password string, additional ...string) (map[string]dockercfg.AuthConfig, error) { + if len(additional)%3 != 0 { + return nil, fmt.Errorf("additional must be a multiple of 3") + } + + additional = append(additional, host, username, password) + authConfigs := make(map[string]dockercfg.AuthConfig, len(additional)/3) + for i := 0; i < len(additional); i += 3 { + host, username, password := additional[i], additional[i+1], additional[i+2] + auth := dockercfg.AuthConfig{ + Username: username, + Password: password, + } + + if username != "" || password != "" { + auth.Auth = base64.StdEncoding.EncodeToString([]byte(username + ":" + password)) + } + authConfigs[host] = auth + } + + return authConfigs, nil +} diff --git a/modules/registry/registry_test.go b/modules/registry/registry_test.go index dd071ef5be..d40f75125e 100644 --- a/modules/registry/registry_test.go +++ b/modules/registry/registry_test.go @@ -2,147 +2,103 @@ package registry_test import ( "context" + "encoding/json" "net/http" "path/filepath" - "strings" "testing" + "github.com/cpuguy83/dockercfg" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/registry" "github.com/testcontainers/testcontainers-go/wait" ) func TestRegistry_unauthenticated(t *testing.T) { - container, err := registry.Run(context.Background(), "registry:2.8.3") - if err != nil { - t.Fatal(err) - } + ctx := context.Background() + container, err := registry.Run(ctx, registry.DefaultImage) + terminateContainerOnEnd(t, ctx, container) + require.NoError(t, err) - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(context.Background()); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - - httpAddress, err := container.Address(context.Background()) - if err != nil { - t.Fatal(err) - } + httpAddress, err := container.Address(ctx) + require.NoError(t, err) resp, err := http.Get(httpAddress + "/v2/_catalog") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Fatalf("expected status code 200, but got %d", resp.StatusCode) - } + require.Equal(t, http.StatusOK, resp.StatusCode) } func TestRunContainer_authenticated(t *testing.T) { + ctx := context.Background() registryContainer, err := registry.Run( - context.Background(), - "registry:2.8.3", + ctx, + registry.DefaultImage, registry.WithHtpasswdFile(filepath.Join("testdata", "auth", "htpasswd")), registry.WithData(filepath.Join("testdata", "data")), ) - if err != nil { - t.Fatalf("failed to start container: %s", err) - } - t.Cleanup(func() { - if err := registryContainer.Terminate(context.Background()); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + terminateContainerOnEnd(t, ctx, registryContainer) + require.NoError(t, err) // httpAddress { - httpAddress, err := registryContainer.Address(context.Background()) + httpAddress, err := registryContainer.Address(ctx) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) - registryPort, err := registryContainer.MappedPort(context.Background(), "5000/tcp") - if err != nil { - t.Fatalf("failed to get mapped port: %s", err) - } - strPort := registryPort.Port() + registryHost, err := registryContainer.HostAddress(ctx) + require.NoError(t, err) t.Run("HTTP connection without basic auth fails", func(tt *testing.T) { httpCli := http.Client{} - req, err := http.NewRequest("GET", httpAddress+"/v2/_catalog", nil) - if err != nil { - tt.Fatal(err) - } + req, err := http.NewRequest(http.MethodGet, httpAddress+"/v2/_catalog", nil) + require.NoError(t, err) resp, err := httpCli.Do(req) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusUnauthorized { - t.Fatalf("expected status code 401, but got %d", resp.StatusCode) - } + require.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("HTTP connection with incorrect basic auth fails", func(tt *testing.T) { httpCli := http.Client{} - req, err := http.NewRequest("GET", httpAddress+"/v2/_catalog", nil) - if err != nil { - tt.Fatal(err) - } + req, err := http.NewRequest(http.MethodGet, httpAddress+"/v2/_catalog", nil) + require.NoError(t, err) req.SetBasicAuth("foo", "bar") resp, err := httpCli.Do(req) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusUnauthorized { - t.Fatalf("expected status code 401, but got %d", resp.StatusCode) - } + require.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("HTTP connection with basic auth succeeds", func(tt *testing.T) { httpCli := http.Client{} - req, err := http.NewRequest("GET", httpAddress+"/v2/_catalog", nil) - if err != nil { - tt.Fatal(err) - } + req, err := http.NewRequest(http.MethodGet, httpAddress+"/v2/_catalog", nil) + require.NoError(t, err) req.SetBasicAuth("testuser", "testpassword") resp, err := httpCli.Do(req) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Fatalf("expected status code 200, but got %d", resp.StatusCode) - } + require.Equal(t, http.StatusOK, resp.StatusCode) }) t.Run("build images with wrong credentials fails", func(tt *testing.T) { - // Zm9vOmJhcg== is base64 for foo:bar - tt.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "localhost:`+strPort+`": { "username": "foo", "password": "bar", "auth": "Zm9vOmJhcg==" } - }, - "credsStore": "desktop" - }`) + setAuthConfig(tt, registryHost, "foo", "bar") redisC, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ FromDockerfile: testcontainers.FromDockerfile{ Context: filepath.Join("testdata", "redis"), BuildArgs: map[string]*string{ - "REGISTRY_PORT": &strPort, + "REGISTRY_HOST": ®istryHost, }, }, AlwaysPullImage: true, // make sure the authentication takes place @@ -151,31 +107,13 @@ func TestRunContainer_authenticated(t *testing.T) { }, Started: true, }) - if err == nil { - tt.Fatalf("expected to fail to start container, but it did not") - } - if redisC != nil { - tt.Fatal("redis container should not be running") - tt.Cleanup(func() { - if err := redisC.Terminate(context.Background()); err != nil { - tt.Fatalf("failed to terminate container: %s", err) - } - }) - } - - if !strings.Contains(err.Error(), "unauthorized: authentication required") { - tt.Fatalf("expected error to be 'unauthorized: authentication required' but got '%s'", err.Error()) - } + terminateContainerOnEnd(tt, ctx, redisC) + require.Error(tt, err) + require.Contains(tt, err.Error(), "unauthorized: authentication required") }) t.Run("build image with valid credentials", func(tt *testing.T) { - // dGVzdHVzZXI6dGVzdHBhc3N3b3Jk is base64 for testuser:testpassword - tt.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "localhost:`+strPort+`": { "username": "testuser", "password": "testpassword", "auth": "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk" } - }, - "credsStore": "desktop" - }`) + setAuthConfig(tt, registryHost, "testuser", "testpassword") // build a custom redis image from the private registry, // using RegistryName of the container as the registry. @@ -187,7 +125,7 @@ func TestRunContainer_authenticated(t *testing.T) { FromDockerfile: testcontainers.FromDockerfile{ Context: filepath.Join("testdata", "redis"), BuildArgs: map[string]*string{ - "REGISTRY_PORT": &strPort, + "REGISTRY_HOST": ®istryHost, }, }, AlwaysPullImage: true, // make sure the authentication takes place @@ -196,97 +134,58 @@ func TestRunContainer_authenticated(t *testing.T) { }, Started: true, }) - if err != nil { - tt.Fatalf("failed to start container: %s", err) - } - - tt.Cleanup(func() { - if err := redisC.Terminate(context.Background()); err != nil { - tt.Fatalf("failed to terminate container: %s", err) - } - }) + terminateContainerOnEnd(tt, ctx, redisC) + require.NoError(tt, err) state, err := redisC.State(context.Background()) - if err != nil { - tt.Fatalf("failed to get redis container state: %s", err) // nolint:gocritic - } - - if !state.Running { - tt.Fatalf("expected redis container to be running, but it is not") - } + require.NoError(tt, err) + require.True(tt, state.Running, "expected redis container to be running, but it is not") }) } func TestRunContainer_authenticated_withCredentials(t *testing.T) { + ctx := context.Background() // htpasswdString { registryContainer, err := registry.Run( - context.Background(), - "registry:2.8.3", + ctx, + registry.DefaultImage, registry.WithHtpasswd("testuser:$2y$05$tTymaYlWwJOqie.bcSUUN.I.kxmo1m5TLzYQ4/ejJ46UMXGtq78EO"), ) // } - if err != nil { - t.Fatalf("failed to start container: %s", err) - } - t.Cleanup(func() { - if err := registryContainer.Terminate(context.Background()); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + terminateContainerOnEnd(t, ctx, registryContainer) + require.NoError(t, err) - httpAddress, err := registryContainer.Address(context.Background()) - if err != nil { - t.Fatal(err) - } + httpAddress, err := registryContainer.Address(ctx) + require.NoError(t, err) httpCli := http.Client{} - req, err := http.NewRequest("GET", httpAddress+"/v2/_catalog", nil) - if err != nil { - t.Fatal(err) - } + req, err := http.NewRequest(http.MethodGet, httpAddress+"/v2/_catalog", nil) + require.NoError(t, err) req.SetBasicAuth("testuser", "testpassword") resp, err := httpCli.Do(req) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Fatalf("expected status code 200, but got %d", resp.StatusCode) - } + require.Equal(t, http.StatusOK, resp.StatusCode) } func TestRunContainer_wrongData(t *testing.T) { + ctx := context.Background() registryContainer, err := registry.Run( - context.Background(), - "registry:2.8.3", + ctx, + registry.DefaultImage, registry.WithHtpasswdFile(filepath.Join("testdata", "auth", "htpasswd")), registry.WithData(filepath.Join("testdata", "wrongdata")), ) - if err != nil { - t.Fatalf("failed to start container: %s", err) - } - t.Cleanup(func() { - if err := registryContainer.Terminate(context.Background()); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + terminateContainerOnEnd(t, ctx, registryContainer) + require.NoError(t, err) - registryPort, err := registryContainer.MappedPort(context.Background(), "5000/tcp") - if err != nil { - t.Fatalf("failed to get mapped port: %s", err) - } - strPort := registryPort.Port() + registryHost, err := registryContainer.HostAddress(ctx) + require.NoError(t, err) - // dGVzdHVzZXI6dGVzdHBhc3N3b3Jk is base64 for testuser:testpassword - t.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "localhost:`+strPort+`": { "username": "testuser", "password": "testpassword", "auth": "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk" } - }, - "credsStore": "desktop" - }`) + setAuthConfig(t, registryHost, "testuser", "testpassword") // build a custom redis image from the private registry, // using RegistryName of the container as the registry. @@ -298,7 +197,7 @@ func TestRunContainer_wrongData(t *testing.T) { FromDockerfile: testcontainers.FromDockerfile{ Context: filepath.Join("testdata", "redis"), BuildArgs: map[string]*string{ - "REGISTRY_PORT": &strPort, + "REGISTRY_HOST": ®istryHost, }, }, AlwaysPullImage: true, // make sure the authentication takes place @@ -307,19 +206,33 @@ func TestRunContainer_wrongData(t *testing.T) { }, Started: true, }) - if err == nil { - t.Fatalf("expected to fail to start container, but it did not") - } - if redisC != nil { - t.Fatal("redis container should not be running") - t.Cleanup(func() { - if err := redisC.Terminate(context.Background()); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - } + terminateContainerOnEnd(t, ctx, redisC) + require.Error(t, err) + require.Contains(t, err.Error(), "manifest unknown") +} + +// setAuthConfig sets the DOCKER_AUTH_CONFIG environment variable with +// authentication for with the given host, username and password. +func setAuthConfig(t *testing.T, host, username, password string) { + t.Helper() - if !strings.Contains(err.Error(), "manifest unknown") { - t.Fatalf("expected error to be 'manifest unknown' but got '%s'", err.Error()) + authConfigs, err := registry.DockerAuthConfig(host, username, password) + require.NoError(t, err) + auth, err := json.Marshal(dockercfg.Config{AuthConfigs: authConfigs}) + require.NoError(t, err) + + t.Setenv("DOCKER_AUTH_CONFIG", string(auth)) +} + +// terminateContainerOnEnd terminates the container when the test ends if it is not nil. +func terminateContainerOnEnd(tb testing.TB, ctx context.Context, container testcontainers.Container) { + tb.Helper() + + if container == nil { + return } + + tb.Cleanup(func() { + require.NoError(tb, container.Terminate(ctx)) + }) } diff --git a/modules/registry/testdata/redis/Dockerfile b/modules/registry/testdata/redis/Dockerfile index 502db64261..280c33c827 100644 --- a/modules/registry/testdata/redis/Dockerfile +++ b/modules/registry/testdata/redis/Dockerfile @@ -1,3 +1,3 @@ -ARG REGISTRY_PORT=5000 +ARG REGISTRY_HOST=localhost:5000 -FROM localhost:${REGISTRY_PORT}/redis:5.0-alpine \ No newline at end of file +FROM ${REGISTRY_HOST}/redis:5.0-alpine From ca76ee195050114626fb2421fb0ba218399a2680 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 19 Aug 2024 15:20:39 +0100 Subject: [PATCH 043/126] fix: authentication tests on WSL (#2706) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix docker auth tests to run on WSL by using the local IP instead of localhost, which can be unreliable. While there refactor the tests to use a helper instead of hand coding each environment setup. Remove duplicate logging about terminating container as default hooks already provide this. Co-authored-by: Manuel de la Peña --- docker_auth_test.go | 152 ++++++++++++++++++++------------------- testdata/auth.Dockerfile | 4 +- testhelpers_test.go | 1 - 3 files changed, 80 insertions(+), 77 deletions(-) diff --git a/docker_auth_test.go b/docker_auth_test.go index 5b3e1e1067..4e55d2b9bf 100644 --- a/docker_auth_test.go +++ b/docker_auth_test.go @@ -3,7 +3,9 @@ package testcontainers import ( "context" _ "embed" + "encoding/base64" "fmt" + "net" "os" "path/filepath" "testing" @@ -75,12 +77,7 @@ func TestGetDockerConfig(t *testing.T) { }) t.Run("DOCKER_AUTH_CONFIG env var takes precedence", func(t *testing.T) { - t.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "`+exampleAuth+`": {} - }, - "credsStore": "desktop" - }`) + setAuthConfig(t, exampleAuth, "", "") t.Setenv("DOCKER_CONFIG", testDockerConfigDirPath) cfg, err := getDockerConfig() @@ -100,36 +97,23 @@ func TestGetDockerConfig(t *testing.T) { }) t.Run("retrieve auth with DOCKER_AUTH_CONFIG env var", func(t *testing.T) { - base64 := "Z29waGVyOnNlY3JldA==" // gopher:secret - - t.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "`+exampleAuth+`": { "username": "gopher", "password": "secret", "auth": "`+base64+`" } - }, - "credsStore": "desktop" - }`) + username, password := "gopher", "secret" + creds := setAuthConfig(t, exampleAuth, username, password) registry, cfg, err := DockerImageAuth(context.Background(), exampleAuth+"/my/image:latest") require.NoError(t, err) require.NotEmpty(t, cfg) assert.Equal(t, exampleAuth, registry) - assert.Equal(t, "gopher", cfg.Username) - assert.Equal(t, "secret", cfg.Password) - assert.Equal(t, base64, cfg.Auth) + assert.Equal(t, username, cfg.Username) + assert.Equal(t, password, cfg.Password) + assert.Equal(t, creds, cfg.Auth) }) t.Run("match registry authentication by host", func(t *testing.T) { - base64 := "Z29waGVyOnNlY3JldA==" // gopher:secret imageReg := "example-auth.com" imagePath := "/my/image:latest" - - t.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "`+exampleAuth+`": { "username": "gopher", "password": "secret", "auth": "`+base64+`" } - }, - "credsStore": "desktop" - }`) + base64 := setAuthConfig(t, exampleAuth, "gopher", "secret") registry, cfg, err := DockerImageAuth(context.Background(), imageReg+imagePath) require.NoError(t, err) @@ -142,17 +126,11 @@ func TestGetDockerConfig(t *testing.T) { }) t.Run("fail to match registry authentication due to invalid host", func(t *testing.T) { - base64 := "Z29waGVyOnNlY3JldA==" // gopher:secret imageReg := "example-auth.com" imagePath := "/my/image:latest" invalidRegistryURL := "://invalid-host" - t.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "`+invalidRegistryURL+`": { "username": "gopher", "password": "secret", "auth": "`+base64+`" } - }, - "credsStore": "desktop" - }`) + setAuthConfig(t, invalidRegistryURL, "gopher", "secret") registry, cfg, err := DockerImageAuth(context.Background(), imageReg+imagePath) require.ErrorIs(t, err, dockercfg.ErrCredentialsNotFound) @@ -170,16 +148,10 @@ func TestGetDockerConfig(t *testing.T) { return "" } - base64 := "Z29waGVyOnNlY3JldA==" // gopher:secret imageReg := "" imagePath := "image:latest" - t.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "example-auth.com": { "username": "gopher", "password": "secret", "auth": "`+base64+`" } - }, - "credsStore": "desktop" - }`) + setAuthConfig(t, "example-auth.com", "gopher", "secret") registry, cfg, err := DockerImageAuth(context.Background(), imageReg+imagePath) require.ErrorIs(t, err, dockercfg.ErrCredentialsNotFound) @@ -219,22 +191,16 @@ func removeImageFromLocalCache(t *testing.T, img string) { Force: true, PruneChildren: true, }) - if err != nil { + if err != nil && !client.IsErrNotFound(err) { t.Logf("could not remove image %s: %v\n", img, err) } } func TestBuildContainerFromDockerfileWithDockerAuthConfig(t *testing.T) { - mappedPort := prepareLocalRegistryWithAuth(t) + registryHost := prepareLocalRegistryWithAuth(t) // using the same credentials as in the Docker Registry - base64 := "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk" // testuser:testpassword - t.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "localhost:`+mappedPort+`": { "username": "testuser", "password": "testpassword", "auth": "`+base64+`" } - }, - "credsStore": "desktop" - }`) + setAuthConfig(t, registryHost, "testuser", "testpassword") ctx := context.Background() @@ -243,8 +209,10 @@ func TestBuildContainerFromDockerfileWithDockerAuthConfig(t *testing.T) { Context: "./testdata", Dockerfile: "auth.Dockerfile", BuildArgs: map[string]*string{ - "REGISTRY_PORT": &mappedPort, + "REGISTRY_HOST": ®istryHost, }, + Repo: "localhost", + PrintBuildLog: true, }, AlwaysPullImage: true, // make sure the authentication takes place ExposedPorts: []string{"6379/tcp"}, @@ -252,21 +220,15 @@ func TestBuildContainerFromDockerfileWithDockerAuthConfig(t *testing.T) { } redisC, err := prepareRedisImage(ctx, req) - require.NoError(t, err) terminateContainerOnEnd(t, ctx, redisC) + require.NoError(t, err) } func TestBuildContainerFromDockerfileShouldFailWithWrongDockerAuthConfig(t *testing.T) { - mappedPort := prepareLocalRegistryWithAuth(t) + registryHost := prepareLocalRegistryWithAuth(t) // using different credentials than in the Docker Registry - base64 := "Zm9vOmJhcg==" // foo:bar - t.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "localhost:`+mappedPort+`": { "username": "foo", "password": "bar", "auth": "`+base64+`" } - }, - "credsStore": "desktop" - }`) + setAuthConfig(t, registryHost, "foo", "bar") ctx := context.Background() @@ -275,7 +237,7 @@ func TestBuildContainerFromDockerfileShouldFailWithWrongDockerAuthConfig(t *test Context: "./testdata", Dockerfile: "auth.Dockerfile", BuildArgs: map[string]*string{ - "REGISTRY_PORT": &mappedPort, + "REGISTRY_HOST": ®istryHost, }, }, AlwaysPullImage: true, // make sure the authentication takes place @@ -284,25 +246,19 @@ func TestBuildContainerFromDockerfileShouldFailWithWrongDockerAuthConfig(t *test } redisC, err := prepareRedisImage(ctx, req) - require.Error(t, err) terminateContainerOnEnd(t, ctx, redisC) + require.Error(t, err) } func TestCreateContainerFromPrivateRegistry(t *testing.T) { - mappedPort := prepareLocalRegistryWithAuth(t) + registryHost := prepareLocalRegistryWithAuth(t) // using the same credentials as in the Docker Registry - base64 := "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk" // testuser:testpassword - t.Setenv("DOCKER_AUTH_CONFIG", `{ - "auths": { - "localhost:`+mappedPort+`": { "username": "testuser", "password": "testpassword", "auth": "`+base64+`" } - }, - "credsStore": "desktop" - }`) + setAuthConfig(t, registryHost, "testuser", "testpassword") ctx := context.Background() req := ContainerRequest{ - Image: "localhost:" + mappedPort + "/redis:5.0-alpine", + Image: registryHost + "/redis:5.0-alpine", AlwaysPullImage: true, // make sure the authentication takes place ExposedPorts: []string{"6379/tcp"}, WaitingFor: wait.ForLog("Ready to accept connections"), @@ -312,8 +268,8 @@ func TestCreateContainerFromPrivateRegistry(t *testing.T) { ContainerRequest: req, Started: true, }) - require.NoError(t, err) terminateContainerOnEnd(t, ctx, redisContainer) + require.NoError(t, err) } func prepareLocalRegistryWithAuth(t *testing.T) string { @@ -356,10 +312,12 @@ func prepareLocalRegistryWithAuth(t *testing.T) string { mappedPort, err := registryC.MappedPort(ctx, "5000/tcp") require.NoError(t, err) + ip := localAddress(t) mp := mappedPort.Port() + addr := ip + ":" + mp t.Cleanup(func() { - removeImageFromLocalCache(t, "localhost:"+mp+"/redis:5.0-alpine") + removeImageFromLocalCache(t, addr+"/redis:5.0-alpine") }) t.Cleanup(func() { require.NoError(t, registryC.Terminate(context.Background())) @@ -368,7 +326,7 @@ func prepareLocalRegistryWithAuth(t *testing.T) string { _, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) - return mp + return addr } func prepareRedisImage(ctx context.Context, req ContainerRequest) (Container, error) { @@ -378,9 +336,55 @@ func prepareRedisImage(ctx context.Context, req ContainerRequest) (Container, er Started: true, } - redisC, err := GenericContainer(ctx, genContainerReq) + return GenericContainer(ctx, genContainerReq) +} + +// setAuthConfig sets the DOCKER_AUTH_CONFIG environment variable with +// authentication for with the given host, username and password. +// It returns the base64 encoded credentials. +func setAuthConfig(t *testing.T, host, username, password string) string { + t.Helper() + + var creds string + if username != "" || password != "" { + creds = base64.StdEncoding.EncodeToString([]byte(username + ":" + password)) + } + + auth := fmt.Sprintf(`{ + "auths": { + %q: { + "username": %q, + "password": %q, + "auth": %q + } + }, + "credsStore": "desktop" +}`, + host, + username, + password, + creds, + ) + t.Setenv("DOCKER_AUTH_CONFIG", auth) + + return creds +} + +// localAddress returns the local address of the machine +// which can be used to connect to the local registry. +// This avoids the issues with localhost on WSL. +func localAddress(t *testing.T) string { + if os.Getenv("WSL_DISTRO_NAME") == "" { + return "localhost" + } + + conn, err := net.Dial("udp", "golang.org:80") + require.NoError(t, err) + defer conn.Close() + + localAddr := conn.LocalAddr().(*net.UDPAddr) - return redisC, err + return localAddr.IP.String() } //go:embed testdata/.docker/config.json diff --git a/testdata/auth.Dockerfile b/testdata/auth.Dockerfile index 367e228a67..5fcebe0baf 100644 --- a/testdata/auth.Dockerfile +++ b/testdata/auth.Dockerfile @@ -1,3 +1,3 @@ -ARG REGISTRY_PORT=5001 +ARG REGISTRY_HOST=localhost:5001 -FROM localhost:${REGISTRY_PORT}/redis:5.0-alpine +FROM ${REGISTRY_HOST}/redis:5.0-alpine diff --git a/testhelpers_test.go b/testhelpers_test.go index 47bbcb54c3..3be3b7c50d 100644 --- a/testhelpers_test.go +++ b/testhelpers_test.go @@ -20,7 +20,6 @@ func terminateContainerOnEnd(tb testing.TB, ctx context.Context, ctr testcontain return } tb.Cleanup(func() { - tb.Log("terminating container") require.NoError(tb, ctr.Terminate(ctx)) }) } From e21a5e1cfa7ffea08f4c5967ec66068b1addf3fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 20 Aug 2024 13:48:12 +0200 Subject: [PATCH 044/126] chore: use new version (v0.33.0) in modules and examples --- docs/modules/grafana-lgtm.md | 18 +++++++++--------- docs/modules/valkey.md | 10 ++++++++-- examples/nginx/go.mod | 2 +- examples/toxiproxy/go.mod | 2 +- mkdocs.yml | 2 +- modules/artemis/go.mod | 2 +- modules/azurite/go.mod | 2 +- modules/cassandra/go.mod | 2 +- modules/chroma/go.mod | 2 +- modules/clickhouse/go.mod | 2 +- modules/cockroachdb/go.mod | 2 +- modules/compose/go.mod | 2 +- modules/consul/go.mod | 2 +- modules/couchbase/go.mod | 2 +- modules/dolt/go.mod | 2 +- modules/elasticsearch/go.mod | 2 +- modules/gcloud/go.mod | 2 +- modules/grafana-lgtm/go.mod | 2 +- modules/inbucket/go.mod | 2 +- modules/influxdb/go.mod | 2 +- modules/k3s/go.mod | 2 +- modules/k6/go.mod | 2 +- modules/kafka/go.mod | 2 +- modules/localstack/go.mod | 2 +- modules/mariadb/go.mod | 2 +- modules/milvus/go.mod | 2 +- modules/minio/go.mod | 2 +- modules/mockserver/go.mod | 2 +- modules/mongodb/go.mod | 2 +- modules/mssql/go.mod | 2 +- modules/mysql/go.mod | 2 +- modules/nats/go.mod | 2 +- modules/neo4j/go.mod | 2 +- modules/ollama/go.mod | 2 +- modules/openfga/go.mod | 2 +- modules/openldap/go.mod | 2 +- modules/opensearch/go.mod | 2 +- modules/postgres/go.mod | 2 +- modules/pulsar/go.mod | 2 +- modules/qdrant/go.mod | 2 +- modules/rabbitmq/go.mod | 2 +- modules/redis/go.mod | 2 +- modules/redpanda/go.mod | 2 +- modules/registry/go.mod | 2 +- modules/surrealdb/go.mod | 2 +- modules/valkey/go.mod | 2 +- modules/vault/go.mod | 2 +- modules/vearch/go.mod | 2 +- modules/weaviate/go.mod | 2 +- sonar-project.properties | 2 +- 50 files changed, 65 insertions(+), 59 deletions(-) diff --git a/docs/modules/grafana-lgtm.md b/docs/modules/grafana-lgtm.md index 56e263aac0..b76c56bc66 100644 --- a/docs/modules/grafana-lgtm.md +++ b/docs/modules/grafana-lgtm.md @@ -1,6 +1,6 @@ # Grafana LGTM -Not available until the next release of testcontainers-go :material-tag: main +Since testcontainers-go :material-tag: v0.33.0 ## Introduction @@ -24,7 +24,7 @@ go get github.com/testcontainers/testcontainers-go/modules/grafanalgtm ### Run function -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.33.0 !!!info The `RunContainer(ctx, opts...)` function is deprecated and will be removed in the next major release of _Testcontainers for Go_. @@ -50,7 +50,7 @@ E.g. `Run(context.Background(), "grafana/otel-lgtm:0.6.0")`. #### Admin Credentials -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.33.0 If you need to set different admin credentials in the Grafana LGTM container, you can set them using the `WithAdminCredentials(user, password)` option. @@ -65,37 +65,37 @@ The Grafana LGTM container exposes the following methods: #### Grafana Endpoint -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.33.0 The `HttpEndpoint(ctx)` method returns the HTTP endpoint to connect to Grafana, using the default `3000` port. The same method with the `Must` prefix returns just the endpoing, and panics if an error occurs. #### Loki Endpoint -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.33.0 The `LokiEndpoint(ctx)` method returns the HTTP endpoint to connect to Loki, using the default `3100` port. The same method with the `Must` prefix returns just the endpoing, and panics if an error occurs. #### Tempo Endpoint -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.33.0 The `TempoEndpoint(ctx)` method returns the HTTP endpoint to connect to Tempo, using the default `3200` port. The same method with the `Must` prefix returns just the endpoing, and panics if an error occurs. #### Otel HTTP Endpoint -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.33.0 The `OtelHTTPEndpoint(ctx)` method returns the endpoint to connect to Otel using HTTP, using the default `4318` port. The same method with the `Must` prefix returns just the endpoing, and panics if an error occurs. #### Otel gRPC Endpoint -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.33.0 The `OtelGRPCEndpoint(ctx)` method returns the endpoint to connect to Otel using gRPC, using the default `4317` port. The same method with the `Must` prefix returns just the endpoing, and panics if an error occurs. #### Prometheus Endpoint -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.33.0 The `PrometheusHttpEndpoint(ctx)` method returns the endpoint to connect to Prometheus, using the default `9090` port. The same method with the `Must` prefix returns just the endpoing, and panics if an error occurs. diff --git a/docs/modules/valkey.md b/docs/modules/valkey.md index 3210c233cb..40b124f242 100644 --- a/docs/modules/valkey.md +++ b/docs/modules/valkey.md @@ -1,6 +1,6 @@ # Valkey -Not available until the next release of testcontainers-go :material-tag: main +Since testcontainers-go :material-tag: v0.33.0 ## Introduction @@ -24,7 +24,7 @@ go get github.com/testcontainers/testcontainers-go/modules/valkey ### Run function -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.33.0 !!!info The `RunContainer(ctx, opts...)` function is deprecated and will be removed in the next major release of _Testcontainers for Go_. @@ -52,10 +52,14 @@ E.g. `Run(context.Background(), "valkey/valkey:7.2.5")`. #### Snapshotting +- Since testcontainers-go :material-tag: v0.33.0 + By default Valkey saves snapshots of the dataset on disk, in a binary file called dump.rdb. You can configure Valkey to have it save the dataset every `N` seconds if there are at least `M` changes in the dataset. E.g. `WithSnapshotting(10, 1)`. #### Log Level +- Since testcontainers-go :material-tag: v0.33.0 + You can easily set the valkey logging level. E.g. `WithLogLevel(LogLevelDebug)`. #### Valkey configuration @@ -68,6 +72,8 @@ The Valkey container exposes the following methods: #### ConnectionString +- Since testcontainers-go :material-tag: v0.33.0 + This method returns the connection string to connect to the Valkey container, using the default `6379` port. diff --git a/examples/nginx/go.mod b/examples/nginx/go.mod index 4852b9d133..4a5021f85f 100644 --- a/examples/nginx/go.mod +++ b/examples/nginx/go.mod @@ -2,7 +2,7 @@ module github.com/testcontainers/testcontainers-go/examples/nginx go 1.21 -require github.com/testcontainers/testcontainers-go v0.32.0 +require github.com/testcontainers/testcontainers-go v0.33.0 replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/examples/toxiproxy/go.mod b/examples/toxiproxy/go.mod index 10f1c0c193..165f9875ce 100644 --- a/examples/toxiproxy/go.mod +++ b/examples/toxiproxy/go.mod @@ -6,7 +6,7 @@ require ( github.com/Shopify/toxiproxy/v2 v2.8.0 github.com/go-redis/redis/v8 v8.11.5 github.com/google/uuid v1.6.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/mkdocs.yml b/mkdocs.yml index 1494555b0c..7dc942de52 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -134,4 +134,4 @@ nav: - Getting help: getting_help.md edit_uri: edit/main/docs/ extra: - latest_version: v0.32.0 + latest_version: v0.33.0 diff --git a/modules/artemis/go.mod b/modules/artemis/go.mod index f89d49fe30..43aebbeaa8 100644 --- a/modules/artemis/go.mod +++ b/modules/artemis/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/go-stomp/stomp/v3 v3.0.5 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/azurite/go.mod b/modules/azurite/go.mod index 209c4a066f..63acddbb1b 100644 --- a/modules/azurite/go.mod +++ b/modules/azurite/go.mod @@ -8,7 +8,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue v1.0.0 github.com/docker/go-connections v0.5.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/cassandra/go.mod b/modules/cassandra/go.mod index ed211d6cd1..ded3d59600 100644 --- a/modules/cassandra/go.mod +++ b/modules/cassandra/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/gocql/gocql v1.6.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/chroma/go.mod b/modules/chroma/go.mod index 2497b2687d..ad2d9ed98b 100644 --- a/modules/chroma/go.mod +++ b/modules/chroma/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/amikos-tech/chroma-go v0.1.2 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/clickhouse/go.mod b/modules/clickhouse/go.mod index fcb4bb180e..1008f9332f 100644 --- a/modules/clickhouse/go.mod +++ b/modules/clickhouse/go.mod @@ -7,7 +7,7 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/cockroachdb/go.mod b/modules/cockroachdb/go.mod index 9189455d27..fd02aa4d62 100644 --- a/modules/cockroachdb/go.mod +++ b/modules/cockroachdb/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/jackc/pgx/v5 v5.5.4 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/compose/go.mod b/modules/compose/go.mod index df034fb4b5..f0cfa98c94 100644 --- a/modules/compose/go.mod +++ b/modules/compose/go.mod @@ -11,7 +11,7 @@ require ( github.com/docker/docker v27.1.1+incompatible github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 golang.org/x/sync v0.7.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/modules/consul/go.mod b/modules/consul/go.mod index be56e58272..c81bd4d53a 100644 --- a/modules/consul/go.mod +++ b/modules/consul/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/hashicorp/consul/api v1.27.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/couchbase/go.mod b/modules/couchbase/go.mod index 7ceb5b8660..517ce1a474 100644 --- a/modules/couchbase/go.mod +++ b/modules/couchbase/go.mod @@ -8,7 +8,7 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 github.com/couchbase/gocb/v2 v2.7.2 github.com/docker/go-connections v0.5.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 github.com/tidwall/gjson v1.17.1 ) diff --git a/modules/dolt/go.mod b/modules/dolt/go.mod index f85df4fdab..201a222475 100644 --- a/modules/dolt/go.mod +++ b/modules/dolt/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/go-sql-driver/mysql v1.7.1 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/elasticsearch/go.mod b/modules/elasticsearch/go.mod index d062972128..2d5f1adb31 100644 --- a/modules/elasticsearch/go.mod +++ b/modules/elasticsearch/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/elastic/go-elasticsearch/v8 v8.12.1 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 golang.org/x/mod v0.16.0 ) diff --git a/modules/gcloud/go.mod b/modules/gcloud/go.mod index 32088e2962..36a70a1269 100644 --- a/modules/gcloud/go.mod +++ b/modules/gcloud/go.mod @@ -10,7 +10,7 @@ require ( cloud.google.com/go/pubsub v1.36.2 cloud.google.com/go/spanner v1.57.0 github.com/docker/go-connections v0.5.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 google.golang.org/api v0.169.0 google.golang.org/grpc v1.64.1 ) diff --git a/modules/grafana-lgtm/go.mod b/modules/grafana-lgtm/go.mod index a1cba21836..a9c73fcafe 100644 --- a/modules/grafana-lgtm/go.mod +++ b/modules/grafana-lgtm/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/docker/go-connections v0.5.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 go.opentelemetry.io/contrib/bridges/otelslog v0.3.0 go.opentelemetry.io/contrib/instrumentation/runtime v0.53.0 go.opentelemetry.io/otel v1.28.0 diff --git a/modules/inbucket/go.mod b/modules/inbucket/go.mod index 68be24e81a..1188b1efc5 100644 --- a/modules/inbucket/go.mod +++ b/modules/inbucket/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/inbucket/inbucket v2.0.0+incompatible github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/influxdb/go.mod b/modules/influxdb/go.mod index abf0e25a9a..749ba62026 100644 --- a/modules/influxdb/go.mod +++ b/modules/influxdb/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/k3s/go.mod b/modules/k3s/go.mod index 2c2fa952a0..fd69916dc6 100644 --- a/modules/k3s/go.mod +++ b/modules/k3s/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.29.2 k8s.io/apimachinery v0.29.2 diff --git a/modules/k6/go.mod b/modules/k6/go.mod index d9eda1b043..159a74c48c 100644 --- a/modules/k6/go.mod +++ b/modules/k6/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/docker/docker v27.1.1+incompatible - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/kafka/go.mod b/modules/kafka/go.mod index 66d66e3663..a33d25d6c8 100644 --- a/modules/kafka/go.mod +++ b/modules/kafka/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/IBM/sarama v1.42.1 github.com/docker/go-connections v0.5.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 golang.org/x/mod v0.16.0 ) diff --git a/modules/localstack/go.mod b/modules/localstack/go.mod index 5394a23978..38c2f059e5 100644 --- a/modules/localstack/go.mod +++ b/modules/localstack/go.mod @@ -11,7 +11,7 @@ require ( github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 golang.org/x/mod v0.16.0 ) diff --git a/modules/mariadb/go.mod b/modules/mariadb/go.mod index 5840823acf..2c0119f1b7 100644 --- a/modules/mariadb/go.mod +++ b/modules/mariadb/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/go-sql-driver/mysql v1.7.1 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/milvus/go.mod b/modules/milvus/go.mod index 09b76b3c02..5de6a6c7eb 100644 --- a/modules/milvus/go.mod +++ b/modules/milvus/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/milvus-io/milvus-sdk-go/v2 v2.3.6 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/minio/go.mod b/modules/minio/go.mod index 5b3d42070b..a15b25688c 100644 --- a/modules/minio/go.mod +++ b/modules/minio/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/minio/minio-go/v7 v7.0.68 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/mockserver/go.mod b/modules/mockserver/go.mod index c956c7af92..81cb5a9d0c 100644 --- a/modules/mockserver/go.mod +++ b/modules/mockserver/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/BraspagDevelopers/mock-server-client v0.2.2 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/mongodb/go.mod b/modules/mongodb/go.mod index 626023da8d..9756c3f722 100644 --- a/modules/mongodb/go.mod +++ b/modules/mongodb/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/mongodb go 1.21 require ( - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 go.mongodb.org/mongo-driver v1.13.1 ) diff --git a/modules/mssql/go.mod b/modules/mssql/go.mod index 561ab41aed..5b36d98189 100644 --- a/modules/mssql/go.mod +++ b/modules/mssql/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/microsoft/go-mssqldb v1.7.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/mysql/go.mod b/modules/mysql/go.mod index 420d1fa56e..1366d35491 100644 --- a/modules/mysql/go.mod +++ b/modules/mysql/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/go-sql-driver/mysql v1.7.1 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) diff --git a/modules/nats/go.mod b/modules/nats/go.mod index 7de187bb61..4163f8ba83 100644 --- a/modules/nats/go.mod +++ b/modules/nats/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/nats-io/nats.go v1.33.1 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/neo4j/go.mod b/modules/neo4j/go.mod index 01cae82a7f..e63e2854a3 100644 --- a/modules/neo4j/go.mod +++ b/modules/neo4j/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/docker/go-connections v0.5.0 github.com/neo4j/neo4j-go-driver/v5 v5.18.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/ollama/go.mod b/modules/ollama/go.mod index 73fd510df4..8dc279da02 100644 --- a/modules/ollama/go.mod +++ b/modules/ollama/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/docker/docker v27.1.1+incompatible github.com/google/uuid v1.6.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 github.com/tmc/langchaingo v0.1.5 ) diff --git a/modules/openfga/go.mod b/modules/openfga/go.mod index d9ce4b4efd..6aa77ede7c 100644 --- a/modules/openfga/go.mod +++ b/modules/openfga/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/openfga/go-sdk v0.3.5 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/openldap/go.mod b/modules/openldap/go.mod index 69ec47711c..e6477cb0a6 100644 --- a/modules/openldap/go.mod +++ b/modules/openldap/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/go-ldap/ldap/v3 v3.4.6 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/opensearch/go.mod b/modules/opensearch/go.mod index c65559d3e1..721eb1f292 100644 --- a/modules/opensearch/go.mod +++ b/modules/opensearch/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/docker/docker v27.1.1+incompatible github.com/docker/go-units v0.5.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/postgres/go.mod b/modules/postgres/go.mod index 83677326b7..45d18c23f0 100644 --- a/modules/postgres/go.mod +++ b/modules/postgres/go.mod @@ -7,7 +7,7 @@ require ( github.com/jackc/pgx/v5 v5.5.4 github.com/lib/pq v1.10.9 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) diff --git a/modules/pulsar/go.mod b/modules/pulsar/go.mod index 20fd5455bf..19b896c1da 100644 --- a/modules/pulsar/go.mod +++ b/modules/pulsar/go.mod @@ -7,7 +7,7 @@ require ( github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/qdrant/go.mod b/modules/qdrant/go.mod index d3fbac9f76..e9e031e284 100644 --- a/modules/qdrant/go.mod +++ b/modules/qdrant/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/qdrant/go-client v1.7.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 google.golang.org/grpc v1.64.1 ) diff --git a/modules/rabbitmq/go.mod b/modules/rabbitmq/go.mod index c5b5784ccb..d7906746d0 100644 --- a/modules/rabbitmq/go.mod +++ b/modules/rabbitmq/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/docker/go-connections v0.5.0 github.com/rabbitmq/amqp091-go v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/redis/go.mod b/modules/redis/go.mod index 0c655fe5c4..db7d207002 100644 --- a/modules/redis/go.mod +++ b/modules/redis/go.mod @@ -6,7 +6,7 @@ require ( github.com/go-redis/redis/v8 v8.11.5 github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) diff --git a/modules/redpanda/go.mod b/modules/redpanda/go.mod index deb901ccaa..8a780fca54 100644 --- a/modules/redpanda/go.mod +++ b/modules/redpanda/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 github.com/twmb/franz-go v1.16.1 github.com/twmb/franz-go/pkg/kadm v1.11.0 golang.org/x/mod v0.16.0 diff --git a/modules/registry/go.mod b/modules/registry/go.mod index 6aa887050c..b1d844515d 100644 --- a/modules/registry/go.mod +++ b/modules/registry/go.mod @@ -6,7 +6,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.1 github.com/docker/docker v27.1.1+incompatible github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/surrealdb/go.mod b/modules/surrealdb/go.mod index 8411ee4e79..80db8eccc6 100644 --- a/modules/surrealdb/go.mod +++ b/modules/surrealdb/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/surrealdb/surrealdb.go v0.2.1 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 ) require ( diff --git a/modules/valkey/go.mod b/modules/valkey/go.mod index 6d394c5c16..220069fea0 100644 --- a/modules/valkey/go.mod +++ b/modules/valkey/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 github.com/valkey-io/valkey-go v1.0.41 ) diff --git a/modules/vault/go.mod b/modules/vault/go.mod index 6e04cb687e..5cdd22209a 100644 --- a/modules/vault/go.mod +++ b/modules/vault/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/docker v27.1.1+incompatible github.com/hashicorp/vault-client-go v0.4.3 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 github.com/tidwall/gjson v1.17.1 ) diff --git a/modules/vearch/go.mod b/modules/vearch/go.mod index 026ba37349..eaad237db7 100644 --- a/modules/vearch/go.mod +++ b/modules/vearch/go.mod @@ -2,7 +2,7 @@ module github.com/testcontainers/testcontainers-go/modules/vearch go 1.22.0 -require github.com/testcontainers/testcontainers-go v0.32.0 +require github.com/testcontainers/testcontainers-go v0.33.0 require ( dario.cat/mergo v1.0.0 // indirect diff --git a/modules/weaviate/go.mod b/modules/weaviate/go.mod index 83e386cdfe..d08dfc8ba2 100644 --- a/modules/weaviate/go.mod +++ b/modules/weaviate/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/weaviate go 1.21 require ( - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.33.0 github.com/weaviate/weaviate-go-client/v4 v4.13.1 google.golang.org/grpc v1.64.1 ) diff --git a/sonar-project.properties b/sonar-project.properties index d93e935f5f..aaa203e905 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -7,7 +7,7 @@ sonar.projectKey=testcontainers_testcontainers-go sonar.projectName=testcontainers-go -sonar.projectVersion=v0.32.0 +sonar.projectVersion=v0.33.0 sonar.sources=. From 0a5cd8b48894116dca45cd34b63ade1b45619755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 20 Aug 2024 13:48:13 +0200 Subject: [PATCH 045/126] chore: prepare for next minor development cycle (0.34.0) --- internal/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/version.go b/internal/version.go index 3dc9297553..0c688d5e3d 100644 --- a/internal/version.go +++ b/internal/version.go @@ -1,4 +1,4 @@ package internal // Version is the next development version of the application -const Version = "0.33.0" +const Version = "0.34.0" From 6ab11347f65a25a16c6d10b3a8c4efe230d3b6c2 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 21 Aug 2024 08:22:10 +0100 Subject: [PATCH 046/126] fix: use of log.Fatal in main (#2739) Remove use of log fatal which prevents defers. Correct order of Write and WriteHeader a update test to validate the correct behaviour, leveraging require. --- docker_test.go | 21 +++++---------------- testdata/echoserver.go | 11 +++++------ wait/testdata/main.go | 15 +++++++++++++-- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/docker_test.go b/docker_test.go index 9e6cb3fb34..f532d8650f 100644 --- a/docker_test.go +++ b/docker_test.go @@ -737,14 +737,10 @@ func TestContainerCreationWaitsForLog(t *testing.T) { } func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { - t.Log("getting ctx") ctx := context.Background() - t.Log("got ctx, creating container request") - // fromDockerfileWithBuildArgs { ba := "build args value" - req := ContainerRequest{ FromDockerfile: FromDockerfile{ Context: filepath.Join(".", "testdata"), @@ -770,23 +766,16 @@ func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { terminateContainerOnEnd(t, ctx, c) ep, err := c.Endpoint(ctx, "http") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) resp, err := http.Get(ep + "/env") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() body, err := io.ReadAll(resp.Body) - if err != nil { - t.Fatal(err) - } - - assert.Equal(t, 200, resp.StatusCode) - assert.Equal(t, ba, string(body)) + require.NoError(t, err) + require.Equal(t, http.StatusAccepted, resp.StatusCode) + require.Equal(t, ba, string(body)) } func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { diff --git a/testdata/echoserver.go b/testdata/echoserver.go index db5798699a..a62c783f5d 100644 --- a/testdata/echoserver.go +++ b/testdata/echoserver.go @@ -10,9 +10,8 @@ import ( func envHandler() http.HandlerFunc { return func(rw http.ResponseWriter, req *http.Request) { - _, _ = rw.Write([]byte(os.Getenv("FOO"))) - rw.WriteHeader(http.StatusAccepted) + rw.Write([]byte(os.Getenv("FOO"))) //nolint:errcheck // Nothing we can usefully do with the error here. } } @@ -21,9 +20,7 @@ func echoHandler(destination *os.File) http.HandlerFunc { echo := req.URL.Query()["echo"][0] l := log.New(destination, "echo ", 0) - l.Println(echo) - _ = destination.Sync() rw.WriteHeader(http.StatusAccepted) } @@ -39,10 +36,12 @@ func main() { ln, err := net.Listen("tcp", ":8080") if err != nil { - panic(err) + log.Fatal(err) } fmt.Println("ready") - _ = http.Serve(ln, mux) + if err := http.Serve(ln, mux); err != nil { + log.Fatal(err) + } } diff --git a/wait/testdata/main.go b/wait/testdata/main.go index b18008db75..f6f965fe6b 100644 --- a/wait/testdata/main.go +++ b/wait/testdata/main.go @@ -5,6 +5,7 @@ import ( "context" "encoding/base64" "errors" + "fmt" "io" "log" "net/http" @@ -15,7 +16,7 @@ import ( "time" ) -func main() { +func run() error { mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) @@ -93,5 +94,15 @@ func main() { log.Println("stopping...") ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() - _ = server.Shutdown(ctx) + if err := server.Shutdown(ctx); err != nil { + return fmt.Errorf("shutdown: %w", err) + } + + return nil +} + +func main() { + if err := run(); err != nil { + log.Fatal(err) + } } From a3b6173ca61e4df1eeaab398bbce4e88af685e05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Aug 2024 17:52:14 +0200 Subject: [PATCH 047/126] chore(deps): bump github/codeql-action from 3.24.9 to 3.25.15 (#2677) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.9 to 3.25.15. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/1b1aada464948af03b950897e5eb522f92603cc2...afb54ba388a7dca6ecae48f608c4ff05ff4cc77a) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 6 +++--- .github/workflows/scorecards.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 8919663257..5952e14d60 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -53,7 +53,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + uses: github/codeql-action/init@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -67,7 +67,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + uses: github/codeql-action/autobuild@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -80,6 +80,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + uses: github/codeql-action/analyze@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 73c657d3c4..d8b8174403 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -51,6 +51,6 @@ jobs: # required for Code scanning alerts - name: "Upload SARIF results to code scanning" - uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + uses: github/codeql-action/upload-sarif@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 with: sarif_file: results.sarif From 3682745d59deb5bc3168f6a60eece12a0a20442e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 23 Aug 2024 14:34:59 +0200 Subject: [PATCH 048/126] chore(deps): bump minimal Go version from 1.21 to 1.22 (#2743) * fix: update devcontainer image Caused by #2531 * chore: bump minimal Go version to 1.22 --- .devcontainer/devcontainer.json | 2 +- .github/workflows/ci.yml | 12 ++++++------ docs/system_requirements/ci/aws_codebuild.md | 2 +- docs/system_requirements/ci/concourse_ci.md | 2 +- docs/system_requirements/ci/dind_patterns.md | 4 ++-- docs/system_requirements/ci/gitlab_ci.md | 2 +- docs/system_requirements/ci/tekton.md | 2 +- docs/system_requirements/ci/travis.md | 2 +- examples/nginx/go.mod | 2 +- examples/toxiproxy/go.mod | 2 +- go.mod | 2 +- modulegen/_template/ci.yml.tmpl | 12 ++++++------ modulegen/go.mod | 2 +- modules/artemis/go.mod | 2 +- modules/azurite/go.mod | 2 +- modules/cassandra/go.mod | 2 +- modules/chroma/go.mod | 2 +- modules/clickhouse/go.mod | 2 +- modules/cockroachdb/go.mod | 2 +- modules/compose/go.mod | 2 +- modules/consul/go.mod | 2 +- modules/couchbase/go.mod | 2 +- modules/dolt/go.mod | 2 +- modules/elasticsearch/go.mod | 2 +- modules/gcloud/go.mod | 2 +- modules/grafana-lgtm/go.mod | 2 +- modules/inbucket/go.mod | 2 +- modules/influxdb/go.mod | 2 +- modules/k3s/go.mod | 2 +- modules/k6/go.mod | 2 +- modules/kafka/go.mod | 2 +- modules/localstack/go.mod | 2 +- modules/mariadb/go.mod | 2 +- modules/milvus/go.mod | 2 +- modules/minio/go.mod | 2 +- modules/mockserver/go.mod | 2 +- modules/mongodb/go.mod | 2 +- modules/mssql/go.mod | 2 +- modules/mysql/go.mod | 2 +- modules/nats/go.mod | 2 +- modules/neo4j/go.mod | 2 +- modules/ollama/go.mod | 2 +- modules/openfga/go.mod | 2 +- modules/openldap/go.mod | 2 +- modules/opensearch/go.mod | 2 +- modules/postgres/go.mod | 2 +- modules/pulsar/go.mod | 2 +- modules/qdrant/go.mod | 2 +- modules/rabbitmq/go.mod | 2 +- modules/redis/go.mod | 2 +- modules/redpanda/go.mod | 2 +- modules/registry/go.mod | 2 +- modules/surrealdb/go.mod | 2 +- modules/valkey/go.mod | 2 +- modules/vault/go.mod | 2 +- modules/weaviate/go.mod | 2 +- scripts/bump-go.sh | 2 +- wait/testdata/go.mod | 2 +- 58 files changed, 69 insertions(+), 69 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 731826913c..5952d31d52 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,7 +2,7 @@ // README at: https://github.com/devcontainers/templates/tree/main/src/go { "name": "Go", - "image": "mcr.microsoft.com/devcontainers/go:1.21-bookworm", + "image": "mcr.microsoft.com/devcontainers/go:1.22-bookworm", // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ca90727cb..a7f48d18dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: test: strategy: matrix: - go-version: [1.21.x, 1.x] + go-version: [1.22.x, 1.x] platform: [ubuntu-latest, macos-latest] uses: ./.github/workflows/ci-test-go.yml with: @@ -44,7 +44,7 @@ jobs: name: "Test with reaper off" strategy: matrix: - go-version: [1.21.x, 1.x] + go-version: [1.22.x, 1.x] uses: ./.github/workflows/ci-test-go.yml with: go-version: ${{ matrix.go-version }} @@ -61,7 +61,7 @@ jobs: name: "Test with Rootless Docker" strategy: matrix: - go-version: [1.21.x, 1.x] + go-version: [1.22.x, 1.x] platform: [ubuntu-latest] uses: ./.github/workflows/ci-test-go.yml with: @@ -76,7 +76,7 @@ jobs: test-module-generator: strategy: matrix: - go-version: [1.21.x, 1.x] + go-version: [1.22.x, 1.x] platform: [ubuntu-latest, macos-latest, windows-latest] uses: ./.github/workflows/ci-test-go.yml with: @@ -92,7 +92,7 @@ jobs: needs: test strategy: matrix: - go-version: [1.21.x, 1.x] + go-version: [1.22.x, 1.x] platform: [ubuntu-latest] module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, dolt, elasticsearch, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate] uses: ./.github/workflows/ci-test-go.yml @@ -112,7 +112,7 @@ jobs: module: [nginx, toxiproxy] uses: ./.github/workflows/ci-test-go.yml with: - go-version: "1.21.x" + go-version: "1.22.x" fail-fast: true platform: 'ubuntu-latest' project-directory: examples/${{ matrix.module }} diff --git a/docs/system_requirements/ci/aws_codebuild.md b/docs/system_requirements/ci/aws_codebuild.md index 1320e6bdba..a64d3691e0 100644 --- a/docs/system_requirements/ci/aws_codebuild.md +++ b/docs/system_requirements/ci/aws_codebuild.md @@ -11,7 +11,7 @@ version: 0.2 phases: install: runtime-versions: - golang: 1.21 + golang: 1.22 build: commands: - go test ./... diff --git a/docs/system_requirements/ci/concourse_ci.md b/docs/system_requirements/ci/concourse_ci.md index 2d711d3b73..ede2aac2ae 100644 --- a/docs/system_requirements/ci/concourse_ci.md +++ b/docs/system_requirements/ci/concourse_ci.md @@ -36,7 +36,7 @@ jobs: start_docker cd repo - docker run -it --rm -v "$PWD:$PWD" -w "$PWD" -v /var/run/docker.sock:/var/run/docker.sock golang:1.21 go test ./... + docker run -it --rm -v "$PWD:$PWD" -w "$PWD" -v /var/run/docker.sock:/var/run/docker.sock golang:1.22 go test ./... ``` Finally, you can use Concourse's [fly CLI](https://concourse-ci.org/fly.html) to set the pipeline and trigger the job: diff --git a/docs/system_requirements/ci/dind_patterns.md b/docs/system_requirements/ci/dind_patterns.md index 853a174d32..267a4baaf5 100644 --- a/docs/system_requirements/ci/dind_patterns.md +++ b/docs/system_requirements/ci/dind_patterns.md @@ -24,7 +24,7 @@ $ tree . └── platform └── integration_test.go -$ docker run -it --rm -v $PWD:$PWD -w $PWD -v /var/run/docker.sock:/var/run/docker.sock golang:1.21 go test ./... -v +$ docker run -it --rm -v $PWD:$PWD -w $PWD -v /var/run/docker.sock:/var/run/docker.sock golang:1.22 go test ./... -v ``` Where: @@ -45,7 +45,7 @@ The same can be achieved with Docker Compose: ```yaml tests: - image: golang:1.21 + image: golang:1.22 stop_signal: SIGKILL stdin_open: true tty: true diff --git a/docs/system_requirements/ci/gitlab_ci.md b/docs/system_requirements/ci/gitlab_ci.md index 6289dc59ae..679292a010 100644 --- a/docs/system_requirements/ci/gitlab_ci.md +++ b/docs/system_requirements/ci/gitlab_ci.md @@ -57,7 +57,7 @@ variables: DOCKER_DRIVER: overlay2 test: - image: golang:1.21 + image: golang:1.22 stage: test script: go test ./... -v ``` diff --git a/docs/system_requirements/ci/tekton.md b/docs/system_requirements/ci/tekton.md index a8280a0802..28f23f77fb 100644 --- a/docs/system_requirements/ci/tekton.md +++ b/docs/system_requirements/ci/tekton.md @@ -16,7 +16,7 @@ spec: - name: source steps: - name: read - image: golang:1.21 + image: golang:1.22 workingDir: $(workspaces.source.path) script: go test ./... -v volumeMounts: diff --git a/docs/system_requirements/ci/travis.md b/docs/system_requirements/ci/travis.md index 0701d2e367..bfc81c303d 100644 --- a/docs/system_requirements/ci/travis.md +++ b/docs/system_requirements/ci/travis.md @@ -7,7 +7,7 @@ is the minimal required config. language: go go: - 1.x -- "1.21" +- "1.22" services: - docker diff --git a/examples/nginx/go.mod b/examples/nginx/go.mod index 4a5021f85f..a6f67e793c 100644 --- a/examples/nginx/go.mod +++ b/examples/nginx/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/examples/nginx -go 1.21 +go 1.22 require github.com/testcontainers/testcontainers-go v0.33.0 diff --git a/examples/toxiproxy/go.mod b/examples/toxiproxy/go.mod index 165f9875ce..04be7036c1 100644 --- a/examples/toxiproxy/go.mod +++ b/examples/toxiproxy/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/examples/toxiproxy -go 1.21 +go 1.22 require ( github.com/Shopify/toxiproxy/v2 v2.8.0 diff --git a/go.mod b/go.mod index fd6a023cb8..678d37ec08 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go -go 1.21 +go 1.22 require ( dario.cat/mergo v1.0.0 diff --git a/modulegen/_template/ci.yml.tmpl b/modulegen/_template/ci.yml.tmpl index 616dd2bee6..4b15371337 100644 --- a/modulegen/_template/ci.yml.tmpl +++ b/modulegen/_template/ci.yml.tmpl @@ -26,7 +26,7 @@ jobs: test: strategy: matrix: - go-version: [1.21.x, 1.x] + go-version: [1.22.x, 1.x] platform: [ubuntu-latest, macos-latest] uses: ./.github/workflows/ci-test-go.yml with: @@ -44,7 +44,7 @@ jobs: name: "Test with reaper off" strategy: matrix: - go-version: [1.21.x, 1.x] + go-version: [1.22.x, 1.x] uses: ./.github/workflows/ci-test-go.yml with: go-version: {{ "${{ matrix.go-version }}" }} @@ -61,7 +61,7 @@ jobs: name: "Test with Rootless Docker" strategy: matrix: - go-version: [1.21.x, 1.x] + go-version: [1.22.x, 1.x] platform: [ubuntu-latest] uses: ./.github/workflows/ci-test-go.yml with: @@ -76,7 +76,7 @@ jobs: test-module-generator: strategy: matrix: - go-version: [1.21.x, 1.x] + go-version: [1.22.x, 1.x] platform: [ubuntu-latest, macos-latest, windows-latest] uses: ./.github/workflows/ci-test-go.yml with: @@ -92,7 +92,7 @@ jobs: needs: test strategy: matrix: - go-version: [1.21.x, 1.x] + go-version: [1.22.x, 1.x] platform: [ubuntu-latest] module: [{{ .Modules }}] uses: ./.github/workflows/ci-test-go.yml @@ -112,7 +112,7 @@ jobs: module: [{{ .Examples }}] uses: ./.github/workflows/ci-test-go.yml with: - go-version: "1.21.x" + go-version: "1.22.x" fail-fast: true platform: 'ubuntu-latest' project-directory: {{ "examples/${{ matrix.module }}" }} diff --git a/modulegen/go.mod b/modulegen/go.mod index 613a7c2791..0e66fb16d7 100644 --- a/modulegen/go.mod +++ b/modulegen/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modulegen -go 1.21 +go 1.22 require ( github.com/spf13/cobra v1.8.0 diff --git a/modules/artemis/go.mod b/modules/artemis/go.mod index 43aebbeaa8..adb9dddf08 100644 --- a/modules/artemis/go.mod +++ b/modules/artemis/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/artemis -go 1.21 +go 1.22 require ( github.com/docker/go-connections v0.5.0 diff --git a/modules/azurite/go.mod b/modules/azurite/go.mod index 63acddbb1b..826a457a9a 100644 --- a/modules/azurite/go.mod +++ b/modules/azurite/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/azurite -go 1.21 +go 1.22 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 diff --git a/modules/cassandra/go.mod b/modules/cassandra/go.mod index ded3d59600..fce3c2d919 100644 --- a/modules/cassandra/go.mod +++ b/modules/cassandra/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/cassandra -go 1.21 +go 1.22 require ( github.com/docker/go-connections v0.5.0 diff --git a/modules/chroma/go.mod b/modules/chroma/go.mod index ad2d9ed98b..2c03baa164 100644 --- a/modules/chroma/go.mod +++ b/modules/chroma/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/chroma -go 1.21 +go 1.22 require ( github.com/amikos-tech/chroma-go v0.1.2 diff --git a/modules/clickhouse/go.mod b/modules/clickhouse/go.mod index 1008f9332f..5542929f72 100644 --- a/modules/clickhouse/go.mod +++ b/modules/clickhouse/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/clickhouse -go 1.21 +go 1.22 require ( github.com/ClickHouse/clickhouse-go/v2 v2.20.0 diff --git a/modules/cockroachdb/go.mod b/modules/cockroachdb/go.mod index fd02aa4d62..d31c6f54ec 100644 --- a/modules/cockroachdb/go.mod +++ b/modules/cockroachdb/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/cockroachdb -go 1.21 +go 1.22 require ( github.com/docker/go-connections v0.5.0 diff --git a/modules/compose/go.mod b/modules/compose/go.mod index f0cfa98c94..487bdcb7d0 100644 --- a/modules/compose/go.mod +++ b/modules/compose/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/compose -go 1.21 +go 1.22 replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/consul/go.mod b/modules/consul/go.mod index c81bd4d53a..079447aa27 100644 --- a/modules/consul/go.mod +++ b/modules/consul/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/consul -go 1.21 +go 1.22 require ( github.com/hashicorp/consul/api v1.27.0 diff --git a/modules/couchbase/go.mod b/modules/couchbase/go.mod index 517ce1a474..96365d44e7 100644 --- a/modules/couchbase/go.mod +++ b/modules/couchbase/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/couchbase -go 1.21 +go 1.22 toolchain go1.21.7 diff --git a/modules/dolt/go.mod b/modules/dolt/go.mod index 201a222475..804efb8483 100644 --- a/modules/dolt/go.mod +++ b/modules/dolt/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/dolt -go 1.21 +go 1.22 require ( github.com/go-sql-driver/mysql v1.7.1 diff --git a/modules/elasticsearch/go.mod b/modules/elasticsearch/go.mod index 2d5f1adb31..a766e55dd0 100644 --- a/modules/elasticsearch/go.mod +++ b/modules/elasticsearch/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/elasticsearch -go 1.21 +go 1.22 require ( github.com/elastic/go-elasticsearch/v8 v8.12.1 diff --git a/modules/gcloud/go.mod b/modules/gcloud/go.mod index 36a70a1269..00a723f58c 100644 --- a/modules/gcloud/go.mod +++ b/modules/gcloud/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/gcloud -go 1.21 +go 1.22 require ( cloud.google.com/go/bigquery v1.59.1 diff --git a/modules/grafana-lgtm/go.mod b/modules/grafana-lgtm/go.mod index a9c73fcafe..73a94c714b 100644 --- a/modules/grafana-lgtm/go.mod +++ b/modules/grafana-lgtm/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/grafanalgtm -go 1.21 +go 1.22 require ( github.com/docker/go-connections v0.5.0 diff --git a/modules/inbucket/go.mod b/modules/inbucket/go.mod index 1188b1efc5..18939bc445 100644 --- a/modules/inbucket/go.mod +++ b/modules/inbucket/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/inbucket -go 1.21 +go 1.22 require ( github.com/inbucket/inbucket v2.0.0+incompatible diff --git a/modules/influxdb/go.mod b/modules/influxdb/go.mod index 749ba62026..f11c1de449 100644 --- a/modules/influxdb/go.mod +++ b/modules/influxdb/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/influxdb -go 1.21 +go 1.22 require ( github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c diff --git a/modules/k3s/go.mod b/modules/k3s/go.mod index fd69916dc6..da3a23fd92 100644 --- a/modules/k3s/go.mod +++ b/modules/k3s/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/k3s -go 1.21 +go 1.22 require ( github.com/docker/docker v27.1.1+incompatible diff --git a/modules/k6/go.mod b/modules/k6/go.mod index 159a74c48c..58f96d04aa 100644 --- a/modules/k6/go.mod +++ b/modules/k6/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/k6 -go 1.21 +go 1.22 require ( github.com/docker/docker v27.1.1+incompatible diff --git a/modules/kafka/go.mod b/modules/kafka/go.mod index a33d25d6c8..1148bd00f8 100644 --- a/modules/kafka/go.mod +++ b/modules/kafka/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/kafka -go 1.21 +go 1.22 require ( github.com/IBM/sarama v1.42.1 diff --git a/modules/localstack/go.mod b/modules/localstack/go.mod index 38c2f059e5..0bd92d1a01 100644 --- a/modules/localstack/go.mod +++ b/modules/localstack/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/localstack -go 1.21 +go 1.22 require ( github.com/aws/aws-sdk-go v1.50.31 diff --git a/modules/mariadb/go.mod b/modules/mariadb/go.mod index 2c0119f1b7..e8039caf58 100644 --- a/modules/mariadb/go.mod +++ b/modules/mariadb/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/mariadb -go 1.21 +go 1.22 require ( github.com/go-sql-driver/mysql v1.7.1 diff --git a/modules/milvus/go.mod b/modules/milvus/go.mod index 5de6a6c7eb..fa6fa4524d 100644 --- a/modules/milvus/go.mod +++ b/modules/milvus/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/milvus -go 1.21 +go 1.22 require ( github.com/milvus-io/milvus-sdk-go/v2 v2.3.6 diff --git a/modules/minio/go.mod b/modules/minio/go.mod index a15b25688c..c50c958c21 100644 --- a/modules/minio/go.mod +++ b/modules/minio/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/minio -go 1.21 +go 1.22 require ( github.com/minio/minio-go/v7 v7.0.68 diff --git a/modules/mockserver/go.mod b/modules/mockserver/go.mod index 81cb5a9d0c..e2ba76d72d 100644 --- a/modules/mockserver/go.mod +++ b/modules/mockserver/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/mockserver -go 1.21 +go 1.22 require ( github.com/BraspagDevelopers/mock-server-client v0.2.2 diff --git a/modules/mongodb/go.mod b/modules/mongodb/go.mod index 9756c3f722..e7e8c724bc 100644 --- a/modules/mongodb/go.mod +++ b/modules/mongodb/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/mongodb -go 1.21 +go 1.22 require ( github.com/testcontainers/testcontainers-go v0.33.0 diff --git a/modules/mssql/go.mod b/modules/mssql/go.mod index 5b36d98189..83411fb7aa 100644 --- a/modules/mssql/go.mod +++ b/modules/mssql/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/mssql -go 1.21 +go 1.22 require ( github.com/microsoft/go-mssqldb v1.7.0 diff --git a/modules/mysql/go.mod b/modules/mysql/go.mod index 1366d35491..f3f00dcb8b 100644 --- a/modules/mysql/go.mod +++ b/modules/mysql/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/mysql -go 1.21 +go 1.22 require ( github.com/go-sql-driver/mysql v1.7.1 diff --git a/modules/nats/go.mod b/modules/nats/go.mod index 4163f8ba83..0a4863c41e 100644 --- a/modules/nats/go.mod +++ b/modules/nats/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/nats -go 1.21 +go 1.22 require ( github.com/nats-io/nats.go v1.33.1 diff --git a/modules/neo4j/go.mod b/modules/neo4j/go.mod index e63e2854a3..13f310eeb5 100644 --- a/modules/neo4j/go.mod +++ b/modules/neo4j/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/neo4j -go 1.21 +go 1.22 require ( github.com/docker/go-connections v0.5.0 diff --git a/modules/ollama/go.mod b/modules/ollama/go.mod index 8dc279da02..5e586e858e 100644 --- a/modules/ollama/go.mod +++ b/modules/ollama/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/ollama -go 1.21 +go 1.22 require ( github.com/docker/docker v27.1.1+incompatible diff --git a/modules/openfga/go.mod b/modules/openfga/go.mod index 6aa77ede7c..388b9c040c 100644 --- a/modules/openfga/go.mod +++ b/modules/openfga/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/openfga -go 1.21 +go 1.22 require ( github.com/openfga/go-sdk v0.3.5 diff --git a/modules/openldap/go.mod b/modules/openldap/go.mod index e6477cb0a6..2f13ed78cc 100644 --- a/modules/openldap/go.mod +++ b/modules/openldap/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/openldap -go 1.21 +go 1.22 require ( github.com/go-ldap/ldap/v3 v3.4.6 diff --git a/modules/opensearch/go.mod b/modules/opensearch/go.mod index 721eb1f292..50146f5964 100644 --- a/modules/opensearch/go.mod +++ b/modules/opensearch/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/opensearch -go 1.21 +go 1.22 require ( github.com/docker/docker v27.1.1+incompatible diff --git a/modules/postgres/go.mod b/modules/postgres/go.mod index 45d18c23f0..4b57997260 100644 --- a/modules/postgres/go.mod +++ b/modules/postgres/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/postgres -go 1.21 +go 1.22 require ( github.com/docker/go-connections v0.5.0 diff --git a/modules/pulsar/go.mod b/modules/pulsar/go.mod index 19b896c1da..b9e77f4d58 100644 --- a/modules/pulsar/go.mod +++ b/modules/pulsar/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/pulsar -go 1.21 +go 1.22 require ( github.com/apache/pulsar-client-go v0.10.0 diff --git a/modules/qdrant/go.mod b/modules/qdrant/go.mod index e9e031e284..85db7229b3 100644 --- a/modules/qdrant/go.mod +++ b/modules/qdrant/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/qdrant -go 1.21 +go 1.22 require ( github.com/qdrant/go-client v1.7.0 diff --git a/modules/rabbitmq/go.mod b/modules/rabbitmq/go.mod index d7906746d0..e9d4a267fa 100644 --- a/modules/rabbitmq/go.mod +++ b/modules/rabbitmq/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/rabbitmq -go 1.21 +go 1.22 require ( github.com/docker/go-connections v0.5.0 diff --git a/modules/redis/go.mod b/modules/redis/go.mod index db7d207002..e76c925c7e 100644 --- a/modules/redis/go.mod +++ b/modules/redis/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/redis -go 1.21 +go 1.22 require ( github.com/go-redis/redis/v8 v8.11.5 diff --git a/modules/redpanda/go.mod b/modules/redpanda/go.mod index 8a780fca54..4ce12872ee 100644 --- a/modules/redpanda/go.mod +++ b/modules/redpanda/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/redpanda -go 1.21 +go 1.22 require ( github.com/docker/go-connections v0.5.0 diff --git a/modules/registry/go.mod b/modules/registry/go.mod index b1d844515d..36e95dfdf0 100644 --- a/modules/registry/go.mod +++ b/modules/registry/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/registry -go 1.21 +go 1.22 require ( github.com/cpuguy83/dockercfg v0.3.1 diff --git a/modules/surrealdb/go.mod b/modules/surrealdb/go.mod index 80db8eccc6..d3d2d049d6 100644 --- a/modules/surrealdb/go.mod +++ b/modules/surrealdb/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/surrealdb -go 1.21 +go 1.22 require ( github.com/surrealdb/surrealdb.go v0.2.1 diff --git a/modules/valkey/go.mod b/modules/valkey/go.mod index 220069fea0..0c1173f987 100644 --- a/modules/valkey/go.mod +++ b/modules/valkey/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/valkey -go 1.21 +go 1.22 require ( github.com/google/uuid v1.6.0 diff --git a/modules/vault/go.mod b/modules/vault/go.mod index 5cdd22209a..064a23bcce 100644 --- a/modules/vault/go.mod +++ b/modules/vault/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/vault -go 1.21 +go 1.22 require ( github.com/docker/docker v27.1.1+incompatible diff --git a/modules/weaviate/go.mod b/modules/weaviate/go.mod index d08dfc8ba2..6572fb3607 100644 --- a/modules/weaviate/go.mod +++ b/modules/weaviate/go.mod @@ -1,6 +1,6 @@ module github.com/testcontainers/testcontainers-go/modules/weaviate -go 1.21 +go 1.22 require ( github.com/testcontainers/testcontainers-go v0.33.0 diff --git a/scripts/bump-go.sh b/scripts/bump-go.sh index 7b949ee89b..5ff33a5e6e 100755 --- a/scripts/bump-go.sh +++ b/scripts/bump-go.sh @@ -21,7 +21,7 @@ readonly CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" readonly DRY_RUN="${DRY_RUN:-true}" readonly ROOT_DIR="$(dirname "$CURRENT_DIR")" readonly GO_MOD_FILE="${ROOT_DIR}/go.mod" -readonly DEVCONTAINER_IMAGE_PREFIX="go:0-" +readonly DEVCONTAINER_IMAGE_PREFIX="go:" function main() { echo "Updating Go version:" diff --git a/wait/testdata/go.mod b/wait/testdata/go.mod index 0b51175838..ab1b280416 100644 --- a/wait/testdata/go.mod +++ b/wait/testdata/go.mod @@ -1,3 +1,3 @@ module httptest -go 1.21 +go 1.22 From 5245aa853b91455d9f20cbdcd5d259a28d700aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 27 Aug 2024 10:33:39 +0200 Subject: [PATCH 049/126] chore: use new testcontainers/ryuk:0.9.0 image (#2750) --- internal/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/config/config.go b/internal/config/config.go index f1d702ec36..a172fa3a16 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -11,7 +11,7 @@ import ( "github.com/magiconair/properties" ) -const ReaperDefaultImage = "testcontainers/ryuk:0.8.1" +const ReaperDefaultImage = "testcontainers/ryuk:0.9.0" var ( tcConfig Config From 0d9e934ec7f62a1e164f7ce4f7560fa5c6b97d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Duarte?= Date: Tue, 27 Aug 2024 14:02:59 +0100 Subject: [PATCH 050/126] Fix trailing slash on Image Prefix (#2747) * Fix trailing slash on Image Prefix * Apply Lint fix --- docker_test.go | 27 +++++++++++++++++++++++++++ options.go | 15 +++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/docker_test.go b/docker_test.go index f532d8650f..402d944dce 100644 --- a/docker_test.go +++ b/docker_test.go @@ -2280,3 +2280,30 @@ func TestDockerProvider_attemptToPullImage_retries(t *testing.T) { }) } } + +func TestCustomPrefixTrailingSlashIsProperlyRemovedIfPresent(t *testing.T) { + hubPrefixWithTrailingSlash := "public.ecr.aws/" + dockerImage := "amazonlinux/amazonlinux:2023" + + ctx := context.Background() + req := ContainerRequest{ + Image: dockerImage, + ImageSubstitutors: []ImageSubstitutor{newPrependHubRegistry(hubPrefixWithTrailingSlash)}, + } + + c, err := GenericContainer(ctx, GenericContainerRequest{ + ContainerRequest: req, + Started: true, + }) + if err != nil { + t.Fatal(err) + } + defer func() { + terminateContainerOnEnd(t, ctx, c) + }() + + // enforce the concrete type, as GenericContainer returns an interface, + // which will be changed in future implementations of the library + dockerContainer := c.(*DockerContainer) + assert.Equal(t, fmt.Sprintf("%s%s", hubPrefixWithTrailingSlash, dockerImage), dockerContainer.Image) +} diff --git a/options.go b/options.go index 6b5dcb1293..2849b15667 100644 --- a/options.go +++ b/options.go @@ -3,6 +3,7 @@ package testcontainers import ( "context" "fmt" + "net/url" "time" "dario.cat/mergo" @@ -155,7 +156,12 @@ func (c CustomHubSubstitutor) Substitute(image string) (string, error) { } } - return fmt.Sprintf("%s/%s", c.hub, image), nil + result, err := url.JoinPath(c.hub, image) + if err != nil { + return "", err + } + + return result, nil } // prependHubRegistry represents a way to prepend a custom Hub registry to the image name, @@ -198,7 +204,12 @@ func (p prependHubRegistry) Substitute(image string) (string, error) { } } - return fmt.Sprintf("%s/%s", p.prefix, image), nil + result, err := url.JoinPath(p.prefix, image) + if err != nil { + return "", err + } + + return result, nil } // WithImageSubstitutors sets the image substitutors for a container From ef4243e86bfecf4197be0ae4dfcda2fb8a8350bd Mon Sep 17 00:00:00 2001 From: HappyHacker123 <149483443+HappyHacker123@users.noreply.github.com> Date: Thu, 29 Aug 2024 00:24:30 +0800 Subject: [PATCH 051/126] Upgrade milvus-io/milvus-sdk-go to avoid checksum mismatch. (#2753) * Upgrade milvus-io/milvus-sdk-go to avoid checksum mismatch. * Update go.sum * Update indirect dependencies. --- modules/milvus/go.mod | 4 ++-- modules/milvus/go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/milvus/go.mod b/modules/milvus/go.mod index fa6fa4524d..1b60fe8cf7 100644 --- a/modules/milvus/go.mod +++ b/modules/milvus/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/milvus go 1.22 require ( - github.com/milvus-io/milvus-sdk-go/v2 v2.3.6 + github.com/milvus-io/milvus-sdk-go/v2 v2.4.0 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.33.0 ) @@ -39,7 +39,7 @@ require ( github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/milvus-io/milvus-proto/go-api/v2 v2.3.5 // indirect + github.com/milvus-io/milvus-proto/go-api/v2 v2.4.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect diff --git a/modules/milvus/go.sum b/modules/milvus/go.sum index cba09d80d3..f8cd7dcf33 100644 --- a/modules/milvus/go.sum +++ b/modules/milvus/go.sum @@ -195,10 +195,10 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= -github.com/milvus-io/milvus-proto/go-api/v2 v2.3.5 h1:4XDy6ATB2Z0fl4Jn0hS6BT6/8YaE0d+ZUf4uBH+Z0Do= -github.com/milvus-io/milvus-proto/go-api/v2 v2.3.5/go.mod h1:1OIl0v5PQeNxIJhCvY+K55CBUOYDZevw9g9380u1Wek= -github.com/milvus-io/milvus-sdk-go/v2 v2.3.6 h1:JVn9OdaronLGmtpxvamQf523mtn3Z/CRxkSZCMWutV4= -github.com/milvus-io/milvus-sdk-go/v2 v2.3.6/go.mod h1:bYFSXVxEj6A/T8BfiR+xkofKbAVZpWiDvKr3SzYUWiA= +github.com/milvus-io/milvus-proto/go-api/v2 v2.4.0 h1:9KsyZR+neMlRvV52C5sIsLB13jthT2AY/+buyiNjcCg= +github.com/milvus-io/milvus-proto/go-api/v2 v2.4.0/go.mod h1:1OIl0v5PQeNxIJhCvY+K55CBUOYDZevw9g9380u1Wek= +github.com/milvus-io/milvus-sdk-go/v2 v2.4.0 h1:llESmiYiaFqRh0CUrZCLH0IWWkk5r8/vz0tkaA0YzQo= +github.com/milvus-io/milvus-sdk-go/v2 v2.4.0/go.mod h1:8IKyxVV+kd+RADMuMpo8GXnTDq5ZxrSSWpe9nJieboQ= 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/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= From c6d8a6c5f5a0a9c83f4cf60b16d1b98461f7c4ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 28 Aug 2024 20:40:45 +0200 Subject: [PATCH 052/126] fix: check if the discovered docker socket responds (#2741) * fix: check if the discovered docker socket responds * fix: update tests * chore: add test * Revert "chore: add test" This reverts commit c6c4832a78138890cfd52543f3658a8d5ee62fd9. * Revert "fix: update tests" This reverts commit fbadada0697c9ac3c69049b77c68e4e231a507fb. * Revert "fix: check if the discovered docker socket responds" This reverts commit 19fb55bcf1f906655a6cbd5d64b8bb297a996b1a. * chore: support passing callback checks to the docker host/socket path resolution This way the tests are able to verify if the socket/host is reachable by calling a mock client. The production code will use the default callback check, which calls a vanilla docker client using the discovered host as host * chore: convert var into function * chore: mock callback check instead * chore: simplify * chore: raise error when extracting the docker host * docs: document that the extract functions panics * chore: simplify error handler * chore: use require.Panics * fix: remove duplicated case * fix: negotiate API version in the plain docker client call * fix: defer closing the client earlier * chore: better function name * chore: convert vars into functions * chore: no need to assert as panic should occur * chor: rename check function * chore: pass ctx to new function * chore: more exhaustive error check in tests * docs: typo * fix: update usage --- docker_client.go | 4 +- docs/features/configuration.md | 4 +- image_test.go | 4 +- internal/core/client.go | 2 +- internal/core/docker_host.go | 89 +++++++++++++--- internal/core/docker_host_test.go | 145 ++++++++++++++++++-------- internal/core/docker_rootless.go | 12 ++- internal/core/docker_rootless_test.go | 8 +- modules/localstack/localstack.go | 2 +- provider.go | 2 +- provider_test.go | 2 +- reaper.go | 2 +- reaper_test.go | 4 +- testcontainers.go | 15 ++- 14 files changed, 205 insertions(+), 90 deletions(-) diff --git a/docker_client.go b/docker_client.go index c8e8e825b0..04df712916 100644 --- a/docker_client.go +++ b/docker_client.go @@ -79,8 +79,8 @@ func (c *DockerClient) Info(ctx context.Context) (system.Info, error) { dockerInfo.OperatingSystem, dockerInfo.MemTotal/1024/1024, infoLabels, internal.Version, - core.ExtractDockerHost(ctx), - core.ExtractDockerSocket(ctx), + core.MustExtractDockerHost(ctx), + core.MustExtractDockerSocket(ctx), core.SessionID(), core.ProcessID(), ) diff --git a/docs/features/configuration.md b/docs/features/configuration.md index aa5a0d0a61..ee5b6a4d69 100644 --- a/docs/features/configuration.md +++ b/docs/features/configuration.md @@ -85,7 +85,7 @@ See [Docker environment variables](https://docs.docker.com/engine/reference/comm 3. `${HOME}/.docker/desktop/docker.sock`. 4. `/run/user/${UID}/docker.sock`, where `${UID}` is the user ID of the current user. -7. The default Docker socket including schema will be returned if none of the above are set. +7. The library panics if none of the above are set, meaning that the Docker host was not detected. ## Docker socket path detection @@ -109,4 +109,4 @@ Path to Docker's socket. Used by Ryuk, Docker Compose, and a few other container 6. Else, the default location of the docker socket is used: `/var/run/docker.sock` -In any case, if the docker socket schema is `tcp://`, the default docker socket path will be returned. +The library panics if the Docker host cannot be discovered. diff --git a/image_test.go b/image_test.go index 17595b6590..795a521b29 100644 --- a/image_test.go +++ b/image_test.go @@ -10,7 +10,7 @@ import ( ) func TestImageList(t *testing.T) { - t.Setenv("DOCKER_HOST", core.ExtractDockerHost(context.Background())) + t.Setenv("DOCKER_HOST", core.MustExtractDockerHost(context.Background())) provider, err := ProviderDocker.GetProvider() if err != nil { @@ -54,7 +54,7 @@ func TestImageList(t *testing.T) { } func TestSaveImages(t *testing.T) { - t.Setenv("DOCKER_HOST", core.ExtractDockerHost(context.Background())) + t.Setenv("DOCKER_HOST", core.MustExtractDockerHost(context.Background())) provider, err := ProviderDocker.GetProvider() if err != nil { diff --git a/internal/core/client.go b/internal/core/client.go index 64af509b9f..04a54bcbc5 100644 --- a/internal/core/client.go +++ b/internal/core/client.go @@ -14,7 +14,7 @@ import ( func NewClient(ctx context.Context, ops ...client.Opt) (*client.Client, error) { tcConfig := config.Read() - dockerHost := ExtractDockerHost(ctx) + dockerHost := MustExtractDockerHost(ctx) opts := []client.Opt{client.FromEnv, client.WithAPIVersionNegotiation()} if dockerHost != "" { diff --git a/internal/core/docker_host.go b/internal/core/docker_host.go index b9d2d60d51..3088a3742b 100644 --- a/internal/core/docker_host.go +++ b/internal/core/docker_host.go @@ -56,7 +56,24 @@ func DefaultGatewayIP() (string, error) { return ip, nil } -// ExtractDockerHost Extracts the docker host from the different alternatives, caching the result to avoid unnecessary +// dockerHostCheck Use a vanilla Docker client to check if the Docker host is reachable. +// It will avoid recursive calls to this function. +var dockerHostCheck = func(ctx context.Context, host string) error { + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithHost(host), client.WithAPIVersionNegotiation()) + if err != nil { + return fmt.Errorf("new client: %w", err) + } + defer cli.Close() + + _, err = cli.Info(ctx) + if err != nil { + return fmt.Errorf("docker info: %w", err) + } + + return nil +} + +// MustExtractDockerHost Extracts the docker host from the different alternatives, caching the result to avoid unnecessary // calculations. Use this function to get the actual Docker host. This function does not consider Windows containers at the moment. // The possible alternatives are: // @@ -66,16 +83,21 @@ func DefaultGatewayIP() (string, error) { // 4. Docker host from the default docker socket path, without the unix schema. // 5. Docker host from the "docker.host" property in the ~/.testcontainers.properties file. // 6. Rootless docker socket path. -// 7. Else, the default Docker socket including schema will be returned. -func ExtractDockerHost(ctx context.Context) string { +// 7. Else, because the Docker host is not set, it panics. +func MustExtractDockerHost(ctx context.Context) string { dockerHostOnce.Do(func() { - dockerHostCache = extractDockerHost(ctx) + cache, err := extractDockerHost(ctx) + if err != nil { + panic(err) + } + + dockerHostCache = cache }) return dockerHostCache } -// ExtractDockerSocket Extracts the docker socket from the different alternatives, removing the socket schema and +// MustExtractDockerSocket Extracts the docker socket from the different alternatives, removing the socket schema and // caching the result to avoid unnecessary calculations. Use this function to get the docker socket path, // not the host (e.g. mounting the socket in a container). This function does not consider Windows containers at the moment. // The possible alternatives are: @@ -83,12 +105,12 @@ func ExtractDockerHost(ctx context.Context) string { // 1. Docker host from the "tc.host" property in the ~/.testcontainers.properties file. // 2. The TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE environment variable. // 3. Using a Docker client, check if the Info().OperativeSystem is "Docker Desktop" and return the default docker socket path for rootless docker. -// 4. Else, Get the current Docker Host from the existing strategies: see ExtractDockerHost. +// 4. Else, Get the current Docker Host from the existing strategies: see MustExtractDockerHost. // 5. If the socket contains the unix schema, the schema is removed (e.g. unix:///var/run/docker.sock -> /var/run/docker.sock) // 6. Else, the default location of the docker socket is used (/var/run/docker.sock) // -// In any case, if the docker socket schema is "tcp://", the default docker socket path will be returned. -func ExtractDockerSocket(ctx context.Context) string { +// It panics if a Docker client cannot be created, or the Docker host cannot be discovered. +func MustExtractDockerSocket(ctx context.Context) string { dockerSocketPathOnce.Do(func() { dockerSocketPathCache = extractDockerSocket(ctx) }) @@ -98,7 +120,7 @@ func ExtractDockerSocket(ctx context.Context) string { // extractDockerHost Extracts the docker host from the different alternatives, without caching the result. // This internal method is handy for testing purposes. -func extractDockerHost(ctx context.Context) string { +func extractDockerHost(ctx context.Context) (string, error) { dockerHostFns := []func(context.Context) (string, error){ testcontainersHostFromProperties, dockerHostFromEnv, @@ -108,25 +130,35 @@ func extractDockerHost(ctx context.Context) string { rootlessDockerSocketPath, } - outerErr := ErrSocketNotFound + var errs []error for _, dockerHostFn := range dockerHostFns { dockerHost, err := dockerHostFn(ctx) if err != nil { - outerErr = fmt.Errorf("%w: %w", outerErr, err) + if !isHostNotSet(err) { + errs = append(errs, err) + } continue } - return dockerHost + if err = dockerHostCheck(ctx, dockerHost); err != nil { + errs = append(errs, fmt.Errorf("check host %q: %w", dockerHost, err)) + continue + } + + return dockerHost, nil } - // We are not supporting Windows containers at the moment - return DockerSocketPathWithSchema + if len(errs) > 0 { + return "", errors.Join(errs...) + } + + return "", ErrSocketNotFound } -// extractDockerHost Extracts the docker socket from the different alternatives, without caching the result. +// extractDockerSocket Extracts the docker socket from the different alternatives, without caching the result. // It will internally use the default Docker client, calling the internal method extractDockerSocketFromClient with it. // This internal method is handy for testing purposes. -// If a Docker client cannot be created, the program will panic. +// It panics if a Docker client cannot be created, or the Docker host is not discovered. func extractDockerSocket(ctx context.Context) string { cli, err := NewClient(ctx) if err != nil { @@ -140,6 +172,7 @@ func extractDockerSocket(ctx context.Context) string { // extractDockerSocketFromClient Extracts the docker socket from the different alternatives, without caching the result, // and receiving an instance of the Docker API client interface. // This internal method is handy for testing purposes, passing a mock type simulating the desired behaviour. +// It panics if the Docker Info call errors, or the Docker host is not discovered. func extractDockerSocketFromClient(ctx context.Context, cli client.APIClient) string { // check that the socket is not a tcp or unix socket checkDockerSocketFn := func(socket string) string { @@ -179,11 +212,33 @@ func extractDockerSocketFromClient(ctx context.Context, cli client.APIClient) st return DockerSocketPath } - dockerHost := extractDockerHost(ctx) + dockerHost, err := extractDockerHost(ctx) + if err != nil { + panic(err) // Docker host is required to get the Docker socket + } return checkDockerSocketFn(dockerHost) } +// isHostNotSet returns true if the error is related to the Docker host +// not being set, false otherwise. +func isHostNotSet(err error) bool { + switch { + case errors.Is(err, ErrTestcontainersHostNotSetInProperties), + errors.Is(err, ErrDockerHostNotSet), + errors.Is(err, ErrDockerSocketNotSetInContext), + errors.Is(err, ErrDockerSocketNotSetInProperties), + errors.Is(err, ErrSocketNotFoundInPath), + errors.Is(err, ErrXDGRuntimeDirNotSet), + errors.Is(err, ErrRootlessDockerNotFoundHomeRunDir), + errors.Is(err, ErrRootlessDockerNotFoundHomeDesktopDir), + errors.Is(err, ErrRootlessDockerNotFoundRunDir): + return true + default: + return false + } +} + // dockerHostFromEnv returns the docker host from the DOCKER_HOST environment variable, if it's not empty func dockerHostFromEnv(ctx context.Context) (string, error) { if dockerHostPath := os.Getenv("DOCKER_HOST"); dockerHostPath != "" { diff --git a/internal/core/docker_host_test.go b/internal/core/docker_host_test.go index 23d8e1e1fa..eceee573fc 100644 --- a/internal/core/docker_host_test.go +++ b/internal/core/docker_host_test.go @@ -2,6 +2,7 @@ package core import ( "context" + "fmt" "os" "path/filepath" "testing" @@ -40,6 +41,22 @@ var resetSocketOverrideFn = func() { os.Setenv("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE", originalDockerSocketOverride) } +func testCallbackCheckPassing(_ context.Context, _ string) error { + return nil +} + +func testCallbackCheckError(_ context.Context, _ string) error { + return fmt.Errorf("could not check the Docker host") +} + +func mockCallbackCheck(t *testing.T, fn func(_ context.Context, _ string) error) { + oldCheck := dockerHostCheck + dockerHostCheck = fn + t.Cleanup(func() { + dockerHostCheck = oldCheck + }) +} + func TestExtractDockerHost(t *testing.T) { setupDockerHostNotFound(t) // do not mess with local .testcontainers.properties @@ -47,17 +64,21 @@ func TestExtractDockerHost(t *testing.T) { t.Setenv("HOME", tmpDir) t.Setenv("USERPROFILE", tmpDir) // Windows support - t.Run("Docker Host as extracted just once", func(t *testing.T) { + // apply the passing check to all sub-tests + mockCallbackCheck(t, testCallbackCheckPassing) + + t.Run("Docker Host is extracted just once", func(t *testing.T) { expected := "/path/to/docker.sock" t.Setenv("DOCKER_HOST", expected) - host := ExtractDockerHost(context.Background()) + + host := MustExtractDockerHost(context.Background()) assert.Equal(t, expected, host) t.Setenv("DOCKER_HOST", "/path/to/another/docker.sock") - host = ExtractDockerHost(context.Background()) - assert.Equal(t, expected, host) + host = MustExtractDockerHost(context.Background()) + require.Equal(t, expected, host) }) t.Run("Testcontainers Host is resolved first", func(t *testing.T) { @@ -66,16 +87,30 @@ func TestExtractDockerHost(t *testing.T) { setupTestcontainersProperties(t, content) - host := extractDockerHost(context.Background()) + host, err := extractDockerHost(context.Background()) + require.NoError(t, err) + require.Equal(t, testRemoteHost, host) + }) + + t.Run("Testcontainers Host is resolved first but not reachable", func(t *testing.T) { + t.Setenv("DOCKER_HOST", "/path/to/docker.sock") + content := "tc.host=" + testRemoteHost - assert.Equal(t, testRemoteHost, host) + setupTestcontainersProperties(t, content) + + // mock the callback check to return an error + mockCallbackCheck(t, testCallbackCheckError) + + host, err := extractDockerHost(context.Background()) + require.Error(t, err) + require.Equal(t, "", host) }) t.Run("Docker Host as environment variable", func(t *testing.T) { t.Setenv("DOCKER_HOST", "/path/to/docker.sock") - host := extractDockerHost(context.Background()) - - assert.Equal(t, "/path/to/docker.sock", host) + host, err := extractDockerHost(context.Background()) + require.NoError(t, err) + require.Equal(t, "/path/to/docker.sock", host) }) t.Run("Malformed Docker Host is passed in context", func(t *testing.T) { @@ -84,9 +119,9 @@ func TestExtractDockerHost(t *testing.T) { ctx := context.Background() - host := extractDockerHost(context.WithValue(ctx, DockerHostContextKey, "path-to-docker-sock")) - - assert.Equal(t, DockerSocketPathWithSchema, host) + host, err := extractDockerHost(context.WithValue(ctx, DockerHostContextKey, "path-to-docker-sock")) + require.Error(t, err) + require.Equal(t, "", host) }) t.Run("Malformed Schema Docker Host is passed in context", func(t *testing.T) { @@ -94,17 +129,17 @@ func TestExtractDockerHost(t *testing.T) { setupRootlessNotFound(t) ctx := context.Background() - host := extractDockerHost(context.WithValue(ctx, DockerHostContextKey, "http://path to docker sock")) - - assert.Equal(t, DockerSocketPathWithSchema, host) + host, err := extractDockerHost(context.WithValue(ctx, DockerHostContextKey, "http://path to docker sock")) + require.Error(t, err) + require.Equal(t, "", host) }) t.Run("Unix Docker Host is passed in context", func(t *testing.T) { ctx := context.Background() - host := extractDockerHost(context.WithValue(ctx, DockerHostContextKey, DockerSocketSchema+"/this/is/a/sample.sock")) - - assert.Equal(t, "/this/is/a/sample.sock", host) + host, err := extractDockerHost(context.WithValue(ctx, DockerHostContextKey, DockerSocketSchema+"/this/is/a/sample.sock")) + require.NoError(t, err) + require.Equal(t, "/this/is/a/sample.sock", host) }) t.Run("Unix Docker Host is passed as docker.host", func(t *testing.T) { @@ -114,26 +149,26 @@ func TestExtractDockerHost(t *testing.T) { setupTestcontainersProperties(t, content) - host := extractDockerHost(context.Background()) - - assert.Equal(t, DockerSocketSchema+"/this/is/a/sample.sock", host) + host, err := extractDockerHost(context.Background()) + require.NoError(t, err) + require.Equal(t, DockerSocketSchema+"/this/is/a/sample.sock", host) }) t.Run("Default Docker socket", func(t *testing.T) { setupRootlessNotFound(t) tmpSocket := setupDockerSocket(t) - host := extractDockerHost(context.Background()) - - assert.Equal(t, tmpSocket, host) + host, err := extractDockerHost(context.Background()) + require.NoError(t, err) + require.Equal(t, tmpSocket, host) }) - t.Run("Default Docker Host when empty", func(t *testing.T) { + t.Run("Error when empty", func(t *testing.T) { setupDockerSocketNotFound(t) setupRootlessNotFound(t) - host := extractDockerHost(context.Background()) - - assert.Equal(t, DockerSocketPathWithSchema, host) + host, err := extractDockerHost(context.Background()) + require.Error(t, err) + require.Equal(t, "", host) }) t.Run("Extract Docker socket", func(t *testing.T) { @@ -147,7 +182,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := testcontainersHostFromProperties(context.Background()) require.NoError(t, err) - assert.Equal(t, testRemoteHost, socket) + require.Equal(t, testRemoteHost, socket) }) t.Run("Testcontainers host is not defined in properties", func(t *testing.T) { @@ -169,7 +204,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := dockerHostFromEnv(context.Background()) require.NoError(t, err) - assert.Equal(t, tmpSocket, socket) + require.Equal(t, tmpSocket, socket) }) t.Run("DOCKER_HOST is not set", func(t *testing.T) { @@ -191,7 +226,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := dockerSocketOverridePath() require.NoError(t, err) - assert.Equal(t, tmpSocket, socket) + require.Equal(t, tmpSocket, socket) }) t.Run("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE is not set", func(t *testing.T) { @@ -209,7 +244,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := dockerHostFromContext(context.WithValue(ctx, DockerHostContextKey, DockerSocketSchema+"/this/is/a/sample.sock")) require.NoError(t, err) - assert.Equal(t, "/this/is/a/sample.sock", socket) + require.Equal(t, "/this/is/a/sample.sock", socket) }) t.Run("Context sets a malformed Docker socket", func(t *testing.T) { @@ -233,7 +268,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := dockerSocketPath(context.Background()) require.NoError(t, err) - assert.Equal(t, tmpSocket, socket) + require.Equal(t, tmpSocket, socket) }) t.Run("Docker host is defined in properties", func(t *testing.T) { @@ -244,7 +279,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := dockerHostFromProperties(context.Background()) require.NoError(t, err) - assert.Equal(t, tmpSocket, socket) + require.Equal(t, tmpSocket, socket) }) t.Run("Docker host is not defined in properties", func(t *testing.T) { @@ -285,13 +320,15 @@ func (m mockCli) Info(ctx context.Context) (system.Info, error) { func TestExtractDockerSocketFromClient(t *testing.T) { setupDockerHostNotFound(t) + mockCallbackCheck(t, testCallbackCheckPassing) + t.Run("Docker socket from Testcontainers host defined in properties", func(t *testing.T) { content := "tc.host=" + testRemoteHost setupTestcontainersProperties(t, content) socket := extractDockerSocketFromClient(context.Background(), mockCli{OS: "foo"}) - assert.Equal(t, DockerSocketPath, socket) + require.Equal(t, DockerSocketPath, socket) }) t.Run("Docker socket from Testcontainers host takes precedence over TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE", func(t *testing.T) { @@ -303,7 +340,7 @@ func TestExtractDockerSocketFromClient(t *testing.T) { t.Setenv("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE", "/path/to/docker.sock") socket := extractDockerSocketFromClient(context.Background(), mockCli{OS: "foo"}) - assert.Equal(t, DockerSocketPath, socket) + require.Equal(t, DockerSocketPath, socket) }) t.Run("Docker Socket as Testcontainers environment variable", func(t *testing.T) { @@ -314,7 +351,7 @@ func TestExtractDockerSocketFromClient(t *testing.T) { t.Setenv("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE", "/path/to/docker.sock") host := extractDockerSocketFromClient(context.Background(), mockCli{OS: "foo"}) - assert.Equal(t, "/path/to/docker.sock", host) + require.Equal(t, "/path/to/docker.sock", host) }) t.Run("Docker Socket as Testcontainers environment variable, removes prefixes", func(t *testing.T) { @@ -324,11 +361,11 @@ func TestExtractDockerSocketFromClient(t *testing.T) { t.Setenv("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE", DockerSocketSchema+"/path/to/docker.sock") host := extractDockerSocketFromClient(context.Background(), mockCli{OS: "foo"}) - assert.Equal(t, "/path/to/docker.sock", host) + require.Equal(t, "/path/to/docker.sock", host) t.Setenv("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE", testRemoteHost) host = extractDockerSocketFromClient(context.Background(), mockCli{OS: "foo"}) - assert.Equal(t, DockerSocketPath, host) + require.Equal(t, DockerSocketPath, host) }) t.Run("Unix Docker Socket is passed as DOCKER_HOST variable (Docker Desktop on non-Windows)", func(t *testing.T) { @@ -347,7 +384,7 @@ func TestExtractDockerSocketFromClient(t *testing.T) { socket := extractDockerSocketFromClient(ctx, mockCli{OS: "Docker Desktop"}) - assert.Equal(t, DockerSocketPath, socket) + require.Equal(t, DockerSocketPath, socket) }) t.Run("Unix Docker Socket is passed as DOCKER_HOST variable (Docker Desktop for Windows)", func(t *testing.T) { @@ -362,7 +399,7 @@ func TestExtractDockerSocketFromClient(t *testing.T) { socket := extractDockerSocketFromClient(ctx, mockCli{OS: "Docker Desktop"}) - assert.Equal(t, WindowsDockerSocketPath, socket) + require.Equal(t, WindowsDockerSocketPath, socket) }) t.Run("Unix Docker Socket is passed as DOCKER_HOST variable (Not Docker Desktop)", func(t *testing.T) { @@ -376,7 +413,7 @@ func TestExtractDockerSocketFromClient(t *testing.T) { socket := extractDockerSocketFromClient(ctx, mockCli{OS: "Ubuntu"}) - assert.Equal(t, "/this/is/a/sample.sock", socket) + require.Equal(t, "/this/is/a/sample.sock", socket) }) t.Run("Unix Docker Socket is passed as DOCKER_HOST variable (Not Docker Desktop), removes prefixes", func(t *testing.T) { @@ -389,11 +426,11 @@ func TestExtractDockerSocketFromClient(t *testing.T) { t.Setenv("DOCKER_HOST", DockerSocketSchema+"/this/is/a/sample.sock") socket := extractDockerSocketFromClient(ctx, mockCli{OS: "Ubuntu"}) - assert.Equal(t, "/this/is/a/sample.sock", socket) + require.Equal(t, "/this/is/a/sample.sock", socket) t.Setenv("DOCKER_HOST", testRemoteHost) socket = extractDockerSocketFromClient(ctx, mockCli{OS: "Ubuntu"}) - assert.Equal(t, DockerSocketPath, socket) + require.Equal(t, DockerSocketPath, socket) }) t.Run("Unix Docker Socket is passed as docker.host property", func(t *testing.T) { @@ -409,7 +446,25 @@ func TestExtractDockerSocketFromClient(t *testing.T) { socket := extractDockerSocketFromClient(ctx, mockCli{OS: "Ubuntu"}) - assert.Equal(t, "/this/is/a/sample.sock", socket) + require.Equal(t, "/this/is/a/sample.sock", socket) + }) + + t.Run("Unix Docker Socket is passed as docker.host property but not reachable", func(t *testing.T) { + content := "docker.host=" + DockerSocketSchema + "/this/is/a/sample.sock" + setupTestcontainersProperties(t, content) + + t.Cleanup(resetSocketOverrideFn) + + ctx := context.Background() + os.Unsetenv("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE") + os.Unsetenv("DOCKER_HOST") + + mockCallbackCheck(t, testCallbackCheckError) + + require.Panics(t, func() { + // no need to check for the returned socket, as it must panic + _ = extractDockerSocketFromClient(ctx, mockCli{OS: "Ubuntu"}) + }) }) } diff --git a/internal/core/docker_rootless.go b/internal/core/docker_rootless.go index 44782d31b3..b8e0f6e17e 100644 --- a/internal/core/docker_rootless.go +++ b/internal/core/docker_rootless.go @@ -53,18 +53,24 @@ func rootlessDockerSocketPath(_ context.Context) (string, error) { rootlessSocketPathFromRunDir, } - outerErr := ErrRootlessDockerNotFound + var errs []error for _, socketPathFn := range socketPathFns { s, err := socketPathFn() if err != nil { - outerErr = fmt.Errorf("%w: %w", outerErr, err) + if !isHostNotSet(err) { + errs = append(errs, err) + } continue } return DockerSocketSchema + s, nil } - return "", outerErr + if len(errs) > 0 { + return "", errors.Join(errs...) + } + + return "", ErrRootlessDockerNotFound } func fileExists(f string) bool { diff --git a/internal/core/docker_rootless_test.go b/internal/core/docker_rootless_test.go index ef018eda53..7897f35783 100644 --- a/internal/core/docker_rootless_test.go +++ b/internal/core/docker_rootless_test.go @@ -178,14 +178,8 @@ func TestRootlessDockerSocketPath(t *testing.T) { setupRootlessNotFound(t) socketPath, err := rootlessDockerSocketPath(context.Background()) - require.ErrorIs(t, err, ErrRootlessDockerNotFound) + require.ErrorIs(t, err, ErrRootlessDockerNotFoundXDGRuntimeDir) assert.Empty(t, socketPath) - - // the wrapped error includes all the locations that were checked - require.ErrorContains(t, err, ErrRootlessDockerNotFoundXDGRuntimeDir.Error()) - require.ErrorContains(t, err, ErrRootlessDockerNotFoundHomeRunDir.Error()) - require.ErrorContains(t, err, ErrRootlessDockerNotFoundHomeDesktopDir.Error()) - require.ErrorContains(t, err, ErrRootlessDockerNotFoundRunDir.Error()) }) } diff --git a/modules/localstack/localstack.go b/modules/localstack/localstack.go index f06054e83b..961527cd3e 100644 --- a/modules/localstack/localstack.go +++ b/modules/localstack/localstack.go @@ -74,7 +74,7 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize // Run creates an instance of the LocalStack container type // - overrideReq: a function that can be used to override the default container request, usually used to set the image version, environment variables for localstack, etc. func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*LocalStackContainer, error) { - dockerHost := testcontainers.ExtractDockerSocket() + dockerHost := testcontainers.MustExtractDockerSocket(ctx) req := testcontainers.ContainerRequest{ Image: img, diff --git a/provider.go b/provider.go index c563503036..b5e5ffa997 100644 --- a/provider.go +++ b/provider.go @@ -147,7 +147,7 @@ func NewDockerProvider(provOpts ...DockerProviderOption) (*DockerProvider, error return &DockerProvider{ DockerProviderOptions: o, - host: core.ExtractDockerHost(ctx), + host: core.MustExtractDockerHost(ctx), client: c, config: config.Read(), }, nil diff --git a/provider_test.go b/provider_test.go index 2448d84c07..097c83a02c 100644 --- a/provider_test.go +++ b/provider_test.go @@ -8,7 +8,7 @@ import ( ) func TestProviderTypeGetProviderAutodetect(t *testing.T) { - dockerHost := core.ExtractDockerHost(context.Background()) + dockerHost := core.MustExtractDockerHost(context.Background()) const podmanSocket = "unix://$XDG_RUNTIME_DIR/podman/podman.sock" tests := []struct { diff --git a/reaper.go b/reaper.go index c17b4f329e..c41520b5b7 100644 --- a/reaper.go +++ b/reaper.go @@ -233,7 +233,7 @@ func reuseReaperContainer(ctx context.Context, sessionID string, provider Reaper // newReaper creates a Reaper with a sessionID to identify containers and a // provider to use. Do not call this directly, use reuseOrCreateReaper instead. func newReaper(ctx context.Context, sessionID string, provider ReaperProvider) (*Reaper, error) { - dockerHostMount := core.ExtractDockerSocket(ctx) + dockerHostMount := core.MustExtractDockerSocket(ctx) reaper := &Reaper{ Provider: provider, diff --git a/reaper_test.go b/reaper_test.go index c757fbb3ea..e526e8ec9a 100644 --- a/reaper_test.go +++ b/reaper_test.go @@ -91,7 +91,7 @@ func createContainerRequest(customize func(ContainerRequest) ContainerRequest) C ExposedPorts: []string{"8080/tcp"}, Labels: core.DefaultLabels(testSessionID), HostConfigModifier: func(hostConfig *container.HostConfig) { - hostConfig.Binds = []string{core.ExtractDockerSocket(context.Background()) + ":/var/run/docker.sock"} + hostConfig.Binds = []string{core.MustExtractDockerSocket(context.Background()) + ":/var/run/docker.sock"} }, WaitingFor: wait.ForListeningPort(nat.Port("8080/tcp")), Env: map[string]string{ @@ -376,7 +376,7 @@ func Test_NewReaper(t *testing.T) { name: "docker-host in context", req: createContainerRequest(func(req ContainerRequest) ContainerRequest { req.HostConfigModifier = func(hostConfig *container.HostConfig) { - hostConfig.Binds = []string{core.ExtractDockerSocket(context.Background()) + ":/var/run/docker.sock"} + hostConfig.Binds = []string{core.MustExtractDockerSocket(context.Background()) + ":/var/run/docker.sock"} } return req }), diff --git a/testcontainers.go b/testcontainers.go index 5b52e09a22..7ae4a40c14 100644 --- a/testcontainers.go +++ b/testcontainers.go @@ -6,7 +6,12 @@ import ( "github.com/testcontainers/testcontainers-go/internal/core" ) -// ExtractDockerSocket Extracts the docker socket from the different alternatives, removing the socket schema. +// Deprecated: use MustExtractDockerHost instead. +func ExtractDockerSocket() string { + return MustExtractDockerSocket(context.Background()) +} + +// MustExtractDockerSocket Extracts the docker socket from the different alternatives, removing the socket schema. // Use this function to get the docker socket path, not the host (e.g. mounting the socket in a container). // This function does not consider Windows containers at the moment. // The possible alternatives are: @@ -14,13 +19,13 @@ import ( // 1. Docker host from the "tc.host" property in the ~/.testcontainers.properties file. // 2. The TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE environment variable. // 3. Using a Docker client, check if the Info().OperativeSystem is "Docker Desktop" and return the default docker socket path for rootless docker. -// 4. Else, Get the current Docker Host from the existing strategies: see ExtractDockerHost. +// 4. Else, Get the current Docker Host from the existing strategies: see MustExtractDockerHost. // 5. If the socket contains the unix schema, the schema is removed (e.g. unix:///var/run/docker.sock -> /var/run/docker.sock) // 6. Else, the default location of the docker socket is used (/var/run/docker.sock) // -// In any case, if the docker socket schema is "tcp://", the default docker socket path will be returned. -func ExtractDockerSocket() string { - return core.ExtractDockerSocket(context.Background()) +// It panics if a Docker client cannot be created, or the Docker host cannot be discovered. +func MustExtractDockerSocket(ctx context.Context) string { + return core.MustExtractDockerSocket(ctx) } // SessionID returns a unique session ID for the current test session. Because each Go package From 6278d6e25249a2f8f51fd9b3b42c8c9342a726de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 13:12:03 +0200 Subject: [PATCH 053/126] chore(deps): bump mkdocs-include-markdown-plugin from 6.0.4 to 6.2.2 (#2760) Bumps [mkdocs-include-markdown-plugin](https://github.com/mondeja/mkdocs-include-markdown-plugin) from 6.0.4 to 6.2.2. - [Release notes](https://github.com/mondeja/mkdocs-include-markdown-plugin/releases) - [Commits](https://github.com/mondeja/mkdocs-include-markdown-plugin/compare/v6.0.4...v6.2.2) --- updated-dependencies: - dependency-name: mkdocs-include-markdown-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Pipfile | 2 +- Pipfile.lock | 215 ++++++++++++++++++++++++++------------------------- 2 files changed, 111 insertions(+), 106 deletions(-) diff --git a/Pipfile b/Pipfile index 6d49cae4de..f19fe13cbd 100644 --- a/Pipfile +++ b/Pipfile @@ -8,7 +8,7 @@ verify_ssl = true [packages] mkdocs = "==1.5.3" mkdocs-codeinclude-plugin = "==0.2.1" -mkdocs-include-markdown-plugin = "==6.2.1" +mkdocs-include-markdown-plugin = "==6.2.2" mkdocs-material = "==9.5.18" mkdocs-markdownextradata-plugin = "==0.2.5" diff --git a/Pipfile.lock b/Pipfile.lock index 3a6f97e05f..6b023f5765 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "de89df66a55ec8bbae341b1e70d15bb1a52b1b04489eee82b2195c83ef08a385" + "sha256": "621bd677256ac0975a720ce1caa39b6594bb39290f0fbf90abc616ab206bec7d" }, "pipfile-spec": 6, "requires": { @@ -26,11 +26,11 @@ }, "bracex": { "hashes": [ - "sha256:a27eaf1df42cf561fed58b7a8f3fdf129d1ea16a81e1fadd1d17989bc6384beb", - "sha256:efdc71eff95eaff5e0f8cfebe7d01adf2c8637c8c92edaf63ef348c241a82418" + "sha256:0725da5045e8d37ea9592ab3614d8b561e22c3c5fde3964699be672e072ab611", + "sha256:d2fcf4b606a82ac325471affe1706dd9bbaa3536c91ef86a31f6b766f3dad1d0" ], "markers": "python_version >= '3.8'", - "version": "==2.4" + "version": "==2.5" }, "certifi": { "hashes": [ @@ -170,11 +170,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f", - "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812" + "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1", + "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5" ], "markers": "python_version < '3.10'", - "version": "==8.0.0" + "version": "==8.4.0" }, "jinja2": { "hashes": [ @@ -186,11 +186,11 @@ }, "markdown": { "hashes": [ - "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f", - "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224" + "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2", + "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803" ], "markers": "python_version >= '3.8'", - "version": "==3.6" + "version": "==3.7" }, "markupsafe": { "hashes": [ @@ -286,12 +286,12 @@ }, "mkdocs-include-markdown-plugin": { "hashes": [ - "sha256:46fc372886d48eec541d36138d1fe1db42afd08b976ef7c8d8d4ea6ee4d5d1e8", - "sha256:8dfc3aee9435679b094cbdff023239e91d86cf357c40b0e99c28036449661830" + "sha256:d293950f6499d2944291ca7b9bc4a60e652bbfd3e3a42b564f6cceee268694e7", + "sha256:f2bd5026650492a581d2fd44be6c22f90391910d76582b96a34c264f2d17875d" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==6.2.1" + "version": "==6.2.2" }, "mkdocs-markdownextradata-plugin": { "hashes": [ @@ -382,60 +382,62 @@ }, "pyyaml": { "hashes": [ - "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", - "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", - "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", - "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", - "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", - "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", - "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", - "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", - "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", - "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", - "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", - "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", - "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", - "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", - "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", - "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", - "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", - "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", - "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", - "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", - "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", - "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", - "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", - "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", - "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", - "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", - "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", - "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", - "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", - "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", - "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", - "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", - "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", - "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", - "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", - "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", - "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", - "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", - "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", - "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", - "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", - "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", - "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", - "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", - "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", - "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", - "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", - "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", - "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", - "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", - "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" + "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", + "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", + "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", + "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", + "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", + "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", + "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", + "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", + "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", + "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", + "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", + "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", + "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", + "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", + "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", + "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", + "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", + "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", + "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", + "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", + "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", + "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", + "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", + "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", + "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", + "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", + "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", + "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", + "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", + "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", + "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", + "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", + "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", + "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", + "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", + "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", + "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", + "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", + "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", + "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", + "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", + "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", + "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", + "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", + "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", + "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", + "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", + "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", + "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", + "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", + "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", + "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", + "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4" ], - "markers": "python_version >= '3.6'", - "version": "==6.0.1" + "markers": "python_version >= '3.8'", + "version": "==6.0.2" }, "pyyaml-env-tag": { "hashes": [ @@ -558,57 +560,60 @@ }, "watchdog": { "hashes": [ - "sha256:0144c0ea9997b92615af1d94afc0c217e07ce2c14912c7b1a5731776329fcfc7", - "sha256:03e70d2df2258fb6cb0e95bbdbe06c16e608af94a3ffbd2b90c3f1e83eb10767", - "sha256:093b23e6906a8b97051191a4a0c73a77ecc958121d42346274c6af6520dec175", - "sha256:123587af84260c991dc5f62a6e7ef3d1c57dfddc99faacee508c71d287248459", - "sha256:17e32f147d8bf9657e0922c0940bcde863b894cd871dbb694beb6704cfbd2fb5", - "sha256:206afc3d964f9a233e6ad34618ec60b9837d0582b500b63687e34011e15bb429", - "sha256:4107ac5ab936a63952dea2a46a734a23230aa2f6f9db1291bf171dac3ebd53c6", - "sha256:4513ec234c68b14d4161440e07f995f231be21a09329051e67a2118a7a612d2d", - "sha256:611be3904f9843f0529c35a3ff3fd617449463cb4b73b1633950b3d97fa4bfb7", - "sha256:62c613ad689ddcb11707f030e722fa929f322ef7e4f18f5335d2b73c61a85c28", - "sha256:667f3c579e813fcbad1b784db7a1aaa96524bed53437e119f6a2f5de4db04235", - "sha256:6e8c70d2cd745daec2a08734d9f63092b793ad97612470a0ee4cbb8f5f705c57", - "sha256:7577b3c43e5909623149f76b099ac49a1a01ca4e167d1785c76eb52fa585745a", - "sha256:998d2be6976a0ee3a81fb8e2777900c28641fb5bfbd0c84717d89bca0addcdc5", - "sha256:a3c2c317a8fb53e5b3d25790553796105501a235343f5d2bf23bb8649c2c8709", - "sha256:ab998f567ebdf6b1da7dc1e5accfaa7c6992244629c0fdaef062f43249bd8dee", - "sha256:ac7041b385f04c047fcc2951dc001671dee1b7e0615cde772e84b01fbf68ee84", - "sha256:bca36be5707e81b9e6ce3208d92d95540d4ca244c006b61511753583c81c70dd", - "sha256:c9904904b6564d4ee8a1ed820db76185a3c96e05560c776c79a6ce5ab71888ba", - "sha256:cad0bbd66cd59fc474b4a4376bc5ac3fc698723510cbb64091c2a793b18654db", - "sha256:d10a681c9a1d5a77e75c48a3b8e1a9f2ae2928eda463e8d33660437705659682", - "sha256:d4925e4bf7b9bddd1c3de13c9b8a2cdb89a468f640e66fbfabaf735bd85b3e35", - "sha256:d7b9f5f3299e8dd230880b6c55504a1f69cf1e4316275d1b215ebdd8187ec88d", - "sha256:da2dfdaa8006eb6a71051795856bedd97e5b03e57da96f98e375682c48850645", - "sha256:dddba7ca1c807045323b6af4ff80f5ddc4d654c8bce8317dde1bd96b128ed253", - "sha256:e7921319fe4430b11278d924ef66d4daa469fafb1da679a2e48c935fa27af193", - "sha256:e93f451f2dfa433d97765ca2634628b789b49ba8b504fdde5837cdcf25fdb53b", - "sha256:eebaacf674fa25511e8867028d281e602ee6500045b57f43b08778082f7f8b44", - "sha256:ef0107bbb6a55f5be727cfc2ef945d5676b97bffb8425650dadbb184be9f9a2b", - "sha256:f0de0f284248ab40188f23380b03b59126d1479cd59940f2a34f8852db710625", - "sha256:f27279d060e2ab24c0aa98363ff906d2386aa6c4dc2f1a374655d4e02a6c5e5e", - "sha256:f8affdf3c0f0466e69f5b3917cdd042f89c8c63aebdb9f7c078996f607cdb0f5" + "sha256:0b4359067d30d5b864e09c8597b112fe0a0a59321a0f331498b013fb097406b4", + "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19", + "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a", + "sha256:10b6683df70d340ac3279eff0b2766813f00f35a1d37515d2c99959ada8f05fa", + "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a", + "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a", + "sha256:2d468028a77b42cc685ed694a7a550a8d1771bb05193ba7b24006b8241a571a1", + "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc", + "sha256:770eef5372f146997638d737c9a3c597a3b41037cfbc5c41538fc27c09c3a3f9", + "sha256:7c7d4bf585ad501c5f6c980e7be9c4f15604c7cc150e942d82083b31a7548930", + "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73", + "sha256:914285126ad0b6eb2258bbbcb7b288d9dfd655ae88fa28945be05a7b475a800b", + "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83", + "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7", + "sha256:984306dc4720da5498b16fc037b36ac443816125a3705dfde4fd90652d8028ef", + "sha256:a2cffa171445b0efa0726c561eca9a27d00a1f2b83846dbd5a4f639c4f8ca8e1", + "sha256:aa160781cafff2719b663c8a506156e9289d111d80f3387cf3af49cedee1f040", + "sha256:b2c45f6e1e57ebb4687690c05bc3a2c1fb6ab260550c4290b8abb1335e0fd08b", + "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270", + "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c", + "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d", + "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8", + "sha256:c100d09ac72a8a08ddbf0629ddfa0b8ee41740f9051429baa8e31bb903ad7508", + "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b", + "sha256:c50f148b31b03fbadd6d0b5980e38b558046b127dc483e5e4505fcef250f9503", + "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757", + "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b", + "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29", + "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c", + "sha256:ede7f010f2239b97cc79e6cb3c249e72962404ae3865860855d5cbe708b0fd22", + "sha256:eeea812f38536a0aa859972d50c76e37f4456474b02bd93674d1947cf1e39578", + "sha256:f15edcae3830ff20e55d1f4e743e92970c847bcddc8b7509bcd172aa04de506e", + "sha256:f5315a8c8dd6dd9425b974515081fc0aadca1d1d61e078d2246509fd756141ee", + "sha256:f6ee8dedd255087bc7fe82adf046f0b75479b989185fb0bdf9a98b612170eac7", + "sha256:f7c739888c20f99824f7aa9d31ac8a97353e22d0c0e54703a547a218f6637eb3" ], "markers": "python_version >= '3.8'", - "version": "==4.0.1" + "version": "==4.0.2" }, "wcmatch": { "hashes": [ - "sha256:17d3ad3758f9d0b5b4dedc770b65420d4dac62e680229c287bf24c9db856a478", - "sha256:a70222b86dea82fb382dd87b73278c10756c138bd6f8f714e2183128887b9eb2" + "sha256:567d66b11ad74384954c8af86f607857c3bdf93682349ad32066231abd556c92", + "sha256:af25922e2b6dbd1550fa37a4c8de7dd558d6c1bb330c641de9b907b9776cb3c4" ], "markers": "python_version >= '3.8'", - "version": "==8.5.2" + "version": "==9.0" }, "zipp": { "hashes": [ - "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19", - "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c" + "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064", + "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b" ], "markers": "python_version >= '3.8'", - "version": "==3.19.2" + "version": "==3.20.1" } }, "develop": {} From 2f5756e8d8a359c597b7cacbc94a8e2de44aa1f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 13:13:32 +0200 Subject: [PATCH 054/126] chore(deps): bump actions/checkout from 4.1.1 to 4.1.7 (#2762) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/b4ffde65f46336ab88eb53be808477a3936bae11...692973e3d937129bcbf40652eb9f2f61becf3332) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-test-go.yml | 2 +- .github/workflows/ci-windows.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/codeql.yml | 2 +- .github/workflows/docker-moby-latest.yml | 2 +- .github/workflows/scorecards.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-test-go.yml b/.github/workflows/ci-test-go.yml index 13fb26422c..c2c0747278 100644 --- a/.github/workflows/ci-test-go.yml +++ b/.github/workflows/ci-test-go.yml @@ -62,7 +62,7 @@ jobs: run: sudo rm -rf /var/run/docker.sock - name: Check out code into the Go module directory - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 - name: Set up Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5 diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml index ba8a27aaf1..fce4331c94 100644 --- a/.github/workflows/ci-windows.yml +++ b/.github/workflows/ci-windows.yml @@ -24,7 +24,7 @@ jobs: }) - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: token: ${{ secrets.GITHUB_TOKEN }} repository: ${{ github.event.client_payload.pull_request.head.repo.full_name }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7f48d18dd..f326e9c1da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -129,7 +129,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: # Disabling shallow clone is recommended for improving relevancy of reporting fetch-depth: 0 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5952e14d60..15f56f2eb5 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -49,7 +49,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/docker-moby-latest.yml b/.github/workflows/docker-moby-latest.yml index acf8704ec8..39cb96df3d 100644 --- a/.github/workflows/docker-moby-latest.yml +++ b/.github/workflows/docker-moby-latest.yml @@ -27,7 +27,7 @@ jobs: run: sudo rm -rf /var/run/docker.sock - name: Check out code into the Go module directory - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 - name: Set up Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5 diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index d8b8174403..82b14c7ad4 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -20,7 +20,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 with: persist-credentials: false From 975d1acba5a111d2c848ae365d46121582776484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 2 Sep 2024 14:18:19 +0200 Subject: [PATCH 055/126] fix: update template too (#2763) --- modulegen/_template/ci.yml.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modulegen/_template/ci.yml.tmpl b/modulegen/_template/ci.yml.tmpl index 4b15371337..e4fd047b24 100644 --- a/modulegen/_template/ci.yml.tmpl +++ b/modulegen/_template/ci.yml.tmpl @@ -129,7 +129,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.1 with: # Disabling shallow clone is recommended for improving relevancy of reporting fetch-depth: 0 From ab41ba5fee7926810ddf568b9e07c410487ba8ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:53:52 +0200 Subject: [PATCH 056/126] chore(deps): bump mkdocs-markdownextradata-plugin from 0.2.5 to 0.2.6 (#2761) Bumps [mkdocs-markdownextradata-plugin](https://github.com/rosscdh/mkdocs-markdownextradata-plugin) from 0.2.5 to 0.2.6. - [Release notes](https://github.com/rosscdh/mkdocs-markdownextradata-plugin/releases) - [Commits](https://github.com/rosscdh/mkdocs-markdownextradata-plugin/compare/0.2.5...0.2.6) --- updated-dependencies: - dependency-name: mkdocs-markdownextradata-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Pipfile | 2 +- Pipfile.lock | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Pipfile b/Pipfile index f19fe13cbd..2648278724 100644 --- a/Pipfile +++ b/Pipfile @@ -10,7 +10,7 @@ mkdocs = "==1.5.3" mkdocs-codeinclude-plugin = "==0.2.1" mkdocs-include-markdown-plugin = "==6.2.2" mkdocs-material = "==9.5.18" -mkdocs-markdownextradata-plugin = "==0.2.5" +mkdocs-markdownextradata-plugin = "==0.2.6" [requires] python_version = "3.8" diff --git a/Pipfile.lock b/Pipfile.lock index 6b023f5765..9a2f6d24c8 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "621bd677256ac0975a720ce1caa39b6594bb39290f0fbf90abc616ab206bec7d" + "sha256": "0411eac13d1b06b42671b8a654fb269eb0c329d9a3d41f669ccf7b653ef8ad32" }, "pipfile-spec": 6, "requires": { @@ -295,11 +295,12 @@ }, "mkdocs-markdownextradata-plugin": { "hashes": [ - "sha256:9c562e8fe375647d5692d11dfe369a7bdd50302174d35995fce2aeca58036ec6" + "sha256:34dd40870781784c75809596b2d8d879da783815b075336d541de1f150c94242", + "sha256:4aed9b43b8bec65b02598387426ca4809099ea5f5aa78bf114f3296fd46686b5" ], "index": "pypi", - "markers": "python_version not in '3.0, 3.1, 3.2, 3.3' and python_full_version >= '2.7.9'", - "version": "==0.2.5" + "markers": "python_version >= '3.6'", + "version": "==0.2.6" }, "mkdocs-material": { "hashes": [ From 5cc104affdb8fb7d6247f30a27018907701d57aa Mon Sep 17 00:00:00 2001 From: Nico Grashoff Date: Mon, 2 Sep 2024 17:10:10 +0200 Subject: [PATCH 057/126] feat(compose): select services via profiles (#2758) This commit allows users of the compose module to selectively enable services by using Docker Compose profiles. More about profiles: https://docs.docker.com/compose/profiles --- modules/compose/compose.go | 8 +++ modules/compose/compose_api.go | 17 ++++++ modules/compose/compose_api_test.go | 53 +++++++++++++++++++ modules/compose/compose_builder_test.go | 6 +++ .../testdata/docker-compose-profiles.yml | 25 +++++++++ 5 files changed, 109 insertions(+) create mode 100644 modules/compose/testdata/docker-compose-profiles.yml diff --git a/modules/compose/compose.go b/modules/compose/compose.go index b0f26370cb..c63eb73bb1 100644 --- a/modules/compose/compose.go +++ b/modules/compose/compose.go @@ -32,6 +32,7 @@ type composeStackOptions struct { Paths []string temporaryPaths map[string]bool Logger testcontainers.Logging + Profiles []string } type ComposeStackOption interface { @@ -116,6 +117,11 @@ func WithStackReaders(readers ...io.Reader) ComposeStackOption { return ComposeStackReaders(readers) } +// WithProfiles allows to enable/disable services based on the profiles defined in the compose file. +func WithProfiles(profiles ...string) ComposeStackOption { + return ComposeProfiles(profiles) +} + func NewDockerCompose(filePaths ...string) (*dockerCompose, error) { return NewDockerComposeWith(WithStackFiles(filePaths...)) } @@ -125,6 +131,7 @@ func NewDockerComposeWith(opts ...ComposeStackOption) (*dockerCompose, error) { Identifier: uuid.New().String(), temporaryPaths: make(map[string]bool), Logger: testcontainers.Logger, + Profiles: nil, } for i := range opts { @@ -168,6 +175,7 @@ func NewDockerComposeWith(opts ...ComposeStackOption) (*dockerCompose, error) { configs: composeOptions.Paths, temporaryConfigs: composeOptions.temporaryPaths, logger: composeOptions.Logger, + projectProfiles: composeOptions.Profiles, composeService: compose.NewComposeService(dockerCli), dockerClient: dockerCli.Client(), waitStrategies: make(map[string]wait.Strategy), diff --git a/modules/compose/compose_api.go b/modules/compose/compose_api.go index 129f55897e..d1b18ec3b6 100644 --- a/modules/compose/compose_api.go +++ b/modules/compose/compose_api.go @@ -153,6 +153,13 @@ func (f ComposeStackFiles) applyToComposeStack(o *composeStackOptions) error { return nil } +type ComposeProfiles []string + +func (p ComposeProfiles) applyToComposeStack(o *composeStackOptions) error { + o.Profiles = append(o.Profiles, p...) + return nil +} + type StackIdentifier string func (f StackIdentifier) applyToComposeStack(o *composeStackOptions) error { @@ -212,6 +219,9 @@ type dockerCompose struct { // e.g. environment settings, ... projectOptions []cli.ProjectOptionsFn + // profiles applied to the compose project after compilation. + projectProfiles []string + // compiled compose project // can be nil if the stack wasn't started yet project *types.Project @@ -512,6 +522,13 @@ func (d *dockerCompose) compileProject(ctx context.Context) (*types.Project, err return nil, fmt.Errorf("load project: %w", err) } + if len(d.projectProfiles) > 0 { + proj, err = proj.WithProfiles(d.projectProfiles) + if err != nil { + return nil, fmt.Errorf("with profiles: %w", err) + } + } + for i, s := range proj.Services { s.CustomLabels = map[string]string{ api.ProjectLabel: proj.Name, diff --git a/modules/compose/compose_api_test.go b/modules/compose/compose_api_test.go index 6771454347..7879dabfa9 100644 --- a/modules/compose/compose_api_test.go +++ b/modules/compose/compose_api_test.go @@ -101,6 +101,59 @@ func TestDockerComposeAPIWithRunServices(t *testing.T) { assert.Contains(t, serviceNames, "api-nginx") } +func TestDockerComposeAPIWithProfiles(t *testing.T) { + path := RenderComposeProfiles(t) + + testcases := map[string]struct { + withProfiles []string + wantServices []string + }{ + "nil profile": { + withProfiles: nil, + wantServices: []string{"starts-always"}, + }, + "no profiles": { + withProfiles: []string{}, + wantServices: []string{"starts-always"}, + }, + "dev profile": { + withProfiles: []string{"dev"}, + wantServices: []string{"starts-always", "only-dev", "dev-or-test"}, + }, + "test profile": { + withProfiles: []string{"test"}, + wantServices: []string{"starts-always", "dev-or-test"}, + }, + "wildcard profile": { + withProfiles: []string{"*"}, + wantServices: []string{"starts-always", "only-dev", "dev-or-test", "only-prod"}, + }, + "undefined profile": { + withProfiles: []string{"undefined-profile"}, + wantServices: []string{"starts-always"}, + }, + } + + for name, test := range testcases { + t.Run(name, func(t *testing.T) { + compose, err := NewDockerComposeWith(WithStackFiles(path), WithProfiles(test.withProfiles...)) + require.NoError(t, err, "NewDockerCompose()") + + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + + for _, service := range test.wantServices { + compose = compose.WaitForService(service, wait.NewHTTPStrategy("/").WithPort("80/tcp").WithStartupTimeout(10*time.Second)).(*dockerCompose) + } + err = compose.Up(ctx, Wait(true)) + cleanup(t, compose) + require.NoError(t, err, "compose.Up()") + + assert.ElementsMatch(t, test.wantServices, compose.Services()) + }) + } +} + func TestDockerComposeAPI_TestcontainersLabelsArePresent(t *testing.T) { path, _ := RenderComposeComplex(t) compose, err := NewDockerCompose(path) diff --git a/modules/compose/compose_builder_test.go b/modules/compose/compose_builder_test.go index fbfe37baa3..4624c1d3c2 100644 --- a/modules/compose/compose_builder_test.go +++ b/modules/compose/compose_builder_test.go @@ -14,6 +14,12 @@ const ( testdataPackage = "testdata" ) +func RenderComposeProfiles(t *testing.T) string { + t.Helper() + + return writeTemplate(t, "docker-compose-profiles.yml") +} + func RenderComposeComplex(t *testing.T) (string, []int) { t.Helper() diff --git a/modules/compose/testdata/docker-compose-profiles.yml b/modules/compose/testdata/docker-compose-profiles.yml new file mode 100644 index 0000000000..fdb92853e1 --- /dev/null +++ b/modules/compose/testdata/docker-compose-profiles.yml @@ -0,0 +1,25 @@ +services: + starts-always: + image: docker.io/nginx:stable-alpine + ports: + - ":80" + # profiles: none defined, therefore always starts. + only-dev: + image: docker.io/nginx:stable-alpine + ports: + - ":80" + profiles: + - dev + dev-or-test: + image: docker.io/nginx:stable-alpine + ports: + - ":80" + profiles: + - dev + - test + only-prod: + image: docker.io/nginx:stable-alpine + ports: + - ":80" + profiles: + - prod From cf51ec77b031630aa60a2df7ecc09b0ad863fdba Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Tue, 3 Sep 2024 13:26:10 +0100 Subject: [PATCH 058/126] feat(wait): for file (#2731) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(wait): for file Add the ability to wait for a file and optionally its contents. This leverages generated mocks using mockery and testify/mock to make testing easier. * debugging: rate limit config dump Add output of the docker config if we hit rate limiting to aid in debugging why this is happening on github actions. Don't use logger as that's no-op when verbose is not in effect. * docs: list the file wait strategy in docs --------- Co-authored-by: Manuel de la Peña --- .mockery.yaml | 11 + docs/features/wait/file.md | 14 + docs/features/wait/introduction.md | 1 + generic.go | 9 + go.mod | 1 + go.sum | 2 + mkdocs.yml | 1 + wait/exec_test.go | 4 + wait/exit_test.go | 5 + wait/file.go | 112 ++++++ wait/file_test.go | 104 ++++++ wait/health_test.go | 5 + wait/nop.go | 4 + wait/strategytarget_mock_test.go | 528 +++++++++++++++++++++++++++++ wait/wait.go | 1 + wait/wait_test.go | 19 +- 16 files changed, 814 insertions(+), 7 deletions(-) create mode 100644 .mockery.yaml create mode 100644 docs/features/wait/file.md create mode 100644 wait/file.go create mode 100644 wait/file_test.go create mode 100644 wait/strategytarget_mock_test.go diff --git a/.mockery.yaml b/.mockery.yaml new file mode 100644 index 0000000000..2f96829f21 --- /dev/null +++ b/.mockery.yaml @@ -0,0 +1,11 @@ +quiet: True +disable-version-string: True +with-expecter: True +mockname: "mock{{.InterfaceName}}" +filename: "{{ .InterfaceName | lower }}_mock_test.go" +outpkg: "{{.PackageName}}_test" +dir: "{{.InterfaceDir}}" +packages: + github.com/testcontainers/testcontainers-go/wait: + interfaces: + StrategyTarget: diff --git a/docs/features/wait/file.md b/docs/features/wait/file.md new file mode 100644 index 0000000000..8bdf8ade27 --- /dev/null +++ b/docs/features/wait/file.md @@ -0,0 +1,14 @@ +# File Wait Strategy + +File Wait Strategy waits for a file to exist in the container, and allows to set the following conditions: + +- the file to wait for. +- a matcher which reads the file content, no-op if nil or not set. +- the startup timeout to be used in seconds, default is 60 seconds. +- the poll interval to be used in milliseconds, default is 100 milliseconds. + +## Waiting for file to exist and extract the content + + +[Waiting for file to exist and extract the content](../../../wait/file_test.go) inside_block:waitForFileWithMatcher + diff --git a/docs/features/wait/introduction.md b/docs/features/wait/introduction.md index 5af611321c..87adabc3ed 100644 --- a/docs/features/wait/introduction.md +++ b/docs/features/wait/introduction.md @@ -8,6 +8,7 @@ Below you can find a list of the available wait strategies that you can use: - [Exec](./exec.md) - [Exit](./exit.md) +- [File](./file.md) - [Health](./health.md) - [HostPort](./host_port.md) - [HTTP](./http.md) diff --git a/generic.go b/generic.go index 4c214744e7..9052287b51 100644 --- a/generic.go +++ b/generic.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "strings" "sync" "github.com/testcontainers/testcontainers-go/internal/core" @@ -74,6 +75,14 @@ func GenericContainer(ctx context.Context, req GenericContainerRequest) (Contain } if err != nil { // At this point `c` might not be nil. Give the caller an opportunity to call Destroy on the container. + // TODO: Remove this debugging. + if strings.Contains(err.Error(), "toomanyrequests") { + // Debugging information for rate limiting. + cfg, err := getDockerConfig() + if err == nil { + fmt.Printf("XXX: too many requests: %+v", cfg) + } + } return c, fmt.Errorf("create container: %w", err) } diff --git a/go.mod b/go.mod index 678d37ec08..8e9b20a12a 100644 --- a/go.mod +++ b/go.mod @@ -47,6 +47,7 @@ require ( github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect diff --git a/go.sum b/go.sum index 563862022b..ef44f5f91c 100644 --- a/go.sum +++ b/go.sum @@ -102,6 +102,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/mkdocs.yml b/mkdocs.yml index 7dc942de52..d48a9dff17 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -57,6 +57,7 @@ nav: - Introduction: features/wait/introduction.md - Exec: features/wait/exec.md - Exit: features/wait/exit.md + - File: features/wait/file.md - Health: features/wait/health.md - HostPort: features/wait/host_port.md - HTTP: features/wait/http.md diff --git a/wait/exec_test.go b/wait/exec_test.go index f81a3ffa01..13e3e47511 100644 --- a/wait/exec_test.go +++ b/wait/exec_test.go @@ -102,6 +102,10 @@ func (st mockExecTarget) State(_ context.Context) (*types.ContainerState, error) return nil, errors.New("not implemented") } +func (st mockExecTarget) CopyFileFromContainer(_ context.Context, _ string) (io.ReadCloser, error) { + return nil, errors.New("not implemented") +} + func TestExecStrategyWaitUntilReady(t *testing.T) { target := mockExecTarget{} wg := wait.NewExecStrategy([]string{"true"}). diff --git a/wait/exit_test.go b/wait/exit_test.go index 137c4f276b..4795fd4ad6 100644 --- a/wait/exit_test.go +++ b/wait/exit_test.go @@ -2,6 +2,7 @@ package wait import ( "context" + "errors" "io" "testing" "time" @@ -45,6 +46,10 @@ func (st exitStrategyTarget) State(ctx context.Context) (*types.ContainerState, return &types.ContainerState{Running: st.isRunning}, nil } +func (st exitStrategyTarget) CopyFileFromContainer(context.Context, string) (io.ReadCloser, error) { + return nil, errors.New("not implemented") +} + func TestWaitForExit(t *testing.T) { target := exitStrategyTarget{ isRunning: false, diff --git a/wait/file.go b/wait/file.go new file mode 100644 index 0000000000..148907f3db --- /dev/null +++ b/wait/file.go @@ -0,0 +1,112 @@ +package wait + +import ( + "context" + "fmt" + "io" + "time" + + "github.com/docker/docker/errdefs" +) + +var ( + _ Strategy = (*FileStrategy)(nil) + _ StrategyTimeout = (*FileStrategy)(nil) +) + +// FileStrategy waits for a file to exist in the container. +type FileStrategy struct { + timeout *time.Duration + file string + pollInterval time.Duration + matcher func(io.Reader) error +} + +// NewFileStrategy constructs an FileStrategy strategy. +func NewFileStrategy(file string) *FileStrategy { + return &FileStrategy{ + file: file, + pollInterval: defaultPollInterval(), + } +} + +// WithStartupTimeout can be used to change the default startup timeout +func (ws *FileStrategy) WithStartupTimeout(startupTimeout time.Duration) *FileStrategy { + ws.timeout = &startupTimeout + return ws +} + +// WithPollInterval can be used to override the default polling interval of 100 milliseconds +func (ws *FileStrategy) WithPollInterval(pollInterval time.Duration) *FileStrategy { + ws.pollInterval = pollInterval + return ws +} + +// WithMatcher can be used to consume the file content. +// The matcher can return an errdefs.ErrNotFound to indicate that the file is not ready. +// Any other error will be considered a failure. +// Default: nil, will only wait for the file to exist. +func (ws *FileStrategy) WithMatcher(matcher func(io.Reader) error) *FileStrategy { + ws.matcher = matcher + return ws +} + +// ForFile is a convenience method to assign FileStrategy +func ForFile(file string) *FileStrategy { + return NewFileStrategy(file) +} + +// Timeout returns the timeout for the strategy +func (ws *FileStrategy) Timeout() *time.Duration { + return ws.timeout +} + +// WaitUntilReady waits until the file exists in the container and copies it to the target. +func (ws *FileStrategy) WaitUntilReady(ctx context.Context, target StrategyTarget) error { + timeout := defaultStartupTimeout() + if ws.timeout != nil { + timeout = *ws.timeout + } + + ctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + + timer := time.NewTicker(ws.pollInterval) + defer timer.Stop() + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-timer.C: + if err := ws.matchFile(ctx, target); err != nil { + if errdefs.IsNotFound(err) { + // Not found, continue polling. + continue + } + + return fmt.Errorf("copy from container: %w", err) + } + return nil + } + } +} + +// matchFile tries to copy the file from the container and match it. +func (ws *FileStrategy) matchFile(ctx context.Context, target StrategyTarget) error { + rc, err := target.CopyFileFromContainer(ctx, ws.file) + if err != nil { + return fmt.Errorf("copy from container: %w", err) + } + defer rc.Close() //nolint: errcheck // Read close error can't tell us anything useful. + + if ws.matcher == nil { + // No matcher, just check if the file exists. + return nil + } + + if err = ws.matcher(rc); err != nil { + return fmt.Errorf("matcher: %w", err) + } + + return nil +} diff --git a/wait/file_test.go b/wait/file_test.go new file mode 100644 index 0000000000..a25d8aa65f --- /dev/null +++ b/wait/file_test.go @@ -0,0 +1,104 @@ +package wait_test + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "testing" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/errdefs" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +const testFilename = "/tmp/file" + +var anyContext = mock.AnythingOfType("*context.timerCtx") + +// newRunningTarget creates a new mockStrategyTarget that is running. +func newRunningTarget() *mockStrategyTarget { + target := &mockStrategyTarget{} + target.EXPECT().State(anyContext). + Return(&types.ContainerState{Running: true}, nil) + + return target +} + +// testForFile creates a new FileStrategy for testing. +func testForFile() *wait.FileStrategy { + return wait.ForFile(testFilename). + WithStartupTimeout(time.Millisecond * 50). + WithPollInterval(time.Millisecond) +} + +func TestForFile(t *testing.T) { + errNotFound := errdefs.NotFound(errors.New("file not found")) + ctx := context.Background() + + t.Run("not-found", func(t *testing.T) { + target := newRunningTarget() + target.EXPECT().CopyFileFromContainer(anyContext, testFilename).Return(nil, errNotFound) + err := testForFile().WaitUntilReady(ctx, target) + require.EqualError(t, err, context.DeadlineExceeded.Error()) + }) + + t.Run("other-error", func(t *testing.T) { + otherErr := errors.New("other error") + target := newRunningTarget() + target.EXPECT().CopyFileFromContainer(anyContext, testFilename).Return(nil, otherErr) + err := testForFile().WaitUntilReady(ctx, target) + require.ErrorIs(t, err, otherErr) + }) + + t.Run("valid", func(t *testing.T) { + data := "my content\nwibble" + file := bytes.NewBufferString(data) + target := newRunningTarget() + target.EXPECT().CopyFileFromContainer(anyContext, testFilename).Once().Return(nil, errNotFound) + target.EXPECT().CopyFileFromContainer(anyContext, testFilename).Return(io.NopCloser(file), nil) + var out bytes.Buffer + err := testForFile().WithMatcher(func(r io.Reader) error { + if _, err := io.Copy(&out, r); err != nil { + return fmt.Errorf("copy: %w", err) + } + return nil + }).WaitUntilReady(ctx, target) + require.NoError(t, err) + require.Equal(t, data, out.String()) + }) +} + +func TestFileStrategyWaitUntilReady_WithMatcher(t *testing.T) { + // waitForFileWithMatcher { + var out bytes.Buffer + dockerReq := testcontainers.ContainerRequest{ + Image: "docker.io/nginx:latest", + WaitingFor: wait.ForFile("/etc/nginx/nginx.conf"). + WithStartupTimeout(time.Second * 10). + WithPollInterval(time.Second). + WithMatcher(func(r io.Reader) error { + if _, err := io.Copy(&out, r); err != nil { + return fmt.Errorf("copy: %w", err) + } + return nil + }), + } + // } + + ctx := context.Background() + container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ContainerRequest: dockerReq, Started: true}) + if container != nil { + t.Cleanup(func() { + require.NoError(t, container.Terminate(context.Background())) + }) + } + require.NoError(t, err) + require.Contains(t, out.String(), "worker_processes") +} diff --git a/wait/health_test.go b/wait/health_test.go index 8a06ab07f8..4141988905 100644 --- a/wait/health_test.go +++ b/wait/health_test.go @@ -2,6 +2,7 @@ package wait import ( "context" + "errors" "io" "sync" "testing" @@ -60,6 +61,10 @@ func (st *healthStrategyTarget) setState(health *types.Health) { st.state.Health = health } +func (st *healthStrategyTarget) CopyFileFromContainer(_ context.Context, _ string) (io.ReadCloser, error) { + return nil, errors.New("not implemented") +} + // TestWaitForHealthTimesOutForUnhealthy confirms that an unhealthy container will eventually // time out. func TestWaitForHealthTimesOutForUnhealthy(t *testing.T) { diff --git a/wait/nop.go b/wait/nop.go index 7b8e918abd..4206eefc1e 100644 --- a/wait/nop.go +++ b/wait/nop.go @@ -75,3 +75,7 @@ func (st NopStrategyTarget) Exec(_ context.Context, _ []string, _ ...exec.Proces func (st NopStrategyTarget) State(_ context.Context) (*types.ContainerState, error) { return &st.ContainerState, nil } + +func (st NopStrategyTarget) CopyFileFromContainer(context.Context, string) (io.ReadCloser, error) { + return st.ReaderCloser, nil +} diff --git a/wait/strategytarget_mock_test.go b/wait/strategytarget_mock_test.go new file mode 100644 index 0000000000..525ff08e1d --- /dev/null +++ b/wait/strategytarget_mock_test.go @@ -0,0 +1,528 @@ +// Code generated by mockery. DO NOT EDIT. + +package wait_test + +import ( + context "context" + io "io" + + exec "github.com/testcontainers/testcontainers-go/exec" + + mock "github.com/stretchr/testify/mock" + + nat "github.com/docker/go-connections/nat" + + types "github.com/docker/docker/api/types" +) + +// mockStrategyTarget is an autogenerated mock type for the StrategyTarget type +type mockStrategyTarget struct { + mock.Mock +} + +type mockStrategyTarget_Expecter struct { + mock *mock.Mock +} + +func (_m *mockStrategyTarget) EXPECT() *mockStrategyTarget_Expecter { + return &mockStrategyTarget_Expecter{mock: &_m.Mock} +} + +// CopyFileFromContainer provides a mock function with given fields: ctx, filePath +func (_m *mockStrategyTarget) CopyFileFromContainer(ctx context.Context, filePath string) (io.ReadCloser, error) { + ret := _m.Called(ctx, filePath) + + if len(ret) == 0 { + panic("no return value specified for CopyFileFromContainer") + } + + var r0 io.ReadCloser + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (io.ReadCloser, error)); ok { + return rf(ctx, filePath) + } + if rf, ok := ret.Get(0).(func(context.Context, string) io.ReadCloser); ok { + r0 = rf(ctx, filePath) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(io.ReadCloser) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, filePath) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockStrategyTarget_CopyFileFromContainer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CopyFileFromContainer' +type mockStrategyTarget_CopyFileFromContainer_Call struct { + *mock.Call +} + +// CopyFileFromContainer is a helper method to define mock.On call +// - ctx context.Context +// - filePath string +func (_e *mockStrategyTarget_Expecter) CopyFileFromContainer(ctx interface{}, filePath interface{}) *mockStrategyTarget_CopyFileFromContainer_Call { + return &mockStrategyTarget_CopyFileFromContainer_Call{Call: _e.mock.On("CopyFileFromContainer", ctx, filePath)} +} + +func (_c *mockStrategyTarget_CopyFileFromContainer_Call) Run(run func(ctx context.Context, filePath string)) *mockStrategyTarget_CopyFileFromContainer_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *mockStrategyTarget_CopyFileFromContainer_Call) Return(_a0 io.ReadCloser, _a1 error) *mockStrategyTarget_CopyFileFromContainer_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockStrategyTarget_CopyFileFromContainer_Call) RunAndReturn(run func(context.Context, string) (io.ReadCloser, error)) *mockStrategyTarget_CopyFileFromContainer_Call { + _c.Call.Return(run) + return _c +} + +// Exec provides a mock function with given fields: _a0, _a1, _a2 +func (_m *mockStrategyTarget) Exec(_a0 context.Context, _a1 []string, _a2 ...exec.ProcessOption) (int, io.Reader, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for Exec") + } + + var r0 int + var r1 io.Reader + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, []string, ...exec.ProcessOption) (int, io.Reader, error)); ok { + return rf(_a0, _a1, _a2...) + } + if rf, ok := ret.Get(0).(func(context.Context, []string, ...exec.ProcessOption) int); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + r0 = ret.Get(0).(int) + } + + if rf, ok := ret.Get(1).(func(context.Context, []string, ...exec.ProcessOption) io.Reader); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(io.Reader) + } + } + + if rf, ok := ret.Get(2).(func(context.Context, []string, ...exec.ProcessOption) error); ok { + r2 = rf(_a0, _a1, _a2...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// mockStrategyTarget_Exec_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Exec' +type mockStrategyTarget_Exec_Call struct { + *mock.Call +} + +// Exec is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 []string +// - _a2 ...exec.ProcessOption +func (_e *mockStrategyTarget_Expecter) Exec(_a0 interface{}, _a1 interface{}, _a2 ...interface{}) *mockStrategyTarget_Exec_Call { + return &mockStrategyTarget_Exec_Call{Call: _e.mock.On("Exec", + append([]interface{}{_a0, _a1}, _a2...)...)} +} + +func (_c *mockStrategyTarget_Exec_Call) Run(run func(_a0 context.Context, _a1 []string, _a2 ...exec.ProcessOption)) *mockStrategyTarget_Exec_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]exec.ProcessOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(exec.ProcessOption) + } + } + run(args[0].(context.Context), args[1].([]string), variadicArgs...) + }) + return _c +} + +func (_c *mockStrategyTarget_Exec_Call) Return(_a0 int, _a1 io.Reader, _a2 error) *mockStrategyTarget_Exec_Call { + _c.Call.Return(_a0, _a1, _a2) + return _c +} + +func (_c *mockStrategyTarget_Exec_Call) RunAndReturn(run func(context.Context, []string, ...exec.ProcessOption) (int, io.Reader, error)) *mockStrategyTarget_Exec_Call { + _c.Call.Return(run) + return _c +} + +// Host provides a mock function with given fields: _a0 +func (_m *mockStrategyTarget) Host(_a0 context.Context) (string, error) { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Host") + } + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (string, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(context.Context) string); ok { + r0 = rf(_a0) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockStrategyTarget_Host_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Host' +type mockStrategyTarget_Host_Call struct { + *mock.Call +} + +// Host is a helper method to define mock.On call +// - _a0 context.Context +func (_e *mockStrategyTarget_Expecter) Host(_a0 interface{}) *mockStrategyTarget_Host_Call { + return &mockStrategyTarget_Host_Call{Call: _e.mock.On("Host", _a0)} +} + +func (_c *mockStrategyTarget_Host_Call) Run(run func(_a0 context.Context)) *mockStrategyTarget_Host_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *mockStrategyTarget_Host_Call) Return(_a0 string, _a1 error) *mockStrategyTarget_Host_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockStrategyTarget_Host_Call) RunAndReturn(run func(context.Context) (string, error)) *mockStrategyTarget_Host_Call { + _c.Call.Return(run) + return _c +} + +// Inspect provides a mock function with given fields: _a0 +func (_m *mockStrategyTarget) Inspect(_a0 context.Context) (*types.ContainerJSON, error) { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Inspect") + } + + var r0 *types.ContainerJSON + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*types.ContainerJSON, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(context.Context) *types.ContainerJSON); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ContainerJSON) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockStrategyTarget_Inspect_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Inspect' +type mockStrategyTarget_Inspect_Call struct { + *mock.Call +} + +// Inspect is a helper method to define mock.On call +// - _a0 context.Context +func (_e *mockStrategyTarget_Expecter) Inspect(_a0 interface{}) *mockStrategyTarget_Inspect_Call { + return &mockStrategyTarget_Inspect_Call{Call: _e.mock.On("Inspect", _a0)} +} + +func (_c *mockStrategyTarget_Inspect_Call) Run(run func(_a0 context.Context)) *mockStrategyTarget_Inspect_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *mockStrategyTarget_Inspect_Call) Return(_a0 *types.ContainerJSON, _a1 error) *mockStrategyTarget_Inspect_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockStrategyTarget_Inspect_Call) RunAndReturn(run func(context.Context) (*types.ContainerJSON, error)) *mockStrategyTarget_Inspect_Call { + _c.Call.Return(run) + return _c +} + +// Logs provides a mock function with given fields: _a0 +func (_m *mockStrategyTarget) Logs(_a0 context.Context) (io.ReadCloser, error) { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Logs") + } + + var r0 io.ReadCloser + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (io.ReadCloser, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(context.Context) io.ReadCloser); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(io.ReadCloser) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockStrategyTarget_Logs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Logs' +type mockStrategyTarget_Logs_Call struct { + *mock.Call +} + +// Logs is a helper method to define mock.On call +// - _a0 context.Context +func (_e *mockStrategyTarget_Expecter) Logs(_a0 interface{}) *mockStrategyTarget_Logs_Call { + return &mockStrategyTarget_Logs_Call{Call: _e.mock.On("Logs", _a0)} +} + +func (_c *mockStrategyTarget_Logs_Call) Run(run func(_a0 context.Context)) *mockStrategyTarget_Logs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *mockStrategyTarget_Logs_Call) Return(_a0 io.ReadCloser, _a1 error) *mockStrategyTarget_Logs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockStrategyTarget_Logs_Call) RunAndReturn(run func(context.Context) (io.ReadCloser, error)) *mockStrategyTarget_Logs_Call { + _c.Call.Return(run) + return _c +} + +// MappedPort provides a mock function with given fields: _a0, _a1 +func (_m *mockStrategyTarget) MappedPort(_a0 context.Context, _a1 nat.Port) (nat.Port, error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for MappedPort") + } + + var r0 nat.Port + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, nat.Port) (nat.Port, error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, nat.Port) nat.Port); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Get(0).(nat.Port) + } + + if rf, ok := ret.Get(1).(func(context.Context, nat.Port) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockStrategyTarget_MappedPort_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MappedPort' +type mockStrategyTarget_MappedPort_Call struct { + *mock.Call +} + +// MappedPort is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 nat.Port +func (_e *mockStrategyTarget_Expecter) MappedPort(_a0 interface{}, _a1 interface{}) *mockStrategyTarget_MappedPort_Call { + return &mockStrategyTarget_MappedPort_Call{Call: _e.mock.On("MappedPort", _a0, _a1)} +} + +func (_c *mockStrategyTarget_MappedPort_Call) Run(run func(_a0 context.Context, _a1 nat.Port)) *mockStrategyTarget_MappedPort_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(nat.Port)) + }) + return _c +} + +func (_c *mockStrategyTarget_MappedPort_Call) Return(_a0 nat.Port, _a1 error) *mockStrategyTarget_MappedPort_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockStrategyTarget_MappedPort_Call) RunAndReturn(run func(context.Context, nat.Port) (nat.Port, error)) *mockStrategyTarget_MappedPort_Call { + _c.Call.Return(run) + return _c +} + +// Ports provides a mock function with given fields: ctx +func (_m *mockStrategyTarget) Ports(ctx context.Context) (nat.PortMap, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for Ports") + } + + var r0 nat.PortMap + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (nat.PortMap, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) nat.PortMap); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(nat.PortMap) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockStrategyTarget_Ports_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ports' +type mockStrategyTarget_Ports_Call struct { + *mock.Call +} + +// Ports is a helper method to define mock.On call +// - ctx context.Context +func (_e *mockStrategyTarget_Expecter) Ports(ctx interface{}) *mockStrategyTarget_Ports_Call { + return &mockStrategyTarget_Ports_Call{Call: _e.mock.On("Ports", ctx)} +} + +func (_c *mockStrategyTarget_Ports_Call) Run(run func(ctx context.Context)) *mockStrategyTarget_Ports_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *mockStrategyTarget_Ports_Call) Return(_a0 nat.PortMap, _a1 error) *mockStrategyTarget_Ports_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockStrategyTarget_Ports_Call) RunAndReturn(run func(context.Context) (nat.PortMap, error)) *mockStrategyTarget_Ports_Call { + _c.Call.Return(run) + return _c +} + +// State provides a mock function with given fields: _a0 +func (_m *mockStrategyTarget) State(_a0 context.Context) (*types.ContainerState, error) { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for State") + } + + var r0 *types.ContainerState + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*types.ContainerState, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(context.Context) *types.ContainerState); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ContainerState) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockStrategyTarget_State_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'State' +type mockStrategyTarget_State_Call struct { + *mock.Call +} + +// State is a helper method to define mock.On call +// - _a0 context.Context +func (_e *mockStrategyTarget_Expecter) State(_a0 interface{}) *mockStrategyTarget_State_Call { + return &mockStrategyTarget_State_Call{Call: _e.mock.On("State", _a0)} +} + +func (_c *mockStrategyTarget_State_Call) Run(run func(_a0 context.Context)) *mockStrategyTarget_State_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *mockStrategyTarget_State_Call) Return(_a0 *types.ContainerState, _a1 error) *mockStrategyTarget_State_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockStrategyTarget_State_Call) RunAndReturn(run func(context.Context) (*types.ContainerState, error)) *mockStrategyTarget_State_Call { + _c.Call.Return(run) + return _c +} + +// newMockStrategyTarget creates a new instance of mockStrategyTarget. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func newMockStrategyTarget(t interface { + mock.TestingT + Cleanup(func()) +}) *mockStrategyTarget { + mock := &mockStrategyTarget{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/wait/wait.go b/wait/wait.go index ccfd4735e2..7211d49b2d 100644 --- a/wait/wait.go +++ b/wait/wait.go @@ -31,6 +31,7 @@ type StrategyTarget interface { Logs(context.Context) (io.ReadCloser, error) Exec(context.Context, []string, ...exec.ProcessOption) (int, io.Reader, error) State(context.Context) (*types.ContainerState, error) + CopyFileFromContainer(ctx context.Context, filePath string) (io.ReadCloser, error) } func checkTarget(ctx context.Context, target StrategyTarget) error { diff --git a/wait/wait_test.go b/wait/wait_test.go index 079e64c2b3..b8c6248703 100644 --- a/wait/wait_test.go +++ b/wait/wait_test.go @@ -14,13 +14,14 @@ import ( var ErrPortNotFound = errors.New("port not found") type MockStrategyTarget struct { - HostImpl func(context.Context) (string, error) - InspectImpl func(context.Context) (*types.ContainerJSON, error) - PortsImpl func(context.Context) (nat.PortMap, error) - MappedPortImpl func(context.Context, nat.Port) (nat.Port, error) - LogsImpl func(context.Context) (io.ReadCloser, error) - ExecImpl func(context.Context, []string, ...tcexec.ProcessOption) (int, io.Reader, error) - StateImpl func(context.Context) (*types.ContainerState, error) + HostImpl func(context.Context) (string, error) + InspectImpl func(context.Context) (*types.ContainerJSON, error) + PortsImpl func(context.Context) (nat.PortMap, error) + MappedPortImpl func(context.Context, nat.Port) (nat.Port, error) + LogsImpl func(context.Context) (io.ReadCloser, error) + ExecImpl func(context.Context, []string, ...tcexec.ProcessOption) (int, io.Reader, error) + StateImpl func(context.Context) (*types.ContainerState, error) + CopyFileFromContainerImpl func(context.Context, string) (io.ReadCloser, error) } func (st MockStrategyTarget) Host(ctx context.Context) (string, error) { @@ -56,3 +57,7 @@ func (st MockStrategyTarget) Exec(ctx context.Context, cmd []string, options ... func (st MockStrategyTarget) State(ctx context.Context) (*types.ContainerState, error) { return st.StateImpl(ctx) } + +func (st MockStrategyTarget) CopyFileFromContainer(ctx context.Context, filePath string) (io.ReadCloser, error) { + return st.CopyFileFromContainerImpl(ctx, filePath) +} From 553afd3c51228cedff0fbbb744b6da94456dbfe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Thu, 5 Sep 2024 16:47:16 +0200 Subject: [PATCH 059/126] docs: refine heading badges in README (#2770) * docs: refine heading badges in README * docs: consistency across langs --- README.md | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index cf7e0fc2f9..ea21c63871 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,14 @@ # Testcontainers -[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=141451032&machine=standardLinux32gb&devcontainer_path=.devcontainer%2Fdevcontainer.json&location=EastUs) - -**Builds** - [![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) - -**Documentation** - [![GoDoc Reference](https://pkg.go.dev/badge/github.com/testcontainers/testcontainers-go.svg)](https://pkg.go.dev/github.com/testcontainers/testcontainers-go) - -**Social** - -[![Slack](https://img.shields.io/badge/Slack-4A154B?logo=slack)](https://testcontainers.slack.com/) - -**Code quality** - [![Go Report Card](https://goreportcard.com/badge/github.com/testcontainers/testcontainers-go)](https://goreportcard.com/report/github.com/testcontainers/testcontainers-go) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=testcontainers_testcontainers-go&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=testcontainers_testcontainers-go) +[![License](https://img.shields.io/badge/license-MIT-blue)](https://github.com/testcontainers/testcontainers-go/blob/main/LICENSE) -**License** +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=141451032&machine=standardLinux32gb&devcontainer_path=.devcontainer%2Fdevcontainer.json&location=EastUs) -[![License](https://img.shields.io/badge/license-MIT-blue)](https://github.com/testcontainers/testcontainers-go/blob/main/LICENSE) +[![Join our Slack](https://img.shields.io/badge/Slack-4A154B?logo=slack)](https://testcontainers.slack.com/) _Testcontainers for 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 From 6a947dc7a93efd578331b30ba565e6665cb424b1 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 9 Sep 2024 15:27:12 +0100 Subject: [PATCH 060/126] fix: docker config error handling when config file does not exist (#2772) Handle file not exist error in getDockerAuthConfigs, treating it as if no authentication was provided. Use config directly for cache instead of loading the file a second time which may be the wrong file if loaded from the environment. Correctly handle json decode errors in getDockerConfig instead of falling back to the default config, which would result in unexpected behaviour. Tests refactored to ensure all edge cases for getDockerConfig and getDockerAuthConfigs are handled. Fixes #2767 --- docker_auth.go | 49 ++--- docker_auth_test.go | 218 ++++++++++++-------- testdata/invalid-config/.docker/config.json | 3 + 3 files changed, 159 insertions(+), 111 deletions(-) create mode 100644 testdata/invalid-config/.docker/config.json diff --git a/docker_auth.go b/docker_auth.go index 99e2d2fdba..af0d415de9 100644 --- a/docker_auth.go +++ b/docker_auth.go @@ -8,7 +8,6 @@ import ( "encoding/json" "errors" "fmt" - "io" "net/url" "os" "sync" @@ -137,24 +136,12 @@ func (c *credentialsCache) Get(hostname, configKey string) (string, string, erro return user, password, nil } -// configFileKey returns a key to use for caching credentials based on +// configKey returns a key to use for caching credentials based on // the contents of the currently active config. -func configFileKey() (string, error) { - configPath, err := dockercfg.ConfigPath() - if err != nil { - return "", err - } - - f, err := os.Open(configPath) - if err != nil { - return "", fmt.Errorf("open config file: %w", err) - } - - defer f.Close() - +func configKey(cfg *dockercfg.Config) (string, error) { h := md5.New() - if _, err := io.Copy(h, f); err != nil { - return "", fmt.Errorf("copying config file: %w", err) + if err := json.NewEncoder(h).Encode(cfg); err != nil { + return "", fmt.Errorf("encode config: %w", err) } return hex.EncodeToString(h.Sum(nil)), nil @@ -165,10 +152,14 @@ func configFileKey() (string, error) { func getDockerAuthConfigs() (map[string]registry.AuthConfig, error) { cfg, err := getDockerConfig() if err != nil { + if errors.Is(err, os.ErrNotExist) { + return map[string]registry.AuthConfig{}, nil + } + return nil, err } - configKey, err := configFileKey() + key, err := configKey(cfg) if err != nil { return nil, err } @@ -195,7 +186,7 @@ func getDockerAuthConfigs() (map[string]registry.AuthConfig, error) { switch { case ac.Username == "" && ac.Password == "": // Look up credentials from the credential store. - u, p, err := creds.Get(k, configKey) + u, p, err := creds.Get(k, key) if err != nil { results <- authConfigResult{err: err} return @@ -218,7 +209,7 @@ func getDockerAuthConfigs() (map[string]registry.AuthConfig, error) { go func(k string) { defer wg.Done() - u, p, err := creds.Get(k, configKey) + u, p, err := creds.Get(k, key) if err != nil { results <- authConfigResult{err: err} return @@ -260,20 +251,20 @@ func getDockerAuthConfigs() (map[string]registry.AuthConfig, error) { // 1. the DOCKER_AUTH_CONFIG environment variable, unmarshalling it into a dockercfg.Config // 2. the DOCKER_CONFIG environment variable, as the path to the config file // 3. else it will load the default config file, which is ~/.docker/config.json -func getDockerConfig() (dockercfg.Config, error) { - dockerAuthConfig := os.Getenv("DOCKER_AUTH_CONFIG") - if dockerAuthConfig != "" { - cfg := dockercfg.Config{} - err := json.Unmarshal([]byte(dockerAuthConfig), &cfg) - if err == nil { - return cfg, nil +func getDockerConfig() (*dockercfg.Config, error) { + if env := os.Getenv("DOCKER_AUTH_CONFIG"); env != "" { + var cfg dockercfg.Config + if err := json.Unmarshal([]byte(env), &cfg); err != nil { + return nil, fmt.Errorf("unmarshal DOCKER_AUTH_CONFIG: %w", err) } + + return &cfg, nil } cfg, err := dockercfg.LoadDefaultConfig() if err != nil { - return cfg, err + return nil, fmt.Errorf("load default config: %w", err) } - return cfg, nil + return &cfg, nil } diff --git a/docker_auth_test.go b/docker_auth_test.go index 4e55d2b9bf..7e42ff83b9 100644 --- a/docker_auth_test.go +++ b/docker_auth_test.go @@ -14,7 +14,6 @@ import ( "github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/registry" "github.com/docker/docker/client" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go/internal/core" @@ -23,91 +22,87 @@ import ( const exampleAuth = "https://example-auth.com" -var testDockerConfigDirPath = filepath.Join("testdata", ".docker") - -var indexDockerIO = core.IndexDockerIO - -func TestGetDockerConfig(t *testing.T) { - const expectedErrorMessage = "Expected to find %s in auth configs" - - // Verify that the default docker config file exists before any test in this suite runs. - // Then, we can safely run the tests that rely on it. - defaultCfg, err := dockercfg.LoadDefaultConfig() - require.NoError(t, err) - require.NotEmpty(t, defaultCfg) - - t.Run("without DOCKER_CONFIG env var retrieves default", func(t *testing.T) { - t.Setenv("DOCKER_CONFIG", "") +func Test_getDockerConfig(t *testing.T) { + expectedConfig := &dockercfg.Config{ + AuthConfigs: map[string]dockercfg.AuthConfig{ + core.IndexDockerIO: {}, + "https://example.com": {}, + "https://my.private.registry": {}, + }, + CredentialsStore: "desktop", + } + t.Run("HOME/valid", func(t *testing.T) { + testDockerConfigHome(t, "testdata") cfg, err := getDockerConfig() require.NoError(t, err) - require.NotEmpty(t, cfg) + require.Equal(t, expectedConfig, cfg) + }) - assert.Equal(t, defaultCfg, cfg) + t.Run("HOME/not-found", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "not-found") + + cfg, err := getDockerConfig() + require.ErrorIs(t, err, os.ErrNotExist) + require.Nil(t, cfg) }) - t.Run("with DOCKER_CONFIG env var pointing to a non-existing file raises error", func(t *testing.T) { - t.Setenv("DOCKER_CONFIG", filepath.Join(testDockerConfigDirPath, "non-existing")) + t.Run("HOME/invalid-config", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "invalid-config") cfg, err := getDockerConfig() - require.Error(t, err) - require.Empty(t, cfg) + require.ErrorContains(t, err, "json: cannot unmarshal array") + require.Nil(t, cfg) }) - t.Run("with DOCKER_CONFIG env var", func(t *testing.T) { - t.Setenv("DOCKER_CONFIG", testDockerConfigDirPath) + t.Run("DOCKER_AUTH_CONFIG/valid", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "not-found") + t.Setenv("DOCKER_AUTH_CONFIG", dockerConfig) cfg, err := getDockerConfig() require.NoError(t, err) - require.NotEmpty(t, cfg) - - assert.Len(t, cfg.AuthConfigs, 3) + require.Equal(t, expectedConfig, cfg) + }) - authCfgs := cfg.AuthConfigs + t.Run("DOCKER_AUTH_CONFIG/invalid-config", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "not-found") + t.Setenv("DOCKER_AUTH_CONFIG", `{"auths": []}`) - if _, ok := authCfgs[indexDockerIO]; !ok { - t.Errorf(expectedErrorMessage, indexDockerIO) - } - if _, ok := authCfgs["https://example.com"]; !ok { - t.Errorf(expectedErrorMessage, "https://example.com") - } - if _, ok := authCfgs["https://my.private.registry"]; !ok { - t.Errorf(expectedErrorMessage, "https://my.private.registry") - } + cfg, err := getDockerConfig() + require.ErrorContains(t, err, "json: cannot unmarshal array") + require.Nil(t, cfg) }) - t.Run("DOCKER_AUTH_CONFIG env var takes precedence", func(t *testing.T) { - setAuthConfig(t, exampleAuth, "", "") - t.Setenv("DOCKER_CONFIG", testDockerConfigDirPath) + t.Run("DOCKER_CONFIG/valid", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "not-found") + t.Setenv("DOCKER_CONFIG", filepath.Join("testdata", ".docker")) cfg, err := getDockerConfig() require.NoError(t, err) - require.NotEmpty(t, cfg) - - assert.Len(t, cfg.AuthConfigs, 1) + require.Equal(t, expectedConfig, cfg) + }) - authCfgs := cfg.AuthConfigs + t.Run("DOCKER_CONFIG/invalid-config", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "not-found") + t.Setenv("DOCKER_CONFIG", filepath.Join("testdata", "invalid-config", ".docker")) - if _, ok := authCfgs[indexDockerIO]; ok { - t.Errorf("Not expected to find %s in auth configs", indexDockerIO) - } - if _, ok := authCfgs[exampleAuth]; !ok { - t.Errorf(expectedErrorMessage, exampleAuth) - } + cfg, err := getDockerConfig() + require.ErrorContains(t, err, "json: cannot unmarshal array") + require.Nil(t, cfg) }) +} +func TestDockerImageAuth(t *testing.T) { t.Run("retrieve auth with DOCKER_AUTH_CONFIG env var", func(t *testing.T) { username, password := "gopher", "secret" creds := setAuthConfig(t, exampleAuth, username, password) registry, cfg, err := DockerImageAuth(context.Background(), exampleAuth+"/my/image:latest") require.NoError(t, err) - require.NotEmpty(t, cfg) - - assert.Equal(t, exampleAuth, registry) - assert.Equal(t, username, cfg.Username) - assert.Equal(t, password, cfg.Password) - assert.Equal(t, creds, cfg.Auth) + require.Equal(t, exampleAuth, registry) + require.Equal(t, username, cfg.Username) + require.Equal(t, password, cfg.Password) + require.Equal(t, creds, cfg.Auth) }) t.Run("match registry authentication by host", func(t *testing.T) { @@ -117,12 +112,10 @@ func TestGetDockerConfig(t *testing.T) { registry, cfg, err := DockerImageAuth(context.Background(), imageReg+imagePath) require.NoError(t, err) - require.NotEmpty(t, cfg) - - assert.Equal(t, imageReg, registry) - assert.Equal(t, "gopher", cfg.Username) - assert.Equal(t, "secret", cfg.Password) - assert.Equal(t, base64, cfg.Auth) + require.Equal(t, imageReg, registry) + require.Equal(t, "gopher", cfg.Username) + require.Equal(t, "secret", cfg.Password) + require.Equal(t, base64, cfg.Auth) }) t.Run("fail to match registry authentication due to invalid host", func(t *testing.T) { @@ -135,8 +128,7 @@ func TestGetDockerConfig(t *testing.T) { registry, cfg, err := DockerImageAuth(context.Background(), imageReg+imagePath) require.ErrorIs(t, err, dockercfg.ErrCredentialsNotFound) require.Empty(t, cfg) - - assert.Equal(t, imageReg, registry) + require.Equal(t, imageReg, registry) }) t.Run("fail to match registry authentication by host with empty URL scheme creds and missing default", func(t *testing.T) { @@ -156,8 +148,7 @@ func TestGetDockerConfig(t *testing.T) { registry, cfg, err := DockerImageAuth(context.Background(), imageReg+imagePath) require.ErrorIs(t, err, dockercfg.ErrCredentialsNotFound) require.Empty(t, cfg) - - assert.Equal(t, imageReg, registry) + require.Equal(t, imageReg, registry) }) } @@ -391,27 +382,90 @@ func localAddress(t *testing.T) string { var dockerConfig string func Test_getDockerAuthConfigs(t *testing.T) { - t.Run("file", func(t *testing.T) { - got, err := getDockerAuthConfigs() + t.Run("HOME/valid", func(t *testing.T) { + testDockerConfigHome(t, "testdata") + + requireValidAuthConfig(t) + }) + + t.Run("HOME/not-found", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "not-exist") + + authConfigs, err := getDockerAuthConfigs() require.NoError(t, err) - require.NotNil(t, got) + require.NotNil(t, authConfigs) + require.Empty(t, authConfigs) + }) + + t.Run("HOME/invalid-config", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "invalid-config") + + authConfigs, err := getDockerAuthConfigs() + require.ErrorContains(t, err, "json: cannot unmarshal array") + require.Nil(t, authConfigs) }) - t.Run("env", func(t *testing.T) { + t.Run("DOCKER_AUTH_CONFIG/valid", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "not-exist") t.Setenv("DOCKER_AUTH_CONFIG", dockerConfig) - got, err := getDockerAuthConfigs() - require.NoError(t, err) + requireValidAuthConfig(t) + }) - // We can only check the keys as the values are not deterministic. - expected := map[string]registry.AuthConfig{ - "https://index.docker.io/v1/": {}, - "https://example.com": {}, - "https://my.private.registry": {}, - } - for k := range got { - got[k] = registry.AuthConfig{} - } - require.Equal(t, expected, got) + t.Run("DOCKER_AUTH_CONFIG/invalid-config", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "not-exist") + t.Setenv("DOCKER_AUTH_CONFIG", `{"auths": []}`) + + authConfigs, err := getDockerAuthConfigs() + require.ErrorContains(t, err, "json: cannot unmarshal array") + require.Nil(t, authConfigs) }) + + t.Run("DOCKER_CONFIG/valid", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "not-found") + t.Setenv("DOCKER_CONFIG", filepath.Join("testdata", ".docker")) + + requireValidAuthConfig(t) + }) + + t.Run("DOCKER_CONFIG/invalid-config", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "not-found") + t.Setenv("DOCKER_CONFIG", filepath.Join("testdata", "invalid-config", ".docker")) + + cfg, err := getDockerConfig() + require.ErrorContains(t, err, "json: cannot unmarshal array") + require.Nil(t, cfg) + }) +} + +// requireValidAuthConfig checks that the given authConfigs map contains the expected keys. +func requireValidAuthConfig(t *testing.T) { + t.Helper() + + authConfigs, err := getDockerAuthConfigs() + require.NoError(t, err) + + // We can only check the keys as the values are not deterministic as they depend + // on users environment. + expected := map[string]registry.AuthConfig{ + "https://index.docker.io/v1/": {}, + "https://example.com": {}, + "https://my.private.registry": {}, + } + for k := range authConfigs { + authConfigs[k] = registry.AuthConfig{} + } + require.Equal(t, expected, authConfigs) +} + +// testDockerConfigHome sets the user's home directory to the given path +// and unsets the DOCKER_CONFIG and DOCKER_AUTH_CONFIG environment variables. +func testDockerConfigHome(t *testing.T, dirs ...string) { + t.Helper() + + dir := filepath.Join(dirs...) + t.Setenv("DOCKER_AUTH_CONFIG", "") + t.Setenv("DOCKER_CONFIG", "") + t.Setenv("HOME", dir) + t.Setenv("USERPROFILE", dir) // Windows } diff --git a/testdata/invalid-config/.docker/config.json b/testdata/invalid-config/.docker/config.json new file mode 100644 index 0000000000..f0f444f355 --- /dev/null +++ b/testdata/invalid-config/.docker/config.json @@ -0,0 +1,3 @@ +{ + "auths": [] +} From b4f82947ee7295898235ee64df290eebe6e49bea Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 9 Sep 2024 17:16:11 +0100 Subject: [PATCH 061/126] ci: add generate for mocks (#2774) Add generation for mocks, which can be run using make generate or go generate ./... Correct output-format for golangci-lint as githubs-actions has been replaced by colored-line-numbers. Add pre-commit target to help check code is valid before pushing. Ensure generate and mod tidy don't result in changes. Run go mod tidy for all modules, some were out of date. Implements: #2765 --- .github/workflows/ci-test-go.yml | 14 +++++++++++++- commons-test.mk | 15 +++++++++++++-- examples/nginx/go.sum | 2 ++ examples/toxiproxy/go.sum | 2 ++ generate.go | 3 +++ modules/artemis/go.sum | 2 ++ modules/azurite/go.sum | 2 ++ modules/cassandra/go.sum | 2 ++ modules/chroma/go.sum | 2 ++ modules/clickhouse/go.sum | 2 ++ modules/cockroachdb/go.sum | 2 ++ modules/compose/go.sum | 2 ++ modules/couchbase/go.mod | 2 -- modules/couchbase/go.sum | 3 ++- modules/dolt/go.sum | 2 ++ modules/elasticsearch/go.sum | 2 ++ modules/gcloud/go.sum | 3 ++- modules/grafana-lgtm/go.sum | 2 ++ modules/inbucket/go.sum | 2 ++ modules/influxdb/go.sum | 2 ++ modules/k3s/go.sum | 2 ++ modules/k6/go.sum | 2 ++ modules/kafka/go.sum | 2 ++ modules/localstack/go.sum | 2 ++ modules/mariadb/go.sum | 2 ++ modules/minio/go.sum | 2 ++ modules/mockserver/go.sum | 2 ++ modules/mongodb/go.sum | 2 ++ modules/mssql/go.sum | 2 ++ modules/mysql/go.sum | 2 ++ modules/nats/go.sum | 2 ++ modules/neo4j/go.sum | 2 ++ modules/ollama/go.sum | 2 ++ modules/openfga/go.sum | 2 ++ modules/openldap/go.sum | 2 ++ modules/opensearch/go.sum | 2 ++ modules/postgres/go.sum | 2 ++ modules/qdrant/go.sum | 2 ++ modules/rabbitmq/go.sum | 2 ++ modules/redis/go.sum | 2 ++ modules/redpanda/go.sum | 2 ++ modules/registry/go.sum | 2 ++ modules/surrealdb/go.sum | 2 ++ modules/valkey/go.sum | 2 ++ modules/vault/go.sum | 2 ++ modules/vearch/go.sum | 2 ++ modules/weaviate/go.sum | 2 ++ 47 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 generate.go diff --git a/.github/workflows/ci-test-go.yml b/.github/workflows/ci-test-go.yml index c2c0747278..0a04327da1 100644 --- a/.github/workflows/ci-test-go.yml +++ b/.github/workflows/ci-test-go.yml @@ -85,13 +85,25 @@ jobs: # takes precedence over all other caching options. skip-cache: true + - name: generate + if: ${{ inputs.platform == 'ubuntu-latest' }} + working-directory: ./${{ inputs.project-directory }} + shell: bash + run: | + make generate + git --no-pager diff && [[ 0 -eq $(git status --porcelain | wc -l) ]] + - name: modVerify working-directory: ./${{ inputs.project-directory }} run: go mod verify - name: modTidy + if: ${{ inputs.platform == 'ubuntu-latest' }} working-directory: ./${{ inputs.project-directory }} - run: make tidy + shell: bash + run: | + make tidy + git --no-pager diff && [[ 0 -eq $(git status --porcelain | wc -l) ]] - name: ensure compilation working-directory: ./${{ inputs.project-directory }} diff --git a/commons-test.mk b/commons-test.mk index 04d0a6e70c..08c9e613ac 100644 --- a/commons-test.mk +++ b/commons-test.mk @@ -11,13 +11,17 @@ $(GOBIN)/golangci-lint: $(GOBIN)/gotestsum: $(call go_install,gotest.tools/gotestsum@latest) +$(GOBIN)/mockery: + $(call go_install,github.com/vektra/mockery/v2@v2.45) + .PHONY: install -install: $(GOBIN)/golangci-lint $(GOBIN)/gotestsum +install: $(GOBIN)/golangci-lint $(GOBIN)/gotestsum $(GOBIN)/mockery .PHONY: clean clean: rm $(GOBIN)/golangci-lint rm $(GOBIN)/gotestsum + rm $(GOBIN)/mockery .PHONY: dependencies-scan dependencies-scan: @@ -26,7 +30,11 @@ dependencies-scan: .PHONY: lint lint: $(GOBIN)/golangci-lint - golangci-lint run --out-format=github-actions --path-prefix=. --verbose -c $(ROOT_DIR)/.golangci.yml --fix + golangci-lint run --out-format=colored-line-number --path-prefix=. --verbose -c $(ROOT_DIR)/.golangci.yml --fix + +.PHONY: generate +generate: $(GOBIN)/mockery + go generate ./... .PHONY: test-% test-%: $(GOBIN)/gotestsum @@ -51,3 +59,6 @@ test-tools: $(GOBIN)/gotestsum .PHONY: tidy tidy: go mod tidy + +.PHONY: pre-commit +pre-commit: generate tidy lint diff --git a/examples/nginx/go.sum b/examples/nginx/go.sum index 85338720c8..ed514ea5ef 100644 --- a/examples/nginx/go.sum +++ b/examples/nginx/go.sum @@ -89,6 +89,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/examples/toxiproxy/go.sum b/examples/toxiproxy/go.sum index c62c0ac532..91a27d9fc8 100644 --- a/examples/toxiproxy/go.sum +++ b/examples/toxiproxy/go.sum @@ -105,6 +105,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/generate.go b/generate.go new file mode 100644 index 0000000000..19ae49695d --- /dev/null +++ b/generate.go @@ -0,0 +1,3 @@ +package testcontainers + +//go:generate mockery diff --git a/modules/artemis/go.sum b/modules/artemis/go.sum index 69f6d52997..db201d6672 100644 --- a/modules/artemis/go.sum +++ b/modules/artemis/go.sum @@ -101,6 +101,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/azurite/go.sum b/modules/azurite/go.sum index 90f8568088..0d2267c5a4 100644 --- a/modules/azurite/go.sum +++ b/modules/azurite/go.sum @@ -114,6 +114,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/cassandra/go.sum b/modules/cassandra/go.sum index 775e48ecf5..4b9d427f27 100644 --- a/modules/cassandra/go.sum +++ b/modules/cassandra/go.sum @@ -107,6 +107,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/modules/chroma/go.sum b/modules/chroma/go.sum index e7d70f0539..9e60fa93f1 100644 --- a/modules/chroma/go.sum +++ b/modules/chroma/go.sum @@ -103,6 +103,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/clickhouse/go.sum b/modules/clickhouse/go.sum index 2f09c4daae..cf050d1739 100644 --- a/modules/clickhouse/go.sum +++ b/modules/clickhouse/go.sum @@ -122,6 +122,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/modules/cockroachdb/go.sum b/modules/cockroachdb/go.sum index c051f94433..19481c176e 100644 --- a/modules/cockroachdb/go.sum +++ b/modules/cockroachdb/go.sum @@ -106,6 +106,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/modules/compose/go.sum b/modules/compose/go.sum index c05580192e..7a9b815421 100644 --- a/modules/compose/go.sum +++ b/modules/compose/go.sum @@ -459,6 +459,8 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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= diff --git a/modules/couchbase/go.mod b/modules/couchbase/go.mod index 96365d44e7..cc14840737 100644 --- a/modules/couchbase/go.mod +++ b/modules/couchbase/go.mod @@ -2,8 +2,6 @@ module github.com/testcontainers/testcontainers-go/modules/couchbase go 1.22 -toolchain go1.21.7 - require ( github.com/cenkalti/backoff/v4 v4.2.1 github.com/couchbase/gocb/v2 v2.7.2 diff --git a/modules/couchbase/go.sum b/modules/couchbase/go.sum index 737e1e5236..7f40c3b63f 100644 --- a/modules/couchbase/go.sum +++ b/modules/couchbase/go.sum @@ -134,8 +134,9 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs 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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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= diff --git a/modules/dolt/go.sum b/modules/dolt/go.sum index 7784d0b833..e2bb93b49d 100644 --- a/modules/dolt/go.sum +++ b/modules/dolt/go.sum @@ -91,6 +91,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/elasticsearch/go.sum b/modules/elasticsearch/go.sum index 59647a3793..046620bb60 100644 --- a/modules/elasticsearch/go.sum +++ b/modules/elasticsearch/go.sum @@ -101,6 +101,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/gcloud/go.sum b/modules/gcloud/go.sum index 31d286e7d0..07f1f7f404 100644 --- a/modules/gcloud/go.sum +++ b/modules/gcloud/go.sum @@ -190,8 +190,9 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/modules/grafana-lgtm/go.sum b/modules/grafana-lgtm/go.sum index 9eb14f31cb..1eced8de79 100644 --- a/modules/grafana-lgtm/go.sum +++ b/modules/grafana-lgtm/go.sum @@ -103,6 +103,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/inbucket/go.sum b/modules/inbucket/go.sum index 2e403c06ad..62be48931c 100644 --- a/modules/inbucket/go.sum +++ b/modules/inbucket/go.sum @@ -100,6 +100,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/influxdb/go.sum b/modules/influxdb/go.sum index ad81df94f6..875bf9d6a1 100644 --- a/modules/influxdb/go.sum +++ b/modules/influxdb/go.sum @@ -99,6 +99,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/k3s/go.sum b/modules/k3s/go.sum index e08a07dd42..86dfae5fc0 100644 --- a/modules/k3s/go.sum +++ b/modules/k3s/go.sum @@ -143,6 +143,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/modules/k6/go.sum b/modules/k6/go.sum index 85338720c8..ed514ea5ef 100644 --- a/modules/k6/go.sum +++ b/modules/k6/go.sum @@ -89,6 +89,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/kafka/go.sum b/modules/kafka/go.sum index 778434567d..9310807a50 100644 --- a/modules/kafka/go.sum +++ b/modules/kafka/go.sum @@ -127,6 +127,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/modules/localstack/go.sum b/modules/localstack/go.sum index 532bf9e05b..93de565615 100644 --- a/modules/localstack/go.sum +++ b/modules/localstack/go.sum @@ -141,6 +141,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/mariadb/go.sum b/modules/mariadb/go.sum index 7784d0b833..e2bb93b49d 100644 --- a/modules/mariadb/go.sum +++ b/modules/mariadb/go.sum @@ -91,6 +91,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/minio/go.sum b/modules/minio/go.sum index 55013e4221..e837e4f48e 100644 --- a/modules/minio/go.sum +++ b/modules/minio/go.sum @@ -110,6 +110,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/modules/mockserver/go.sum b/modules/mockserver/go.sum index e752fd0812..acf88d134a 100644 --- a/modules/mockserver/go.sum +++ b/modules/mockserver/go.sum @@ -93,6 +93,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/mongodb/go.sum b/modules/mongodb/go.sum index 0f2d5d5336..bc45e6d333 100644 --- a/modules/mongodb/go.sum +++ b/modules/mongodb/go.sum @@ -95,6 +95,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/mssql/go.sum b/modules/mssql/go.sum index 4160a61ee2..2f512564ff 100644 --- a/modules/mssql/go.sum +++ b/modules/mssql/go.sum @@ -113,6 +113,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/mysql/go.sum b/modules/mysql/go.sum index 7784d0b833..e2bb93b49d 100644 --- a/modules/mysql/go.sum +++ b/modules/mysql/go.sum @@ -91,6 +91,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/nats/go.sum b/modules/nats/go.sum index 11a786d5d4..61daa84ab4 100644 --- a/modules/nats/go.sum +++ b/modules/nats/go.sum @@ -95,6 +95,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/neo4j/go.sum b/modules/neo4j/go.sum index 2576f66232..8cccf1cd87 100644 --- a/modules/neo4j/go.sum +++ b/modules/neo4j/go.sum @@ -91,6 +91,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/ollama/go.sum b/modules/ollama/go.sum index 07f9ef689f..d2ff261f5b 100644 --- a/modules/ollama/go.sum +++ b/modules/ollama/go.sum @@ -93,6 +93,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/openfga/go.sum b/modules/openfga/go.sum index a2fe09d6b4..1ab48ebfe2 100644 --- a/modules/openfga/go.sum +++ b/modules/openfga/go.sum @@ -93,6 +93,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/openldap/go.sum b/modules/openldap/go.sum index 57de498077..eb7f8b79e3 100644 --- a/modules/openldap/go.sum +++ b/modules/openldap/go.sum @@ -98,6 +98,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/opensearch/go.sum b/modules/opensearch/go.sum index 85338720c8..ed514ea5ef 100644 --- a/modules/opensearch/go.sum +++ b/modules/opensearch/go.sum @@ -89,6 +89,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/postgres/go.sum b/modules/postgres/go.sum index 4293379353..1b1f37ba8d 100644 --- a/modules/postgres/go.sum +++ b/modules/postgres/go.sum @@ -106,6 +106,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/modules/qdrant/go.sum b/modules/qdrant/go.sum index c4425e8182..c38866d982 100644 --- a/modules/qdrant/go.sum +++ b/modules/qdrant/go.sum @@ -91,6 +91,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/rabbitmq/go.sum b/modules/rabbitmq/go.sum index f57610f497..bf809122da 100644 --- a/modules/rabbitmq/go.sum +++ b/modules/rabbitmq/go.sum @@ -96,6 +96,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/redis/go.sum b/modules/redis/go.sum index 1698de2ecf..afc80497f0 100644 --- a/modules/redis/go.sum +++ b/modules/redis/go.sum @@ -111,6 +111,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/redpanda/go.sum b/modules/redpanda/go.sum index cf26162896..6b3772dc87 100644 --- a/modules/redpanda/go.sum +++ b/modules/redpanda/go.sum @@ -101,6 +101,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/registry/go.sum b/modules/registry/go.sum index 5583e9b0fc..28367d0020 100644 --- a/modules/registry/go.sum +++ b/modules/registry/go.sum @@ -96,6 +96,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/surrealdb/go.sum b/modules/surrealdb/go.sum index 4a82bd3217..d39dac7fa4 100644 --- a/modules/surrealdb/go.sum +++ b/modules/surrealdb/go.sum @@ -91,6 +91,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/valkey/go.sum b/modules/valkey/go.sum index f92f0dbcc7..1256ebe114 100644 --- a/modules/valkey/go.sum +++ b/modules/valkey/go.sum @@ -96,6 +96,8 @@ github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnj github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= diff --git a/modules/vault/go.sum b/modules/vault/go.sum index 5bed30736e..8fa2d5b6df 100644 --- a/modules/vault/go.sum +++ b/modules/vault/go.sum @@ -119,6 +119,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/vearch/go.sum b/modules/vearch/go.sum index 85338720c8..ed514ea5ef 100644 --- a/modules/vearch/go.sum +++ b/modules/vearch/go.sum @@ -89,6 +89,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= diff --git a/modules/weaviate/go.sum b/modules/weaviate/go.sum index 4d55fd59af..b2be18dab8 100644 --- a/modules/weaviate/go.sum +++ b/modules/weaviate/go.sum @@ -203,6 +203,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= From b60497e9c7921c637aa2213bb9bffb486346c15d Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Thu, 12 Sep 2024 09:47:04 +0100 Subject: [PATCH 062/126] fix: resource clean up for tests and examples (#2738) Ensure that all resources are cleaned up for tests and examples even if they fail. This leverages new helpers in testcontainers: * TerminateContainer for examples * CleanupContainer and CleanupNetwork for tests These are required ensuring that containers that are created but fail in later actions are returned alongside the error so that clean up can be performed. Consistently clean up created networks using a new context to ensure that the removal gets run even if original context has timed out or been cancelled. Use fmt.Print instead of log.Fatal to ensure that defers are run in all examples again ensuring that clean up is processed. Call Stop from Terminate to ensure that child containers are shutdown correctly on clean up as the hard coded timeout using by ContainerRemove is too short to allow this to happen correctly. Clean up of test logic replacing manual checks and asserts with require to make them more concise and hence easier to understand. Quiet test output by either capturing or disabling output so it's easier to identify issues when tests are run in non verbose mode. Clarify source of errors with wrapping and update tests to handle. Ensure that port forwarding container is shutdown if an error occurs during setup so it isn't orphaned. Shutdown the port forwarding container on both stop and terminate to prevent it being orphaned when the Stop is used. Add missing error checks to tests. Remove unused nolint directives and enable the nolintlint to catch any regressions. Don't use container as a variable as its overused. --- .gitignore | 5 +- .golangci.yml | 1 + cleanup.go | 107 ++++++ container_test.go | 53 ++- docker.go | 31 +- docker_auth_test.go | 15 +- docker_exec_test.go | 21 +- docker_files_test.go | 67 ++-- docker_test.go | 321 ++++++++---------- docs/features/common_functional_options.md | 3 +- docs/features/creating_container.md | 101 ++++-- docs/quickstart.md | 17 +- examples/nginx/go.mod | 9 +- examples/nginx/go.sum | 9 + examples/nginx/nginx.go | 15 +- examples/nginx/nginx_test.go | 25 +- examples/toxiproxy/go.mod | 7 +- examples/toxiproxy/go.sum | 9 + examples/toxiproxy/redis.go | 8 +- examples/toxiproxy/toxiproxy.go | 14 +- examples/toxiproxy/toxiproxy_test.go | 70 +--- from_dockerfile_test.go | 50 +-- generic_test.go | 6 +- image_substitutors_test.go | 1 + image_test.go | 14 +- lifecycle.go | 4 +- lifecycle_test.go | 139 ++++---- logconsumer_test.go | 73 ++-- modulegen/_template/examples_test.go.tmpl | 16 +- modulegen/_template/module.go.tmpl | 9 +- modulegen/_template/module_test.go.tmpl | 16 +- modulegen/main_test.go | 24 +- modules/artemis/artemis.go | 12 +- modules/artemis/artemis_test.go | 14 +- modules/artemis/examples_test.go | 23 +- modules/azurite/azurite.go | 9 +- modules/azurite/azurite_test.go | 17 +- modules/azurite/examples_test.go | 110 +++--- modules/azurite/go.mod | 7 +- modules/azurite/go.sum | 9 + modules/cassandra/cassandra.go | 10 +- modules/cassandra/cassandra_test.go | 61 +--- modules/cassandra/examples_test.go | 26 +- modules/chroma/chroma.go | 9 +- modules/chroma/chroma_test.go | 21 +- modules/chroma/examples_test.go | 71 ++-- modules/clickhouse/clickhouse.go | 14 +- modules/clickhouse/clickhouse_test.go | 124 +++---- modules/clickhouse/examples_test.go | 21 +- modules/cockroachdb/cockroachdb.go | 10 +- modules/cockroachdb/cockroachdb_test.go | 72 ++-- modules/cockroachdb/examples_test.go | 23 +- modules/compose/compose_api.go | 4 + modules/consul/consul.go | 9 +- modules/consul/consul_test.go | 6 +- modules/consul/examples_test.go | 39 ++- modules/couchbase/couchbase.go | 14 +- modules/couchbase/couchbase_test.go | 73 ++-- modules/couchbase/examples_test.go | 24 +- modules/couchbase/go.mod | 6 +- modules/couchbase/go.sum | 8 + modules/dolt/dolt.go | 15 +- modules/dolt/dolt_test.go | 126 +++---- modules/dolt/examples_test.go | 41 ++- modules/dolt/go.mod | 7 +- modules/dolt/go.sum | 9 + modules/elasticsearch/elasticsearch.go | 25 +- modules/elasticsearch/elasticsearch_test.go | 54 +-- modules/elasticsearch/examples_test.go | 48 +-- modules/gcloud/bigquery.go | 15 +- modules/gcloud/bigquery_test.go | 26 +- modules/gcloud/bigtable.go | 10 +- modules/gcloud/bigtable_test.go | 32 +- modules/gcloud/datastore.go | 10 +- modules/gcloud/datastore_test.go | 23 +- modules/gcloud/firestore.go | 10 +- modules/gcloud/firestore_test.go | 29 +- modules/gcloud/gcloud.go | 25 +- modules/gcloud/go.mod | 4 + modules/gcloud/go.sum | 8 + modules/gcloud/pubsub.go | 10 +- modules/gcloud/pubsub_test.go | 32 +- modules/gcloud/spanner.go | 7 +- modules/gcloud/spanner_test.go | 44 ++- modules/grafana-lgtm/examples_test.go | 113 ++++--- modules/grafana-lgtm/go.mod | 5 + modules/grafana-lgtm/go.sum | 10 + modules/grafana-lgtm/grafana.go | 4 +- modules/grafana-lgtm/grafana_test.go | 37 +- modules/inbucket/examples_test.go | 17 +- modules/inbucket/inbucket.go | 9 +- modules/inbucket/inbucket_test.go | 15 +- modules/influxdb/examples_test.go | 17 +- modules/influxdb/influxdb.go | 9 +- modules/influxdb/influxdb_test.go | 21 +- modules/k3s/go.mod | 4 +- modules/k3s/k3s.go | 9 +- modules/k3s/k3s_example_test.go | 29 +- modules/k3s/k3s_test.go | 97 ++---- modules/k6/examples_test.go | 43 ++- modules/k6/go.mod | 7 +- modules/k6/go.sum | 9 + modules/k6/k6.go | 31 +- modules/k6/k6_test.go | 44 ++- modules/kafka/examples_test.go | 17 +- modules/kafka/go.mod | 6 +- modules/kafka/go.sum | 9 + modules/kafka/kafka.go | 11 +- modules/kafka/kafka_test.go | 58 +--- modules/localstack/examples_test.go | 96 +++--- modules/localstack/localstack.go | 10 +- modules/localstack/localstack_test.go | 34 +- modules/localstack/v1/s3_test.go | 5 +- modules/localstack/v2/s3_test.go | 5 +- modules/mariadb/examples_test.go | 17 +- modules/mariadb/go.mod | 7 +- modules/mariadb/go.sum | 9 + modules/mariadb/mariadb.go | 16 +- modules/mariadb/mariadb_test.go | 176 +++------- modules/milvus/examples_test.go | 42 +-- modules/milvus/milvus.go | 9 +- modules/milvus/milvus_test.go | 12 +- modules/minio/examples_test.go | 17 +- modules/minio/go.mod | 7 +- modules/minio/go.sum | 9 + modules/minio/minio.go | 9 +- modules/minio/minio_test.go | 50 +-- modules/mockserver/examples_test.go | 42 +-- modules/mockserver/go.mod | 5 + modules/mockserver/go.sum | 9 + modules/mongodb/examples_test.go | 64 ++-- modules/mongodb/go.mod | 7 +- modules/mongodb/go.sum | 9 + modules/mongodb/mongodb.go | 12 +- modules/mongodb/mongodb_test.go | 29 +- modules/mssql/examples_test.go | 17 +- modules/mssql/go.mod | 7 +- modules/mssql/go.sum | 9 + modules/mssql/mssql.go | 12 +- modules/mssql/mssql_test.go | 156 +++------ modules/mysql/examples_test.go | 44 +-- modules/mysql/go.mod | 7 +- modules/mysql/go.sum | 9 + modules/mysql/mysql.go | 16 +- modules/mysql/mysql_test.go | 119 +++---- modules/nats/examples_test.go | 128 ++++--- modules/nats/go.mod | 7 +- modules/nats/go.sum | 9 + modules/nats/nats.go | 17 +- modules/nats/nats_test.go | 62 ++-- modules/neo4j/examples_test.go | 17 +- modules/neo4j/go.mod | 7 +- modules/neo4j/go.sum | 9 + modules/neo4j/neo4j.go | 9 +- modules/neo4j/neo4j_test.go | 78 ++--- modules/ollama/examples_test.go | 69 ++-- modules/ollama/go.mod | 6 +- modules/ollama/go.sum | 8 + modules/ollama/ollama.go | 9 +- modules/ollama/ollama_test.go | 102 ++---- modules/openfga/examples_test.go | 94 +++--- modules/openfga/go.mod | 7 +- modules/openfga/go.sum | 9 + modules/openfga/openfga.go | 9 +- modules/openfga/openfga_test.go | 17 +- modules/openldap/examples_test.go | 45 +-- modules/openldap/go.mod | 7 +- modules/openldap/go.sum | 9 + modules/openldap/openldap.go | 19 +- modules/openldap/openldap_test.go | 176 +++------- modules/opensearch/examples_test.go | 17 +- modules/opensearch/go.mod | 7 +- modules/opensearch/go.sum | 9 + modules/opensearch/opensearch.go | 9 +- modules/opensearch/opensearch_test.go | 31 +- modules/postgres/examples_test.go | 16 +- modules/postgres/postgres.go | 19 +- modules/postgres/postgres_test.go | 274 +++++---------- modules/pulsar/examples_test.go | 17 +- modules/pulsar/pulsar.go | 13 +- modules/pulsar/pulsar_test.go | 31 +- modules/qdrant/examples_test.go | 59 ++-- modules/qdrant/go.mod | 7 +- modules/qdrant/go.sum | 9 + modules/qdrant/qdrant.go | 9 +- modules/qdrant/qdrant_test.go | 54 +-- modules/rabbitmq/examples_test.go | 109 +++--- modules/rabbitmq/go.mod | 19 +- modules/rabbitmq/go.sum | 7 + modules/rabbitmq/rabbitmq.go | 15 +- modules/rabbitmq/rabbitmq_test.go | 59 +--- modules/redis/examples_test.go | 17 +- modules/redis/redis.go | 9 +- modules/redis/redis_test.go | 31 +- modules/redpanda/examples_test.go | 17 +- modules/redpanda/options.go | 2 +- modules/redpanda/redpanda.go | 42 +-- modules/redpanda/redpanda_test.go | 128 +++---- modules/registry/examples_test.go | 103 +++--- modules/registry/registry.go | 10 +- modules/registry/registry_test.go | 31 +- modules/surrealdb/examples_test.go | 17 +- modules/surrealdb/go.mod | 5 + modules/surrealdb/go.sum | 9 + modules/surrealdb/surrealdb.go | 9 +- modules/surrealdb/surrealdb_test.go | 120 ++----- modules/valkey/examples_test.go | 17 +- modules/valkey/valkey.go | 9 +- modules/valkey/valkey_test.go | 31 +- modules/vault/examples_test.go | 52 +-- modules/vault/vault.go | 9 +- modules/vault/vault_test.go | 9 +- modules/vearch/examples_test.go | 17 +- modules/vearch/go.mod | 9 +- modules/vearch/go.sum | 9 + modules/vearch/vearch.go | 9 +- modules/vearch/vearch_test.go | 32 +- modules/weaviate/examples_test.go | 52 +-- modules/weaviate/go.mod | 5 +- modules/weaviate/weaviate.go | 9 +- modules/weaviate/weaviate_test.go | 36 +- mounts_test.go | 14 +- network/examples_test.go | 4 +- network/network_test.go | 224 ++++-------- options_test.go | 12 +- parallel.go | 9 +- parallel_test.go | 4 +- port_forwarding.go | 67 ++-- port_forwarding_test.go | 17 +- reaper_test.go | 40 +-- testcontainers_test.go | 3 +- testdata/echoserver.go | 3 +- testhelpers_test.go | 19 -- testing.go | 98 ++++++ testing_test.go | 81 ++++- wait/exec_test.go | 30 +- wait/file.go | 2 +- wait/host_port.go | 26 +- wait/host_port_test.go | 78 ++--- wait/http_test.go | 356 +++++++------------- wait/testdata/main.go | 2 +- 241 files changed, 3914 insertions(+), 4199 deletions(-) create mode 100644 cleanup.go diff --git a/.gitignore b/.gitignore index 4b420b86b4..e529356359 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,7 @@ TEST-*.xml tcvenv -**/go.work \ No newline at end of file +**/go.work + +# VS Code settings +.vscode diff --git a/.golangci.yml b/.golangci.yml index 1791b9caac..861e0cbc5c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,6 +8,7 @@ linters: - nonamedreturns - testifylint - errcheck + - nolintlint linters-settings: errorlint: diff --git a/cleanup.go b/cleanup.go new file mode 100644 index 0000000000..e2d52440b9 --- /dev/null +++ b/cleanup.go @@ -0,0 +1,107 @@ +package testcontainers + +import ( + "context" + "errors" + "fmt" + "reflect" + "time" +) + +// terminateOptions is a type that holds the options for terminating a container. +type terminateOptions struct { + ctx context.Context + timeout *time.Duration + volumes []string +} + +// TerminateOption is a type that represents an option for terminating a container. +type TerminateOption func(*terminateOptions) + +// StopContext returns a TerminateOption that sets the context. +// Default: context.Background(). +func StopContext(ctx context.Context) TerminateOption { + return func(c *terminateOptions) { + c.ctx = ctx + } +} + +// StopTimeout returns a TerminateOption that sets the timeout. +// Default: See [Container.Stop]. +func StopTimeout(timeout time.Duration) TerminateOption { + return func(c *terminateOptions) { + c.timeout = &timeout + } +} + +// RemoveVolumes returns a TerminateOption that sets additional volumes to remove. +// This is useful when the container creates named volumes that should be removed +// which are not removed by default. +// Default: nil. +func RemoveVolumes(volumes ...string) TerminateOption { + return func(c *terminateOptions) { + c.volumes = volumes + } +} + +// TerminateContainer calls [Container.Terminate] on the container if it is not nil. +// +// This should be called as a defer directly after [GenericContainer](...) +// or a modules Run(...) to ensure the container is terminated when the +// function ends. +func TerminateContainer(container Container, options ...TerminateOption) error { + if isNil(container) { + return nil + } + + c := &terminateOptions{ + ctx: context.Background(), + } + + for _, opt := range options { + opt(c) + } + + // TODO: Add a timeout when terminate supports it. + err := container.Terminate(c.ctx) + if !isCleanupSafe(err) { + return fmt.Errorf("terminate: %w", err) + } + + // Remove additional volumes if any. + if len(c.volumes) == 0 { + return nil + } + + client, err := NewDockerClientWithOpts(c.ctx) + if err != nil { + return fmt.Errorf("docker client: %w", err) + } + + defer client.Close() + + // Best effort to remove all volumes. + var errs []error + for _, volume := range c.volumes { + if errRemove := client.VolumeRemove(c.ctx, volume, true); errRemove != nil { + errs = append(errs, fmt.Errorf("volume remove %q: %w", volume, errRemove)) + } + } + + return errors.Join(errs...) +} + +// isNil returns true if val is nil or an nil instance false otherwise. +func isNil(val any) bool { + if val == nil { + return true + } + + valueOf := reflect.ValueOf(val) + switch valueOf.Kind() { + case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: + return valueOf.IsNil() + default: + return false + } +} diff --git a/container_test.go b/container_test.go index 3cb14ac296..074a818569 100644 --- a/container_test.go +++ b/container_test.go @@ -290,8 +290,7 @@ func Test_BuildImageWithContexts(t *testing.T) { ContainerRequest: req, Started: true, }) - - defer terminateContainerOnEnd(t, ctx, c) + testcontainers.CleanupContainer(t, c) if testCase.ExpectedError != "" { require.EqualError(t, err, testCase.ExpectedError) @@ -317,7 +316,7 @@ func Test_GetLogsFromFailedContainer(t *testing.T) { ContainerRequest: req, Started: true, }) - terminateContainerOnEnd(t, ctx, c) + testcontainers.CleanupContainer(t, c) require.Error(t, err) require.Contains(t, err.Error(), "container exited with code 0") @@ -417,25 +416,21 @@ func TestImageSubstitutors(t *testing.T) { ImageSubstitutors: test.substitutors, } - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, }) + testcontainers.CleanupContainer(t, ctr) if test.expectedError != nil { require.ErrorIs(t, err, test.expectedError) return } - if err != nil { - t.Fatal(err) - } - defer func() { - terminateContainerOnEnd(t, ctx, container) - }() + require.NoError(t, err) // enforce the concrete type, as GenericContainer returns an interface, // which will be changed in future implementations of the library - dockerContainer := container.(*testcontainers.DockerContainer) + dockerContainer := ctr.(*testcontainers.DockerContainer) assert.Equal(t, test.expectedImage, dockerContainer.Image) }) } @@ -455,21 +450,17 @@ func TestShouldStartContainersInParallel(t *testing.T) { ExposedPorts: []string{nginxDefaultPort}, WaitingFor: wait.ForHTTP("/").WithStartupTimeout(10 * time.Second), } - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, }) - if err != nil { - t.Fatalf("could not start container: %v", err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + // mappedPort { - port, err := container.MappedPort(ctx, nginxDefaultPort) + port, err := ctr.MappedPort(ctx, nginxDefaultPort) // } - if err != nil { - t.Fatalf("could not get mapped port: %v", err) - } - - terminateContainerOnEnd(t, ctx, container) + require.NoError(t, err) t.Logf("Parallel container [iteration_%d] listening on %d\n", i, port.Int()) }) @@ -480,28 +471,28 @@ func ExampleGenericContainer_withSubstitutors() { ctx := context.Background() // applyImageSubstitutors { - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ Image: "alpine:latest", ImageSubstitutors: []testcontainers.ImageSubstitutor{dockerImageSubstitutor{}}, }, Started: true, }) - // } - if err != nil { - log.Fatalf("could not start container: %v", err) - } - defer func() { - err := container.Terminate(ctx) - if err != nil { - log.Fatalf("could not terminate container: %v", err) + if err := testcontainers.TerminateContainer(ctr); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + // } + if err != nil { + log.Printf("could not start container: %v", err) + return + } + // enforce the concrete type, as GenericContainer returns an interface, // which will be changed in future implementations of the library - dockerContainer := container.(*testcontainers.DockerContainer) + dockerContainer := ctr.(*testcontainers.DockerContainer) fmt.Println(dockerContainer.Image) diff --git a/docker.go b/docker.go index 5f6c415627..dcd962ffc8 100644 --- a/docker.go +++ b/docker.go @@ -259,9 +259,14 @@ func (c *DockerContainer) Start(ctx context.Context) error { // // If the container is already stopped, the method is a no-op. func (c *DockerContainer) Stop(ctx context.Context, timeout *time.Duration) error { + // Note we can't check isRunning here because we allow external creation + // without exposing the ability to fully initialize the container state. + // See: https://github.com/testcontainers/testcontainers-go/issues/2667 + // TODO: Add a check for isRunning when the above issue is resolved. + err := c.stoppingHook(ctx) if err != nil { - return err + return fmt.Errorf("stopping hook: %w", err) } var options container.StopOptions @@ -272,22 +277,38 @@ func (c *DockerContainer) Stop(ctx context.Context, timeout *time.Duration) erro } if err := c.provider.client.ContainerStop(ctx, c.ID, options); err != nil { - return err + return fmt.Errorf("container stop: %w", err) } + defer c.provider.Close() c.isRunning = false err = c.stoppedHook(ctx) if err != nil { - return err + return fmt.Errorf("stopped hook: %w", err) } return nil } -// Terminate is used to kill the container. It is usually triggered by as defer function. +// Terminate calls stops and then removes the container including its volumes. +// If its image was built it and all child images are also removed unless +// the [FromDockerfile.KeepImage] on the [ContainerRequest] was set to true. +// +// The following hooks are called in order: +// - [ContainerLifecycleHooks.PreTerminates] +// - [ContainerLifecycleHooks.PostTerminates] func (c *DockerContainer) Terminate(ctx context.Context) error { + // ContainerRemove hardcodes stop timeout to 3 seconds which is too short + // to ensure that child containers are stopped so we manually call stop. + // TODO: make this configurable via a functional option. + timeout := 10 * time.Second + err := c.Stop(ctx, &timeout) + if err != nil && !isCleanupSafe(err) { + return fmt.Errorf("stop: %w", err) + } + select { // close reaper if it was created case c.terminationSignal <- true: @@ -296,6 +317,8 @@ func (c *DockerContainer) Terminate(ctx context.Context) error { defer c.provider.client.Close() + // TODO: Handle errors from ContainerRemove more correctly, e.g. should we + // run the terminated hook? errs := []error{ c.terminatingHook(ctx), c.provider.client.ContainerRemove(ctx, c.GetContainerID(), container.RemoveOptions{ diff --git a/docker_auth_test.go b/docker_auth_test.go index 7e42ff83b9..d494d6d12e 100644 --- a/docker_auth_test.go +++ b/docker_auth_test.go @@ -164,8 +164,8 @@ func TestBuildContainerFromDockerfile(t *testing.T) { } redisC, err := prepareRedisImage(ctx, req) + CleanupContainer(t, redisC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, redisC) } // removeImageFromLocalCache removes the image from the local cache @@ -202,8 +202,7 @@ func TestBuildContainerFromDockerfileWithDockerAuthConfig(t *testing.T) { BuildArgs: map[string]*string{ "REGISTRY_HOST": ®istryHost, }, - Repo: "localhost", - PrintBuildLog: true, + Repo: "localhost", }, AlwaysPullImage: true, // make sure the authentication takes place ExposedPorts: []string{"6379/tcp"}, @@ -211,7 +210,7 @@ func TestBuildContainerFromDockerfileWithDockerAuthConfig(t *testing.T) { } redisC, err := prepareRedisImage(ctx, req) - terminateContainerOnEnd(t, ctx, redisC) + CleanupContainer(t, redisC) require.NoError(t, err) } @@ -237,7 +236,7 @@ func TestBuildContainerFromDockerfileShouldFailWithWrongDockerAuthConfig(t *test } redisC, err := prepareRedisImage(ctx, req) - terminateContainerOnEnd(t, ctx, redisC) + CleanupContainer(t, redisC) require.Error(t, err) } @@ -259,7 +258,7 @@ func TestCreateContainerFromPrivateRegistry(t *testing.T) { ContainerRequest: req, Started: true, }) - terminateContainerOnEnd(t, ctx, redisContainer) + CleanupContainer(t, redisContainer) require.NoError(t, err) } @@ -298,6 +297,7 @@ func prepareLocalRegistryWithAuth(t *testing.T) string { } registryC, err := GenericContainer(ctx, genContainerReq) + CleanupContainer(t, registryC) require.NoError(t, err) mappedPort, err := registryC.MappedPort(ctx, "5000/tcp") @@ -310,9 +310,6 @@ func prepareLocalRegistryWithAuth(t *testing.T) string { t.Cleanup(func() { removeImageFromLocalCache(t, addr+"/redis:5.0-alpine") }) - t.Cleanup(func() { - require.NoError(t, registryC.Terminate(context.Background())) - }) _, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) diff --git a/docker_exec_test.go b/docker_exec_test.go index 11f187c226..65f9e71e07 100644 --- a/docker_exec_test.go +++ b/docker_exec_test.go @@ -51,19 +51,18 @@ func TestExecWithOptions(t *testing.T) { Image: nginxAlpineImage, } - container, err := GenericContainer(ctx, GenericContainerRequest{ + ctr, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: req, Started: true, }) - + CleanupContainer(t, ctr) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, container) // always append the multiplexed option for having the output // in a readable format tt.opts = append(tt.opts, tcexec.Multiplexed()) - code, reader, err := container.Exec(ctx, tt.cmds, tt.opts...) + code, reader, err := ctr.Exec(ctx, tt.cmds, tt.opts...) require.NoError(t, err) require.Zero(t, code) require.NotNil(t, reader) @@ -84,15 +83,14 @@ func TestExecWithMultiplexedResponse(t *testing.T) { Image: nginxAlpineImage, } - container, err := GenericContainer(ctx, GenericContainerRequest{ + ctr, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: req, Started: true, }) - + CleanupContainer(t, ctr) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, container) - code, reader, err := container.Exec(ctx, []string{"sh", "-c", "echo stdout; echo stderr >&2"}, tcexec.Multiplexed()) + code, reader, err := ctr.Exec(ctx, []string{"sh", "-c", "echo stdout; echo stderr >&2"}, tcexec.Multiplexed()) require.NoError(t, err) require.Zero(t, code) require.NotNil(t, reader) @@ -112,15 +110,14 @@ func TestExecWithNonMultiplexedResponse(t *testing.T) { Image: nginxAlpineImage, } - container, err := GenericContainer(ctx, GenericContainerRequest{ + ctr, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: req, Started: true, }) - + CleanupContainer(t, ctr) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, container) - code, reader, err := container.Exec(ctx, []string{"sh", "-c", "echo stdout; echo stderr >&2"}) + code, reader, err := ctr.Exec(ctx, []string{"sh", "-c", "echo stdout; echo stderr >&2"}) require.NoError(t, err) require.Zero(t, code) require.NotNil(t, reader) diff --git a/docker_files_test.go b/docker_files_test.go index 6fcfc92a0b..6a767e6163 100644 --- a/docker_files_test.go +++ b/docker_files_test.go @@ -28,7 +28,7 @@ func TestCopyFileToContainer(t *testing.T) { t.Fatal(err) } - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ Image: "docker.io/bash", Files: []testcontainers.ContainerFile{ @@ -45,9 +45,8 @@ func TestCopyFileToContainer(t *testing.T) { Started: true, }) // } - + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - require.NoError(t, container.Terminate(ctx)) } func TestCopyFileToRunningContainer(t *testing.T) { @@ -65,7 +64,7 @@ func TestCopyFileToRunningContainer(t *testing.T) { t.Fatal(err) } - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ Image: "docker.io/bash:5.2.26", Files: []testcontainers.ContainerFile{ @@ -79,20 +78,17 @@ func TestCopyFileToRunningContainer(t *testing.T) { }, Started: true, }) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - err = container.CopyFileToContainer(ctx, helloPath, "/scripts/hello.sh", 0o700) + err = ctr.CopyFileToContainer(ctx, helloPath, "/scripts/hello.sh", 0o700) // } require.NoError(t, err) // Give some time to the wait script to catch the hello script being created - err = wait.ForLog("done").WithStartupTimeout(2*time.Second).WaitUntilReady(ctx, container) + err = wait.ForLog("done").WithStartupTimeout(2*time.Second).WaitUntilReady(ctx, ctr) require.NoError(t, err) - - require.NoError(t, container.Terminate(ctx)) } func TestCopyDirectoryToContainer(t *testing.T) { @@ -106,7 +102,7 @@ func TestCopyDirectoryToContainer(t *testing.T) { t.Fatal(err) } - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ Image: "docker.io/bash", Files: []testcontainers.ContainerFile{ @@ -125,9 +121,8 @@ func TestCopyDirectoryToContainer(t *testing.T) { Started: true, }) // } - + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - require.NoError(t, container.Terminate(ctx)) } func TestCopyDirectoryToRunningContainerAsFile(t *testing.T) { @@ -144,7 +139,7 @@ func TestCopyDirectoryToRunningContainerAsFile(t *testing.T) { t.Fatal(err) } - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ Image: "docker.io/bash", Files: []testcontainers.ContainerFile{ @@ -158,25 +153,17 @@ func TestCopyDirectoryToRunningContainerAsFile(t *testing.T) { }, Started: true, }) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // as the container is started, we can create the directory first - _, _, err = container.Exec(ctx, []string{"mkdir", "-p", "/scripts"}) - if err != nil { - t.Fatal(err) - } + _, _, err = ctr.Exec(ctx, []string{"mkdir", "-p", "/scripts"}) + require.NoError(t, err) // because the container path is a directory, it will use the copy dir method as fallback - err = container.CopyFileToContainer(ctx, dataDirectory, "/scripts", 0o700) - if err != nil { - t.Fatal(err) - } - // } - + err = ctr.CopyFileToContainer(ctx, dataDirectory, "/scripts", 0o700) require.NoError(t, err) - require.NoError(t, container.Terminate(ctx)) + // } } func TestCopyDirectoryToRunningContainerAsDir(t *testing.T) { @@ -194,7 +181,7 @@ func TestCopyDirectoryToRunningContainerAsDir(t *testing.T) { t.Fatal(err) } - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ Image: "docker.io/bash", Files: []testcontainers.ContainerFile{ @@ -208,22 +195,14 @@ func TestCopyDirectoryToRunningContainerAsDir(t *testing.T) { }, Started: true, }) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // as the container is started, we can create the directory first - _, _, err = container.Exec(ctx, []string{"mkdir", "-p", "/scripts"}) - if err != nil { - t.Fatal(err) - } - - err = container.CopyDirToContainer(ctx, dataDirectory, "/scripts", 0o700) - if err != nil { - t.Fatal(err) - } - // } + _, _, err = ctr.Exec(ctx, []string{"mkdir", "-p", "/scripts"}) + require.NoError(t, err) + err = ctr.CopyDirToContainer(ctx, dataDirectory, "/scripts", 0o700) require.NoError(t, err) - require.NoError(t, container.Terminate(ctx)) + // } } diff --git a/docker_test.go b/docker_test.go index 402d944dce..fdc3196dae 100644 --- a/docker_test.go +++ b/docker_test.go @@ -82,8 +82,8 @@ func TestContainerWithHostNetworkOptions(t *testing.T) { } nginxC, err := GenericContainer(ctx, gcr) + CleanupContainer(t, nginxC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxC) // host, err := nginxC.Host(ctx) // if err != nil { @@ -113,12 +113,11 @@ func TestContainerWithHostNetworkOptions_UseExposePortsFromImageConfigs(t *testi } nginxC, err := GenericContainer(ctx, gcr) + CleanupContainer(t, nginxC) if err != nil { t.Fatal(err) } - terminateContainerOnEnd(t, ctx, nginxC) - endpoint, err := nginxC.Endpoint(ctx, "http") if err != nil { t.Errorf("Expected server endpoint. Got '%v'.", err) @@ -158,11 +157,11 @@ func TestContainerWithNetworkModeAndNetworkTogether(t *testing.T) { } nginx, err := GenericContainer(ctx, gcr) + CleanupContainer(t, nginx) if err != nil { // Error when NetworkMode = host and Network = []string{"bridge"} t.Logf("Can't use Network and NetworkMode together, %s\n", err) } - terminateContainerOnEnd(t, ctx, nginx) } func TestContainerWithHostNetwork(t *testing.T) { @@ -197,9 +196,8 @@ func TestContainerWithHostNetwork(t *testing.T) { } nginxC, err := GenericContainer(ctx, gcr) - + CleanupContainer(t, nginxC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxC) portEndpoint, err := nginxC.PortEndpoint(ctx, nginxHighPort, "http") if err != nil { @@ -234,9 +232,8 @@ func TestContainerReturnItsContainerID(t *testing.T) { }, }, }) - + CleanupContainer(t, nginxA) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxA) if nginxA.GetContainerID() == "" { t.Errorf("expected a containerID but we got an empty string.") @@ -256,21 +253,16 @@ func TestContainerTerminationResetsState(t *testing.T) { }, Started: true, }) - if err != nil { - t.Fatal(err) - } + CleanupContainer(t, nginxA) + require.NoError(t, err) err = nginxA.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - if nginxA.SessionID() != "" { - t.Fatal("Internal state must be reset.") - } + require.NoError(t, err) + require.Empty(t, nginxA.SessionID()) + inspect, err := nginxA.Inspect(ctx) - if err == nil || inspect != nil { - t.Fatal("expected error from container inspect.") - } + require.Error(t, err) + require.Nil(t, inspect) } func TestContainerStateAfterTermination(t *testing.T) { @@ -290,15 +282,12 @@ func TestContainerStateAfterTermination(t *testing.T) { t.Run("Nil State after termination", func(t *testing.T) { ctx := context.Background() nginx, err := createContainerFn(ctx) - if err != nil { - t.Fatal(err) - } + CleanupContainer(t, nginx) + require.NoError(t, err) // terminate the container before the raw state is set err = nginx.Terminate(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) state, err := nginx.State(ctx) require.Error(t, err, "expected error from container inspect.") @@ -309,25 +298,20 @@ func TestContainerStateAfterTermination(t *testing.T) { t.Run("Nil State after termination if raw as already set", func(t *testing.T) { ctx := context.Background() nginx, err := createContainerFn(ctx) - if err != nil { - t.Fatal(err) - } + CleanupContainer(t, nginx) + require.NoError(t, err) state, err := nginx.State(ctx) require.NoError(t, err, "unexpected error from container inspect before container termination.") - - assert.NotNil(t, state, "unexpected nil container inspect before container termination.") + require.NotNil(t, state, "unexpected nil container inspect before container termination.") // terminate the container before the raw state is set err = nginx.Terminate(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) state, err = nginx.State(ctx) require.Error(t, err, "expected error from container inspect after container termination.") - - assert.Nil(t, state, "unexpected nil container inspect after container termination.") + require.Nil(t, state, "unexpected nil container inspect after container termination.") }) } @@ -350,13 +334,12 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { }, Started: true, }) - if err != nil { - t.Fatal(err) - } + CleanupContainer(t, ctr) + require.NoError(t, err) + err = ctr.Terminate(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + _, _, err = dockerClient.ImageInspectWithRaw(ctx, nginxAlpineImage) if err != nil { t.Fatal("nginx image should not have been removed") @@ -383,6 +366,7 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { ContainerRequest: req, Started: true, }) + CleanupContainer(t, ctr) if err != nil { t.Fatal(err) } @@ -418,9 +402,8 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxA) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxA) nginxB, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, @@ -433,9 +416,8 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxB) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxB) endpointA, err := nginxA.PortEndpoint(ctx, nginxDefaultPort, "http") require.NoError(t, err) @@ -480,9 +462,8 @@ func TestContainerCreation(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxC) endpoint, err := nginxC.PortEndpoint(ctx, nginxDefaultPort, "http") require.NoError(t, err) @@ -536,9 +517,8 @@ func TestContainerCreationWithName(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxC) inspect, err := nginxC.Inspect(ctx) if err != nil { @@ -597,9 +577,8 @@ func TestContainerCreationAndWaitForListeningPortLongEnough(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxC) origin, err := nginxC.PortEndpoint(ctx, nginxDefaultPort, "http") if err != nil { @@ -630,8 +609,7 @@ func TestContainerCreationTimesOut(t *testing.T) { }, Started: true, }) - - terminateContainerOnEnd(t, ctx, nginxC) + CleanupContainer(t, nginxC) if err == nil { t.Error("Expected timeout") @@ -652,9 +630,8 @@ func TestContainerRespondsWithHttp200ForIndex(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxC) origin, err := nginxC.PortEndpoint(ctx, nginxDefaultPort, "http") if err != nil { @@ -685,8 +662,7 @@ func TestContainerCreationTimesOutWithHttp(t *testing.T) { }, Started: true, }) - terminateContainerOnEnd(t, ctx, nginxC) - + CleanupContainer(t, nginxC) if err == nil { t.Error("Expected timeout") } @@ -708,11 +684,10 @@ func TestContainerCreationWaitsForLogContextTimeout(t *testing.T) { ContainerRequest: req, Started: true, }) + CleanupContainer(t, c) if err == nil { t.Error("Expected timeout") } - - terminateContainerOnEnd(t, ctx, c) } func TestContainerCreationWaitsForLog(t *testing.T) { @@ -731,9 +706,8 @@ func TestContainerCreationWaitsForLog(t *testing.T) { ContainerRequest: req, Started: true, }) - + CleanupContainer(t, mysqlC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, mysqlC) } func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { @@ -761,9 +735,8 @@ func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { } c, err := GenericContainer(ctx, genContainerReq) - + CleanupContainer(t, c) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, c) ep, err := c.Endpoint(ctx, "http") require.NoError(t, err) @@ -779,13 +752,16 @@ func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { } func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { - rescueStdout := os.Stderr - r, w, _ := os.Pipe() + r, w, err := os.Pipe() + require.NoError(t, err) + + oldStderr := os.Stderr os.Stderr = w + t.Cleanup(func() { + os.Stderr = oldStderr + }) - t.Log("getting ctx") ctx := context.Background() - t.Log("got ctx, creating container request") // fromDockerfile { req := ContainerRequest{ @@ -804,17 +780,19 @@ func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { } c, err := GenericContainer(ctx, genContainerReq) + CleanupContainer(t, c) + require.NoError(t, err) + + err = w.Close() + require.NoError(t, err) + out, err := io.ReadAll(r) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, c) - _ = w.Close() - out, _ := io.ReadAll(r) - os.Stdout = rescueStdout temp := strings.Split(string(out), "\n") if !regexp.MustCompile(`^Step\s*1/\d+\s*:\s*FROM docker.io/alpine$`).MatchString(temp[0]) { - t.Errorf("Expected stdout firstline to be %s. Got '%s'.", "Step 1/* : FROM docker.io/alpine", temp[0]) + t.Errorf("Expected stdout first line to be %s. Got '%s'.", "Step 1/* : FROM docker.io/alpine", temp[0]) } } @@ -837,11 +815,10 @@ func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { ContainerRequest: req, Started: true, }) + CleanupContainer(t, c) if err == nil { t.Fatal("Expected timeout") } - - terminateContainerOnEnd(t, ctx, c) } func TestContainerCreationWaitingForHostPort(t *testing.T) { @@ -858,9 +835,8 @@ func TestContainerCreationWaitingForHostPort(t *testing.T) { ContainerRequest: req, Started: true, }) - + CleanupContainer(t, nginx) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginx) } func TestContainerCreationWaitingForHostPortWithoutBashThrowsAnError(t *testing.T) { @@ -875,9 +851,8 @@ func TestContainerCreationWaitingForHostPortWithoutBashThrowsAnError(t *testing. ContainerRequest: req, Started: true, }) - + CleanupContainer(t, nginx) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginx) } func TestCMD(t *testing.T) { @@ -902,9 +877,8 @@ func TestCMD(t *testing.T) { ContainerRequest: req, Started: true, }) - + CleanupContainer(t, c) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, c) } func TestEntrypoint(t *testing.T) { @@ -929,9 +903,8 @@ func TestEntrypoint(t *testing.T) { ContainerRequest: req, Started: true, }) - + CleanupContainer(t, c) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, c) } func TestWorkingDir(t *testing.T) { @@ -957,9 +930,8 @@ func TestWorkingDir(t *testing.T) { ContainerRequest: req, Started: true, }) - + CleanupContainer(t, c) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, c) } func ExampleDockerProvider_CreateContainer() { @@ -969,19 +941,24 @@ func ExampleDockerProvider_CreateContainer() { ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/").WithStartupTimeout(10 * time.Second), } - nginxC, _ := GenericContainer(ctx, GenericContainerRequest{ + nginxC, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: req, Started: true, }) defer func() { - if err := nginxC.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := TerminateContainer(nginxC); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to create container: %s", err) + return + } state, err := nginxC.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -997,28 +974,38 @@ func ExampleContainer_Host() { ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/").WithStartupTimeout(10 * time.Second), } - nginxC, _ := GenericContainer(ctx, GenericContainerRequest{ + nginxC, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: req, Started: true, }) defer func() { - if err := nginxC.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := TerminateContainer(nginxC); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to create container: %s", err) + return + } // containerHost { - ip, _ := nginxC.Host(ctx) + ip, err := nginxC.Host(ctx) + if err != nil { + log.Printf("failed to create container: %s", err) + return + } // } - println(ip) + fmt.Println(ip) state, err := nginxC.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) // Output: + // localhost // true } @@ -1029,19 +1016,28 @@ func ExampleContainer_Start() { ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/").WithStartupTimeout(10 * time.Second), } - nginxC, _ := GenericContainer(ctx, GenericContainerRequest{ + nginxC, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: req, }) defer func() { - if err := nginxC.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := TerminateContainer(nginxC); err != nil { + log.Printf("failed to terminate container: %s", err) } }() - _ = nginxC.Start(ctx) + if err != nil { + log.Printf("failed to create container: %s", err) + return + } + + if err = nginxC.Start(ctx); err != nil { + log.Printf("failed to start container: %s", err) + return + } state, err := nginxC.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -1057,19 +1053,24 @@ func ExampleContainer_Stop() { ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/").WithStartupTimeout(10 * time.Second), } - nginxC, _ := GenericContainer(ctx, GenericContainerRequest{ + nginxC, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: req, }) defer func() { - if err := nginxC.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := TerminateContainer(nginxC); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to create and start container: %s", err) + return + } + fmt.Println("Container has been started") timeout := 10 * time.Second - err := nginxC.Stop(ctx, &timeout) - if err != nil { - log.Fatalf("failed to stop container: %s", err) // nolint:gocritic + if err = nginxC.Stop(ctx, &timeout); err != nil { + log.Printf("failed to terminate container: %s", err) + return } fmt.Println("Container has been stopped") @@ -1086,15 +1087,20 @@ func ExampleContainer_MappedPort() { ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/").WithStartupTimeout(10 * time.Second), } - nginxC, _ := GenericContainer(ctx, GenericContainerRequest{ + nginxC, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: req, Started: true, }) defer func() { - if err := nginxC.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := TerminateContainer(nginxC); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to create and start container: %s", err) + return + } + // buildingAddresses { ip, _ := nginxC.Host(ctx) port, _ := nginxC.MappedPort(ctx, "80") @@ -1103,7 +1109,8 @@ func ExampleContainer_MappedPort() { state, err := nginxC.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -1140,9 +1147,8 @@ func TestContainerCreationWithVolumeAndFileWritingToIt(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, bashC, RemoveVolumes(volumeName)) require.NoError(t, err) - require.NoError(t, bashC.Terminate(ctx)) } func TestContainerWithTmpFs(t *testing.T) { @@ -1158,9 +1164,8 @@ func TestContainerWithTmpFs(t *testing.T) { ContainerRequest: req, Started: true, }) - + CleanupContainer(t, ctr) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, ctr) path := "/testtmpfs/test.file" @@ -1204,12 +1209,13 @@ func TestContainerWithTmpFs(t *testing.T) { func TestContainerNonExistentImage(t *testing.T) { t.Run("if the image not found don't propagate the error", func(t *testing.T) { - _, err := GenericContainer(context.Background(), GenericContainerRequest{ + ctr, err := GenericContainer(context.Background(), GenericContainerRequest{ ContainerRequest: ContainerRequest{ Image: "postgres:nonexistent-version", }, Started: true, }) + CleanupContainer(t, ctr) var nf errdefs.ErrNotFound if !errors.As(err, &nf) { @@ -1228,11 +1234,10 @@ func TestContainerNonExistentImage(t *testing.T) { }, Started: true, }) + CleanupContainer(t, c) if !errors.Is(err, ctx.Err()) { t.Fatalf("err should be a ctx cancelled error %v", err) } - - terminateContainerOnEnd(t, context.Background(), c) // use non-cancelled context }) } @@ -1253,9 +1258,7 @@ func TestContainerCustomPlatformImage(t *testing.T) { }, Started: false, }) - - terminateContainerOnEnd(t, ctx, c) - + CleanupContainer(t, c) require.Error(t, err) }) @@ -1271,9 +1274,8 @@ func TestContainerCustomPlatformImage(t *testing.T) { }, Started: false, }) - + CleanupContainer(t, c) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, c) dockerCli, err := NewDockerClientWithOpts(ctx) require.NoError(t, err) @@ -1303,9 +1305,8 @@ func TestContainerWithCustomHostname(t *testing.T) { ContainerRequest: req, Started: true, }) - + CleanupContainer(t, ctr) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, ctr) if actualHostname := readHostname(t, ctr.GetContainerID()); actualHostname != hostname { t.Fatalf("expected hostname %s, got %s", hostname, actualHostname) @@ -1319,8 +1320,8 @@ func TestContainerInspect_RawInspectIsCleanedOnStop(t *testing.T) { }, Started: true, }) + CleanupContainer(t, ctr) require.NoError(t, err) - terminateContainerOnEnd(t, context.Background(), ctr) inspect, err := ctr.Inspect(context.Background()) require.NoError(t, err) @@ -1373,9 +1374,8 @@ func TestDockerContainerCopyFileToContainer(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxC) _ = nginxC.CopyFileToContainer(ctx, filepath.Join(".", "testdata", "hello.sh"), tc.copiedFileName, 700) c, _, err := nginxC.Exec(ctx, []string{"bash", tc.copiedFileName}) @@ -1401,11 +1401,10 @@ func TestDockerContainerCopyDirToContainer(t *testing.T) { }, Started: true, }) - - p := filepath.Join(".", "testdata", "Dokerfile") + CleanupContainer(t, nginxC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxC) + p := filepath.Join(".", "testdata", "Dokerfile") err = nginxC.CopyDirToContainer(ctx, p, "/tmp/testdata/Dockerfile", 700) require.Error(t, err) // copying a file using the directory method will raise an error @@ -1462,7 +1461,7 @@ func TestDockerCreateContainerWithFiles(t *testing.T) { }, Started: false, }) - terminateContainerOnEnd(t, ctx, nginxC) + CleanupContainer(t, nginxC) if err != nil { require.Contains(t, err.Error(), tc.errMsg) @@ -1547,7 +1546,7 @@ func TestDockerCreateContainerWithDirs(t *testing.T) { }, Started: false, }) - terminateContainerOnEnd(t, ctx, nginxC) + CleanupContainer(t, nginxC) require.Equal(t, (err != nil), tc.hasError) if err == nil { @@ -1587,9 +1586,8 @@ func TestDockerContainerCopyToContainer(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxC) fileContent, err := os.ReadFile(filepath.Join(".", "testdata", "hello.sh")) if err != nil { @@ -1626,9 +1624,8 @@ func TestDockerContainerCopyFileFromContainer(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxC) copiedFileName := "hello_copy.sh" _ = nginxC.CopyFileToContainer(ctx, filepath.Join(".", "testdata", "hello.sh"), "/"+copiedFileName, 700) @@ -1665,9 +1662,8 @@ func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxC) copiedFileName := "hello_copy.sh" _ = nginxC.CopyFileToContainer(ctx, filepath.Join(".", "testdata", "empty.sh"), "/"+copiedFileName, 700) @@ -1729,9 +1725,8 @@ func TestDockerContainerResources(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxC) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxC) c, err := NewDockerClientWithOpts(ctx) require.NoError(t, err) @@ -1766,8 +1761,8 @@ func TestContainerCapAdd(t *testing.T) { }, Started: true, }) + CleanupContainer(t, nginx) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginx) dockerClient, err := NewDockerClientWithOpts(ctx) require.NoError(t, err) @@ -1799,11 +1794,10 @@ func TestContainerRunningCheckingStatusCode(t *testing.T) { ContainerRequest: req, Started: true, }) + CleanupContainer(t, influx) if err != nil { t.Fatal(err) } - - terminateContainerOnEnd(t, ctx, influx) } func TestContainerWithUserID(t *testing.T) { @@ -1819,9 +1813,8 @@ func TestContainerWithUserID(t *testing.T) { ContainerRequest: req, Started: true, }) - + CleanupContainer(t, ctr) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, ctr) r, err := ctr.Logs(ctx) if err != nil { @@ -1848,9 +1841,8 @@ func TestContainerWithNoUserID(t *testing.T) { ContainerRequest: req, Started: true, }) - + CleanupContainer(t, ctr) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, ctr) r, err := ctr.Logs(ctx) if err != nil { @@ -1892,9 +1884,8 @@ func TestNetworkModeWithContainerReference(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxA) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxA) networkMode := fmt.Sprintf("container:%v", nginxA.GetContainerID()) nginxB, err := GenericContainer(ctx, GenericContainerRequest{ @@ -1907,9 +1898,8 @@ func TestNetworkModeWithContainerReference(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxB) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxB) } // creates a temporary dir in which the files will be extracted. Then it will compare the bytes of each file in the source with the bytes from the copied-from-container file @@ -1957,16 +1947,6 @@ func assertExtractedFiles(t *testing.T, ctx context.Context, container Container } } -func terminateContainerOnEnd(tb testing.TB, ctx context.Context, ctr Container) { - tb.Helper() - if ctr == nil { - return - } - tb.Cleanup(func() { - require.NoError(tb, ctr.Terminate(ctx)) - }) -} - func TestDockerProviderFindContainerByName(t *testing.T) { ctx := context.Background() provider, err := NewDockerProvider(WithLogger(TestLogger(t))) @@ -1982,11 +1962,12 @@ func TestDockerProviderFindContainerByName(t *testing.T) { }, Started: true, }) + CleanupContainer(t, c1) require.NoError(t, err) c1Inspect, err := c1.Inspect(ctx) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, c1) + CleanupContainer(t, c1) c1Name := c1Inspect.Name @@ -1999,8 +1980,8 @@ func TestDockerProviderFindContainerByName(t *testing.T) { }, Started: true, }) + CleanupContainer(t, c2) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, c2) c, err := provider.findContainerByName(ctx, "test") require.NoError(t, err) @@ -2035,8 +2016,8 @@ func TestImageBuiltFromDockerfile_KeepBuiltImage(t *testing.T) { }, }, }) + CleanupContainer(t, c) require.NoError(t, err, "create container should not fail") - defer func() { _ = c.Terminate(context.Background()) }() // Get the image ID. containerInspect, err := c.Inspect(ctx) require.NoError(t, err, "container inspect should not fail") @@ -2058,7 +2039,7 @@ func TestImageBuiltFromDockerfile_KeepBuiltImage(t *testing.T) { if tt.keepBuiltImage { require.NoError(t, err, "image should still exist") } else { - require.Error(t, err, "image should not exist anymore") + require.Error(t, err, "image should not exist any more") } }) } @@ -2295,15 +2276,11 @@ func TestCustomPrefixTrailingSlashIsProperlyRemovedIfPresent(t *testing.T) { ContainerRequest: req, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - terminateContainerOnEnd(t, ctx, c) - }() + CleanupContainer(t, c) + require.NoError(t, err) // enforce the concrete type, as GenericContainer returns an interface, // which will be changed in future implementations of the library dockerContainer := c.(*DockerContainer) - assert.Equal(t, fmt.Sprintf("%s%s", hubPrefixWithTrailingSlash, dockerImage), dockerContainer.Image) + require.Equal(t, fmt.Sprintf("%s%s", hubPrefixWithTrailingSlash, dockerImage), dockerContainer.Image) } diff --git a/docs/features/common_functional_options.md b/docs/features/common_functional_options.md index d559a3ee7f..18d0e4b007 100644 --- a/docs/features/common_functional_options.md +++ b/docs/features/common_functional_options.md @@ -70,7 +70,8 @@ useful context instead of appearing out of band. ```golang func TestHandler(t *testing.T) { logger := TestLogger(t) - _, err := postgresModule.Run(ctx, "postgres:15-alpine", testcontainers.WithLogger(logger)) + ctr, err := postgresModule.Run(ctx, "postgres:15-alpine", testcontainers.WithLogger(logger)) + CleanupContainer(t, ctr) require.NoError(t, err) // Do something with container. } diff --git a/docs/features/creating_container.md b/docs/features/creating_container.md index 30264a05da..ec33bdb014 100644 --- a/docs/features/creating_container.md +++ b/docs/features/creating_container.md @@ -11,7 +11,15 @@ up with Testcontainers and integrate into your tests: `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: +The following test creates an NGINX container on both the `bridge` (docker default +network) and the `foo` network and validates that it returns 200 for the status code. + +It also demonstrates how to use `CleanupContainer` ensures that nginx container +is removed when the test ends even if the underlying `GenericContainer` errored +as well as the `CleanupNetwork` which does the same for networks. + +The alternatives for these outside of tests as a `defer` are `TerminateContainer` +and `Network.Remove` which can be seen in the examples. ```go package main @@ -32,33 +40,38 @@ type nginxContainer struct { } -func setupNginx(ctx context.Context) (*nginxContainer, error) { +func setupNginx(ctx context.Context, networkName string) (*nginxContainer, error) { req := testcontainers.ContainerRequest{ Image: "nginx", ExposedPorts: []string{"80/tcp"}, + Networks: []string{"bridge", networkName}, WaitingFor: wait.ForHTTP("/"), } container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, }) + var nginxC *nginxContainer + if container != nil { + nginxC = &nginxContainer{Container: c} + } if err != nil { - return nil, err + return nginxC, err } ip, err := container.Host(ctx) if err != nil { - return nil, err + return nginxC, err } mappedPort, err := container.MappedPort(ctx, "80") if err != nil { - return nil, err + return nginxC, err } - uri := fmt.Sprintf("http://%s:%s", ip, mappedPort.Port()) + nginxC.URI = fmt.Sprintf("http://%s:%s", ip, mappedPort.Port()) - return &nginxContainer{Container: container, URI: uri}, nil + return nginxC, nil } func TestIntegrationNginxLatestReturn(t *testing.T) { @@ -68,25 +81,25 @@ func TestIntegrationNginxLatestReturn(t *testing.T) { ctx := context.Background() - nginxC, err := setupNginx(ctx) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := nginxC.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } + networkName := "foo" + net, err := provider.CreateNetwork(ctx, NetworkRequest{ + Name: networkName, }) + require.NoError(t, err) + CleanupNetwork(t, net) + + nginxC, err := setupNginx(ctx, networkName) + testcontainers.CleanupContainer(t, nginxC) + require.NoError(t, err) resp, err := http.Get(nginxC.URI) - if resp.StatusCode != http.StatusOK { - t.Fatalf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) - } + require.Equal(t, http.StatusOK, resp.StatusCode) } ``` + + + ### Lifecycle hooks _Testcontainers for Go_ allows you to define your own lifecycle hooks for better control over your containers. You just need to define functions that return an error and receive the Go context as first argument, and a `ContainerRequest` for the `Creating` hook, and a `Container` for the rest of them as second argument. @@ -145,8 +158,8 @@ The aforementioned `GenericContainer` function and the `ContainerRequest` struct ## Reusable container -With `Reuse` option you can reuse an existing container. Reusing will work only if you pass an -existing container name via 'req.Name' field. If the name is not in a list of existing containers, +With `Reuse` option you can reuse an existing container. Reusing will work only if you pass an +existing container name via 'req.Name' field. If the name is not in a list of existing containers, the function will create a new generic container. If `Reuse` is true and `Name` is empty, you will get error. The following test creates an NGINX container, adds a file into it and then reuses the container again for checking the file: @@ -178,16 +191,22 @@ func main() { }, Started: true, }) + defer func() { + if err := testcontainers.TerminateContainer(n1); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() if err != nil { - log.Fatal(err) + log.Print(err) + return } - defer n1.Terminate(ctx) copiedFileName := "hello_copy.sh" err = n1.CopyFileToContainer(ctx, "./testdata/hello.sh", "/"+copiedFileName, 700) if err != nil { - log.Fatal(err) + log.Print(err) + return } n2, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ @@ -200,13 +219,20 @@ func main() { Started: true, Reuse: true, }) + defer func() { + if err := testcontainers.TerminateContainer(n2); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() if err != nil { - log.Fatal(err) + log.Print(err) + return } c, _, err := n2.Exec(ctx, []string{"bash", copiedFileName}) if err != nil { - log.Fatal(err) + log.Print(err) + return } fmt.Println(c) } @@ -256,10 +282,20 @@ func main() { } res, err := testcontainers.ParallelContainers(ctx, requests, testcontainers.ParallelContainersOptions{}) + for _, c := range res { + c := c + defer func() { + if err := testcontainers.TerminateContainer(c); err != nil { + log.Printf("failed to terminate container: %s", c) + } + }() + } + if err != nil { e, ok := err.(testcontainers.ParallelContainersError) if !ok { - log.Fatalf("unknown error: %v", err) + log.Printf("unknown error: %v", err) + return } for _, pe := range e.Errors { @@ -267,14 +303,5 @@ func main() { } return } - - for _, c := range res { - c := c - defer func() { - if err := c.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", c) - } - }() - } } ``` diff --git a/docs/quickstart.md b/docs/quickstart.md index 5660e35757..ed6bbfcd4a 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -9,7 +9,7 @@ Please read the [system requirements](../system_requirements/) page before you s ## 2. Install _Testcontainers for Go_ -We use [gomod](https://blog.golang.org/using-go-modules) and you can get it installed via: +We use [go mod](https://blog.golang.org/using-go-modules) and you can get it installed via: ``` go get github.com/testcontainers/testcontainers-go @@ -22,6 +22,8 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" ) @@ -37,14 +39,8 @@ func TestWithRedis(t *testing.T) { ContainerRequest: req, Started: true, }) - if err != nil { - t.Fatalf("Could not start redis: %s", err) - } - defer func() { - if err := redisC.Terminate(ctx); err != nil { - t.Fatalf("Could not stop redis: %s", err) - } - }() + testcontainers.CleanupContainer(t, redisC) + require.NoError(t, err) } ``` @@ -75,7 +71,8 @@ start, leaving to you the decision about when to start it. All the containers must be removed at some point, otherwise they will run until the host is overloaded. One of the ways we have to clean up is by deferring the -terminated function: `defer redisC.Terminate(ctx)`. +terminated function: `defer testcontainers.TerminateContainer(redisC)` which +automatically handles nil container so is safe to use even in the error case. !!!tip diff --git a/examples/nginx/go.mod b/examples/nginx/go.mod index a6f67e793c..4b4830eaa3 100644 --- a/examples/nginx/go.mod +++ b/examples/nginx/go.mod @@ -2,7 +2,10 @@ module github.com/testcontainers/testcontainers-go/examples/nginx go 1.22 -require github.com/testcontainers/testcontainers-go v0.33.0 +require ( + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 +) replace github.com/testcontainers/testcontainers-go => ../.. @@ -15,6 +18,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -26,6 +30,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -37,6 +42,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -53,4 +59,5 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/examples/nginx/go.sum b/examples/nginx/go.sum index ed514ea5ef..28367d0020 100644 --- a/examples/nginx/go.sum +++ b/examples/nginx/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -52,6 +53,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -78,6 +83,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -174,6 +181,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/examples/nginx/nginx.go b/examples/nginx/nginx.go index fd0e530ea6..6a5718c3e0 100644 --- a/examples/nginx/nginx.go +++ b/examples/nginx/nginx.go @@ -24,21 +24,24 @@ func startContainer(ctx context.Context) (*nginxContainer, error) { ContainerRequest: req, Started: true, }) + var nginxC *nginxContainer + if container != nil { + nginxC = &nginxContainer{Container: container} + } if err != nil { - return nil, err + return nginxC, err } ip, err := container.Host(ctx) if err != nil { - return nil, err + return nginxC, err } mappedPort, err := container.MappedPort(ctx, "80") if err != nil { - return nil, err + return nginxC, err } - uri := fmt.Sprintf("http://%s:%s", ip, mappedPort.Port()) - - return &nginxContainer{Container: container, URI: uri}, nil + nginxC.URI = fmt.Sprintf("http://%s:%s", ip, mappedPort.Port()) + return nginxC, nil } diff --git a/examples/nginx/nginx_test.go b/examples/nginx/nginx_test.go index 3d7b8ada48..fe662daf07 100644 --- a/examples/nginx/nginx_test.go +++ b/examples/nginx/nginx_test.go @@ -4,6 +4,10 @@ import ( "context" "net/http" "testing" + + "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go" ) func TestIntegrationNginxLatestReturn(t *testing.T) { @@ -14,23 +18,10 @@ func TestIntegrationNginxLatestReturn(t *testing.T) { ctx := context.Background() nginxC, err := startContainer(ctx) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := nginxC.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, nginxC) + require.NoError(t, err) resp, err := http.Get(nginxC.URI) - if err != nil { - t.Fatal(err) - } - - if resp.StatusCode != http.StatusOK { - t.Fatalf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) - } + require.NoError(t, err) + require.Equal(t, http.StatusOK, resp.StatusCode) } diff --git a/examples/toxiproxy/go.mod b/examples/toxiproxy/go.mod index 04be7036c1..7cdb477e6c 100644 --- a/examples/toxiproxy/go.mod +++ b/examples/toxiproxy/go.mod @@ -6,7 +6,8 @@ require ( github.com/Shopify/toxiproxy/v2 v2.8.0 github.com/go-redis/redis/v8 v8.11.5 github.com/google/uuid v1.6.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -19,6 +20,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect @@ -30,6 +32,7 @@ require ( github.com/go-ole/go-ole v1.2.6 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -41,6 +44,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -57,6 +61,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/examples/toxiproxy/go.sum b/examples/toxiproxy/go.sum index 91a27d9fc8..8173198d1b 100644 --- a/examples/toxiproxy/go.sum +++ b/examples/toxiproxy/go.sum @@ -20,6 +20,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -62,6 +63,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -94,6 +99,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -190,6 +197,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 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.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/examples/toxiproxy/redis.go b/examples/toxiproxy/redis.go index ead526773d..c66e52550f 100644 --- a/examples/toxiproxy/redis.go +++ b/examples/toxiproxy/redis.go @@ -27,9 +27,9 @@ func setupRedis(ctx context.Context, network string, networkAlias []string) (*re ContainerRequest: req, Started: true, }) - if err != nil { - return nil, err + var nginxC *redisContainer + if container != nil { + nginxC = &redisContainer{Container: container} } - - return &redisContainer{Container: container}, nil + return nginxC, err } diff --git a/examples/toxiproxy/toxiproxy.go b/examples/toxiproxy/toxiproxy.go index e7903a9f99..1a226e8c61 100644 --- a/examples/toxiproxy/toxiproxy.go +++ b/examples/toxiproxy/toxiproxy.go @@ -31,21 +31,25 @@ func startContainer(ctx context.Context, network string, networkAlias []string) ContainerRequest: req, Started: true, }) + var toxiC *toxiproxyContainer + if container != nil { + toxiC = &toxiproxyContainer{Container: container} + } if err != nil { - return nil, err + return toxiC, err } mappedPort, err := container.MappedPort(ctx, "8474") if err != nil { - return nil, err + return toxiC, err } hostIP, err := container.Host(ctx) if err != nil { - return nil, err + return toxiC, err } - uri := fmt.Sprintf("%s:%s", hostIP, mappedPort.Port()) + toxiC.URI = fmt.Sprintf("%s:%s", hostIP, mappedPort.Port()) - return &toxiproxyContainer{Container: container, URI: uri}, nil + return toxiC, nil } diff --git a/examples/toxiproxy/toxiproxy_test.go b/examples/toxiproxy/toxiproxy_test.go index 0cb3f05320..c372d739b8 100644 --- a/examples/toxiproxy/toxiproxy_test.go +++ b/examples/toxiproxy/toxiproxy_test.go @@ -9,7 +9,9 @@ import ( toxiproxy "github.com/Shopify/toxiproxy/v2/client" "github.com/go-redis/redis/v8" "github.com/google/uuid" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/network" ) @@ -17,63 +19,37 @@ func TestToxiproxy(t *testing.T) { ctx := context.Background() newNetwork, err := network.New(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + testcontainers.CleanupNetwork(t, newNetwork) networkName := newNetwork.Name toxiproxyContainer, err := startContainer(ctx, networkName, []string{"toxiproxy"}) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, toxiproxyContainer) + require.NoError(t, err) redisContainer, err := setupRedis(ctx, networkName, []string{"redis"}) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := toxiproxyContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - if err := redisContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - if err := newNetwork.Remove(ctx); err != nil { - t.Fatalf("failed to terminate network: %s", err) - } - }) + testcontainers.CleanupContainer(t, redisContainer) + require.NoError(t, err) toxiproxyClient := toxiproxy.NewClient(toxiproxyContainer.URI) proxy, err := toxiproxyClient.CreateProxy("redis", "0.0.0.0:8666", "redis:6379") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) toxiproxyProxyPort, err := toxiproxyContainer.MappedPort(ctx, "8666") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) toxiproxyProxyHostIP, err := toxiproxyContainer.Host(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) redisUri := fmt.Sprintf("redis://%s:%s?read_timeout=2s", toxiproxyProxyHostIP, toxiproxyProxyPort.Port()) options, err := redis.ParseURL(redisUri) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) redisClient := redis.NewClient(options) + defer func() { - err := flushRedis(ctx, *redisClient) - if err != nil { - t.Fatal(err) - } + require.NoError(t, flushRedis(ctx, *redisClient)) }() // Set data @@ -81,28 +57,18 @@ func TestToxiproxy(t *testing.T) { value := "Cabbage Biscuits" ttl, _ := time.ParseDuration("2h") err = redisClient.Set(ctx, key, value, ttl).Err() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) _, err = proxy.AddToxic("latency_down", "latency", "downstream", 1.0, toxiproxy.Attributes{ "latency": 1000, "jitter": 100, }) - if err != nil { - return - } + require.NoError(t, err) // Get data savedValue, err := redisClient.Get(ctx, key).Result() - if err != nil { - t.Fatal(err) - } - - // perform assertions - if savedValue != value { - t.Fatalf("Expected value %s. Got %s.", savedValue, value) - } + require.NoError(t, err) + require.Equal(t, value, savedValue) } func flushRedis(ctx context.Context, client redis.Client) error { diff --git a/from_dockerfile_test.go b/from_dockerfile_test.go index fc1d4052ea..f6f7512ae3 100644 --- a/from_dockerfile_test.go +++ b/from_dockerfile_test.go @@ -102,12 +102,12 @@ func TestBuildImageFromDockerfile_BuildError(t *testing.T) { Context: filepath.Join(".", "testdata"), }, } - _, err = GenericContainer(ctx, GenericContainerRequest{ + ctr, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: req, Started: true, }) - + CleanupContainer(t, ctr) require.EqualError(t, err, `create container: build image: The command '/bin/sh -c exit 1' returned a non-zero code: 1`) } @@ -153,10 +153,9 @@ func TestBuildImageFromDockerfile_Target(t *testing.T) { c, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: ContainerRequest{ FromDockerfile: FromDockerfile{ - Context: "testdata", - Dockerfile: "target.Dockerfile", - PrintBuildLog: true, - KeepImage: false, + Context: "testdata", + Dockerfile: "target.Dockerfile", + KeepImage: false, BuildOptionsModifier: func(buildOptions *types.ImageBuildOptions) { buildOptions.Target = fmt.Sprintf("target%d", i) }, @@ -164,6 +163,7 @@ func TestBuildImageFromDockerfile_Target(t *testing.T) { }, Started: true, }) + CleanupContainer(t, c) require.NoError(t, err) r, err := c.Logs(ctx) @@ -171,12 +171,7 @@ func TestBuildImageFromDockerfile_Target(t *testing.T) { logs, err := io.ReadAll(r) require.NoError(t, err) - - assert.Equal(t, fmt.Sprintf("target%d\n\n", i), string(logs)) - - t.Cleanup(func() { - require.NoError(t, c.Terminate(ctx)) - }) + require.Equal(t, fmt.Sprintf("target%d\n\n", i), string(logs)) } } @@ -187,10 +182,9 @@ func ExampleGenericContainer_buildFromDockerfile() { c, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: ContainerRequest{ FromDockerfile: FromDockerfile{ - Context: "testdata", - Dockerfile: "target.Dockerfile", - PrintBuildLog: true, - KeepImage: false, + Context: "testdata", + Dockerfile: "target.Dockerfile", + KeepImage: false, BuildOptionsModifier: func(buildOptions *types.ImageBuildOptions) { buildOptions.Target = "target2" }, @@ -199,18 +193,26 @@ func ExampleGenericContainer_buildFromDockerfile() { Started: true, }) // } + defer func() { + if err := TerminateContainer(c); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() if err != nil { - log.Fatalf("failed to start container: %v", err) + log.Printf("failed to start container: %v", err) + return } r, err := c.Logs(ctx) if err != nil { - log.Fatalf("failed to get logs: %v", err) + log.Printf("failed to get logs: %v", err) + return } logs, err := io.ReadAll(r) if err != nil { - log.Fatalf("failed to read logs: %v", err) + log.Printf("failed to read logs: %v", err) + return } fmt.Println(string(logs)) @@ -223,13 +225,12 @@ func TestBuildImageFromDockerfile_TargetDoesNotExist(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - _, err := GenericContainer(ctx, GenericContainerRequest{ + ctr, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: ContainerRequest{ FromDockerfile: FromDockerfile{ - Context: "testdata", - Dockerfile: "target.Dockerfile", - PrintBuildLog: true, - KeepImage: false, + Context: "testdata", + Dockerfile: "target.Dockerfile", + KeepImage: false, BuildOptionsModifier: func(buildOptions *types.ImageBuildOptions) { buildOptions.Target = "target-foo" }, @@ -237,5 +238,6 @@ func TestBuildImageFromDockerfile_TargetDoesNotExist(t *testing.T) { }, Started: true, }) + CleanupContainer(t, ctr) require.Error(t, err) } diff --git a/generic_test.go b/generic_test.go index 9116fd0f65..99c13f5bfa 100644 --- a/generic_test.go +++ b/generic_test.go @@ -38,7 +38,7 @@ func TestGenericReusableContainer(t *testing.T) { }) require.NoError(t, err) require.True(t, n1.IsRunning()) - terminateContainerOnEnd(t, ctx, n1) + CleanupContainer(t, n1) copiedFileName := "hello_copy.sh" err = n1.CopyFileToContainer(ctx, "./testdata/hello.sh", "/"+copiedFileName, 700) @@ -123,7 +123,7 @@ func TestGenericContainerShouldReturnRefOnError(t *testing.T) { }) require.Error(t, err) require.NotNil(t, c) - terminateContainerOnEnd(t, context.Background(), c) + CleanupContainer(t, c) } func TestGenericReusableContainerInSubprocess(t *testing.T) { @@ -160,7 +160,7 @@ func TestGenericReusableContainerInSubprocess(t *testing.T) { nginxC, err := containerFromDockerResponse(context.Background(), ctrs[0]) require.NoError(t, err) - terminateContainerOnEnd(t, context.Background(), nginxC) + CleanupContainer(t, nginxC) } func createReuseContainerInSubprocess(t *testing.T) string { diff --git a/image_substitutors_test.go b/image_substitutors_test.go index 8054ebf96c..4a41f31ce6 100644 --- a/image_substitutors_test.go +++ b/image_substitutors_test.go @@ -149,6 +149,7 @@ func TestSubstituteBuiltImage(t *testing.T) { t.Run("should not use the properties prefix on built images", func(t *testing.T) { config.Reset() c, err := GenericContainer(context.Background(), req) + CleanupContainer(t, c) if err != nil { t.Fatal(err) } diff --git a/image_test.go b/image_test.go index 795a521b29..2344c5063d 100644 --- a/image_test.go +++ b/image_test.go @@ -25,15 +25,12 @@ func TestImageList(t *testing.T) { Image: "redis:latest", } - container, err := provider.CreateContainer(context.Background(), req) + ctr, err := provider.CreateContainer(context.Background(), req) + CleanupContainer(t, ctr) if err != nil { t.Fatalf("creating test container %v", err) } - defer func() { - _ = container.Terminate(context.Background()) - }() - images, err := provider.ListImages(context.Background()) if err != nil { t.Fatalf("listing images %v", err) @@ -69,15 +66,12 @@ func TestSaveImages(t *testing.T) { Image: "redis:latest", } - container, err := provider.CreateContainer(context.Background(), req) + ctr, err := provider.CreateContainer(context.Background(), req) + CleanupContainer(t, ctr) if err != nil { t.Fatalf("creating test container %v", err) } - defer func() { - _ = container.Terminate(context.Background()) - }() - output := filepath.Join(t.TempDir(), "images.tar") err = provider.SaveImages(context.Background(), output, req.Image) if err != nil { diff --git a/lifecycle.go b/lifecycle.go index 40360a4c0b..c38e60240d 100644 --- a/lifecycle.go +++ b/lifecycle.go @@ -411,10 +411,10 @@ func (c ContainerLifecycleHooks) Creating(ctx context.Context) func(req Containe // containerHookFn is a helper function that will create a function to be returned by all the different // container lifecycle hooks. The created function will iterate over all the hooks and call them one by one. func containerHookFn(ctx context.Context, containerHook []ContainerHook) func(container Container) error { - return func(container Container) error { + return func(ctr Container) error { errs := make([]error, len(containerHook)) for i, hook := range containerHook { - errs[i] = hook(ctx, container) + errs[i] = hook(ctx, ctr) } return errors.Join(errs...) diff --git a/lifecycle_test.go b/lifecycle_test.go index f4b0a2ae37..66c4ad8a8a 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -210,12 +210,7 @@ func TestPreCreateModifierHook(t *testing.T) { Name: networkName, }) require.NoError(t, err) - defer func() { - err := net.Remove(ctx) - if err != nil { - t.Logf("failed to remove network %s: %s\n", networkName, err) - } - }() + CleanupNetwork(t, net) dockerNetwork, err := provider.GetNetwork(ctx, NetworkRequest{ Name: networkName, @@ -262,12 +257,7 @@ func TestPreCreateModifierHook(t *testing.T) { Name: networkName, }) require.NoError(t, err) - defer func() { - err := net.Remove(ctx) - if err != nil { - t.Logf("failed to remove network %s: %s\n", networkName, err) - } - }() + CleanupNetwork(t, net) dockerNetwork, err := provider.GetNetwork(ctx, NetworkRequest{ Name: networkName, @@ -549,91 +539,91 @@ func TestLifecycleHooks(t *testing.T) { { PreCreates: []ContainerRequestHook{ func(ctx context.Context, req ContainerRequest) error { - prints = append(prints, fmt.Sprintf("pre-create hook 1: %#v", req)) + prints = append(prints, "pre-create hook 1") return nil }, func(ctx context.Context, req ContainerRequest) error { - prints = append(prints, fmt.Sprintf("pre-create hook 2: %#v", req)) + prints = append(prints, "pre-create hook 2") return nil }, }, PostCreates: []ContainerHook{ func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("post-create hook 1: %#v", c)) + prints = append(prints, "post-create hook 1") return nil }, func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("post-create hook 2: %#v", c)) + prints = append(prints, "post-create hook 2") return nil }, }, PreStarts: []ContainerHook{ func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("pre-start hook 1: %#v", c)) + prints = append(prints, "pre-start hook 1") return nil }, func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("pre-start hook 2: %#v", c)) + prints = append(prints, "pre-start hook 2") return nil }, }, PostStarts: []ContainerHook{ func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("post-start hook 1: %#v", c)) + prints = append(prints, "post-start hook 1") return nil }, func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("post-start hook 2: %#v", c)) + prints = append(prints, "post-start hook 2") return nil }, }, PostReadies: []ContainerHook{ func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("post-ready hook 1: %#v", c)) + prints = append(prints, "post-ready hook 1") return nil }, func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("post-ready hook 2: %#v", c)) + prints = append(prints, "post-ready hook 2") return nil }, }, PreStops: []ContainerHook{ func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("pre-stop hook 1: %#v", c)) + prints = append(prints, "pre-stop hook 1") return nil }, func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("pre-stop hook 2: %#v", c)) + prints = append(prints, "pre-stop hook 2") return nil }, }, PostStops: []ContainerHook{ func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("post-stop hook 1: %#v", c)) + prints = append(prints, "post-stop hook 1") return nil }, func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("post-stop hook 2: %#v", c)) + prints = append(prints, "post-stop hook 2") return nil }, }, PreTerminates: []ContainerHook{ func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("pre-terminate hook 1: %#v", c)) + prints = append(prints, "pre-terminate hook 1") return nil }, func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("pre-terminate hook 2: %#v", c)) + prints = append(prints, "pre-terminate hook 2") return nil }, }, PostTerminates: []ContainerHook{ func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("post-terminate hook 1: %#v", c)) + prints = append(prints, "post-terminate hook 1") return nil }, func(ctx context.Context, c Container) error { - prints = append(prints, fmt.Sprintf("post-terminate hook 2: %#v", c)) + prints = append(prints, "post-terminate hook 2") return nil }, }, @@ -651,6 +641,7 @@ func TestLifecycleHooks(t *testing.T) { Reuse: tt.reuse, Started: true, }) + CleanupContainer(t, c) require.NoError(t, err) require.NotNil(t, c) @@ -664,7 +655,7 @@ func TestLifecycleHooks(t *testing.T) { err = c.Terminate(ctx) require.NoError(t, err) - lifecycleHooksIsHonouredFn(t, ctx, prints) + lifecycleHooksIsHonouredFn(t, prints) }) } } @@ -698,6 +689,7 @@ func TestLifecycleHooks_WithDefaultLogger(t *testing.T) { ContainerRequest: req, Started: true, }) + CleanupContainer(t, c) require.NoError(t, err) require.NotNil(t, c) @@ -711,7 +703,8 @@ func TestLifecycleHooks_WithDefaultLogger(t *testing.T) { err = c.Terminate(ctx) require.NoError(t, err) - require.Len(t, dl.data, 12) + // Includes two additional entries for stop when terminate is called. + require.Len(t, dl.data, 14) } func TestCombineLifecycleHooks(t *testing.T) { @@ -864,6 +857,7 @@ func TestLifecycleHooks_WithMultipleHooks(t *testing.T) { ContainerRequest: req, Started: true, }) + CleanupContainer(t, c) require.NoError(t, err) require.NotNil(t, c) @@ -877,7 +871,8 @@ func TestLifecycleHooks_WithMultipleHooks(t *testing.T) { err = c.Terminate(ctx) require.NoError(t, err) - require.Len(t, dl.data, 24) + // Includes four additional entries for stop (twice) when terminate is called. + require.Len(t, dl.data, 28) } type linesTestLogger struct { @@ -901,19 +896,19 @@ func TestPrintContainerLogsOnError(t *testing.T) { data: []string{}, } - container, err := GenericContainer(ctx, GenericContainerRequest{ + ctr, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: req, Logger: &arrayOfLinesLogger, Started: true, }) + CleanupContainer(t, ctr) // it should fail because the waiting for condition is not met if err == nil { t.Fatal(err) } - terminateContainerOnEnd(t, ctx, container) - containerLogs, err := container.Logs(ctx) + containerLogs, err := ctr.Logs(ctx) if err != nil { t.Fatal(err) } @@ -944,42 +939,40 @@ func TestPrintContainerLogsOnError(t *testing.T) { } } -func lifecycleHooksIsHonouredFn(t *testing.T, ctx context.Context, prints []string) { - require.Len(t, prints, 24) - - assert.True(t, strings.HasPrefix(prints[0], "pre-create hook 1: ")) - assert.True(t, strings.HasPrefix(prints[1], "pre-create hook 2: ")) - - assert.True(t, strings.HasPrefix(prints[2], "post-create hook 1: ")) - assert.True(t, strings.HasPrefix(prints[3], "post-create hook 2: ")) - - assert.True(t, strings.HasPrefix(prints[4], "pre-start hook 1: ")) - assert.True(t, strings.HasPrefix(prints[5], "pre-start hook 2: ")) - - assert.True(t, strings.HasPrefix(prints[6], "post-start hook 1: ")) - assert.True(t, strings.HasPrefix(prints[7], "post-start hook 2: ")) - - assert.True(t, strings.HasPrefix(prints[8], "post-ready hook 1: ")) - assert.True(t, strings.HasPrefix(prints[9], "post-ready hook 2: ")) - - assert.True(t, strings.HasPrefix(prints[10], "pre-stop hook 1: ")) - assert.True(t, strings.HasPrefix(prints[11], "pre-stop hook 2: ")) - - assert.True(t, strings.HasPrefix(prints[12], "post-stop hook 1: ")) - assert.True(t, strings.HasPrefix(prints[13], "post-stop hook 2: ")) - - assert.True(t, strings.HasPrefix(prints[14], "pre-start hook 1: ")) - assert.True(t, strings.HasPrefix(prints[15], "pre-start hook 2: ")) - - assert.True(t, strings.HasPrefix(prints[16], "post-start hook 1: ")) - assert.True(t, strings.HasPrefix(prints[17], "post-start hook 2: ")) - - assert.True(t, strings.HasPrefix(prints[18], "post-ready hook 1: ")) - assert.True(t, strings.HasPrefix(prints[19], "post-ready hook 2: ")) - - assert.True(t, strings.HasPrefix(prints[20], "pre-terminate hook 1: ")) - assert.True(t, strings.HasPrefix(prints[21], "pre-terminate hook 2: ")) +func lifecycleHooksIsHonouredFn(t *testing.T, prints []string) { + t.Helper() + + expects := []string{ + "pre-create hook 1", + "pre-create hook 2", + "post-create hook 1", + "post-create hook 2", + "pre-start hook 1", + "pre-start hook 2", + "post-start hook 1", + "post-start hook 2", + "post-ready hook 1", + "post-ready hook 2", + "pre-stop hook 1", + "pre-stop hook 2", + "post-stop hook 1", + "post-stop hook 2", + "pre-start hook 1", + "pre-start hook 2", + "post-start hook 1", + "post-start hook 2", + "post-ready hook 1", + "post-ready hook 2", + // Terminate currently calls stop to ensure that child containers are stopped. + "pre-stop hook 1", + "pre-stop hook 2", + "post-stop hook 1", + "post-stop hook 2", + "pre-terminate hook 1", + "pre-terminate hook 2", + "post-terminate hook 1", + "post-terminate hook 2", + } - assert.True(t, strings.HasPrefix(prints[22], "post-terminate hook 1: ")) - assert.True(t, strings.HasPrefix(prints[23], "post-terminate hook 2: ")) + require.Equal(t, expects, prints) } diff --git a/logconsumer_test.go b/logconsumer_test.go index 6265f0a578..855a849914 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -92,6 +92,7 @@ func Test_LogConsumerGetsCalled(t *testing.T) { } c, err := GenericContainer(ctx, gReq) + CleanupContainer(t, c) require.NoError(t, err) ep, err := c.Endpoint(ctx, "http") @@ -112,9 +113,7 @@ func Test_LogConsumerGetsCalled(t *testing.T) { t.Fatal("never received final log message") } - assert.Equal(t, []string{"ready\n", "echo hello\n", "echo there\n"}, g.Msgs()) - - terminateContainerOnEnd(t, ctx, c) + require.Equal(t, []string{"ready\n", "echo hello\n", "echo there\n"}, g.Msgs()) } type TestLogTypeConsumer struct { @@ -157,8 +156,8 @@ func Test_ShouldRecognizeLogTypes(t *testing.T) { } c, err := GenericContainer(ctx, gReq) + CleanupContainer(t, c) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, c) ep, err := c.Endpoint(ctx, "http") require.NoError(t, err) @@ -212,6 +211,7 @@ func Test_MultipleLogConsumers(t *testing.T) { } c, err := GenericContainer(ctx, gReq) + CleanupContainer(t, c) require.NoError(t, err) ep, err := c.Endpoint(ctx, "http") @@ -226,9 +226,9 @@ func Test_MultipleLogConsumers(t *testing.T) { <-first.Done <-second.Done - assert.Equal(t, []string{"ready\n", "echo mlem\n"}, first.Msgs()) - assert.Equal(t, []string{"ready\n", "echo mlem\n"}, second.Msgs()) - require.NoError(t, c.Terminate(ctx)) + expected := []string{"ready\n", "echo mlem\n"} + require.Equal(t, expected, first.Msgs()) + require.Equal(t, expected, second.Msgs()) } func TestContainerLogWithErrClosed(t *testing.T) { @@ -258,9 +258,8 @@ func TestContainerLogWithErrClosed(t *testing.T) { Privileged: true, }, }) - + CleanupContainer(t, dind) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, dind) var remoteDocker string @@ -320,7 +319,7 @@ func TestContainerLogWithErrClosed(t *testing.T) { if err := nginx.Start(ctx); err != nil { t.Fatal(err) } - terminateContainerOnEnd(t, ctx, nginx) + CleanupContainer(t, nginx) port, err := nginx.MappedPort(ctx, "80/tcp") if err != nil { @@ -380,15 +379,16 @@ func TestContainerLogsShouldBeWithoutStreamHeader(t *testing.T) { Cmd: []string{"sh", "-c", "id -u"}, WaitingFor: wait.ForExit(), } - container, err := GenericContainer(ctx, GenericContainerRequest{ + ctr, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: req, Started: true, }) + CleanupContainer(t, ctr) if err != nil { t.Fatal(err) } - terminateContainerOnEnd(t, ctx, container) - r, err := container.Logs(ctx) + + r, err := ctr.Logs(ctx) if err != nil { t.Fatal(err) } @@ -429,6 +429,7 @@ func TestContainerLogsEnableAtStart(t *testing.T) { } c, err := GenericContainer(ctx, gReq) + CleanupContainer(t, c) require.NoError(t, err) ep, err := c.Endpoint(ctx, "http") @@ -448,9 +449,7 @@ func TestContainerLogsEnableAtStart(t *testing.T) { case <-time.After(10 * time.Second): t.Fatal("never received final log message") } - assert.Equal(t, []string{"ready\n", "echo hello\n", "echo there\n"}, g.Msgs()) - - terminateContainerOnEnd(t, ctx, c) + require.Equal(t, []string{"ready\n", "echo hello\n", "echo there\n"}, g.Msgs()) } func Test_StartLogProductionStillStartsWithTooLowTimeout(t *testing.T) { @@ -481,8 +480,8 @@ func Test_StartLogProductionStillStartsWithTooLowTimeout(t *testing.T) { } c, err := GenericContainer(ctx, gReq) + CleanupContainer(t, c) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, c) } func Test_StartLogProductionStillStartsWithTooHighTimeout(t *testing.T) { @@ -513,22 +512,25 @@ func Test_StartLogProductionStillStartsWithTooHighTimeout(t *testing.T) { } c, err := GenericContainer(ctx, gReq) + CleanupContainer(t, c) require.NoError(t, err) require.NotNil(t, c) - // because the log production timeout is too high, the container should have already been terminated - // so no need to terminate it again with "terminateContainerOnEnd(t, ctx, c)" dc := c.(*DockerContainer) require.NoError(t, dc.stopLogProduction()) - - terminateContainerOnEnd(t, ctx, c) } func Test_MultiContainerLogConsumer_CancelledContext(t *testing.T) { // Redirect stderr to a buffer + r, w, err := os.Pipe() + require.NoError(t, err) oldStderr := os.Stderr - r, w, _ := os.Pipe() os.Stderr = w + defer func() { + // Restore stderr + os.Stderr = oldStderr + w.Close() + }() // Context with cancellation functionality for simulating user interruption ctx, cancel := context.WithCancel(context.Background()) @@ -558,6 +560,7 @@ func Test_MultiContainerLogConsumer_CancelledContext(t *testing.T) { } c, err := GenericContainer(ctx, genericReq1) + CleanupContainer(t, c) require.NoError(t, err) ep1, err := c.Endpoint(ctx, "http") @@ -593,6 +596,7 @@ func Test_MultiContainerLogConsumer_CancelledContext(t *testing.T) { } c2, err := GenericContainer(ctx, genericReq2) + CleanupContainer(t, c2) require.NoError(t, err) ep2, err := c2.Endpoint(ctx, "http") @@ -604,16 +608,6 @@ func Test_MultiContainerLogConsumer_CancelledContext(t *testing.T) { _, err = http.Get(ep2 + "/stdout?echo=there2") require.NoError(t, err) - // Handling the termination of the containers - defer func() { - shutdownCtx, shutdownCancel := context.WithTimeout( - context.Background(), 10*time.Second, - ) - defer shutdownCancel() - _ = c.Terminate(shutdownCtx) - _ = c2.Terminate(shutdownCtx) - }() - // Deliberately calling context cancel cancel() @@ -622,9 +616,8 @@ func Test_MultiContainerLogConsumer_CancelledContext(t *testing.T) { assert.GreaterOrEqual(t, len(first.Msgs()), 2) assert.GreaterOrEqual(t, len(second.Msgs()), 2) - // Restore stderr + // Close the pipe so as not to block on empty. w.Close() - os.Stderr = oldStderr // Read the stderr output from the buffer var buf bytes.Buffer @@ -636,7 +629,7 @@ func Test_MultiContainerLogConsumer_CancelledContext(t *testing.T) { // The context cancel shouldn't cause the system to throw a // logStoppedForOutOfSyncMessage, as it hangs the system with // the multiple containers. - assert.False(t, strings.Contains(actual, logStoppedForOutOfSyncMessage)) + require.NotContains(t, actual, logStoppedForOutOfSyncMessage) } // FooLogConsumer is a test log consumer that accepts logs from the @@ -689,7 +682,7 @@ func TestRestartContainerWithLogConsumer(t *testing.T) { logConsumer := NewFooLogConsumer(t) ctx := context.Background() - container, err := GenericContainer(ctx, GenericContainerRequest{ + ctr, err := GenericContainer(ctx, GenericContainerRequest{ ContainerRequest: ContainerRequest{ Image: "hello-world", AlwaysPullImage: true, @@ -699,24 +692,24 @@ func TestRestartContainerWithLogConsumer(t *testing.T) { }, Started: false, }) - terminateContainerOnEnd(t, ctx, container) + CleanupContainer(t, ctr) require.NoError(t, err) // Start and confirm that the log consumer receives the log message. - err = container.Start(ctx) + err = ctr.Start(ctx) require.NoError(t, err) logConsumer.AssertRead() // Stop the container and clear any pending message. d := 5 * time.Second - err = container.Stop(ctx, &d) + err = ctr.Stop(ctx, &d) require.NoError(t, err) logConsumer.SlurpOne() // Restart the container and confirm that the log consumer receives new log messages. - err = container.Start(ctx) + err = ctr.Start(ctx) require.NoError(t, err) // First message is from the first start. diff --git a/modulegen/_template/examples_test.go.tmpl b/modulegen/_template/examples_test.go.tmpl index b81cf22c58..f02ab36021 100644 --- a/modulegen/_template/examples_test.go.tmpl +++ b/modulegen/_template/examples_test.go.tmpl @@ -13,21 +13,21 @@ func Example{{ $entrypoint }}() { ctx := context.Background() {{ $lower }}Container, err := {{ $lower }}.{{ $entrypoint }}(ctx, "{{ $image }}") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := {{ $lower }}Container.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer({{ $lower }}Container); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := {{ $lower }}Container.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modulegen/_template/module.go.tmpl b/modulegen/_template/module.go.tmpl index fe988afada..31e50981d0 100644 --- a/modulegen/_template/module.go.tmpl +++ b/modulegen/_template/module.go.tmpl @@ -30,9 +30,14 @@ func {{ $entrypoint }}(ctx context.Context, img string, opts ...testcontainers.C } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *{{ $containerName }} + if container != nil { + c = &{{ $containerName }}{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &{{ $containerName }}{Container: container}, nil + return c, nil } diff --git a/modulegen/_template/module_test.go.tmpl b/modulegen/_template/module_test.go.tmpl index 2f7774ad7a..351ba5c8d5 100644 --- a/modulegen/_template/module_test.go.tmpl +++ b/modulegen/_template/module_test.go.tmpl @@ -4,23 +4,17 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go/{{ ParentDir }}/{{ $lower }}" ) func Test{{ $title }}(t *testing.T) { ctx := context.Background() - container, err := {{ $lower }}.{{ $entrypoint }}(ctx, "{{ $image }}") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := {{ $lower }}.{{ $entrypoint }}(ctx, "{{ $image }}") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions } diff --git a/modulegen/main_test.go b/modulegen/main_test.go index 2c1ddbd8e9..322cb25920 100644 --- a/modulegen/main_test.go +++ b/modulegen/main_test.go @@ -407,8 +407,8 @@ func assertModuleTestContent(t *testing.T, module context.TestcontainersModule, data := sanitiseContent(content) assert.Equal(t, "package "+module.Lower()+"_test", data[0]) - assert.Equal(t, "func Test"+module.Title()+"(t *testing.T) {", data[9]) - assert.Equal(t, "\tcontainer, err := "+module.Lower()+"."+module.Entrypoint()+"(ctx, \""+module.Image+"\")", data[12]) + assert.Equal(t, "func Test"+module.Title()+"(t *testing.T) {", data[11]) + assert.Equal(t, "\tctr, err := "+module.Lower()+"."+module.Entrypoint()+"(ctx, \""+module.Image+"\")", data[14]) } // assert content module @@ -422,15 +422,17 @@ func assertModuleContent(t *testing.T, module context.TestcontainersModule, exam entrypoint := module.Entrypoint() data := sanitiseContent(content) - assert.Equal(t, "package "+lower, data[0]) - assert.Equal(t, "// "+containerName+" represents the "+exampleName+" container type used in the module", data[9]) - assert.Equal(t, "type "+containerName+" struct {", data[10]) - assert.Equal(t, "// "+entrypoint+" creates an instance of the "+exampleName+" container type", data[14]) - assert.Equal(t, "func "+entrypoint+"(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*"+containerName+", error) {", data[15]) - assert.Equal(t, "\t\tImage: img,", data[17]) - assert.Equal(t, "\t\tif err := opt.Customize(&genericContainerReq); err != nil {", data[26]) - assert.Equal(t, "\t\t\treturn nil, fmt.Errorf(\"customize: %w\", err)", data[27]) - assert.Equal(t, "\treturn &"+containerName+"{Container: container}, nil", data[36]) + require.Equal(t, "package "+lower, data[0]) + require.Equal(t, "// "+containerName+" represents the "+exampleName+" container type used in the module", data[9]) + require.Equal(t, "type "+containerName+" struct {", data[10]) + require.Equal(t, "// "+entrypoint+" creates an instance of the "+exampleName+" container type", data[14]) + require.Equal(t, "func "+entrypoint+"(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*"+containerName+", error) {", data[15]) + require.Equal(t, "\t\tImage: img,", data[17]) + require.Equal(t, "\t\tif err := opt.Customize(&genericContainerReq); err != nil {", data[26]) + require.Equal(t, "\t\t\treturn nil, fmt.Errorf(\"customize: %w\", err)", data[27]) + require.Equal(t, "\tvar c *"+containerName, data[32]) + require.Equal(t, "\t\tc = &"+containerName+"{Container: container}", data[34]) + require.Equal(t, "\treturn c, nil", data[41]) } // assert content GitHub workflow for the module diff --git a/modules/artemis/artemis.go b/modules/artemis/artemis.go index 9edfcaa527..a8721ce189 100644 --- a/modules/artemis/artemis.go +++ b/modules/artemis/artemis.go @@ -109,12 +109,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, req) + var c *Container + if container != nil { + c = &Container{Container: container} + } if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - user := req.Env["ARTEMIS_USER"] - password := req.Env["ARTEMIS_PASSWORD"] + c.user = req.Env["ARTEMIS_USER"] + c.password = req.Env["ARTEMIS_PASSWORD"] - return &Container{Container: container, user: user, password: password}, nil + return c, nil } diff --git a/modules/artemis/artemis_test.go b/modules/artemis/artemis_test.go index c2767790ad..01097463b2 100644 --- a/modules/artemis/artemis_test.go +++ b/modules/artemis/artemis_test.go @@ -64,12 +64,12 @@ func TestArtemis(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - container, err := artemis.Run(ctx, "docker.io/apache/activemq-artemis:2.30.0-alpine", test.opts...) + ctr, err := artemis.Run(ctx, "docker.io/apache/activemq-artemis:2.30.0-alpine", test.opts...) + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, container.Terminate(ctx), "failed to terminate container") }) // consoleURL { - u, err := container.ConsoleURL(ctx) + u, err := ctr.ConsoleURL(ctx) // } require.NoError(t, err) @@ -79,15 +79,15 @@ func TestArtemis(t *testing.T) { assert.Equal(t, http.StatusOK, res.StatusCode, "failed to access console") if test.user != "" { - assert.Equal(t, test.user, container.User(), "unexpected user") + assert.Equal(t, test.user, ctr.User(), "unexpected user") } if test.pass != "" { - assert.Equal(t, test.pass, container.Password(), "unexpected password") + assert.Equal(t, test.pass, ctr.Password(), "unexpected password") } // brokerEndpoint { - host, err := container.BrokerEndpoint(ctx) + host, err := ctr.BrokerEndpoint(ctx) // } require.NoError(t, err) @@ -116,7 +116,7 @@ func TestArtemis(t *testing.T) { } if test.hook != nil { - test.hook(t, container) + test.hook(t, ctr) } }) } diff --git a/modules/artemis/examples_test.go b/modules/artemis/examples_test.go index e1c21f3afc..78f8c2d13d 100644 --- a/modules/artemis/examples_test.go +++ b/modules/artemis/examples_test.go @@ -7,6 +7,7 @@ import ( "github.com/go-stomp/stomp/v3" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/artemis" ) @@ -18,19 +19,21 @@ func ExampleRun() { "docker.io/apache/activemq-artemis:2.30.0", artemis.WithCredentials("test", "test"), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } defer func() { - if err := artemisContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(artemisContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := artemisContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -39,7 +42,8 @@ func ExampleRun() { // Get broker endpoint. host, err := artemisContainer.BrokerEndpoint(ctx) if err != nil { - log.Fatalf("failed to get broker endpoint: %s", err) + log.Printf("failed to get broker endpoint: %s", err) + return } // containerUser { @@ -52,11 +56,12 @@ func ExampleRun() { // Connect to Artemis via STOMP. conn, err := stomp.Dial("tcp", host, stomp.ConnOpt.Login(user, pass)) if err != nil { - log.Fatalf("failed to connect to Artemis: %s", err) + log.Printf("failed to connect to Artemis: %s", err) + return } defer func() { if err := conn.Disconnect(); err != nil { - log.Fatalf("failed to disconnect from Artemis: %s", err) + log.Printf("failed to disconnect from Artemis: %s", err) } }() // } diff --git a/modules/azurite/azurite.go b/modules/azurite/azurite.go index 1dcdae4709..c3172fd58a 100644 --- a/modules/azurite/azurite.go +++ b/modules/azurite/azurite.go @@ -121,9 +121,14 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *AzuriteContainer + if container != nil { + c = &AzuriteContainer{Container: container, Settings: settings} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &AzuriteContainer{Container: container, Settings: settings}, nil + return c, nil } diff --git a/modules/azurite/azurite_test.go b/modules/azurite/azurite_test.go index 8fe5946e2f..618fc28b0b 100644 --- a/modules/azurite/azurite_test.go +++ b/modules/azurite/azurite_test.go @@ -4,23 +4,18 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/azurite" ) func TestAzurite(t *testing.T) { ctx := context.Background() - container, err := azurite.Run(ctx, "mcr.microsoft.com/azure-storage/azurite:3.23.0") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := azurite.Run(ctx, "mcr.microsoft.com/azure-storage/azurite:3.23.0") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions } diff --git a/modules/azurite/examples_test.go b/modules/azurite/examples_test.go index d2fc9965f0..567685891f 100644 --- a/modules/azurite/examples_test.go +++ b/modules/azurite/examples_test.go @@ -12,6 +12,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/azurite" ) @@ -23,21 +24,21 @@ func ExampleRun() { ctx, "mcr.microsoft.com/azure-storage/azurite:3.28.0", ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := azuriteContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(azuriteContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := azuriteContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -57,20 +58,21 @@ func ExampleRun_blobOperations() { "mcr.microsoft.com/azure-storage/azurite:3.28.0", azurite.WithInMemoryPersistence(64), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := azuriteContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(azuriteContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // using the built-in shared key credential type cred, err := azblob.NewSharedKeyCredential(azurite.AccountName, azurite.AccountKey) if err != nil { - log.Fatalf("failed to create shared key credential: %s", err) // nolint:gocritic + log.Printf("failed to create shared key credential: %s", err) + return } // create an azblob.Client for the specified storage account that uses the above credentials @@ -78,14 +80,16 @@ func ExampleRun_blobOperations() { client, err := azblob.NewClientWithSharedKeyCredential(blobServiceURL, cred, nil) if err != nil { - log.Fatalf("failed to create client: %s", err) // nolint:gocritic + log.Printf("failed to create client: %s", err) + return } // ===== 1. Create a container ===== containerName := "testcontainer" _, err = client.CreateContainer(context.TODO(), containerName, nil) if err != nil { - log.Fatalf("failed to create container: %s", err) + log.Printf("failed to create container: %s", err) + return } // ===== 2. Upload and Download a block blob ===== @@ -101,13 +105,15 @@ func ExampleRun_blobOperations() { Tags: map[string]string{"Year": "2022"}, }) if err != nil { - log.Fatalf("failed to upload blob: %s", err) + log.Printf("failed to upload blob: %s", err) + return } // Download the blob's contents and ensure that the download worked properly blobDownloadResponse, err := client.DownloadStream(context.TODO(), containerName, blobName, nil) if err != nil { - log.Fatalf("failed to download blob: %s", err) // nolint:gocritic + log.Printf("failed to download blob: %s", err) + return } // Use the bytes.Buffer object to read the downloaded data. @@ -115,7 +121,8 @@ func ExampleRun_blobOperations() { reader := blobDownloadResponse.Body downloadData, err := io.ReadAll(reader) if err != nil { - log.Fatalf("failed to read downloaded data: %s", err) // nolint:gocritic + log.Printf("failed to read downloaded data: %s", err) + return } fmt.Println(string(downloadData)) @@ -133,7 +140,8 @@ func ExampleRun_blobOperations() { for pager.More() { resp, err := pager.NextPage(context.TODO()) if err != nil { - log.Fatalf("failed to list blobs: %s", err) + log.Printf("failed to list blobs: %s", err) + return } fmt.Println(len(resp.Segment.BlobItems)) @@ -142,13 +150,15 @@ func ExampleRun_blobOperations() { // Delete the blob. _, err = client.DeleteBlob(context.TODO(), containerName, blobName, nil) if err != nil { - log.Fatalf("failed to delete blob: %s", err) + log.Printf("failed to delete blob: %s", err) + return } // Delete the container. _, err = client.DeleteContainer(context.TODO(), containerName, nil) if err != nil { - log.Fatalf("failed to delete container: %s", err) + log.Printf("failed to delete container: %s", err) + return } // } @@ -169,20 +179,21 @@ func ExampleRun_queueOperations() { "mcr.microsoft.com/azure-storage/azurite:3.28.0", azurite.WithInMemoryPersistence(64), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := azuriteContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(azuriteContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // using the built-in shared key credential type cred, err := azqueue.NewSharedKeyCredential(azurite.AccountName, azurite.AccountKey) if err != nil { - log.Fatalf("failed to create shared key credential: %s", err) // nolint:gocritic + log.Printf("failed to create shared key credential: %s", err) + return } // create an azqueue.Client for the specified storage account that uses the above credentials @@ -190,7 +201,8 @@ func ExampleRun_queueOperations() { client, err := azqueue.NewServiceClientWithSharedKeyCredential(queueServiceURL, cred, nil) if err != nil { - log.Fatalf("failed to create client: %s", err) + log.Printf("failed to create client: %s", err) + return } queueName := "testqueue" @@ -199,7 +211,8 @@ func ExampleRun_queueOperations() { Metadata: map[string]*string{"hello": to.Ptr("world")}, }) if err != nil { - log.Fatalf("failed to create queue: %s", err) + log.Printf("failed to create queue: %s", err) + return } pager := client.NewListQueuesPager(&azqueue.ListQueuesOptions{ @@ -210,7 +223,8 @@ func ExampleRun_queueOperations() { for pager.More() { resp, err := pager.NextPage(context.Background()) if err != nil { - log.Fatalf("failed to list queues: %s", err) + log.Printf("failed to list queues: %s", err) + return } fmt.Println(len(resp.Queues)) @@ -220,7 +234,8 @@ func ExampleRun_queueOperations() { // delete the queue _, err = client.DeleteQueue(context.TODO(), queueName, &azqueue.DeleteOptions{}) if err != nil { - log.Fatalf("failed to delete queue: %s", err) + log.Printf("failed to delete queue: %s", err) + return } // } @@ -241,20 +256,21 @@ func ExampleRun_tableOperations() { "mcr.microsoft.com/azure-storage/azurite:3.28.0", azurite.WithInMemoryPersistence(64), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := azuriteContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(azuriteContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // using the built-in shared key credential type cred, err := aztables.NewSharedKeyCredential(azurite.AccountName, azurite.AccountKey) if err != nil { - log.Fatalf("failed to create shared key credential: %s", err) // nolint:gocritic + log.Printf("failed to create shared key credential: %s", err) + return } // create an aztables.Client for the specified storage account that uses the above credentials @@ -262,14 +278,16 @@ func ExampleRun_tableOperations() { client, err := aztables.NewServiceClientWithSharedKey(tablesServiceURL, cred, nil) if err != nil { - log.Fatalf("failed to create client: %s", err) + log.Printf("failed to create client: %s", err) + return } tableName := "fromServiceClient" // Create a table _, err = client.CreateTable(context.TODO(), tableName, nil) if err != nil { - log.Fatalf("failed to create table: %s", err) + log.Printf("failed to create table: %s", err) + return } // List tables @@ -277,7 +295,8 @@ func ExampleRun_tableOperations() { for pager.More() { resp, err := pager.NextPage(context.Background()) if err != nil { - log.Fatalf("failed to list tables: %s", err) + log.Printf("failed to list tables: %s", err) + return } fmt.Println(len(resp.Tables)) @@ -287,7 +306,8 @@ func ExampleRun_tableOperations() { // Delete a table _, err = client.DeleteTable(context.TODO(), tableName, nil) if err != nil { - panic(err) + fmt.Println(err) + return } // } diff --git a/modules/azurite/go.mod b/modules/azurite/go.mod index 826a457a9a..99eaff2d54 100644 --- a/modules/azurite/go.mod +++ b/modules/azurite/go.mod @@ -8,7 +8,8 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue v1.0.0 github.com/docker/go-connections v0.5.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -21,6 +22,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect @@ -31,6 +33,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -42,6 +45,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -59,6 +63,7 @@ require ( golang.org/x/text v0.16.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/azurite/go.sum b/modules/azurite/go.sum index 0d2267c5a4..4dd10ea119 100644 --- a/modules/azurite/go.sum +++ b/modules/azurite/go.sum @@ -32,6 +32,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -73,6 +74,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= @@ -103,6 +108,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -199,6 +206,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 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= diff --git a/modules/cassandra/cassandra.go b/modules/cassandra/cassandra.go index c5dbfc61d6..e63d1c7e97 100644 --- a/modules/cassandra/cassandra.go +++ b/modules/cassandra/cassandra.go @@ -2,6 +2,7 @@ package cassandra import ( "context" + "fmt" "io" "path/filepath" "strings" @@ -114,9 +115,14 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *CassandraContainer + if container != nil { + c = &CassandraContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &CassandraContainer{Container: container}, nil + return c, nil } diff --git a/modules/cassandra/cassandra_test.go b/modules/cassandra/cassandra_test.go index a878db4f6f..3c8cd1e918 100644 --- a/modules/cassandra/cassandra_test.go +++ b/modules/cassandra/cassandra_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/cassandra" ) @@ -20,26 +21,18 @@ type Test struct { func TestCassandra(t *testing.T) { ctx := context.Background() - container, err := cassandra.Run(ctx, "cassandra:4.1.3") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - require.NoError(t, container.Terminate(ctx)) - }) + ctr, err := cassandra.Run(ctx, "cassandra:4.1.3") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // connectionString { - connectionHost, err := container.ConnectionHost(ctx) + connectionHost, err := ctr.ConnectionHost(ctx) // } require.NoError(t, err) cluster := gocql.NewCluster(connectionHost) session, err := cluster.CreateSession() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer session.Close() // perform assertions @@ -60,17 +53,11 @@ func TestCassandra(t *testing.T) { func TestCassandraWithConfigFile(t *testing.T) { ctx := context.Background() - container, err := cassandra.Run(ctx, "cassandra:4.1.3", cassandra.WithConfigFile(filepath.Join("testdata", "config.yaml"))) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - require.NoError(t, container.Terminate(ctx)) - }) + ctr, err := cassandra.Run(ctx, "cassandra:4.1.3", cassandra.WithConfigFile(filepath.Join("testdata", "config.yaml"))) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - connectionHost, err := container.ConnectionHost(ctx) + connectionHost, err := ctr.ConnectionHost(ctx) require.NoError(t, err) cluster := gocql.NewCluster(connectionHost) @@ -91,19 +78,13 @@ func TestCassandraWithInitScripts(t *testing.T) { ctx := context.Background() // withInitScripts { - container, err := cassandra.Run(ctx, "cassandra:4.1.3", cassandra.WithInitScripts(filepath.Join("testdata", "init.cql"))) + ctr, err := cassandra.Run(ctx, "cassandra:4.1.3", cassandra.WithInitScripts(filepath.Join("testdata", "init.cql"))) // } - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - require.NoError(t, container.Terminate(ctx)) - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // connectionHost { - connectionHost, err := container.ConnectionHost(ctx) + connectionHost, err := ctr.ConnectionHost(ctx) // } require.NoError(t, err) @@ -123,17 +104,11 @@ func TestCassandraWithInitScripts(t *testing.T) { t.Run("with init bash script", func(t *testing.T) { ctx := context.Background() - container, err := cassandra.Run(ctx, "cassandra:4.1.3", cassandra.WithInitScripts(filepath.Join("testdata", "init.sh"))) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - require.NoError(t, container.Terminate(ctx)) - }) + ctr, err := cassandra.Run(ctx, "cassandra:4.1.3", cassandra.WithInitScripts(filepath.Join("testdata", "init.sh"))) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - connectionHost, err := container.ConnectionHost(ctx) + connectionHost, err := ctr.ConnectionHost(ctx) require.NoError(t, err) cluster := gocql.NewCluster(connectionHost) diff --git a/modules/cassandra/examples_test.go b/modules/cassandra/examples_test.go index f80cb3f666..68a80589ea 100644 --- a/modules/cassandra/examples_test.go +++ b/modules/cassandra/examples_test.go @@ -8,6 +8,7 @@ import ( "github.com/gocql/gocql" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/cassandra" ) @@ -20,41 +21,44 @@ func ExampleRun() { cassandra.WithInitScripts(filepath.Join("testdata", "init.cql")), cassandra.WithConfigFile(filepath.Join("testdata", "config.yaml")), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := cassandraContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(cassandraContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := cassandraContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) connectionHost, err := cassandraContainer.ConnectionHost(ctx) if err != nil { - log.Fatalf("failed to get connection host: %s", err) + log.Printf("failed to get connection host: %s", err) + return } cluster := gocql.NewCluster(connectionHost) session, err := cluster.CreateSession() if err != nil { - log.Fatalf("failed to create session: %s", err) + log.Printf("failed to create session: %s", err) + return } defer session.Close() var version string err = session.Query("SELECT release_version FROM system.local").Scan(&version) if err != nil { - log.Fatalf("failed to query: %s", err) + log.Printf("failed to query: %s", err) + return } fmt.Println(version) diff --git a/modules/chroma/chroma.go b/modules/chroma/chroma.go index d0d633f390..d0919e899f 100644 --- a/modules/chroma/chroma.go +++ b/modules/chroma/chroma.go @@ -45,11 +45,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *ChromaContainer + if container != nil { + c = &ChromaContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &ChromaContainer{Container: container}, nil + return c, nil } // RESTEndpoint returns the REST endpoint of the Chroma container diff --git a/modules/chroma/chroma_test.go b/modules/chroma/chroma_test.go index 0e33d059f7..5bf44b3282 100644 --- a/modules/chroma/chroma_test.go +++ b/modules/chroma/chroma_test.go @@ -8,27 +8,20 @@ import ( chromago "github.com/amikos-tech/chroma-go" "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/chroma" ) func TestChroma(t *testing.T) { ctx := context.Background() - container, err := chroma.Run(ctx, "chromadb/chroma:0.4.24") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := chroma.Run(ctx, "chromadb/chroma:0.4.24") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) t.Run("REST Endpoint retrieve docs site", func(tt *testing.T) { // restEndpoint { - restEndpoint, err := container.RESTEndpoint(ctx) + restEndpoint, err := ctr.RESTEndpoint(ctx) // } if err != nil { tt.Fatalf("failed to get REST endpoint: %s", err) @@ -48,9 +41,9 @@ func TestChroma(t *testing.T) { t.Run("GetClient", func(tt *testing.T) { // restEndpoint { - endpoint, err := container.RESTEndpoint(context.Background()) + endpoint, err := ctr.RESTEndpoint(context.Background()) if err != nil { - tt.Fatalf("failed to get REST endpoint: %s", err) // nolint:gocritic + tt.Fatalf("failed to get REST endpoint: %s", err) } chromaClient, err := chromago.NewClient(endpoint) // } diff --git a/modules/chroma/examples_test.go b/modules/chroma/examples_test.go index 1828c1eef4..a44125b242 100644 --- a/modules/chroma/examples_test.go +++ b/modules/chroma/examples_test.go @@ -17,21 +17,21 @@ func ExampleRun() { ctx := context.Background() chromaContainer, err := chroma.Run(ctx, "chromadb/chroma:0.4.24") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := chromaContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(chromaContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := chromaContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -45,24 +45,25 @@ func ExampleChromaContainer_connectWithClient() { ctx := context.Background() chromaContainer, err := chroma.Run(ctx, "chromadb/chroma:0.4.24") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := chromaContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(chromaContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } endpoint, err := chromaContainer.RESTEndpoint(context.Background()) if err != nil { - log.Fatalf("failed to get REST endpoint: %s", err) // nolint:gocritic + log.Printf("failed to get REST endpoint: %s", err) + return } chromaClient, err := chromago.NewClient(endpoint) if err != nil { - log.Fatalf("failed to get client: %s", err) // nolint:gocritic + log.Printf("failed to get client: %s", err) + return } hbs, errHb := chromaClient.Heartbeat(context.Background()) @@ -82,32 +83,35 @@ func ExampleChromaContainer_collections() { ctx := context.Background() chromaContainer, err := chroma.Run(ctx, "chromadb/chroma:0.4.24", testcontainers.WithEnv(map[string]string{"ALLOW_RESET": "true"})) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := chromaContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(chromaContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // getClient { // create the client connection and confirm that we can access the server with it endpoint, err := chromaContainer.RESTEndpoint(context.Background()) if err != nil { - log.Fatalf("failed to get REST endpoint: %s", err) // nolint:gocritic + log.Printf("failed to get REST endpoint: %s", err) + return } chromaClient, err := chromago.NewClient(endpoint) // } if err != nil { - log.Fatalf("failed to get client: %s", err) // nolint:gocritic + log.Printf("failed to get client: %s", err) + return } // reset { reset, err := chromaClient.Reset(context.Background()) // } if err != nil { - log.Fatalf("failed to reset: %s", err) // nolint:gocritic + log.Printf("failed to reset: %s", err) + return } fmt.Printf("Reset successful: %v\n", reset) @@ -116,7 +120,8 @@ func ExampleChromaContainer_collections() { col, err := chromaClient.CreateCollection(context.Background(), "test-collection", map[string]any{}, true, types.NewConsistentHashEmbeddingFunction(), types.L2) // } if err != nil { - log.Fatalf("failed to create collection: %s", err) // nolint:gocritic + log.Printf("failed to create collection: %s", err) + return } fmt.Println("Collection created:", col.Name) @@ -132,7 +137,8 @@ func ExampleChromaContainer_collections() { ) // } if err != nil { - log.Fatalf("failed to add data to collection: %s", err) // nolint:gocritic + log.Printf("failed to add data to collection: %s", err) + return } fmt.Println(col1.Count(context.Background())) @@ -147,7 +153,8 @@ func ExampleChromaContainer_collections() { ) // } if err != nil { - log.Fatalf("failed to query collection: %s", err) // nolint:gocritic + log.Printf("failed to query collection: %s", err) + return } fmt.Printf("Result of query: %v\n", queryResults) @@ -156,7 +163,8 @@ func ExampleChromaContainer_collections() { cols, err := chromaClient.ListCollections(context.Background()) // } if err != nil { - log.Fatalf("failed to list collections: %s", err) // nolint:gocritic + log.Printf("failed to list collections: %s", err) + return } fmt.Println(len(cols)) @@ -165,7 +173,8 @@ func ExampleChromaContainer_collections() { _, err = chromaClient.DeleteCollection(context.Background(), "test-collection") // } if err != nil { - log.Fatalf("failed to delete collection: %s", err) // nolint:gocritic + log.Printf("failed to delete collection: %s", err) + return } fmt.Println(err) diff --git a/modules/clickhouse/clickhouse.go b/modules/clickhouse/clickhouse.go index 88b8b82d4b..43b41110b8 100644 --- a/modules/clickhouse/clickhouse.go +++ b/modules/clickhouse/clickhouse.go @@ -249,13 +249,17 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *ClickHouseContainer + if container != nil { + c = &ClickHouseContainer{Container: container} + } if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - user := req.Env["CLICKHOUSE_USER"] - password := req.Env["CLICKHOUSE_PASSWORD"] - dbName := req.Env["CLICKHOUSE_DB"] + c.User = req.Env["CLICKHOUSE_USER"] + c.Password = req.Env["CLICKHOUSE_PASSWORD"] + c.DbName = req.Env["CLICKHOUSE_DB"] - return &ClickHouseContainer{Container: container, DbName: dbName, Password: password, User: user}, nil + return c, nil } diff --git a/modules/clickhouse/clickhouse_test.go b/modules/clickhouse/clickhouse_test.go index a581e8d4c5..c14814d3fe 100644 --- a/modules/clickhouse/clickhouse_test.go +++ b/modules/clickhouse/clickhouse_test.go @@ -10,7 +10,6 @@ import ( "github.com/ClickHouse/clickhouse-go/v2/lib/driver" "github.com/cenkalti/backoff/v4" "github.com/docker/go-connections/nat" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" @@ -31,29 +30,23 @@ type Test struct { func TestClickHouseDefaultConfig(t *testing.T) { ctx := context.Background() - container, err := clickhouse.Run(ctx, "clickhouse/clickhouse-server:23.3.8.21-alpine") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - require.NoError(t, container.Terminate(ctx)) - }) + ctr, err := clickhouse.Run(ctx, "clickhouse/clickhouse-server:23.3.8.21-alpine") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - connectionHost, err := container.ConnectionHost(ctx) + connectionHost, err := ctr.ConnectionHost(ctx) require.NoError(t, err) conn, err := ch.Open(&ch.Options{ Addr: []string{connectionHost}, Auth: ch.Auth{ - Database: container.DbName, - Username: container.User, - Password: container.Password, + Database: ctr.DbName, + Username: ctr.User, + Password: ctr.Password, }, }) require.NoError(t, err) - assert.NotNil(t, conn) + require.NotNil(t, conn) defer conn.Close() err = conn.Ping(context.Background()) @@ -63,23 +56,17 @@ func TestClickHouseDefaultConfig(t *testing.T) { func TestClickHouseConnectionHost(t *testing.T) { ctx := context.Background() - container, err := clickhouse.Run(ctx, + ctr, err := clickhouse.Run(ctx, "clickhouse/clickhouse-server:23.3.8.21-alpine", clickhouse.WithUsername(user), clickhouse.WithPassword(password), clickhouse.WithDatabase(dbname), ) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - require.NoError(t, container.Terminate(ctx)) - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // connectionHost { - connectionHost, err := container.ConnectionHost(ctx) + connectionHost, err := ctr.ConnectionHost(ctx) // } require.NoError(t, err) @@ -92,74 +79,63 @@ func TestClickHouseConnectionHost(t *testing.T) { }, }) require.NoError(t, err) - assert.NotNil(t, conn) + require.NotNil(t, conn) defer conn.Close() // perform assertions data, err := performCRUD(t, conn) require.NoError(t, err) - assert.Len(t, data, 1) + require.Len(t, data, 1) } func TestClickHouseDSN(t *testing.T) { ctx := context.Background() - container, err := clickhouse.Run(ctx, + ctr, err := clickhouse.Run(ctx, "clickhouse/clickhouse-server:23.3.8.21-alpine", clickhouse.WithUsername(user), clickhouse.WithPassword(password), clickhouse.WithDatabase(dbname), ) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - require.NoError(t, container.Terminate(ctx)) - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // connectionString { - connectionString, err := container.ConnectionString(ctx, "debug=true") + connectionString, err := ctr.ConnectionString(ctx, "debug=true") // } require.NoError(t, err) opts, err := ch.ParseDSN(connectionString) require.NoError(t, err) + opts.Debugf = t.Logf conn, err := ch.Open(opts) require.NoError(t, err) - assert.NotNil(t, conn) + require.NotNil(t, conn) defer conn.Close() // perform assertions data, err := performCRUD(t, conn) require.NoError(t, err) - assert.Len(t, data, 1) + require.Len(t, data, 1) } func TestClickHouseWithInitScripts(t *testing.T) { ctx := context.Background() // withInitScripts { - container, err := clickhouse.Run(ctx, + ctr, err := clickhouse.Run(ctx, "clickhouse/clickhouse-server:23.3.8.21-alpine", clickhouse.WithUsername(user), clickhouse.WithPassword(password), clickhouse.WithDatabase(dbname), clickhouse.WithInitScripts(filepath.Join("testdata", "init-db.sh")), ) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // } - // Clean up the container after the test is complete - t.Cleanup(func() { - require.NoError(t, container.Terminate(ctx)) - }) - - connectionHost, err := container.ConnectionHost(ctx) + connectionHost, err := ctr.ConnectionHost(ctx) require.NoError(t, err) conn, err := ch.Open(&ch.Options{ @@ -171,13 +147,13 @@ func TestClickHouseWithInitScripts(t *testing.T) { }, }) require.NoError(t, err) - assert.NotNil(t, conn) + require.NotNil(t, conn) defer conn.Close() // perform assertions data, err := getAllRows(conn) require.NoError(t, err) - assert.Len(t, data, 1) + require.Len(t, data, 1) } func TestClickHouseWithConfigFile(t *testing.T) { @@ -192,23 +168,17 @@ func TestClickHouseWithConfigFile(t *testing.T) { } for _, tC := range testCases { t.Run(tC.desc, func(t *testing.T) { - container, err := clickhouse.Run(ctx, + ctr, err := clickhouse.Run(ctx, "clickhouse/clickhouse-server:23.3.8.21-alpine", clickhouse.WithUsername(user), clickhouse.WithPassword(""), clickhouse.WithDatabase(dbname), tC.configOption, ) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - require.NoError(t, container.Terminate(ctx)) - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - connectionHost, err := container.ConnectionHost(ctx) + connectionHost, err := ctr.ConnectionHost(ctx) require.NoError(t, err) conn, err := ch.Open(&ch.Options{ @@ -220,13 +190,13 @@ func TestClickHouseWithConfigFile(t *testing.T) { }, }) require.NoError(t, err) - assert.NotNil(t, conn) + require.NotNil(t, conn) defer conn.Close() // perform assertions data, err := performCRUD(t, conn) require.NoError(t, err) - assert.Len(t, data, 1) + require.Len(t, data, 1) }) } } @@ -245,34 +215,24 @@ func TestClickHouseWithZookeeper(t *testing.T) { }, Started: true, }) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, zkcontainer) + require.NoError(t, err) ipaddr, err := zkcontainer.ContainerIP(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) - container, err := clickhouse.Run(ctx, + ctr, err := clickhouse.Run(ctx, "clickhouse/clickhouse-server:23.3.8.21-alpine", clickhouse.WithUsername(user), clickhouse.WithPassword(password), clickhouse.WithDatabase(dbname), clickhouse.WithZookeeper(ipaddr, zkPort.Port()), ) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // } - // Clean up the container after the test is complete - t.Cleanup(func() { - require.NoError(t, container.Terminate(ctx)) - require.NoError(t, zkcontainer.Terminate(ctx)) - }) - - connectionHost, err := container.ConnectionHost(ctx) + connectionHost, err := ctr.ConnectionHost(ctx) require.NoError(t, err) conn, err := ch.Open(&ch.Options{ @@ -284,13 +244,13 @@ func TestClickHouseWithZookeeper(t *testing.T) { }, }) require.NoError(t, err) - assert.NotNil(t, conn) + require.NotNil(t, conn) defer conn.Close() // perform assertions data, err := performReplicatedCRUD(t, conn) require.NoError(t, err) - assert.Len(t, data, 1) + require.Len(t, data, 1) } func performReplicatedCRUD(t *testing.T, conn driver.Conn) ([]Test, error) { diff --git a/modules/clickhouse/examples_test.go b/modules/clickhouse/examples_test.go index d63c440541..bc031f134d 100644 --- a/modules/clickhouse/examples_test.go +++ b/modules/clickhouse/examples_test.go @@ -9,6 +9,7 @@ import ( ch "github.com/ClickHouse/clickhouse-go/v2" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/clickhouse" ) @@ -28,31 +29,35 @@ func ExampleRun() { clickhouse.WithInitScripts(filepath.Join("testdata", "init-db.sh")), clickhouse.WithConfigFile(filepath.Join("testdata", "config.xml")), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } defer func() { - if err := clickHouseContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(clickHouseContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := clickHouseContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) connectionString, err := clickHouseContainer.ConnectionString(ctx) if err != nil { - log.Fatalf("failed to get connection string: %s", err) + log.Printf("failed to get connection string: %s", err) + return } opts, err := ch.ParseDSN(connectionString) if err != nil { - log.Fatalf("failed to parse DSN: %s", err) + log.Printf("failed to parse DSN: %s", err) + return } fmt.Println(strings.HasPrefix(opts.ClientInfo.String(), "clickhouse-go/")) diff --git a/modules/cockroachdb/cockroachdb.go b/modules/cockroachdb/cockroachdb.go index e53ef08c6a..4d412f04d3 100644 --- a/modules/cockroachdb/cockroachdb.go +++ b/modules/cockroachdb/cockroachdb.go @@ -118,10 +118,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, req) + var c *CockroachDBContainer + if container != nil { + c = &CockroachDBContainer{Container: container, opts: o} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &CockroachDBContainer{Container: container, opts: o}, nil + + return c, nil } type modiferFunc func(*testcontainers.GenericContainerRequest, options) error diff --git a/modules/cockroachdb/cockroachdb_test.go b/modules/cockroachdb/cockroachdb_test.go index 1f5a6df0ad..cc355e9168 100644 --- a/modules/cockroachdb/cockroachdb_test.go +++ b/modules/cockroachdb/cockroachdb_test.go @@ -63,15 +63,11 @@ type AuthNSuite struct { func (suite *AuthNSuite) TestConnectionString() { ctx := context.Background() - container, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", suite.opts...) + ctr, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", suite.opts...) + testcontainers.CleanupContainer(suite.T(), ctr) suite.Require().NoError(err) - suite.T().Cleanup(func() { - err := container.Terminate(ctx) - suite.Require().NoError(err) - }) - - connStr, err := removePort(container.MustConnectionString(ctx)) + connStr, err := removePort(ctr.MustConnectionString(ctx)) suite.Require().NoError(err) suite.Equal(suite.url, connStr) @@ -101,15 +97,11 @@ func (suite *AuthNSuite) TestPing() { opts := suite.opts opts = append(opts, input.opts...) - container, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", opts...) + ctr, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", opts...) + testcontainers.CleanupContainer(suite.T(), ctr) suite.Require().NoError(err) - suite.T().Cleanup(func() { - err := container.Terminate(ctx) - suite.Require().NoError(err) - }) - - conn, err := conn(ctx, container) + conn, err := conn(ctx, ctr) suite.Require().NoError(err) defer conn.Close(ctx) @@ -122,15 +114,11 @@ func (suite *AuthNSuite) TestPing() { func (suite *AuthNSuite) TestQuery() { ctx := context.Background() - container, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", suite.opts...) + ctr, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", suite.opts...) + testcontainers.CleanupContainer(suite.T(), ctr) suite.Require().NoError(err) - suite.T().Cleanup(func() { - err := container.Terminate(ctx) - suite.Require().NoError(err) - }) - - conn, err := conn(ctx, container) + conn, err := conn(ctx, ctr) suite.Require().NoError(err) defer conn.Close(ctx) @@ -155,15 +143,9 @@ func (suite *AuthNSuite) TestWithWaitStrategyAndDeadline() { // This will never match a log statement suite.opts = append(suite.opts, testcontainers.WithWaitStrategyAndDeadline(time.Millisecond*250, wait.ForLog("Won't Exist In Logs"))) - container, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", suite.opts...) - + ctr, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", suite.opts...) + testcontainers.CleanupContainer(suite.T(), ctr) suite.Require().ErrorIs(err, context.DeadlineExceeded) - suite.T().Cleanup(func() { - if container != nil { - err := container.Terminate(ctx) - suite.Require().NoError(err) - } - }) }) suite.Run("Expected Failure To Run But Would Succeed ", func() { @@ -171,15 +153,9 @@ func (suite *AuthNSuite) TestWithWaitStrategyAndDeadline() { // This will timeout as we didn't give enough time for intialization, but would have succeeded otherwise suite.opts = append(suite.opts, testcontainers.WithWaitStrategyAndDeadline(time.Millisecond*20, wait.ForLog(nodeStartUpCompleted))) - container, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", suite.opts...) - + ctr, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", suite.opts...) + testcontainers.CleanupContainer(suite.T(), ctr) suite.Require().ErrorIs(err, context.DeadlineExceeded) - suite.T().Cleanup(func() { - if container != nil { - err := container.Terminate(ctx) - suite.Require().NoError(err) - } - }) }) suite.Run("Succeeds And Executes Commands", func() { @@ -187,21 +163,16 @@ func (suite *AuthNSuite) TestWithWaitStrategyAndDeadline() { // This will succeed suite.opts = append(suite.opts, testcontainers.WithWaitStrategyAndDeadline(time.Second*60, wait.ForLog(nodeStartUpCompleted))) - container, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", suite.opts...) + ctr, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", suite.opts...) + testcontainers.CleanupContainer(suite.T(), ctr) suite.Require().NoError(err) - conn, err := conn(ctx, container) + conn, err := conn(ctx, ctr) suite.Require().NoError(err) defer conn.Close(ctx) _, err = conn.Exec(ctx, "CREATE TABLE test (id INT PRIMARY KEY)") suite.Require().NoError(err) - suite.T().Cleanup(func() { - if container != nil { - err := container.Terminate(ctx) - suite.Require().NoError(err) - } - }) }) suite.Run("Succeeds And Executes Commands Waiting on HTTP Endpoint", func() { @@ -209,21 +180,16 @@ func (suite *AuthNSuite) TestWithWaitStrategyAndDeadline() { // This will succeed suite.opts = append(suite.opts, testcontainers.WithWaitStrategyAndDeadline(time.Second*60, wait.ForHTTP("/health").WithPort("8080/tcp"))) - container, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", suite.opts...) + ctr, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1", suite.opts...) + testcontainers.CleanupContainer(suite.T(), ctr) suite.Require().NoError(err) - conn, err := conn(ctx, container) + conn, err := conn(ctx, ctr) suite.Require().NoError(err) defer conn.Close(ctx) _, err = conn.Exec(ctx, "CREATE TABLE test (id INT PRIMARY KEY)") suite.Require().NoError(err) - suite.T().Cleanup(func() { - if container != nil { - err := container.Terminate(ctx) - suite.Require().NoError(err) - } - }) }) } diff --git a/modules/cockroachdb/examples_test.go b/modules/cockroachdb/examples_test.go index b427846d4b..c06c97596b 100644 --- a/modules/cockroachdb/examples_test.go +++ b/modules/cockroachdb/examples_test.go @@ -6,6 +6,7 @@ import ( "log" "net/url" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/cockroachdb" ) @@ -14,31 +15,33 @@ func ExampleRun() { ctx := context.Background() cockroachdbContainer, err := cockroachdb.Run(ctx, "cockroachdb/cockroach:latest-v23.1") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := cockroachdbContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(cockroachdbContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := cockroachdbContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) addr, err := cockroachdbContainer.ConnectionString(ctx) if err != nil { - log.Fatalf("failed to get connection string: %s", err) + log.Printf("failed to get connection string: %s", err) + return } u, err := url.Parse(addr) if err != nil { - log.Fatalf("failed to parse connection string: %s", err) + log.Printf("failed to parse connection string: %s", err) + return } u.Host = fmt.Sprintf("%s:%s", u.Hostname(), "xxx") fmt.Println(u.String()) diff --git a/modules/compose/compose_api.go b/modules/compose/compose_api.go index d1b18ec3b6..9f21d09e87 100644 --- a/modules/compose/compose_api.go +++ b/modules/compose/compose_api.go @@ -460,6 +460,10 @@ func (d *dockerCompose) lookupContainer(ctx context.Context, svcName string) (*t } containerInstance := containers[0] + // TODO: Fix as this is only setting a subset of the fields + // and the container is not fully initialized, for example + // the isRunning flag is not set. + // See: https://github.com/testcontainers/testcontainers-go/issues/2667 ctr := &testcontainers.DockerContainer{ ID: containerInstance.ID, Image: containerInstance.Image, diff --git a/modules/consul/consul.go b/modules/consul/consul.go index fab3c5b29d..c374938c32 100644 --- a/modules/consul/consul.go +++ b/modules/consul/consul.go @@ -94,9 +94,14 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, containerReq) + var c *ConsulContainer + if container != nil { + c = &ConsulContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &ConsulContainer{Container: container}, nil + return c, nil } diff --git a/modules/consul/consul_test.go b/modules/consul/consul_test.go index 2b24457785..f89c785874 100644 --- a/modules/consul/consul_test.go +++ b/modules/consul/consul_test.go @@ -40,12 +40,12 @@ func TestConsul(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - container, err := consul.Run(ctx, "docker.io/hashicorp/consul:1.15", test.opts...) + ctr, err := consul.Run(ctx, "docker.io/hashicorp/consul:1.15", test.opts...) + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, container.Terminate(ctx), "failed to terminate container") }) // Check if API is up - host, err := container.ApiEndpoint(ctx) + host, err := ctr.ApiEndpoint(ctx) require.NoError(t, err) assert.NotEmpty(t, len(host)) diff --git a/modules/consul/examples_test.go b/modules/consul/examples_test.go index a65a30c066..32d323fe3d 100644 --- a/modules/consul/examples_test.go +++ b/modules/consul/examples_test.go @@ -7,6 +7,7 @@ import ( capi "github.com/hashicorp/consul/api" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/consul" ) @@ -15,21 +16,21 @@ func ExampleRun() { ctx := context.Background() consulContainer, err := consul.Run(ctx, "docker.io/hashicorp/consul:1.15") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := consulContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(consulContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := consulContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -43,33 +44,35 @@ func ExampleRun_connect() { ctx := context.Background() consulContainer, err := consul.Run(ctx, "docker.io/hashicorp/consul:1.15") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := consulContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(consulContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } endpoint, err := consulContainer.ApiEndpoint(ctx) if err != nil { - log.Fatalf("failed to get endpoint: %s", err) // nolint:gocritic + log.Printf("failed to get endpoint: %s", err) + return } config := capi.DefaultConfig() config.Address = endpoint client, err := capi.NewClient(config) if err != nil { - log.Fatalf("failed to connect to Consul: %s", err) + log.Printf("failed to connect to Consul: %s", err) + return } // } node_name, err := client.Agent().NodeName() if err != nil { - log.Fatalf("failed to get node name: %s", err) // nolint:gocritic + log.Printf("failed to get node name: %s", err) + return } fmt.Println(len(node_name) > 0) diff --git a/modules/couchbase/couchbase.go b/modules/couchbase/couchbase.go index 5bd73a4eab..e061ecf3a4 100644 --- a/modules/couchbase/couchbase.go +++ b/modules/couchbase/couchbase.go @@ -113,21 +113,23 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var couchbaseContainer *CouchbaseContainer + if container != nil { + couchbaseContainer = &CouchbaseContainer{container, config} + } if err != nil { - return nil, err + return couchbaseContainer, err } - couchbaseContainer := CouchbaseContainer{container, config} - if err = couchbaseContainer.initCluster(ctx); err != nil { - return nil, err + return couchbaseContainer, fmt.Errorf("init cluster: %w", err) } if err = couchbaseContainer.createBuckets(ctx); err != nil { - return nil, err + return couchbaseContainer, fmt.Errorf("create buckets: %w", err) } - return &couchbaseContainer, nil + return couchbaseContainer, nil } // StartContainer creates an instance of the Couchbase container type diff --git a/modules/couchbase/couchbase_test.go b/modules/couchbase/couchbase_test.go index 9fee51317e..c873115898 100644 --- a/modules/couchbase/couchbase_test.go +++ b/modules/couchbase/couchbase_test.go @@ -6,7 +6,9 @@ import ( "time" "github.com/couchbase/gocb/v2" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" tccouchbase "github.com/testcontainers/testcontainers-go/modules/couchbase" ) @@ -29,23 +31,13 @@ func TestCouchbaseWithCommunityContainer(t *testing.T) { WithFlushEnabled(false). WithPrimaryIndex(true) - container, err := tccouchbase.Run(ctx, communityEdition, tccouchbase.WithBuckets(bucket)) - if err != nil { - t.Fatal(err) - } + ctr, err := tccouchbase.Run(ctx, communityEdition, tccouchbase.WithBuckets(bucket)) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // } - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - - cluster, err := connectCluster(ctx, container) - if err != nil { - t.Fatalf("could not connect couchbase: %s", err) - } + cluster, err := connectCluster(ctx, ctr) + require.NoError(t, err) testBucketUsage(t, cluster.Bucket(bucketName)) } @@ -59,25 +51,15 @@ func TestCouchbaseWithEnterpriseContainer(t *testing.T) { WithReplicas(0). WithFlushEnabled(true). WithPrimaryIndex(true) - container, err := tccouchbase.Run(ctx, + ctr, err := tccouchbase.Run(ctx, enterpriseEdition, tccouchbase.WithBuckets(bucket), ) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - cluster, err := connectCluster(ctx, container) - if err != nil { - t.Fatalf("could not connect couchbase: %s", err) - } + cluster, err := connectCluster(ctx, ctr) + require.NoError(t, err) testBucketUsage(t, cluster.Bucket(bucketName)) } @@ -86,55 +68,48 @@ func TestWithCredentials(t *testing.T) { ctx := context.Background() bucketName := "testBucket" - _, err := tccouchbase.Run(ctx, + ctr, err := tccouchbase.Run(ctx, communityEdition, tccouchbase.WithAdminCredentials("testcontainers", "testcontainers.IS.cool!"), tccouchbase.WithBuckets(tccouchbase.NewBucket(bucketName))) - if err != nil { - t.Errorf("Expected error to be [%v] , got nil", err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) } func TestWithCredentials_Password_LessThan_6(t *testing.T) { ctx := context.Background() bucketName := "testBucket" - _, err := tccouchbase.Run(ctx, + ctr, err := tccouchbase.Run(ctx, communityEdition, tccouchbase.WithAdminCredentials("testcontainers", "12345"), tccouchbase.WithBuckets(tccouchbase.NewBucket(bucketName))) - - if err == nil { - t.Errorf("Expected error to be [%v] , got nil", err) - } + testcontainers.CleanupContainer(t, ctr) + require.Error(t, err) } func TestAnalyticsServiceWithCommunityContainer(t *testing.T) { ctx := context.Background() bucketName := "testBucket" - _, err := tccouchbase.Run(ctx, + ctr, err := tccouchbase.Run(ctx, communityEdition, tccouchbase.WithServiceAnalytics(), tccouchbase.WithBuckets(tccouchbase.NewBucket(bucketName))) - - if err == nil { - t.Errorf("Expected error to be [%v] , got nil", err) - } + testcontainers.CleanupContainer(t, ctr) + require.Error(t, err) } func TestEventingServiceWithCommunityContainer(t *testing.T) { ctx := context.Background() bucketName := "testBucket" - _, err := tccouchbase.Run(ctx, + ctr, err := tccouchbase.Run(ctx, communityEdition, tccouchbase.WithServiceEventing(), tccouchbase.WithBuckets(tccouchbase.NewBucket(bucketName))) - - if err == nil { - t.Errorf("Expected error to be [%v] , got nil", err) - } + testcontainers.CleanupContainer(t, ctr) + require.Error(t, err) } func testBucketUsage(t *testing.T, bucket *gocb.Bucket) { diff --git a/modules/couchbase/examples_test.go b/modules/couchbase/examples_test.go index 518b270613..cc1a09a9db 100644 --- a/modules/couchbase/examples_test.go +++ b/modules/couchbase/examples_test.go @@ -7,6 +7,7 @@ import ( "github.com/couchbase/gocb/v2" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/couchbase" ) @@ -27,26 +28,29 @@ func ExampleRun() { couchbase.WithAdminCredentials("testcontainers", "testcontainers.IS.cool!"), couchbase.WithBuckets(bucket), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } defer func() { - if err := couchbaseContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(couchbaseContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := couchbaseContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) connectionString, err := couchbaseContainer.ConnectionString(ctx) if err != nil { - log.Fatalf("failed to get connection string: %s", err) + log.Printf("failed to get connection string: %s", err) + return } cluster, err := gocb.Connect(connectionString, gocb.ClusterOptions{ @@ -54,12 +58,14 @@ func ExampleRun() { Password: couchbaseContainer.Password(), }) if err != nil { - log.Fatalf("failed to connect to cluster: %s", err) + log.Printf("failed to connect to cluster: %s", err) + return } buckets, err := cluster.Buckets().GetAllBuckets(nil) if err != nil { - log.Fatalf("failed to get buckets: %s", err) + log.Printf("failed to get buckets: %s", err) + return } fmt.Println(len(buckets)) diff --git a/modules/couchbase/go.mod b/modules/couchbase/go.mod index cc14840737..d07defe4ae 100644 --- a/modules/couchbase/go.mod +++ b/modules/couchbase/go.mod @@ -6,7 +6,8 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 github.com/couchbase/gocb/v2 v2.7.2 github.com/docker/go-connections v0.5.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 github.com/tidwall/gjson v1.17.1 ) @@ -22,6 +23,7 @@ require ( github.com/couchbase/goprotostellar v1.0.2 // indirect github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20230515165046-68b522a21131 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect @@ -45,6 +47,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -67,6 +70,7 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/grpc v1.64.1 // indirect google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/couchbase/go.sum b/modules/couchbase/go.sum index 7f40c3b63f..f7b1f393fd 100644 --- a/modules/couchbase/go.sum +++ b/modules/couchbase/go.sum @@ -91,8 +91,12 @@ github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -122,6 +126,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -272,6 +278,8 @@ google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGm google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/modules/dolt/dolt.go b/modules/dolt/dolt.go index d819e18f5c..87713233d8 100644 --- a/modules/dolt/dolt.go +++ b/modules/dolt/dolt.go @@ -88,15 +88,20 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var dc *DoltContainer + if container != nil { + dc = &DoltContainer{Container: container, username: username, password: password, database: database} + } if err != nil { - return nil, err + return dc, err } - dc := &DoltContainer{container, username, password, database} - // dolthub/dolt-sql-server does not create user or database, so we do so here - err = dc.initialize(ctx, createUser) - return dc, err + if err = dc.initialize(ctx, createUser); err != nil { + return dc, fmt.Errorf("initialize: %w", err) + } + + return dc, nil } func (c *DoltContainer) initialize(ctx context.Context, createUser bool) error { diff --git a/modules/dolt/dolt_test.go b/modules/dolt/dolt_test.go index a511549c78..61787e237b 100644 --- a/modules/dolt/dolt_test.go +++ b/modules/dolt/dolt_test.go @@ -9,78 +9,64 @@ import ( // Import mysql into the scope of this package (required) _ "github.com/go-sql-driver/mysql" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/dolt" ) func TestDolt(t *testing.T) { ctx := context.Background() - container, err := dolt.Run(ctx, "dolthub/dolt-sql-server:1.32.4") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := dolt.Run(ctx, "dolthub/dolt-sql-server:1.32.4") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions // connectionString { - connectionString, err := container.ConnectionString(ctx) + connectionString, err := ctr.ConnectionString(ctx) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) db, err := sql.Open("mysql", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) + _, err = db.Exec("CREATE TABLE IF NOT EXISTS a_table ( \n" + " `col_1` VARCHAR(128) NOT NULL, \n" + " `col_2` VARCHAR(128) NOT NULL, \n" + " PRIMARY KEY (`col_1`, `col_2`) \n" + ")") - if err != nil { - t.Errorf("error creating table: %+v\n", err) - } + require.NoError(t, err) } func TestDoltWithNonRootUserAndEmptyPassword(t *testing.T) { ctx := context.Background() - _, err := dolt.Run(ctx, + ctr, err := dolt.Run(ctx, "dolthub/dolt-sql-server:1.32.4", dolt.WithDatabase("foo"), dolt.WithUsername("test"), dolt.WithPassword("")) - if err.Error() != "empty password can be used only with the root user" { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.EqualError(t, err, "empty password can be used only with the root user") } func TestDoltWithPublicRemoteCloneUrl(t *testing.T) { ctx := context.Background() - _, err := dolt.Run(ctx, + ctr, err := dolt.Run(ctx, "dolthub/dolt-sql-server:1.32.4", dolt.WithDatabase("foo"), dolt.WithUsername("test"), dolt.WithPassword("test"), dolt.WithScripts(filepath.Join("testdata", "check_clone_public.sh")), dolt.WithDoltCloneRemoteUrl("fake-remote-url")) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) } func createTestCredsFile(t *testing.T) string { @@ -100,7 +86,7 @@ func TestDoltWithPrivateRemoteCloneUrl(t *testing.T) { ctx := context.Background() filename := createTestCredsFile(t) - _, err := dolt.Run(ctx, + ctr, err := dolt.Run(ctx, "dolthub/dolt-sql-server:1.32.4", dolt.WithDatabase("foo"), dolt.WithUsername("test"), @@ -109,93 +95,65 @@ func TestDoltWithPrivateRemoteCloneUrl(t *testing.T) { dolt.WithDoltCloneRemoteUrl("fake-remote-url"), dolt.WithDoltCredsPublicKey("fake-public-key"), dolt.WithCredsFile(filename)) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) } func TestDoltWithRootUserAndEmptyPassword(t *testing.T) { ctx := context.Background() - container, err := dolt.Run(ctx, + ctr, err := dolt.Run(ctx, "dolthub/dolt-sql-server:1.32.4", dolt.WithDatabase("foo"), dolt.WithUsername("root"), dolt.WithPassword("")) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions - connectionString := container.MustConnectionString(ctx) + connectionString := ctr.MustConnectionString(ctx) db, err := sql.Open("mysql", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) + _, err = db.Exec("CREATE TABLE IF NOT EXISTS a_table ( \n" + " `col_1` VARCHAR(128) NOT NULL, \n" + " `col_2` VARCHAR(128) NOT NULL, \n" + " PRIMARY KEY (`col_1`, `col_2`) \n" + ")") - if err != nil { - t.Errorf("error creating table: %+v\n", err) - } + require.NoError(t, err) } func TestDoltWithScripts(t *testing.T) { ctx := context.Background() - container, err := dolt.Run(ctx, + ctr, err := dolt.Run(ctx, "dolthub/dolt-sql-server:1.32.4", dolt.WithScripts(filepath.Join("testdata", "schema.sql"))) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions - connectionString := container.MustConnectionString(ctx) + connectionString := ctr.MustConnectionString(ctx) db, err := sql.Open("mysql", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) + stmt, err := db.Prepare("SELECT name from profile") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + defer stmt.Close() row := stmt.QueryRow() var name string err = row.Scan(&name) - if err != nil { - t.Errorf("error fetching data") - } - if name != "profile 1" { - t.Fatal("The expected record was not found in the database.") - } + require.NoError(t, err) + require.Equal(t, "profile 1", name) } diff --git a/modules/dolt/examples_test.go b/modules/dolt/examples_test.go index 73e430d871..ddbf81b079 100644 --- a/modules/dolt/examples_test.go +++ b/modules/dolt/examples_test.go @@ -7,6 +7,7 @@ import ( "log" "path/filepath" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/dolt" ) @@ -22,21 +23,21 @@ func ExampleRun() { dolt.WithPassword("password"), dolt.WithScripts(filepath.Join("testdata", "schema.sql")), ) - if err != nil { - log.Fatalf("failed to run dolt container: %s", err) // nolint:gocritic - } - - // Clean up the container defer func() { - if err := doltContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate dolt container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(doltContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to run dolt container: %s", err) + return + } // } state, err := doltContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -56,37 +57,41 @@ func ExampleRun_connect() { dolt.WithPassword("password"), dolt.WithScripts(filepath.Join("testdata", "schema.sql")), ) - if err != nil { - log.Fatalf("failed to run dolt container: %s", err) // nolint:gocritic - } - defer func() { - if err := doltContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate dolt container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(doltContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to run dolt container: %s", err) + return + } connectionString := doltContainer.MustConnectionString(ctx) db, err := sql.Open("mysql", connectionString) if err != nil { - log.Fatalf("failed to open database connection: %s", err) // nolint:gocritic + log.Printf("failed to open database connection: %s", err) + return } defer db.Close() if err = db.Ping(); err != nil { - log.Fatalf("failed to ping database: %s", err) // nolint:gocritic + log.Printf("failed to ping database: %s", err) + return } stmt, err := db.Prepare("SELECT dolt_version();") if err != nil { - log.Fatalf("failed to prepate sql statement: %s", err) // nolint:gocritic + log.Printf("failed to prepate sql statement: %s", err) + return } defer stmt.Close() row := stmt.QueryRow() version := "" err = row.Scan(&version) if err != nil { - log.Fatalf("failed to scan row: %s", err) // nolint:gocritic + log.Printf("failed to scan row: %s", err) + return } fmt.Println(version) diff --git a/modules/dolt/go.mod b/modules/dolt/go.mod index 804efb8483..a4c2376a9b 100644 --- a/modules/dolt/go.mod +++ b/modules/dolt/go.mod @@ -4,7 +4,8 @@ go 1.22 require ( github.com/go-sql-driver/mysql v1.7.1 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -16,6 +17,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -27,6 +29,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -38,6 +41,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -54,6 +58,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/dolt/go.sum b/modules/dolt/go.sum index e2bb93b49d..dcc1a8d165 100644 --- a/modules/dolt/go.sum +++ b/modules/dolt/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -54,6 +55,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -80,6 +85,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -176,6 +183,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/elasticsearch/elasticsearch.go b/modules/elasticsearch/elasticsearch.go index 10a863c589..5fab503b36 100644 --- a/modules/elasticsearch/elasticsearch.go +++ b/modules/elasticsearch/elasticsearch.go @@ -95,33 +95,32 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, req) - if err != nil { - return nil, err + var esContainer *ElasticsearchContainer + if container != nil { + esContainer = &ElasticsearchContainer{Container: container, Settings: *settings} } - - esContainer := &ElasticsearchContainer{Container: container, Settings: *settings} - - address, err := configureAddress(ctx, esContainer) if err != nil { - return nil, err + return esContainer, fmt.Errorf("generic container: %w", err) } - esContainer.Settings.Address = address + if err := esContainer.configureAddress(ctx); err != nil { + return esContainer, fmt.Errorf("configure address: %w", err) + } return esContainer, nil } // configureAddress sets the address of the Elasticsearch container. // If the certificate is set, it will use https as protocol, otherwise http. -func configureAddress(ctx context.Context, c *ElasticsearchContainer) (string, error) { +func (c *ElasticsearchContainer) configureAddress(ctx context.Context) error { containerPort, err := c.MappedPort(ctx, defaultHTTPPort+"/tcp") if err != nil { - return "", err + return fmt.Errorf("mapped port: %w", err) } host, err := c.Host(ctx) if err != nil { - return "", err + return fmt.Errorf("host: %w", err) } proto := "http" @@ -129,7 +128,9 @@ func configureAddress(ctx context.Context, c *ElasticsearchContainer) (string, e proto = "https" } - return fmt.Sprintf("%s://%s:%s", proto, host, containerPort.Port()), nil + c.Settings.Address = fmt.Sprintf("%s://%s:%s", proto, host, containerPort.Port()) + + return nil } // configureCertificate transfers the certificate settings to the container request. diff --git a/modules/elasticsearch/elasticsearch_test.go b/modules/elasticsearch/elasticsearch_test.go index 1bc7d79456..69c4149fc4 100644 --- a/modules/elasticsearch/elasticsearch_test.go +++ b/modules/elasticsearch/elasticsearch_test.go @@ -8,6 +8,8 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/elasticsearch" ) @@ -80,22 +82,13 @@ func TestElasticsearch(t *testing.T) { } esContainer, err := elasticsearch.Run(ctx, tt.image, opts...) - if err != nil { - t.Fatal(err) - } - - t.Cleanup(func() { - if err := esContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, esContainer) + require.NoError(t, err) httpClient := configureHTTPClient(esContainer) req, err := http.NewRequest("GET", esContainer.Settings.Address, nil) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // set the password for the request using the Authentication header if tt.passwordCustomiser != nil { @@ -184,23 +177,16 @@ func TestElasticsearch8WithoutSSL(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { ctx := context.Background() - container, err := elasticsearch.Run( + ctr, err := elasticsearch.Run( ctx, baseImage8, testcontainers.WithEnv(map[string]string{ test.configKey: "false", })) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - - if len(container.Settings.CACert) > 0 { + if len(ctr.Settings.CACert) > 0 { t.Fatal("expected CA cert to be empty") } }) @@ -210,26 +196,19 @@ func TestElasticsearch8WithoutSSL(t *testing.T) { func TestElasticsearch8WithoutCredentials(t *testing.T) { ctx := context.Background() - container, err := elasticsearch.Run(ctx, baseImage8) - if err != nil { - t.Fatal(err) - } - - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := elasticsearch.Run(ctx, baseImage8) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - httpClient := configureHTTPClient(container) + httpClient := configureHTTPClient(ctr) - req, err := http.NewRequest("GET", container.Settings.Address, nil) + req, err := http.NewRequest("GET", ctr.Settings.Address, nil) if err != nil { t.Fatal(err) } // elastic:changeme are the default credentials for Elasticsearch 8 - req.SetBasicAuth(container.Settings.Username, container.Settings.Password) + req.SetBasicAuth(ctr.Settings.Username, ctr.Settings.Password) resp, err := httpClient.Do(req) if err != nil { @@ -253,7 +232,8 @@ func TestElasticsearchOSSCannotuseWithPassword(t *testing.T) { ossImage := elasticsearch.DefaultBaseImageOSS + ":7.9.2" - _, err := elasticsearch.Run(ctx, ossImage, elasticsearch.WithPassword("foo")) + ctr, err := elasticsearch.Run(ctx, ossImage, elasticsearch.WithPassword("foo")) + testcontainers.CleanupContainer(t, ctr) if err == nil { t.Fatal(err, "Should not be able to use WithPassword with OSS image.") } diff --git a/modules/elasticsearch/examples_test.go b/modules/elasticsearch/examples_test.go index db578a46ee..f4ada5df60 100644 --- a/modules/elasticsearch/examples_test.go +++ b/modules/elasticsearch/examples_test.go @@ -9,6 +9,7 @@ import ( es "github.com/elastic/go-elasticsearch/v8" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/elasticsearch" ) @@ -16,19 +17,21 @@ func ExampleRun() { // runElasticsearchContainer { ctx := context.Background() elasticsearchContainer, err := elasticsearch.Run(ctx, "docker.elastic.co/elasticsearch/elasticsearch:8.9.0") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } defer func() { - if err := elasticsearchContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(elasticsearchContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := elasticsearchContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -45,15 +48,15 @@ func ExampleRun_withUsingPassword() { "docker.elastic.co/elasticsearch/elasticsearch:7.9.2", elasticsearch.WithPassword("foo"), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } defer func() { - err := elasticsearchContainer.Terminate(ctx) - if err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(elasticsearchContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } fmt.Println(strings.HasPrefix(elasticsearchContainer.Settings.Address, "http://")) @@ -72,15 +75,15 @@ func ExampleRun_connectUsingElasticsearchClient() { "docker.elastic.co/elasticsearch/elasticsearch:8.9.0", elasticsearch.WithPassword("foo"), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } defer func() { - err := elasticsearchContainer.Terminate(ctx) - if err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(elasticsearchContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } cfg := es.Config{ Addresses: []string{ @@ -93,19 +96,22 @@ func ExampleRun_connectUsingElasticsearchClient() { esClient, err := es.NewClient(cfg) if err != nil { - log.Fatalf("error creating the client: %s", err) // nolint:gocritic + log.Printf("error creating the client: %s", err) + return } resp, err := esClient.Info() if err != nil { - log.Fatalf("error getting response: %s", err) + log.Printf("error getting response: %s", err) + return } defer resp.Body.Close() // } var esResp ElasticsearchResponse if err := json.NewDecoder(resp.Body).Decode(&esResp); err != nil { - log.Fatalf("error decoding response: %s", err) + log.Printf("error decoding response: %s", err) + return } fmt.Println(esResp.Tagline) diff --git a/modules/gcloud/bigquery.go b/modules/gcloud/bigquery.go index 54363dc2f2..ce8ff1fcbd 100644 --- a/modules/gcloud/bigquery.go +++ b/modules/gcloud/bigquery.go @@ -33,18 +33,5 @@ func RunBigQuery(ctx context.Context, img string, opts ...testcontainers.Contain req.Cmd = []string{"--project", settings.ProjectID} - container, err := testcontainers.GenericContainer(ctx, req) - if err != nil { - return nil, err - } - - bigQueryContainer, err := newGCloudContainer(ctx, 9050, container, settings) - if err != nil { - return nil, err - } - - // always prepend http:// to the URI - bigQueryContainer.URI = "http://" + bigQueryContainer.URI - - return bigQueryContainer, nil + return newGCloudContainer(ctx, req, 9050, settings, "http://") } diff --git a/modules/gcloud/bigquery_test.go b/modules/gcloud/bigquery_test.go index a39347a23f..957b17e3e5 100644 --- a/modules/gcloud/bigquery_test.go +++ b/modules/gcloud/bigquery_test.go @@ -13,6 +13,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/gcloud" ) @@ -25,16 +26,15 @@ func ExampleRunBigQueryContainer() { "ghcr.io/goccy/bigquery-emulator:0.4.3", gcloud.WithProjectID("bigquery-project"), ) - if err != nil { - log.Fatalf("failed to run container: %v", err) - } - - // Clean up the container defer func() { - if err := bigQueryContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %v", err) + if err := testcontainers.TerminateContainer(bigQueryContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to run container: %v", err) + return + } // } // bigQueryClient { @@ -49,7 +49,8 @@ func ExampleRunBigQueryContainer() { client, err := bigquery.NewClient(ctx, projectID, opts...) if err != nil { - log.Fatalf("failed to create bigquery client: %v", err) // nolint:gocritic + log.Printf("failed to create bigquery client: %v", err) + return } defer client.Close() // } @@ -57,13 +58,15 @@ func ExampleRunBigQueryContainer() { createFnQuery := client.Query("CREATE FUNCTION testr(arr ARRAY>) AS ((SELECT SUM(IF(elem.name = \"foo\",elem.val,null)) FROM UNNEST(arr) AS elem))") _, err = createFnQuery.Read(ctx) if err != nil { - log.Fatalf("failed to create function: %v", err) + log.Printf("failed to create function: %v", err) + return } selectQuery := client.Query("SELECT testr([STRUCT(\"foo\", 10), STRUCT(\"bar\", 40), STRUCT(\"foo\", 20)])") it, err := selectQuery.Read(ctx) if err != nil { - log.Fatalf("failed to read query: %v", err) + log.Printf("failed to read query: %v", err) + return } var val []bigquery.Value @@ -73,7 +76,8 @@ func ExampleRunBigQueryContainer() { break } if err != nil { - log.Fatalf("failed to iterate: %v", err) + log.Printf("failed to iterate: %v", err) + return } } diff --git a/modules/gcloud/bigtable.go b/modules/gcloud/bigtable.go index 4bea521ff1..134f14d1d6 100644 --- a/modules/gcloud/bigtable.go +++ b/modules/gcloud/bigtable.go @@ -2,7 +2,6 @@ package gcloud import ( "context" - "fmt" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" @@ -33,13 +32,8 @@ func RunBigTable(ctx context.Context, img string, opts ...testcontainers.Contain req.Cmd = []string{ "/bin/sh", "-c", - "gcloud beta emulators bigtable start --host-port 0.0.0.0:9000 " + fmt.Sprintf("--project=%s", settings.ProjectID), + "gcloud beta emulators bigtable start --host-port 0.0.0.0:9000 --project=" + settings.ProjectID, } - container, err := testcontainers.GenericContainer(ctx, req) - if err != nil { - return nil, err - } - - return newGCloudContainer(ctx, 9000, container, settings) + return newGCloudContainer(ctx, req, 9000, settings, "") } diff --git a/modules/gcloud/bigtable_test.go b/modules/gcloud/bigtable_test.go index 15409e2b0e..553581bcc4 100644 --- a/modules/gcloud/bigtable_test.go +++ b/modules/gcloud/bigtable_test.go @@ -10,6 +10,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/gcloud" ) @@ -22,16 +23,15 @@ func ExampleRunBigTableContainer() { "gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators", gcloud.WithProjectID("bigtable-project"), ) - if err != nil { - log.Fatalf("failed to run container: %v", err) - } - - // Clean up the container defer func() { - if err := bigTableContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %v", err) + if err := testcontainers.TerminateContainer(bigTableContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to run container: %v", err) + return + } // } // bigTableAdminClient { @@ -49,24 +49,28 @@ func ExampleRunBigTableContainer() { } adminClient, err := bigtable.NewAdminClient(ctx, projectId, instanceId, options...) if err != nil { - log.Fatalf("failed to create admin client: %v", err) // nolint:gocritic + log.Printf("failed to create admin client: %v", err) + return } defer adminClient.Close() // } err = adminClient.CreateTable(ctx, tableName) if err != nil { - log.Fatalf("failed to create table: %v", err) + log.Printf("failed to create table: %v", err) + return } err = adminClient.CreateColumnFamily(ctx, tableName, "name") if err != nil { - log.Fatalf("failed to create column family: %v", err) + log.Printf("failed to create column family: %v", err) + return } // bigTableClient { client, err := bigtable.NewClient(ctx, projectId, instanceId, options...) if err != nil { - log.Fatalf("failed to create client: %v", err) + log.Printf("failed to create client: %v", err) + return } defer client.Close() // } @@ -77,12 +81,14 @@ func ExampleRunBigTableContainer() { mut.Set("name", "firstName", bigtable.Now(), []byte("Gopher")) err = tbl.Apply(ctx, "1", mut) if err != nil { - log.Fatalf("failed to apply mutation: %v", err) + log.Printf("failed to apply mutation: %v", err) + return } row, err := tbl.ReadRow(ctx, "1", bigtable.RowFilter(bigtable.FamilyFilter("name"))) if err != nil { - log.Fatalf("failed to read row: %v", err) + log.Printf("failed to read row: %v", err) + return } fmt.Println(string(row["name"][0].Value)) diff --git a/modules/gcloud/datastore.go b/modules/gcloud/datastore.go index 92ab671842..caf53e9879 100644 --- a/modules/gcloud/datastore.go +++ b/modules/gcloud/datastore.go @@ -2,7 +2,6 @@ package gcloud import ( "context" - "fmt" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" @@ -33,13 +32,8 @@ func RunDatastore(ctx context.Context, img string, opts ...testcontainers.Contai req.Cmd = []string{ "/bin/sh", "-c", - "gcloud beta emulators datastore start --host-port 0.0.0.0:8081 " + fmt.Sprintf("--project=%s", settings.ProjectID), + "gcloud beta emulators datastore start --host-port 0.0.0.0:8081 --project=" + settings.ProjectID, } - container, err := testcontainers.GenericContainer(ctx, req) - if err != nil { - return nil, err - } - - return newGCloudContainer(ctx, 8081, container, settings) + return newGCloudContainer(ctx, req, 8081, settings, "") } diff --git a/modules/gcloud/datastore_test.go b/modules/gcloud/datastore_test.go index 0cf04780ef..fa056bbf63 100644 --- a/modules/gcloud/datastore_test.go +++ b/modules/gcloud/datastore_test.go @@ -10,6 +10,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/gcloud" ) @@ -22,16 +23,15 @@ func ExampleRunDatastoreContainer() { "gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators", gcloud.WithProjectID("datastore-project"), ) - if err != nil { - log.Fatalf("failed to run container: %v", err) - } - - // Clean up the container defer func() { - if err := datastoreContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %v", err) + if err := testcontainers.TerminateContainer(datastoreContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to run container: %v", err) + return + } // } // datastoreClient { @@ -45,7 +45,8 @@ func ExampleRunDatastoreContainer() { dsClient, err := datastore.NewClient(ctx, projectID, options...) if err != nil { - log.Fatalf("failed to create client: %v", err) // nolint:gocritic + log.Printf("failed to create client: %v", err) + return } defer dsClient.Close() // } @@ -60,13 +61,15 @@ func ExampleRunDatastoreContainer() { } _, err = dsClient.Put(ctx, k, &data) if err != nil { - log.Fatalf("failed to put data: %v", err) + log.Printf("failed to put data: %v", err) + return } saved := Task{} err = dsClient.Get(ctx, k, &saved) if err != nil { - log.Fatalf("failed to get data: %v", err) + log.Printf("failed to get data: %v", err) + return } fmt.Println(saved.Description) diff --git a/modules/gcloud/firestore.go b/modules/gcloud/firestore.go index 7f9ced72f7..297b47f80c 100644 --- a/modules/gcloud/firestore.go +++ b/modules/gcloud/firestore.go @@ -2,7 +2,6 @@ package gcloud import ( "context" - "fmt" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" @@ -33,13 +32,8 @@ func RunFirestore(ctx context.Context, img string, opts ...testcontainers.Contai req.Cmd = []string{ "/bin/sh", "-c", - "gcloud beta emulators firestore start --host-port 0.0.0.0:8080 " + fmt.Sprintf("--project=%s", settings.ProjectID), + "gcloud beta emulators firestore start --host-port 0.0.0.0:8080 --project=" + settings.ProjectID, } - container, err := testcontainers.GenericContainer(ctx, req) - if err != nil { - return nil, err - } - - return newGCloudContainer(ctx, 8080, container, settings) + return newGCloudContainer(ctx, req, 8080, settings, "") } diff --git a/modules/gcloud/firestore_test.go b/modules/gcloud/firestore_test.go index 54e03e4522..83ccd0464c 100644 --- a/modules/gcloud/firestore_test.go +++ b/modules/gcloud/firestore_test.go @@ -10,6 +10,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/gcloud" ) @@ -32,16 +33,15 @@ func ExampleRunFirestoreContainer() { "gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators", gcloud.WithProjectID("firestore-project"), ) - if err != nil { - log.Fatalf("failed to run container: %v", err) - } - - // Clean up the container defer func() { - if err := firestoreContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %v", err) + if err := testcontainers.TerminateContainer(firestoreContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to run container: %v", err) + return + } // } // firestoreClient { @@ -49,13 +49,15 @@ func ExampleRunFirestoreContainer() { conn, err := grpc.NewClient(firestoreContainer.URI, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithPerRPCCredentials(emulatorCreds{})) if err != nil { - log.Fatalf("failed to dial: %v", err) // nolint:gocritic + log.Printf("failed to dial: %v", err) + return } options := []option.ClientOption{option.WithGRPCConn(conn)} client, err := firestore.NewClient(ctx, projectID, options...) if err != nil { - log.Fatalf("failed to create client: %v", err) + log.Printf("failed to create client: %v", err) + return } defer client.Close() // } @@ -74,17 +76,20 @@ func ExampleRunFirestoreContainer() { } _, err = docRef.Create(ctx, data) if err != nil { - log.Fatalf("failed to create document: %v", err) + log.Printf("failed to create document: %v", err) + return } docsnap, err := docRef.Get(ctx) if err != nil { - log.Fatalf("failed to get document: %v", err) + log.Printf("failed to get document: %v", err) + return } var saved Person if err := docsnap.DataTo(&saved); err != nil { - log.Fatalf("failed to convert data: %v", err) + log.Printf("failed to convert data: %v", err) + return } fmt.Println(saved.Firstname, saved.Lastname) diff --git a/modules/gcloud/gcloud.go b/modules/gcloud/gcloud.go index a5886dc743..7f0e7cdffb 100644 --- a/modules/gcloud/gcloud.go +++ b/modules/gcloud/gcloud.go @@ -18,26 +18,29 @@ type GCloudContainer struct { } // newGCloudContainer creates a new GCloud container, obtaining the URL to access the container from the specified port. -func newGCloudContainer(ctx context.Context, port int, c testcontainers.Container, settings options) (*GCloudContainer, error) { +func newGCloudContainer(ctx context.Context, req testcontainers.GenericContainerRequest, port int, settings options, urlPrefix string) (*GCloudContainer, error) { + container, err := testcontainers.GenericContainer(ctx, req) + var c *GCloudContainer + if container != nil { + c = &GCloudContainer{Container: container, Settings: settings} + } + if err != nil { + return c, fmt.Errorf("generic container: %w", err) + } + mappedPort, err := c.MappedPort(ctx, nat.Port(fmt.Sprintf("%d/tcp", port))) if err != nil { - return nil, err + return c, fmt.Errorf("mapped port: %w", err) } hostIP, err := c.Host(ctx) if err != nil { - return nil, err + return c, fmt.Errorf("host: %w", err) } - uri := fmt.Sprintf("%s:%s", hostIP, mappedPort.Port()) - - gCloudContainer := &GCloudContainer{ - Container: c, - Settings: settings, - URI: uri, - } + c.URI = urlPrefix + hostIP + ":" + mappedPort.Port() - return gCloudContainer, nil + return c, nil } type options struct { diff --git a/modules/gcloud/go.mod b/modules/gcloud/go.mod index 00a723f58c..2aac027255 100644 --- a/modules/gcloud/go.mod +++ b/modules/gcloud/go.mod @@ -33,6 +33,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect @@ -68,10 +69,12 @@ require ( github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/stretchr/testify v1.9.0 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect @@ -97,6 +100,7 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/gcloud/go.sum b/modules/gcloud/go.sum index 07f1f7f404..7283a49502 100644 --- a/modules/gcloud/go.sum +++ b/modules/gcloud/go.sum @@ -146,6 +146,10 @@ github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -180,6 +184,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -362,6 +368,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/gcloud/pubsub.go b/modules/gcloud/pubsub.go index a2a4e74a1c..d57ea35c16 100644 --- a/modules/gcloud/pubsub.go +++ b/modules/gcloud/pubsub.go @@ -2,7 +2,6 @@ package gcloud import ( "context" - "fmt" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" @@ -33,13 +32,8 @@ func RunPubsub(ctx context.Context, img string, opts ...testcontainers.Container req.Cmd = []string{ "/bin/sh", "-c", - "gcloud beta emulators pubsub start --host-port 0.0.0.0:8085 " + fmt.Sprintf("--project=%s", settings.ProjectID), + "gcloud beta emulators pubsub start --host-port 0.0.0.0:8085 --project=" + settings.ProjectID, } - container, err := testcontainers.GenericContainer(ctx, req) - if err != nil { - return nil, err - } - - return newGCloudContainer(ctx, 8085, container, settings) + return newGCloudContainer(ctx, req, 8085, settings, "") } diff --git a/modules/gcloud/pubsub_test.go b/modules/gcloud/pubsub_test.go index e0718a4d03..151df3a546 100644 --- a/modules/gcloud/pubsub_test.go +++ b/modules/gcloud/pubsub_test.go @@ -10,6 +10,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/gcloud" ) @@ -22,16 +23,15 @@ func ExampleRunPubsubContainer() { "gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators", gcloud.WithProjectID("pubsub-project"), ) - if err != nil { - log.Fatalf("failed to run container: %v", err) - } - - // Clean up the container defer func() { - if err := pubsubContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %v", err) + if err := testcontainers.TerminateContainer(pubsubContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to run container: %v", err) + return + } // } // pubsubClient { @@ -39,30 +39,35 @@ func ExampleRunPubsubContainer() { conn, err := grpc.NewClient(pubsubContainer.URI, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { - log.Fatalf("failed to dial: %v", err) // nolint:gocritic + log.Printf("failed to dial: %v", err) + return } options := []option.ClientOption{option.WithGRPCConn(conn)} client, err := pubsub.NewClient(ctx, projectID, options...) if err != nil { - log.Fatalf("failed to create client: %v", err) + log.Printf("failed to create client: %v", err) + return } defer client.Close() // } topic, err := client.CreateTopic(ctx, "greetings") if err != nil { - log.Fatalf("failed to create topic: %v", err) + log.Printf("failed to create topic: %v", err) + return } subscription, err := client.CreateSubscription(ctx, "subscription", pubsub.SubscriptionConfig{Topic: topic}) if err != nil { - log.Fatalf("failed to create subscription: %v", err) + log.Printf("failed to create subscription: %v", err) + return } result := topic.Publish(ctx, &pubsub.Message{Data: []byte("Hello World")}) _, err = result.Get(ctx) if err != nil { - log.Fatalf("failed to publish message: %v", err) + log.Printf("failed to publish message: %v", err) + return } var data []byte @@ -73,7 +78,8 @@ func ExampleRunPubsubContainer() { defer cancel() }) if err != nil { - log.Fatalf("failed to receive message: %v", err) + log.Printf("failed to receive message: %v", err) + return } fmt.Println(string(data)) diff --git a/modules/gcloud/spanner.go b/modules/gcloud/spanner.go index d57154ab1d..8b306db4ce 100644 --- a/modules/gcloud/spanner.go +++ b/modules/gcloud/spanner.go @@ -29,10 +29,5 @@ func RunSpanner(ctx context.Context, img string, opts ...testcontainers.Containe return nil, err } - container, err := testcontainers.GenericContainer(ctx, req) - if err != nil { - return nil, err - } - - return newGCloudContainer(ctx, 9010, container, settings) + return newGCloudContainer(ctx, req, 9010, settings, "") } diff --git a/modules/gcloud/spanner_test.go b/modules/gcloud/spanner_test.go index 10fdec441f..0e976c3dff 100644 --- a/modules/gcloud/spanner_test.go +++ b/modules/gcloud/spanner_test.go @@ -15,6 +15,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/gcloud" ) @@ -27,16 +28,15 @@ func ExampleRunSpannerContainer() { "gcr.io/cloud-spanner-emulator/emulator:1.4.0", gcloud.WithProjectID("spanner-project"), ) - if err != nil { - log.Fatalf("failed to run container: %v", err) - } - - // Clean up the container defer func() { - if err := spannerContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %v", err) + if err := testcontainers.TerminateContainer(spannerContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to run container: %v", err) + return + } // } // spannerAdminClient { @@ -56,7 +56,8 @@ func ExampleRunSpannerContainer() { instanceAdmin, err := instance.NewInstanceAdminClient(ctx, options...) if err != nil { - log.Fatalf("failed to create instance admin client: %v", err) // nolint:gocritic + log.Printf("failed to create instance admin client: %v", err) + return } defer instanceAdmin.Close() // } @@ -69,18 +70,21 @@ func ExampleRunSpannerContainer() { }, }) if err != nil { - log.Fatalf("failed to create instance: %v", err) + log.Printf("failed to create instance: %v", err) + return } _, err = instanceOp.Wait(ctx) if err != nil { - log.Fatalf("failed to wait for instance creation: %v", err) + log.Printf("failed to wait for instance creation: %v", err) + return } // spannerDBAdminClient { c, err := database.NewDatabaseAdminClient(ctx, options...) if err != nil { - log.Fatalf("failed to create admin client: %v", err) + log.Printf("failed to create admin client: %v", err) + return } defer c.Close() // } @@ -93,17 +97,20 @@ func ExampleRunSpannerContainer() { }, }) if err != nil { - log.Fatalf("failed to create database: %v", err) + log.Printf("failed to create database: %v", err) + return } _, err = databaseOp.Wait(ctx) if err != nil { - log.Fatalf("failed to wait for database creation: %v", err) + log.Printf("failed to wait for database creation: %v", err) + return } db := fmt.Sprintf("projects/%s/instances/%s/databases/%s", projectId, instanceId, databaseName) client, err := spanner.NewClient(ctx, db, options...) if err != nil { - log.Fatalf("failed to create client: %v", err) + log.Printf("failed to create client: %v", err) + return } defer client.Close() @@ -113,18 +120,21 @@ func ExampleRunSpannerContainer() { []interface{}{"Go", "Gopher"}), }) if err != nil { - log.Fatalf("failed to apply mutation: %v", err) + log.Printf("failed to apply mutation: %v", err) + return } row, err := client.Single().ReadRow(ctx, "Languages", spanner.Key{"Go"}, []string{"mascot"}) if err != nil { - log.Fatalf("failed to read row: %v", err) + log.Printf("failed to read row: %v", err) + return } var mascot string err = row.ColumnByName("Mascot", &mascot) if err != nil { - log.Fatalf("failed to read column: %v", err) + log.Printf("failed to read column: %v", err) + return } fmt.Println(mascot) diff --git a/modules/grafana-lgtm/examples_test.go b/modules/grafana-lgtm/examples_test.go index c13f1bbd62..a31a6b873f 100644 --- a/modules/grafana-lgtm/examples_test.go +++ b/modules/grafana-lgtm/examples_test.go @@ -4,10 +4,9 @@ import ( "context" "errors" "fmt" - golog "log" + "log" "log/slog" "math/rand" - "sync" "time" "go.opentelemetry.io/contrib/bridges/otelslog" @@ -22,10 +21,12 @@ import ( "go.opentelemetry.io/otel/log/global" metricsapi "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/propagation" - "go.opentelemetry.io/otel/sdk/log" + otellog "go.opentelemetry.io/otel/sdk/log" "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/trace" + "golang.org/x/sync/errgroup" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/grafanalgtm" ) @@ -34,21 +35,21 @@ func ExampleRun() { ctx := context.Background() grafanaLgtmContainer, err := grafanalgtm.Run(ctx, "grafana/otel-lgtm:0.6.0") - if err != nil { - golog.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := grafanaLgtmContainer.Terminate(ctx); err != nil { - golog.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(grafanaLgtmContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := grafanaLgtmContainer.State(ctx) if err != nil { - golog.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -61,66 +62,72 @@ func ExampleRun_otelCollector() { ctx := context.Background() ctr, err := grafanalgtm.Run(ctx, "grafana/otel-lgtm:0.6.0", grafanalgtm.WithAdminCredentials("admin", "123456789")) - if err != nil { - golog.Fatalf("failed to start Grafana LGTM container: %s", err) - } defer func() { - if err := ctr.Terminate(ctx); err != nil { - golog.Fatalf("failed to terminate Grafana LGTM container: %s", err) + if err := testcontainers.TerminateContainer(ctr); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start Grafana LGTM container: %s", err) + return + } // Set up OpenTelemetry. otelShutdown, err := setupOTelSDK(ctx, ctr) if err != nil { + log.Printf("failed to set up OpenTelemetry: %s", err) return } // Handle shutdown properly so nothing leaks. defer func() { - err = errors.Join(err, otelShutdown(context.Background())) + if err := otelShutdown(context.Background()); err != nil { + log.Printf("failed to shutdown OpenTelemetry: %s", err) + } }() // roll dice 10000 times, concurrently max := 10_000 - wg := sync.WaitGroup{} + var wg errgroup.Group for i := 0; i < max; i++ { - wg.Add(1) - - go func() { - defer wg.Done() - rolldice(ctx) - }() + wg.Go(func() error { + return rolldice(ctx) + }) } - wg.Wait() + if err = wg.Wait(); err != nil { + log.Printf("failed to roll dice: %s", err) + return + } // Output: - // shutdown errors: } // setupOTelSDK bootstraps the OpenTelemetry pipeline. // If it does not return an error, make sure to call shutdown for proper cleanup. -func setupOTelSDK(ctx context.Context, ctr *grafanalgtm.GrafanaLGTMContainer) (shutdown func(context.Context) error, err error) { // nolint:nonamedreturns // this is a pattern in the OpenTelemetry Go SDK +func setupOTelSDK(ctx context.Context, ctr *grafanalgtm.GrafanaLGTMContainer) (shutdown func(context.Context) error, err error) { //nolint:nonamedreturns // this is a pattern in the OpenTelemetry Go SDK var shutdownFuncs []func(context.Context) error // shutdown calls cleanup functions registered via shutdownFuncs. // The errors from the calls are joined. // Each registered cleanup will be invoked once. shutdown = func(ctx context.Context) error { - var err error + var errs []error for _, fn := range shutdownFuncs { - err = errors.Join(err, fn(ctx)) + if err := fn(ctx); err != nil { + errs = append(errs, err) + } } - shutdownFuncs = nil - fmt.Println("shutdown errors:", err) - return err - } - // handleErr calls shutdown for cleanup and makes sure that all errors are returned. - handleErr := func(inErr error) { - err = errors.Join(inErr, shutdown(ctx)) + return errors.Join(errs...) } + // Ensure that the OpenTelemetry SDK is properly shutdown. + defer func() { + if err != nil { + err = errors.Join(shutdown(ctx)) + } + }() + prop := propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{}, @@ -139,13 +146,12 @@ func setupOTelSDK(ctx context.Context, ctr *grafanalgtm.GrafanaLGTMContainer) (s ), ) if err != nil { - return nil, err + return nil, fmt.Errorf("new trace exporter: %w", err) } tracerProvider := trace.NewTracerProvider(trace.WithBatcher(traceExporter)) if err != nil { - handleErr(err) - return + return nil, fmt.Errorf("new trace provider: %w", err) } shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) otel.SetTracerProvider(tracerProvider) @@ -155,7 +161,7 @@ func setupOTelSDK(ctx context.Context, ctr *grafanalgtm.GrafanaLGTMContainer) (s otlpmetrichttp.WithEndpoint(otlpHttpEndpoint), ) if err != nil { - return nil, err + return nil, fmt.Errorf("new metric exporter: %w", err) } // The exporter embeds a default OpenTelemetry Reader and @@ -163,7 +169,7 @@ func setupOTelSDK(ctx context.Context, ctr *grafanalgtm.GrafanaLGTMContainer) (s // both a Reader and Collector. prometheusExporter, err := prometheus.New() if err != nil { - return nil, err + return nil, fmt.Errorf("new prometheus exporter: %w", err) } meterProvider := metric.NewMeterProvider( @@ -171,9 +177,9 @@ func setupOTelSDK(ctx context.Context, ctr *grafanalgtm.GrafanaLGTMContainer) (s metric.WithReader(prometheusExporter), ) if err != nil { - handleErr(err) - return + return nil, fmt.Errorf("new meter provider: %w", err) } + shutdownFuncs = append(shutdownFuncs, meterProvider.Shutdown) otel.SetMeterProvider(meterProvider) @@ -182,23 +188,22 @@ func setupOTelSDK(ctx context.Context, ctr *grafanalgtm.GrafanaLGTMContainer) (s otlploghttp.WithEndpoint(otlpHttpEndpoint), ) if err != nil { - return nil, err + return nil, fmt.Errorf("new log exporter: %w", err) } - loggerProvider := log.NewLoggerProvider(log.WithProcessor(log.NewBatchProcessor(logExporter))) + loggerProvider := otellog.NewLoggerProvider(otellog.WithProcessor(otellog.NewBatchProcessor(logExporter))) if err != nil { - handleErr(err) - return + return nil, fmt.Errorf("new logger provider: %w", err) } + shutdownFuncs = append(shutdownFuncs, loggerProvider.Shutdown) global.SetLoggerProvider(loggerProvider) - err = runtime.Start(runtime.WithMinimumReadMemStatsInterval(time.Second)) - if err != nil { - logger.ErrorContext(ctx, "otel runtime instrumentation failed:", err) // nolint:all // this is a pattern in the OpenTelemetry Go SDK + if err = runtime.Start(runtime.WithMinimumReadMemStatsInterval(time.Second)); err != nil { + return nil, fmt.Errorf("start runtime instrumentation: %w", err) } - return + return shutdown, nil } // rollDiceApp { @@ -210,7 +215,7 @@ var ( meter = otel.Meter(schemaName) ) -func rolldice(ctx context.Context) { +func rolldice(ctx context.Context) error { ctx, span := tracer.Start(ctx, "roll") defer span.End() @@ -225,9 +230,11 @@ func rolldice(ctx context.Context) { // This is the equivalent of prometheus.NewCounterVec counter, err := meter.Int64Counter("rolldice-counter", metricsapi.WithDescription("a 20-sided dice")) if err != nil { - golog.Fatal(err) + return fmt.Errorf("roll dice: %w", err) } counter.Add(ctx, int64(roll), opt) + + return nil } // } diff --git a/modules/grafana-lgtm/go.mod b/modules/grafana-lgtm/go.mod index 73a94c714b..26c4b8c34d 100644 --- a/modules/grafana-lgtm/go.mod +++ b/modules/grafana-lgtm/go.mod @@ -4,6 +4,7 @@ go 1.22 require ( github.com/docker/go-connections v0.5.0 + github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.33.0 go.opentelemetry.io/contrib/bridges/otelslog v0.3.0 go.opentelemetry.io/contrib/instrumentation/runtime v0.53.0 @@ -18,6 +19,7 @@ require ( go.opentelemetry.io/otel/sdk v1.28.0 go.opentelemetry.io/otel/sdk/log v0.4.0 go.opentelemetry.io/otel/sdk/metric v1.28.0 + golang.org/x/sync v0.7.0 ) require ( @@ -31,6 +33,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect @@ -54,6 +57,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_golang v1.19.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect @@ -76,6 +80,7 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/grpc v1.64.1 // indirect google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/grafana-lgtm/go.sum b/modules/grafana-lgtm/go.sum index 1eced8de79..d80ed84f72 100644 --- a/modules/grafana-lgtm/go.sum +++ b/modules/grafana-lgtm/go.sum @@ -56,6 +56,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -92,6 +96,8 @@ github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -167,6 +173,8 @@ golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= 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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -204,6 +212,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/grafana-lgtm/grafana.go b/modules/grafana-lgtm/grafana.go index 1e2f33adba..3cee949938 100644 --- a/modules/grafana-lgtm/grafana.go +++ b/modules/grafana-lgtm/grafana.go @@ -45,7 +45,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom container, err := testcontainers.GenericContainer(ctx, genericContainerReq) if err != nil { - return nil, err + return nil, fmt.Errorf("generic container: %w", err) } c := &GrafanaLGTMContainer{Container: container} @@ -53,7 +53,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom url, err := c.OtlpHttpEndpoint(ctx) if err != nil { // return the container instance to allow the caller to clean up - return c, err + return c, fmt.Errorf("otlp http endpoint: %w", err) } testcontainers.Logger.Printf("Access to the Grafana dashboard: %s", url) diff --git a/modules/grafana-lgtm/grafana_test.go b/modules/grafana-lgtm/grafana_test.go index b0a4960616..c6c6d9f0d8 100644 --- a/modules/grafana-lgtm/grafana_test.go +++ b/modules/grafana-lgtm/grafana_test.go @@ -8,6 +8,9 @@ import ( "net/url" "testing" + "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/grafanalgtm" ) @@ -15,24 +18,14 @@ func TestGrafanaLGTM(t *testing.T) { ctx := context.Background() grafanaLgtmContainer, err := grafanalgtm.Run(ctx, "grafana/otel-lgtm:0.6.0") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := grafanaLgtmContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, grafanaLgtmContainer) + require.NoError(t, err) // perform assertions t.Run("container is running with right version", func(t *testing.T) { healthURL, err := url.Parse(fmt.Sprintf("http://%s/api/health", grafanaLgtmContainer.MustHttpEndpoint(ctx))) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) httpReq := http.Request{ Method: http.MethodGet, @@ -42,23 +35,15 @@ func TestGrafanaLGTM(t *testing.T) { httpClient := http.Client{} httpResp, err := httpClient.Do(&httpReq) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + defer httpResp.Body.Close() - if httpResp.StatusCode != http.StatusOK { - t.Fatalf("expected status code %d, got %d", http.StatusOK, httpResp.StatusCode) - } + require.Equal(t, http.StatusOK, httpResp.StatusCode) body := make(map[string]interface{}) err = json.NewDecoder(httpResp.Body).Decode(&body) - if err != nil { - t.Fatal(err) - } - - if body["version"] != "11.0.0" { - t.Fatalf("expected version %q, got %q", "11.0.0", body["version"]) - } + require.NoError(t, err) + require.Equal(t, "11.0.0", body["version"]) }) } diff --git a/modules/inbucket/examples_test.go b/modules/inbucket/examples_test.go index 7680a9563a..c10f8b5b58 100644 --- a/modules/inbucket/examples_test.go +++ b/modules/inbucket/examples_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/inbucket" ) @@ -13,21 +14,21 @@ func ExampleRun() { ctx := context.Background() inbucketContainer, err := inbucket.Run(ctx, "inbucket/inbucket:sha-2d409bb") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := inbucketContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(inbucketContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := inbucketContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/inbucket/inbucket.go b/modules/inbucket/inbucket.go index beae784557..565bc4253e 100644 --- a/modules/inbucket/inbucket.go +++ b/modules/inbucket/inbucket.go @@ -77,9 +77,14 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *InbucketContainer + if container != nil { + c = &InbucketContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &InbucketContainer{Container: container}, nil + return c, nil } diff --git a/modules/inbucket/inbucket_test.go b/modules/inbucket/inbucket_test.go index eb6dc3c493..1cb53cedd7 100644 --- a/modules/inbucket/inbucket_test.go +++ b/modules/inbucket/inbucket_test.go @@ -7,27 +7,24 @@ import ( "github.com/inbucket/inbucket/pkg/rest/client" "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go" ) func TestInbucket(t *testing.T) { ctx := context.Background() - container, err := Run(ctx, "inbucket/inbucket:sha-2d409bb") + ctr, err := Run(ctx, "inbucket/inbucket:sha-2d409bb") + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - // Clean up the container after the test is complete - t.Cleanup(func() { - err := container.Terminate(ctx) - require.NoError(t, err) - }) - // smtpConnection { - smtpUrl, err := container.SmtpConnection(ctx) + smtpUrl, err := ctr.SmtpConnection(ctx) // } require.NoError(t, err) // webInterface { - webInterfaceUrl, err := container.WebInterface(ctx) + webInterfaceUrl, err := ctr.WebInterface(ctx) // } require.NoError(t, err) restClient, err := client.New(webInterfaceUrl) diff --git a/modules/influxdb/examples_test.go b/modules/influxdb/examples_test.go index 2d37117993..30c892537f 100644 --- a/modules/influxdb/examples_test.go +++ b/modules/influxdb/examples_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/influxdb" ) @@ -18,21 +19,21 @@ func ExampleRun() { influxdb.WithUsername("root"), influxdb.WithPassword("password"), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := influxdbContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(influxdbContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := influxdbContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/influxdb/influxdb.go b/modules/influxdb/influxdb.go index d359c8cbbc..609b11467b 100644 --- a/modules/influxdb/influxdb.go +++ b/modules/influxdb/influxdb.go @@ -80,11 +80,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *InfluxDbContainer + if container != nil { + c = &InfluxDbContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &InfluxDbContainer{container}, nil + return c, nil } func (c *InfluxDbContainer) MustConnectionUrl(ctx context.Context) string { diff --git a/modules/influxdb/influxdb_test.go b/modules/influxdb/influxdb_test.go index 6ec5ec7399..e04a800dc6 100644 --- a/modules/influxdb/influxdb_test.go +++ b/modules/influxdb/influxdb_test.go @@ -15,18 +15,11 @@ import ( "github.com/testcontainers/testcontainers-go/modules/influxdb" ) -func containerCleanup(t *testing.T, container testcontainers.Container) { - err := container.Terminate(context.Background()) - require.NoError(t, err, "failed to terminate container") -} - func TestV1Container(t *testing.T) { ctx := context.Background() influxDbContainer, err := influxdb.Run(ctx, "influxdb:1.8.10") + testcontainers.CleanupContainer(t, influxDbContainer) require.NoError(t, err) - t.Cleanup(func() { - containerCleanup(t, influxDbContainer) - }) state, err := influxDbContainer.State(ctx) require.NoError(t, err) @@ -44,10 +37,8 @@ func TestV2Container(t *testing.T) { influxdb.WithUsername("root"), influxdb.WithPassword("password"), ) + testcontainers.CleanupContainer(t, influxDbContainer) require.NoError(t, err) - t.Cleanup(func() { - containerCleanup(t, influxDbContainer) - }) state, err := influxDbContainer.State(ctx) require.NoError(t, err) @@ -63,10 +54,8 @@ func TestWithInitDb(t *testing.T) { "influxdb:1.8.10", influxdb.WithInitDb("testdata"), ) + testcontainers.CleanupContainer(t, influxDbContainer) require.NoError(t, err) - t.Cleanup(func() { - containerCleanup(t, influxDbContainer) - }) if state, err := influxDbContainer.State(ctx); err != nil || !state.Running { require.NoError(t, err) @@ -99,10 +88,8 @@ func TestWithConfigFile(t *testing.T) { "influxdb:"+influxVersion, influxdb.WithConfigFile(filepath.Join("testdata", "influxdb.conf")), ) + testcontainers.CleanupContainer(t, influxDbContainer) require.NoError(t, err) - t.Cleanup(func() { - containerCleanup(t, influxDbContainer) - }) if state, err := influxDbContainer.State(context.Background()); err != nil || !state.Running { require.NoError(t, err) diff --git a/modules/k3s/go.mod b/modules/k3s/go.mod index da3a23fd92..724d10e24a 100644 --- a/modules/k3s/go.mod +++ b/modules/k3s/go.mod @@ -5,7 +5,8 @@ go 1.22 require ( github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.29.2 k8s.io/apimachinery v0.29.2 @@ -56,6 +57,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect diff --git a/modules/k3s/k3s.go b/modules/k3s/k3s.go index f6cfb055c4..509719bd64 100644 --- a/modules/k3s/k3s.go +++ b/modules/k3s/k3s.go @@ -98,11 +98,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *K3sContainer + if container != nil { + c = &K3sContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &K3sContainer{Container: container}, nil + return c, nil } func getContainerHost(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (string, error) { diff --git a/modules/k3s/k3s_example_test.go b/modules/k3s/k3s_example_test.go index eef8f87280..ef2ca36538 100644 --- a/modules/k3s/k3s_example_test.go +++ b/modules/k3s/k3s_example_test.go @@ -9,6 +9,7 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/k3s" ) @@ -17,43 +18,47 @@ func ExampleRun() { ctx := context.Background() k3sContainer, err := k3s.Run(ctx, "docker.io/rancher/k3s:v1.27.1-k3s1") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := k3sContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(k3sContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := k3sContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) kubeConfigYaml, err := k3sContainer.GetKubeConfig(ctx) if err != nil { - log.Fatalf("failed to get kubeconfig: %s", err) + log.Printf("failed to get kubeconfig: %s", err) + return } restcfg, err := clientcmd.RESTConfigFromKubeConfig(kubeConfigYaml) if err != nil { - log.Fatalf("failed to create rest config: %s", err) + log.Printf("failed to create rest config: %s", err) + return } k8s, err := kubernetes.NewForConfig(restcfg) if err != nil { - log.Fatalf("failed to create k8s client: %s", err) + log.Printf("failed to create k8s client: %s", err) + return } nodes, err := k8s.CoreV1().Nodes().List(ctx, v1.ListOptions{}) if err != nil { - log.Fatalf("failed to list nodes: %s", err) + log.Printf("failed to list nodes: %s", err) + return } fmt.Println(len(nodes.Items)) diff --git a/modules/k3s/k3s_test.go b/modules/k3s/k3s_test.go index 7a5fe0d94b..f3970a25da 100644 --- a/modules/k3s/k3s_test.go +++ b/modules/k3s/k3s_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kwait "k8s.io/apimachinery/pkg/util/wait" @@ -23,55 +24,33 @@ func Test_LoadImages(t *testing.T) { defer cancel() k3sContainer, err := k3s.Run(ctx, "docker.io/rancher/k3s:v1.27.1-k3s1") - if err != nil { - t.Fatal(err) - } - - // Clean up the container - defer func() { - if err := k3sContainer.Terminate(ctx); err != nil { - t.Fatal(err) - } - }() + testcontainers.CleanupContainer(t, k3sContainer) + require.NoError(t, err) kubeConfigYaml, err := k3sContainer.GetKubeConfig(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) restcfg, err := clientcmd.RESTConfigFromKubeConfig(kubeConfigYaml) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) k8s, err := kubernetes.NewForConfig(restcfg) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) provider, err := testcontainers.ProviderDocker.GetProvider() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // ensure nginx image is available locally err = provider.PullImage(ctx, "nginx") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) t.Run("Test load image not available", func(t *testing.T) { err := k3sContainer.LoadImages(ctx, "fake.registry/fake:non-existing") - if err == nil { - t.Fatal("should had failed") - } + require.Error(t, err) }) t.Run("Test load image in cluster", func(t *testing.T) { err := k3sContainer.LoadImages(ctx, "nginx") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) pod := &corev1.Pod{ TypeMeta: metav1.TypeMeta{ @@ -93,9 +72,7 @@ func Test_LoadImages(t *testing.T) { } _, err = k8s.CoreV1().Pods("default").Create(ctx, pod, metav1.CreateOptions{}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) err = kwait.PollUntilContextCancel(ctx, time.Second, true, func(ctx context.Context) (bool, error) { state, err := getTestPodState(ctx, k8s) @@ -107,17 +84,11 @@ func Test_LoadImages(t *testing.T) { } return state.Running != nil, nil }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) state, err := getTestPodState(ctx, k8s) - if err != nil { - t.Fatal(err) - } - if state.Running == nil { - t.Fatalf("Unexpected status %v", state) - } + require.NoError(t, err) + require.NotNil(t, state.Running) }) } @@ -135,31 +106,17 @@ func Test_APIServerReady(t *testing.T) { ctx := context.Background() k3sContainer, err := k3s.Run(ctx, "docker.io/rancher/k3s:v1.27.1-k3s1") - if err != nil { - t.Fatal(err) - } - - // Clean up the container - defer func() { - if err := k3sContainer.Terminate(ctx); err != nil { - t.Fatal(err) - } - }() + testcontainers.CleanupContainer(t, k3sContainer) + require.NoError(t, err) kubeConfigYaml, err := k3sContainer.GetKubeConfig(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) restcfg, err := clientcmd.RESTConfigFromKubeConfig(kubeConfigYaml) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) k8s, err := kubernetes.NewForConfig(restcfg) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) pod := &corev1.Pod{ TypeMeta: metav1.TypeMeta{ @@ -180,9 +137,7 @@ func Test_APIServerReady(t *testing.T) { } _, err = k8s.CoreV1().Pods("default").Create(context.Background(), pod, metav1.CreateOptions{}) - if err != nil { - t.Fatalf("failed to create pod %v", err) - } + require.NoError(t, err) } func Test_WithManifestOption(t *testing.T) { @@ -193,14 +148,6 @@ func Test_WithManifestOption(t *testing.T) { k3s.WithManifest("nginx-manifest.yaml"), testcontainers.WithWaitStrategy(wait.ForExec([]string{"kubectl", "wait", "pod", "nginx", "--for=condition=Ready"})), ) - if err != nil { - t.Fatal(err) - } - - // Clean up the container - defer func() { - if err := k3sContainer.Terminate(ctx); err != nil { - t.Fatal(err) - } - }() + testcontainers.CleanupContainer(t, k3sContainer) + require.NoError(t, err) } diff --git a/modules/k6/examples_test.go b/modules/k6/examples_test.go index 468d113450..c842814d4c 100644 --- a/modules/k6/examples_test.go +++ b/modules/k6/examples_test.go @@ -29,27 +29,29 @@ func ExampleRun() { Started: true, } httpbin, err := testcontainers.GenericContainer(ctx, gcr) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := httpbin.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(httpbin); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } // getHTTPBinIP { httpbinIP, err := httpbin.ContainerIP(ctx) if err != nil { - log.Fatalf("failed to get container IP: %s", err) // nolint:gocritic + log.Printf("failed to get container IP: %s", err) + return } // } absPath, err := filepath.Abs(filepath.Join("scripts", "httpbin.js")) if err != nil { - log.Fatalf("failed to get absolute path to test script: %s", err) + log.Printf("failed to get absolute path to test script: %s", err) + return } // runK6Container { @@ -61,21 +63,32 @@ func ExampleRun() { k6.WithTestScript(absPath), k6.SetEnvVar("HTTPBIN", httpbinIP), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := k6.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + cacheMount, err := k6.CacheMount(ctx) + if err != nil { + log.Printf("failed to determine cache mount: %s", err) + } + + var options []testcontainers.TerminateOption + if cacheMount != "" { + options = append(options, testcontainers.RemoveVolumes(cacheMount)) + } + + if err = testcontainers.TerminateContainer(k6, options...); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } //} // assert the result of the test state, err := k6.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.ExitCode) diff --git a/modules/k6/go.mod b/modules/k6/go.mod index 58f96d04aa..4dcd9395d9 100644 --- a/modules/k6/go.mod +++ b/modules/k6/go.mod @@ -4,7 +4,8 @@ go 1.22 require ( github.com/docker/docker v27.1.1+incompatible - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -16,6 +17,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect @@ -26,6 +28,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -37,6 +40,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -53,6 +57,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/k6/go.sum b/modules/k6/go.sum index ed514ea5ef..28367d0020 100644 --- a/modules/k6/go.sum +++ b/modules/k6/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -52,6 +53,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -78,6 +83,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -174,6 +181,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/k6/k6.go b/modules/k6/k6.go index 591cd48f0c..ea99db3a88 100644 --- a/modules/k6/k6.go +++ b/modules/k6/k6.go @@ -17,6 +17,9 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) +// cacheTarget is the path to the cache volume in the container. +const cacheTarget = "/cache" + // K6Container represents the K6 container type used in the module type K6Container struct { testcontainers.Container @@ -152,7 +155,7 @@ func WithCache() testcontainers.CustomizeRequestOption { Name: cacheVol, VolumeOptions: volOptions, }, - Target: "/cache", + Target: cacheTarget, } req.Mounts = append(req.Mounts, mount) @@ -186,9 +189,31 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *K6Container + if container != nil { + c = &K6Container{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) + } + + return c, nil +} + +// CacheMount returns the name of volume used as a cache or an empty string +// if no cache was found. +func (k *K6Container) CacheMount(ctx context.Context) (string, error) { + inspect, err := k.Inspect(ctx) + if err != nil { + return "", fmt.Errorf("inspect: %w", err) + } + + for _, m := range inspect.Mounts { + if m.Type == mount.TypeVolume && m.Destination == cacheTarget { + return m.Name, nil + } } - return &K6Container{Container: container}, nil + return "", nil } diff --git a/modules/k6/k6_test.go b/modules/k6/k6_test.go index ead72dcac4..f2cc39ef72 100644 --- a/modules/k6/k6_test.go +++ b/modules/k6/k6_test.go @@ -7,6 +7,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/k6" ) @@ -39,8 +41,22 @@ func TestK6(t *testing.T) { }, } + var cacheMount string + t.Cleanup(func() { + if cacheMount == "" { + return + } + + // Ensure the cache volume is removed as mounts that specify a volume + // source as defined by the name are not removed automatically. + provider, err := testcontainers.NewDockerProvider() + require.NoError(t, err) + defer provider.Close() + + require.NoError(t, provider.Client().VolumeRemove(context.Background(), cacheMount, true)) + }) + for _, tc := range testCases { - tc := tc t.Run(tc.title, func(t *testing.T) { ctx := context.Background() @@ -62,25 +78,19 @@ func TestK6(t *testing.T) { options = k6.WithRemoteTestScript(desc) } - container, err := k6.Run(ctx, "szkiba/k6x:v0.3.1", k6.WithCache(), options) - if err != nil { - t.Fatal(err) + ctr, err := k6.Run(ctx, "szkiba/k6x:v0.3.1", k6.WithCache(), options) + if ctr != nil && cacheMount == "" { + // First container, determine the cache mount. + cacheMount, err = ctr.CacheMount(ctx) + require.NoError(t, err) } - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // assert the result of the test - state, err := container.State(ctx) - if err != nil { - t.Fatal(err) - } - if state.ExitCode != tc.expect { - t.Fatalf("expected %d got %d", tc.expect, state.ExitCode) - } + state, err := ctr.State(ctx) + require.NoError(t, err) + require.Equal(t, tc.expect, state.ExitCode) }) } } diff --git a/modules/kafka/examples_test.go b/modules/kafka/examples_test.go index 2b547970fc..c275924ecc 100644 --- a/modules/kafka/examples_test.go +++ b/modules/kafka/examples_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/kafka" ) @@ -16,21 +17,21 @@ func ExampleRun() { "confluentinc/confluent-local:7.5.0", kafka.WithClusterID("test-cluster"), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container after defer func() { - if err := kafkaContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(kafkaContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := kafkaContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(kafkaContainer.ClusterID) diff --git a/modules/kafka/go.mod b/modules/kafka/go.mod index 1148bd00f8..7595e2d7a0 100644 --- a/modules/kafka/go.mod +++ b/modules/kafka/go.mod @@ -5,7 +5,8 @@ go 1.22 require ( github.com/IBM/sarama v1.42.1 github.com/docker/go-connections v0.5.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 golang.org/x/mod v0.16.0 ) @@ -41,6 +42,7 @@ require ( github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect github.com/jcmturner/rpc/v2 v2.0.3 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -53,6 +55,7 @@ require ( github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect @@ -71,6 +74,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/kafka/go.sum b/modules/kafka/go.sum index 9310807a50..9dddd03e0b 100644 --- a/modules/kafka/go.sum +++ b/modules/kafka/go.sum @@ -18,6 +18,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -86,6 +87,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -116,6 +121,8 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -239,6 +246,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/modules/kafka/kafka.go b/modules/kafka/kafka.go index c0c02890d4..d4f070b8a1 100644 --- a/modules/kafka/kafka.go +++ b/modules/kafka/kafka.go @@ -104,16 +104,19 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom return nil, err } - clusterID := genericContainerReq.Env["CLUSTER_ID"] - configureControllerQuorumVoters(&genericContainerReq) container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *KafkaContainer + if container != nil { + c = &KafkaContainer{Container: container, ClusterID: genericContainerReq.Env["CLUSTER_ID"]} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &KafkaContainer{Container: container, ClusterID: clusterID}, nil + return c, nil } // copyStarterScript copies the starter script into the container. diff --git a/modules/kafka/kafka_test.go b/modules/kafka/kafka_test.go index 1e2e009b58..42fca78650 100644 --- a/modules/kafka/kafka_test.go +++ b/modules/kafka/kafka_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/IBM/sarama" + "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/kafka" @@ -18,16 +19,8 @@ func TestKafka(t *testing.T) { ctx := context.Background() kafkaContainer, err := kafka.Run(ctx, "confluentinc/confluent-local:7.5.0", kafka.WithClusterID("kraftCluster")) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := kafkaContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, kafkaContainer) + require.NoError(t, err) assertAdvertisedListeners(t, kafkaContainer) @@ -38,17 +31,14 @@ func TestKafka(t *testing.T) { // getBrokers { brokers, err := kafkaContainer.Brokers(ctx) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) config := sarama.NewConfig() client, err := sarama.NewConsumerGroup(brokers, "groupName", config) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) consumer, ready, done, cancel := NewTestKafkaConsumer(t) + defer cancel() go func() { if err := client.Consume(context.Background(), []string{topic}, consumer); err != nil { cancel() @@ -64,19 +54,14 @@ func TestKafka(t *testing.T) { config.Producer.Return.Successes = true producer, err := sarama.NewSyncProducer(brokers, config) - if err != nil { - cancel() - t.Fatal(err) - } + require.NoError(t, err) - if _, _, err := producer.SendMessage(&sarama.ProducerMessage{ + _, _, err = producer.SendMessage(&sarama.ProducerMessage{ Topic: topic, Key: sarama.StringEncoder("key"), Value: sarama.StringEncoder("value"), - }); err != nil { - cancel() - t.Fatal(err) - } + }) + require.NoError(t, err) <-done @@ -91,35 +76,26 @@ func TestKafka(t *testing.T) { func TestKafka_invalidVersion(t *testing.T) { ctx := context.Background() - _, err := kafka.Run(ctx, "confluentinc/confluent-local:6.3.3", kafka.WithClusterID("kraftCluster")) - if err == nil { - t.Fatal(err) - } + ctr, err := kafka.Run(ctx, "confluentinc/confluent-local:6.3.3", kafka.WithClusterID("kraftCluster")) + testcontainers.CleanupContainer(t, ctr) + require.Error(t, err) } // assertAdvertisedListeners checks that the advertised listeners are set correctly: // - The BROKER:// protocol is using the hostname of the Kafka container func assertAdvertisedListeners(t *testing.T, container testcontainers.Container) { inspect, err := container.Inspect(context.Background()) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) hostname := inspect.Config.Hostname code, r, err := container.Exec(context.Background(), []string{"cat", "/usr/sbin/testcontainers_start.sh"}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) - if code != 0 { - t.Fatalf("expected exit code to be 0, got %d", code) - } + require.Zero(t, code) bs, err := io.ReadAll(r) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if !strings.Contains(string(bs), "BROKER://"+hostname+":9092") { t.Fatalf("expected advertised listeners to contain %s, got %s", "BROKER://"+hostname+":9092", string(bs)) diff --git a/modules/localstack/examples_test.go b/modules/localstack/examples_test.go index 65a55c317b..d503ecee6f 100644 --- a/modules/localstack/examples_test.go +++ b/modules/localstack/examples_test.go @@ -24,21 +24,21 @@ func ExampleRun() { ctx := context.Background() localstackContainer, err := localstack.Run(ctx, "localstack/localstack:1.4.0") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := localstackContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(localstackContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := localstackContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -53,9 +53,16 @@ func ExampleRun_withNetwork() { newNetwork, err := network.New(ctx) if err != nil { - log.Fatalf("failed to create network: %s", err) + log.Printf("failed to create network: %s", err) + return } + defer func() { + if err := newNetwork.Remove(context.Background()); err != nil { + log.Printf("failed to remove network: %s", err) + } + }() + nwName := newNetwork.Name localstackContainer, err := localstack.Run( @@ -64,21 +71,21 @@ func ExampleRun_withNetwork() { testcontainers.WithEnv(map[string]string{"SERVICES": "s3,sqs"}), network.WithNetwork([]string{nwName}, newNetwork), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - // } - - // Clean up the container defer func() { - if err := localstackContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(localstackContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + // } networks, err := localstackContainer.Networks(ctx) if err != nil { - log.Fatalf("failed to get container networks: %s", err) // nolint:gocritic + log.Printf("failed to get container networks: %s", err) + return } fmt.Println(len(networks)) @@ -90,14 +97,20 @@ func ExampleRun_withNetwork() { func ExampleRun_legacyMode() { ctx := context.Background() - _, err := localstack.Run( + ctr, err := localstack.Run( ctx, "localstack/localstack:0.10.0", testcontainers.WithEnv(map[string]string{"SERVICES": "s3,sqs"}), testcontainers.WithWaitStrategy(wait.ForLog("Ready.").WithStartupTimeout(5*time.Minute).WithOccurrence(1)), ) + defer func() { + if err := testcontainers.TerminateContainer(ctr); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() if err == nil { - log.Fatalf("expected an error, got nil") + log.Printf("expected an error, got nil") + return } fmt.Println(err) @@ -123,7 +136,7 @@ func ExampleRun_usingLambdas() { lambdaName := "localstack-lambda-url-example" // withCustomContainerRequest { - container, err := localstack.Run(ctx, + ctr, err := localstack.Run(ctx, "localstack/localstack:2.3.0", testcontainers.WithEnv(map[string]string{ "SERVICES": "lambda", @@ -139,17 +152,17 @@ func ExampleRun_usingLambdas() { }, }, }), - // } ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } + // } defer func() { - err := container.Terminate(ctx) - if err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(ctr); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // the three commands below are doing the following: // 1. create a lambda function @@ -169,9 +182,10 @@ func ExampleRun_usingLambdas() { {"awslocal", "lambda", "wait", "function-active-v2", "--function-name", lambdaName}, } for _, cmd := range lambdaCommands { - _, _, err := container.Exec(ctx, cmd) + _, _, err := ctr.Exec(ctx, cmd) if err != nil { - log.Fatalf("failed to execute command %v: %s", cmd, err) // nolint:gocritic + log.Printf("failed to execute command %v: %s", cmd, err) + return } } @@ -179,15 +193,17 @@ func ExampleRun_usingLambdas() { cmd := []string{ "awslocal", "lambda", "list-function-url-configs", "--function-name", lambdaName, } - _, reader, err := container.Exec(ctx, cmd, exec.Multiplexed()) + _, reader, err := ctr.Exec(ctx, cmd, exec.Multiplexed()) if err != nil { - log.Fatalf("failed to execute command %v: %s", cmd, err) + log.Printf("failed to execute command %v: %s", cmd, err) + return } buf := new(bytes.Buffer) _, err = buf.ReadFrom(reader) if err != nil { - log.Fatalf("failed to read from reader: %s", err) + log.Printf("failed to read from reader: %s", err) + return } content := buf.Bytes() @@ -205,7 +221,8 @@ func ExampleRun_usingLambdas() { v := &FunctionURLConfig{} err = json.Unmarshal(content, v) if err != nil { - log.Fatalf("failed to unmarshal content: %s", err) + log.Printf("failed to unmarshal content: %s", err) + return } httpClient := http.Client{ @@ -215,21 +232,24 @@ func ExampleRun_usingLambdas() { functionURL := v.FunctionURLConfigs[0].FunctionURL // replace the port with the one exposed by the container - mappedPort, err := container.MappedPort(ctx, "4566/tcp") + mappedPort, err := ctr.MappedPort(ctx, "4566/tcp") if err != nil { - log.Fatalf("failed to get mapped port: %s", err) + log.Printf("failed to get mapped port: %s", err) + return } functionURL = strings.ReplaceAll(functionURL, "4566", mappedPort.Port()) resp, err := httpClient.Post(functionURL, "application/json", bytes.NewBufferString(`{"num1": "10", "num2": "10"}`)) if err != nil { - log.Fatalf("failed to send request to lambda function: %s", err) + log.Printf("failed to send request to lambda function: %s", err) + return } jsonResponse, err := io.ReadAll(resp.Body) if err != nil { - log.Fatalf("failed to read response body: %s", err) + log.Printf("failed to read response body: %s", err) + return } fmt.Println(string(jsonResponse)) diff --git a/modules/localstack/localstack.go b/modules/localstack/localstack.go index 961527cd3e..5cfe054a85 100644 --- a/modules/localstack/localstack.go +++ b/modules/localstack/localstack.go @@ -116,13 +116,15 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom localStackReq.GenericContainerRequest.Logger.Printf("Setting %s to %s (%s)\n", envVar, req.Env[envVar], hostnameExternalReason) container, err := testcontainers.GenericContainer(ctx, localStackReq.GenericContainerRequest) - if err != nil { - return nil, err + var c *LocalStackContainer + if container != nil { + c = &LocalStackContainer{Container: container} } - c := &LocalStackContainer{ - Container: container, + if err != nil { + return c, fmt.Errorf("generic container: %w", err) } + return c, nil } diff --git a/modules/localstack/localstack_test.go b/modules/localstack/localstack_test.go index 70797fe3cd..5991c52fbf 100644 --- a/modules/localstack/localstack_test.go +++ b/modules/localstack/localstack_test.go @@ -8,7 +8,6 @@ import ( "testing" "time" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" @@ -43,7 +42,7 @@ func TestConfigureDockerHost(t *testing.T) { reason, err := configureDockerHost(req, tt.envVar) require.NoError(t, err) - assert.Equal(t, "explicitly as environment variable", reason) + require.Equal(t, "explicitly as environment variable", reason) }) t.Run("HOSTNAME_EXTERNAL matches the last network alias on a container with non-default network", func(t *testing.T) { @@ -58,8 +57,8 @@ func TestConfigureDockerHost(t *testing.T) { reason, err := configureDockerHost(req, tt.envVar) require.NoError(t, err) - assert.Equal(t, "to match last network alias on container with non-default network", reason) - assert.Equal(t, "foo3", req.Env[tt.envVar]) + require.Equal(t, "to match last network alias on container with non-default network", reason) + require.Equal(t, "foo3", req.Env[tt.envVar]) }) t.Run("HOSTNAME_EXTERNAL matches the daemon host because there are no aliases", func(t *testing.T) { @@ -78,8 +77,8 @@ func TestConfigureDockerHost(t *testing.T) { reason, err := configureDockerHost(req, tt.envVar) require.NoError(t, err) - assert.Equal(t, "to match host-routable address for container", reason) - assert.Equal(t, expectedDaemonHost, req.Env[tt.envVar]) + require.Equal(t, "to match host-routable address for container", reason) + require.Equal(t, expectedDaemonHost, req.Env[tt.envVar]) }) } } @@ -102,7 +101,7 @@ func TestIsLegacyMode(t *testing.T) { for _, tt := range tests { t.Run(tt.version, func(t *testing.T) { got := isLegacyMode(fmt.Sprintf("localstack/localstack:%s", tt.version)) - assert.Equal(t, tt.want, got, "runInLegacyMode() = %v, want %v", got, tt.want) + require.Equal(t, tt.want, got, "runInLegacyMode() = %v, want %v", got, tt.want) }) } } @@ -118,16 +117,17 @@ func TestRunContainer(t *testing.T) { for _, tt := range tests { ctx := context.Background() - container, err := Run( + ctr, err := Run( ctx, fmt.Sprintf("localstack/localstack:%s", tt.version), ) + testcontainers.CleanupContainer(t, ctr) t.Run("Localstack:"+tt.version+" - multiple services exposed on same port", func(t *testing.T) { require.NoError(t, err) - assert.NotNil(t, container) + require.NotNil(t, ctr) - inspect, err := container.Inspect(ctx) + inspect, err := ctr.Inspect(ctx) require.NoError(t, err) rawPorts := inspect.NetworkSettings.Ports @@ -140,7 +140,7 @@ func TestRunContainer(t *testing.T) { } } - assert.Equal(t, 1, ports) // a single port is exposed + require.Equal(t, 1, ports) // a single port is exposed }) } } @@ -148,9 +148,10 @@ func TestRunContainer(t *testing.T) { func TestStartWithoutOverride(t *testing.T) { ctx := context.Background() - container, err := Run(ctx, "localstack/localstack:2.0.0") + ctr, err := Run(ctx, "localstack/localstack:2.0.0") + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - assert.NotNil(t, container) + require.NotNil(t, ctr) } func TestStartV2WithNetwork(t *testing.T) { @@ -158,6 +159,7 @@ func TestStartV2WithNetwork(t *testing.T) { nw, err := network.New(ctx) require.NoError(t, err) + testcontainers.CleanupNetwork(t, nw) localstack, err := Run( ctx, @@ -165,8 +167,9 @@ func TestStartV2WithNetwork(t *testing.T) { network.WithNetwork([]string{"localstack"}, nw), testcontainers.WithEnv(map[string]string{"SERVICES": "s3,sqs"}), ) + testcontainers.CleanupContainer(t, localstack) require.NoError(t, err) - assert.NotNil(t, localstack) + require.NotNil(t, localstack) networkName := nw.Name @@ -197,6 +200,7 @@ func TestStartV2WithNetwork(t *testing.T) { }, Started: true, }) + testcontainers.CleanupContainer(t, cli) require.NoError(t, err) - assert.NotNil(t, cli) + require.NotNil(t, cli) } diff --git a/modules/localstack/v1/s3_test.go b/modules/localstack/v1/s3_test.go index be643228f6..87eba46080 100644 --- a/modules/localstack/v1/s3_test.go +++ b/modules/localstack/v1/s3_test.go @@ -62,10 +62,11 @@ func awsSession(ctx context.Context, l *localstack.LocalStackContainer) (*sessio func TestS3(t *testing.T) { ctx := context.Background() - container, err := localstack.Run(ctx, "localstack/localstack:1.4.0") + ctr, err := localstack.Run(ctx, "localstack/localstack:1.4.0") + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - session, err := awsSession(ctx, container) + session, err := awsSession(ctx, ctr) require.NoError(t, err) s3Uploader := s3manager.NewUploader(session) diff --git a/modules/localstack/v2/s3_test.go b/modules/localstack/v2/s3_test.go index 2b5308ddd8..477549fb9c 100644 --- a/modules/localstack/v2/s3_test.go +++ b/modules/localstack/v2/s3_test.go @@ -73,10 +73,11 @@ func s3Client(ctx context.Context, l *localstack.LocalStackContainer) (*s3.Clien func TestS3(t *testing.T) { ctx := context.Background() - container, err := localstack.Run(ctx, "localstack/localstack:1.4.0") + ctr, err := localstack.Run(ctx, "localstack/localstack:1.4.0") + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - s3Client, err := s3Client(ctx, container) + s3Client, err := s3Client(ctx, ctr) require.NoError(t, err) t.Run("S3 operations", func(t *testing.T) { diff --git a/modules/mariadb/examples_test.go b/modules/mariadb/examples_test.go index d33970df14..59e168d3e4 100644 --- a/modules/mariadb/examples_test.go +++ b/modules/mariadb/examples_test.go @@ -6,6 +6,7 @@ import ( "log" "path/filepath" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mariadb" ) @@ -21,21 +22,21 @@ func ExampleRun() { mariadb.WithUsername("root"), mariadb.WithPassword(""), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := mariadbContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(mariadbContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := mariadbContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/mariadb/go.mod b/modules/mariadb/go.mod index e8039caf58..a3d2ee8f70 100644 --- a/modules/mariadb/go.mod +++ b/modules/mariadb/go.mod @@ -4,7 +4,8 @@ go 1.22 require ( github.com/go-sql-driver/mysql v1.7.1 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -16,6 +17,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -27,6 +29,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -38,6 +41,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -54,6 +58,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/mariadb/go.sum b/modules/mariadb/go.sum index e2bb93b49d..dcc1a8d165 100644 --- a/modules/mariadb/go.sum +++ b/modules/mariadb/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -54,6 +55,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -80,6 +85,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -176,6 +183,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/mariadb/mariadb.go b/modules/mariadb/mariadb.go index fae71c7871..1d0b553e41 100644 --- a/modules/mariadb/mariadb.go +++ b/modules/mariadb/mariadb.go @@ -169,13 +169,21 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) - if err != nil { - return nil, err + var c *MariaDBContainer + if container != nil { + c = &MariaDBContainer{ + Container: container, + username: username, + password: password, + database: req.Env["MARIADB_DATABASE"], + } } - database := req.Env["MARIADB_DATABASE"] + if err != nil { + return c, fmt.Errorf("generic container: %w", err) + } - return &MariaDBContainer{container, username, password, database}, nil + return c, nil } // MustConnectionString panics if the address cannot be determined. diff --git a/modules/mariadb/mariadb_test.go b/modules/mariadb/mariadb_test.go index f1863f472c..8e55609ec4 100644 --- a/modules/mariadb/mariadb_test.go +++ b/modules/mariadb/mariadb_test.go @@ -8,55 +8,41 @@ import ( // Import mysql into the scope of this package (required) _ "github.com/go-sql-driver/mysql" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mariadb" ) func TestMariaDB(t *testing.T) { ctx := context.Background() - container, err := mariadb.Run(ctx, "mariadb:11.0.3") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := mariadb.Run(ctx, "mariadb:11.0.3") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // connectionString { // By default, MariaDB transmits data between the server and clients without encrypting it. - connectionString, err := container.ConnectionString(ctx, "tls=false") + connectionString, err := ctr.ConnectionString(ctx, "tls=false") // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) - mustConnectionString := container.MustConnectionString(ctx, "tls=false") - if mustConnectionString != connectionString { - t.Errorf("ConnectionString was not equal to MustConnectionString") - } + mustConnectionString := ctr.MustConnectionString(ctx, "tls=false") + require.Equal(t, connectionString, mustConnectionString) db, err := sql.Open("mysql", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) + _, err = db.Exec("CREATE TABLE IF NOT EXISTS a_table ( \n" + " `col_1` VARCHAR(128) NOT NULL, \n" + " `col_2` VARCHAR(128) NOT NULL, \n" + " PRIMARY KEY (`col_1`, `col_2`) \n" + ")") - if err != nil { - t.Errorf("error creating table: %+v\n", err) - } + require.NoError(t, err) } func TestMariaDBWithNonRootUserAndEmptyPassword(t *testing.T) { @@ -75,163 +61,105 @@ func TestMariaDBWithNonRootUserAndEmptyPassword(t *testing.T) { func TestMariaDBWithRootUserAndEmptyPassword(t *testing.T) { ctx := context.Background() - container, err := mariadb.Run(ctx, + ctr, err := mariadb.Run(ctx, "mariadb:11.0.3", mariadb.WithDatabase("foo"), mariadb.WithUsername("root"), mariadb.WithPassword("")) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - - connectionString, err := container.ConnectionString(ctx) - if err != nil { - t.Fatal(err) - } + connectionString, err := ctr.ConnectionString(ctx) + require.NoError(t, err) db, err := sql.Open("mysql", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) + _, err = db.Exec("CREATE TABLE IF NOT EXISTS a_table ( \n" + " `col_1` VARCHAR(128) NOT NULL, \n" + " `col_2` VARCHAR(128) NOT NULL, \n" + " PRIMARY KEY (`col_1`, `col_2`) \n" + ")") - if err != nil { - t.Errorf("error creating table: %+v\n", err) - } + require.NoError(t, err) } func TestMariaDBWithMySQLEnvVars(t *testing.T) { ctx := context.Background() - container, err := mariadb.Run(ctx, "mariadb:10.3.29", + ctr, err := mariadb.Run(ctx, "mariadb:10.3.29", mariadb.WithScripts(filepath.Join("testdata", "schema.sql"))) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - - assertDataCanBeFetched(t, ctx, container) + assertDataCanBeFetched(t, ctx, ctr) } func TestMariaDBWithConfigFile(t *testing.T) { ctx := context.Background() - container, err := mariadb.Run(ctx, "mariadb:11.0.3", + ctr, err := mariadb.Run(ctx, "mariadb:11.0.3", mariadb.WithConfigFile(filepath.Join("testdata", "my.cnf"))) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - - connectionString, err := container.ConnectionString(ctx) - if err != nil { - t.Fatal(err) - } + connectionString, err := ctr.ConnectionString(ctx) + require.NoError(t, err) db, err := sql.Open("mysql", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) // In MariaDB 10.2.2 and later, the default file format is Barracuda and Antelope is deprecated. // Barracuda is a newer InnoDB file format. It supports the COMPACT, REDUNDANT, DYNAMIC and // COMPRESSED row formats. Tables with large BLOB or TEXT columns in particular could benefit // from the dynamic row format. stmt, err := db.Prepare("SELECT @@GLOBAL.innodb_default_row_format") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + defer stmt.Close() row := stmt.QueryRow() innodbFileFormat := "" err = row.Scan(&innodbFileFormat) - if err != nil { - t.Errorf("error fetching innodb_default_row_format value") - } - if innodbFileFormat != "dynamic" { - t.Fatal("The InnoDB file format has been set by the ini file content") - } + require.NoError(t, err) + require.Equal(t, "dynamic", innodbFileFormat) } func TestMariaDBWithScripts(t *testing.T) { ctx := context.Background() - container, err := mariadb.Run(ctx, + ctr, err := mariadb.Run(ctx, "mariadb:11.0.3", mariadb.WithScripts(filepath.Join("testdata", "schema.sql"))) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - assertDataCanBeFetched(t, ctx, container) + assertDataCanBeFetched(t, ctx, ctr) } func assertDataCanBeFetched(t *testing.T, ctx context.Context, container *mariadb.MariaDBContainer) { connectionString, err := container.ConnectionString(ctx) - if err != nil { - t.Fatal(err) - } - + require.NoError(t, err) db, err := sql.Open("mysql", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) stmt, err := db.Prepare("SELECT name from profile") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer stmt.Close() + row := stmt.QueryRow() var name string err = row.Scan(&name) - if err != nil { - t.Errorf("error fetching data") - } - if name != "profile 1" { - t.Fatal("The expected record was not found in the database.") - } + require.NoError(t, err) + require.Equal(t, "profile 1", name) } diff --git a/modules/milvus/examples_test.go b/modules/milvus/examples_test.go index 79ca1b9812..a8242f15b2 100644 --- a/modules/milvus/examples_test.go +++ b/modules/milvus/examples_test.go @@ -8,6 +8,7 @@ import ( "github.com/milvus-io/milvus-sdk-go/v2/client" "github.com/milvus-io/milvus-sdk-go/v2/entity" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/milvus" ) @@ -16,21 +17,21 @@ func ExampleRun() { ctx := context.Background() milvusContainer, err := milvus.Run(ctx, "milvusdb/milvus:v2.3.9") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := milvusContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(milvusContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := milvusContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -44,26 +45,27 @@ func ExampleMilvusContainer_collections() { ctx := context.Background() milvusContainer, err := milvus.Run(ctx, "milvusdb/milvus:v2.3.9") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := milvusContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(milvusContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } connectionStr, err := milvusContainer.ConnectionString(ctx) if err != nil { - log.Fatalf("failed to get connection string: %s", err) // nolint:gocritic + log.Printf("failed to get connection string: %s", err) + return } // Create a client to interact with the Milvus container milvusClient, err := client.NewGrpcClient(context.Background(), connectionStr) if err != nil { - log.Fatal("failed to connect to Milvus:", err.Error()) + log.Print("failed to connect to Milvus:", err.Error()) + return } defer milvusClient.Close() @@ -101,12 +103,14 @@ func ExampleMilvusContainer_collections() { 2, // shardNum ) if err != nil { - log.Fatalf("failed to create collection: %s", err) // nolint:gocritic + log.Printf("failed to create collection: %s", err) + return } list, err := milvusClient.ListCollections(context.Background()) if err != nil { - log.Fatalf("failed to list collections: %s", err) // nolint:gocritic + log.Printf("failed to list collections: %s", err) + return } // } diff --git a/modules/milvus/milvus.go b/modules/milvus/milvus.go index 9b944f6160..b35cc99335 100644 --- a/modules/milvus/milvus.go +++ b/modules/milvus/milvus.go @@ -85,11 +85,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *MilvusContainer + if container != nil { + c = &MilvusContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &MilvusContainer{Container: container}, nil + return c, nil } type embedEtcdConfigTplParams struct { diff --git a/modules/milvus/milvus_test.go b/modules/milvus/milvus_test.go index c49f37c92f..c1ad0a070e 100644 --- a/modules/milvus/milvus_test.go +++ b/modules/milvus/milvus_test.go @@ -7,24 +7,20 @@ import ( "github.com/milvus-io/milvus-sdk-go/v2/client" "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/milvus" ) func TestMilvus(t *testing.T) { ctx := context.Background() - container, err := milvus.Run(ctx, "milvusdb/milvus:v2.3.9") + ctr, err := milvus.Run(ctx, "milvusdb/milvus:v2.3.9") + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - // Clean up the container after the test is complete - t.Cleanup(func() { - err = container.Terminate(ctx) - require.NoError(t, err) - }) - t.Run("Connect to Milvus with gRPC", func(tt *testing.T) { // connectionString { - connectionStr, err := container.ConnectionString(ctx) + connectionStr, err := ctr.ConnectionString(ctx) // } require.NoError(t, err) diff --git a/modules/minio/examples_test.go b/modules/minio/examples_test.go index c13e679388..a1e50b6c84 100644 --- a/modules/minio/examples_test.go +++ b/modules/minio/examples_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/minio" ) @@ -13,21 +14,21 @@ func ExampleRun() { ctx := context.Background() minioContainer, err := minio.Run(ctx, "minio/minio:RELEASE.2024-01-16T16-07-38Z") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := minioContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(minioContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := minioContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/minio/go.mod b/modules/minio/go.mod index c50c958c21..84d98587fd 100644 --- a/modules/minio/go.mod +++ b/modules/minio/go.mod @@ -4,7 +4,8 @@ go 1.22 require ( github.com/minio/minio-go/v7 v7.0.68 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -16,6 +17,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -30,6 +32,7 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.17.6 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/minio/md5-simd v1.1.2 // indirect @@ -45,6 +48,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/rs/xid v1.5.0 // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect @@ -64,6 +68,7 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/minio/go.sum b/modules/minio/go.sum index e837e4f48e..5afc27ffd9 100644 --- a/modules/minio/go.sum +++ b/modules/minio/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -60,6 +61,10 @@ github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6K github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -97,6 +102,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= @@ -197,6 +204,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/modules/minio/minio.go b/modules/minio/minio.go index c7e2898d9f..6907b1372b 100644 --- a/modules/minio/minio.go +++ b/modules/minio/minio.go @@ -93,9 +93,14 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *MinioContainer + if container != nil { + c = &MinioContainer{Container: container, Username: username, Password: password} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &MinioContainer{Container: container, Username: username, Password: password}, nil + return c, nil } diff --git a/modules/minio/minio_test.go b/modules/minio/minio_test.go index 60bf8034b3..d8ca857cb3 100644 --- a/modules/minio/minio_test.go +++ b/modules/minio/minio_test.go @@ -8,51 +8,39 @@ import ( "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" tcminio "github.com/testcontainers/testcontainers-go/modules/minio" ) func TestMinio(t *testing.T) { ctx := context.Background() - container, err := tcminio.Run(ctx, + ctr, err := tcminio.Run(ctx, "minio/minio:RELEASE.2024-01-16T16-07-38Z", tcminio.WithUsername("thisismyuser"), tcminio.WithPassword("thisismypassword")) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions // connectionString { - url, err := container.ConnectionString(ctx) + url, err := ctr.ConnectionString(ctx) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) minioClient, err := minio.New(url, &minio.Options{ - Creds: credentials.NewStaticV4(container.Username, container.Password, ""), + Creds: credentials.NewStaticV4(ctr.Username, ctr.Password, ""), Secure: false, }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) bucketName := "testcontainers" location := "eu-west-2" // create bucket err = minioClient.MakeBucket(ctx, bucketName, minio.MakeBucketOptions{Region: location}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) objectName := "testdata" contentType := "applcation/octet-stream" @@ -60,23 +48,15 @@ func TestMinio(t *testing.T) { contentLength := int64(len(content)) uploadInfo, err := minioClient.PutObject(ctx, bucketName, objectName, strings.NewReader(content), contentLength, minio.PutObjectOptions{ContentType: contentType}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // object is a readSeekCloser object, err := minioClient.GetObject(ctx, uploadInfo.Bucket, uploadInfo.Key, minio.GetObjectOptions{}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + defer object.Close() n, err := io.Copy(io.Discard, object) - if err != nil { - t.Fatal(err) - } - - if n != contentLength { - t.Fatalf("expected %d; got %d", contentLength, n) - } + require.NoError(t, err) + require.Equal(t, contentLength, n) } diff --git a/modules/mockserver/examples_test.go b/modules/mockserver/examples_test.go index 17f4cfffea..a93c8bcbf0 100644 --- a/modules/mockserver/examples_test.go +++ b/modules/mockserver/examples_test.go @@ -10,6 +10,7 @@ import ( client "github.com/BraspagDevelopers/mock-server-client" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mockserver" ) @@ -18,21 +19,21 @@ func ExampleRun() { ctx := context.Background() mockserverContainer, err := mockserver.Run(ctx, "mockserver/mockserver:5.15.0") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := mockserverContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(mockserverContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := mockserverContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -46,20 +47,20 @@ func ExampleRun_connect() { ctx := context.Background() mockserverContainer, err := mockserver.Run(ctx, "mockserver/mockserver:5.15.0") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := mockserverContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(mockserverContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } url, err := mockserverContainer.URL(ctx) if err != nil { - log.Fatalf("failed to get container URL: %s", err) // nolint:gocritic + log.Printf("failed to get container URL: %s", err) + return } ms := client.NewClientURL(url) // } @@ -71,18 +72,21 @@ func ExampleRun_connect() { requestMatcher = requestMatcher.WithJSONFields(map[string]interface{}{"name": "Tools"}) err = ms.RegisterExpectation(client.NewExpectation(requestMatcher).WithResponse(client.NewResponseOK().WithJSONBody(map[string]any{"test": "value"}))) if err != nil { - log.Fatalf("failed to register expectation: %s", err) + log.Printf("failed to register expectation: %s", err) + return } httpClient := &http.Client{} resp, err := httpClient.Post(url+"/api/categories", "application/json", strings.NewReader(`{"name": "Tools"}`)) if err != nil { - log.Fatalf("failed to send request: %s", err) + log.Printf("failed to send request: %s", err) + return } buf, err := io.ReadAll(resp.Body) if err != nil { - log.Fatalf("failed to read response: %s", err) + log.Printf("failed to read response: %s", err) + return } resp.Body.Close() diff --git a/modules/mockserver/go.mod b/modules/mockserver/go.mod index e2ba76d72d..36f5772800 100644 --- a/modules/mockserver/go.mod +++ b/modules/mockserver/go.mod @@ -16,6 +16,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -28,6 +29,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -39,10 +41,12 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/stretchr/testify v1.9.0 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect @@ -55,6 +59,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/mockserver/go.sum b/modules/mockserver/go.sum index acf88d134a..16335ff9dd 100644 --- a/modules/mockserver/go.sum +++ b/modules/mockserver/go.sum @@ -18,6 +18,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -56,6 +57,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -82,6 +87,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -180,6 +187,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/mongodb/examples_test.go b/modules/mongodb/examples_test.go index 5e8cbe8009..98a31d61fa 100644 --- a/modules/mongodb/examples_test.go +++ b/modules/mongodb/examples_test.go @@ -19,21 +19,21 @@ func ExampleRun() { ctx := context.Background() mongodbContainer, err := mongodb.Run(ctx, "mongo:6") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := mongodbContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(mongodbContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := mongodbContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -47,31 +47,33 @@ func ExampleRun_connect() { ctx := context.Background() mongodbContainer, err := mongodb.Run(ctx, "mongo:6") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := mongodbContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(mongodbContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } endpoint, err := mongodbContainer.ConnectionString(ctx) if err != nil { - log.Fatalf("failed to get connection string: %s", err) // nolint:gocritic + log.Printf("failed to get connection string: %s", err) + return } mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(endpoint)) if err != nil { - log.Fatalf("failed to connect to MongoDB: %s", err) + log.Printf("failed to connect to MongoDB: %s", err) + return } // } err = mongoClient.Ping(ctx, nil) if err != nil { - log.Fatalf("failed to ping MongoDB: %s", err) + log.Printf("failed to ping MongoDB: %s", err) + return } fmt.Println(mongoClient.Database("test").Name()) @@ -83,36 +85,38 @@ func ExampleRun_connect() { func ExampleRun_withCredentials() { ctx := context.Background() - container, err := mongodb.Run(ctx, + ctr, err := mongodb.Run(ctx, "mongo:6", mongodb.WithUsername("root"), mongodb.WithPassword("password"), testcontainers.WithWaitStrategy(wait.ForLog("Waiting for connections")), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := container.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(ctr); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } - connStr, err := container.ConnectionString(ctx) + connStr, err := ctr.ConnectionString(ctx) if err != nil { - log.Fatalf("failed to get connection string: %s", err) // nolint:gocritic + log.Printf("failed to get connection string: %s", err) + return } mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(connStr)) if err != nil { - log.Fatalf("failed to connect to MongoDB: %s", err) + log.Printf("failed to connect to MongoDB: %s", err) + return } err = mongoClient.Ping(ctx, nil) if err != nil { - log.Fatalf("failed to ping MongoDB: %s", err) + log.Printf("failed to ping MongoDB: %s", err) + return } fmt.Println(strings.Split(connStr, "@")[0]) diff --git a/modules/mongodb/go.mod b/modules/mongodb/go.mod index e7e8c724bc..66311410d7 100644 --- a/modules/mongodb/go.mod +++ b/modules/mongodb/go.mod @@ -3,7 +3,8 @@ module github.com/testcontainers/testcontainers-go/modules/mongodb go 1.22 require ( - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 go.mongodb.org/mongo-driver v1.13.1 ) @@ -16,6 +17,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -28,6 +30,7 @@ require ( github.com/golang/snappy v0.0.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -40,6 +43,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -62,6 +66,7 @@ require ( golang.org/x/text v0.16.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/mongodb/go.sum b/modules/mongodb/go.sum index bc45e6d333..7f2154a1b2 100644 --- a/modules/mongodb/go.sum +++ b/modules/mongodb/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -56,6 +57,10 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -84,6 +89,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -212,6 +219,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/mongodb/mongodb.go b/modules/mongodb/mongodb.go index 188c55e85b..4923473593 100644 --- a/modules/mongodb/mongodb.go +++ b/modules/mongodb/mongodb.go @@ -50,14 +50,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) - if err != nil { - return nil, err + var c *MongoDBContainer + if container != nil { + c = &MongoDBContainer{Container: container, username: username, password: password} } - if username != "" && password != "" { - return &MongoDBContainer{Container: container, username: username, password: password}, nil + if err != nil { + return c, fmt.Errorf("generic container: %w", err) } - return &MongoDBContainer{Container: container}, nil + + return c, nil } // WithUsername sets the initial username to be created when the container starts diff --git a/modules/mongodb/mongodb_test.go b/modules/mongodb/mongodb_test.go index ead2b1818b..663f05cff6 100644 --- a/modules/mongodb/mongodb_test.go +++ b/modules/mongodb/mongodb_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" @@ -57,37 +58,21 @@ func TestMongoDB(t *testing.T) { ctx := context.Background() mongodbContainer, err := mongodb.Run(ctx, tc.img, tc.opts...) - if err != nil { - tt.Fatalf("failed to start container: %s", err) - } - - defer func() { - if err := mongodbContainer.Terminate(ctx); err != nil { - tt.Fatalf("failed to terminate container: %s", err) - } - }() + testcontainers.CleanupContainer(t, mongodbContainer) + require.NoError(tt, err) endpoint, err := mongodbContainer.ConnectionString(ctx) - if err != nil { - tt.Fatalf("failed to get connection string: %s", err) - } + require.NoError(tt, err) // Force direct connection to the container to avoid the replica set // connection string that is returned by the container itself when // using the replica set option. mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(endpoint+"/?connect=direct")) - if err != nil { - tt.Fatalf("failed to connect to MongoDB: %s", err) - } + require.NoError(tt, err) err = mongoClient.Ping(ctx, nil) - if err != nil { - tt.Fatalf("failed to ping MongoDB: %s", err) - } - - if mongoClient.Database("test").Name() != "test" { - tt.Fatalf("failed to connect to the correct database") - } + require.NoError(tt, err) + require.Equal(t, "test", mongoClient.Database("test").Name()) }) } } diff --git a/modules/mssql/examples_test.go b/modules/mssql/examples_test.go index 10363d9b48..f5e7ebd04d 100644 --- a/modules/mssql/examples_test.go +++ b/modules/mssql/examples_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mssql" ) @@ -19,21 +20,21 @@ func ExampleRun() { mssql.WithAcceptEULA(), mssql.WithPassword(password), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := mssqlContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(mssqlContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := mssqlContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/mssql/go.mod b/modules/mssql/go.mod index 83411fb7aa..80bd7ba219 100644 --- a/modules/mssql/go.mod +++ b/modules/mssql/go.mod @@ -4,7 +4,8 @@ go 1.22 require ( github.com/microsoft/go-mssqldb v1.7.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -16,6 +17,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -29,6 +31,7 @@ require ( github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -40,6 +43,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -57,6 +61,7 @@ require ( golang.org/x/text v0.16.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/mssql/go.sum b/modules/mssql/go.sum index 2f512564ff..452ef25661 100644 --- a/modules/mssql/go.sum +++ b/modules/mssql/go.sum @@ -28,6 +28,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,6 +71,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= @@ -102,6 +107,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -198,6 +205,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/mssql/mssql.go b/modules/mssql/mssql.go index ca30d02385..57f634c02c 100644 --- a/modules/mssql/mssql.go +++ b/modules/mssql/mssql.go @@ -70,14 +70,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) - if err != nil { - return nil, err + var c *MSSQLServerContainer + if container != nil { + c = &MSSQLServerContainer{Container: container, password: req.Env["MSSQL_SA_PASSWORD"], username: defaultUsername} } - username := defaultUsername - password := req.Env["MSSQL_SA_PASSWORD"] + if err != nil { + return c, fmt.Errorf("generic container: %w", err) + } - return &MSSQLServerContainer{Container: container, password: password, username: username}, nil + return c, nil } func (c *MSSQLServerContainer) ConnectionString(ctx context.Context, args ...string) (string, error) { diff --git a/modules/mssql/mssql_test.go b/modules/mssql/mssql_test.go index 4e2050385a..602778f8a0 100644 --- a/modules/mssql/mssql_test.go +++ b/modules/mssql/mssql_test.go @@ -6,6 +6,7 @@ import ( "testing" _ "github.com/microsoft/go-mssqldb" + "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mssql" @@ -15,63 +16,45 @@ import ( func TestMSSQLServer(t *testing.T) { ctx := context.Background() - container, err := mssql.Run(ctx, + ctr, err := mssql.Run(ctx, "mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04", mssql.WithAcceptEULA(), ) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions - connectionString, err := container.ConnectionString(ctx) - if err != nil { - t.Fatal(err) - } + connectionString, err := ctr.ConnectionString(ctx) + require.NoError(t, err) db, err := sql.Open("sqlserver", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) _, err = db.Exec("CREATE TABLE a_table ( " + " [col_1] NVARCHAR(128) NOT NULL, " + " [col_2] NVARCHAR(128) NOT NULL, " + " PRIMARY KEY ([col_1], [col_2]) " + ")") - if err != nil { - t.Errorf("error creating table: %+v\n", err) - } + require.NoError(t, err) } func TestMSSQLServerWithMissingEulaOption(t *testing.T) { ctx := context.Background() - container, err := mssql.Run(ctx, + ctr, err := mssql.Run(ctx, "mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04", testcontainers.WithWaitStrategy( wait.ForLog("The SQL Server End-User License Agreement (EULA) must be accepted")), ) - if err != nil { - t.Fatalf("Expected a log to confirm missing EULA but got error: %s", err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - state, err := container.State(ctx) - if err != nil { - t.Fatalf("failed to get container state: %s", err) - } + state, err := ctr.State(ctx) + require.NoError(t, err) if !state.Running { t.Log("Success: Confirmed proper handling of missing EULA, so container is not running.") @@ -81,140 +64,89 @@ func TestMSSQLServerWithMissingEulaOption(t *testing.T) { func TestMSSQLServerWithConnectionStringParameters(t *testing.T) { ctx := context.Background() - container, err := mssql.Run(ctx, + ctr, err := mssql.Run(ctx, "mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04", mssql.WithAcceptEULA(), ) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions - connectionString, err := container.ConnectionString(ctx, "encrypt=false", "TrustServerCertificate=true") - if err != nil { - t.Fatal(err) - } + connectionString, err := ctr.ConnectionString(ctx, "encrypt=false", "TrustServerCertificate=true") + require.NoError(t, err) db, err := sql.Open("sqlserver", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) _, err = db.Exec("CREATE TABLE a_table ( " + " [col_1] NVARCHAR(128) NOT NULL, " + " [col_2] NVARCHAR(128) NOT NULL, " + " PRIMARY KEY ([col_1], [col_2]) " + ")") - if err != nil { - t.Errorf("error creating table: %+v\n", err) - } + require.NoError(t, err) } func TestMSSQLServerWithCustomStrongPassword(t *testing.T) { ctx := context.Background() - container, err := mssql.Run(ctx, + ctr, err := mssql.Run(ctx, "mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04", mssql.WithAcceptEULA(), mssql.WithPassword("Strong@Passw0rd"), ) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions - connectionString, err := container.ConnectionString(ctx) - if err != nil { - t.Fatal(err) - } + connectionString, err := ctr.ConnectionString(ctx) + require.NoError(t, err) db, err := sql.Open("sqlserver", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) } // tests that a weak password is not accepted by the container due to Microsoft's password strength policy func TestMSSQLServerWithInvalidPassword(t *testing.T) { ctx := context.Background() - container, err := mssql.Run(ctx, + ctr, err := mssql.Run(ctx, "mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04", testcontainers.WithWaitStrategy( wait.ForLog("Password validation failed")), mssql.WithAcceptEULA(), mssql.WithPassword("weakPassword"), ) - - if err == nil { - t.Log("Success: Received invalid password validation docker log.") - } else { - t.Fatalf("Expected a password validation log but got error: %s", err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) } func TestMSSQLServerWithAlternativeImage(t *testing.T) { ctx := context.Background() - container, err := mssql.Run(ctx, + ctr, err := mssql.Run(ctx, "mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04", mssql.WithAcceptEULA(), ) - if err != nil { - t.Fatalf("Failed to create the container with alternative image: %s", err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions - connectionString, err := container.ConnectionString(ctx) - if err != nil { - t.Fatal(err) - } + connectionString, err := ctr.ConnectionString(ctx) + require.NoError(t, err) db, err := sql.Open("sqlserver", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) } diff --git a/modules/mysql/examples_test.go b/modules/mysql/examples_test.go index bf203c9018..61ee33113d 100644 --- a/modules/mysql/examples_test.go +++ b/modules/mysql/examples_test.go @@ -7,6 +7,7 @@ import ( "log" "path/filepath" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mysql" ) @@ -22,21 +23,21 @@ func ExampleRun() { mysql.WithPassword("password"), mysql.WithScripts(filepath.Join("testdata", "schema.sql")), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := mysqlContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(mysqlContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := mysqlContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -56,40 +57,45 @@ func ExampleRun_connect() { mysql.WithPassword("password"), mysql.WithScripts(filepath.Join("testdata", "schema.sql")), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := mysqlContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(mysqlContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } connectionString, err := mysqlContainer.ConnectionString(ctx) if err != nil { - log.Fatalf("failed to get connection string: %s", err) // nolint:gocritic + log.Printf("failed to get connection string: %s", err) + return } db, err := sql.Open("mysql", connectionString) if err != nil { - log.Fatalf("failed to connect to MySQL: %s", err) // nolint:gocritic + log.Printf("failed to connect to MySQL: %s", err) + return } defer db.Close() if err = db.Ping(); err != nil { - log.Fatalf("failed to ping MySQL: %s", err) + log.Printf("failed to ping MySQL: %s", err) + return } stmt, err := db.Prepare("SELECT @@GLOBAL.tmpdir") if err != nil { - log.Fatalf("failed to prepare statement: %s", err) + log.Printf("failed to prepare statement: %s", err) + return } defer stmt.Close() row := stmt.QueryRow() tmpDir := "" err = row.Scan(&tmpDir) if err != nil { - log.Fatalf("failed to scan row: %s", err) + log.Printf("failed to scan row: %s", err) + return } fmt.Println(tmpDir) diff --git a/modules/mysql/go.mod b/modules/mysql/go.mod index f3f00dcb8b..9e0da8e36a 100644 --- a/modules/mysql/go.mod +++ b/modules/mysql/go.mod @@ -4,7 +4,8 @@ go 1.22 require ( github.com/go-sql-driver/mysql v1.7.1 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) @@ -17,6 +18,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -28,6 +30,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -39,6 +42,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -55,6 +59,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/mysql/go.sum b/modules/mysql/go.sum index e2bb93b49d..dcc1a8d165 100644 --- a/modules/mysql/go.sum +++ b/modules/mysql/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -54,6 +55,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -80,6 +85,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -176,6 +183,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/mysql/mysql.go b/modules/mysql/mysql.go index 7bc6bf7e25..4eee6e654e 100644 --- a/modules/mysql/mysql.go +++ b/modules/mysql/mysql.go @@ -86,13 +86,21 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) - if err != nil { - return nil, err + var c *MySQLContainer + if container != nil { + c = &MySQLContainer{ + Container: container, + password: password, + username: username, + database: req.Env["MYSQL_DATABASE"], + } } - database := req.Env["MYSQL_DATABASE"] + if err != nil { + return c, fmt.Errorf("generic container: %w", err) + } - return &MySQLContainer{container, username, password, database}, nil + return c, nil } // MustConnectionString panics if the address cannot be determined. diff --git a/modules/mysql/mysql_test.go b/modules/mysql/mysql_test.go index e40ce9bf58..364f2a97a8 100644 --- a/modules/mysql/mysql_test.go +++ b/modules/mysql/mysql_test.go @@ -8,151 +8,110 @@ import ( // Import mysql into the scope of this package (required) _ "github.com/go-sql-driver/mysql" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/mysql" ) func TestMySQL(t *testing.T) { ctx := context.Background() - container, err := mysql.Run(ctx, "mysql:8.0.36") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := mysql.Run(ctx, "mysql:8.0.36") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions // connectionString { - connectionString, err := container.ConnectionString(ctx, "tls=skip-verify") + connectionString, err := ctr.ConnectionString(ctx, "tls=skip-verify") // } - if err != nil { - t.Fatal(err) - } - mustConnectionString := container.MustConnectionString(ctx, "tls=skip-verify") - if mustConnectionString != connectionString { - t.Errorf("ConnectionString was not equal to MustConnectionString") - } + require.NoError(t, err) + + mustConnectionString := ctr.MustConnectionString(ctx, "tls=skip-verify") + require.Equal(t, connectionString, mustConnectionString) db, err := sql.Open("mysql", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) + _, err = db.Exec("CREATE TABLE IF NOT EXISTS a_table ( \n" + " `col_1` VARCHAR(128) NOT NULL, \n" + " `col_2` VARCHAR(128) NOT NULL, \n" + " PRIMARY KEY (`col_1`, `col_2`) \n" + ")") - if err != nil { - t.Errorf("error creating table: %+v\n", err) - } + require.NoError(t, err) } func TestMySQLWithNonRootUserAndEmptyPassword(t *testing.T) { ctx := context.Background() - _, err := mysql.Run(ctx, + ctr, err := mysql.Run(ctx, "mysql:8.0.36", mysql.WithDatabase("foo"), mysql.WithUsername("test"), mysql.WithPassword("")) - if err.Error() != "empty password can be used only with the root user" { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.EqualError(t, err, "empty password can be used only with the root user") } func TestMySQLWithRootUserAndEmptyPassword(t *testing.T) { ctx := context.Background() - container, err := mysql.Run(ctx, + ctr, err := mysql.Run(ctx, "mysql:8.0.36", mysql.WithDatabase("foo"), mysql.WithUsername("root"), mysql.WithPassword("")) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions - connectionString, _ := container.ConnectionString(ctx) + connectionString, _ := ctr.ConnectionString(ctx) db, err := sql.Open("mysql", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) + _, err = db.Exec("CREATE TABLE IF NOT EXISTS a_table ( \n" + " `col_1` VARCHAR(128) NOT NULL, \n" + " `col_2` VARCHAR(128) NOT NULL, \n" + " PRIMARY KEY (`col_1`, `col_2`) \n" + ")") - if err != nil { - t.Errorf("error creating table: %+v\n", err) - } + require.NoError(t, err) } func TestMySQLWithScripts(t *testing.T) { ctx := context.Background() - container, err := mysql.Run(ctx, + ctr, err := mysql.Run(ctx, "mysql:8.0.36", mysql.WithScripts(filepath.Join("testdata", "schema.sql"))) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions - connectionString, _ := container.ConnectionString(ctx) + connectionString, _ := ctr.ConnectionString(ctx) db, err := sql.Open("mysql", connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if err = db.Ping(); err != nil { - t.Errorf("error pinging db: %+v\n", err) - } + err = db.Ping() + require.NoError(t, err) + stmt, err := db.Prepare("SELECT name from profile") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer stmt.Close() + row := stmt.QueryRow() var name string err = row.Scan(&name) - if err != nil { - t.Errorf("error fetching data") - } - if name != "profile 1" { - t.Fatal("The expected record was not found in the database.") - } + require.NoError(t, err) + require.Equal(t, "profile 1", name) } diff --git a/modules/nats/examples_test.go b/modules/nats/examples_test.go index 56ade42187..b88fba4c4a 100644 --- a/modules/nats/examples_test.go +++ b/modules/nats/examples_test.go @@ -8,6 +8,7 @@ import ( natsgo "github.com/nats-io/nats.go" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/nats" "github.com/testcontainers/testcontainers-go/network" ) @@ -17,21 +18,21 @@ func ExampleRun() { ctx := context.Background() natsContainer, err := nats.Run(ctx, "nats:2.9") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := natsContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(natsContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := natsContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -44,26 +45,27 @@ func ExampleRun_connectWithCredentials() { // natsConnect { ctx := context.Background() - container, err := nats.Run(ctx, "nats:2.9", nats.WithUsername("foo"), nats.WithPassword("bar")) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container + ctr, err := nats.Run(ctx, "nats:2.9", nats.WithUsername("foo"), nats.WithPassword("bar")) defer func() { - if err := container.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(ctr); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } - uri, err := container.ConnectionString(ctx) + uri, err := ctr.ConnectionString(ctx) if err != nil { - log.Fatalf("failed to get connection string: %s", err) // nolint:gocritic + log.Printf("failed to get connection string: %s", err) + return } - nc, err := natsgo.Connect(uri, natsgo.UserInfo(container.User, container.Password)) + nc, err := natsgo.Connect(uri, natsgo.UserInfo(ctr.User, ctr.Password)) if err != nil { - log.Fatalf("failed to connect to NATS: %s", err) + log.Printf("failed to connect to NATS: %s", err) + return } defer nc.Close() // } @@ -79,9 +81,16 @@ func ExampleRun_cluster() { nwr, err := network.New(ctx) if err != nil { - log.Fatalf("failed to create network: %s", err) + log.Printf("failed to create network: %s", err) + return } + defer func() { + if err := nwr.Remove(context.Background()); err != nil { + log.Printf("failed to remove network: %s", err) + } + }() + // withArguments { natsContainer1, err := nats.Run(ctx, "nats:2.9", @@ -93,15 +102,15 @@ func ExampleRun_cluster() { nats.WithArgument("http_port", "8222"), ) // } - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - // Clean up the container defer func() { - if err := natsContainer1.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(natsContainer1); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } natsContainer2, err := nats.Run(ctx, "nats:2.9", @@ -112,15 +121,15 @@ func ExampleRun_cluster() { nats.WithArgument("routes", "nats://nats1:6222,nats://nats2:6222,nats://nats3:6222"), nats.WithArgument("http_port", "8222"), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) // nolint:gocritic - } - // Clean up the container defer func() { - if err := natsContainer2.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(natsContainer2); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } natsContainer3, err := nats.Run(ctx, "nats:2.9", @@ -131,28 +140,34 @@ func ExampleRun_cluster() { nats.WithArgument("routes", "nats://nats1:6222,nats://nats2:6222,nats://nats3:6222"), nats.WithArgument("http_port", "8222"), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) // nolint:gocritic - } defer func() { - if err := natsContainer3.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(natsContainer3); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // cluster URL servers := natsContainer1.MustConnectionString(ctx) + "," + natsContainer2.MustConnectionString(ctx) + "," + natsContainer3.MustConnectionString(ctx) nc, err := natsgo.Connect(servers, natsgo.MaxReconnects(5), natsgo.ReconnectWait(2*time.Second)) if err != nil { - log.Fatalf("connecting to nats container failed:\n\t%v\n", err) // nolint:gocritic + log.Printf("connecting to nats container failed:\n\t%v\n", err) + return } + // Close connection + defer nc.Close() + { // Simple Publisher err = nc.Publish("foo", []byte("Hello World")) if err != nil { - log.Fatalf("failed to publish message: %s", err) // nolint:gocritic + log.Printf("failed to publish message: %s", err) + return } } @@ -161,13 +176,15 @@ func ExampleRun_cluster() { ch := make(chan *natsgo.Msg, 64) sub, err := nc.ChanSubscribe("channel", ch) if err != nil { - log.Fatalf("failed to subscribe to message: %s", err) // nolint:gocritic + log.Printf("failed to subscribe to message: %s", err) + return } // Request err = nc.Publish("channel", []byte("Hello NATS Cluster!")) if err != nil { - log.Fatalf("failed to publish message: %s", err) // nolint:gocritic + log.Printf("failed to publish message: %s", err) + return } msg := <-ch @@ -175,12 +192,14 @@ func ExampleRun_cluster() { err = sub.Unsubscribe() if err != nil { - log.Fatalf("failed to unsubscribe: %s", err) // nolint:gocritic + log.Printf("failed to unsubscribe: %s", err) + return } err = sub.Drain() if err != nil { - log.Fatalf("failed to drain: %s", err) // nolint:gocritic + log.Printf("failed to drain: %s", err) + return } } @@ -189,29 +208,34 @@ func ExampleRun_cluster() { sub, err := nc.Subscribe("request", func(m *natsgo.Msg) { err1 := m.Respond([]byte("answer is 42")) if err1 != nil { - log.Fatalf("failed to respond to message: %s", err1) // nolint:gocritic + log.Printf("failed to respond to message: %s", err1) + return } }) if err != nil { - log.Fatalf("failed to subscribe to message: %s", err) // nolint:gocritic + log.Printf("failed to subscribe to message: %s", err) + return } // Request msg, err := nc.Request("request", []byte("what is the answer?"), 1*time.Second) if err != nil { - log.Fatalf("failed to send request: %s", err) // nolint:gocritic + log.Printf("failed to send request: %s", err) + return } fmt.Println(string(msg.Data)) err = sub.Unsubscribe() if err != nil { - log.Fatalf("failed to unsubscribe: %s", err) // nolint:gocritic + log.Printf("failed to unsubscribe: %s", err) + return } err = sub.Drain() if err != nil { - log.Fatalf("failed to drain: %s", err) // nolint:gocritic + log.Printf("failed to drain: %s", err) + return } } @@ -219,12 +243,10 @@ func ExampleRun_cluster() { // Close() not needed if this is called. err = nc.Drain() if err != nil { - log.Fatalf("failed to drain connection: %s", err) // nolint:gocritic + log.Printf("failed to drain connection: %s", err) + return } - // Close connection - nc.Close() - // Output: // Hello NATS Cluster! // answer is 42 diff --git a/modules/nats/go.mod b/modules/nats/go.mod index 0a4863c41e..066f3d976f 100644 --- a/modules/nats/go.mod +++ b/modules/nats/go.mod @@ -4,7 +4,8 @@ go 1.22 require ( github.com/nats-io/nats.go v1.33.1 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -16,6 +17,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -27,6 +29,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -40,6 +43,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -56,6 +60,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/nats/go.sum b/modules/nats/go.sum index 61daa84ab4..ec68d27737 100644 --- a/modules/nats/go.sum +++ b/modules/nats/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -52,6 +53,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -84,6 +89,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -180,6 +187,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/nats/nats.go b/modules/nats/nats.go index 0ded01dd09..cd040c09e2 100644 --- a/modules/nats/nats.go +++ b/modules/nats/nats.go @@ -59,17 +59,20 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) - if err != nil { - return nil, err + var c *NATSContainer + if container != nil { + c = &NATSContainer{ + Container: container, + User: settings.CmdArgs["user"], + Password: settings.CmdArgs["pass"], + } } - natsContainer := NATSContainer{ - Container: container, - User: settings.CmdArgs["user"], - Password: settings.CmdArgs["pass"], + if err != nil { + return c, fmt.Errorf("generic container: %w", err) } - return &natsContainer, nil + return c, nil } func (c *NATSContainer) MustConnectionString(ctx context.Context, args ...string) string { diff --git a/modules/nats/nats_test.go b/modules/nats/nats_test.go index e223f0aa24..660473c2e5 100644 --- a/modules/nats/nats_test.go +++ b/modules/nats/nats_test.go @@ -5,7 +5,9 @@ import ( "testing" "github.com/nats-io/nats.go" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" tcnats "github.com/testcontainers/testcontainers-go/modules/nats" ) @@ -13,67 +15,45 @@ func TestNATS(t *testing.T) { ctx := context.Background() // createNATSContainer { - container, err := tcnats.Run(ctx, "nats:2.9") + ctr, err := tcnats.Run(ctx, "nats:2.9") // } - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // connectionString { - uri, err := container.ConnectionString(ctx) + uri, err := ctr.ConnectionString(ctx) // } - if err != nil { - t.Fatalf("failed to get connection string: %s", err) - } - mustUri := container.MustConnectionString(ctx) - if mustUri != uri { - t.Errorf("URI was not equal to MustUri") - } + require.NoError(t, err) + + mustUri := ctr.MustConnectionString(ctx) + require.Equal(t, mustUri, uri) + // perform assertions nc, err := nats.Connect(uri) - if err != nil { - t.Fatalf("failed to connect to nats: %s", err) - } + require.NoError(t, err) defer nc.Close() js, err := nc.JetStream() - if err != nil { - t.Fatalf("failed to create jetstream context: %s", err) - } + require.NoError(t, err) // add stream to nats - if _, err = js.AddStream(&nats.StreamConfig{ + _, err = js.AddStream(&nats.StreamConfig{ Name: "hello", Subjects: []string{"hello"}, - }); err != nil { - t.Fatalf("failed to add stream: %s", err) - } + }) + require.NoError(t, err) // add subscriber to nats sub, err := js.SubscribeSync("hello", nats.Durable("worker")) - if err != nil { - t.Fatalf("failed to subscribe to hello: %s", err) - } + require.NoError(t, err) // publish a message to nats - if _, err = js.Publish("hello", []byte("hello")); err != nil { - t.Fatalf("failed to publish hello: %s", err) - } + _, err = js.Publish("hello", []byte("hello")) + require.NoError(t, err) // wait for the message to be received msg, err := sub.NextMsgWithContext(ctx) - if err != nil { - t.Fatalf("failed to get message: %s", err) - } + require.NoError(t, err) - if string(msg.Data) != "hello" { - t.Fatalf("expected message to be 'hello', got '%s'", msg.Data) - } + require.Equal(t, "hello", string(msg.Data)) } diff --git a/modules/neo4j/examples_test.go b/modules/neo4j/examples_test.go index 375184a1d6..6e8c42936a 100644 --- a/modules/neo4j/examples_test.go +++ b/modules/neo4j/examples_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/neo4j" ) @@ -20,21 +21,21 @@ func ExampleRun() { neo4j.WithLabsPlugin(neo4j.Apoc), neo4j.WithNeo4jSetting("dbms.tx_log.rotation.size", "42M"), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := neo4jContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(neo4jContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := neo4jContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/neo4j/go.mod b/modules/neo4j/go.mod index 13f310eeb5..50da4a55d4 100644 --- a/modules/neo4j/go.mod +++ b/modules/neo4j/go.mod @@ -5,7 +5,8 @@ go 1.22 require ( github.com/docker/go-connections v0.5.0 github.com/neo4j/neo4j-go-driver/v5 v5.18.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -17,6 +18,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect @@ -27,6 +29,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -38,6 +41,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -54,6 +58,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/neo4j/go.sum b/modules/neo4j/go.sum index 8cccf1cd87..54b5d9c6d5 100644 --- a/modules/neo4j/go.sum +++ b/modules/neo4j/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -52,6 +53,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -80,6 +85,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -176,6 +183,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/neo4j/neo4j.go b/modules/neo4j/neo4j.go index e4f7fc3314..36cac5e4be 100644 --- a/modules/neo4j/neo4j.go +++ b/modules/neo4j/neo4j.go @@ -93,11 +93,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *Neo4jContainer + if container != nil { + c = &Neo4jContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &Neo4jContainer{Container: container}, nil + return c, nil } func isHttpOk() func(status int) bool { diff --git a/modules/neo4j/neo4j_test.go b/modules/neo4j/neo4j_test.go index 20bd17188b..466bd3ddf7 100644 --- a/modules/neo4j/neo4j_test.go +++ b/modules/neo4j/neo4j_test.go @@ -8,7 +8,9 @@ import ( "testing" neo "github.com/neo4j/neo4j-go-driver/v5/neo4j" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/neo4j" ) @@ -19,16 +21,12 @@ func TestNeo4j(outer *testing.T) { ctx := context.Background() - container := setupNeo4j(ctx, outer) - - outer.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - outer.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := setupNeo4j(ctx) + testcontainers.CleanupContainer(outer, ctr) + require.NoError(outer, err) outer.Run("connects via Bolt", func(t *testing.T) { - driver := createDriver(t, ctx, container) + driver := createDriver(t, ctx, ctr) err := driver.VerifyConnectivity(ctx) if err != nil { @@ -37,7 +35,7 @@ func TestNeo4j(outer *testing.T) { }) outer.Run("exercises APOC plugin", func(t *testing.T) { - driver := createDriver(t, ctx, container) + driver := createDriver(t, ctx, ctr) result, err := neo.ExecuteQuery(ctx, driver, "RETURN apoc.number.arabicToRoman(1986) AS output", nil, @@ -51,7 +49,7 @@ func TestNeo4j(outer *testing.T) { }) outer.Run("is configured with custom Neo4j settings", func(t *testing.T) { - env := getContainerEnv(t, ctx, container) + env := getContainerEnv(t, ctx, ctr) if !strings.Contains(env, "NEO4J_dbms_tx__log_rotation_size=42M") { t.Fatal("expected to custom setting to be exported but was not") @@ -73,22 +71,15 @@ func TestNeo4jWithEnterpriseLicense(t *testing.T) { edition, img := edition, img t.Run(edition, func(t *testing.T) { t.Parallel() - container, err := neo4j.Run(ctx, + ctr, err := neo4j.Run(ctx, img, neo4j.WithAdminPassword(testPassword), neo4j.WithAcceptCommercialLicenseAgreement(), ) - if err != nil { - t.Fatalf("expected container to successfully initialize but did not: %s", err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - - env := getContainerEnv(t, ctx, container) + env := getContainerEnv(t, ctx, ctr) if !strings.Contains(env, "NEO4J_ACCEPT_LICENSE_AGREEMENT=yes") { t.Fatal("expected to accept license agreement but did not") @@ -103,27 +94,22 @@ func TestNeo4jWithWrongSettings(outer *testing.T) { ctx := context.Background() outer.Run("without authentication", func(t *testing.T) { - container, err := neo4j.Run(ctx, "neo4j:4.4") - if err != nil { - t.Fatalf("expected env to successfully run but did not: %s", err) - } - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - outer.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := neo4j.Run(ctx, "neo4j:4.4") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) }) outer.Run("auth setting outside WithAdminPassword raises error", func(t *testing.T) { - container, err := neo4j.Run(ctx, + ctr, err := neo4j.Run(ctx, "neo4j:4.4", neo4j.WithAdminPassword(testPassword), neo4j.WithNeo4jSetting("AUTH", "neo4j/thisisgonnafail"), ) + testcontainers.CleanupContainer(t, ctr) if err == nil { t.Fatalf("expected env to fail due to conflicting auth settings but did not") } - if container != nil { + if ctr != nil { t.Fatalf("container must not be created with conflicting auth settings") } }) @@ -131,7 +117,7 @@ func TestNeo4jWithWrongSettings(outer *testing.T) { outer.Run("warns about overwrites of setting keys", func(t *testing.T) { // withSettings { logger := &inMemoryLogger{} - container, err := neo4j.Run(ctx, + ctr, err := neo4j.Run(ctx, "neo4j:4.4", neo4j.WithLogger(logger), // needs to go before WithNeo4jSetting and WithNeo4jSettings neo4j.WithAdminPassword(testPassword), @@ -140,29 +126,23 @@ func TestNeo4jWithWrongSettings(outer *testing.T) { neo4j.WithNeo4jSetting("some.key", "value3"), ) // } - if err != nil { - t.Fatalf("expected env to successfully run but did not: %s", err) - } - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - outer.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) errorLogs := logger.Logs() if !Contains(errorLogs, `setting "some.key" with value "value1" is now overwritten with value "value2"`+"\n") || !Contains(errorLogs, `setting "some.key" with value "value2" is now overwritten with value "value3"`+"\n") { t.Fatalf("expected setting overwrites to be logged") } - if !strings.Contains(getContainerEnv(t, ctx, container), "NEO4J_some_key=value3") { + if !strings.Contains(getContainerEnv(t, ctx, ctr), "NEO4J_some_key=value3") { t.Fatalf("expected custom setting to be set with last value") } }) outer.Run("rejects nil logger", func(t *testing.T) { - container, err := neo4j.Run(ctx, "neo4j:4.4", neo4j.WithLogger(nil)) - - if container != nil { + ctr, err := neo4j.Run(ctx, "neo4j:4.4", neo4j.WithLogger(nil)) + testcontainers.CleanupContainer(t, ctr) + if ctr != nil { t.Fatalf("container must not be created with nil logger") } if err == nil || err.Error() != "nil logger is not permitted" { @@ -171,8 +151,8 @@ func TestNeo4jWithWrongSettings(outer *testing.T) { }) } -func setupNeo4j(ctx context.Context, t *testing.T) *neo4j.Neo4jContainer { - container, err := neo4j.Run(ctx, +func setupNeo4j(ctx context.Context) (*neo4j.Neo4jContainer, error) { + return neo4j.Run(ctx, "neo4j:4.4", neo4j.WithAdminPassword(testPassword), // withLabsPlugin { @@ -180,10 +160,6 @@ func setupNeo4j(ctx context.Context, t *testing.T) *neo4j.Neo4jContainer { // } neo4j.WithNeo4jSetting("dbms.tx_log.rotation.size", "42M"), ) - if err != nil { - t.Fatalf("expected container to successfully initialize but did not: %s", err) - } - return container } func createDriver(t *testing.T, ctx context.Context, container *neo4j.Neo4jContainer) neo.DriverWithContext { diff --git a/modules/ollama/examples_test.go b/modules/ollama/examples_test.go index 3e2a273854..46d65ebe0a 100644 --- a/modules/ollama/examples_test.go +++ b/modules/ollama/examples_test.go @@ -10,6 +10,7 @@ import ( "github.com/tmc/langchaingo/llms" langchainollama "github.com/tmc/langchaingo/llms/ollama" + "github.com/testcontainers/testcontainers-go" tcollama "github.com/testcontainers/testcontainers-go/modules/ollama" ) @@ -18,21 +19,21 @@ func ExampleRun() { ctx := context.Background() ollamaContainer, err := tcollama.Run(ctx, "ollama/ollama:0.1.25") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := ollamaContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(ollamaContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := ollamaContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -46,30 +47,34 @@ func ExampleRun_withModel_llama2_http() { ctx := context.Background() ollamaContainer, err := tcollama.Run(ctx, "ollama/ollama:0.1.25") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } defer func() { - if err := ollamaContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(ollamaContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } model := "llama2" _, _, err = ollamaContainer.Exec(ctx, []string{"ollama", "pull", model}) if err != nil { - log.Fatalf("failed to pull model %s: %s", model, err) // nolint:gocritic + log.Printf("failed to pull model %s: %s", model, err) + return } _, _, err = ollamaContainer.Exec(ctx, []string{"ollama", "run", model}) if err != nil { - log.Fatalf("failed to run model %s: %s", model, err) // nolint:gocritic + log.Printf("failed to run model %s: %s", model, err) + return } connectionStr, err := ollamaContainer.ConnectionString(ctx) if err != nil { - log.Fatalf("failed to get connection string: %s", err) // nolint:gocritic + log.Printf("failed to get connection string: %s", err) + return } httpClient := &http.Client{} @@ -82,12 +87,14 @@ func ExampleRun_withModel_llama2_http() { req, err := http.NewRequest("POST", fmt.Sprintf("%s/api/generate", connectionStr), strings.NewReader(payload)) if err != nil { - log.Fatalf("failed to create request: %s", err) // nolint:gocritic + log.Printf("failed to create request: %s", err) + return } resp, err := httpClient.Do(req) if err != nil { - log.Fatalf("failed to get response: %s", err) // nolint:gocritic + log.Printf("failed to get response: %s", err) + return } // } @@ -101,30 +108,34 @@ func ExampleRun_withModel_llama2_langchain() { ctx := context.Background() ollamaContainer, err := tcollama.Run(ctx, "ollama/ollama:0.1.25") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } defer func() { - if err := ollamaContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(ollamaContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } model := "llama2" _, _, err = ollamaContainer.Exec(ctx, []string{"ollama", "pull", model}) if err != nil { - log.Fatalf("failed to pull model %s: %s", model, err) // nolint:gocritic + log.Printf("failed to pull model %s: %s", model, err) + return } _, _, err = ollamaContainer.Exec(ctx, []string{"ollama", "run", model}) if err != nil { - log.Fatalf("failed to run model %s: %s", model, err) // nolint:gocritic + log.Printf("failed to run model %s: %s", model, err) + return } connectionStr, err := ollamaContainer.ConnectionString(ctx) if err != nil { - log.Fatalf("failed to get connection string: %s", err) // nolint:gocritic + log.Printf("failed to get connection string: %s", err) + return } var llm *langchainollama.LLM @@ -132,7 +143,8 @@ func ExampleRun_withModel_llama2_langchain() { langchainollama.WithModel(model), langchainollama.WithServerURL(connectionStr), ); err != nil { - log.Fatalf("failed to create langchain ollama: %s", err) // nolint:gocritic + log.Printf("failed to create langchain ollama: %s", err) + return } completion, err := llm.Call( @@ -142,7 +154,8 @@ func ExampleRun_withModel_llama2_langchain() { llms.WithTemperature(0.0), // the lower the temperature, the more creative the completion ) if err != nil { - log.Fatalf("failed to create langchain ollama: %s", err) // nolint:gocritic + log.Printf("failed to create langchain ollama: %s", err) + return } words := []string{ diff --git a/modules/ollama/go.mod b/modules/ollama/go.mod index 5e586e858e..b338de0b0d 100644 --- a/modules/ollama/go.mod +++ b/modules/ollama/go.mod @@ -5,7 +5,8 @@ go 1.22 require ( github.com/docker/docker v27.1.1+incompatible github.com/google/uuid v1.6.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 github.com/tmc/langchaingo v0.1.5 ) @@ -18,6 +19,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/dlclark/regexp2 v1.8.1 // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -40,6 +42,7 @@ require ( github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pkoukk/tiktoken-go v0.1.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -56,6 +59,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/ollama/go.sum b/modules/ollama/go.sum index d2ff261f5b..9e9bf8b2c1 100644 --- a/modules/ollama/go.sum +++ b/modules/ollama/go.sum @@ -54,6 +54,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -82,6 +86,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -180,6 +186,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/ollama/ollama.go b/modules/ollama/ollama.go index b8a2fc1de6..203d80103f 100644 --- a/modules/ollama/ollama.go +++ b/modules/ollama/ollama.go @@ -101,9 +101,14 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *OllamaContainer + if container != nil { + c = &OllamaContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &OllamaContainer{Container: container}, nil + return c, nil } diff --git a/modules/ollama/ollama_test.go b/modules/ollama/ollama_test.go index b60538835b..0f6614a51e 100644 --- a/modules/ollama/ollama_test.go +++ b/modules/ollama/ollama_test.go @@ -4,13 +4,14 @@ import ( "context" "fmt" "io" - "log" "net/http" "strings" "testing" "github.com/google/uuid" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/exec" "github.com/testcontainers/testcontainers-go/modules/ollama" ) @@ -18,52 +19,34 @@ import ( func TestOllama(t *testing.T) { ctx := context.Background() - container, err := ollama.Run(ctx, "ollama/ollama:0.1.25") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := ollama.Run(ctx, "ollama/ollama:0.1.25") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) t.Run("ConnectionString", func(t *testing.T) { // connectionString { - connectionStr, err := container.ConnectionString(ctx) + connectionStr, err := ctr.ConnectionString(ctx) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) httpClient := &http.Client{} resp, err := httpClient.Get(connectionStr) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Fatalf("expected status code 200, got %d", resp.StatusCode) - } + require.Equal(t, http.StatusOK, resp.StatusCode) }) t.Run("Pull and Run Model", func(t *testing.T) { model := "all-minilm" - _, _, err = container.Exec(context.Background(), []string{"ollama", "pull", model}) - if err != nil { - log.Fatalf("failed to pull model %s: %s", model, err) - } + _, _, err = ctr.Exec(context.Background(), []string{"ollama", "pull", model}) + require.NoError(t, err) - _, _, err = container.Exec(context.Background(), []string{"ollama", "run", model}) - if err != nil { - log.Fatalf("failed to run model %s: %s", model, err) - } + _, _, err = ctr.Exec(context.Background(), []string{"ollama", "run", model}) + require.NoError(t, err) - assertLoadedModel(t, container) + assertLoadedModel(t, ctr) }) t.Run("Commit to image including model", func(t *testing.T) { @@ -73,24 +56,16 @@ func TestOllama(t *testing.T) { // Users can change the way this is generated, but it should be unique. targetImage := fmt.Sprintf("%s-%s", ollama.DefaultOllamaImage, strings.ToLower(uuid.New().String()[:4])) - err := container.Commit(context.Background(), targetImage) + err := ctr.Commit(context.Background(), targetImage) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) newOllamaContainer, err := ollama.Run( context.Background(), targetImage, ) - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { - if err := newOllamaContainer.Terminate(context.Background()); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, newOllamaContainer) + require.NoError(t, err) assertLoadedModel(t, newOllamaContainer) }) @@ -101,30 +76,20 @@ func TestOllama(t *testing.T) { // contains the model name. func assertLoadedModel(t *testing.T, c *ollama.OllamaContainer) { url, err := c.ConnectionString(context.Background()) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) httpCli := &http.Client{} resp, err := httpCli.Get(url + "/api/tags") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Fatalf("expected status code 200, got %d", resp.StatusCode) - } + require.Equal(t, http.StatusOK, resp.StatusCode) bs, err := io.ReadAll(resp.Body) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) - if !strings.Contains(string(bs), "all-minilm") { - t.Fatalf("expected response to contain all-minilm, got %s", string(bs)) - } + require.Contains(t, string(bs), "all-minilm") } func TestRunContainer_withModel_error(t *testing.T) { @@ -134,30 +99,21 @@ func TestRunContainer_withModel_error(t *testing.T) { ctx, "ollama/ollama:0.1.25", ) - if err != nil { - t.Fatalf("expected error to be nil, got %s", err) - } + testcontainers.CleanupContainer(t, ollamaContainer) + require.NoError(t, err) model := "non-existent" _, _, err = ollamaContainer.Exec(ctx, []string{"ollama", "pull", model}) - if err != nil { - log.Fatalf("expected nil error, got %s", err) - } + require.NoError(t, err) // we need to parse the response here to check if the error message is correct _, r, err := ollamaContainer.Exec(ctx, []string{"ollama", "run", model}, exec.Multiplexed()) - if err != nil { - log.Fatalf("expected nil error, got %s", err) - } + require.NoError(t, err) bs, err := io.ReadAll(r) - if err != nil { - t.Fatalf("failed to run %s model: %s", model, err) - } + require.NoError(t, err) stdOutput := string(bs) - if !strings.Contains(stdOutput, "Error: pull model manifest: file does not exist") { - t.Fatalf("expected output to contain %q, got %s", "Error: pull model manifest: file does not exist", stdOutput) - } + require.Contains(t, stdOutput, "Error: pull model manifest: file does not exist") } diff --git a/modules/openfga/examples_test.go b/modules/openfga/examples_test.go index 38609451ef..cb0443b863 100644 --- a/modules/openfga/examples_test.go +++ b/modules/openfga/examples_test.go @@ -22,21 +22,21 @@ func ExampleRun() { ctx := context.Background() openfgaContainer, err := openfga.Run(ctx, "openfga/openfga:v1.5.0") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := openfgaContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(openfgaContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := openfgaContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -47,21 +47,21 @@ func ExampleRun() { func ExampleRun_connectToPlayground() { openfgaContainer, err := openfga.Run(context.Background(), "openfga/openfga:v1.5.0") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := openfgaContainer.Terminate(context.Background()); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(openfgaContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // playgroundEndpoint { playgroundEndpoint, err := openfgaContainer.PlaygroundEndpoint(context.Background()) if err != nil { - log.Fatalf("failed to get playground endpoint: %s", err) // nolint:gocritic + log.Printf("failed to get playground endpoint: %s", err) + return } // } @@ -69,7 +69,8 @@ func ExampleRun_connectToPlayground() { resp, err := httpClient.Get(playgroundEndpoint) if err != nil { - log.Fatalf("failed to get playground endpoint: %s", err) // nolint:gocritic + log.Printf("failed to get playground endpoint: %s", err) + return } fmt.Println(resp.StatusCode) @@ -80,21 +81,21 @@ func ExampleRun_connectToPlayground() { func ExampleRun_connectWithSDKClient() { openfgaContainer, err := openfga.Run(context.Background(), "openfga/openfga:v1.5.0") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := openfgaContainer.Terminate(context.Background()); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(openfgaContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // httpEndpoint { httpEndpoint, err := openfgaContainer.HttpEndpoint(context.Background()) if err != nil { - log.Fatalf("failed to get HTTP endpoint: %s", err) // nolint:gocritic + log.Printf("failed to get HTTP endpoint: %s", err) + return } // } @@ -103,26 +104,30 @@ func ExampleRun_connectWithSDKClient() { ApiUrl: httpEndpoint, // required }) if err != nil { - log.Fatalf("failed to create SDK client: %s", err) // nolint:gocritic + log.Printf("failed to create SDK client: %s", err) + return } list, err := fgaClient.ListStores(context.Background()).Execute() if err != nil { - log.Fatalf("failed to list stores: %s", err) // nolint:gocritic + log.Printf("failed to list stores: %s", err) + return } fmt.Println(len(list.Stores)) store, err := fgaClient.CreateStore(context.Background()).Body(client.ClientCreateStoreRequest{Name: "test"}).Execute() if err != nil { - log.Fatalf("failed to create store: %s", err) // nolint:gocritic + log.Printf("failed to create store: %s", err) + return } fmt.Println(store.Name) list, err = fgaClient.ListStores(context.Background()).Execute() if err != nil { - log.Fatalf("failed to list stores: %s", err) // nolint:gocritic + log.Printf("failed to list stores: %s", err) + return } fmt.Println(len(list.Stores)) @@ -145,20 +150,20 @@ func ExampleRun_writeModel() { "OPENFGA_AUTHN_PRESHARED_KEYS": secret, }), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := openfgaContainer.Terminate(context.Background()); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(openfgaContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } httpEndpoint, err := openfgaContainer.HttpEndpoint(context.Background()) if err != nil { - log.Fatalf("failed to get HTTP endpoint: %s", err) // nolint:gocritic + log.Printf("failed to get HTTP endpoint: %s", err) + return } fgaClient, err := client.NewSdkClient(&client.ClientConfiguration{ @@ -177,28 +182,33 @@ func ExampleRun_writeModel() { StoreId: "11111111111111111111111111", }) if err != nil { - log.Fatalf("failed to create openfga client: %v", err) + log.Printf("failed to create openfga client: %v", err) + return } f, err := os.Open(filepath.Join("testdata", "authorization_model.json")) if err != nil { - log.Fatalf("failed to open file: %v", err) + log.Printf("failed to open file: %v", err) + return } defer f.Close() bs, err := io.ReadAll(f) if err != nil { - log.Fatalf("failed to read file: %v", err) + log.Printf("failed to read file: %v", err) + return } var body client.ClientWriteAuthorizationModelRequest if err := json.Unmarshal(bs, &body); err != nil { - log.Fatalf("failed to unmarshal json: %v", err) + log.Printf("failed to unmarshal json: %v", err) + return } resp, err := fgaClient.WriteAuthorizationModel(context.Background()).Body(body).Execute() if err != nil { - log.Fatalf("failed to write authorization model: %v", err) + log.Printf("failed to write authorization model: %v", err) + return } // } diff --git a/modules/openfga/go.mod b/modules/openfga/go.mod index 388b9c040c..3f5a238a82 100644 --- a/modules/openfga/go.mod +++ b/modules/openfga/go.mod @@ -4,7 +4,8 @@ go 1.22 require ( github.com/openfga/go-sdk v0.3.5 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -16,6 +17,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -27,6 +29,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -38,6 +41,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -55,6 +59,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/openfga/go.sum b/modules/openfga/go.sum index 1ab48ebfe2..a24767f45f 100644 --- a/modules/openfga/go.sum +++ b/modules/openfga/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -54,6 +55,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -82,6 +87,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -180,6 +187,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/openfga/openfga.go b/modules/openfga/openfga.go index ccdaab71cb..d6a3930a1d 100644 --- a/modules/openfga/openfga.go +++ b/modules/openfga/openfga.go @@ -78,9 +78,14 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *OpenFGAContainer + if container != nil { + c = &OpenFGAContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &OpenFGAContainer{Container: container}, nil + return c, nil } diff --git a/modules/openfga/openfga_test.go b/modules/openfga/openfga_test.go index ec0a16bf1b..85e1966198 100644 --- a/modules/openfga/openfga_test.go +++ b/modules/openfga/openfga_test.go @@ -4,23 +4,18 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/openfga" ) func TestOpenFGA(t *testing.T) { ctx := context.Background() - container, err := openfga.Run(ctx, "openfga/openfga:v1.5.0") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := openfga.Run(ctx, "openfga/openfga:v1.5.0") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // perform assertions } diff --git a/modules/openldap/examples_test.go b/modules/openldap/examples_test.go index f3bf2f40f5..757385cc92 100644 --- a/modules/openldap/examples_test.go +++ b/modules/openldap/examples_test.go @@ -7,6 +7,7 @@ import ( "github.com/go-ldap/ldap/v3" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/openldap" ) @@ -15,21 +16,21 @@ func ExampleRun() { ctx := context.Background() openldapContainer, err := openldap.Run(ctx, "bitnami/openldap:2.6.6") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := openldapContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(openldapContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := openldapContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -43,32 +44,34 @@ func ExampleRun_connect() { ctx := context.Background() openldapContainer, err := openldap.Run(ctx, "bitnami/openldap:2.6.6") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := openldapContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(openldapContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } connectionString, err := openldapContainer.ConnectionString(ctx) if err != nil { - log.Fatalf("failed to get connection string: %s", err) // nolint:gocritic + log.Printf("failed to get connection string: %s", err) + return } client, err := ldap.DialURL(connectionString) if err != nil { - log.Fatalf("failed to connect to LDAP server: %s", err) + log.Printf("failed to connect to LDAP server: %s", err) + return } defer client.Close() // First bind with a read only user err = client.Bind("cn=admin,dc=example,dc=org", "adminpassword") if err != nil { - log.Fatalf("failed to bind to LDAP server: %s", err) + log.Printf("failed to bind to LDAP server: %s", err) + return } // Search for the given username @@ -82,11 +85,13 @@ func ExampleRun_connect() { sr, err := client.Search(searchRequest) if err != nil { - log.Fatalf("failed to search LDAP server: %s", err) + log.Printf("failed to search LDAP server: %s", err) + return } if len(sr.Entries) != 1 { - log.Fatal("User does not exist or too many entries returned") + log.Print("User does not exist or too many entries returned") + return } fmt.Println(sr.Entries[0].DN) diff --git a/modules/openldap/go.mod b/modules/openldap/go.mod index 2f13ed78cc..e096880ed6 100644 --- a/modules/openldap/go.mod +++ b/modules/openldap/go.mod @@ -4,7 +4,8 @@ go 1.22 require ( github.com/go-ldap/ldap/v3 v3.4.6 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -17,6 +18,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -29,6 +31,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -40,6 +43,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -56,6 +60,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/openldap/go.sum b/modules/openldap/go.sum index eb7f8b79e3..0723cad762 100644 --- a/modules/openldap/go.sum +++ b/modules/openldap/go.sum @@ -20,6 +20,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -61,6 +62,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -87,6 +92,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -211,6 +218,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/openldap/openldap.go b/modules/openldap/openldap.go index dc215226c1..940897f4dd 100644 --- a/modules/openldap/openldap.go +++ b/modules/openldap/openldap.go @@ -161,14 +161,19 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *OpenLDAPContainer + if container != nil { + c = &OpenLDAPContainer{ + Container: container, + adminUsername: req.Env["LDAP_ADMIN_USERNAME"], + adminPassword: req.Env["LDAP_ADMIN_PASSWORD"], + rootDn: req.Env["LDAP_ROOT"], + } + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &OpenLDAPContainer{ - Container: container, - adminUsername: req.Env["LDAP_ADMIN_USERNAME"], - adminPassword: req.Env["LDAP_ADMIN_PASSWORD"], - rootDn: req.Env["LDAP_ROOT"], - }, nil + return c, nil } diff --git a/modules/openldap/openldap_test.go b/modules/openldap/openldap_test.go index 40639b9932..b73a8dce36 100644 --- a/modules/openldap/openldap_test.go +++ b/modules/openldap/openldap_test.go @@ -6,112 +6,70 @@ import ( "testing" "github.com/go-ldap/ldap/v3" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/openldap" ) func TestOpenLDAP(t *testing.T) { ctx := context.Background() - container, err := openldap.Run(ctx, "bitnami/openldap:2.6.6") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := openldap.Run(ctx, "bitnami/openldap:2.6.6") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) } func TestOpenLDAPWithAdminUsernameAndPassword(t *testing.T) { ctx := context.Background() - container, err := openldap.Run(ctx, + ctr, err := openldap.Run(ctx, "bitnami/openldap:2.6.6", openldap.WithAdminUsername("openldap"), openldap.WithAdminPassword("openldap"), ) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - connectionString, err := container.ConnectionString(ctx) - if err != nil { - t.Fatal(err) - } + connectionString, err := ctr.ConnectionString(ctx) + require.NoError(t, err) client, err := ldap.DialURL(connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer client.Close() // First bind with a read only user err = client.Bind("cn=openldap,dc=example,dc=org", "openldap") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } func TestOpenLDAPWithDifferentRoot(t *testing.T) { ctx := context.Background() - container, err := openldap.Run(ctx, "bitnami/openldap:2.6.6", openldap.WithRoot("dc=mydomain,dc=com")) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := openldap.Run(ctx, "bitnami/openldap:2.6.6", openldap.WithRoot("dc=mydomain,dc=com")) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // connectionString { - connectionString, err := container.ConnectionString(ctx) + connectionString, err := ctr.ConnectionString(ctx) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) client, err := ldap.DialURL(connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer client.Close() // First bind with a read only user err = client.Bind("cn=admin,dc=mydomain,dc=com", "adminpassword") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } func TestOpenLDAPLoadLdif(t *testing.T) { ctx := context.Background() - container, err := openldap.Run(ctx, "bitnami/openldap:2.6.6") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := openldap.Run(ctx, "bitnami/openldap:2.6.6") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // loadLdif { ldif := ` @@ -124,28 +82,20 @@ mail: test.user@example.org userPassword: Password1 ` - err = container.LoadLdif(ctx, []byte(ldif)) + err = ctr.LoadLdif(ctx, []byte(ldif)) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) - connectionString, err := container.ConnectionString(ctx) - if err != nil { - t.Fatal(err) - } + connectionString, err := ctr.ConnectionString(ctx) + require.NoError(t, err) client, err := ldap.DialURL(connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer client.Close() // First bind with a read only user err = client.Bind("cn=admin,dc=example,dc=org", "adminpassword") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) result, err := client.Search(&ldap.SearchRequest{ BaseDN: "uid=test.user,ou=users,dc=example,dc=org", @@ -153,16 +103,9 @@ userPassword: Password1 Filter: "(objectClass=*)", Attributes: []string{"dn"}, }) - if err != nil { - t.Fatal(err) - } - - if len(result.Entries) != 1 { - t.Fatal("Invalid number of entries returned", result.Entries) - } - if result.Entries[0].DN != "uid=test.user,ou=users,dc=example,dc=org" { - t.Fatal("Invalid entry returned", result.Entries[0].DN) - } + require.NoError(t, err) + require.Len(t, result.Entries, 1) + require.Equal(t, "uid=test.user,ou=users,dc=example,dc=org", result.Entries[0].DN) } func TestOpenLDAPWithInitialLdif(t *testing.T) { @@ -178,47 +121,28 @@ userPassword: Password1 ` f, err := os.CreateTemp(t.TempDir(), "test.ldif") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) _, err = f.WriteString(ldif) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + err = f.Close() - if err != nil { - t.Fatal(err) - } - - container, err := openldap.Run(ctx, "bitnami/openldap:2.6.6", openldap.WithInitialLdif(f.Name())) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + require.NoError(t, err) - connectionString, err := container.ConnectionString(ctx) - if err != nil { - t.Fatal(err) - } + ctr, err := openldap.Run(ctx, "bitnami/openldap:2.6.6", openldap.WithInitialLdif(f.Name())) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + connectionString, err := ctr.ConnectionString(ctx) + require.NoError(t, err) client, err := ldap.DialURL(connectionString) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer client.Close() // First bind with a read only user err = client.Bind("cn=admin,dc=example,dc=org", "adminpassword") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) result, err := client.Search(&ldap.SearchRequest{ BaseDN: "uid=test.user,ou=users,dc=example,dc=org", @@ -226,14 +150,8 @@ userPassword: Password1 Filter: "(objectClass=*)", Attributes: []string{"dn"}, }) - if err != nil { - t.Fatal(err) - } - - if len(result.Entries) != 1 { - t.Fatal("Invalid number of entries returned", result.Entries) - } - if result.Entries[0].DN != "uid=test.user,ou=users,dc=example,dc=org" { - t.Fatal("Invalid entry returned", result.Entries[0].DN) - } + require.NoError(t, err) + + require.Len(t, result.Entries, 1) + require.Equal(t, "uid=test.user,ou=users,dc=example,dc=org", result.Entries[0].DN) } diff --git a/modules/opensearch/examples_test.go b/modules/opensearch/examples_test.go index 89bc9cb7c6..d2e4c5807d 100644 --- a/modules/opensearch/examples_test.go +++ b/modules/opensearch/examples_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/opensearch" ) @@ -18,21 +19,21 @@ func ExampleRun() { opensearch.WithUsername("new-username"), opensearch.WithPassword("new-password"), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := opensearchContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(opensearchContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := opensearchContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/opensearch/go.mod b/modules/opensearch/go.mod index 50146f5964..7fe56f884b 100644 --- a/modules/opensearch/go.mod +++ b/modules/opensearch/go.mod @@ -5,7 +5,8 @@ go 1.22 require ( github.com/docker/docker v27.1.1+incompatible github.com/docker/go-units v0.5.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -17,6 +18,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect @@ -26,6 +28,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -37,6 +40,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -53,6 +57,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/opensearch/go.sum b/modules/opensearch/go.sum index ed514ea5ef..28367d0020 100644 --- a/modules/opensearch/go.sum +++ b/modules/opensearch/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -52,6 +53,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -78,6 +83,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -174,6 +181,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/opensearch/opensearch.go b/modules/opensearch/opensearch.go index 83177c8471..fcc5a1f714 100644 --- a/modules/opensearch/opensearch.go +++ b/modules/opensearch/opensearch.go @@ -118,11 +118,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom }) container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *OpenSearchContainer + if container != nil { + c = &OpenSearchContainer{Container: container, User: username, Password: password} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &OpenSearchContainer{Container: container, User: username, Password: password}, nil + return c, nil } // Address retrieves the address of the OpenSearch container. diff --git a/modules/opensearch/opensearch_test.go b/modules/opensearch/opensearch_test.go index 64d0db37a5..3829ea2dfb 100644 --- a/modules/opensearch/opensearch_test.go +++ b/modules/opensearch/opensearch_test.go @@ -5,41 +5,30 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/opensearch" ) func TestOpenSearch(t *testing.T) { ctx := context.Background() - container, err := opensearch.Run(ctx, "opensearchproject/opensearch:2.11.1") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := opensearch.Run(ctx, "opensearchproject/opensearch:2.11.1") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) t.Run("Connect to Address", func(t *testing.T) { - address, err := container.Address(ctx) - if err != nil { - t.Fatal(err) - } + address, err := ctr.Address(ctx) + require.NoError(t, err) client := &http.Client{} req, err := http.NewRequest("GET", address, nil) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) resp, err := client.Do(req) - if err != nil { - t.Fatalf("failed to perform GET request: %s", err) - } + require.NoError(t, err) defer resp.Body.Close() }) } diff --git a/modules/postgres/examples_test.go b/modules/postgres/examples_test.go index d579068686..8b7f562ea9 100644 --- a/modules/postgres/examples_test.go +++ b/modules/postgres/examples_test.go @@ -32,21 +32,21 @@ func ExampleRun() { WithOccurrence(2). WithStartupTimeout(5*time.Second)), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := postgresContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(postgresContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := postgresContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/postgres/postgres.go b/modules/postgres/postgres.go index 0ab4d889d1..a6bc418ff3 100644 --- a/modules/postgres/postgres.go +++ b/modules/postgres/postgres.go @@ -169,15 +169,22 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) - if err != nil { - return nil, err + var c *PostgresContainer + if container != nil { + c = &PostgresContainer{ + Container: container, + dbName: req.Env["POSTGRES_DB"], + password: req.Env["POSTGRES_PASSWORD"], + user: req.Env["POSTGRES_USER"], + sqlDriverName: settings.SQLDriverName, + } } - user := req.Env["POSTGRES_USER"] - password := req.Env["POSTGRES_PASSWORD"] - dbName := req.Env["POSTGRES_DB"] + if err != nil { + return c, fmt.Errorf("generic container: %w", err) + } - return &PostgresContainer{Container: container, dbName: dbName, password: password, user: user, sqlDriverName: settings.SQLDriverName}, nil + return c, nil } type snapshotConfig struct { diff --git a/modules/postgres/postgres_test.go b/modules/postgres/postgres_test.go index adef0defe3..825a5bdc6f 100644 --- a/modules/postgres/postgres_test.go +++ b/modules/postgres/postgres_test.go @@ -3,7 +3,6 @@ package postgres_test import ( "context" "database/sql" - "errors" "fmt" "path/filepath" "testing" @@ -13,7 +12,6 @@ import ( "github.com/jackc/pgx/v5" _ "github.com/jackc/pgx/v5/stdlib" _ "github.com/lib/pq" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" @@ -60,53 +58,45 @@ func TestPostgres(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - container, err := postgres.Run(ctx, + ctr, err := postgres.Run(ctx, tt.image, postgres.WithDatabase(dbname), postgres.WithUsername(user), postgres.WithPassword(password), postgres.BasicWaitStrategies(), ) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // connectionString { // explicitly set sslmode=disable because the container is not configured to use TLS - connStr, err := container.ConnectionString(ctx, "sslmode=disable", "application_name=test") + connStr, err := ctr.ConnectionString(ctx, "sslmode=disable", "application_name=test") // } require.NoError(t, err) - mustConnStr := container.MustConnectionString(ctx, "sslmode=disable", "application_name=test") + mustConnStr := ctr.MustConnectionString(ctx, "sslmode=disable", "application_name=test") if mustConnStr != connStr { t.Errorf("ConnectionString was not equal to MustConnectionString") } // Ensure connection string is using generic format - id, err := container.MappedPort(ctx, "5432/tcp") + id, err := ctr.MappedPort(ctx, "5432/tcp") require.NoError(t, err) - assert.Equal(t, fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable&application_name=test", user, password, "localhost", id.Port(), dbname), connStr) + require.Equal(t, fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable&application_name=test", user, password, "localhost", id.Port(), dbname), connStr) // perform assertions db, err := sql.Open("postgres", connStr) require.NoError(t, err) - assert.NotNil(t, db) + require.NotNil(t, db) defer db.Close() result, err := db.Exec("CREATE TABLE IF NOT EXISTS test (id int, name varchar(255));") require.NoError(t, err) - assert.NotNil(t, result) + require.NotNil(t, result) result, err = db.Exec("INSERT INTO test (id, name) VALUES (1, 'test');") require.NoError(t, err) - assert.NotNil(t, result) + require.NotNil(t, result) }) } } @@ -120,7 +110,7 @@ func TestContainerWithWaitForSQL(t *testing.T) { } t.Run("default query", func(t *testing.T) { - container, err := postgres.Run( + ctr, err := postgres.Run( ctx, "docker.io/postgres:16-alpine", postgres.WithDatabase(dbname), @@ -128,11 +118,12 @@ func TestContainerWithWaitForSQL(t *testing.T) { postgres.WithPassword(password), testcontainers.WithWaitStrategy(wait.ForSQL(nat.Port(port), "postgres", dbURL)), ) + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - require.NotNil(t, container) + require.NotNil(t, ctr) }) t.Run("custom query", func(t *testing.T) { - container, err := postgres.Run( + ctr, err := postgres.Run( ctx, "docker.io/postgres:16-alpine", postgres.WithDatabase(dbname), @@ -140,11 +131,12 @@ func TestContainerWithWaitForSQL(t *testing.T) { postgres.WithPassword(password), testcontainers.WithWaitStrategy(wait.ForSQL(nat.Port(port), "postgres", dbURL).WithStartupTimeout(time.Second*5).WithQuery("SELECT 10")), ) + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - require.NotNil(t, container) + require.NotNil(t, ctr) }) t.Run("custom bad query", func(t *testing.T) { - container, err := postgres.Run( + ctr, err := postgres.Run( ctx, "docker.io/postgres:16-alpine", postgres.WithDatabase(dbname), @@ -152,15 +144,15 @@ func TestContainerWithWaitForSQL(t *testing.T) { postgres.WithPassword(password), testcontainers.WithWaitStrategy(wait.ForSQL(nat.Port(port), "postgres", dbURL).WithStartupTimeout(time.Second*5).WithQuery("SELECT 'a' from b")), ) + testcontainers.CleanupContainer(t, ctr) require.Error(t, err) - require.Nil(t, container) }) } func TestWithConfigFile(t *testing.T) { ctx := context.Background() - container, err := postgres.Run(ctx, + ctr, err := postgres.Run(ctx, "docker.io/postgres:16-alpine", postgres.WithConfigFile(filepath.Join("testdata", "my-postgres.conf")), postgres.WithDatabase(dbname), @@ -168,30 +160,23 @@ func TestWithConfigFile(t *testing.T) { postgres.WithPassword(password), postgres.BasicWaitStrategies(), ) - if err != nil { - t.Fatal(err) - } - - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // explicitly set sslmode=disable because the container is not configured to use TLS - connStr, err := container.ConnectionString(ctx, "sslmode=disable") + connStr, err := ctr.ConnectionString(ctx, "sslmode=disable") require.NoError(t, err) db, err := sql.Open("postgres", connStr) require.NoError(t, err) - assert.NotNil(t, db) + require.NotNil(t, db) defer db.Close() } func TestWithInitScript(t *testing.T) { ctx := context.Background() - container, err := postgres.Run(ctx, + ctr, err := postgres.Run(ctx, "docker.io/postgres:15.2-alpine", postgres.WithInitScripts(filepath.Join("testdata", "init-user-db.sh")), postgres.WithDatabase(dbname), @@ -199,37 +184,30 @@ func TestWithInitScript(t *testing.T) { postgres.WithPassword(password), postgres.BasicWaitStrategies(), ) - if err != nil { - t.Fatal(err) - } - - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // explicitly set sslmode=disable because the container is not configured to use TLS - connStr, err := container.ConnectionString(ctx, "sslmode=disable") + connStr, err := ctr.ConnectionString(ctx, "sslmode=disable") require.NoError(t, err) db, err := sql.Open("postgres", connStr) require.NoError(t, err) - assert.NotNil(t, db) + require.NotNil(t, db) defer db.Close() // database created in init script. See testdata/init-user-db.sh result, err := db.Exec("SELECT * FROM testdb;") require.NoError(t, err) - assert.NotNil(t, result) + require.NotNil(t, result) } func TestSnapshot(t *testing.T) { // snapshotAndReset { ctx := context.Background() - // 1. Start the postgres container and run any migrations on it - container, err := postgres.Run( + // 1. Start the postgres ctr and run any migrations on it + ctr, err := postgres.Run( ctx, "docker.io/postgres:16-alpine", postgres.WithDatabase(dbname), @@ -238,90 +216,58 @@ func TestSnapshot(t *testing.T) { postgres.BasicWaitStrategies(), postgres.WithSQLDriver("pgx"), ) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // Run any migrations on the database - _, _, err = container.Exec(ctx, []string{"psql", "-U", user, "-d", dbname, "-c", "CREATE TABLE users (id SERIAL, name TEXT NOT NULL, age INT NOT NULL)"}) - if err != nil { - t.Fatal(err) - } + _, _, err = ctr.Exec(ctx, []string{"psql", "-U", user, "-d", dbname, "-c", "CREATE TABLE users (id SERIAL, name TEXT NOT NULL, age INT NOT NULL)"}) + require.NoError(t, err) // 2. Create a snapshot of the database to restore later - err = container.Snapshot(ctx, postgres.WithSnapshotName("test-snapshot")) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + err = ctr.Snapshot(ctx, postgres.WithSnapshotName("test-snapshot")) + require.NoError(t, err) - dbURL, err := container.ConnectionString(ctx) - if err != nil { - t.Fatal(err) - } + dbURL, err := ctr.ConnectionString(ctx) + require.NoError(t, err) t.Run("Test inserting a user", func(t *testing.T) { t.Cleanup(func() { // 3. In each test, reset the DB to its snapshot state. - err = container.Restore(ctx) - if err != nil { - t.Fatal(err) - } + err = ctr.Restore(ctx) + require.NoError(t, err) }) conn, err := pgx.Connect(context.Background(), dbURL) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer conn.Close(context.Background()) _, err = conn.Exec(ctx, "INSERT INTO users(name, age) VALUES ($1, $2)", "test", 42) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) var name string var age int64 err = conn.QueryRow(context.Background(), "SELECT name, age FROM users LIMIT 1").Scan(&name, &age) - if err != nil { - t.Fatal(err) - } - - if name != "test" { - t.Fatalf("Expected %s to equal `test`", name) - } - if age != 42 { - t.Fatalf("Expected %d to equal `42`", age) - } + require.NoError(t, err) + + require.Equal(t, "test", name) + require.EqualValues(t, 42, age) }) // 4. Run as many tests as you need, they will each get a clean database t.Run("Test querying empty DB", func(t *testing.T) { t.Cleanup(func() { - err = container.Restore(ctx) - if err != nil { - t.Fatal(err) - } + err = ctr.Restore(ctx) + require.NoError(t, err) }) conn, err := pgx.Connect(context.Background(), dbURL) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer conn.Close(context.Background()) var name string var age int64 err = conn.QueryRow(context.Background(), "SELECT name, age FROM users LIMIT 1").Scan(&name, &age) - if !errors.Is(err, pgx.ErrNoRows) { - t.Fatalf("Expected error to be a NoRows error, since the DB should be empty on every test. Got %s instead", err) - } + require.ErrorIs(t, err, pgx.ErrNoRows) }) // } } @@ -333,7 +279,7 @@ func TestSnapshotWithOverrides(t *testing.T) { user := "other-user" password := "other-password" - container, err := postgres.Run( + ctr, err := postgres.Run( ctx, "docker.io/postgres:16-alpine", postgres.WithDatabase(dbname), @@ -341,58 +287,34 @@ func TestSnapshotWithOverrides(t *testing.T) { postgres.WithPassword(password), postgres.BasicWaitStrategies(), ) - if err != nil { - t.Fatal(err) - } - - _, _, err = container.Exec(ctx, []string{"psql", "-U", user, "-d", dbname, "-c", "CREATE TABLE users (id SERIAL, name TEXT NOT NULL, age INT NOT NULL)"}) - if err != nil { - t.Fatal(err) - } - - err = container.Snapshot(ctx, postgres.WithSnapshotName("other-snapshot")) - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + _, _, err = ctr.Exec(ctx, []string{"psql", "-U", user, "-d", dbname, "-c", "CREATE TABLE users (id SERIAL, name TEXT NOT NULL, age INT NOT NULL)"}) + require.NoError(t, err) + err = ctr.Snapshot(ctx, postgres.WithSnapshotName("other-snapshot")) + require.NoError(t, err) - dbURL, err := container.ConnectionString(ctx) - if err != nil { - t.Fatal(err) - } + dbURL, err := ctr.ConnectionString(ctx) + require.NoError(t, err) t.Run("Test that the restore works when not using defaults", func(t *testing.T) { - _, _, err = container.Exec(ctx, []string{"psql", "-U", user, "-d", dbname, "-c", "INSERT INTO users(name, age) VALUES ('test', 42)"}) - if err != nil { - t.Fatal(err) - } + _, _, err = ctr.Exec(ctx, []string{"psql", "-U", user, "-d", dbname, "-c", "INSERT INTO users(name, age) VALUES ('test', 42)"}) + require.NoError(t, err) // Doing the restore before we connect since this resets the pgx connection - err = container.Restore(ctx) - if err != nil { - t.Fatal(err) - } + err = ctr.Restore(ctx) + require.NoError(t, err) conn, err := pgx.Connect(context.Background(), dbURL) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer conn.Close(context.Background()) var count int64 err = conn.QueryRow(context.Background(), "SELECT COUNT(1) FROM users").Scan(&count) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) - if count != 0 { - t.Fatalf("Expected %d to equal `0`", count) - } + require.Zero(t, count) }) } @@ -413,90 +335,58 @@ func TestSnapshotWithDockerExecFallback(t *testing.T) { postgres.WithSQLDriver("DoesNotExist"), ) // } - if err != nil { - t.Fatal(err) - } + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // Run any migrations on the database _, _, err = ctr.Exec(ctx, []string{"psql", "-U", user, "-d", dbname, "-c", "CREATE TABLE users (id SERIAL, name TEXT NOT NULL, age INT NOT NULL)"}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // 2. Create a snapshot of the database to restore later err = ctr.Snapshot(ctx, postgres.WithSnapshotName("test-snapshot")) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := ctr.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + require.NoError(t, err) dbURL, err := ctr.ConnectionString(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) t.Run("Test inserting a user", func(t *testing.T) { t.Cleanup(func() { // 3. In each test, reset the DB to its snapshot state. err := ctr.Restore(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) }) conn, err2 := pgx.Connect(context.Background(), dbURL) - if err2 != nil { - t.Fatal(err2) - } + require.NoError(t, err2) defer conn.Close(context.Background()) _, err2 = conn.Exec(ctx, "INSERT INTO users(name, age) VALUES ($1, $2)", "test", 42) - if err2 != nil { - t.Fatal(err2) - } + require.NoError(t, err2) var name string var age int64 err2 = conn.QueryRow(context.Background(), "SELECT name, age FROM users LIMIT 1").Scan(&name, &age) - if err2 != nil { - t.Fatal(err2) - } - - if name != "test" { - t.Fatalf("Expected %s to equal `test`", name) - } - if age != 42 { - t.Fatalf("Expected %d to equal `42`", age) - } + require.NoError(t, err2) + + require.Equal(t, "test", name) + require.EqualValues(t, 42, age) }) t.Run("Test querying empty DB", func(t *testing.T) { // 4. Run as many tests as you need, they will each get a clean database t.Cleanup(func() { err := ctr.Restore(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) }) conn, err2 := pgx.Connect(context.Background(), dbURL) - if err2 != nil { - t.Fatal(err2) - } + require.NoError(t, err2) defer conn.Close(context.Background()) var name string var age int64 err2 = conn.QueryRow(context.Background(), "SELECT name, age FROM users LIMIT 1").Scan(&name, &age) - if !errors.Is(err2, pgx.ErrNoRows) { - t.Fatalf("Expected error to be a NoRows error, since the DB should be empty on every test. Got %s instead", err2) - } + require.ErrorIs(t, err2, pgx.ErrNoRows) }) // } } diff --git a/modules/pulsar/examples_test.go b/modules/pulsar/examples_test.go index 2ee1f3c38e..ad871f1494 100644 --- a/modules/pulsar/examples_test.go +++ b/modules/pulsar/examples_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/pulsar" ) @@ -13,21 +14,21 @@ func ExampleRun() { ctx := context.Background() pulsarContainer, err := pulsar.Run(ctx, "docker.io/apachepulsar/pulsar:2.10.2") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := pulsarContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(pulsarContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := pulsarContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/pulsar/pulsar.go b/modules/pulsar/pulsar.go index c1c5c94517..26c57b5742 100644 --- a/modules/pulsar/pulsar.go +++ b/modules/pulsar/pulsar.go @@ -164,14 +164,15 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } } - c, err := testcontainers.GenericContainer(ctx, genericContainerReq) - if err != nil { - return nil, err + container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *Container + if container != nil { + c = &Container{Container: container} } - pc := &Container{ - Container: c, + if err != nil { + return c, fmt.Errorf("generic container: %w", err) } - return pc, nil + return c, nil } diff --git a/modules/pulsar/pulsar_test.go b/modules/pulsar/pulsar_test.go index 6d911bf9e5..cd04284913 100644 --- a/modules/pulsar/pulsar_test.go +++ b/modules/pulsar/pulsar_test.go @@ -3,7 +3,6 @@ package pulsar_test import ( "context" "encoding/json" - "fmt" "io" "net/http" "strings" @@ -11,6 +10,7 @@ import ( "time" "github.com/apache/pulsar-client-go/pulsar" + "github.com/apache/pulsar-client-go/pulsar/log" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" "github.com/stretchr/testify/assert" @@ -21,12 +21,20 @@ import ( tcnetwork "github.com/testcontainers/testcontainers-go/network" ) +// noopLogConsumer implements testcontainers.LogConsumer +// and does nothing with the logs. +type noopLogConsumer struct{} + +// Accept implements testcontainers.LogConsumer. +func (*noopLogConsumer) Accept(testcontainers.Log) {} + func TestPulsar(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() nw, err := tcnetwork.New(ctx) require.NoError(t, err) + testcontainers.CleanupNetwork(t, nw) nwName := nw.Name @@ -80,7 +88,7 @@ func TestPulsar(t *testing.T) { name: "with log consumers", opts: []testcontainers.ContainerCustomizer{ // withLogconsumers { - testcontainers.WithLogConsumers(&testcontainers.StdoutLogConsumer{}), + testcontainers.WithLogConsumers(&noopLogConsumer{}), // } }, }, @@ -93,11 +101,8 @@ func TestPulsar(t *testing.T) { "docker.io/apachepulsar/pulsar:2.10.2", tt.opts..., ) + testcontainers.CleanupContainer(t, c) require.NoError(t, err) - defer func() { - err := c.Terminate(ctx) - require.NoError(t, err) - }() // getBrokerURL { brokerURL, err := c.BrokerURL(ctx) @@ -116,6 +121,7 @@ func TestPulsar(t *testing.T) { URL: brokerURL, OperationTimeout: 30 * time.Second, ConnectionTimeout: 30 * time.Second, + Logger: log.DefaultNopLogger(), }) require.NoError(t, err) t.Cleanup(func() { pc.Close() }) @@ -134,13 +140,13 @@ func TestPulsar(t *testing.T) { go func() { msg, err := consumer.Receive(ctx) if err != nil { - fmt.Println("failed to receive message", err) + t.Log("failed to receive message", err) return } msgChan <- msg.Payload() err = consumer.Ack(msg) if err != nil { - fmt.Println("failed to send ack", err) + t.Log("failed to send ack", err) return } }() @@ -188,14 +194,7 @@ func TestPulsar(t *testing.T) { // check that the subscription exists _, ok := subscriptionsMap[subscriptionName] - assert.True(t, ok) + require.True(t, ok) }) } - - // remove the network after the last, so that all containers are already removed - // and there are no active endpoints on the network - t.Cleanup(func() { - err := nw.Remove(context.Background()) - require.NoError(t, err) - }) } diff --git a/modules/qdrant/examples_test.go b/modules/qdrant/examples_test.go index eca3adb4ad..85bd2763de 100644 --- a/modules/qdrant/examples_test.go +++ b/modules/qdrant/examples_test.go @@ -10,6 +10,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/qdrant" ) @@ -18,21 +19,21 @@ func ExampleRun() { ctx := context.Background() qdrantContainer, err := qdrant.Run(ctx, "qdrant/qdrant:v1.7.4") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := qdrantContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(qdrantContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := qdrantContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -44,25 +45,27 @@ func ExampleRun() { func ExampleRun_createPoints() { // fullExample { qdrantContainer, err := qdrant.Run(context.Background(), "qdrant/qdrant:v1.7.4") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := qdrantContainer.Terminate(context.Background()); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(qdrantContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } grpcEndpoint, err := qdrantContainer.GRPCEndpoint(context.Background()) if err != nil { - log.Fatalf("failed to get gRPC endpoint: %s", err) // nolint:gocritic + log.Printf("failed to get gRPC endpoint: %s", err) + return } // Set up a connection to the server. conn, err := grpc.NewClient(grpcEndpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { - log.Fatalf("did not connect: %v", err) + log.Printf("did not connect: %v", err) + return } defer conn.Close() @@ -89,7 +92,8 @@ func ExampleRun_createPoints() { }, }) if err != nil { - log.Fatalf("Could not create collection: %v", err) + log.Printf("Could not create collection: %v", err) + return } // 2. Contact the server and print out its response. @@ -97,7 +101,8 @@ func ExampleRun_createPoints() { defer cancel() r, err := collections_client.List(ctx, &pb.ListCollectionsRequest{}) if err != nil { - log.Fatalf("could not get collections: %v", err) + log.Printf("could not get collections: %v", err) + return } fmt.Printf("List of collections: %s\n", r.GetCollections()) @@ -113,7 +118,8 @@ func ExampleRun_createPoints() { FieldType: &fieldIndex1Type, }) if err != nil { - log.Fatalf("Could not create field index: %v", err) + log.Printf("Could not create field index: %v", err) + return } // 5. Create integer field index @@ -125,7 +131,8 @@ func ExampleRun_createPoints() { FieldType: &fieldIndex2Type, }) if err != nil { - log.Fatalf("Could not create field index: %v", err) + log.Printf("Could not create field index: %v", err) + return } // 6. Upsert points @@ -258,7 +265,8 @@ func ExampleRun_createPoints() { Points: upsertPoints, }) if err != nil { - log.Fatalf("Could not upsert points: %v", err) + log.Printf("Could not upsert points: %v", err) + return } // 7. Retrieve points by ids @@ -270,7 +278,8 @@ func ExampleRun_createPoints() { }, }) if err != nil { - log.Fatalf("Could not retrieve points: %v", err) + log.Printf("Could not retrieve points: %v", err) + return } fmt.Printf("Retrieved points: %d\n", len(pointsById.GetResult())) @@ -285,7 +294,8 @@ func ExampleRun_createPoints() { WithPayload: &pb.WithPayloadSelector{SelectorOptions: &pb.WithPayloadSelector_Enable{Enable: true}}, }) if err != nil { - log.Fatalf("Could not search points: %v", err) + log.Printf("Could not search points: %v", err) + return } fmt.Printf("Found points: %d\n", len(unfilteredSearchResult.GetResult())) @@ -313,7 +323,8 @@ func ExampleRun_createPoints() { }, }) if err != nil { - log.Fatalf("Could not search points: %v", err) + log.Printf("Could not search points: %v", err) + return } // } diff --git a/modules/qdrant/go.mod b/modules/qdrant/go.mod index 85db7229b3..05c20884ee 100644 --- a/modules/qdrant/go.mod +++ b/modules/qdrant/go.mod @@ -4,7 +4,8 @@ go 1.22 require ( github.com/qdrant/go-client v1.7.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 google.golang.org/grpc v1.64.1 ) @@ -17,6 +18,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -28,6 +30,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -39,6 +42,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -56,6 +60,7 @@ require ( golang.org/x/text v0.16.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/qdrant/go.sum b/modules/qdrant/go.sum index c38866d982..b33ba47727 100644 --- a/modules/qdrant/go.sum +++ b/modules/qdrant/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -52,6 +53,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -80,6 +85,8 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/qdrant/go-client v1.7.0 h1:2TeeWyZAWIup7vvD7Ne6aAvo0H+F5OUb1pB9Z8Y4pFk= github.com/qdrant/go-client v1.7.0/go.mod h1:680gkxNAsVtre0Z8hAQmtPzJtz1xFAyCu2TUxULtnoE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -177,6 +184,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/qdrant/qdrant.go b/modules/qdrant/qdrant.go index e934403f96..5a2b6d365f 100644 --- a/modules/qdrant/qdrant.go +++ b/modules/qdrant/qdrant.go @@ -43,11 +43,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *QdrantContainer + if container != nil { + c = &QdrantContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &QdrantContainer{Container: container}, nil + return c, nil } // RESTEndpoint returns the REST endpoint of the Qdrant container diff --git a/modules/qdrant/qdrant_test.go b/modules/qdrant/qdrant_test.go index 2b9bcdbb75..63b95d30ea 100644 --- a/modules/qdrant/qdrant_test.go +++ b/modules/qdrant/qdrant_test.go @@ -5,79 +5,57 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/qdrant" ) func TestQdrant(t *testing.T) { ctx := context.Background() - container, err := qdrant.Run(ctx, "qdrant/qdrant:v1.7.4") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := qdrant.Run(ctx, "qdrant/qdrant:v1.7.4") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) t.Run("REST Endpoint", func(tt *testing.T) { // restEndpoint { - restEndpoint, err := container.RESTEndpoint(ctx) + restEndpoint, err := ctr.RESTEndpoint(ctx) // } - if err != nil { - tt.Fatalf("failed to get REST endpoint: %s", err) - } + require.NoError(t, err) cli := &http.Client{} resp, err := cli.Get(restEndpoint) - if err != nil { - tt.Fatalf("failed to perform GET request: %s", err) - } + require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - tt.Fatalf("unexpected status code: %d", resp.StatusCode) - } + require.Equal(t, http.StatusOK, resp.StatusCode) }) t.Run("gRPC Endpoint", func(tt *testing.T) { // gRPCEndpoint { - grpcEndpoint, err := container.GRPCEndpoint(ctx) + grpcEndpoint, err := ctr.GRPCEndpoint(ctx) // } - if err != nil { - tt.Fatalf("failed to get REST endpoint: %s", err) - } + require.NoError(t, err) conn, err := grpc.NewClient(grpcEndpoint, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - t.Fatalf("did not connect: %v", err) - } + require.NoError(t, err) defer conn.Close() }) t.Run("Web UI", func(tt *testing.T) { // webUIEndpoint { - webUI, err := container.WebUI(ctx) + webUI, err := ctr.WebUI(ctx) // } - if err != nil { - tt.Fatalf("failed to get REST endpoint: %s", err) - } + require.NoError(t, err) cli := &http.Client{} resp, err := cli.Get(webUI) - if err != nil { - tt.Fatalf("failed to perform GET request: %s", err) - } + require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - tt.Fatalf("unexpected status code: %d", resp.StatusCode) - } + require.Equal(t, http.StatusOK, resp.StatusCode) }) } diff --git a/modules/rabbitmq/examples_test.go b/modules/rabbitmq/examples_test.go index 4471d512d4..bc6a849456 100644 --- a/modules/rabbitmq/examples_test.go +++ b/modules/rabbitmq/examples_test.go @@ -24,21 +24,21 @@ func ExampleRun() { rabbitmq.WithAdminUsername("admin"), rabbitmq.WithAdminPassword("password"), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := rabbitmqContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(rabbitmqContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := rabbitmqContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -55,28 +55,31 @@ func ExampleRun_connectUsingAmqp() { rabbitmq.WithAdminUsername("admin"), rabbitmq.WithAdminPassword("password"), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } defer func() { - if err := rabbitmqContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(rabbitmqContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } amqpURL, err := rabbitmqContainer.AmqpURL(ctx) if err != nil { - log.Fatalf("failed to get AMQP URL: %s", err) // nolint:gocritic + log.Printf("failed to get AMQP URL: %s", err) + return } amqpConnection, err := amqp.Dial(amqpURL) if err != nil { - log.Fatalf("failed to connect to RabbitMQ: %s", err) // nolint:gocritic + log.Printf("failed to connect to RabbitMQ: %s", err) + return } defer func() { err := amqpConnection.Close() if err != nil { - log.Fatalf("failed to close connection: %s", err) // nolint:gocritic + log.Printf("failed to close connection: %s", err) } }() @@ -93,7 +96,8 @@ func ExampleRun_withSSL() { tmpDir := os.TempDir() certDirs := tmpDir + "/rabbitmq" if err := os.MkdirAll(certDirs, 0o755); err != nil { - log.Fatalf("failed to create temporary directory: %s", err) + log.Printf("failed to create temporary directory: %s", err) + return } defer os.RemoveAll(certDirs) @@ -105,7 +109,8 @@ func ExampleRun_withSSL() { ParentDir: certDirs, }) if caCert == nil { - log.Fatal("failed to generate CA certificate") // nolint:gocritic + log.Print("failed to generate CA certificate") + return } cert := tlscert.SelfSignedFromRequest(tlscert.Request{ @@ -116,7 +121,8 @@ func ExampleRun_withSSL() { ParentDir: certDirs, }) if cert == nil { - log.Fatal("failed to generate certificate") // nolint:gocritic + log.Print("failed to generate certificate") + return } sslSettings := rabbitmq.SSLSettings{ @@ -132,20 +138,21 @@ func ExampleRun_withSSL() { "rabbitmq:3.7.25-management-alpine", rabbitmq.WithSSL(sslSettings), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) // nolint:gocritic - } - // } - defer func() { - if err := rabbitmqContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(rabbitmqContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + // } state, err := rabbitmqContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -166,17 +173,22 @@ func ExampleRun_withPlugins() { testcontainers.NewRawCommand([]string{"rabbitmq_random_exchange"}), ), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := rabbitmqContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(rabbitmqContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + + if err = assertPlugins(rabbitmqContainer, "rabbitmq_shovel", "rabbitmq_random_exchange"); err != nil { + log.Printf("failed to find plugin: %s", err) + return + } - fmt.Println(assertPlugins(rabbitmqContainer, "rabbitmq_shovel", "rabbitmq_random_exchange")) + fmt.Println(true) // Output: // true @@ -188,24 +200,26 @@ func ExampleRun_withCustomConfigFile() { rabbitmqContainer, err := rabbitmq.Run(ctx, "rabbitmq:3.7.25-management-alpine", ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := rabbitmqContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(rabbitmqContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } logs, err := rabbitmqContainer.Logs(ctx) if err != nil { - log.Fatalf("failed to get logs: %s", err) // nolint:gocritic + log.Printf("failed to get logs: %s", err) + return } bytes, err := io.ReadAll(logs) if err != nil { - log.Fatalf("failed to read logs: %s", err) // nolint:gocritic + log.Printf("failed to read logs: %s", err) + return } fmt.Println(strings.Contains(string(bytes), "config file(s) : /etc/rabbitmq/rabbitmq-testcontainers.conf")) @@ -214,25 +228,24 @@ func ExampleRun_withCustomConfigFile() { // true } -func assertPlugins(container testcontainers.Container, plugins ...string) bool { +func assertPlugins(container testcontainers.Container, plugins ...string) error { ctx := context.Background() for _, plugin := range plugins { - _, out, err := container.Exec(ctx, []string{"rabbitmq-plugins", "is_enabled", plugin}) if err != nil { - log.Fatalf("failed to execute command: %s", err) + return fmt.Errorf("failed to execute command: %w", err) } check, err := io.ReadAll(out) if err != nil { - log.Fatalf("failed to read output: %s", err) + return fmt.Errorf("failed to read output: %w", err) } if !strings.Contains(string(check), plugin+" is enabled") { - return false + return fmt.Errorf("plugin %q is not enabled", plugin) } } - return true + return nil } diff --git a/modules/rabbitmq/go.mod b/modules/rabbitmq/go.mod index e9d4a267fa..46f915a46d 100644 --- a/modules/rabbitmq/go.mod +++ b/modules/rabbitmq/go.mod @@ -5,15 +5,8 @@ go 1.22 require ( github.com/docker/go-connections v0.5.0 github.com/rabbitmq/amqp091-go v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 -) - -require ( - github.com/containerd/platforms v0.2.1 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/net v0.26.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 ) require ( @@ -23,7 +16,9 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect @@ -37,6 +32,7 @@ require ( github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mdelapenya/tlscert v0.1.0 + github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/user v0.1.0 // indirect @@ -45,6 +41,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -56,8 +53,12 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/net v0.26.0 // indirect golang.org/x/sys v0.21.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/rabbitmq/go.sum b/modules/rabbitmq/go.sum index bf809122da..5994d5e5b7 100644 --- a/modules/rabbitmq/go.sum +++ b/modules/rabbitmq/go.sum @@ -53,7 +53,10 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +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/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= @@ -85,6 +88,8 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/rabbitmq/amqp091-go v1.9.0 h1:qrQtyzB4H8BQgEuJwhmVQqVHB9O4+MNDJCCAcpc3Aoo= github.com/rabbitmq/amqp091-go v1.9.0/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -184,6 +189,8 @@ google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGm google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/rabbitmq/rabbitmq.go b/modules/rabbitmq/rabbitmq.go index bcc1a849d7..32d18c09a9 100644 --- a/modules/rabbitmq/rabbitmq.go +++ b/modules/rabbitmq/rabbitmq.go @@ -133,14 +133,17 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) - if err != nil { - return nil, err + var c *RabbitMQContainer + if container != nil { + c = &RabbitMQContainer{ + Container: container, + AdminUsername: settings.AdminUsername, + AdminPassword: settings.AdminPassword, + } } - c := &RabbitMQContainer{ - Container: container, - AdminUsername: settings.AdminUsername, - AdminPassword: settings.AdminPassword, + if err != nil { + return c, fmt.Errorf("generic container: %w", err) } return c, nil diff --git a/modules/rabbitmq/rabbitmq_test.go b/modules/rabbitmq/rabbitmq_test.go index 9b024d7b5a..f0b82ca2db 100644 --- a/modules/rabbitmq/rabbitmq_test.go +++ b/modules/rabbitmq/rabbitmq_test.go @@ -12,6 +12,7 @@ import ( "github.com/mdelapenya/tlscert" amqp "github.com/rabbitmq/amqp091-go" + "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/rabbitmq" @@ -21,29 +22,17 @@ func TestRunContainer_connectUsingAmqp(t *testing.T) { ctx := context.Background() rabbitmqContainer, err := rabbitmq.Run(ctx, "rabbitmq:3.12.11-management-alpine") - if err != nil { - t.Fatal(err) - } - - defer func() { - if err := rabbitmqContainer.Terminate(ctx); err != nil { - t.Fatal(err) - } - }() + testcontainers.CleanupContainer(t, rabbitmqContainer) + require.NoError(t, err) amqpURL, err := rabbitmqContainer.AmqpURL(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) amqpConnection, err := amqp.Dial(amqpURL) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) - if err = amqpConnection.Close(); err != nil { - t.Fatal(err) - } + err = amqpConnection.Close() + require.NoError(t, err) } func TestRunContainer_connectUsingAmqps(t *testing.T) { @@ -82,20 +71,11 @@ func TestRunContainer_connectUsingAmqps(t *testing.T) { } rabbitmqContainer, err := rabbitmq.Run(ctx, "rabbitmq:3.12.11-management-alpine", rabbitmq.WithSSL(sslSettings)) - if err != nil { - t.Fatal(err) - } - - defer func() { - if err := rabbitmqContainer.Terminate(ctx); err != nil { - t.Fatal(err) - } - }() + testcontainers.CleanupContainer(t, rabbitmqContainer) + require.NoError(t, err) amqpsURL, err := rabbitmqContainer.AmqpsURL(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if !strings.HasPrefix(amqpsURL, "amqps") { t.Fatal(fmt.Errorf("AMQPS Url should begin with `amqps`")) @@ -104,15 +84,11 @@ func TestRunContainer_connectUsingAmqps(t *testing.T) { certs := x509.NewCertPool() pemData, err := os.ReadFile(sslSettings.CACertFile) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) certs.AppendCertsFromPEM(pemData) amqpsConnection, err := amqp.DialTLS(amqpsURL, &tls.Config{InsecureSkipVerify: false, RootCAs: certs}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if amqpsConnection.IsClosed() { t.Fatal(fmt.Errorf("AMQPS Connection unexpectdely closed")) @@ -238,15 +214,8 @@ func TestRunContainer_withAllSettings(t *testing.T) { testcontainers.WithAfterReadyCommand(Plugin{Name: "rabbitmq_shovel"}, Plugin{Name: "rabbitmq_random_exchange"}), // } ) - if err != nil { - t.Fatal(err) - } - - defer func() { - if err := rabbitmqContainer.Terminate(ctx); err != nil { - t.Fatal(err) - } - }() + testcontainers.CleanupContainer(t, rabbitmqContainer) + require.NoError(t, err) if !assertEntity(t, rabbitmqContainer, "queues", "queue1", "queue2", "queue3", "queue4") { t.Fatal(err) diff --git a/modules/redis/examples_test.go b/modules/redis/examples_test.go index 9fb7c2cf11..e5e83a01a1 100644 --- a/modules/redis/examples_test.go +++ b/modules/redis/examples_test.go @@ -6,6 +6,7 @@ import ( "log" "path/filepath" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/redis" ) @@ -19,21 +20,21 @@ func ExampleRun() { redis.WithLogLevel(redis.LogLevelVerbose), redis.WithConfigFile(filepath.Join("testdata", "redis7.conf")), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := redisContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(redisContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := redisContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/redis/redis.go b/modules/redis/redis.go index 33ce823994..df75ad7311 100644 --- a/modules/redis/redis.go +++ b/modules/redis/redis.go @@ -69,11 +69,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *RedisContainer + if container != nil { + c = &RedisContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &RedisContainer{Container: container}, nil + return c, nil } // WithConfigFile sets the config file to be used for the redis container, and sets the command to run the redis server diff --git a/modules/redis/redis_test.go b/modules/redis/redis_test.go index f98079685f..0fd0a960f9 100644 --- a/modules/redis/redis_test.go +++ b/modules/redis/redis_test.go @@ -11,6 +11,7 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" tcredis "github.com/testcontainers/testcontainers-go/modules/redis" ) @@ -18,12 +19,8 @@ func TestIntegrationSetGet(t *testing.T) { ctx := context.Background() redisContainer, err := tcredis.Run(ctx, "docker.io/redis:7") + testcontainers.CleanupContainer(t, redisContainer) require.NoError(t, err) - t.Cleanup(func() { - if err := redisContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) assertSetsGets(t, ctx, redisContainer, 1) } @@ -32,12 +29,8 @@ func TestRedisWithConfigFile(t *testing.T) { ctx := context.Background() redisContainer, err := tcredis.Run(ctx, "docker.io/redis:7", tcredis.WithConfigFile(filepath.Join("testdata", "redis7.conf"))) + testcontainers.CleanupContainer(t, redisContainer) require.NoError(t, err) - t.Cleanup(func() { - if err := redisContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) assertSetsGets(t, ctx, redisContainer, 1) } @@ -74,12 +67,8 @@ func TestRedisWithImage(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { redisContainer, err := tcredis.Run(ctx, tt.image, tcredis.WithConfigFile(filepath.Join("testdata", "redis6.conf"))) + testcontainers.CleanupContainer(t, redisContainer) require.NoError(t, err) - t.Cleanup(func() { - if err := redisContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) assertSetsGets(t, ctx, redisContainer, 1) }) @@ -90,12 +79,8 @@ func TestRedisWithLogLevel(t *testing.T) { ctx := context.Background() redisContainer, err := tcredis.Run(ctx, "docker.io/redis:7", tcredis.WithLogLevel(tcredis.LogLevelVerbose)) + testcontainers.CleanupContainer(t, redisContainer) require.NoError(t, err) - t.Cleanup(func() { - if err := redisContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) assertSetsGets(t, ctx, redisContainer, 10) } @@ -104,12 +89,8 @@ func TestRedisWithSnapshotting(t *testing.T) { ctx := context.Background() redisContainer, err := tcredis.Run(ctx, "docker.io/redis:7", tcredis.WithSnapshotting(10, 1)) + testcontainers.CleanupContainer(t, redisContainer) require.NoError(t, err) - t.Cleanup(func() { - if err := redisContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) assertSetsGets(t, ctx, redisContainer, 10) } diff --git a/modules/redpanda/examples_test.go b/modules/redpanda/examples_test.go index 68cb314418..69fb0c9d6a 100644 --- a/modules/redpanda/examples_test.go +++ b/modules/redpanda/examples_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/redpanda" ) @@ -25,21 +26,21 @@ func ExampleRun() { redpanda.WithSuperusers("superuser-1", "superuser-2"), redpanda.WithEnableSchemaRegistryHTTPBasicAuth(), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := redpandaContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(redpandaContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := redpandaContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/redpanda/options.go b/modules/redpanda/options.go index ae15e33001..180edcc48f 100644 --- a/modules/redpanda/options.go +++ b/modules/redpanda/options.go @@ -139,7 +139,7 @@ func WithTLS(cert, key []byte) Option { // WithListener adds a custom listener to the Redpanda containers. Listener // will be aliases to all networks, so they can be accessed from within docker -// networks. At leas one network must be attached to the container, if not an +// networks. At least one network must be attached to the container, if not an // error will be thrown when starting the container. func WithListener(lis string) Option { host, port, err := net.SplitHostPort(lis) diff --git a/modules/redpanda/redpanda.go b/modules/redpanda/redpanda.go index 3ed3932066..686d310d9f 100644 --- a/modules/redpanda/redpanda.go +++ b/modules/redpanda/redpanda.go @@ -179,32 +179,36 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom ) } - container, err := testcontainers.GenericContainer(ctx, req) + ctr, err := testcontainers.GenericContainer(ctx, req) + var c *Container + if ctr != nil { + c = &Container{Container: ctr} + } if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } // 6. Get mapped port for the Kafka API, so that we can render and then mount // the Redpanda config with the advertised Kafka address. - hostIP, err := container.Host(ctx) + hostIP, err := ctr.Host(ctx) if err != nil { - return nil, fmt.Errorf("failed to get container host: %w", err) + return c, fmt.Errorf("failed to get container host: %w", err) } - kafkaPort, err := container.MappedPort(ctx, nat.Port(defaultKafkaAPIPort)) + kafkaPort, err := ctr.MappedPort(ctx, nat.Port(defaultKafkaAPIPort)) if err != nil { - return nil, fmt.Errorf("failed to get mapped Kafka port: %w", err) + return c, fmt.Errorf("failed to get mapped Kafka port: %w", err) } // 7. Render redpanda.yaml config and mount it. nodeConfig, err := renderNodeConfig(settings, hostIP, kafkaPort.Int()) if err != nil { - return nil, fmt.Errorf("failed to render node config: %w", err) + return c, fmt.Errorf("failed to render node config: %w", err) } - err = container.CopyToContainer(ctx, nodeConfig, filepath.Join(redpandaDir, "redpanda.yaml"), 600) + err = ctr.CopyToContainer(ctx, nodeConfig, filepath.Join(redpandaDir, "redpanda.yaml"), 600) if err != nil { - return nil, fmt.Errorf("failed to copy redpanda.yaml into container: %w", err) + return c, fmt.Errorf("failed to copy redpanda.yaml into container: %w", err) } // 8. Wait until Redpanda is ready to serve requests. @@ -213,29 +217,29 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom wait.ForListeningPort(defaultAdminAPIPort), wait.ForListeningPort(defaultSchemaRegistryPort), wait.ForLog("Successfully started Redpanda!"), - ).WaitUntilReady(ctx, container) + ).WaitUntilReady(ctx, ctr) if err != nil { - return nil, fmt.Errorf("failed to wait for Redpanda readiness: %w", err) + return c, fmt.Errorf("failed to wait for Redpanda readiness: %w", err) } - scheme := "http" + c.urlScheme = "http" if settings.EnableTLS { - scheme += "s" + c.urlScheme += "s" } // 9. Create Redpanda Service Accounts if configured to do so. if len(settings.ServiceAccounts) > 0 { - adminAPIPort, err := container.MappedPort(ctx, nat.Port(defaultAdminAPIPort)) + adminAPIPort, err := ctr.MappedPort(ctx, nat.Port(defaultAdminAPIPort)) if err != nil { - return nil, fmt.Errorf("failed to get mapped Admin API port: %w", err) + return c, fmt.Errorf("failed to get mapped Admin API port: %w", err) } - adminAPIUrl := fmt.Sprintf("%s://%v:%d", scheme, hostIP, adminAPIPort.Int()) + adminAPIUrl := fmt.Sprintf("%s://%v:%d", c.urlScheme, hostIP, adminAPIPort.Int()) adminCl := NewAdminAPIClient(adminAPIUrl) if settings.EnableTLS { cert, err := tls.X509KeyPair(settings.cert, settings.key) if err != nil { - return nil, fmt.Errorf("failed to create admin client with cert: %w", err) + return c, fmt.Errorf("failed to create admin client with cert: %w", err) } caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(settings.cert) @@ -254,12 +258,12 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom for username, password := range settings.ServiceAccounts { if err := adminCl.CreateUser(ctx, username, password); err != nil { - return nil, fmt.Errorf("failed to create service account with username %q: %w", username, err) + return c, fmt.Errorf("failed to create service account with username %q: %w", username, err) } } } - return &Container{Container: container, urlScheme: scheme}, nil + return c, nil } // KafkaSeedBroker returns the seed broker that should be used for connecting diff --git a/modules/redpanda/redpanda_test.go b/modules/redpanda/redpanda_test.go index 09bad2c0d0..09d391f794 100644 --- a/modules/redpanda/redpanda_test.go +++ b/modules/redpanda/redpanda_test.go @@ -27,18 +27,12 @@ import ( func TestRedpanda(t *testing.T) { ctx := context.Background() - container, err := redpanda.Run(ctx, "docker.redpanda.com/redpandadata/redpanda:v23.3.3") + ctr, err := redpanda.Run(ctx, "docker.redpanda.com/redpandadata/redpanda:v23.3.3") + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - // Test Kafka API - seedBroker, err := container.KafkaSeedBroker(ctx) + seedBroker, err := ctr.KafkaSeedBroker(ctx) require.NoError(t, err) kafkaCl, err := kgo.NewClient( @@ -54,7 +48,7 @@ func TestRedpanda(t *testing.T) { // Test Schema Registry API httpCl := &http.Client{Timeout: 5 * time.Second} - schemaRegistryURL, err := container.SchemaRegistryAddress(ctx) + schemaRegistryURL, err := ctr.SchemaRegistryAddress(ctx) require.NoError(t, err) req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/subjects", schemaRegistryURL), nil) require.NoError(t, err) @@ -65,7 +59,7 @@ func TestRedpanda(t *testing.T) { // Test Admin API // adminAPIAddress { - adminAPIURL, err := container.AdminAPIAddress(ctx) + adminAPIURL, err := ctr.AdminAPIAddress(ctx) // } require.NoError(t, err) req, err = http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v1/cluster/health_overview", adminAPIURL), nil) @@ -83,7 +77,7 @@ func TestRedpanda(t *testing.T) { func TestRedpandaWithAuthentication(t *testing.T) { ctx := context.Background() // redpandaCreateContainer { - container, err := redpanda.Run(ctx, + ctr, err := redpanda.Run(ctx, "docker.redpanda.com/redpandadata/redpanda:v23.3.3", redpanda.WithEnableSASL(), redpanda.WithEnableKafkaAuthorization(), @@ -94,18 +88,12 @@ func TestRedpandaWithAuthentication(t *testing.T) { redpanda.WithSuperusers("superuser-1", "superuser-2"), redpanda.WithEnableSchemaRegistryHTTPBasicAuth(), ) + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) // } - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - // kafkaSeedBroker { - seedBroker, err := container.KafkaSeedBroker(ctx) + seedBroker, err := ctr.KafkaSeedBroker(ctx) // } require.NoError(t, err) @@ -169,7 +157,7 @@ func TestRedpandaWithAuthentication(t *testing.T) { // Test Schema Registry API httpCl := &http.Client{Timeout: 5 * time.Second} // schemaRegistryAddress { - schemaRegistryURL, err := container.SchemaRegistryAddress(ctx) + schemaRegistryURL, err := ctr.SchemaRegistryAddress(ctx) // } require.NoError(t, err) @@ -178,7 +166,7 @@ func TestRedpandaWithAuthentication(t *testing.T) { require.NoError(t, err) resp, err := httpCl.Do(req) require.NoError(t, err) - assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) + require.Equal(t, http.StatusUnauthorized, resp.StatusCode) resp.Body.Close() // Successful authentication @@ -186,7 +174,7 @@ func TestRedpandaWithAuthentication(t *testing.T) { req.SetBasicAuth(user, password) resp, err = httpCl.Do(req) require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, http.StatusOK, resp.StatusCode) resp.Body.Close() } } @@ -195,7 +183,7 @@ func TestRedpandaWithOldVersionAndWasm(t *testing.T) { ctx := context.Background() // redpandaCreateContainer { // this would fail to start if we weren't ignoring wasm transforms for older versions - container, err := redpanda.Run(ctx, + ctr, err := redpanda.Run(ctx, "redpandadata/redpanda:v23.2.18", redpanda.WithEnableSASL(), redpanda.WithEnableKafkaAuthorization(), @@ -206,18 +194,12 @@ func TestRedpandaWithOldVersionAndWasm(t *testing.T) { redpanda.WithSuperusers("superuser-1", "superuser-2"), redpanda.WithEnableSchemaRegistryHTTPBasicAuth(), ) + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) // } - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - // kafkaSeedBroker { - seedBroker, err := container.KafkaSeedBroker(ctx) + seedBroker, err := ctr.KafkaSeedBroker(ctx) // } require.NoError(t, err) @@ -298,7 +280,7 @@ func TestRedpandaWithOldVersionAndWasm(t *testing.T) { // Test Schema Registry API httpCl := &http.Client{Timeout: 5 * time.Second} // schemaRegistryAddress { - schemaRegistryURL, err := container.SchemaRegistryAddress(ctx) + schemaRegistryURL, err := ctr.SchemaRegistryAddress(ctx) // } require.NoError(t, err) @@ -323,16 +305,11 @@ func TestRedpandaWithOldVersionAndWasm(t *testing.T) { func TestRedpandaProduceWithAutoCreateTopics(t *testing.T) { ctx := context.Background() - container, err := redpanda.Run(ctx, "docker.redpanda.com/redpandadata/redpanda:v23.3.3", redpanda.WithAutoCreateTopics()) + ctr, err := redpanda.Run(ctx, "docker.redpanda.com/redpandadata/redpanda:v23.3.3", redpanda.WithAutoCreateTopics()) + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - - brokers, err := container.KafkaSeedBroker(ctx) + brokers, err := ctr.KafkaSeedBroker(ctx) require.NoError(t, err) kafkaCl, err := kgo.NewClient( @@ -357,15 +334,10 @@ func TestRedpandaWithTLS(t *testing.T) { ctx := context.Background() - container, err := redpanda.Run(ctx, "docker.redpanda.com/redpandadata/redpanda:v23.3.3", redpanda.WithTLS(cert.Bytes, cert.KeyBytes)) + ctr, err := redpanda.Run(ctx, "docker.redpanda.com/redpandadata/redpanda:v23.3.3", redpanda.WithTLS(cert.Bytes, cert.KeyBytes)) + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - tlsConfig := cert.TLSConfig() httpCl := &http.Client{ @@ -378,7 +350,7 @@ func TestRedpandaWithTLS(t *testing.T) { } // Test Admin API - adminAPIURL, err := container.AdminAPIAddress(ctx) + adminAPIURL, err := ctr.AdminAPIAddress(ctx) require.NoError(t, err) require.True(t, strings.HasPrefix(adminAPIURL, "https://"), "AdminAPIAddress should return https url") req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v1/cluster/health_overview", adminAPIURL), nil) @@ -389,7 +361,7 @@ func TestRedpandaWithTLS(t *testing.T) { resp.Body.Close() // Test Schema Registry API - schemaRegistryURL, err := container.SchemaRegistryAddress(ctx) + schemaRegistryURL, err := ctr.SchemaRegistryAddress(ctx) require.NoError(t, err) require.True(t, strings.HasPrefix(adminAPIURL, "https://"), "SchemaRegistryAddress should return https url") req, err = http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/subjects", schemaRegistryURL), nil) @@ -399,7 +371,7 @@ func TestRedpandaWithTLS(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) resp.Body.Close() - brokers, err := container.KafkaSeedBroker(ctx) + brokers, err := ctr.KafkaSeedBroker(ctx) require.NoError(t, err) kafkaCl, err := kgo.NewClient( @@ -426,7 +398,7 @@ func TestRedpandaWithTLSAndSASL(t *testing.T) { ctx := context.Background() - container, err := redpanda.Run(ctx, + ctr, err := redpanda.Run(ctx, "docker.redpanda.com/redpandadata/redpanda:v23.3.3", redpanda.WithTLS(cert.Bytes, cert.KeyBytes), redpanda.WithEnableSASL(), @@ -434,17 +406,12 @@ func TestRedpandaWithTLSAndSASL(t *testing.T) { redpanda.WithNewServiceAccount("superuser-1", "test"), redpanda.WithSuperusers("superuser-1"), ) + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) - tlsConfig := cert.TLSConfig() - broker, err := container.KafkaSeedBroker(ctx) + broker, err := ctr.KafkaSeedBroker(ctx) require.NoError(t, err) kafkaCl, err := kgo.NewClient( @@ -469,14 +436,17 @@ func TestRedpandaListener_Simple(t *testing.T) { rpNetwork, err := network.New(ctx) require.NoError(t, err) - // 2. Start Redpanda container + testcontainers.CleanupNetwork(t, rpNetwork) + + // 2. Start Redpanda ctr // withListenerRP { - container, err := redpanda.Run(ctx, + ctr, err := redpanda.Run(ctx, "redpandadata/redpanda:v23.2.18", network.WithNetwork([]string{"redpanda-host"}, rpNetwork), redpanda.WithListener("redpanda:29092"), redpanda.WithAutoCreateTopics(), ) // } + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) // 3. Start KCat container @@ -498,7 +468,7 @@ func TestRedpandaListener_Simple(t *testing.T) { Started: true, }) // } - + testcontainers.CleanupContainer(t, kcat) require.NoError(t, err) // 4. Copy message to kcat @@ -519,21 +489,7 @@ func TestRedpandaListener_Simple(t *testing.T) { // 7. Read Message from stdout out, err := io.ReadAll(stdout) require.NoError(t, err) - require.Contains(t, string(out), "Message produced by kcat") - - t.Cleanup(func() { - if err := kcat.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate kcat container: %s", err) - } - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate redpanda container: %s", err) - } - - if err := rpNetwork.Remove(ctx); err != nil { - t.Fatalf("failed to remove network: %s", err) - } - }) } func TestRedpandaListener_InvalidPort(t *testing.T) { @@ -542,34 +498,28 @@ func TestRedpandaListener_InvalidPort(t *testing.T) { // 1. Create network RPNetwork, err := network.New(ctx) require.NoError(t, err) + testcontainers.CleanupNetwork(t, RPNetwork) - // 2. Attempt Start Redpanda container - _, err = redpanda.Run(ctx, + // 2. Attempt Start Redpanda ctr + ctr, err := redpanda.Run(ctx, "redpandadata/redpanda:v23.2.18", redpanda.WithListener("redpanda:99092"), network.WithNetwork([]string{"redpanda-host"}, RPNetwork), ) - + testcontainers.CleanupContainer(t, ctr) require.Error(t, err) - require.Contains(t, err.Error(), "invalid port on listener redpanda:99092") - - t.Cleanup(func() { - if err := RPNetwork.Remove(ctx); err != nil { - t.Fatalf("failed to remove network: %s", err) - } - }) } func TestRedpandaListener_NoNetwork(t *testing.T) { ctx := context.Background() - // 1. Attempt Start Redpanda container - _, err := redpanda.Run(ctx, + // 1. Attempt Start Redpanda ctr + ctr, err := redpanda.Run(ctx, "redpandadata/redpanda:v23.2.18", redpanda.WithListener("redpanda:99092"), ) - + testcontainers.CleanupContainer(t, ctr) require.Error(t, err) require.Contains(t, err.Error(), "container must be attached to at least one network") diff --git a/modules/registry/examples_test.go b/modules/registry/examples_test.go index ada7e33b85..8742456eef 100644 --- a/modules/registry/examples_test.go +++ b/modules/registry/examples_test.go @@ -14,21 +14,21 @@ import ( func ExampleRun() { // runRegistryContainer { registryContainer, err := registry.Run(context.Background(), "registry:2.8.3") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := registryContainer.Terminate(context.Background()); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(registryContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := registryContainer.State(context.Background()) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -47,23 +47,26 @@ func ExampleRun_withAuthentication() { registry.WithData(filepath.Join("testdata", "data")), ) // } - if err != nil { - log.Fatalf("failed to start container: %s", err) - } defer func() { - if err := registryContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(registryContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } registryHost, err := registryContainer.HostAddress(ctx) if err != nil { - log.Fatalf("failed to get host: %s", err) // nolint:gocritic + log.Printf("failed to get host: %s", err) + return } cleanup, err := registry.SetDockerAuthConfig(registryHost, "testuser", "testpassword") if err != nil { - log.Fatalf("failed to set docker auth config: %s", err) // nolint:gocritic + log.Printf("failed to set docker auth config: %s", err) + return } defer cleanup() @@ -77,7 +80,6 @@ func ExampleRun_withAuthentication() { BuildArgs: map[string]*string{ "REGISTRY_HOST": ®istryHost, }, - PrintBuildLog: true, }, AlwaysPullImage: true, // make sure the authentication takes place ExposedPorts: []string{"6379/tcp"}, @@ -85,18 +87,20 @@ func ExampleRun_withAuthentication() { }, Started: true, }) - if err != nil { - log.Fatalf("failed to start container: %s", err) // nolint:gocritic - } defer func() { - if err := redisC.Terminate(context.Background()); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(redisC); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } state, err := redisC.State(context.Background()) if err != nil { - log.Fatalf("failed to get redis container state: %s", err) // nolint:gocritic + log.Printf("failed to get redis container state: %s", err) + return } fmt.Println(state.Running) @@ -113,18 +117,20 @@ func ExampleRun_pushImage() { registry.WithHtpasswdFile(filepath.Join("testdata", "auth", "htpasswd")), registry.WithData(filepath.Join("testdata", "data")), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } defer func() { - if err := registryContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(registryContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } registryHost, err := registryContainer.HostAddress(ctx) if err != nil { - log.Fatalf("failed to get host: %s", err) // nolint:gocritic + log.Printf("failed to get host: %s", err) + return } // Besides, we are also setting the authentication @@ -135,13 +141,14 @@ func ExampleRun_pushImage() { registryContainer.RegistryName, "testuser", "testpassword", ) if err != nil { - log.Fatalf("failed to set docker auth config: %s", err) // nolint:gocritic + log.Printf("failed to set docker auth config: %s", err) + return } defer cleanup() // build a custom redis image from the private registry, // using RegistryName of the container as the registry. - // We are agoing to build the image with a fixed tag + // We are going to build the image with a fixed tag // that matches the private registry, and we are going to // push it again to the registry after the build. @@ -155,9 +162,8 @@ func ExampleRun_pushImage() { BuildArgs: map[string]*string{ "REGISTRY_HOST": ®istryHost, }, - Repo: repo, - Tag: tag, - PrintBuildLog: true, + Repo: repo, + Tag: tag, }, AlwaysPullImage: true, // make sure the authentication takes place ExposedPorts: []string{"6379/tcp"}, @@ -165,21 +171,23 @@ func ExampleRun_pushImage() { }, Started: true, }) - if err != nil { - log.Fatalf("failed to start container: %s", err) // nolint:gocritic - } defer func() { - if err := redisC.Terminate(context.Background()); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(redisC); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // pushingImage { // repo is localhost:32878/customredis // tag is v1.2.3 err = registryContainer.PushImage(context.Background(), fmt.Sprintf("%s:%s", repo, tag)) if err != nil { - log.Fatalf("failed to push image: %s", err) // nolint:gocritic + log.Printf("failed to push image: %s", err) + return } // } @@ -192,7 +200,8 @@ func ExampleRun_pushImage() { // newImage is customredis:v1.2.3 err = registryContainer.DeleteImage(context.Background(), newImage) if err != nil { - log.Fatalf("failed to delete image: %s", err) // nolint:gocritic + log.Printf("failed to delete image: %s", err) + return } // } @@ -204,18 +213,20 @@ func ExampleRun_pushImage() { }, Started: true, }) - if err != nil { - log.Fatalf("failed to start container from %s: %s", newImage, err) // nolint:gocritic - } defer func() { - if err := newRedisC.Terminate(context.Background()); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(newRedisC); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container from %s: %s", newImage, err) + return + } state, err := newRedisC.State(context.Background()) if err != nil { - log.Fatalf("failed to get redis container state from %s: %s", newImage, err) // nolint:gocritic + log.Printf("failed to get redis container state from %s: %s", newImage, err) + return } fmt.Println(state.Running) diff --git a/modules/registry/registry.go b/modules/registry/registry.go index b554f8dcc7..6cfa3d537b 100644 --- a/modules/registry/registry.go +++ b/modules/registry/registry.go @@ -238,15 +238,17 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *RegistryContainer + if container != nil { + c = &RegistryContainer{Container: container} + } if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - c := &RegistryContainer{Container: container} - address, err := c.Address(ctx) if err != nil { - return c, err + return c, fmt.Errorf("address: %w", err) } c.RegistryName = strings.TrimPrefix(address, "http://") diff --git a/modules/registry/registry_test.go b/modules/registry/registry_test.go index d40f75125e..6b90349ff3 100644 --- a/modules/registry/registry_test.go +++ b/modules/registry/registry_test.go @@ -17,11 +17,11 @@ import ( func TestRegistry_unauthenticated(t *testing.T) { ctx := context.Background() - container, err := registry.Run(ctx, registry.DefaultImage) - terminateContainerOnEnd(t, ctx, container) + ctr, err := registry.Run(ctx, registry.DefaultImage) + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - httpAddress, err := container.Address(ctx) + httpAddress, err := ctr.Address(ctx) require.NoError(t, err) resp, err := http.Get(httpAddress + "/v2/_catalog") @@ -39,7 +39,7 @@ func TestRunContainer_authenticated(t *testing.T) { registry.WithHtpasswdFile(filepath.Join("testdata", "auth", "htpasswd")), registry.WithData(filepath.Join("testdata", "data")), ) - terminateContainerOnEnd(t, ctx, registryContainer) + testcontainers.CleanupContainer(t, registryContainer) require.NoError(t, err) // httpAddress { @@ -107,7 +107,7 @@ func TestRunContainer_authenticated(t *testing.T) { }, Started: true, }) - terminateContainerOnEnd(tt, ctx, redisC) + testcontainers.CleanupContainer(tt, redisC) require.Error(tt, err) require.Contains(tt, err.Error(), "unauthorized: authentication required") }) @@ -134,7 +134,7 @@ func TestRunContainer_authenticated(t *testing.T) { }, Started: true, }) - terminateContainerOnEnd(tt, ctx, redisC) + testcontainers.CleanupContainer(tt, redisC) require.NoError(tt, err) state, err := redisC.State(context.Background()) @@ -152,7 +152,7 @@ func TestRunContainer_authenticated_withCredentials(t *testing.T) { registry.WithHtpasswd("testuser:$2y$05$tTymaYlWwJOqie.bcSUUN.I.kxmo1m5TLzYQ4/ejJ46UMXGtq78EO"), ) // } - terminateContainerOnEnd(t, ctx, registryContainer) + testcontainers.CleanupContainer(t, registryContainer) require.NoError(t, err) httpAddress, err := registryContainer.Address(ctx) @@ -179,7 +179,7 @@ func TestRunContainer_wrongData(t *testing.T) { registry.WithHtpasswdFile(filepath.Join("testdata", "auth", "htpasswd")), registry.WithData(filepath.Join("testdata", "wrongdata")), ) - terminateContainerOnEnd(t, ctx, registryContainer) + testcontainers.CleanupContainer(t, registryContainer) require.NoError(t, err) registryHost, err := registryContainer.HostAddress(ctx) @@ -206,7 +206,7 @@ func TestRunContainer_wrongData(t *testing.T) { }, Started: true, }) - terminateContainerOnEnd(t, ctx, redisC) + testcontainers.CleanupContainer(t, redisC) require.Error(t, err) require.Contains(t, err.Error(), "manifest unknown") } @@ -223,16 +223,3 @@ func setAuthConfig(t *testing.T, host, username, password string) { t.Setenv("DOCKER_AUTH_CONFIG", string(auth)) } - -// terminateContainerOnEnd terminates the container when the test ends if it is not nil. -func terminateContainerOnEnd(tb testing.TB, ctx context.Context, container testcontainers.Container) { - tb.Helper() - - if container == nil { - return - } - - tb.Cleanup(func() { - require.NoError(tb, container.Terminate(ctx)) - }) -} diff --git a/modules/surrealdb/examples_test.go b/modules/surrealdb/examples_test.go index 2063903d42..7d5c13a598 100644 --- a/modules/surrealdb/examples_test.go +++ b/modules/surrealdb/examples_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/surrealdb" ) @@ -13,21 +14,21 @@ func ExampleRun() { ctx := context.Background() surrealdbContainer, err := surrealdb.Run(ctx, "surrealdb/surrealdb:v1.1.1") - if err != nil { - log.Fatal(err) - } - - // Clean up the container defer func() { - if err := surrealdbContainer.Terminate(ctx); err != nil { - log.Fatal(err) + if err := testcontainers.TerminateContainer(surrealdbContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Print(err) + return + } // } state, err := surrealdbContainer.State(ctx) if err != nil { - log.Fatal(err) // nolint:gocritic + log.Print(err) + return } fmt.Println(state.Running) diff --git a/modules/surrealdb/go.mod b/modules/surrealdb/go.mod index d3d2d049d6..8d740ce836 100644 --- a/modules/surrealdb/go.mod +++ b/modules/surrealdb/go.mod @@ -3,6 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/surrealdb go 1.22 require ( + github.com/stretchr/testify v1.9.0 github.com/surrealdb/surrealdb.go v0.2.1 github.com/testcontainers/testcontainers-go v0.33.0 ) @@ -16,6 +17,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -28,6 +30,7 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -39,6 +42,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -55,6 +59,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/surrealdb/go.sum b/modules/surrealdb/go.sum index d39dac7fa4..ffb535bb9f 100644 --- a/modules/surrealdb/go.sum +++ b/modules/surrealdb/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -54,6 +55,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -80,6 +85,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -178,6 +185,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/surrealdb/surrealdb.go b/modules/surrealdb/surrealdb.go index 1968ca5d98..cc9ae744dc 100644 --- a/modules/surrealdb/surrealdb.go +++ b/modules/surrealdb/surrealdb.go @@ -116,9 +116,14 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *SurrealDBContainer + if container != nil { + c = &SurrealDBContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &SurrealDBContainer{Container: container}, nil + return c, nil } diff --git a/modules/surrealdb/surrealdb_test.go b/modules/surrealdb/surrealdb_test.go index 7a3de29bfd..5823ca9e2f 100644 --- a/modules/surrealdb/surrealdb_test.go +++ b/modules/surrealdb/surrealdb_test.go @@ -4,133 +4,87 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" "github.com/surrealdb/surrealdb.go" + + "github.com/testcontainers/testcontainers-go" ) func TestSurrealDBSelect(t *testing.T) { ctx := context.Background() - container, err := Run(ctx, "surrealdb/surrealdb:v1.1.1") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := Run(ctx, "surrealdb/surrealdb:v1.1.1") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) - url, err := container.URL(ctx) - if err != nil { - t.Fatal(err) - } + url, err := ctr.URL(ctx) + require.NoError(t, err) db, err := surrealdb.New(url) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if _, err := db.Use("test", "test"); err != nil { - t.Fatal(err) - } + _, err = db.Use("test", "test") + require.NoError(t, err) - if _, err := db.Create("person.tobie", map[string]any{ + _, err = db.Create("person.tobie", map[string]any{ "title": "Founder & CEO", "name": map[string]string{ "first": "Tobie", "last": "Morgan Hitchcock", }, "marketing": true, - }); err != nil { - t.Fatal(err) - } + }) + require.NoError(t, err) result, err := db.Select("person.tobie") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) resultData := result.([]any)[0].(map[string]interface{}) - if resultData["title"] != "Founder & CEO" { - t.Fatal("title is not Founder & CEO") - } - if resultData["name"].(map[string]interface{})["first"] != "Tobie" { - t.Fatal("name.first is not Tobie") - } - if resultData["name"].(map[string]interface{})["last"] != "Morgan Hitchcock" { - t.Fatal("name.last is not Morgan Hitchcock") - } - if resultData["marketing"] != true { - t.Fatal("marketing is not true") - } + require.Equal(t, "Founder & CEO", resultData["title"]) + require.Equal(t, "Tobie", resultData["name"].(map[string]interface{})["first"]) + require.Equal(t, "Morgan Hitchcock", resultData["name"].(map[string]interface{})["last"]) + require.Equal(t, true, resultData["marketing"]) } func TestSurrealDBWithAuth(t *testing.T) { ctx := context.Background() - container, err := Run(ctx, "surrealdb/surrealdb:v1.1.1", WithAuthentication()) - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := Run(ctx, "surrealdb/surrealdb:v1.1.1", WithAuthentication()) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) // websocketURL { - url, err := container.URL(ctx) + url, err := ctr.URL(ctx) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) db, err := surrealdb.New(url) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer db.Close() - if _, err := db.Signin(map[string]string{"user": "root", "pass": "root"}); err != nil { - t.Fatal(err) - } + _, err = db.Signin(map[string]string{"user": "root", "pass": "root"}) + require.NoError(t, err) - if _, err := db.Use("test", "test"); err != nil { - t.Fatal(err) - } + _, err = db.Use("test", "test") + require.NoError(t, err) - if _, err := db.Create("person.tobie", map[string]any{ + _, err = db.Create("person.tobie", map[string]any{ "title": "Founder & CEO", "name": map[string]string{ "first": "Tobie", "last": "Morgan Hitchcock", }, "marketing": true, - }); err != nil { - t.Fatal(err) - } + }) + require.NoError(t, err) result, err := db.Select("person.tobie") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) resultData := result.([]any)[0].(map[string]interface{}) - if resultData["title"] != "Founder & CEO" { - t.Fatal("title is not Founder & CEO") - } - if resultData["name"].(map[string]interface{})["first"] != "Tobie" { - t.Fatal("name.first is not Tobie") - } - if resultData["name"].(map[string]interface{})["last"] != "Morgan Hitchcock" { - t.Fatal("name.last is not Morgan Hitchcock") - } - if resultData["marketing"] != true { - t.Fatal("marketing is not true") - } + require.Equal(t, "Founder & CEO", resultData["title"]) + require.Equal(t, "Tobie", resultData["name"].(map[string]interface{})["first"]) + require.Equal(t, "Morgan Hitchcock", resultData["name"].(map[string]interface{})["last"]) + require.Equal(t, true, resultData["marketing"]) } diff --git a/modules/valkey/examples_test.go b/modules/valkey/examples_test.go index b302fc6326..7e1d261850 100644 --- a/modules/valkey/examples_test.go +++ b/modules/valkey/examples_test.go @@ -6,6 +6,7 @@ import ( "log" "path/filepath" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/valkey" ) @@ -19,21 +20,21 @@ func ExampleRun() { valkey.WithLogLevel(valkey.LogLevelVerbose), valkey.WithConfigFile(filepath.Join("testdata", "valkey7.conf")), ) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := valkeyContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(valkeyContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := valkeyContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/valkey/valkey.go b/modules/valkey/valkey.go index e3b3728ddd..00f4e91186 100644 --- a/modules/valkey/valkey.go +++ b/modules/valkey/valkey.go @@ -71,11 +71,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *ValkeyContainer + if container != nil { + c = &ValkeyContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &ValkeyContainer{Container: container}, nil + return c, nil } // WithConfigFile sets the config file to be used for the valkey container, and sets the command to run the valkey server diff --git a/modules/valkey/valkey_test.go b/modules/valkey/valkey_test.go index c440f79179..ed4fd75d12 100644 --- a/modules/valkey/valkey_test.go +++ b/modules/valkey/valkey_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/valkey-io/valkey-go" + "github.com/testcontainers/testcontainers-go" tcvalkey "github.com/testcontainers/testcontainers-go/modules/valkey" ) @@ -18,12 +19,8 @@ func TestIntegrationSetGet(t *testing.T) { ctx := context.Background() valkeyContainer, err := tcvalkey.Run(ctx, "docker.io/valkey/valkey:7.2.5") + testcontainers.CleanupContainer(t, valkeyContainer) require.NoError(t, err) - t.Cleanup(func() { - if err := valkeyContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) assertSetsGets(t, ctx, valkeyContainer, 1) } @@ -32,12 +29,8 @@ func TestValkeyWithConfigFile(t *testing.T) { ctx := context.Background() valkeyContainer, err := tcvalkey.Run(ctx, "docker.io/valkey/valkey:7.2.5", tcvalkey.WithConfigFile(filepath.Join("testdata", "valkey7.conf"))) + testcontainers.CleanupContainer(t, valkeyContainer) require.NoError(t, err) - t.Cleanup(func() { - if err := valkeyContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) assertSetsGets(t, ctx, valkeyContainer, 1) } @@ -59,12 +52,8 @@ func TestValkeyWithImage(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { valkeyContainer, err := tcvalkey.Run(ctx, tt.image, tcvalkey.WithConfigFile(filepath.Join("testdata", "valkey7.conf"))) + testcontainers.CleanupContainer(t, valkeyContainer) require.NoError(t, err) - t.Cleanup(func() { - if err := valkeyContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) assertSetsGets(t, ctx, valkeyContainer, 1) }) @@ -75,12 +64,8 @@ func TestValkeyWithLogLevel(t *testing.T) { ctx := context.Background() valkeyContainer, err := tcvalkey.Run(ctx, "docker.io/valkey/valkey:7.2.5", tcvalkey.WithLogLevel(tcvalkey.LogLevelVerbose)) + testcontainers.CleanupContainer(t, valkeyContainer) require.NoError(t, err) - t.Cleanup(func() { - if err := valkeyContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) assertSetsGets(t, ctx, valkeyContainer, 10) } @@ -89,12 +74,8 @@ func TestValkeyWithSnapshotting(t *testing.T) { ctx := context.Background() valkeyContainer, err := tcvalkey.Run(ctx, "docker.io/valkey/valkey:7.2.5", tcvalkey.WithSnapshotting(10, 1)) + testcontainers.CleanupContainer(t, valkeyContainer) require.NoError(t, err) - t.Cleanup(func() { - if err := valkeyContainer.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) assertSetsGets(t, ctx, valkeyContainer, 10) } diff --git a/modules/vault/examples_test.go b/modules/vault/examples_test.go index 75dc908f6b..0b3d257c06 100644 --- a/modules/vault/examples_test.go +++ b/modules/vault/examples_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/exec" "github.com/testcontainers/testcontainers-go/modules/vault" ) @@ -14,21 +15,21 @@ func ExampleRun() { ctx := context.Background() vaultContainer, err := vault.Run(ctx, "hashicorp/vault:1.13.0") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := vaultContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(vaultContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := vaultContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -42,21 +43,21 @@ func ExampleRun_withToken() { ctx := context.Background() vaultContainer, err := vault.Run(ctx, "hashicorp/vault:1.13.0", vault.WithToken("MyToKeN")) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := vaultContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(vaultContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := vaultContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -66,7 +67,8 @@ func ExampleRun_withToken() { } exitCode, _, err := vaultContainer.Exec(ctx, cmds, exec.Multiplexed()) if err != nil { - log.Fatalf("failed to execute command: %s", err) + log.Printf("failed to execute command: %s", err) + return } fmt.Println(exitCode) @@ -87,21 +89,21 @@ func ExampleRun_withInitCommand() { "write --force auth/approle/role/myrole", // Create a role "write secret/testing top_secret=password123", // Create a secret )) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := vaultContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(vaultContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := vaultContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/vault/vault.go b/modules/vault/vault.go index 37237748ed..b679d45c21 100644 --- a/modules/vault/vault.go +++ b/modules/vault/vault.go @@ -52,11 +52,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *VaultContainer + if container != nil { + c = &VaultContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &VaultContainer{container}, nil + return c, nil } // WithToken is a container option function that sets the root token for the Vault diff --git a/modules/vault/vault_test.go b/modules/vault/vault_test.go index 23a52cee57..c55f792c2c 100644 --- a/modules/vault/vault_test.go +++ b/modules/vault/vault_test.go @@ -3,7 +3,6 @@ package vault_test import ( "context" "io" - "log" "net/http" "testing" "time" @@ -35,6 +34,7 @@ func TestVault(t *testing.T) { } vaultContainer, err := testcontainervault.Run(ctx, "hashicorp/vault:1.13.0", opts...) + testcontainers.CleanupContainer(t, vaultContainer) require.NoError(t, err) // httpHostAddress { @@ -118,11 +118,4 @@ func TestVault(t *testing.T) { assert.Equal(t, "bar", s.Data.Data["foo"]) }) }) - - t.Cleanup(func() { - // Clean up the vault after the test is complete - if err := vaultContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate vault: %s", err) - } - }) } diff --git a/modules/vearch/examples_test.go b/modules/vearch/examples_test.go index d75bd8e66a..97ef8d8fe4 100644 --- a/modules/vearch/examples_test.go +++ b/modules/vearch/examples_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/vearch" ) @@ -13,21 +14,21 @@ func ExampleRun() { ctx := context.Background() vearchContainer, err := vearch.Run(ctx, "vearch/vearch:3.5.1") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := vearchContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(vearchContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := vearchContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) diff --git a/modules/vearch/go.mod b/modules/vearch/go.mod index eaad237db7..18363db517 100644 --- a/modules/vearch/go.mod +++ b/modules/vearch/go.mod @@ -2,7 +2,10 @@ module github.com/testcontainers/testcontainers-go/modules/vearch go 1.22.0 -require github.com/testcontainers/testcontainers-go v0.33.0 +require ( + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 +) require ( dario.cat/mergo v1.0.0 // indirect @@ -13,6 +16,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -24,6 +28,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -35,6 +40,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect @@ -51,6 +57,7 @@ require ( golang.org/x/sys v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/vearch/go.sum b/modules/vearch/go.sum index ed514ea5ef..28367d0020 100644 --- a/modules/vearch/go.sum +++ b/modules/vearch/go.sum @@ -16,6 +16,7 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -52,6 +53,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -78,6 +83,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -174,6 +181,8 @@ google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvy google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/modules/vearch/vearch.go b/modules/vearch/vearch.go index dccedacad1..3338eac0fe 100644 --- a/modules/vearch/vearch.go +++ b/modules/vearch/vearch.go @@ -52,11 +52,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *VearchContainer + if container != nil { + c = &VearchContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &VearchContainer{Container: container}, nil + return c, nil } // RESTEndpoint returns the REST endpoint of the Vearch container diff --git a/modules/vearch/vearch_test.go b/modules/vearch/vearch_test.go index f73abda7de..43c0f7e1f5 100644 --- a/modules/vearch/vearch_test.go +++ b/modules/vearch/vearch_test.go @@ -5,40 +5,30 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/vearch" ) func TestVearch(t *testing.T) { ctx := context.Background() - container, err := vearch.Run(ctx, "vearch/vearch:3.5.1") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := vearch.Run(ctx, "vearch/vearch:3.5.1") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) t.Run("REST Endpoint", func(tt *testing.T) { // restEndpoint { - restEndpoint, err := container.RESTEndpoint(ctx) + restEndpoint, err := ctr.RESTEndpoint(ctx) // } - if err != nil { - tt.Fatalf("failed to get REST endpoint: %s", err) - } + require.NoError(t, err) cli := &http.Client{} resp, err := cli.Get(restEndpoint) - if err != nil { - tt.Fatalf("failed to perform GET request: %s", err) - } + require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - tt.Fatalf("unexpected status code: %d", resp.StatusCode) - } + + require.Equal(t, http.StatusOK, resp.StatusCode) }) } diff --git a/modules/weaviate/examples_test.go b/modules/weaviate/examples_test.go index d6c8f50988..2f8e4f84a4 100644 --- a/modules/weaviate/examples_test.go +++ b/modules/weaviate/examples_test.go @@ -20,21 +20,21 @@ func ExampleRun() { ctx := context.Background() weaviateContainer, err := tcweaviate.Run(ctx, "semitechnologies/weaviate:1.24.5") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - - // Clean up the container defer func() { - if err := weaviateContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(weaviateContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } // } state, err := weaviateContainer.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -48,24 +48,26 @@ func ExampleRun_connectWithClient() { ctx := context.Background() weaviateContainer, err := tcweaviate.Run(ctx, "semitechnologies/weaviate:1.23.9") - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := weaviateContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(weaviateContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } scheme, host, err := weaviateContainer.HttpHostAddress(ctx) if err != nil { - log.Fatalf("failed to get http schema and host: %s", err) // nolint:gocritic + log.Printf("failed to get http schema and host: %s", err) + return } grpcHost, err := weaviateContainer.GrpcHostAddress(ctx) if err != nil { - log.Fatalf("failed to get gRPC host: %s", err) // nolint:gocritic + log.Printf("failed to get gRPC host: %s", err) + return } connectionClient := &http.Client{} @@ -115,24 +117,26 @@ func ExampleRun_connectWithClientWithModules() { } weaviateContainer, err := tcweaviate.Run(ctx, "semitechnologies/weaviate:1.25.5", opts...) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := weaviateContainer.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) // nolint:gocritic + if err := testcontainers.TerminateContainer(weaviateContainer); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } scheme, host, err := weaviateContainer.HttpHostAddress(ctx) if err != nil { - log.Fatalf("failed to get http schema and host: %s", err) // nolint:gocritic + log.Printf("failed to get http schema and host: %s", err) + return } grpcHost, err := weaviateContainer.GrpcHostAddress(ctx) if err != nil { - log.Fatalf("failed to get gRPC host: %s", err) // nolint:gocritic + log.Printf("failed to get gRPC host: %s", err) + return } connectionClient := &http.Client{} diff --git a/modules/weaviate/go.mod b/modules/weaviate/go.mod index 6572fb3607..f8b7d6895a 100644 --- a/modules/weaviate/go.mod +++ b/modules/weaviate/go.mod @@ -3,7 +3,8 @@ module github.com/testcontainers/testcontainers-go/modules/weaviate go 1.22 require ( - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.32.0 github.com/weaviate/weaviate-go-client/v4 v4.13.1 google.golang.org/grpc v1.64.1 ) @@ -20,6 +21,7 @@ require ( github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect @@ -56,6 +58,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect diff --git a/modules/weaviate/weaviate.go b/modules/weaviate/weaviate.go index 93665efc66..3e0830fe3b 100644 --- a/modules/weaviate/weaviate.go +++ b/modules/weaviate/weaviate.go @@ -54,11 +54,16 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *WeaviateContainer + if container != nil { + c = &WeaviateContainer{Container: container} + } + if err != nil { - return nil, err + return c, fmt.Errorf("generic container: %w", err) } - return &WeaviateContainer{Container: container}, nil + return c, nil } // HttpHostAddress returns the schema and host of the Weaviate container. diff --git a/modules/weaviate/weaviate_test.go b/modules/weaviate/weaviate_test.go index bb44e7a90a..d6dae679e6 100644 --- a/modules/weaviate/weaviate_test.go +++ b/modules/weaviate/weaviate_test.go @@ -6,53 +6,41 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/require" wvt "github.com/weaviate/weaviate-go-client/v4/weaviate" wvtgrpc "github.com/weaviate/weaviate-go-client/v4/weaviate/grpc" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/health/grpc_health_v1" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/weaviate" ) func TestWeaviate(t *testing.T) { ctx := context.Background() - container, err := weaviate.Run(ctx, "semitechnologies/weaviate:1.25.5") - if err != nil { - t.Fatal(err) - } - - // Clean up the container after the test is complete - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := weaviate.Run(ctx, "semitechnologies/weaviate:1.25.5") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) t.Run("HttpHostAddress", func(tt *testing.T) { // httpHostAddress { - schema, host, err := container.HttpHostAddress(ctx) + schema, host, err := ctr.HttpHostAddress(ctx) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) cli := &http.Client{} resp, err := cli.Get(fmt.Sprintf("%s://%s", schema, host)) - if err != nil { - tt.Fatalf("failed to perform GET request: %s", err) - } + require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - tt.Fatalf("unexpected status code: %d", resp.StatusCode) - } + require.Equal(t, http.StatusOK, resp.StatusCode) }) t.Run("GrpcHostAddress", func(tt *testing.T) { // gRPCHostAddress { - host, err := container.GrpcHostAddress(ctx) + host, err := ctr.GrpcHostAddress(ctx) // } if err != nil { t.Fatal(err) @@ -76,11 +64,11 @@ func TestWeaviate(t *testing.T) { }) t.Run("Weaviate client", func(tt *testing.T) { - httpScheme, httpHost, err := container.HttpHostAddress(ctx) + httpScheme, httpHost, err := ctr.HttpHostAddress(ctx) if err != nil { tt.Fatal(err) } - grpcHost, err := container.GrpcHostAddress(ctx) + grpcHost, err := ctr.GrpcHostAddress(ctx) if err != nil { tt.Fatal(err) } diff --git a/mounts_test.go b/mounts_test.go index 533b584feb..b1ac51d305 100644 --- a/mounts_test.go +++ b/mounts_test.go @@ -171,13 +171,14 @@ func TestContainerMounts_PrepareMounts(t *testing.T) { } func TestCreateContainerWithVolume(t *testing.T) { + volumeName := "test-volume" // volumeMounts { req := testcontainers.ContainerRequest{ Image: "alpine", Mounts: testcontainers.ContainerMounts{ { Source: testcontainers.GenericVolumeMountSource{ - Name: "test-volume", + Name: volumeName, }, Target: "/data", }, @@ -190,8 +191,8 @@ func TestCreateContainerWithVolume(t *testing.T) { ContainerRequest: req, Started: true, }) + testcontainers.CleanupContainer(t, c, testcontainers.RemoveVolumes(volumeName)) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, c) // Check if volume is created client, err := testcontainers.NewDockerClientWithOpts(ctx) @@ -204,12 +205,13 @@ func TestCreateContainerWithVolume(t *testing.T) { } func TestMountsReceiveRyukLabels(t *testing.T) { + volumeName := "app-data" req := testcontainers.ContainerRequest{ Image: "alpine", Mounts: testcontainers.ContainerMounts{ { Source: testcontainers.GenericVolumeMountSource{ - Name: "app-data", + Name: volumeName, }, Target: "/data", }, @@ -223,18 +225,18 @@ func TestMountsReceiveRyukLabels(t *testing.T) { // Ensure the volume is removed before creating the container // otherwise the volume will be reused and the labels won't be set. - err = client.VolumeRemove(ctx, "app-data", true) + err = client.VolumeRemove(ctx, volumeName, true) require.NoError(t, err) c, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, }) + testcontainers.CleanupContainer(t, c, testcontainers.RemoveVolumes(volumeName)) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, c) // Check if volume is created with the expected labels. - volume, err := client.VolumeInspect(ctx, "app-data") + volume, err := client.VolumeInspect(ctx, volumeName) require.NoError(t, err) require.Equal(t, testcontainers.GenericLabels(), volume.Labels) } diff --git a/network/examples_test.go b/network/examples_test.go index 7335b85564..a6b6bec495 100644 --- a/network/examples_test.go +++ b/network/examples_test.go @@ -21,7 +21,7 @@ func ExampleNew() { } defer func() { if err := net.Remove(ctx); err != nil { - log.Fatalf("failed to remove network: %s", err) + log.Printf("failed to remove network: %s", err) } }() // } @@ -62,7 +62,7 @@ func ExampleNew_withOptions() { } defer func() { if err := net.Remove(ctx); err != nil { - log.Fatalf("failed to remove network: %s", err) + log.Printf("failed to remove network: %s", err) } }() // } diff --git a/network/network_test.go b/network/network_test.go index 4ff80e2bed..5cee817ecc 100644 --- a/network/network_test.go +++ b/network/network_test.go @@ -7,7 +7,6 @@ import ( "github.com/docker/docker/api/types/filters" dockernetwork "github.com/docker/docker/api/types/network" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" @@ -26,21 +25,17 @@ func TestNew(t *testing.T) { net, err := network.New(ctx, network.WithAttachable(), - // Makes the network internal only, meaning the host machine cannot access it. - // Remove or use `network.WithDriver("bridge")` to change the network's mode. - network.WithInternal(), + network.WithDriver("bridge"), network.WithLabels(map[string]string{"this-is-a-test": "value"}), ) require.NoError(t, err) defer func() { - if err := net.Remove(ctx); err != nil { - t.Fatalf("failed to remove network: %s", err) - } + require.NoError(t, net.Remove(ctx)) }() networkName := net.Name - nginxC, _ := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + nginxC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ Image: "nginx:alpine", ExposedPorts: []string{ @@ -52,11 +47,8 @@ func TestNew(t *testing.T) { }, Started: true, }) - defer func() { - if err := nginxC.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }() + testcontainers.CleanupContainer(t, nginxC) + require.NoError(t, err) client, err := testcontainers.NewDockerClientWithOpts(context.Background()) require.NoError(t, err) @@ -65,19 +57,16 @@ func TestNew(t *testing.T) { Filters: filters.NewArgs(filters.Arg("name", networkName)), }) require.NoError(t, err) - - assert.Len(t, resources, 1) + require.Len(t, resources, 1) newNetwork := resources[0] - expectedLabels := testcontainers.GenericLabels() expectedLabels["this-is-a-test"] = "true" - assert.True(t, newNetwork.Attachable) - assert.True(t, newNetwork.Internal) - assert.Equal(t, "value", newNetwork.Labels["this-is-a-test"]) - - require.NoError(t, err) + require.True(t, newNetwork.Attachable) + require.False(t, newNetwork.Internal) + require.Equal(t, "value", newNetwork.Labels["this-is-a-test"]) + require.NoError(t, testcontainers.TerminateContainer(nginxC)) } // testNetworkAliases { @@ -85,12 +74,8 @@ func TestContainerAttachedToNewNetwork(t *testing.T) { ctx := context.Background() newNetwork, err := network.New(ctx) - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { - require.NoError(t, newNetwork.Remove(ctx)) - }) + require.NoError(t, err) + testcontainers.CleanupNetwork(t, newNetwork) networkName := newNetwork.Name @@ -113,33 +98,21 @@ func TestContainerAttachedToNewNetwork(t *testing.T) { } nginx, err := testcontainers.GenericContainer(ctx, gcr) + testcontainers.CleanupContainer(t, nginx) require.NoError(t, err) - defer func() { - require.NoError(t, nginx.Terminate(ctx)) - }() networks, err := nginx.Networks(ctx) - if err != nil { - t.Fatal(err) - } - if len(networks) != 1 { - t.Errorf("Expected networks 1. Got '%d'.", len(networks)) - } + require.NoError(t, err) + require.Len(t, networks, 1) + nw := networks[0] - if nw != networkName { - t.Errorf("Expected network name '%s'. Got '%s'.", networkName, nw) - } + require.Equal(t, networkName, nw) networkAliases, err := nginx.NetworkAliases(ctx) - if err != nil { - t.Fatal(err) - } - if len(networkAliases) != 1 { - t.Errorf("Expected network aliases for 1 network. Got '%d'.", len(networkAliases)) - } + require.NoError(t, err) + require.Len(t, networkAliases, 1) networkAlias := networkAliases[networkName] - require.NotEmpty(t, networkAlias) for _, alias := range aliases { @@ -147,12 +120,8 @@ func TestContainerAttachedToNewNetwork(t *testing.T) { } networkIP, err := nginx.ContainerIP(ctx) - if err != nil { - t.Fatal(err) - } - if len(networkIP) == 0 { - t.Errorf("Expected an IP address, got %v", networkIP) - } + require.NoError(t, err) + require.NotEmpty(t, networkIP) } // } @@ -161,12 +130,8 @@ func TestContainerIPs(t *testing.T) { ctx := context.Background() newNetwork, err := network.New(ctx) - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { - require.NoError(t, newNetwork.Remove(ctx)) - }) + require.NoError(t, err) + testcontainers.CleanupNetwork(t, newNetwork) networkName := newNetwork.Name @@ -184,19 +149,12 @@ func TestContainerIPs(t *testing.T) { }, Started: true, }) + testcontainers.CleanupContainer(t, nginx) require.NoError(t, err) - defer func() { - require.NoError(t, nginx.Terminate(ctx)) - }() ips, err := nginx.ContainerIPs(ctx) - if err != nil { - t.Fatal(err) - } - - if len(ips) != 2 { - t.Errorf("Expected two IP addresses, got %v", len(ips)) - } + require.NoError(t, err) + require.Len(t, ips, 2) } func TestContainerWithReaperNetwork(t *testing.T) { @@ -212,10 +170,7 @@ func TestContainerWithReaperNetwork(t *testing.T) { for i := 0; i < maxNetworksCount; i++ { n, err := network.New(ctx) require.NoError(t, err) - // use t.Cleanup to run after terminateContainerOnEnd - t.Cleanup(func() { - require.NoError(t, n.Remove(ctx)) - }) + testcontainers.CleanupNetwork(t, n) networks = append(networks, n.Name) } @@ -232,11 +187,8 @@ func TestContainerWithReaperNetwork(t *testing.T) { }, Started: true, }) - + testcontainers.CleanupContainer(t, nginx) require.NoError(t, err) - defer func() { - require.NoError(t, nginx.Terminate(ctx)) - }() containerId := nginx.GetContainerID() @@ -246,21 +198,17 @@ func TestContainerWithReaperNetwork(t *testing.T) { cnt, err := cli.ContainerInspect(ctx, containerId) require.NoError(t, err) - assert.Len(t, cnt.NetworkSettings.Networks, maxNetworksCount) - assert.NotNil(t, cnt.NetworkSettings.Networks[networks[0]]) - assert.NotNil(t, cnt.NetworkSettings.Networks[networks[1]]) + require.Len(t, cnt.NetworkSettings.Networks, maxNetworksCount) + require.NotNil(t, cnt.NetworkSettings.Networks[networks[0]]) + require.NotNil(t, cnt.NetworkSettings.Networks[networks[1]]) } func TestMultipleContainersInTheNewNetwork(t *testing.T) { ctx := context.Background() net, err := network.New(ctx, network.WithDriver("bridge")) - if err != nil { - t.Fatal("cannot create network") - } - defer func() { - require.NoError(t, net.Remove(ctx)) - }() + require.NoError(t, err) + testcontainers.CleanupNetwork(t, net) networkName := net.Name @@ -271,12 +219,8 @@ func TestMultipleContainersInTheNewNetwork(t *testing.T) { }, Started: true, }) - if err != nil { - t.Fatal(err) - } - defer func() { - require.NoError(t, c1.Terminate(ctx)) - }() + testcontainers.CleanupContainer(t, c1) + require.NoError(t, err) c2, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ @@ -285,13 +229,8 @@ func TestMultipleContainersInTheNewNetwork(t *testing.T) { }, Started: true, }) - if err != nil { - t.Fatal(err) - return - } - defer func() { - require.NoError(t, c2.Terminate(ctx)) - }() + testcontainers.CleanupContainer(t, c2) + require.NoError(t, err) pNets, err := c1.Networks(ctx) require.NoError(t, err) @@ -299,11 +238,11 @@ func TestMultipleContainersInTheNewNetwork(t *testing.T) { rNets, err := c2.Networks(ctx) require.NoError(t, err) - assert.Len(t, pNets, 1) - assert.Len(t, rNets, 1) + require.Len(t, pNets, 1) + require.Len(t, rNets, 1) - assert.Equal(t, networkName, pNets[0]) - assert.Equal(t, networkName, rNets[0]) + require.Equal(t, networkName, pNets[0]) + require.Equal(t, networkName, rNets[0]) } func TestNew_withOptions(t *testing.T) { @@ -329,12 +268,8 @@ func TestNew_withOptions(t *testing.T) { network.WithDriver("bridge"), ) // } - if err != nil { - t.Fatal("cannot create network: ", err) - } - defer func() { - require.NoError(t, net.Remove(ctx)) - }() + require.NoError(t, err) + testcontainers.CleanupNetwork(t, net) networkName := net.Name @@ -349,32 +284,24 @@ func TestNew_withOptions(t *testing.T) { }, }, }) + testcontainers.CleanupContainer(t, nginx) require.NoError(t, err) - defer func() { - require.NoError(t, nginx.Terminate(ctx)) - }() provider, err := testcontainers.ProviderDocker.GetProvider() - if err != nil { - t.Fatal("Cannot get Provider") - } + require.NoError(t, err) defer provider.Close() //nolint:staticcheck foundNetwork, err := provider.GetNetwork(ctx, testcontainers.NetworkRequest{Name: networkName}) - if err != nil { - t.Fatal("Cannot get created network by name") - } - assert.Equal(t, ipamConfig, foundNetwork.IPAM) + require.NoError(t, err) + require.Equal(t, ipamConfig, foundNetwork.IPAM) } func TestWithNetwork(t *testing.T) { // first create the network to be reused nw, err := network.New(context.Background(), network.WithLabels(map[string]string{"network-type": "unique"})) require.NoError(t, err) - defer func() { - require.NoError(t, nw.Remove(context.Background())) - }() + testcontainers.CleanupNetwork(t, nw) networkName := nw.Name @@ -387,11 +314,11 @@ func TestWithNetwork(t *testing.T) { err := network.WithNetwork([]string{"alias"}, nw)(&req) require.NoError(t, err) - assert.Len(t, req.Networks, 1) - assert.Equal(t, networkName, req.Networks[0]) + require.Len(t, req.Networks, 1) + require.Equal(t, networkName, req.Networks[0]) - assert.Len(t, req.NetworkAliases, 1) - assert.Equal(t, map[string][]string{networkName: {"alias"}}, req.NetworkAliases) + require.Len(t, req.NetworkAliases, 1) + require.Equal(t, map[string][]string{networkName: {"alias"}}, req.NetworkAliases) } // verify that the network is created only once @@ -402,17 +329,17 @@ func TestWithNetwork(t *testing.T) { Filters: filters.NewArgs(filters.Arg("name", networkName)), }) require.NoError(t, err) - assert.Len(t, resources, 1) + require.Len(t, resources, 1) newNetwork := resources[0] expectedLabels := testcontainers.GenericLabels() expectedLabels["network-type"] = "unique" - assert.Equal(t, networkName, newNetwork.Name) - assert.False(t, newNetwork.Attachable) - assert.False(t, newNetwork.Internal) - assert.Equal(t, expectedLabels, newNetwork.Labels) + require.Equal(t, networkName, newNetwork.Name) + require.False(t, newNetwork.Attachable) + require.False(t, newNetwork.Internal) + require.Equal(t, expectedLabels, newNetwork.Labels) } func TestWithSyntheticNetwork(t *testing.T) { @@ -431,11 +358,11 @@ func TestWithSyntheticNetwork(t *testing.T) { err := network.WithNetwork([]string{"alias"}, nw)(&req) require.NoError(t, err) - assert.Len(t, req.Networks, 1) - assert.Equal(t, networkName, req.Networks[0]) + require.Len(t, req.Networks, 1) + require.Equal(t, networkName, req.Networks[0]) - assert.Len(t, req.NetworkAliases, 1) - assert.Equal(t, map[string][]string{networkName: {"alias"}}, req.NetworkAliases) + require.Len(t, req.NetworkAliases, 1) + require.Equal(t, map[string][]string{networkName: {"alias"}}, req.NetworkAliases) // verify that the network is created only once client, err := testcontainers.NewDockerClientWithOpts(context.Background()) @@ -445,14 +372,12 @@ func TestWithSyntheticNetwork(t *testing.T) { Filters: filters.NewArgs(filters.Arg("name", networkName)), }) require.NoError(t, err) - assert.Empty(t, resources) // no Docker network was created + require.Empty(t, resources) // no Docker network was created c, err := testcontainers.GenericContainer(context.Background(), req) + testcontainers.CleanupContainer(t, c) require.NoError(t, err) - assert.NotNil(t, c) - defer func() { - require.NoError(t, c.Terminate(context.Background())) - }() + require.NotNil(t, c) } func TestWithNewNetwork(t *testing.T) { @@ -466,13 +391,12 @@ func TestWithNewNetwork(t *testing.T) { network.WithLabels(map[string]string{"this-is-a-test": "value"}), )(&req) require.NoError(t, err) - - assert.Len(t, req.Networks, 1) + require.Len(t, req.Networks, 1) networkName := req.Networks[0] - assert.Len(t, req.NetworkAliases, 1) - assert.Equal(t, map[string][]string{networkName: {"alias"}}, req.NetworkAliases) + require.Len(t, req.NetworkAliases, 1) + require.Equal(t, map[string][]string{networkName: {"alias"}}, req.NetworkAliases) client, err := testcontainers.NewDockerClientWithOpts(context.Background()) require.NoError(t, err) @@ -481,7 +405,7 @@ func TestWithNewNetwork(t *testing.T) { Filters: filters.NewArgs(filters.Arg("name", networkName)), }) require.NoError(t, err) - assert.Len(t, resources, 1) + require.Len(t, resources, 1) newNetwork := resources[0] defer func() { @@ -491,10 +415,10 @@ func TestWithNewNetwork(t *testing.T) { expectedLabels := testcontainers.GenericLabels() expectedLabels["this-is-a-test"] = "value" - assert.Equal(t, networkName, newNetwork.Name) - assert.True(t, newNetwork.Attachable) - assert.True(t, newNetwork.Internal) - assert.Equal(t, expectedLabels, newNetwork.Labels) + require.Equal(t, networkName, newNetwork.Name) + require.True(t, newNetwork.Attachable) + require.True(t, newNetwork.Internal) + require.Equal(t, expectedLabels, newNetwork.Labels) } func TestWithNewNetworkContextTimeout(t *testing.T) { @@ -513,6 +437,6 @@ func TestWithNewNetworkContextTimeout(t *testing.T) { require.Error(t, err) // we do not want to fail, just skip the network creation - assert.Empty(t, req.Networks) - assert.Empty(t, req.NetworkAliases) + require.Empty(t, req.Networks) + require.Empty(t, req.NetworkAliases) } diff --git a/options_test.go b/options_test.go index e19ecde96e..c8a67b0b06 100644 --- a/options_test.go +++ b/options_test.go @@ -93,7 +93,7 @@ func TestWithLogConsumers(t *testing.T) { ctx := context.Background() c, err := testcontainers.GenericContainer(ctx, req) - terminateContainerOnEnd(t, ctx, c) + testcontainers.CleanupContainer(t, c) // we expect an error because the MySQL environment variables are not set // but this is expected because we just want to test the log consumer require.Error(t, err) @@ -119,11 +119,8 @@ func TestWithStartupCommand(t *testing.T) { assert.Len(t, req.LifecycleHooks[0].PostStarts, 1) c, err := testcontainers.GenericContainer(context.Background(), req) + testcontainers.CleanupContainer(t, c) require.NoError(t, err) - defer func() { - err = c.Terminate(context.Background()) - require.NoError(t, err) - }() _, reader, err := c.Exec(context.Background(), []string{"ls", "/tmp/.testcontainers"}, exec.Multiplexed()) require.NoError(t, err) @@ -151,11 +148,8 @@ func TestWithAfterReadyCommand(t *testing.T) { assert.Len(t, req.LifecycleHooks[0].PostReadies, 1) c, err := testcontainers.GenericContainer(context.Background(), req) + testcontainers.CleanupContainer(t, c) require.NoError(t, err) - defer func() { - err = c.Terminate(context.Background()) - require.NoError(t, err) - }() _, reader, err := c.Exec(context.Background(), []string{"ls", "/tmp/.testcontainers"}, exec.Multiplexed()) require.NoError(t, err) diff --git a/parallel.go b/parallel.go index 34740eeaf4..0027619b4c 100644 --- a/parallel.go +++ b/parallel.go @@ -2,6 +2,7 @@ package testcontainers import ( "context" + "errors" "fmt" "sync" ) @@ -34,22 +35,22 @@ func (gpe ParallelContainersError) Error() string { func parallelContainersRunner( ctx context.Context, requests <-chan GenericContainerRequest, - errors chan<- ParallelContainersRequestError, + errorsCh chan<- ParallelContainersRequestError, containers chan<- Container, wg *sync.WaitGroup, ) { + defer wg.Done() for req := range requests { c, err := GenericContainer(ctx, req) if err != nil { - errors <- ParallelContainersRequestError{ + errorsCh <- ParallelContainersRequestError{ Request: req, - Error: err, + Error: errors.Join(err, TerminateContainer(c)), } continue } containers <- c } - wg.Done() } // ParallelContainers creates a generic containers with parameters and run it in parallel mode diff --git a/parallel_test.go b/parallel_test.go index 122f59a4f7..f937b1e56d 100644 --- a/parallel_test.go +++ b/parallel_test.go @@ -110,7 +110,7 @@ func TestParallelContainers(t *testing.T) { for _, c := range res { c := c - terminateContainerOnEnd(t, context.Background(), c) + CleanupContainer(t, c) } if len(res) != tc.resLen { @@ -163,5 +163,5 @@ func TestParallelContainersWithReuse(t *testing.T) { t.Fatalf("expected errors: %d, got: %d\n", 0, len(e.Errors)) } // Container is reused, only terminate first container - terminateContainerOnEnd(t, ctx, res[0]) + CleanupContainer(t, res[0]) } diff --git a/port_forwarding.go b/port_forwarding.go index 1d86a8cdd5..88f14f2d72 100644 --- a/port_forwarding.go +++ b/port_forwarding.go @@ -38,9 +38,7 @@ var sshPassword = uuid.NewString() // 1. Create a new SSHD container. // 2. Expose the host ports to the container after the container is ready. // 3. Close the SSH sessions before killing the container. -func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) (ContainerLifecycleHooks, error) { - var sshdConnectHook ContainerLifecycleHooks - +func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) (sshdConnectHook ContainerLifecycleHooks, err error) { //nolint:nonamedreturns // Required for error check. if len(ports) == 0 { return sshdConnectHook, fmt.Errorf("no ports to expose") } @@ -91,6 +89,12 @@ func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) ( // start the SSHD container with the provided options sshdContainer, err := newSshdContainer(ctx, opts...) + // Ensure the SSHD container is stopped and removed in case of error. + defer func() { + if err != nil { + err = errors.Join(err, TerminateContainer(sshdContainer)) + } + }() if err != nil { return sshdConnectHook, fmt.Errorf("new sshd container: %w", err) } @@ -129,6 +133,20 @@ func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) ( originalHCM(hostConfig) } + stopHooks := []ContainerHook{ + func(ctx context.Context, _ Container) error { + if ctx.Err() != nil { + // Context already canceled, need to create a new one to ensure + // the SSH session is closed. + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + } + + return TerminateContainer(sshdContainer, StopContext(ctx)) + }, + } + // after the container is ready, create the SSH tunnel // for each exposed port from the host. sshdConnectHook = ContainerLifecycleHooks{ @@ -137,12 +155,8 @@ func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) ( return sshdContainer.exposeHostPort(ctx, req.HostAccessPorts...) }, }, - PreTerminates: []ContainerHook{ - func(ctx context.Context, _ Container) error { - // before killing the container, close the SSH sessions - return sshdContainer.Terminate(ctx) - }, - }, + PreStops: stopHooks, + PreTerminates: stopHooks, } return sshdConnectHook, nil @@ -168,17 +182,13 @@ func newSshdContainer(ctx context.Context, opts ...ContainerCustomizer) (*sshdCo } c, err := GenericContainer(ctx, req) - if err != nil { - return nil, err + var sshd *sshdContainer + if c != nil { + sshd = &sshdContainer{Container: c} } - // force a type assertion to return a concrete type, - // because GenericContainer returns a Container interface. - dc := c.(*DockerContainer) - - sshd := &sshdContainer{ - DockerContainer: dc, - portForwarders: []PortForwarder{}, + if err != nil { + return sshd, fmt.Errorf("generic container: %w", err) } sshClientConfig, err := configureSSHConfig(ctx, sshd) @@ -195,7 +205,7 @@ func newSshdContainer(ctx context.Context, opts ...ContainerCustomizer) (*sshdCo // sshdContainer represents the SSHD container type used for the port forwarding container. // It's an internal type that extends the DockerContainer type, to add the SSH tunneling capabilities. type sshdContainer struct { - *DockerContainer + Container port string sshConfig *ssh.ClientConfig portForwarders []PortForwarder @@ -203,17 +213,30 @@ type sshdContainer struct { // Terminate stops the container and closes the SSH session func (sshdC *sshdContainer) Terminate(ctx context.Context) error { + sshdC.closePorts(ctx) + + return sshdC.Container.Terminate(ctx) +} + +// Stop stops the container and closes the SSH session +func (sshdC *sshdContainer) Stop(ctx context.Context, timeout *time.Duration) error { + sshdC.closePorts(ctx) + + return sshdC.Container.Stop(ctx, timeout) +} + +// closePorts closes all port forwarders. +func (sshdC *sshdContainer) closePorts(ctx context.Context) { for _, pfw := range sshdC.portForwarders { pfw.Close(ctx) } - - return sshdC.DockerContainer.Terminate(ctx) + sshdC.portForwarders = nil // Ensure the port forwarders are not used after closing. } func configureSSHConfig(ctx context.Context, sshdC *sshdContainer) (*ssh.ClientConfig, error) { mappedPort, err := sshdC.MappedPort(ctx, sshPort) if err != nil { - return nil, err + return nil, fmt.Errorf("mapped port: %w", err) } sshdC.port = mappedPort.Port() diff --git a/port_forwarding_test.go b/port_forwarding_test.go index 471736150b..7a82158147 100644 --- a/port_forwarding_test.go +++ b/port_forwarding_test.go @@ -80,10 +80,7 @@ func TestExposeHostPorts(t *testing.T) { var err error nw, err = network.New(context.Background()) require.NoError(tt, err) - - tt.Cleanup(func() { - require.NoError(tt, nw.Remove(context.Background())) - }) + testcontainers.CleanupNetwork(t, nw) req.Networks = []string{nw.Name} req.NetworkAliases = map[string][]string{nw.Name: {"myalpine"}} @@ -97,10 +94,8 @@ func TestExposeHostPorts(t *testing.T) { } c, err := testcontainers.GenericContainer(ctx, req) + testcontainers.CleanupContainer(t, c) require.NoError(tt, err) - tt.Cleanup(func() { - require.NoError(tt, c.Terminate(context.Background())) - }) if tc.hasHostAccess { // create a container that has host access, which will @@ -124,15 +119,11 @@ func httpRequest(t *testing.T, c testcontainers.Container, port int) (int, strin tcexec.Multiplexed(), ) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // read the response bs, err := io.ReadAll(reader) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) return code, string(bs) } diff --git a/reaper_test.go b/reaper_test.go index e526e8ec9a..f421c2686d 100644 --- a/reaper_test.go +++ b/reaper_test.go @@ -119,7 +119,7 @@ func TestContainerStartsWithoutTheReaper(t *testing.T) { ctx := context.Background() - container, err := GenericContainer(ctx, GenericContainerRequest{ + ctr, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ Image: nginxAlpineImage, @@ -129,9 +129,8 @@ func TestContainerStartsWithoutTheReaper(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, ctr) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, container) sessionID := core.SessionID() @@ -163,10 +162,10 @@ func TestContainerStartsWithTheReaper(t *testing.T) { }, Started: true, }) + CleanupContainer(t, c) if err != nil { t.Fatal(err) } - terminateContainerOnEnd(t, ctx, c) sessionID := core.SessionID() @@ -198,9 +197,8 @@ func TestContainerStopWithReaper(t *testing.T) { }, Started: true, }) - + CleanupContainer(t, nginxA) require.NoError(t, err) - terminateContainerOnEnd(t, ctx, nginxA) state, err := nginxA.State(ctx) if err != nil { @@ -246,25 +244,18 @@ func TestContainerTerminationWithReaper(t *testing.T) { }, Started: true, }) - if err != nil { - t.Fatal(err) - } + CleanupContainer(t, nginxA) + require.NoError(t, err) state, err := nginxA.State(ctx) - if err != nil { - t.Fatal(err) - } - if state.Running != true { - t.Fatal("The container shoud be in running state") - } + require.NoError(t, err) + require.True(t, state.Running) + err = nginxA.Terminate(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + _, err = nginxA.State(ctx) - if err == nil { - t.Fatal("expected error from container inspect.") - } + require.Error(t, err) } func TestContainerTerminationWithoutReaper(t *testing.T) { @@ -286,6 +277,7 @@ func TestContainerTerminationWithoutReaper(t *testing.T) { }, Started: true, }) + CleanupContainer(t, nginxA) if err != nil { t.Fatal(err) } @@ -493,7 +485,7 @@ func Test_ReaperReusedIfHealthy(t *testing.T) { require.NoError(t, err, "connecting to Reaper should be successful") if !wasReaperRunning { - terminateContainerOnEnd(t, ctx, reaper.container) + CleanupContainer(t, reaper.container) } } @@ -530,7 +522,7 @@ func Test_RecreateReaperIfTerminated(t *testing.T) { term <- true }(terminate) require.NoError(t, err, "connecting to Reaper should be successful") - terminateContainerOnEnd(t, ctx, recreatedReaper.container) + CleanupContainer(t, recreatedReaper.container) } func TestReaper_reuseItFromOtherTestProgramUsingDocker(t *testing.T) { @@ -582,7 +574,7 @@ func TestReaper_reuseItFromOtherTestProgramUsingDocker(t *testing.T) { require.NoError(t, err, "connecting to Reaper should be successful") if !wasReaperRunning { - terminateContainerOnEnd(t, ctx, reaper.container) + CleanupContainer(t, reaper.container) } } diff --git a/testcontainers_test.go b/testcontainers_test.go index fe5af71e89..5ff914051c 100644 --- a/testcontainers_test.go +++ b/testcontainers_test.go @@ -1,7 +1,6 @@ package testcontainers import ( - "fmt" "os" "os/exec" "regexp" @@ -81,5 +80,5 @@ func TestSessionIDHelper(t *testing.T) { t.Skip("Not a real test, used as a test helper") } - fmt.Printf(">>>%s<<<\n", SessionID()) + t.Logf(">>>%s<<<\n", SessionID()) } diff --git a/testdata/echoserver.go b/testdata/echoserver.go index a62c783f5d..1222b7045f 100644 --- a/testdata/echoserver.go +++ b/testdata/echoserver.go @@ -36,7 +36,8 @@ func main() { ln, err := net.Listen("tcp", ":8080") if err != nil { - log.Fatal(err) + log.Println(err) + return } fmt.Println("ready") diff --git a/testhelpers_test.go b/testhelpers_test.go index 3be3b7c50d..4f268a8aee 100644 --- a/testhelpers_test.go +++ b/testhelpers_test.go @@ -1,25 +1,6 @@ package testcontainers_test -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/testcontainers/testcontainers-go" -) - const ( nginxAlpineImage = "docker.io/nginx:alpine" nginxDefaultPort = "80/tcp" ) - -func terminateContainerOnEnd(tb testing.TB, ctx context.Context, ctr testcontainers.Container) { - tb.Helper() - if ctr == nil { - return - } - tb.Cleanup(func() { - require.NoError(tb, ctr.Terminate(ctx)) - }) -} diff --git a/testing.go b/testing.go index eab23cb805..41391519de 100644 --- a/testing.go +++ b/testing.go @@ -3,9 +3,17 @@ package testcontainers import ( "context" "fmt" + "regexp" "testing" + + "github.com/docker/docker/errdefs" + "github.com/stretchr/testify/require" ) +// errAlreadyInProgress is a regular expression that matches the error for a container +// removal that is already in progress. +var errAlreadyInProgress = regexp.MustCompile(`removal of container .* is already in progress`) + // SkipIfProviderIsNotHealthy is a utility function capable of skipping tests // if the provider is not healthy, or running at all. // This is a function designed to be used in your test, when Docker is not mandatory for CI/CD. @@ -51,3 +59,93 @@ func (lc *StdoutLogConsumer) Accept(l Log) { } // } + +// CleanupContainer is a helper function that schedules the container +// to be stopped / terminated when the test ends. +// +// This should be called as a defer directly after (before any error check) +// of [GenericContainer](...) or a modules Run(...) in a test to ensure the +// container is stopped when the function ends. +// +// before any error check. If container is nil, its a no-op. +func CleanupContainer(tb testing.TB, container Container, options ...TerminateOption) { + tb.Helper() + + tb.Cleanup(func() { + noErrorOrIgnored(tb, TerminateContainer(container, options...)) + }) +} + +// CleanupNetwork is a helper function that schedules the network to be +// removed when the test ends. +// This should be the first call after NewNetwork(...) in a test before +// any error check. If network is nil, its a no-op. +func CleanupNetwork(tb testing.TB, network Network) { + tb.Helper() + + tb.Cleanup(func() { + noErrorOrIgnored(tb, network.Remove(context.Background())) + }) +} + +// noErrorOrIgnored is a helper function that checks if the error is nil or an error +// we can ignore. +func noErrorOrIgnored(tb testing.TB, err error) { + tb.Helper() + + if isCleanupSafe(err) { + return + } + + require.NoError(tb, err) +} + +// causer is an interface that allows to get the cause of an error. +type causer interface { + Cause() error +} + +// wrapErr is an interface that allows to unwrap an error. +type wrapErr interface { + Unwrap() error +} + +// unwrapErrs is an interface that allows to unwrap multiple errors. +type unwrapErrs interface { + Unwrap() []error +} + +// isCleanupSafe reports whether all errors in err's tree are one of the +// following, so can safely be ignored: +// - nil +// - not found +// - already in progress +func isCleanupSafe(err error) bool { + if err == nil { + return true + } + + switch x := err.(type) { //nolint:errorlint // We need to check for interfaces. + case errdefs.ErrNotFound: + return true + case errdefs.ErrConflict: + // Terminating a container that is already terminating. + if errAlreadyInProgress.MatchString(err.Error()) { + return true + } + return false + case causer: + return isCleanupSafe(x.Cause()) + case wrapErr: + return isCleanupSafe(x.Unwrap()) + case unwrapErrs: + for _, e := range x.Unwrap() { + if !isCleanupSafe(e) { + return false + } + } + return true + default: + return false + } +} diff --git a/testing_test.go b/testing_test.go index 56817d655a..6c50738220 100644 --- a/testing_test.go +++ b/testing_test.go @@ -1,7 +1,86 @@ package testcontainers -import "testing" +import ( + "errors" + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) func ExampleSkipIfProviderIsNotHealthy() { SkipIfProviderIsNotHealthy(&testing.T{}) } + +type notFoundError struct{} + +func (notFoundError) NotFound() {} + +func (notFoundError) Error() string { + return "not found" +} + +func Test_isNotFound(t *testing.T) { + tests := map[string]struct { + err error + want bool + }{ + "nil": { + err: nil, + want: true, + }, + "join-nils": { + err: errors.Join(nil, nil), + want: true, + }, + "join-nil-not-found": { + err: errors.Join(nil, notFoundError{}), + want: true, + }, + "not-found": { + err: notFoundError{}, + want: true, + }, + "other": { + err: errors.New("other"), + want: false, + }, + "join-other": { + err: errors.Join(nil, notFoundError{}, errors.New("other")), + want: false, + }, + "warp": { + err: fmt.Errorf("wrap: %w", notFoundError{}), + want: true, + }, + "multi-warp": { + err: fmt.Errorf("wrap: %w", fmt.Errorf("wrap: %w", notFoundError{})), + want: true, + }, + "multi-warp-other": { + err: fmt.Errorf("wrap: %w", fmt.Errorf("wrap: %w", errors.New("other"))), + want: false, + }, + "multi-warp-other-not-found": { + err: fmt.Errorf("wrap: %w", fmt.Errorf("wrap: %w %w", errors.New("other"), notFoundError{})), + want: false, + }, + "multi-warp-not-found-nil": { + err: fmt.Errorf("wrap: %w", fmt.Errorf("wrap: %w %w", nil, notFoundError{})), + want: true, + }, + "multi-join-not-found-other": { + err: errors.Join(nil, fmt.Errorf("wrap: %w", errors.Join(notFoundError{}, errors.New("other")))), + want: false, + }, + "multi-join-not-found-nil": { + err: errors.Join(nil, fmt.Errorf("wrap: %w", errors.Join(notFoundError{}, nil))), + want: true, + }, + } + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + require.Equal(t, tc.want, isCleanupSafe(tc.err)) + }) + } +} diff --git a/wait/exec_test.go b/wait/exec_test.go index 13e3e47511..224f7d99d9 100644 --- a/wait/exec_test.go +++ b/wait/exec_test.go @@ -12,6 +12,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/go-connections/nat" + "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" tcexec "github.com/testcontainers/testcontainers-go/exec" @@ -29,19 +30,20 @@ func ExampleExecStrategy() { ContainerRequest: req, Started: true, }) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := localstack.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(localstack); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } state, err := localstack.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -203,14 +205,8 @@ func TestExecStrategyWaitUntilReady_CustomResponseMatcher(t *testing.T) { // } ctx := context.Background() - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ContainerRequest: dockerReq, Started: true}) - if err != nil { - t.Error(err) - return - } - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ContainerRequest: dockerReq, Started: true}) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + // } } diff --git a/wait/file.go b/wait/file.go index 148907f3db..d9cab7a6e4 100644 --- a/wait/file.go +++ b/wait/file.go @@ -97,7 +97,7 @@ func (ws *FileStrategy) matchFile(ctx context.Context, target StrategyTarget) er if err != nil { return fmt.Errorf("copy from container: %w", err) } - defer rc.Close() //nolint: errcheck // Read close error can't tell us anything useful. + defer rc.Close() if ws.matcher == nil { // No matcher, just check if the file exists. diff --git a/wait/host_port.go b/wait/host_port.go index b349cc0371..a3e9137006 100644 --- a/wait/host_port.go +++ b/wait/host_port.go @@ -130,31 +130,33 @@ func (hp *HostPortStrategy) WaitUntilReady(ctx context.Context, target StrategyT select { case <-ctx.Done(): - return fmt.Errorf("%w: %w", ctx.Err(), err) + return fmt.Errorf("mapped port: retries: %d, port: %q, last err: %w, ctx err: %w", i, port, err, ctx.Err()) case <-time.After(waitInterval): if err := checkTarget(ctx, target); err != nil { - return err + return fmt.Errorf("check target: retries: %d, port: %q, last err: %w", i, port, err) } port, err = target.MappedPort(ctx, internalPort) if err != nil { - log.Printf("(%d) [%s] %s\n", i, port, err) + log.Printf("mapped port: retries: %d, port: %q, err: %s\n", i, port, err) } } } if err := externalCheck(ctx, ipAddress, port, target, waitInterval); err != nil { - return err + return fmt.Errorf("external check: %w", err) } if hp.skipInternalCheck { return nil } - err = internalCheck(ctx, internalPort, target) - if err != nil && errors.Is(errShellNotExecutable, err) { - log.Println("Shell not executable in container, only external port check will be performed") - } else { - return err + if err = internalCheck(ctx, internalPort, target); err != nil { + if errors.Is(errShellNotExecutable, err) { + log.Println("Shell not executable in container, only external port validated") + return nil + } + + return fmt.Errorf("internal check: %w", err) } return nil @@ -167,9 +169,9 @@ func externalCheck(ctx context.Context, ipAddress string, port nat.Port, target dialer := net.Dialer{} address := net.JoinHostPort(ipAddress, portString) - for { + for i := 0; ; i++ { if err := checkTarget(ctx, target); err != nil { - return err + return fmt.Errorf("check target: retries: %d address: %s: %w", i, address, err) } conn, err := dialer.DialContext(ctx, proto, address) if err != nil { @@ -183,7 +185,7 @@ func externalCheck(ctx context.Context, ipAddress string, port nat.Port, target } } } - return err + return fmt.Errorf("dial: %w", err) } conn.Close() diff --git a/wait/host_port_test.go b/wait/host_port_test.go index c31c3dabc9..bf349f05a7 100644 --- a/wait/host_port_test.go +++ b/wait/host_port_test.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/go-connections/nat" + "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go/exec" ) @@ -152,14 +153,10 @@ func TestHostPortStrategyFailsWhileGettingPortDueToOOMKilledContainer(t *testing { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } + require.Error(t, err) expected := "container crashed with out-of-memory (OOMKilled)" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.Contains(t, err.Error(), expected) } } @@ -190,14 +187,10 @@ func TestHostPortStrategyFailsWhileGettingPortDueToExitedContainer(t *testing.T) { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } + require.Error(t, err) expected := "container exited with code 1" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.Contains(t, err.Error(), expected) } } @@ -227,14 +220,10 @@ func TestHostPortStrategyFailsWhileGettingPortDueToUnexpectedContainerStatus(t * { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } + require.Error(t, err) expected := "unexpected container status \"dead\"" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.Contains(t, err.Error(), expected) } } @@ -259,14 +248,10 @@ func TestHostPortStrategyFailsWhileExternalCheckingDueToOOMKilledContainer(t *te { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } + require.Error(t, err) expected := "container crashed with out-of-memory (OOMKilled)" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.Contains(t, err.Error(), expected) } } @@ -292,14 +277,10 @@ func TestHostPortStrategyFailsWhileExternalCheckingDueToExitedContainer(t *testi { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } + require.Error(t, err) expected := "container exited with code 1" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.Contains(t, err.Error(), expected) } } @@ -324,14 +305,10 @@ func TestHostPortStrategyFailsWhileExternalCheckingDueToUnexpectedContainerStatu { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } + require.Error(t, err) expected := "unexpected container status \"dead\"" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.Contains(t, err.Error(), expected) } } @@ -375,14 +352,10 @@ func TestHostPortStrategyFailsWhileInternalCheckingDueToOOMKilledContainer(t *te { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } + require.Error(t, err) expected := "container crashed with out-of-memory (OOMKilled)" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.Contains(t, err.Error(), expected) } } @@ -427,14 +400,10 @@ func TestHostPortStrategyFailsWhileInternalCheckingDueToExitedContainer(t *testi { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } + require.Error(t, err) expected := "container exited with code 1" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.Contains(t, err.Error(), expected) } } @@ -478,14 +447,10 @@ func TestHostPortStrategyFailsWhileInternalCheckingDueToUnexpectedContainerStatu { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } + require.Error(t, err) expected := "unexpected container status \"dead\"" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.Contains(t, err.Error(), expected) } } @@ -540,7 +505,6 @@ func TestHostPortStrategySucceedsGivenShellIsNotInstalled(t *testing.T) { WithStartupTimeout(5 * time.Second). WithPollInterval(100 * time.Millisecond) - if err := wg.WaitUntilReady(context.Background(), target); err != nil { - t.Fatal(err) - } + err = wg.WaitUntilReady(context.Background(), target) + require.NoError(t, err) } diff --git a/wait/http_test.go b/wait/http_test.go index 54610f4686..8e30210065 100644 --- a/wait/http_test.go +++ b/wait/http_test.go @@ -17,6 +17,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/go-connections/nat" + "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" @@ -36,20 +37,21 @@ func ExampleHTTPStrategy() { ContainerRequest: req, Started: true, }) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - // } - defer func() { - if err := c.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(c); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + // } state, err := c.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -62,12 +64,14 @@ func ExampleHTTPStrategy_WithHeaders() { capath := filepath.Join("testdata", "root.pem") cafile, err := os.ReadFile(capath) if err != nil { - log.Fatalf("can't load ca file: %v", err) + log.Printf("can't load ca file: %v", err) + return } certpool := x509.NewCertPool() if !certpool.AppendCertsFromPEM(cafile) { - log.Fatalf("the ca file isn't valid") + log.Printf("the ca file isn't valid") + return } ctx := context.Background() @@ -94,19 +98,20 @@ func ExampleHTTPStrategy_WithHeaders() { ContainerRequest: req, Started: true, }) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := c.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(c); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } state, err := c.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -128,20 +133,21 @@ func ExampleHTTPStrategy_WithPort() { ContainerRequest: req, Started: true, }) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - // } - defer func() { - if err := c.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(c); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + // } state, err := c.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -162,19 +168,20 @@ func ExampleHTTPStrategy_WithForcedIPv4LocalHost() { ContainerRequest: req, Started: true, }) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - defer func() { - if err := c.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(c); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } state, err := c.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -196,20 +203,21 @@ func ExampleHTTPStrategy_WithBasicAuth() { ContainerRequest: req, Started: true, }) - if err != nil { - log.Fatalf("failed to start container: %s", err) - } - // } - defer func() { - if err := gogs.Terminate(ctx); err != nil { - log.Fatalf("failed to terminate container: %s", err) + if err := testcontainers.TerminateContainer(gogs); err != nil { + log.Printf("failed to terminate container: %s", err) } }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + // } state, err := gogs.State(ctx) if err != nil { - log.Fatalf("failed to get container state: %s", err) // nolint:gocritic + log.Printf("failed to get container state: %s", err) + return } fmt.Println(state.Running) @@ -220,17 +228,11 @@ func ExampleHTTPStrategy_WithBasicAuth() { func TestHTTPStrategyWaitUntilReady(t *testing.T) { workdir, err := os.Getwd() - if err != nil { - t.Error(err) - return - } + require.NoError(t, err) capath := filepath.Join(workdir, "testdata", "root.pem") cafile, err := os.ReadFile(capath) - if err != nil { - t.Errorf("can't load ca file: %v", err) - return - } + require.NoError(t, err) certpool := x509.NewCertPool() if !certpool.AppendCertsFromPEM(cafile) { @@ -254,24 +256,17 @@ func TestHTTPStrategyWaitUntilReady(t *testing.T) { WithMethod(http.MethodPost).WithBody(bytes.NewReader([]byte("ping"))), } - container, err := testcontainers.GenericContainer(context.Background(), + ctr, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{ContainerRequest: dockerReq, Started: true}) - if err != nil { - t.Error(err) - return - } - defer container.Terminate(context.Background()) // nolint: errcheck + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + host, err := ctr.Host(context.Background()) + require.NoError(t, err) + + port, err := ctr.MappedPort(context.Background(), "6443/tcp") + require.NoError(t, err) - host, err := container.Host(context.Background()) - if err != nil { - t.Error(err) - return - } - port, err := container.MappedPort(context.Background(), "6443/tcp") - if err != nil { - t.Error(err) - return - } client := http.Client{ Transport: &http.Transport{ TLSClientConfig: tlsconfig, @@ -289,30 +284,19 @@ func TestHTTPStrategyWaitUntilReady(t *testing.T) { }, } resp, err := client.Get(fmt.Sprintf("https://%s:%s", host, port.Port())) - if err != nil { - t.Error(err) - return - } + require.NoError(t, err) + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Errorf("status code isn't ok: %s", resp.Status) - return - } + require.Equal(t, http.StatusOK, resp.StatusCode) } func TestHTTPStrategyWaitUntilReadyWithQueryString(t *testing.T) { workdir, err := os.Getwd() - if err != nil { - t.Error(err) - return - } + require.NoError(t, err) capath := filepath.Join(workdir, "testdata", "root.pem") cafile, err := os.ReadFile(capath) - if err != nil { - t.Errorf("can't load ca file: %v", err) - return - } + require.NoError(t, err) certpool := x509.NewCertPool() if !certpool.AppendCertsFromPEM(cafile) { @@ -335,24 +319,17 @@ func TestHTTPStrategyWaitUntilReadyWithQueryString(t *testing.T) { }), } - container, err := testcontainers.GenericContainer(context.Background(), + ctr, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{ContainerRequest: dockerReq, Started: true}) - if err != nil { - t.Error(err) - return - } - defer container.Terminate(context.Background()) // nolint: errcheck + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + host, err := ctr.Host(context.Background()) + require.NoError(t, err) + + port, err := ctr.MappedPort(context.Background(), "6443/tcp") + require.NoError(t, err) - host, err := container.Host(context.Background()) - if err != nil { - t.Error(err) - return - } - port, err := container.MappedPort(context.Background(), "6443/tcp") - if err != nil { - t.Error(err) - return - } client := http.Client{ Transport: &http.Transport{ TLSClientConfig: tlsconfig, @@ -370,30 +347,19 @@ func TestHTTPStrategyWaitUntilReadyWithQueryString(t *testing.T) { }, } resp, err := client.Get(fmt.Sprintf("https://%s:%s", host, port.Port())) - if err != nil { - t.Error(err) - return - } + require.NoError(t, err) + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Errorf("status code isn't ok: %s", resp.Status) - return - } + require.Equal(t, http.StatusOK, resp.StatusCode) } func TestHTTPStrategyWaitUntilReadyNoBasicAuth(t *testing.T) { workdir, err := os.Getwd() - if err != nil { - t.Error(err) - return - } + require.NoError(t, err) capath := filepath.Join(workdir, "testdata", "root.pem") cafile, err := os.ReadFile(capath) - if err != nil { - t.Errorf("can't load ca file: %v", err) - return - } + require.NoError(t, err) certpool := x509.NewCertPool() if !certpool.AppendCertsFromPEM(cafile) { @@ -424,27 +390,16 @@ func TestHTTPStrategyWaitUntilReadyNoBasicAuth(t *testing.T) { // } ctx := context.Background() - container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ContainerRequest: dockerReq, Started: true}) - if err != nil { - t.Error(err) - return - } - t.Cleanup(func() { - if err := container.Terminate(ctx); err != nil { - t.Fatalf("failed to terminate container: %s", err) - } - }) + ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ContainerRequest: dockerReq, Started: true}) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + host, err := ctr.Host(ctx) + require.NoError(t, err) + + port, err := ctr.MappedPort(ctx, "6443/tcp") + require.NoError(t, err) - host, err := container.Host(ctx) - if err != nil { - t.Error(err) - return - } - port, err := container.MappedPort(ctx, "6443/tcp") - if err != nil { - t.Error(err) - return - } client := http.Client{ Transport: &http.Transport{ TLSClientConfig: tlsconfig, @@ -462,15 +417,10 @@ func TestHTTPStrategyWaitUntilReadyNoBasicAuth(t *testing.T) { }, } resp, err := client.Get(fmt.Sprintf("https://%s:%s", host, port.Port())) - if err != nil { - t.Error(err) - return - } + require.NoError(t, err) + defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Errorf("status code isn't ok: %s", resp.Status) - return - } + require.Equal(t, http.StatusOK, resp.StatusCode) } func TestHttpStrategyFailsWhileGettingPortDueToOOMKilledContainer(t *testing.T) { @@ -513,17 +463,9 @@ func TestHttpStrategyFailsWhileGettingPortDueToOOMKilledContainer(t *testing.T) WithStartupTimeout(500 * time.Millisecond). WithPollInterval(100 * time.Millisecond) - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "container crashed with out-of-memory (OOMKilled)" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "container crashed with out-of-memory (OOMKilled)" + require.EqualError(t, err, expected) } func TestHttpStrategyFailsWhileGettingPortDueToExitedContainer(t *testing.T) { @@ -567,17 +509,9 @@ func TestHttpStrategyFailsWhileGettingPortDueToExitedContainer(t *testing.T) { WithStartupTimeout(500 * time.Millisecond). WithPollInterval(100 * time.Millisecond) - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "container exited with code 1" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "container exited with code 1" + require.EqualError(t, err, expected) } func TestHttpStrategyFailsWhileGettingPortDueToUnexpectedContainerStatus(t *testing.T) { @@ -620,17 +554,9 @@ func TestHttpStrategyFailsWhileGettingPortDueToUnexpectedContainerStatus(t *test WithStartupTimeout(500 * time.Millisecond). WithPollInterval(100 * time.Millisecond) - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "unexpected container status \"dead\"" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "unexpected container status \"dead\"" + require.EqualError(t, err, expected) } func TestHTTPStrategyFailsWhileRequestSendingDueToOOMKilledContainer(t *testing.T) { @@ -668,17 +594,9 @@ func TestHTTPStrategyFailsWhileRequestSendingDueToOOMKilledContainer(t *testing. WithStartupTimeout(500 * time.Millisecond). WithPollInterval(100 * time.Millisecond) - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "container crashed with out-of-memory (OOMKilled)" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "container crashed with out-of-memory (OOMKilled)" + require.EqualError(t, err, expected) } func TestHttpStrategyFailsWhileRequestSendingDueToExitedContainer(t *testing.T) { @@ -717,17 +635,9 @@ func TestHttpStrategyFailsWhileRequestSendingDueToExitedContainer(t *testing.T) WithStartupTimeout(500 * time.Millisecond). WithPollInterval(100 * time.Millisecond) - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "container exited with code 1" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "container exited with code 1" + require.EqualError(t, err, expected) } func TestHttpStrategyFailsWhileRequestSendingDueToUnexpectedContainerStatus(t *testing.T) { @@ -765,17 +675,9 @@ func TestHttpStrategyFailsWhileRequestSendingDueToUnexpectedContainerStatus(t *t WithStartupTimeout(500 * time.Millisecond). WithPollInterval(100 * time.Millisecond) - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "unexpected container status \"dead\"" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "unexpected container status \"dead\"" + require.EqualError(t, err, expected) } func TestHttpStrategyFailsWhileGettingPortDueToNoExposedPorts(t *testing.T) { @@ -812,17 +714,9 @@ func TestHttpStrategyFailsWhileGettingPortDueToNoExposedPorts(t *testing.T) { WithStartupTimeout(500 * time.Millisecond). WithPollInterval(100 * time.Millisecond) - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "No exposed tcp ports or mapped ports - cannot wait for status" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "No exposed tcp ports or mapped ports - cannot wait for status" + require.EqualError(t, err, expected) } func TestHttpStrategyFailsWhileGettingPortDueToOnlyUDPPorts(t *testing.T) { @@ -866,17 +760,9 @@ func TestHttpStrategyFailsWhileGettingPortDueToOnlyUDPPorts(t *testing.T) { WithStartupTimeout(500 * time.Millisecond). WithPollInterval(100 * time.Millisecond) - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "No exposed tcp ports or mapped ports - cannot wait for status" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "No exposed tcp ports or mapped ports - cannot wait for status" + require.EqualError(t, err, expected) } func TestHttpStrategyFailsWhileGettingPortDueToExposedPortNoBindings(t *testing.T) { @@ -915,15 +801,7 @@ func TestHttpStrategyFailsWhileGettingPortDueToExposedPortNoBindings(t *testing. WithStartupTimeout(500 * time.Millisecond). WithPollInterval(100 * time.Millisecond) - { - err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "No exposed tcp ports or mapped ports - cannot wait for status" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } - } + err := wg.WaitUntilReady(context.Background(), target) + expected := "No exposed tcp ports or mapped ports - cannot wait for status" + require.EqualError(t, err, expected) } diff --git a/wait/testdata/main.go b/wait/testdata/main.go index f6f965fe6b..523278ba0b 100644 --- a/wait/testdata/main.go +++ b/wait/testdata/main.go @@ -83,7 +83,7 @@ func run() error { go func() { log.Println("serving...") if err := server.ListenAndServeTLS("tls.pem", "tls-key.pem"); err != nil && !errors.Is(err, http.ErrServerClosed) { - log.Fatal(err) + log.Println(err) } }() From 060734b868fe71a55bdfa2a9293add71caf794ff Mon Sep 17 00:00:00 2001 From: Kevin Wittek Date: Tue, 17 Sep 2024 14:26:06 +0200 Subject: [PATCH 063/126] fix(postgres): Apply default snapshot name if no name specified (#2783) --- modules/postgres/options.go | 2 + modules/postgres/postgres.go | 1 + modules/postgres/postgres_test.go | 138 +++++++++++++++++------------- 3 files changed, 83 insertions(+), 58 deletions(-) diff --git a/modules/postgres/options.go b/modules/postgres/options.go index ad24c79fc3..5779f85c04 100644 --- a/modules/postgres/options.go +++ b/modules/postgres/options.go @@ -7,11 +7,13 @@ import ( type options struct { // SQLDriverName is the name of the SQL driver to use. SQLDriverName string + Snapshot string } func defaultOptions() options { return options{ SQLDriverName: "postgres", + Snapshot: defaultSnapshotName, } } diff --git a/modules/postgres/postgres.go b/modules/postgres/postgres.go index a6bc418ff3..b4b59663a2 100644 --- a/modules/postgres/postgres.go +++ b/modules/postgres/postgres.go @@ -177,6 +177,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom password: req.Env["POSTGRES_PASSWORD"], user: req.Env["POSTGRES_USER"], sqlDriverName: settings.SQLDriverName, + snapshotName: settings.Snapshot, } } diff --git a/modules/postgres/postgres_test.go b/modules/postgres/postgres_test.go index 825a5bdc6f..505fb3b05c 100644 --- a/modules/postgres/postgres_test.go +++ b/modules/postgres/postgres_test.go @@ -203,73 +203,95 @@ func TestWithInitScript(t *testing.T) { } func TestSnapshot(t *testing.T) { - // snapshotAndReset { - ctx := context.Background() - - // 1. Start the postgres ctr and run any migrations on it - ctr, err := postgres.Run( - ctx, - "docker.io/postgres:16-alpine", - postgres.WithDatabase(dbname), - postgres.WithUsername(user), - postgres.WithPassword(password), - postgres.BasicWaitStrategies(), - postgres.WithSQLDriver("pgx"), - ) - testcontainers.CleanupContainer(t, ctr) - require.NoError(t, err) - - // Run any migrations on the database - _, _, err = ctr.Exec(ctx, []string{"psql", "-U", user, "-d", dbname, "-c", "CREATE TABLE users (id SERIAL, name TEXT NOT NULL, age INT NOT NULL)"}) - require.NoError(t, err) + tests := []struct { + name string + options []postgres.SnapshotOption + }{ + { + name: "snapshot/default", + options: nil, + }, - // 2. Create a snapshot of the database to restore later - err = ctr.Snapshot(ctx, postgres.WithSnapshotName("test-snapshot")) - require.NoError(t, err) + { + name: "snapshot/custom", + options: []postgres.SnapshotOption{ + postgres.WithSnapshotName("custom-snapshot"), + }, + }, + } - dbURL, err := ctr.ConnectionString(ctx) - require.NoError(t, err) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // snapshotAndReset { + ctx := context.Background() - t.Run("Test inserting a user", func(t *testing.T) { - t.Cleanup(func() { - // 3. In each test, reset the DB to its snapshot state. - err = ctr.Restore(ctx) + // 1. Start the postgres ctr and run any migrations on it + ctr, err := postgres.Run( + ctx, + "docker.io/postgres:16-alpine", + postgres.WithDatabase(dbname), + postgres.WithUsername(user), + postgres.WithPassword(password), + postgres.BasicWaitStrategies(), + postgres.WithSQLDriver("pgx"), + ) + testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - }) - conn, err := pgx.Connect(context.Background(), dbURL) - require.NoError(t, err) - defer conn.Close(context.Background()) - - _, err = conn.Exec(ctx, "INSERT INTO users(name, age) VALUES ($1, $2)", "test", 42) - require.NoError(t, err) - - var name string - var age int64 - err = conn.QueryRow(context.Background(), "SELECT name, age FROM users LIMIT 1").Scan(&name, &age) - require.NoError(t, err) - - require.Equal(t, "test", name) - require.EqualValues(t, 42, age) - }) + // Run any migrations on the database + _, _, err = ctr.Exec(ctx, []string{"psql", "-U", user, "-d", dbname, "-c", "CREATE TABLE users (id SERIAL, name TEXT NOT NULL, age INT NOT NULL)"}) + require.NoError(t, err) - // 4. Run as many tests as you need, they will each get a clean database - t.Run("Test querying empty DB", func(t *testing.T) { - t.Cleanup(func() { - err = ctr.Restore(ctx) + // 2. Create a snapshot of the database to restore later + // tt.options comes the test case, it can be specified as e.g. `postgres.WithSnapshotName("custom-snapshot")` or omitted, to use default name + err = ctr.Snapshot(ctx, tt.options...) require.NoError(t, err) - }) - conn, err := pgx.Connect(context.Background(), dbURL) - require.NoError(t, err) - defer conn.Close(context.Background()) + dbURL, err := ctr.ConnectionString(ctx) + require.NoError(t, err) - var name string - var age int64 - err = conn.QueryRow(context.Background(), "SELECT name, age FROM users LIMIT 1").Scan(&name, &age) - require.ErrorIs(t, err, pgx.ErrNoRows) - }) - // } + t.Run("Test inserting a user", func(t *testing.T) { + t.Cleanup(func() { + // 3. In each test, reset the DB to its snapshot state. + err = ctr.Restore(ctx) + require.NoError(t, err) + }) + + conn, err := pgx.Connect(context.Background(), dbURL) + require.NoError(t, err) + defer conn.Close(context.Background()) + + _, err = conn.Exec(ctx, "INSERT INTO users(name, age) VALUES ($1, $2)", "test", 42) + require.NoError(t, err) + + var name string + var age int64 + err = conn.QueryRow(context.Background(), "SELECT name, age FROM users LIMIT 1").Scan(&name, &age) + require.NoError(t, err) + + require.Equal(t, "test", name) + require.EqualValues(t, 42, age) + }) + + // 4. Run as many tests as you need, they will each get a clean database + t.Run("Test querying empty DB", func(t *testing.T) { + t.Cleanup(func() { + err = ctr.Restore(ctx) + require.NoError(t, err) + }) + + conn, err := pgx.Connect(context.Background(), dbURL) + require.NoError(t, err) + defer conn.Close(context.Background()) + + var name string + var age int64 + err = conn.QueryRow(context.Background(), "SELECT name, age FROM users LIMIT 1").Scan(&name, &age) + require.ErrorIs(t, err, pgx.ErrNoRows) + }) + // } + }) + } } func TestSnapshotWithOverrides(t *testing.T) { From e2bd70faa82e7338c56d352f79a13314215d9371 Mon Sep 17 00:00:00 2001 From: Simon Gate Date: Wed, 18 Sep 2024 01:26:57 +0200 Subject: [PATCH 064/126] feat(mongodb): Wait for mongodb module with a replicaset to finish (#2777) * Insert a document in mongodb during tests To be able to catch `NotWritablePrimary` error * Add mongo:7 to replica set tests * Add new waiting strategy for mongodb replicaset * Extend default wait strategy Thanks @stevenh --------- Co-authored-by: Steven Hartland --- modules/mongodb/mongodb.go | 5 +++++ modules/mongodb/mongodb_test.go | 13 ++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/modules/mongodb/mongodb.go b/modules/mongodb/mongodb.go index 4923473593..3f73e5dc70 100644 --- a/modules/mongodb/mongodb.go +++ b/modules/mongodb/mongodb.go @@ -3,6 +3,7 @@ package mongodb import ( "context" "fmt" + "time" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" @@ -89,6 +90,10 @@ func WithPassword(password string) testcontainers.CustomizeRequestOption { func WithReplicaSet(replSetName string) testcontainers.CustomizeRequestOption { return func(req *testcontainers.GenericContainerRequest) error { req.Cmd = append(req.Cmd, "--replSet", replSetName) + req.WaitingFor = wait.ForAll( + req.WaitingFor, + wait.ForExec(eval("rs.status().ok")), + ).WithDeadline(60 * time.Second) req.LifecycleHooks = append(req.LifecycleHooks, testcontainers.ContainerLifecycleHooks{ PostStarts: []testcontainers.ContainerHook{ func(ctx context.Context, c testcontainers.Container) error { diff --git a/modules/mongodb/mongodb_test.go b/modules/mongodb/mongodb_test.go index 663f05cff6..03d669bb7e 100644 --- a/modules/mongodb/mongodb_test.go +++ b/modules/mongodb/mongodb_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/require" + "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" @@ -48,6 +49,13 @@ func TestMongoDB(t *testing.T) { mongodb.WithReplicaSet("rs"), }, }, + { + name: "With Replica set and mongo:7", + img: "mongo:7", + opts: []testcontainers.ContainerCustomizer{ + mongodb.WithReplicaSet("rs"), + }, + }, } for _, tc := range testCases { @@ -67,12 +75,15 @@ func TestMongoDB(t *testing.T) { // Force direct connection to the container to avoid the replica set // connection string that is returned by the container itself when // using the replica set option. - mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(endpoint+"/?connect=direct")) + mongoClient, err := mongo.Connect(ctx, options.Client().ApplyURI(endpoint).SetDirect(true)) require.NoError(tt, err) err = mongoClient.Ping(ctx, nil) require.NoError(tt, err) require.Equal(t, "test", mongoClient.Database("test").Name()) + + _, err = mongoClient.Database("testcontainer").Collection("test").InsertOne(context.Background(), bson.M{}) + require.NoError(tt, err) }) } } From 31a033c5ff201ea3b75a85d702cd98a2de39eca6 Mon Sep 17 00:00:00 2001 From: Rafal Zajac Date: Wed, 18 Sep 2024 14:32:48 +0200 Subject: [PATCH 065/126] fix: do not override ImageBuildOptions.Labels when building from a Dockerfile (#2775) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix #2632 - ImageBuildOptions.Labels are overwritten * Fix #2632 - fix linter errors. * Update internal/core/labels_test.go Co-authored-by: Steven Hartland * Update internal/core/labels_test.go Co-authored-by: Steven Hartland * Update internal/core/labels_test.go Co-authored-by: Steven Hartland * Update internal/core/labels_test.go Co-authored-by: Steven Hartland * Update container.go Co-authored-by: Manuel de la Peña * Update internal/core/labels.go Co-authored-by: Manuel de la Peña * Update container_test.go Co-authored-by: Manuel de la Peña * Fix #2632 - remove given, when, then comments. * Update internal/core/labels.go Co-authored-by: Manuel de la Peña * Fix #2632 - unit test update. * Update internal/core/labels_test.go Co-authored-by: Steven Hartland * Fix #2632 - return error when destination labels map is nil and custom labels are present. * Update internal/core/labels_test.go Co-authored-by: Steven Hartland * Update internal/core/labels.go Co-authored-by: Steven Hartland * Update internal/core/labels.go Co-authored-by: Steven Hartland * Update internal/core/labels.go Co-authored-by: Steven Hartland * Update internal/core/labels_test.go Co-authored-by: Steven Hartland * Update internal/core/labels_test.go Co-authored-by: Steven Hartland * Fix #2632 - fix test. * Update container_test.go Co-authored-by: Manuel de la Peña --------- Co-authored-by: Steven Hartland Co-authored-by: Manuel de la Peña --- container.go | 9 +++++- container_test.go | 59 ++++++++++++++++++++++++++++++++++++ internal/core/labels.go | 20 ++++++++++++ internal/core/labels_test.go | 34 +++++++++++++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 internal/core/labels_test.go diff --git a/container.go b/container.go index 8747335a28..54d89c08e5 100644 --- a/container.go +++ b/container.go @@ -460,7 +460,14 @@ func (c *ContainerRequest) BuildOptions() (types.ImageBuildOptions, error) { } if !c.ShouldKeepBuiltImage() { - buildOptions.Labels = core.DefaultLabels(core.SessionID()) + dst := GenericLabels() + if err = core.MergeCustomLabels(dst, c.Labels); err != nil { + return types.ImageBuildOptions{}, err + } + if err = core.MergeCustomLabels(dst, buildOptions.Labels); err != nil { + return types.ImageBuildOptions{}, err + } + buildOptions.Labels = dst } // Do this as late as possible to ensure we don't leak the context on error/panic. diff --git a/container_test.go b/container_test.go index 074a818569..0cca97e6f5 100644 --- a/container_test.go +++ b/container_test.go @@ -11,6 +11,7 @@ import ( "testing" "time" + "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -302,6 +303,64 @@ func Test_BuildImageWithContexts(t *testing.T) { } } +func TestCustomLabelsImage(t *testing.T) { + const ( + myLabelName = "org.my.label" + myLabelValue = "my-label-value" + ) + + ctx := context.Background() + req := testcontainers.GenericContainerRequest{ + ContainerRequest: testcontainers.ContainerRequest{ + Image: "alpine:latest", + Labels: map[string]string{myLabelName: myLabelValue}, + }, + } + + ctr, err := testcontainers.GenericContainer(ctx, req) + + require.NoError(t, err) + t.Cleanup(func() { assert.NoError(t, ctr.Terminate(ctx)) }) + + ctrJSON, err := ctr.Inspect(ctx) + require.NoError(t, err) + assert.Equal(t, myLabelValue, ctrJSON.Config.Labels[myLabelName]) +} + +func TestCustomLabelsBuildOptionsModifier(t *testing.T) { + const ( + myLabelName = "org.my.label" + myLabelValue = "my-label-value" + myBuildOptionLabel = "org.my.bo.label" + myBuildOptionValue = "my-bo-label-value" + ) + + ctx := context.Background() + req := testcontainers.GenericContainerRequest{ + ContainerRequest: testcontainers.ContainerRequest{ + FromDockerfile: testcontainers.FromDockerfile{ + Context: "./testdata", + Dockerfile: "Dockerfile", + BuildOptionsModifier: func(opts *types.ImageBuildOptions) { + opts.Labels = map[string]string{ + myBuildOptionLabel: myBuildOptionValue, + } + }, + }, + Labels: map[string]string{myLabelName: myLabelValue}, + }, + } + + ctr, err := testcontainers.GenericContainer(ctx, req) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + ctrJSON, err := ctr.Inspect(ctx) + require.NoError(t, err) + require.Equal(t, myLabelValue, ctrJSON.Config.Labels[myLabelName]) + require.Equal(t, myBuildOptionValue, ctrJSON.Config.Labels[myBuildOptionLabel]) +} + func Test_GetLogsFromFailedContainer(t *testing.T) { ctx := context.Background() // directDockerHubReference { diff --git a/internal/core/labels.go b/internal/core/labels.go index 58b054ab95..b5da2fb29d 100644 --- a/internal/core/labels.go +++ b/internal/core/labels.go @@ -1,6 +1,10 @@ package core import ( + "errors" + "fmt" + "strings" + "github.com/testcontainers/testcontainers-go/internal" ) @@ -21,3 +25,19 @@ func DefaultLabels(sessionID string) map[string]string { LabelVersion: internal.Version, } } + +// MergeCustomLabels sets labels from src to dst. +// If a key in src has [LabelBase] prefix returns an error. +// If dst is nil returns an error. +func MergeCustomLabels(dst, src map[string]string) error { + if dst == nil { + return errors.New("destination map is nil") + } + for key, value := range src { + if strings.HasPrefix(key, LabelBase) { + return fmt.Errorf("key %q has %q prefix", key, LabelBase) + } + dst[key] = value + } + return nil +} diff --git a/internal/core/labels_test.go b/internal/core/labels_test.go new file mode 100644 index 0000000000..e382a0ad48 --- /dev/null +++ b/internal/core/labels_test.go @@ -0,0 +1,34 @@ +package core + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestMergeCustomLabels(t *testing.T) { + t.Run("success", func(t *testing.T) { + dst := map[string]string{"A": "1", "B": "2"} + src := map[string]string{"B": "X", "C": "3"} + + err := MergeCustomLabels(dst, src) + require.NoError(t, err) + require.Equal(t, map[string]string{"A": "1", "B": "X", "C": "3"}, dst) + }) + + t.Run("invalid-prefix", func(t *testing.T) { + dst := map[string]string{"A": "1", "B": "2"} + src := map[string]string{"B": "X", LabelLang: "go"} + + err := MergeCustomLabels(dst, src) + + require.EqualError(t, err, `key "org.testcontainers.lang" has "org.testcontainers" prefix`) + require.Equal(t, map[string]string{"A": "1", "B": "X"}, dst) + }) + + t.Run("nil-destination", func(t *testing.T) { + src := map[string]string{"A": "1"} + err := MergeCustomLabels(nil, src) + require.Error(t, err) + }) +} From 069f7248cc14b9f8edfcb31c56e1481d1332170e Mon Sep 17 00:00:00 2001 From: Vivek Chandela <107602480+vchandela@users.noreply.github.com> Date: Thu, 19 Sep 2024 01:42:54 +0530 Subject: [PATCH 066/126] fix: handle 127 error code for podman compatibility (#2778) * fix: handle 127 error code for podman compatibility * fix: remove magic numbers; handle 126 and 127 error code separately * chore: handle comments for removing exitStatus type; handle returned error and switch case instead of if-else-if * feat: add unit test for exit code 127 * chore: add internalCheck() tests for exit code = 126/127 * chore: replace t.fatal() with require.NoError() * chore: merge internal check tests with existing tests; revert mockStrategyTarget to MockStrategyTarget to avoid export errors; run make lint --- wait/host_port.go | 33 ++++++++++++----- wait/host_port_test.go | 81 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 99 insertions(+), 15 deletions(-) diff --git a/wait/host_port.go b/wait/host_port.go index a3e9137006..9360517a04 100644 --- a/wait/host_port.go +++ b/wait/host_port.go @@ -13,13 +13,21 @@ import ( "github.com/docker/go-connections/nat" ) +const ( + exitEaccess = 126 // container cmd can't be invoked (permission denied) + exitCmdNotFound = 127 // container cmd not found/does not exist or invalid bind-mount +) + // Implement interface var ( _ Strategy = (*HostPortStrategy)(nil) _ StrategyTimeout = (*HostPortStrategy)(nil) ) -var errShellNotExecutable = errors.New("/bin/sh command not executable") +var ( + errShellNotExecutable = errors.New("/bin/sh command not executable") + errShellNotFound = errors.New("/bin/sh command not found") +) type HostPortStrategy struct { // Port is a string containing port number and protocol in the format "80/tcp" @@ -151,12 +159,16 @@ func (hp *HostPortStrategy) WaitUntilReady(ctx context.Context, target StrategyT } if err = internalCheck(ctx, internalPort, target); err != nil { - if errors.Is(errShellNotExecutable, err) { + switch { + case errors.Is(err, errShellNotExecutable): log.Println("Shell not executable in container, only external port validated") return nil + case errors.Is(err, errShellNotFound): + log.Println("Shell not found in container") + return nil + default: + return fmt.Errorf("internal check: %w", err) } - - return fmt.Errorf("internal check: %w", err) } return nil @@ -207,13 +219,18 @@ func internalCheck(ctx context.Context, internalPort nat.Port, target StrategyTa return fmt.Errorf("%w, host port waiting failed", err) } - if exitCode == 0 { - break - } else if exitCode == 126 { + // Docker has a issue which override exit code 127 to 126 due to: + // https://github.com/moby/moby/issues/45795 + // Handle both to ensure compatibility with Docker and Podman for now. + switch exitCode { + case 0: + return nil + case exitEaccess: return errShellNotExecutable + case exitCmdNotFound: + return errShellNotFound } } - return nil } func buildInternalCheckCommand(internalPort int) string { diff --git a/wait/host_port_test.go b/wait/host_port_test.go index bf349f05a7..18a15aed82 100644 --- a/wait/host_port_test.go +++ b/wait/host_port_test.go @@ -1,8 +1,10 @@ package wait import ( + "bytes" "context" "io" + "log" "net" "strconv" "testing" @@ -456,16 +458,12 @@ func TestHostPortStrategyFailsWhileInternalCheckingDueToUnexpectedContainerStatu func TestHostPortStrategySucceedsGivenShellIsNotInstalled(t *testing.T) { listener, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer listener.Close() rawPort := listener.Addr().(*net.TCPAddr).Port port, err := nat.NewPort("tcp", strconv.Itoa(rawPort)) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) target := &MockStrategyTarget{ HostImpl: func(_ context.Context) (string, error) { @@ -497,7 +495,67 @@ func TestHostPortStrategySucceedsGivenShellIsNotInstalled(t *testing.T) { }, ExecImpl: func(_ context.Context, _ []string, _ ...exec.ProcessOption) (int, io.Reader, error) { // This is the error that would be returned if the shell is not installed. - return 126, nil, nil + return exitEaccess, nil, nil + }, + } + + wg := NewHostPortStrategy("80"). + WithStartupTimeout(5 * time.Second). + WithPollInterval(100 * time.Millisecond) + + oldWriter := log.Default().Writer() + var buf bytes.Buffer + log.Default().SetOutput(&buf) + t.Cleanup(func() { + log.Default().SetOutput(oldWriter) + }) + + err = wg.WaitUntilReady(context.Background(), target) + require.NoError(t, err) + + require.Contains(t, buf.String(), "Shell not executable in container, only external port validated") +} + +func TestHostPortStrategySucceedsGivenShellIsNotFound(t *testing.T) { + listener, err := net.Listen("tcp", "localhost:0") + require.NoError(t, err) + defer listener.Close() + + rawPort := listener.Addr().(*net.TCPAddr).Port + port, err := nat.NewPort("tcp", strconv.Itoa(rawPort)) + require.NoError(t, err) + + target := &MockStrategyTarget{ + HostImpl: func(_ context.Context) (string, error) { + return "localhost", nil + }, + InspectImpl: func(_ context.Context) (*types.ContainerJSON, error) { + return &types.ContainerJSON{ + NetworkSettings: &types.NetworkSettings{ + NetworkSettingsBase: types.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80": []nat.PortBinding{ + { + HostIP: "0.0.0.0", + HostPort: port.Port(), + }, + }, + }, + }, + }, + }, nil + }, + MappedPortImpl: func(_ context.Context, _ nat.Port) (nat.Port, error) { + return port, nil + }, + StateImpl: func(_ context.Context) (*types.ContainerState, error) { + return &types.ContainerState{ + Running: true, + }, nil + }, + ExecImpl: func(_ context.Context, _ []string, _ ...exec.ProcessOption) (int, io.Reader, error) { + // This is the error that would be returned if the shell is not found. + return exitCmdNotFound, nil, nil }, } @@ -505,6 +563,15 @@ func TestHostPortStrategySucceedsGivenShellIsNotInstalled(t *testing.T) { WithStartupTimeout(5 * time.Second). WithPollInterval(100 * time.Millisecond) + oldWriter := log.Default().Writer() + var buf bytes.Buffer + log.Default().SetOutput(&buf) + t.Cleanup(func() { + log.Default().SetOutput(oldWriter) + }) + err = wg.WaitUntilReady(context.Background(), target) require.NoError(t, err) + + require.Contains(t, buf.String(), "Shell not found in container") } From fa560fb4a64b817ca9166f23de4b72774d26e97d Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Thu, 19 Sep 2024 18:23:52 -0400 Subject: [PATCH 067/126] fix(mssql): bump Docker image version (#2786) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: disable mssql tests Disable all mssql tests as the container is currently crashing, see #2785 * fix: use valid MSSQL image --------- Co-authored-by: Manuel de la Peña --- modules/mssql/examples_test.go | 2 +- modules/mssql/mssql.go | 2 +- modules/mssql/mssql_test.go | 32 +++++--------------------------- 3 files changed, 7 insertions(+), 29 deletions(-) diff --git a/modules/mssql/examples_test.go b/modules/mssql/examples_test.go index f5e7ebd04d..8c1f2c0cac 100644 --- a/modules/mssql/examples_test.go +++ b/modules/mssql/examples_test.go @@ -16,7 +16,7 @@ func ExampleRun() { password := "SuperStrong@Passw0rd" mssqlContainer, err := mssql.Run(ctx, - "mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04", + "mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04", mssql.WithAcceptEULA(), mssql.WithPassword(password), ) diff --git a/modules/mssql/mssql.go b/modules/mssql/mssql.go index 57f634c02c..17337bf85b 100644 --- a/modules/mssql/mssql.go +++ b/modules/mssql/mssql.go @@ -44,7 +44,7 @@ func WithPassword(password string) testcontainers.CustomizeRequestOption { // Deprecated: use Run instead // RunContainer creates an instance of the MSSQLServer container type func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*MSSQLServerContainer, error) { - return Run(ctx, "mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04", opts...) + return Run(ctx, "mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04", opts...) } // Run creates an instance of the MSSQLServer container type diff --git a/modules/mssql/mssql_test.go b/modules/mssql/mssql_test.go index 602778f8a0..737c97414e 100644 --- a/modules/mssql/mssql_test.go +++ b/modules/mssql/mssql_test.go @@ -17,7 +17,7 @@ func TestMSSQLServer(t *testing.T) { ctx := context.Background() ctr, err := mssql.Run(ctx, - "mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04", + "mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04", mssql.WithAcceptEULA(), ) testcontainers.CleanupContainer(t, ctr) @@ -46,7 +46,7 @@ func TestMSSQLServerWithMissingEulaOption(t *testing.T) { ctx := context.Background() ctr, err := mssql.Run(ctx, - "mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04", + "mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04", testcontainers.WithWaitStrategy( wait.ForLog("The SQL Server End-User License Agreement (EULA) must be accepted")), ) @@ -65,7 +65,7 @@ func TestMSSQLServerWithConnectionStringParameters(t *testing.T) { ctx := context.Background() ctr, err := mssql.Run(ctx, - "mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04", + "mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04", mssql.WithAcceptEULA(), ) testcontainers.CleanupContainer(t, ctr) @@ -95,7 +95,7 @@ func TestMSSQLServerWithCustomStrongPassword(t *testing.T) { ctx := context.Background() ctr, err := mssql.Run(ctx, - "mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04", + "mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04", mssql.WithAcceptEULA(), mssql.WithPassword("Strong@Passw0rd"), ) @@ -119,7 +119,7 @@ func TestMSSQLServerWithInvalidPassword(t *testing.T) { ctx := context.Background() ctr, err := mssql.Run(ctx, - "mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04", + "mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04", testcontainers.WithWaitStrategy( wait.ForLog("Password validation failed")), mssql.WithAcceptEULA(), @@ -128,25 +128,3 @@ func TestMSSQLServerWithInvalidPassword(t *testing.T) { testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) } - -func TestMSSQLServerWithAlternativeImage(t *testing.T) { - ctx := context.Background() - - ctr, err := mssql.Run(ctx, - "mcr.microsoft.com/mssql/server:2022-RTM-GDR1-ubuntu-20.04", - mssql.WithAcceptEULA(), - ) - testcontainers.CleanupContainer(t, ctr) - require.NoError(t, err) - - // perform assertions - connectionString, err := ctr.ConnectionString(ctx) - require.NoError(t, err) - - db, err := sql.Open("sqlserver", connectionString) - require.NoError(t, err) - defer db.Close() - - err = db.Ping() - require.NoError(t, err) -} From fca969838f4decbe198e29407f7d7158be5057ce Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 20 Sep 2024 04:34:08 -0400 Subject: [PATCH 068/126] chore: golangci-lint 1.61.0 (#2787) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: golangci-lint 1.61.0 Update golangci-lint to v1.61.0 and update the action to v6.1.0. * Update ci-test-go.yml Co-authored-by: Manuel de la Peña * fix: lint * chore: fix not empty check Fix use of assert.NotEmpty and replace assert with replace. --------- Co-authored-by: Manuel de la Peña --- .github/workflows/ci-test-go.yml | 4 ++-- commons-test.mk | 2 +- container.go | 2 +- internal/config/config_test.go | 3 +-- modules/consul/consul_test.go | 5 ++--- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci-test-go.yml b/.github/workflows/ci-test-go.yml index 0a04327da1..badbed8b72 100644 --- a/.github/workflows/ci-test-go.yml +++ b/.github/workflows/ci-test-go.yml @@ -73,10 +73,10 @@ jobs: - name: golangci-lint if: ${{ inputs.platform == 'ubuntu-latest' }} - uses: golangci/golangci-lint-action@9d1e0624a798bb64f6c3cea93db47765312263dc # v5 + uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v1.59.1 + version: v1.61.0 # Optional: working directory, useful for monorepos working-directory: ${{ inputs.project-directory }} # Optional: golangci-lint command line arguments. diff --git a/commons-test.mk b/commons-test.mk index 08c9e613ac..d168ff5c65 100644 --- a/commons-test.mk +++ b/commons-test.mk @@ -6,7 +6,7 @@ define go_install endef $(GOBIN)/golangci-lint: - $(call go_install,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.1) + $(call go_install,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0) $(GOBIN)/gotestsum: $(call go_install,gotest.tools/gotestsum@latest) diff --git a/container.go b/container.go index 54d89c08e5..1e95fb09d4 100644 --- a/container.go +++ b/container.go @@ -520,7 +520,7 @@ func (c *ContainerRequest) validateMounts() error { c.HostConfigModifier(&hostConfig) - if hostConfig.Binds != nil && len(hostConfig.Binds) > 0 { + if len(hostConfig.Binds) > 0 { for _, bind := range hostConfig.Binds { parts := strings.Split(bind, ":") if len(parts) != 2 { diff --git a/internal/config/config_test.go b/internal/config/config_test.go index efd2e054e6..319deb85b7 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -1,7 +1,6 @@ package config import ( - "fmt" "os" "path/filepath" "testing" @@ -517,7 +516,7 @@ func TestReadTCConfig(t *testing.T) { }, } for _, tt := range tests { - t.Run(fmt.Sprintf(tt.name), func(t *testing.T) { + t.Run(tt.name, func(t *testing.T) { tmpDir := t.TempDir() t.Setenv("HOME", tmpDir) t.Setenv("USERPROFILE", tmpDir) // Windows support diff --git a/modules/consul/consul_test.go b/modules/consul/consul_test.go index f89c785874..79b626d359 100644 --- a/modules/consul/consul_test.go +++ b/modules/consul/consul_test.go @@ -7,7 +7,6 @@ import ( "testing" capi "github.com/hashicorp/consul/api" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" @@ -47,11 +46,11 @@ func TestConsul(t *testing.T) { // Check if API is up host, err := ctr.ApiEndpoint(ctx) require.NoError(t, err) - assert.NotEmpty(t, len(host)) + require.NotEmpty(t, host) res, err := http.Get("http://" + host) require.NoError(t, err) - assert.Equal(t, http.StatusOK, res.StatusCode) + require.Equal(t, http.StatusOK, res.StatusCode) cfg := capi.DefaultConfig() cfg.Address = host From c1bb0bbeafc6d8f8e7c6e42502004d09b380f03b Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 20 Sep 2024 16:55:39 +0800 Subject: [PATCH 069/126] feat: support databend module (#2779) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: support databend module * chore: add project scaffolding * chore: more file * chore: run make lint * fix: proper pinned version * fix comment * add the detail documents * Update modules/databend/databend.go Co-authored-by: Steven Hartland * fix review comment * fix * default database * Update modules/databend/databend_test.go Co-authored-by: Steven Hartland * fix review comments * Update modules/databend/databend.go Co-authored-by: Steven Hartland * Update modules/databend/databend.go Co-authored-by: Steven Hartland * fix comment * fix databend-go module * fix databend tests * fix golangci-lint * Update modules/databend/databend.go Co-authored-by: Steven Hartland * remove WithDatabase * fix * chore: rollback pinned version We'll tackle that in a separate PR --------- Co-authored-by: Manuel de la Peña Co-authored-by: Steven Hartland Co-authored-by: Manuel de la Peña --- .github/workflows/ci.yml | 2 +- .vscode/.testcontainers-go.code-workspace | 4 + docs/modules/databend.md | 72 ++++++++ mkdocs.yml | 1 + modules/databend/Makefile | 5 + modules/databend/databend.go | 135 +++++++++++++++ modules/databend/databend_test.go | 74 ++++++++ modules/databend/examples_test.go | 88 ++++++++++ modules/databend/go.mod | 63 +++++++ modules/databend/go.sum | 199 ++++++++++++++++++++++ sonar-project.properties | 2 +- 11 files changed, 643 insertions(+), 2 deletions(-) create mode 100644 docs/modules/databend.md create mode 100644 modules/databend/Makefile create mode 100644 modules/databend/databend.go create mode 100644 modules/databend/databend_test.go create mode 100644 modules/databend/examples_test.go create mode 100644 modules/databend/go.mod create mode 100644 modules/databend/go.sum diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f326e9c1da..e7dcb44618 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: matrix: go-version: [1.22.x, 1.x] platform: [ubuntu-latest] - module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, dolt, elasticsearch, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate] + module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, elasticsearch, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate] uses: ./.github/workflows/ci-test-go.yml with: go-version: ${{ matrix.go-version }} diff --git a/.vscode/.testcontainers-go.code-workspace b/.vscode/.testcontainers-go.code-workspace index 156da3891d..b355235ac2 100644 --- a/.vscode/.testcontainers-go.code-workspace +++ b/.vscode/.testcontainers-go.code-workspace @@ -49,6 +49,10 @@ "name": "module / couchbase", "path": "../modules/couchbase" }, + { + "name": "module / databend", + "path": "../modules/databend" + }, { "name": "module / dolt", "path": "../modules/dolt" diff --git a/docs/modules/databend.md b/docs/modules/databend.md new file mode 100644 index 0000000000..450595a264 --- /dev/null +++ b/docs/modules/databend.md @@ -0,0 +1,72 @@ +# Databend + +Not available until the next release of testcontainers-go :material-tag: main + +## Introduction + +The Testcontainers module for Databend. + +## Adding this module to your project dependencies + +Please run the following command to add the Databend module to your Go dependencies: + +``` +go get github.com/testcontainers/testcontainers-go/modules/databend +``` + +## Usage example + + +[Creating a Databend container](../../modules/databend/examples_test.go) inside_block:runDatabendContainer + + +## Module Reference + +### Run function + +- Not available until the next release of testcontainers-go :material-tag: main + +The Databend module exposes one entrypoint function to create the Databend container, and this function receives three parameters: + +```golang +func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*DatabendContainer, error) +``` + +- `context.Context`, the Go context. +- `string`, the Docker image to use. +- `testcontainers.ContainerCustomizer`, a variadic argument for passing options. + +### Container Options + +When starting the Databend container, you can pass options in a variadic way to configure it. + +#### Image + +If you need to set a different Databend Docker image, you can set a valid Docker image as the second argument in the `Run` function. +E.g. `Run(context.Background(), "datafuselabs/databend:v1.2.615")`. + +{% include "../features/common_functional_options.md" %} + +#### Set username, password + +If you need to set a different user/password/database, you can use `WithUsername`, `WithPassword` options. + +!!!info +The default values for the username is `databend`, for password is `databend` and for the default database name is `default`. + +### Container Methods + +The Databend container exposes the following methods: + +#### ConnectionString + +This method returns the connection string to connect to the Databend container, using the default `8000` port. +It's possible to pass extra parameters to the connection string, e.g. `sslmode=disable`. + + +[Get connection string](../../modules/databend/databend_test.go) inside_block:connectionString + + +#### MustGetConnectionString + +`MustConnectionString` panics if the address cannot be determined. diff --git a/mkdocs.yml b/mkdocs.yml index d48a9dff17..3aa4af31b7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -74,6 +74,7 @@ nav: - modules/cockroachdb.md - modules/consul.md - modules/couchbase.md + - modules/databend.md - modules/dolt.md - modules/elasticsearch.md - modules/gcloud.md diff --git a/modules/databend/Makefile b/modules/databend/Makefile new file mode 100644 index 0000000000..a8ea6a7163 --- /dev/null +++ b/modules/databend/Makefile @@ -0,0 +1,5 @@ +include ../../commons-test.mk + +.PHONY: test +test: + $(MAKE) test-databend diff --git a/modules/databend/databend.go b/modules/databend/databend.go new file mode 100644 index 0000000000..85202bbe44 --- /dev/null +++ b/modules/databend/databend.go @@ -0,0 +1,135 @@ +package databend + +import ( + "context" + "errors" + "fmt" + "strings" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +const ( + databendUser = "databend" + defaultUser = "databend" + defaultPassword = "databend" + defaultDatabaseName = "default" +) + +// DatabendContainer represents the Databend container type used in the module +type DatabendContainer struct { + testcontainers.Container + username string + password string + database string +} + +var _ testcontainers.ContainerCustomizer = (*DatabendOption)(nil) + +// DatabendOption is an option for the Databend container. +type DatabendOption func(*DatabendContainer) + +// Customize is a NOOP. It's defined to satisfy the testcontainers.ContainerCustomizer interface. +func (o DatabendOption) Customize(*testcontainers.GenericContainerRequest) error { + // NOOP to satisfy interface. + return nil +} + +// Run creates an instance of the Databend container type +func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*DatabendContainer, error) { + req := testcontainers.ContainerRequest{ + Image: img, + ExposedPorts: []string{"8000/tcp"}, + Env: map[string]string{ + "QUERY_DEFAULT_USER": defaultUser, + "QUERY_DEFAULT_PASSWORD": defaultPassword, + }, + WaitingFor: wait.ForListeningPort("8000/tcp"), + } + + genericContainerReq := testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + } + + for _, opt := range opts { + if err := opt.Customize(&genericContainerReq); err != nil { + return nil, err + } + } + + username := req.Env["QUERY_DEFAULT_USER"] + password := req.Env["QUERY_DEFAULT_PASSWORD"] + if password == "" && username == "" { + return nil, errors.New("empty password and user") + } + + container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *DatabendContainer + if container != nil { + c = &DatabendContainer{ + Container: container, + password: password, + username: username, + database: defaultDatabaseName, + } + } + + if err != nil { + return c, fmt.Errorf("generic container: %w", err) + } + + return c, nil +} + +// MustConnectionString panics if the address cannot be determined. +func (c *DatabendContainer) MustConnectionString(ctx context.Context, args ...string) string { + addr, err := c.ConnectionString(ctx, args...) + if err != nil { + panic(err) + } + return addr +} + +func (c *DatabendContainer) ConnectionString(ctx context.Context, args ...string) (string, error) { + containerPort, err := c.MappedPort(ctx, "8000/tcp") + if err != nil { + return "", fmt.Errorf("mapped port: %w", err) + } + + host, err := c.Host(ctx) + if err != nil { + return "", err + } + + extraArgs := "" + if len(args) > 0 { + extraArgs = "?" + strings.Join(args, "&") + } + if c.database == "" { + return "", errors.New("database name is empty") + } + + // databend://databend:databend@localhost:8000/default?sslmode=disable + connectionString := fmt.Sprintf("databend://%s:%s@%s:%s/%s%s", c.username, c.password, host, containerPort.Port(), c.database, extraArgs) + return connectionString, nil +} + +// WithUsername sets the username for the Databend container. +// WithUsername is [Run] option that configures the default query user by setting +// the `QUERY_DEFAULT_USER` container environment variable. +func WithUsername(username string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + req.Env["QUERY_DEFAULT_USER"] = username + return nil + } +} + +// WithPassword sets the password for the Databend container. +func WithPassword(password string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + req.Env["QUERY_DEFAULT_PASSWORD"] = password + return nil + } +} diff --git a/modules/databend/databend_test.go b/modules/databend/databend_test.go new file mode 100644 index 0000000000..58ac71e327 --- /dev/null +++ b/modules/databend/databend_test.go @@ -0,0 +1,74 @@ +package databend_test + +import ( + "context" + "database/sql" + "testing" + + _ "github.com/datafuselabs/databend-go" + "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/databend" +) + +func TestDatabend(t *testing.T) { + ctx := context.Background() + + ctr, err := databend.Run(ctx, "datafuselabs/databend:v1.2.615") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + // perform assertions + // connectionString { + connectionString, err := ctr.ConnectionString(ctx, "sslmode=disable") + // } + require.NoError(t, err) + + mustConnectionString := ctr.MustConnectionString(ctx, "sslmode=disable") + require.Equal(t, connectionString, mustConnectionString) + + db, err := sql.Open("databend", connectionString) + require.NoError(t, err) + defer db.Close() + + err = db.Ping() + require.NoError(t, err) + + _, err = db.Exec("CREATE TABLE IF NOT EXISTS a_table ( \n" + + " `col_1` VARCHAR(128) NOT NULL, \n" + + " `col_2` VARCHAR(128) NOT NULL \n" + + ")") + require.NoError(t, err) +} + +func TestDatabendWithDefaultUserAndPassword(t *testing.T) { + ctx := context.Background() + + ctr, err := databend.Run(ctx, + "datafuselabs/databend:v1.2.615", + databend.WithUsername("databend")) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + // perform assertions + connectionString, err := ctr.ConnectionString(ctx, "sslmode=disable") + require.NoError(t, err) + + db, err := sql.Open("databend", connectionString) + require.NoError(t, err) + defer db.Close() + err = db.Ping() + require.NoError(t, err) + + var i int + row := db.QueryRow("select 1") + err = row.Scan(&i) + require.NoError(t, err) + + _, err = db.Exec("CREATE TABLE IF NOT EXISTS a_table ( \n" + + " `col_1` VARCHAR(128) NOT NULL, \n" + + " `col_2` VARCHAR(128) NOT NULL \n" + + ")") + require.NoError(t, err) +} diff --git a/modules/databend/examples_test.go b/modules/databend/examples_test.go new file mode 100644 index 0000000000..ac284ef009 --- /dev/null +++ b/modules/databend/examples_test.go @@ -0,0 +1,88 @@ +package databend_test + +import ( + "context" + "database/sql" + "fmt" + "log" + + _ "github.com/datafuselabs/databend-go" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/databend" +) + +func ExampleRun() { + ctx := context.Background() + + databendContainer, err := databend.Run(ctx, + "datafuselabs/databend:v1.2.615", + databend.WithUsername("test1"), + databend.WithPassword("pass1"), + ) + defer func() { + if err := testcontainers.TerminateContainer(databendContainer); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + + state, err := databendContainer.State(ctx) + if err != nil { + log.Printf("failed to get container state: %s", err) + return + } + + fmt.Println(state.Running) + + // Output: + // true +} + +func ExampleRun_connect() { + ctx := context.Background() + + databendContainer, err := databend.Run(ctx, + "datafuselabs/databend:v1.2.615", + databend.WithUsername("root"), + databend.WithPassword("password"), + ) + defer func() { + if err := testcontainers.TerminateContainer(databendContainer); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + + connectionString, err := databendContainer.ConnectionString(ctx, "sslmode=disable") + if err != nil { + log.Printf("failed to get connection string: %s", err) + return + } + + db, err := sql.Open("databend", connectionString) + if err != nil { + log.Printf("failed to connect to Databend: %s", err) + return + } + defer db.Close() + + var i int + row := db.QueryRow("select 1") + err = row.Scan(&i) + if err != nil { + log.Printf("failed to scan result: %s", err) + return + } + + fmt.Println(i) + + // Output: + // 1 +} diff --git a/modules/databend/go.mod b/modules/databend/go.mod new file mode 100644 index 0000000000..182f764bf2 --- /dev/null +++ b/modules/databend/go.mod @@ -0,0 +1,63 @@ +module github.com/testcontainers/testcontainers-go/modules/databend + +go 1.22.0 + +require ( + github.com/datafuselabs/databend-go v0.7.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.33.0 +) + +require ( + dario.cat/mergo v1.0.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/BurntSushi/toml v1.2.1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/avast/retry-go v3.0.0+incompatible // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/containerd/containerd v1.7.18 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v27.1.1+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/sys v0.21.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/databend/go.sum b/modules/databend/go.sum new file mode 100644 index 0000000000..ff2bf473a8 --- /dev/null +++ b/modules/databend/go.sum @@ -0,0 +1,199 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +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/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= +github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= +github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= +github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/datafuselabs/databend-go v0.7.0 h1:wPND9I8r/FfcY/nAPo8yeZbh5PMga3ICSDIaq8/eP3o= +github.com/datafuselabs/databend-go v0.7.0/go.mod h1:h/sGUBZs7EqJgqnZ3XB0KHfyUlpGvfNrw2lWcdDJVIw= +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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +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.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +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.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= +github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +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/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20230920204549-e6e6cdab5c13 h1:vlzZttNJGVqTsRFU9AmdnrcO1Znh8Ew9kCD//yjigk0= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= +google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/sonar-project.properties b/sonar-project.properties index aaa203e905..5a6dd117bb 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -18,4 +18,4 @@ sonar.test.inclusions=**/*_test.go sonar.test.exclusions=**/vendor/** sonar.go.coverage.reportPaths=**/coverage.out -sonar.go.tests.reportPaths=TEST-unit.xml,examples/nginx/TEST-unit.xml,examples/toxiproxy/TEST-unit.xml,modulegen/TEST-unit.xml,modules/artemis/TEST-unit.xml,modules/azurite/TEST-unit.xml,modules/cassandra/TEST-unit.xml,modules/chroma/TEST-unit.xml,modules/clickhouse/TEST-unit.xml,modules/cockroachdb/TEST-unit.xml,modules/compose/TEST-unit.xml,modules/consul/TEST-unit.xml,modules/couchbase/TEST-unit.xml,modules/dolt/TEST-unit.xml,modules/elasticsearch/TEST-unit.xml,modules/gcloud/TEST-unit.xml,modules/grafana-lgtm/TEST-unit.xml,modules/inbucket/TEST-unit.xml,modules/influxdb/TEST-unit.xml,modules/k3s/TEST-unit.xml,modules/k6/TEST-unit.xml,modules/kafka/TEST-unit.xml,modules/localstack/TEST-unit.xml,modules/mariadb/TEST-unit.xml,modules/milvus/TEST-unit.xml,modules/minio/TEST-unit.xml,modules/mockserver/TEST-unit.xml,modules/mongodb/TEST-unit.xml,modules/mssql/TEST-unit.xml,modules/mysql/TEST-unit.xml,modules/nats/TEST-unit.xml,modules/neo4j/TEST-unit.xml,modules/ollama/TEST-unit.xml,modules/openfga/TEST-unit.xml,modules/openldap/TEST-unit.xml,modules/opensearch/TEST-unit.xml,modules/postgres/TEST-unit.xml,modules/pulsar/TEST-unit.xml,modules/qdrant/TEST-unit.xml,modules/rabbitmq/TEST-unit.xml,modules/redis/TEST-unit.xml,modules/redpanda/TEST-unit.xml,modules/registry/TEST-unit.xml,modules/surrealdb/TEST-unit.xml,modules/valkey/TEST-unit.xml,modules/vault/TEST-unit.xml,modules/vearch/TEST-unit.xml,modules/weaviate/TEST-unit.xml +sonar.go.tests.reportPaths=TEST-unit.xml,examples/nginx/TEST-unit.xml,examples/toxiproxy/TEST-unit.xml,modulegen/TEST-unit.xml,modules/artemis/TEST-unit.xml,modules/azurite/TEST-unit.xml,modules/cassandra/TEST-unit.xml,modules/chroma/TEST-unit.xml,modules/clickhouse/TEST-unit.xml,modules/cockroachdb/TEST-unit.xml,modules/compose/TEST-unit.xml,modules/consul/TEST-unit.xml,modules/couchbase/TEST-unit.xml,modules/databend/TEST-unit.xml,modules/dolt/TEST-unit.xml,modules/elasticsearch/TEST-unit.xml,modules/gcloud/TEST-unit.xml,modules/grafana-lgtm/TEST-unit.xml,modules/inbucket/TEST-unit.xml,modules/influxdb/TEST-unit.xml,modules/k3s/TEST-unit.xml,modules/k6/TEST-unit.xml,modules/kafka/TEST-unit.xml,modules/localstack/TEST-unit.xml,modules/mariadb/TEST-unit.xml,modules/milvus/TEST-unit.xml,modules/minio/TEST-unit.xml,modules/mockserver/TEST-unit.xml,modules/mongodb/TEST-unit.xml,modules/mssql/TEST-unit.xml,modules/mysql/TEST-unit.xml,modules/nats/TEST-unit.xml,modules/neo4j/TEST-unit.xml,modules/ollama/TEST-unit.xml,modules/openfga/TEST-unit.xml,modules/openldap/TEST-unit.xml,modules/opensearch/TEST-unit.xml,modules/postgres/TEST-unit.xml,modules/pulsar/TEST-unit.xml,modules/qdrant/TEST-unit.xml,modules/rabbitmq/TEST-unit.xml,modules/redis/TEST-unit.xml,modules/redpanda/TEST-unit.xml,modules/registry/TEST-unit.xml,modules/surrealdb/TEST-unit.xml,modules/valkey/TEST-unit.xml,modules/vault/TEST-unit.xml,modules/vearch/TEST-unit.xml,modules/weaviate/TEST-unit.xml From b823aad932f72950c80aa5bc7d07440f749f94e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Fri, 20 Sep 2024 13:16:06 +0200 Subject: [PATCH 070/126] docs: document redpanda options (#2789) * docs: document redpanda options * docs: fix heading * docs: include versions for each option and method --- docs/modules/redpanda.md | 71 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/docs/modules/redpanda.md b/docs/modules/redpanda.md index f923b8be09..028dbaf95f 100644 --- a/docs/modules/redpanda.md +++ b/docs/modules/redpanda.md @@ -61,6 +61,8 @@ If you need to enable TLS use `WithTLS` with a valid PEM encoded certificate and #### Additional Listener +- Since testcontainers-go :material-tag: v0.28.0 + There are scenarios where additional listeners are needed, for example if you want to consume/from another container in the same network @@ -79,12 +81,77 @@ Produce messages using the new registered listener [Produce/consume via registered listener](../../modules/redpanda/redpanda_test.go) inside_block:withListenerExec +#### Adding Service Accounts + +- Since testcontainers-go :material-tag: v0.20.0 + +It's possible to add service accounts to the Redpanda container using the `WithNewServiceAccount` option, setting the service account name and its password. +E.g. `WithNewServiceAccount("service-account", "password")`. + +#### Adding Super Users + +- Since testcontainers-go :material-tag: v0.20.0 + +When a super user is needed, you can use the `WithSuperusers` option, passing a variadic list of super users. +E.g. `WithSuperusers("superuser-1", "superuser-2")`. + +#### Enabling SASL + +- Since testcontainers-go :material-tag: v0.20.0 + +The `WithEnableSASL()` option enables SASL scram sha authentication. By default, no authentication (plaintext) is used. +When setting an authentication method, make sure to add users as well and authorize them using the `WithSuperusers()` option. + +#### WithEnableKafkaAuthorization + +- Since testcontainers-go :material-tag: v0.20.0 + +The `WithEnableKafkaAuthorization` enables authorization for connections on the Kafka API. + +#### WithEnableWasmTransform + +- Since testcontainers-go :material-tag: v0.28.0 + +The `WithEnableWasmTransform` enables wasm transform. + +!!!warning + Should not be used with RP versions before 23.3 + +#### WithEnableSchemaRegistryHTTPBasicAuth + +- Since testcontainers-go :material-tag: v0.20.0 + +The `WithEnableSchemaRegistryHTTPBasicAuth` enables HTTP basic authentication for the Schema Registry. + +#### WithAutoCreateTopics + +- Since testcontainers-go :material-tag: v0.22.0 + +The `WithAutoCreateTopics` option enables the auto-creation of topics. + +#### WithTLS + +- Since testcontainers-go :material-tag: v0.24.0 + +The `WithTLS` option enables TLS encryption. It requires a valid PEM encoded certificate and key, passed as byte slices. +E.g. `WithTLS([]byte(cert), []byte(key))`. + +#### WithBootstrapConfig + +- Since testcontainers-go :material-tag: v0.33.0 + +`WithBootstrapConfig` adds an arbitrary config key-value pair to the Redpanda container. Per the name, this config will be interpolated into the generated bootstrap +config file, which is particularly useful for configs requiring a restart when otherwise applied to a running Redpanda instance. +E.g. `WithBootstrapConfig("config_key", config_value)`, where `config_value` is of type `any`. + ### Container Methods The Redpanda container exposes the following methods: #### KafkaSeedBroker +- Since testcontainers-go :material-tag: v0.20.0 + KafkaSeedBroker returns the seed broker that should be used for connecting to the Kafka API with your Kafka client. It'll be returned in the format: "host:port" - for example: "localhost:55687". @@ -95,6 +162,8 @@ to the Kafka API with your Kafka client. It'll be returned in the format: #### SchemaRegistryAddress +- Since testcontainers-go :material-tag: v0.20.0 + SchemaRegistryAddress returns the address to the schema registry API. This is an HTTP-based API and thus the returned format will be: http://host:port. @@ -105,6 +174,8 @@ is an HTTP-based API and thus the returned format will be: http://host:port. #### AdminAPIAddress +- Since testcontainers-go :material-tag: v0.20.0 + AdminAPIAddress returns the address to the Redpanda Admin API. This is an HTTP-based API and thus the returned format will be: http://host:port. From c0ac18fae45b3032b306fc6950cb6ac6127813f5 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Sat, 21 Sep 2024 16:46:54 -0400 Subject: [PATCH 071/126] fix: container timeout test (#2792) Reduce the timeout for TestContainerCreationTimesOutWithHttp to reduce the likely hood of failure. --- docker_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docker_test.go b/docker_test.go index fdc3196dae..b0a78b346d 100644 --- a/docker_test.go +++ b/docker_test.go @@ -658,14 +658,12 @@ func TestContainerCreationTimesOutWithHttp(t *testing.T) { ExposedPorts: []string{ nginxDefaultPort, }, - WaitingFor: wait.ForHTTP("/").WithStartupTimeout(1 * time.Second), + WaitingFor: wait.ForHTTP("/").WithStartupTimeout(time.Millisecond * 500), }, Started: true, }) CleanupContainer(t, nginxC) - if err == nil { - t.Error("Expected timeout") - } + require.Error(t, err, "expected timeout") } func TestContainerCreationWaitsForLogContextTimeout(t *testing.T) { From 1d01e218d3a05bb615538802d9ba8e32d4dec0b0 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Sat, 21 Sep 2024 23:09:44 -0400 Subject: [PATCH 072/126] fix(registry): wait for (#2793) Switch registry containers to wait for http response to ensure the container is ready to serve requests, which was causing random test failures. Also remove unnecessary context creation. --- docker_auth_test.go | 5 +---- modules/registry/registry.go | 7 +++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/docker_auth_test.go b/docker_auth_test.go index d494d6d12e..b8580a08ea 100644 --- a/docker_auth_test.go +++ b/docker_auth_test.go @@ -286,7 +286,7 @@ func prepareLocalRegistryWithAuth(t *testing.T) string { ContainerFilePath: "/data", }, }, - WaitingFor: wait.ForExposedPort(), + WaitingFor: wait.ForHTTP("/").WithPort("5000/tcp"), } // } @@ -311,9 +311,6 @@ func prepareLocalRegistryWithAuth(t *testing.T) string { removeImageFromLocalCache(t, addr+"/redis:5.0-alpine") }) - _, cancel := context.WithCancel(context.Background()) - t.Cleanup(cancel) - return addr } diff --git a/modules/registry/registry.go b/modules/registry/registry.go index 6cfa3d537b..22aa86be54 100644 --- a/modules/registry/registry.go +++ b/modules/registry/registry.go @@ -220,10 +220,9 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom // convenient for testing "REGISTRY_STORAGE_DELETE_ENABLED": "true", }, - WaitingFor: wait.ForAll( - wait.ForExposedPort(), - wait.ForLog("listening on [::]:5000").WithStartupTimeout(10*time.Second), - ), + WaitingFor: wait.ForHTTP("/"). + WithPort(registryPort). + WithStartupTimeout(10 * time.Second), } genericContainerReq := testcontainers.GenericContainerRequest{ From 309dec137deae09e8a0f0608328c86a212fa645d Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 23 Sep 2024 05:36:52 -0400 Subject: [PATCH 073/126] fix: parallel containers clean race (#2790) Simply the logic in parallel containers, eliminating a clean up race condition where multiple clean ups on the same container could occur at the same time. --- parallel.go | 70 ++++++++++++++++++++---------------------------- parallel_test.go | 29 +++++++------------- 2 files changed, 39 insertions(+), 60 deletions(-) diff --git a/parallel.go b/parallel.go index 0027619b4c..0349023ba2 100644 --- a/parallel.go +++ b/parallel.go @@ -2,7 +2,6 @@ package testcontainers import ( "context" - "errors" "fmt" "sync" ) @@ -32,24 +31,27 @@ func (gpe ParallelContainersError) Error() string { return fmt.Sprintf("%v", gpe.Errors) } +// parallelContainersResult represents result. +type parallelContainersResult struct { + ParallelContainersRequestError + Container Container +} + func parallelContainersRunner( ctx context.Context, requests <-chan GenericContainerRequest, - errorsCh chan<- ParallelContainersRequestError, - containers chan<- Container, + results chan<- parallelContainersResult, wg *sync.WaitGroup, ) { defer wg.Done() for req := range requests { c, err := GenericContainer(ctx, req) + res := parallelContainersResult{Container: c} if err != nil { - errorsCh <- ParallelContainersRequestError{ - Request: req, - Error: errors.Join(err, TerminateContainer(c)), - } - continue + res.Request = req + res.Error = err } - containers <- c + results <- res } } @@ -65,41 +67,26 @@ func ParallelContainers(ctx context.Context, reqs ParallelContainerRequest, opt } tasksChan := make(chan GenericContainerRequest, tasksChanSize) - errsChan := make(chan ParallelContainersRequestError) - resChan := make(chan Container) - waitRes := make(chan struct{}) - - containers := make([]Container, 0) - errors := make([]ParallelContainersRequestError, 0) + resultsChan := make(chan parallelContainersResult, tasksChanSize) + done := make(chan struct{}) - wg := sync.WaitGroup{} + var wg sync.WaitGroup wg.Add(tasksChanSize) // run workers for i := 0; i < tasksChanSize; i++ { - go parallelContainersRunner(ctx, tasksChan, errsChan, resChan, &wg) + go parallelContainersRunner(ctx, tasksChan, resultsChan, &wg) } + var errs []ParallelContainersRequestError + containers := make([]Container, 0, len(reqs)) 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 + defer close(done) + for res := range resultsChan { + if res.Error != nil { + errs = append(errs, res.ParallelContainersRequestError) + } else { + containers = append(containers, res.Container) } } }() @@ -108,14 +95,15 @@ func ParallelContainers(ctx context.Context, reqs ParallelContainerRequest, opt tasksChan <- req } close(tasksChan) + wg.Wait() - close(resChan) - close(errsChan) - <-waitRes + close(resultsChan) + + <-done - if len(errors) != 0 { - return containers, ParallelContainersError{Errors: errors} + if len(errs) != 0 { + return containers, ParallelContainersError{Errors: errs} } return containers, nil diff --git a/parallel_test.go b/parallel_test.go index f937b1e56d..25f919e99d 100644 --- a/parallel_test.go +++ b/parallel_test.go @@ -2,7 +2,6 @@ package testcontainers import ( "context" - "errors" "fmt" "testing" "time" @@ -99,23 +98,18 @@ func TestParallelContainers(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { res, err := ParallelContainers(context.Background(), tc.reqs, ParallelContainersOptions{}) - if err != nil { - require.NotZero(t, tc.expErrors) - var e ParallelContainersError - errors.As(err, &e) - if len(e.Errors) != tc.expErrors { - t.Fatalf("expected errors: %d, got: %d\n", tc.expErrors, len(e.Errors)) - } - } - for _, c := range res { - c := c CleanupContainer(t, c) } - if len(res) != tc.resLen { - t.Fatalf("expected containers: %d, got: %d\n", tc.resLen, len(res)) + if tc.expErrors != 0 { + require.Error(t, err) + var errs ParallelContainersError + require.ErrorAs(t, err, &errs) + require.Len(t, errs.Errors, tc.expErrors) } + + require.Len(t, res, tc.resLen) }) } } @@ -157,11 +151,8 @@ func TestParallelContainersWithReuse(t *testing.T) { ctx := context.Background() res, err := ParallelContainers(ctx, parallelRequest, ParallelContainersOptions{}) - if err != nil { - var e ParallelContainersError - errors.As(err, &e) - t.Fatalf("expected errors: %d, got: %d\n", 0, len(e.Errors)) + for _, c := range res { + CleanupContainer(t, c) } - // Container is reused, only terminate first container - CleanupContainer(t, res[0]) + require.NoError(t, err) } From 738e8fc456c4a2736a6499daef0a0c0a68ac628f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 23 Sep 2024 12:28:03 +0200 Subject: [PATCH 074/126] chore: use a much smaller image for testing (#2795) --- wait/exec_test.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/wait/exec_test.go b/wait/exec_test.go index 224f7d99d9..8a82fb0211 100644 --- a/wait/exec_test.go +++ b/wait/exec_test.go @@ -22,16 +22,17 @@ import ( func ExampleExecStrategy() { ctx := context.Background() req := testcontainers.ContainerRequest{ - Image: "localstack/localstack:latest", - WaitingFor: wait.ForExec([]string{"awslocal", "dynamodb", "list-tables"}), + Image: "alpine:latest", + Entrypoint: []string{"tail", "-f", "/dev/null"}, // needed for the container to stay alive + WaitingFor: wait.ForExec([]string{"ls", "/"}).WithStartupTimeout(1 * time.Second), } - localstack, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ + ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, }) defer func() { - if err := testcontainers.TerminateContainer(localstack); err != nil { + if err := testcontainers.TerminateContainer(ctr); err != nil { log.Printf("failed to terminate container: %s", err) } }() @@ -40,7 +41,7 @@ func ExampleExecStrategy() { return } - state, err := localstack.State(ctx) + state, err := ctr.State(ctx) if err != nil { log.Printf("failed to get container state: %s", err) return From e02e8ebe7d320e573864141fe6d0a74dcdecf2fd Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 25 Sep 2024 07:46:09 -0400 Subject: [PATCH 075/126] fix: container logging deadlocks (#2791) Refactor container log handling simplifying the logic fixing various issues with error handling and race conditions between the complex combinations of multiple channels that have been causing random deadlocks in tests. The new version has simple for loop with an inter call to ContainerLogs and stdcopy.StdCopy leveraging an adapter between io.Writer and LogConsumer. This could be used to easily expose separate stdout and stderr handlers. --- docker.go | 261 +++++++++++++++++++++++--------------------- docker_test.go | 15 +++ lifecycle.go | 1 - logconsumer_test.go | 46 ++++---- 4 files changed, 172 insertions(+), 151 deletions(-) diff --git a/docker.go b/docker.go index dcd962ffc8..9319c630dd 100644 --- a/docker.go +++ b/docker.go @@ -5,7 +5,6 @@ import ( "bufio" "context" "encoding/base64" - "encoding/binary" "encoding/json" "errors" "fmt" @@ -17,7 +16,6 @@ import ( "path/filepath" "regexp" "strings" - "sync" "time" "github.com/cenkalti/backoff/v4" @@ -30,6 +28,7 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/jsonmessage" + "github.com/docker/docker/pkg/stdcopy" "github.com/docker/go-connections/nat" "github.com/moby/term" specs "github.com/opencontainers/image-spec/specs-go/v1" @@ -48,11 +47,21 @@ const ( Podman = "podman" ReaperDefault = "reaper_default" // Default network name when bridge is not available packagePath = "github.com/testcontainers/testcontainers-go" - - logStoppedForOutOfSyncMessage = "Stopping log consumer: Headers out of sync" ) -var createContainerFailDueToNameConflictRegex = regexp.MustCompile("Conflict. The container name .* is already in use by container .*") +var ( + // createContainerFailDueToNameConflictRegex is a regular expression that matches the container is already in use error. + createContainerFailDueToNameConflictRegex = regexp.MustCompile("Conflict. The container name .* is already in use by container .*") + + // minLogProductionTimeout is the minimum log production timeout. + minLogProductionTimeout = time.Duration(5 * time.Second) + + // maxLogProductionTimeout is the maximum log production timeout. + maxLogProductionTimeout = time.Duration(60 * time.Second) + + // errLogProductionStop is the cause for stopping log production. + errLogProductionStop = errors.New("log production stopped") +) // DockerContainer represents a container started using Docker type DockerContainer struct { @@ -65,23 +74,19 @@ type DockerContainer struct { isRunning bool imageWasBuilt bool // keepBuiltImage makes Terminate not remove the image if imageWasBuilt. - keepBuiltImage bool - provider *DockerProvider - sessionID string - terminationSignal chan bool - consumers []LogConsumer - logProductionError chan error + keepBuiltImage bool + provider *DockerProvider + sessionID string + terminationSignal chan bool + consumers []LogConsumer // TODO: Remove locking and wait group once the deprecated StartLogProducer and // StopLogProducer have been removed and hence logging can only be started and // stopped once. - // logProductionWaitGroup is used to signal when the log production has stopped. - // This allows stopLogProduction to safely set logProductionStop to nil. - // See simplification in https://go.dev/play/p/x0pOElF2Vjf - logProductionWaitGroup sync.WaitGroup - - logProductionStop chan struct{} + // logProductionCancel is used to signal the log production to stop. + logProductionCancel context.CancelCauseFunc + logProductionCtx context.Context logProductionTimeout *time.Duration logger Logging @@ -263,7 +268,6 @@ func (c *DockerContainer) Stop(ctx context.Context, timeout *time.Duration) erro // without exposing the ability to fully initialize the container state. // See: https://github.com/testcontainers/testcontainers-go/issues/2667 // TODO: Add a check for isRunning when the above issue is resolved. - err := c.stoppingHook(ctx) if err != nil { return fmt.Errorf("stopping hook: %w", err) @@ -310,7 +314,7 @@ func (c *DockerContainer) Terminate(ctx context.Context) error { } select { - // close reaper if it was created + // Close reaper connection if it was attached. case c.terminationSignal <- true: default: } @@ -690,6 +694,29 @@ func (c *DockerContainer) copyToContainer(ctx context.Context, fileContent func( return nil } +// logConsumerWriter is a writer that writes to a LogConsumer. +type logConsumerWriter struct { + log Log + consumers []LogConsumer +} + +// newLogConsumerWriter creates a new logConsumerWriter for logType that sends messages to all consumers. +func newLogConsumerWriter(logType string, consumers []LogConsumer) *logConsumerWriter { + return &logConsumerWriter{ + log: Log{LogType: logType}, + consumers: consumers, + } +} + +// Write writes the p content to all consumers. +func (lw logConsumerWriter) Write(p []byte) (int, error) { + lw.log.Content = p + for _, consumer := range lw.consumers { + consumer.Accept(lw.log) + } + return len(p), nil +} + type LogProductionOption func(*DockerContainer) // WithLogProductionTimeout is a functional option that sets the timeout for the log production. @@ -707,124 +734,94 @@ func (c *DockerContainer) StartLogProducer(ctx context.Context, opts ...LogProdu // startLogProduction will start a concurrent process that will continuously read logs // from the container and will send them to each added LogConsumer. +// // Default log production timeout is 5s. It is used to set the context timeout -// which means that each log-reading loop will last at least the specified timeout -// and that it cannot be cancelled earlier. +// which means that each log-reading loop will last at up to the specified timeout. +// // Use functional option WithLogProductionTimeout() to override default timeout. If it's // lower than 5s and greater than 60s it will be set to 5s or 60s respectively. func (c *DockerContainer) startLogProduction(ctx context.Context, opts ...LogProductionOption) error { - c.logProductionStop = make(chan struct{}, 1) // buffered channel to avoid blocking - c.logProductionWaitGroup.Add(1) - for _, opt := range opts { opt(c) } - minLogProductionTimeout := time.Duration(5 * time.Second) - maxLogProductionTimeout := time.Duration(60 * time.Second) - - if c.logProductionTimeout == nil { + // Validate the log production timeout. + switch { + case c.logProductionTimeout == nil: c.logProductionTimeout = &minLogProductionTimeout - } - - if *c.logProductionTimeout < minLogProductionTimeout { + case *c.logProductionTimeout < minLogProductionTimeout: c.logProductionTimeout = &minLogProductionTimeout - } - - if *c.logProductionTimeout > maxLogProductionTimeout { + case *c.logProductionTimeout > maxLogProductionTimeout: c.logProductionTimeout = &maxLogProductionTimeout } - c.logProductionError = make(chan error, 1) + // Setup the log writers. + stdout := newLogConsumerWriter(StdoutLog, c.consumers) + stderr := newLogConsumerWriter(StderrLog, c.consumers) + + // Setup the log production context which will be used to stop the log production. + c.logProductionCtx, c.logProductionCancel = context.WithCancelCause(ctx) go func() { - defer func() { - close(c.logProductionError) - c.logProductionWaitGroup.Done() - }() - - since := "" - // if the socket is closed we will make additional logs request with updated Since timestamp - BEGIN: - options := container.LogsOptions{ - ShowStdout: true, - ShowStderr: true, - Follow: true, - Since: since, - } + err := c.logProducer(stdout, stderr) + // Set context cancel cause, if not already set. + c.logProductionCancel(err) + }() - ctx, cancel := context.WithTimeout(ctx, *c.logProductionTimeout) + return nil +} + +// logProducer read logs from the container and writes them to stdout, stderr until either: +// - logProductionCtx is done +// - A fatal error occurs +// - No more logs are available +func (c *DockerContainer) logProducer(stdout, stderr io.Writer) error { + // Clean up idle client connections. + defer c.provider.Close() + + // Setup the log options, start from the beginning. + options := container.LogsOptions{ + ShowStdout: true, + ShowStderr: true, + Follow: true, + } + + for { + timeoutCtx, cancel := context.WithTimeout(c.logProductionCtx, *c.logProductionTimeout) defer cancel() - r, err := c.provider.client.ContainerLogs(ctx, c.GetContainerID(), options) - if err != nil { - c.logProductionError <- err - return + err := c.copyLogs(timeoutCtx, stdout, stderr, options) + switch { + case err == nil: + // No more logs available. + return nil + case c.logProductionCtx.Err() != nil: + // Log production was stopped or caller context is done. + return nil + case timeoutCtx.Err() != nil, errors.Is(err, net.ErrClosed): + // Timeout or client connection closed, retry. + default: + // Unexpected error, retry. + Logger.Printf("Unexpected error reading logs: %v", err) } - defer c.provider.Close() - for { - select { - case <-c.logProductionStop: - c.logProductionError <- r.Close() - return - default: - } - h := make([]byte, 8) - _, err := io.ReadFull(r, h) - if err != nil { - switch { - case err == io.EOF: - // No more logs coming - case errors.Is(err, net.ErrClosed): - now := time.Now() - since = fmt.Sprintf("%d.%09d", now.Unix(), int64(now.Nanosecond())) - goto BEGIN - case errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled): - // Probably safe to continue here - continue - default: - _, _ = fmt.Fprintf(os.Stderr, "container log error: %+v. %s", err, logStoppedForOutOfSyncMessage) - // if we would continue here, the next header-read will result into random data... - } - return - } - - count := binary.BigEndian.Uint32(h[4:]) - if count == 0 { - continue - } - logType := h[0] - if logType > 2 { - _, _ = 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 - } + // Retry from the last log received. + now := time.Now() + options.Since = fmt.Sprintf("%d.%09d", now.Unix(), int64(now.Nanosecond())) + } +} - // 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 - logTypes := []string{"", StdoutLog, StderrLog} +// copyLogs copies logs from the container to stdout and stderr. +func (c *DockerContainer) copyLogs(ctx context.Context, stdout, stderr io.Writer, options container.LogsOptions) error { + rc, err := c.provider.client.ContainerLogs(ctx, c.GetContainerID(), options) + if err != nil { + return fmt.Errorf("container logs: %w", err) + } + defer rc.Close() - b := make([]byte, count) - _, err = io.ReadFull(r, 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()) - if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) { - // Probably safe to continue here - continue - } - // we can not continue here as the next read most likely will not be the next header - _, _ = fmt.Fprintln(os.Stderr, logStoppedForOutOfSyncMessage) - return - } - for _, c := range c.consumers { - c.Accept(Log{ - LogType: logTypes[logType], - Content: b, - }) - } - } - }() + if _, err = stdcopy.StdCopy(stdout, stderr, rc); err != nil { + return fmt.Errorf("stdcopy: %w", err) + } return nil } @@ -837,18 +834,25 @@ func (c *DockerContainer) StopLogProducer() error { // stopLogProduction will stop the concurrent process that is reading logs // and sending them to each added LogConsumer func (c *DockerContainer) stopLogProduction() error { - // signal the log production to stop - c.logProductionStop <- struct{}{} + if c.logProductionCancel == nil { + return nil + } - c.logProductionWaitGroup.Wait() + // Signal the log production to stop. + c.logProductionCancel(errLogProductionStop) - if err := <-c.logProductionError; err != nil { - if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) { - // Returning context errors is not useful for the consumer. + if err := context.Cause(c.logProductionCtx); err != nil { + switch { + case errors.Is(err, errLogProductionStop): + // Log production was stopped. return nil + case errors.Is(err, context.DeadlineExceeded), + errors.Is(err, context.Canceled): + // Parent context is done. + return nil + default: + return err } - - return err } return nil @@ -857,7 +861,16 @@ func (c *DockerContainer) stopLogProduction() error { // GetLogProductionErrorChannel exposes the only way for the consumer // to be able to listen to errors and react to them. func (c *DockerContainer) GetLogProductionErrorChannel() <-chan error { - return c.logProductionError + if c.logProductionCtx == nil { + return nil + } + + errCh := make(chan error, 1) + go func() { + <-c.logProductionCtx.Done() + errCh <- context.Cause(c.logProductionCtx) + }() + return errCh } // DockerNetwork represents a network started using Docker diff --git a/docker_test.go b/docker_test.go index b0a78b346d..bbbe519c28 100644 --- a/docker_test.go +++ b/docker_test.go @@ -240,6 +240,15 @@ func TestContainerReturnItsContainerID(t *testing.T) { } } +// testLogConsumer is a simple implementation of LogConsumer that logs to the test output. +type testLogConsumer struct { + t *testing.T +} + +func (l *testLogConsumer) Accept(log Log) { + l.t.Log(log.LogType + ": " + strings.TrimSpace(string(log.Content))) +} + func TestContainerTerminationResetsState(t *testing.T) { ctx := context.Background() @@ -250,6 +259,9 @@ func TestContainerTerminationResetsState(t *testing.T) { ExposedPorts: []string{ nginxDefaultPort, }, + LogConsumerCfg: &LogConsumerConfig{ + Consumers: []LogConsumer{&testLogConsumer{t: t}}, + }, }, Started: true, }) @@ -274,6 +286,9 @@ func TestContainerStateAfterTermination(t *testing.T) { ExposedPorts: []string{ nginxDefaultPort, }, + LogConsumerCfg: &LogConsumerConfig{ + Consumers: []LogConsumer{&testLogConsumer{t: t}}, + }, }, Started: true, }) diff --git a/lifecycle.go b/lifecycle.go index c38e60240d..ff1472d043 100644 --- a/lifecycle.go +++ b/lifecycle.go @@ -190,7 +190,6 @@ var defaultLogConsumersHook = func(cfg *LogConsumerConfig) ContainerLifecycleHoo } dockerContainer := c.(*DockerContainer) - return dockerContainer.stopLogProduction() }, }, diff --git a/logconsumer_test.go b/logconsumer_test.go index 855a849914..9f4b0b61f9 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -520,17 +520,24 @@ func Test_StartLogProductionStillStartsWithTooHighTimeout(t *testing.T) { require.NoError(t, dc.stopLogProduction()) } +// bufLogger is a Logging implementation that writes to a bytes.Buffer. +type bufLogger struct { + bytes.Buffer +} + +// Printf implements Logging. +func (l *bufLogger) Printf(format string, v ...any) { + fmt.Fprintf(l, format, v...) +} + func Test_MultiContainerLogConsumer_CancelledContext(t *testing.T) { - // Redirect stderr to a buffer - r, w, err := os.Pipe() - require.NoError(t, err) - oldStderr := os.Stderr - os.Stderr = w - defer func() { - // Restore stderr - os.Stderr = oldStderr - w.Close() - }() + // Capture global logger. + logger := &bufLogger{} + Logger = logger + oldLogger := Logger + t.Cleanup(func() { + Logger = oldLogger + }) // Context with cancellation functionality for simulating user interruption ctx, cancel := context.WithCancel(context.Background()) @@ -613,23 +620,10 @@ func Test_MultiContainerLogConsumer_CancelledContext(t *testing.T) { // We check log size due to context cancellation causing // varying message counts, leading to test failure. - assert.GreaterOrEqual(t, len(first.Msgs()), 2) - assert.GreaterOrEqual(t, len(second.Msgs()), 2) - - // Close the pipe so as not to block on empty. - w.Close() - - // Read the stderr output from the buffer - var buf bytes.Buffer - _, _ = buf.ReadFrom(r) - - // Check the stderr message - actual := buf.String() + require.GreaterOrEqual(t, len(first.Msgs()), 2) + require.GreaterOrEqual(t, len(second.Msgs()), 2) - // The context cancel shouldn't cause the system to throw a - // logStoppedForOutOfSyncMessage, as it hangs the system with - // the multiple containers. - require.NotContains(t, actual, logStoppedForOutOfSyncMessage) + require.NotContains(t, logger.String(), "Unexpected error reading logs") } // FooLogConsumer is a test log consumer that accepts logs from the From ec9bf5dbf4e89f40a285ce32795c0b6109432e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 25 Sep 2024 15:40:14 +0200 Subject: [PATCH 076/126] fix: update module path (#2797) --- modules/grafana-lgtm/examples_test.go | 2 +- modules/grafana-lgtm/go.mod | 2 +- modules/grafana-lgtm/grafana_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/grafana-lgtm/examples_test.go b/modules/grafana-lgtm/examples_test.go index a31a6b873f..2510e07b1e 100644 --- a/modules/grafana-lgtm/examples_test.go +++ b/modules/grafana-lgtm/examples_test.go @@ -27,7 +27,7 @@ import ( "golang.org/x/sync/errgroup" "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/modules/grafanalgtm" + grafanalgtm "github.com/testcontainers/testcontainers-go/modules/grafana-lgtm" ) func ExampleRun() { diff --git a/modules/grafana-lgtm/go.mod b/modules/grafana-lgtm/go.mod index 26c4b8c34d..e7ce7ee0d8 100644 --- a/modules/grafana-lgtm/go.mod +++ b/modules/grafana-lgtm/go.mod @@ -1,4 +1,4 @@ -module github.com/testcontainers/testcontainers-go/modules/grafanalgtm +module github.com/testcontainers/testcontainers-go/modules/grafana-lgtm go 1.22 diff --git a/modules/grafana-lgtm/grafana_test.go b/modules/grafana-lgtm/grafana_test.go index c6c6d9f0d8..826451e579 100644 --- a/modules/grafana-lgtm/grafana_test.go +++ b/modules/grafana-lgtm/grafana_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/modules/grafanalgtm" + grafanalgtm "github.com/testcontainers/testcontainers-go/modules/grafana-lgtm" ) func TestGrafanaLGTM(t *testing.T) { From a73c28a543d36f90e5abf6e120fe8f4a3b85295b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 25 Sep 2024 20:16:39 +0200 Subject: [PATCH 077/126] fix: template for code generation (#2800) --- modulegen/_template/ci.yml.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modulegen/_template/ci.yml.tmpl b/modulegen/_template/ci.yml.tmpl index e4fd047b24..46fc3e3906 100644 --- a/modulegen/_template/ci.yml.tmpl +++ b/modulegen/_template/ci.yml.tmpl @@ -129,7 +129,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.1 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: # Disabling shallow clone is recommended for improving relevancy of reporting fetch-depth: 0 From 1bf8e2bca3a87b3147016e7145f241eaf7acb645 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Thu, 26 Sep 2024 11:17:45 -0400 Subject: [PATCH 078/126] chore: update dockercfg module (#2801) Update to dockercfg v0.3.2 which improves error reporting. --- examples/nginx/go.mod | 2 +- examples/nginx/go.sum | 4 ++-- examples/toxiproxy/go.mod | 2 +- examples/toxiproxy/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- modules/artemis/go.mod | 2 +- modules/artemis/go.sum | 4 ++-- modules/azurite/go.mod | 2 +- modules/azurite/go.sum | 4 ++-- modules/cassandra/go.mod | 2 +- modules/cassandra/go.sum | 4 ++-- modules/chroma/go.mod | 2 +- modules/chroma/go.sum | 4 ++-- modules/clickhouse/go.mod | 2 +- modules/clickhouse/go.sum | 4 ++-- modules/cockroachdb/go.mod | 2 +- modules/cockroachdb/go.sum | 4 ++-- modules/compose/go.mod | 2 +- modules/compose/go.sum | 4 ++-- modules/consul/go.mod | 2 +- modules/consul/go.sum | 4 ++-- modules/couchbase/go.mod | 2 +- modules/couchbase/go.sum | 4 ++-- modules/databend/go.mod | 2 +- modules/databend/go.sum | 4 ++-- modules/dolt/go.mod | 2 +- modules/dolt/go.sum | 4 ++-- modules/elasticsearch/go.mod | 2 +- modules/elasticsearch/go.sum | 4 ++-- modules/gcloud/go.mod | 2 +- modules/gcloud/go.sum | 4 ++-- modules/grafana-lgtm/go.mod | 2 +- modules/grafana-lgtm/go.sum | 4 ++-- modules/inbucket/go.mod | 2 +- modules/inbucket/go.sum | 4 ++-- modules/influxdb/go.mod | 2 +- modules/influxdb/go.sum | 4 ++-- modules/k3s/go.mod | 2 +- modules/k3s/go.sum | 4 ++-- modules/k6/go.mod | 2 +- modules/k6/go.sum | 4 ++-- modules/kafka/go.mod | 2 +- modules/kafka/go.sum | 4 ++-- modules/localstack/go.mod | 2 +- modules/localstack/go.sum | 4 ++-- modules/mariadb/go.mod | 2 +- modules/mariadb/go.sum | 4 ++-- modules/milvus/go.mod | 2 +- modules/milvus/go.sum | 4 ++-- modules/minio/go.mod | 2 +- modules/minio/go.sum | 4 ++-- modules/mockserver/go.mod | 2 +- modules/mockserver/go.sum | 4 ++-- modules/mongodb/go.mod | 2 +- modules/mongodb/go.sum | 4 ++-- modules/mssql/go.mod | 2 +- modules/mssql/go.sum | 4 ++-- modules/mysql/go.mod | 2 +- modules/mysql/go.sum | 4 ++-- modules/nats/go.mod | 2 +- modules/nats/go.sum | 4 ++-- modules/neo4j/go.mod | 2 +- modules/neo4j/go.sum | 4 ++-- modules/ollama/go.mod | 2 +- modules/ollama/go.sum | 4 ++-- modules/openfga/go.mod | 2 +- modules/openfga/go.sum | 4 ++-- modules/openldap/go.mod | 2 +- modules/openldap/go.sum | 4 ++-- modules/opensearch/go.mod | 2 +- modules/opensearch/go.sum | 4 ++-- modules/postgres/go.mod | 2 +- modules/postgres/go.sum | 4 ++-- modules/pulsar/go.mod | 2 +- modules/pulsar/go.sum | 4 ++-- modules/qdrant/go.mod | 2 +- modules/qdrant/go.sum | 4 ++-- modules/rabbitmq/go.mod | 2 +- modules/rabbitmq/go.sum | 4 ++-- modules/redis/go.mod | 2 +- modules/redis/go.sum | 4 ++-- modules/redpanda/go.mod | 2 +- modules/redpanda/go.sum | 4 ++-- modules/registry/go.mod | 2 +- modules/registry/go.sum | 4 ++-- modules/surrealdb/go.mod | 2 +- modules/surrealdb/go.sum | 4 ++-- modules/valkey/go.mod | 2 +- modules/valkey/go.sum | 4 ++-- modules/vault/go.mod | 2 +- modules/vault/go.sum | 4 ++-- modules/vearch/go.mod | 2 +- modules/vearch/go.sum | 4 ++-- modules/weaviate/go.mod | 2 +- modules/weaviate/go.sum | 4 ++-- 96 files changed, 144 insertions(+), 144 deletions(-) diff --git a/examples/nginx/go.mod b/examples/nginx/go.mod index 4b4830eaa3..186070ac1e 100644 --- a/examples/nginx/go.mod +++ b/examples/nginx/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/examples/nginx/go.sum b/examples/nginx/go.sum index 28367d0020..afea3b1fff 100644 --- a/examples/nginx/go.sum +++ b/examples/nginx/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/examples/toxiproxy/go.mod b/examples/toxiproxy/go.mod index 7cdb477e6c..a15d130181 100644 --- a/examples/toxiproxy/go.mod +++ b/examples/toxiproxy/go.mod @@ -19,7 +19,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/distribution/reference v0.6.0 // indirect diff --git a/examples/toxiproxy/go.sum b/examples/toxiproxy/go.sum index 8173198d1b..5759c448e0 100644 --- a/examples/toxiproxy/go.sum +++ b/examples/toxiproxy/go.sum @@ -18,8 +18,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/go.mod b/go.mod index 8e9b20a12a..39c52eea45 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( dario.cat/mergo v1.0.0 github.com/cenkalti/backoff/v4 v4.2.1 github.com/containerd/platforms v0.2.1 - github.com/cpuguy83/dockercfg v0.3.1 + github.com/cpuguy83/dockercfg v0.3.2 github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index ef44f5f91c..ae807b42af 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/artemis/go.mod b/modules/artemis/go.mod index adb9dddf08..cd2c28ae3a 100644 --- a/modules/artemis/go.mod +++ b/modules/artemis/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/artemis/go.sum b/modules/artemis/go.sum index db201d6672..5960b48221 100644 --- a/modules/artemis/go.sum +++ b/modules/artemis/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/modules/azurite/go.mod b/modules/azurite/go.mod index 99eaff2d54..0855bdcfb3 100644 --- a/modules/azurite/go.mod +++ b/modules/azurite/go.mod @@ -21,7 +21,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/azurite/go.sum b/modules/azurite/go.sum index 4dd10ea119..3c4a74cf45 100644 --- a/modules/azurite/go.sum +++ b/modules/azurite/go.sum @@ -30,8 +30,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/cassandra/go.mod b/modules/cassandra/go.mod index fce3c2d919..7f75e81bb4 100644 --- a/modules/cassandra/go.mod +++ b/modules/cassandra/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/cassandra/go.sum b/modules/cassandra/go.sum index 4b9d427f27..90f2553cd8 100644 --- a/modules/cassandra/go.sum +++ b/modules/cassandra/go.sum @@ -18,8 +18,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/modules/chroma/go.mod b/modules/chroma/go.mod index 2c03baa164..616f0df680 100644 --- a/modules/chroma/go.mod +++ b/modules/chroma/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/chroma/go.sum b/modules/chroma/go.sum index 9e60fa93f1..3efa70b786 100644 --- a/modules/chroma/go.sum +++ b/modules/chroma/go.sum @@ -18,8 +18,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/clickhouse/go.mod b/modules/clickhouse/go.mod index 5542929f72..ad2e8b0033 100644 --- a/modules/clickhouse/go.mod +++ b/modules/clickhouse/go.mod @@ -19,7 +19,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/clickhouse/go.sum b/modules/clickhouse/go.sum index cf050d1739..015f3a6d09 100644 --- a/modules/clickhouse/go.sum +++ b/modules/clickhouse/go.sum @@ -20,8 +20,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/modules/cockroachdb/go.mod b/modules/cockroachdb/go.mod index d31c6f54ec..e26132e941 100644 --- a/modules/cockroachdb/go.mod +++ b/modules/cockroachdb/go.mod @@ -23,7 +23,7 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/cockroachdb/go.sum b/modules/cockroachdb/go.sum index 19481c176e..2bef2696ee 100644 --- a/modules/cockroachdb/go.sum +++ b/modules/cockroachdb/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/compose/go.mod b/modules/compose/go.mod index 487bdcb7d0..16f28c9da3 100644 --- a/modules/compose/go.mod +++ b/modules/compose/go.mod @@ -50,7 +50,7 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/containerd/ttrpc v1.2.5 // indirect github.com/containerd/typeurl/v2 v2.1.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/buildx v0.15.1 // indirect diff --git a/modules/compose/go.sum b/modules/compose/go.sum index 7a9b815421..f6bc950a37 100644 --- a/modules/compose/go.sum +++ b/modules/compose/go.sum @@ -113,8 +113,8 @@ github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oL github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4= github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/consul/go.mod b/modules/consul/go.mod index 079447aa27..ee6d9c2bd9 100644 --- a/modules/consul/go.mod +++ b/modules/consul/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/consul/go.sum b/modules/consul/go.sum index d82d1cb435..150864f08a 100644 --- a/modules/consul/go.sum +++ b/modules/consul/go.sum @@ -32,8 +32,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/modules/couchbase/go.mod b/modules/couchbase/go.mod index d07defe4ae..7eee2904d4 100644 --- a/modules/couchbase/go.mod +++ b/modules/couchbase/go.mod @@ -22,7 +22,7 @@ require ( github.com/couchbase/gocbcoreps v0.1.2 // indirect github.com/couchbase/goprotostellar v1.0.2 // indirect github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20230515165046-68b522a21131 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/couchbase/go.sum b/modules/couchbase/go.sum index f7b1f393fd..eda139da73 100644 --- a/modules/couchbase/go.sum +++ b/modules/couchbase/go.sum @@ -33,8 +33,8 @@ github.com/couchbaselabs/gocaves/client v0.0.0-20230404095311-05e3ba4f0259 h1:2T github.com/couchbaselabs/gocaves/client v0.0.0-20230404095311-05e3ba4f0259/go.mod h1:AVekAZwIY2stsJOMWLAS/0uA/+qdp7pjO8EHnl61QkY= github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20230515165046-68b522a21131 h1:2EAfFswAfgYn3a05DVcegiw6DgMgn1Mv5eGz6IHt1Cw= github.com/couchbaselabs/gocbconnstr/v2 v2.0.0-20230515165046-68b522a21131/go.mod h1:o7T431UOfFVHDNvMBUmUxpHnhivwv7BziUao/nMl81E= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/modules/databend/go.mod b/modules/databend/go.mod index 182f764bf2..e4892363cc 100644 --- a/modules/databend/go.mod +++ b/modules/databend/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/databend/go.sum b/modules/databend/go.sum index ff2bf473a8..82d0c95ad2 100644 --- a/modules/databend/go.sum +++ b/modules/databend/go.sum @@ -18,8 +18,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/dolt/go.mod b/modules/dolt/go.mod index a4c2376a9b..189b6a7701 100644 --- a/modules/dolt/go.mod +++ b/modules/dolt/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/dolt/go.sum b/modules/dolt/go.sum index dcc1a8d165..5ec2f1b6fa 100644 --- a/modules/dolt/go.sum +++ b/modules/dolt/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/elasticsearch/go.mod b/modules/elasticsearch/go.mod index a766e55dd0..a56a624637 100644 --- a/modules/elasticsearch/go.mod +++ b/modules/elasticsearch/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/elasticsearch/go.sum b/modules/elasticsearch/go.sum index 046620bb60..8ad3562871 100644 --- a/modules/elasticsearch/go.sum +++ b/modules/elasticsearch/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/gcloud/go.mod b/modules/gcloud/go.mod index 2aac027255..8ba19423ab 100644 --- a/modules/gcloud/go.mod +++ b/modules/gcloud/go.mod @@ -32,7 +32,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/gcloud/go.sum b/modules/gcloud/go.sum index 7283a49502..da1d6d6919 100644 --- a/modules/gcloud/go.sum +++ b/modules/gcloud/go.sum @@ -55,8 +55,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/modules/grafana-lgtm/go.mod b/modules/grafana-lgtm/go.mod index e7ce7ee0d8..26abe93727 100644 --- a/modules/grafana-lgtm/go.mod +++ b/modules/grafana-lgtm/go.mod @@ -32,7 +32,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/grafana-lgtm/go.sum b/modules/grafana-lgtm/go.sum index d80ed84f72..c19cef2137 100644 --- a/modules/grafana-lgtm/go.sum +++ b/modules/grafana-lgtm/go.sum @@ -18,8 +18,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/modules/inbucket/go.mod b/modules/inbucket/go.mod index 18939bc445..e64575c11c 100644 --- a/modules/inbucket/go.mod +++ b/modules/inbucket/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/inbucket/go.sum b/modules/inbucket/go.sum index 62be48931c..0a2d246379 100644 --- a/modules/inbucket/go.sum +++ b/modules/inbucket/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/influxdb/go.mod b/modules/influxdb/go.mod index f11c1de449..bdac56db10 100644 --- a/modules/influxdb/go.mod +++ b/modules/influxdb/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/influxdb/go.sum b/modules/influxdb/go.sum index 875bf9d6a1..49dede80c1 100644 --- a/modules/influxdb/go.sum +++ b/modules/influxdb/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/k3s/go.mod b/modules/k3s/go.mod index 724d10e24a..6ef16a669d 100644 --- a/modules/k3s/go.mod +++ b/modules/k3s/go.mod @@ -21,7 +21,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-units v0.5.0 // indirect diff --git a/modules/k3s/go.sum b/modules/k3s/go.sum index 86dfae5fc0..c086e351c5 100644 --- a/modules/k3s/go.sum +++ b/modules/k3s/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/k6/go.mod b/modules/k6/go.mod index 4dcd9395d9..897cf23fe6 100644 --- a/modules/k6/go.mod +++ b/modules/k6/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.5.0 // indirect diff --git a/modules/k6/go.sum b/modules/k6/go.sum index 28367d0020..afea3b1fff 100644 --- a/modules/k6/go.sum +++ b/modules/k6/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/kafka/go.mod b/modules/kafka/go.mod index 7595e2d7a0..f8e135d941 100644 --- a/modules/kafka/go.mod +++ b/modules/kafka/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/kafka/go.sum b/modules/kafka/go.sum index 9dddd03e0b..7c3a427da5 100644 --- a/modules/kafka/go.sum +++ b/modules/kafka/go.sum @@ -16,8 +16,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/localstack/go.mod b/modules/localstack/go.mod index 0bd92d1a01..333b5279b0 100644 --- a/modules/localstack/go.mod +++ b/modules/localstack/go.mod @@ -37,7 +37,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-units v0.5.0 // indirect diff --git a/modules/localstack/go.sum b/modules/localstack/go.sum index 93de565615..265c675ed5 100644 --- a/modules/localstack/go.sum +++ b/modules/localstack/go.sum @@ -52,8 +52,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/mariadb/go.mod b/modules/mariadb/go.mod index a3d2ee8f70..8a911aaff2 100644 --- a/modules/mariadb/go.mod +++ b/modules/mariadb/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/mariadb/go.sum b/modules/mariadb/go.sum index dcc1a8d165..5ec2f1b6fa 100644 --- a/modules/mariadb/go.sum +++ b/modules/mariadb/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/milvus/go.mod b/modules/milvus/go.mod index 1b60fe8cf7..d743fcd143 100644 --- a/modules/milvus/go.mod +++ b/modules/milvus/go.mod @@ -19,7 +19,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/milvus/go.sum b/modules/milvus/go.sum index f8cd7dcf33..6666d6eae0 100644 --- a/modules/milvus/go.sum +++ b/modules/milvus/go.sum @@ -39,8 +39,8 @@ github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7np github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= diff --git a/modules/minio/go.mod b/modules/minio/go.mod index 84d98587fd..3ed9eac6de 100644 --- a/modules/minio/go.mod +++ b/modules/minio/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/minio/go.sum b/modules/minio/go.sum index 5afc27ffd9..4bd2ff7754 100644 --- a/modules/minio/go.sum +++ b/modules/minio/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/mockserver/go.mod b/modules/mockserver/go.mod index 36f5772800..4ce03a96e0 100644 --- a/modules/mockserver/go.mod +++ b/modules/mockserver/go.mod @@ -15,7 +15,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/mockserver/go.sum b/modules/mockserver/go.sum index 16335ff9dd..cea4315677 100644 --- a/modules/mockserver/go.sum +++ b/modules/mockserver/go.sum @@ -16,8 +16,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/mongodb/go.mod b/modules/mongodb/go.mod index 66311410d7..a6433e76f1 100644 --- a/modules/mongodb/go.mod +++ b/modules/mongodb/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/mongodb/go.sum b/modules/mongodb/go.sum index 7f2154a1b2..4255434867 100644 --- a/modules/mongodb/go.sum +++ b/modules/mongodb/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/mssql/go.mod b/modules/mssql/go.mod index 80bd7ba219..c61a8691f9 100644 --- a/modules/mssql/go.mod +++ b/modules/mssql/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/mssql/go.sum b/modules/mssql/go.sum index 452ef25661..0d6c8ec14b 100644 --- a/modules/mssql/go.sum +++ b/modules/mssql/go.sum @@ -26,8 +26,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/mysql/go.mod b/modules/mysql/go.mod index 9e0da8e36a..9f2ddb5634 100644 --- a/modules/mysql/go.mod +++ b/modules/mysql/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/mysql/go.sum b/modules/mysql/go.sum index dcc1a8d165..5ec2f1b6fa 100644 --- a/modules/mysql/go.sum +++ b/modules/mysql/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/nats/go.mod b/modules/nats/go.mod index 066f3d976f..823cf79e58 100644 --- a/modules/nats/go.mod +++ b/modules/nats/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/nats/go.sum b/modules/nats/go.sum index ec68d27737..71e540e367 100644 --- a/modules/nats/go.sum +++ b/modules/nats/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/neo4j/go.mod b/modules/neo4j/go.mod index 50da4a55d4..61893d0dfe 100644 --- a/modules/neo4j/go.mod +++ b/modules/neo4j/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/neo4j/go.sum b/modules/neo4j/go.sum index 54b5d9c6d5..1311c05d5f 100644 --- a/modules/neo4j/go.sum +++ b/modules/neo4j/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/ollama/go.mod b/modules/ollama/go.mod index b338de0b0d..23ae742e4d 100644 --- a/modules/ollama/go.mod +++ b/modules/ollama/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/dlclark/regexp2 v1.8.1 // indirect diff --git a/modules/ollama/go.sum b/modules/ollama/go.sum index 9e9bf8b2c1..9e203cb685 100644 --- a/modules/ollama/go.sum +++ b/modules/ollama/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/modules/openfga/go.mod b/modules/openfga/go.mod index 3f5a238a82..3232062282 100644 --- a/modules/openfga/go.mod +++ b/modules/openfga/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/openfga/go.sum b/modules/openfga/go.sum index a24767f45f..485a6b769f 100644 --- a/modules/openfga/go.sum +++ b/modules/openfga/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/openldap/go.mod b/modules/openldap/go.mod index e096880ed6..edab455ba4 100644 --- a/modules/openldap/go.mod +++ b/modules/openldap/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/openldap/go.sum b/modules/openldap/go.sum index 0723cad762..6b65a59a24 100644 --- a/modules/openldap/go.sum +++ b/modules/openldap/go.sum @@ -18,8 +18,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/opensearch/go.mod b/modules/opensearch/go.mod index 7fe56f884b..00521e4b15 100644 --- a/modules/opensearch/go.mod +++ b/modules/opensearch/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.5.0 // indirect diff --git a/modules/opensearch/go.sum b/modules/opensearch/go.sum index 28367d0020..afea3b1fff 100644 --- a/modules/opensearch/go.sum +++ b/modules/opensearch/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/postgres/go.mod b/modules/postgres/go.mod index 4b57997260..e7906f03dd 100644 --- a/modules/postgres/go.mod +++ b/modules/postgres/go.mod @@ -19,7 +19,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/postgres/go.sum b/modules/postgres/go.sum index 1b1f37ba8d..09dfe64dce 100644 --- a/modules/postgres/go.sum +++ b/modules/postgres/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/pulsar/go.mod b/modules/pulsar/go.mod index b9e77f4d58..1b0812dfa3 100644 --- a/modules/pulsar/go.mod +++ b/modules/pulsar/go.mod @@ -28,7 +28,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect diff --git a/modules/pulsar/go.sum b/modules/pulsar/go.sum index e8aa08578a..89361ee568 100644 --- a/modules/pulsar/go.sum +++ b/modules/pulsar/go.sum @@ -84,8 +84,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/qdrant/go.mod b/modules/qdrant/go.mod index 05c20884ee..19553c2a6e 100644 --- a/modules/qdrant/go.mod +++ b/modules/qdrant/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/qdrant/go.sum b/modules/qdrant/go.sum index b33ba47727..a0015288c5 100644 --- a/modules/qdrant/go.sum +++ b/modules/qdrant/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/rabbitmq/go.mod b/modules/rabbitmq/go.mod index 46f915a46d..d908287f7e 100644 --- a/modules/rabbitmq/go.mod +++ b/modules/rabbitmq/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/rabbitmq/go.sum b/modules/rabbitmq/go.sum index 5994d5e5b7..07a95eaae0 100644 --- a/modules/rabbitmq/go.sum +++ b/modules/rabbitmq/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/modules/redis/go.mod b/modules/redis/go.mod index e76c925c7e..6f0f6da6fd 100644 --- a/modules/redis/go.mod +++ b/modules/redis/go.mod @@ -21,7 +21,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/distribution/reference v0.6.0 // indirect diff --git a/modules/redis/go.sum b/modules/redis/go.sum index afc80497f0..2c86fe53c0 100644 --- a/modules/redis/go.sum +++ b/modules/redis/go.sum @@ -16,8 +16,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/redpanda/go.mod b/modules/redpanda/go.mod index 4ce12872ee..34bc34422a 100644 --- a/modules/redpanda/go.mod +++ b/modules/redpanda/go.mod @@ -25,7 +25,7 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/redpanda/go.sum b/modules/redpanda/go.sum index 6b3772dc87..d5a1dff81f 100644 --- a/modules/redpanda/go.sum +++ b/modules/redpanda/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/registry/go.mod b/modules/registry/go.mod index 36e95dfdf0..b74bf67a98 100644 --- a/modules/registry/go.mod +++ b/modules/registry/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/registry go 1.22 require ( - github.com/cpuguy83/dockercfg v0.3.1 + github.com/cpuguy83/dockercfg v0.3.2 github.com/docker/docker v27.1.1+incompatible github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.33.0 diff --git a/modules/registry/go.sum b/modules/registry/go.sum index 28367d0020..afea3b1fff 100644 --- a/modules/registry/go.sum +++ b/modules/registry/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/surrealdb/go.mod b/modules/surrealdb/go.mod index 8d740ce836..11b0a8422d 100644 --- a/modules/surrealdb/go.mod +++ b/modules/surrealdb/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/surrealdb/go.sum b/modules/surrealdb/go.sum index ffb535bb9f..25e6634a3d 100644 --- a/modules/surrealdb/go.sum +++ b/modules/surrealdb/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/valkey/go.mod b/modules/valkey/go.mod index 0c1173f987..07528d9ff9 100644 --- a/modules/valkey/go.mod +++ b/modules/valkey/go.mod @@ -19,7 +19,7 @@ require ( github.com/containerd/containerd v1.7.19 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/valkey/go.sum b/modules/valkey/go.sum index 1256ebe114..20d81e13fc 100644 --- a/modules/valkey/go.sum +++ b/modules/valkey/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/vault/go.mod b/modules/vault/go.mod index 064a23bcce..5f03db61f5 100644 --- a/modules/vault/go.mod +++ b/modules/vault/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.5.0 // indirect diff --git a/modules/vault/go.sum b/modules/vault/go.sum index 8fa2d5b6df..0fd470dc49 100644 --- a/modules/vault/go.sum +++ b/modules/vault/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/vearch/go.mod b/modules/vearch/go.mod index 18363db517..757149cc58 100644 --- a/modules/vearch/go.mod +++ b/modules/vearch/go.mod @@ -15,7 +15,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/vearch/go.sum b/modules/vearch/go.sum index 28367d0020..afea3b1fff 100644 --- a/modules/vearch/go.sum +++ b/modules/vearch/go.sum @@ -14,8 +14,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/modules/weaviate/go.mod b/modules/weaviate/go.mod index f8b7d6895a..b0d02fba08 100644 --- a/modules/weaviate/go.mod +++ b/modules/weaviate/go.mod @@ -20,7 +20,7 @@ require ( github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect - github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.1.1+incompatible // indirect diff --git a/modules/weaviate/go.sum b/modules/weaviate/go.sum index b2be18dab8..9f06fcd049 100644 --- a/modules/weaviate/go.sum +++ b/modules/weaviate/go.sum @@ -22,8 +22,8 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= From 4dc366203f32040d15294f0b43069f87dc828a15 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 27 Sep 2024 03:27:10 -0400 Subject: [PATCH 079/126] fix(elasticsearch): wait for (#2724) Wait for the HTTP port to be available to prevent random failures when the container isn't fully started and returns 503 errors. --- modules/elasticsearch/elasticsearch.go | 155 ++++++++++++++----------- modules/elasticsearch/options.go | 1 - 2 files changed, 89 insertions(+), 67 deletions(-) diff --git a/modules/elasticsearch/elasticsearch.go b/modules/elasticsearch/elasticsearch.go index 5fab503b36..e878c3e6ef 100644 --- a/modules/elasticsearch/elasticsearch.go +++ b/modules/elasticsearch/elasticsearch.go @@ -2,6 +2,8 @@ package elasticsearch import ( "context" + "crypto/tls" + "crypto/x509" "fmt" "io" "os" @@ -15,6 +17,7 @@ const ( defaultTCPPort = "9300" defaultPassword = "changeme" defaultUsername = "elastic" + defaultCaCertPath = "/usr/share/elasticsearch/config/certs/http_ca.crt" minimalImageVersion = "7.9.2" ) @@ -32,7 +35,7 @@ type ElasticsearchContainer struct { } // Deprecated: use Run instead -// RunContainer creates an instance of the Couchbase container type +// RunContainer creates an instance of the Elasticsearch container type func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*ElasticsearchContainer, error) { return Run(ctx, "docker.elastic.co/elasticsearch/elasticsearch:7.9.2", opts...) } @@ -50,54 +53,41 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom defaultHTTPPort + "/tcp", defaultTCPPort + "/tcp", }, - // regex that - // matches 8.3 JSON logging with started message and some follow up content within the message field - // matches 8.0 JSON logging with no whitespace between message field and content - // matches 7.x JSON logging with whitespace between message field and content - // matches 6.x text logging with node name in brackets and just a 'started' message till the end of the line - WaitingFor: wait.ForLog(`.*("message":\s?"started(\s|")?.*|]\sstarted\n)`).AsRegexp(), - LifecycleHooks: []testcontainers.ContainerLifecycleHooks{ - { - // the container needs a post create hook to set the default JVM options in a file - PostCreates: []testcontainers.ContainerHook{}, - PostReadies: []testcontainers.ContainerHook{}, - }, - }, }, Started: true, } // Gather all config options (defaults and then apply provided options) - settings := defaultOptions() + options := defaultOptions() for _, opt := range opts { if apply, ok := opt.(Option); ok { - apply(settings) + apply(options) } if err := opt.Customize(&req); err != nil { return nil, err } } - // Transfer the certificate settings to the container request - err := configureCertificate(settings, &req) - if err != nil { - return nil, err - } - // Transfer the password settings to the container request - err = configurePassword(settings, &req) - if err != nil { + if err := configurePassword(options, &req); err != nil { return nil, err } if isAtLeastVersion(req.Image, 7) { - req.LifecycleHooks[0].PostCreates = append(req.LifecycleHooks[0].PostCreates, configureJvmOpts) + req.LifecycleHooks = append(req.LifecycleHooks, + testcontainers.ContainerLifecycleHooks{ + PostCreates: []testcontainers.ContainerHook{configureJvmOpts}, + }, + ) } + // Set the default waiting strategy if not already set. + setWaitFor(options, &req.ContainerRequest) + container, err := testcontainers.GenericContainer(ctx, req) var esContainer *ElasticsearchContainer if container != nil { - esContainer = &ElasticsearchContainer{Container: container, Settings: *settings} + esContainer = &ElasticsearchContainer{Container: container, Settings: *options} } if err != nil { return esContainer, fmt.Errorf("generic container: %w", err) @@ -110,6 +100,61 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom return esContainer, nil } +// certWriter is a helper that writes the details of a CA cert to options. +type certWriter struct { + options *Options + certPool *x509.CertPool +} + +// Read reads the CA cert from the reader and appends it to the options. +func (w *certWriter) Read(r io.Reader) error { + buf, err := io.ReadAll(r) + if err != nil { + return fmt.Errorf("read CA cert: %w", err) + } + + w.options.CACert = buf + w.certPool.AppendCertsFromPEM(w.options.CACert) + + return nil +} + +// setWaitFor sets the req.WaitingFor strategy based on settings. +func setWaitFor(options *Options, req *testcontainers.ContainerRequest) { + var strategies []wait.Strategy + if req.WaitingFor != nil { + // Custom waiting strategy, ensure we honour it. + strategies = append(strategies, req.WaitingFor) + } + + waitHTTP := wait.ForHTTP("/").WithPort(defaultHTTPPort) + if sslRequired(req) { + waitHTTP = waitHTTP.WithTLS(true).WithAllowInsecure(true) + cw := &certWriter{ + options: options, + certPool: x509.NewCertPool(), + } + + waitHTTP = waitHTTP. + WithTLS(true, &tls.Config{RootCAs: cw.certPool}) + + strategies = append(strategies, wait.ForFile(defaultCaCertPath).WithMatcher(cw.Read)) + } + + if options.Password != "" || options.Username != "" { + waitHTTP = waitHTTP.WithBasicAuth(options.Username, options.Password) + } + + strategies = append(strategies, waitHTTP) + + if len(strategies) > 1 { + req.WaitingFor = wait.ForAll(strategies...) + return + } + + req.WaitingFor = strategies[0] +} + // configureAddress sets the address of the Elasticsearch container. // If the certificate is set, it will use https as protocol, otherwise http. func (c *ElasticsearchContainer) configureAddress(ctx context.Context) error { @@ -133,50 +178,28 @@ func (c *ElasticsearchContainer) configureAddress(ctx context.Context) error { return nil } -// configureCertificate transfers the certificate settings to the container request. -// For that, it defines a post start hook that copies the certificate from the container to the host. -// The certificate is only available since version 8, and will be located in a well-known location. -func configureCertificate(settings *Options, req *testcontainers.GenericContainerRequest) error { - if isAtLeastVersion(req.Image, 8) { - // These configuration keys explicitly disable CA generation. - // If any are set we skip the file retrieval. - configKeys := []string{ - "xpack.security.enabled", - "xpack.security.http.ssl.enabled", - "xpack.security.transport.ssl.enabled", - } - for _, configKey := range configKeys { - if value, ok := req.Env[configKey]; ok { - if value == "false" { - return nil - } +// sslRequired returns true if the SSL is required, otherwise false. +func sslRequired(req *testcontainers.ContainerRequest) bool { + if !isAtLeastVersion(req.Image, 8) { + return false + } + + // These configuration keys explicitly disable CA generation. + // If any are set we skip the file retrieval. + configKeys := []string{ + "xpack.security.enabled", + "xpack.security.http.ssl.enabled", + "xpack.security.transport.ssl.enabled", + } + for _, configKey := range configKeys { + if value, ok := req.Env[configKey]; ok { + if value == "false" { + return false } } - - // The container needs a post ready hook to copy the certificate from the container to the host. - // This certificate is only available since version 8 - req.LifecycleHooks[0].PostReadies = append(req.LifecycleHooks[0].PostReadies, - func(ctx context.Context, container testcontainers.Container) error { - const defaultCaCertPath = "/usr/share/elasticsearch/config/certs/http_ca.crt" - - readCloser, err := container.CopyFileFromContainer(ctx, defaultCaCertPath) - if err != nil { - return err - } - - // receive the bytes from the default location - certBytes, err := io.ReadAll(readCloser) - if err != nil { - return err - } - - settings.CACert = certBytes - - return nil - }) } - return nil + return true } // configurePassword transfers the password settings to the container request. diff --git a/modules/elasticsearch/options.go b/modules/elasticsearch/options.go index ed801c3b09..ba4dca75c3 100644 --- a/modules/elasticsearch/options.go +++ b/modules/elasticsearch/options.go @@ -16,7 +16,6 @@ type Options struct { func defaultOptions() *Options { return &Options{ - CACert: nil, Username: defaultUsername, } } From 9562594af1a5a9fc3ed9dd9047b7e9c7d31f225b Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 27 Sep 2024 03:41:12 -0400 Subject: [PATCH 080/126] fix(redpanda): wait for (#2794) Wait for the admin interface to response to HTTP to avoid failures in configuring the instance when its not fully ready. Clean up error wrapping. --- modules/redpanda/redpanda.go | 71 +++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/modules/redpanda/redpanda.go b/modules/redpanda/redpanda.go index 686d310d9f..c0936637d3 100644 --- a/modules/redpanda/redpanda.go +++ b/modules/redpanda/redpanda.go @@ -62,7 +62,7 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*Container, error) { tmpDir, err := os.MkdirTemp("", "redpanda") if err != nil { - return nil, fmt.Errorf("failed to create directory: %w", err) + return nil, fmt.Errorf("create temporary directory: %w", err) } defer os.RemoveAll(tmpDir) @@ -121,13 +121,13 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom // the Kafka API. entrypointPath := filepath.Join(tmpDir, entrypointFile) if err := os.WriteFile(entrypointPath, entrypoint, 0o700); err != nil { - return nil, fmt.Errorf("failed to create entrypoint file: %w", err) + return nil, fmt.Errorf("write entrypoint file: %w", err) } // 4. Register extra kafka listeners if provided, network aliases will be // set if err := registerListeners(settings, req); err != nil { - return nil, fmt.Errorf("failed to register listeners: %w", err) + return nil, fmt.Errorf("register listeners: %w", err) } // Bootstrap config file contains cluster configurations which will only be considered @@ -135,10 +135,10 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom bootstrapConfigPath := filepath.Join(tmpDir, bootstrapConfigFile) bootstrapConfig, err := renderBootstrapConfig(settings) if err != nil { - return nil, fmt.Errorf("failed to create bootstrap config file: %w", err) + return nil, err } if err := os.WriteFile(bootstrapConfigPath, bootstrapConfig, 0o600); err != nil { - return nil, fmt.Errorf("failed to create bootstrap config file: %w", err) + return nil, fmt.Errorf("write bootstrap config: %w", err) } req.Files = append(req.Files, @@ -158,11 +158,11 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom if settings.EnableTLS { certPath := filepath.Join(tmpDir, certFile) if err := os.WriteFile(certPath, settings.cert, 0o600); err != nil { - return nil, fmt.Errorf("failed to create certificate file: %w", err) + return nil, fmt.Errorf("write certificate file: %w", err) } keyPath := filepath.Join(tmpDir, keyFile) if err := os.WriteFile(keyPath, settings.key, 0o600); err != nil { - return nil, fmt.Errorf("failed to create key file: %w", err) + return nil, fmt.Errorf("write key file: %w", err) } req.Files = append(req.Files, @@ -192,34 +192,54 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom // the Redpanda config with the advertised Kafka address. hostIP, err := ctr.Host(ctx) if err != nil { - return c, fmt.Errorf("failed to get container host: %w", err) + return c, fmt.Errorf("host: %w", err) } kafkaPort, err := ctr.MappedPort(ctx, nat.Port(defaultKafkaAPIPort)) if err != nil { - return c, fmt.Errorf("failed to get mapped Kafka port: %w", err) + return c, fmt.Errorf("mapped kafka port: %w", err) } // 7. Render redpanda.yaml config and mount it. nodeConfig, err := renderNodeConfig(settings, hostIP, kafkaPort.Int()) if err != nil { - return c, fmt.Errorf("failed to render node config: %w", err) + return c, err } - err = ctr.CopyToContainer(ctx, nodeConfig, filepath.Join(redpandaDir, "redpanda.yaml"), 600) + err = ctr.CopyToContainer(ctx, nodeConfig, filepath.Join(redpandaDir, "redpanda.yaml"), 0o600) if err != nil { - return c, fmt.Errorf("failed to copy redpanda.yaml into container: %w", err) + return c, fmt.Errorf("copy to container: %w", err) } // 8. Wait until Redpanda is ready to serve requests. + waitHTTP := wait.ForHTTP(defaultAdminAPIPort). + WithStatusCodeMatcher(func(status int) bool { + // Redpanda's admin API returns 404 for requests to "/". + return status == http.StatusNotFound + }) + + var tlsConfig *tls.Config + if settings.EnableTLS { + cert, err := tls.X509KeyPair(settings.cert, settings.key) + if err != nil { + return c, fmt.Errorf("create admin cert: %w", err) + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(settings.cert) + tlsConfig = &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: caCertPool, + } + waitHTTP = waitHTTP.WithTLS(true, tlsConfig) + } err = wait.ForAll( wait.ForListeningPort(defaultKafkaAPIPort), - wait.ForListeningPort(defaultAdminAPIPort), + waitHTTP, wait.ForListeningPort(defaultSchemaRegistryPort), wait.ForLog("Successfully started Redpanda!"), ).WaitUntilReady(ctx, ctr) if err != nil { - return c, fmt.Errorf("failed to wait for Redpanda readiness: %w", err) + return c, fmt.Errorf("wait for readiness: %w", err) } c.urlScheme = "http" @@ -231,34 +251,25 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom if len(settings.ServiceAccounts) > 0 { adminAPIPort, err := ctr.MappedPort(ctx, nat.Port(defaultAdminAPIPort)) if err != nil { - return c, fmt.Errorf("failed to get mapped Admin API port: %w", err) + return c, fmt.Errorf("mapped admin port: %w", err) } adminAPIUrl := fmt.Sprintf("%s://%v:%d", c.urlScheme, hostIP, adminAPIPort.Int()) adminCl := NewAdminAPIClient(adminAPIUrl) if settings.EnableTLS { - cert, err := tls.X509KeyPair(settings.cert, settings.key) - if err != nil { - return c, fmt.Errorf("failed to create admin client with cert: %w", err) - } - caCertPool := x509.NewCertPool() - caCertPool.AppendCertsFromPEM(settings.cert) adminCl = adminCl.WithHTTPClient(&http.Client{ Timeout: 5 * time.Second, Transport: &http.Transport{ ForceAttemptHTTP2: true, TLSHandshakeTimeout: 10 * time.Second, - TLSClientConfig: &tls.Config{ - Certificates: []tls.Certificate{cert}, - RootCAs: caCertPool, - }, + TLSClientConfig: tlsConfig, }, }) } for username, password := range settings.ServiceAccounts { if err := adminCl.CreateUser(ctx, username, password); err != nil { - return c, fmt.Errorf("failed to create service account with username %q: %w", username, err) + return c, fmt.Errorf("create user %q: %w", username, err) } } } @@ -299,12 +310,12 @@ func renderBootstrapConfig(settings options) ([]byte, error) { tpl, err := template.New("bootstrap.yaml").Parse(bootstrapConfigTpl) if err != nil { - return nil, fmt.Errorf("failed to parse redpanda config file template: %w", err) + return nil, fmt.Errorf("parse bootstrap template: %w", err) } var bootstrapConfig bytes.Buffer if err := tpl.Execute(&bootstrapConfig, bootstrapTplParams); err != nil { - return nil, fmt.Errorf("failed to render redpanda bootstrap config template: %w", err) + return nil, fmt.Errorf("render bootstrap template: %w", err) } return bootstrapConfig.Bytes(), nil @@ -353,12 +364,12 @@ func renderNodeConfig(settings options, hostIP string, advertisedKafkaPort int) ncTpl, err := template.New("redpanda.yaml").Parse(nodeConfigTpl) if err != nil { - return nil, fmt.Errorf("failed to parse redpanda config file template: %w", err) + return nil, fmt.Errorf("parse node config template: %w", err) } var redpandaYaml bytes.Buffer if err := ncTpl.Execute(&redpandaYaml, tplParams); err != nil { - return nil, fmt.Errorf("failed to render redpanda node config template: %w", err) + return nil, fmt.Errorf("render node config template: %w", err) } return redpandaYaml.Bytes(), nil From 7a1419d9e6ff7f8beeacd006283f270adb59499e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 30 Sep 2024 10:13:21 +0200 Subject: [PATCH 081/126] feat: add dynamodb-local module (#2799) * feat: add dynamodb-local module * docs: fix * fix: remove module from CI * fix: wrongly generated * chore: bump dockercfg * chore: wrap errors * Revert "chore: wrap errors" This reverts commit 93a9d015f7145e8becc712cf7d4acbf0a1257e8e. * fix: remove unused constant * chore: wrap errors * chore: simplify helper methods * chore: wrap methods * fix: partially revert helpers as we need to check for errors in the caller * chore: wrap error * chore: simplify variable Co-authored-by: Steven Hartland * fixlint * chore: pass testing.T --------- Co-authored-by: Steven Hartland --- .github/workflows/ci.yml | 2 +- .vscode/.testcontainers-go.code-workspace | 4 + docs/modules/dynamodb.md | 77 +++++++ mkdocs.yml | 1 + modules/dynamodb/Makefile | 5 + modules/dynamodb/dynamodb.go | 90 ++++++++ modules/dynamodb/dynamodb_test.go | 260 ++++++++++++++++++++++ modules/dynamodb/examples_test.go | 38 ++++ modules/dynamodb/go.mod | 76 +++++++ modules/dynamodb/go.sum | 228 +++++++++++++++++++ sonar-project.properties | 2 +- 11 files changed, 781 insertions(+), 2 deletions(-) create mode 100644 docs/modules/dynamodb.md create mode 100644 modules/dynamodb/Makefile create mode 100644 modules/dynamodb/dynamodb.go create mode 100644 modules/dynamodb/dynamodb_test.go create mode 100644 modules/dynamodb/examples_test.go create mode 100644 modules/dynamodb/go.mod create mode 100644 modules/dynamodb/go.sum diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7dcb44618..49dfc336c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: matrix: go-version: [1.22.x, 1.x] platform: [ubuntu-latest] - module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, elasticsearch, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate] + module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, dynamodb, elasticsearch, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate] uses: ./.github/workflows/ci-test-go.yml with: go-version: ${{ matrix.go-version }} diff --git a/.vscode/.testcontainers-go.code-workspace b/.vscode/.testcontainers-go.code-workspace index b355235ac2..df74747a48 100644 --- a/.vscode/.testcontainers-go.code-workspace +++ b/.vscode/.testcontainers-go.code-workspace @@ -57,6 +57,10 @@ "name": "module / dolt", "path": "../modules/dolt" }, + { + "name": "module / dynamodb", + "path": "../modules/dynamodb" + }, { "name": "module / elasticsearch", "path": "../modules/elasticsearch" diff --git a/docs/modules/dynamodb.md b/docs/modules/dynamodb.md new file mode 100644 index 0000000000..cdc7312640 --- /dev/null +++ b/docs/modules/dynamodb.md @@ -0,0 +1,77 @@ +# DynamoDB + +Not available until the next release of testcontainers-go :material-tag: main + +## Introduction + +The Testcontainers module for DynamoDB. + +## Adding this module to your project dependencies + +Please run the following command to add the DynamoDB module to your Go dependencies: + +``` +go get github.com/testcontainers/testcontainers-go/modules/dynamodb +``` + +## Usage example + + +[Creating a DynamoDB container](../../modules/dynamodb/examples_test.go) inside_block:runDynamoDBContainer + + +## Module Reference + +### Run function + +- Not available until the next release of testcontainers-go :material-tag: main + +The DynamoDB module exposes one entrypoint function to create the DynamoDB container, and this function receives three parameters: + +```golang +func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*DynamoDBContainer, error) +``` + +- `context.Context`, the Go context. +- `string`, the Docker image to use. +- `testcontainers.ContainerCustomizer`, a variadic argument for passing options. + +### Container Options + +When starting the DynamoDB container, you can pass options in a variadic way to configure it. + +#### Image + +If you need to set a different DynamoDB Docker image, you can set a valid Docker image as the second argument in the `Run` function. +E.g. `Run(context.Background(), "amazon/dynamodb-local:2.2.1")`. + +{% include "../features/common_functional_options.md" %} + +#### WithSharedDB + +- Not available until the next release of testcontainers-go :material-tag: main + +The `WithSharedDB` option tells the DynamoDB container to use a single database file. At the same time, it marks the container as reusable, which causes that successive calls to the `Run` function will return the same container instance, and therefore, the same database file. + +#### WithDisableTelemetry + +- Not available until the next release of testcontainers-go :material-tag: main + +You can turn off telemetry when starting the DynamoDB container, using the option `WithDisableTelemetry`. + +### Container Methods + +The DynamoDB container exposes the following methods: + +#### ConnectionString + +- Not available until the next release of testcontainers-go :material-tag: main + +The `ConnectionString` method returns the connection string to the DynamoDB container. This connection string can be used to connect to the DynamoDB container from your application, +using the AWS SDK or any other DynamoDB client of your choice. + + +[Creating a client](../../modules/dynamodb/dynamodb_test.go) inside_block:createClient + + +The above example uses `github.com/aws/aws-sdk-go-v2/service/dynamodb` to create a client and connect to the DynamoDB container. diff --git a/mkdocs.yml b/mkdocs.yml index 3aa4af31b7..f5dfafebdd 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -76,6 +76,7 @@ nav: - modules/couchbase.md - modules/databend.md - modules/dolt.md + - modules/dynamodb.md - modules/elasticsearch.md - modules/gcloud.md - modules/grafana-lgtm.md diff --git a/modules/dynamodb/Makefile b/modules/dynamodb/Makefile new file mode 100644 index 0000000000..42d3e1226f --- /dev/null +++ b/modules/dynamodb/Makefile @@ -0,0 +1,5 @@ +include ../../commons-test.mk + +.PHONY: test +test: + $(MAKE) test-dynamodb diff --git a/modules/dynamodb/dynamodb.go b/modules/dynamodb/dynamodb.go new file mode 100644 index 0000000000..62a6938efe --- /dev/null +++ b/modules/dynamodb/dynamodb.go @@ -0,0 +1,90 @@ +package dynamodb + +import ( + "context" + "fmt" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +const ( + port = "8000/tcp" + containerName = "tc_dynamodb_local" +) + +// DynamoDBContainer represents the DynamoDB container type used in the module +type DynamoDBContainer struct { + testcontainers.Container +} + +// Run creates an instance of the DynamoDB container type +func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*DynamoDBContainer, error) { + req := testcontainers.ContainerRequest{ + Image: img, + ExposedPorts: []string{string(port)}, + Entrypoint: []string{"java", "-Djava.library.path=./DynamoDBLocal_lib"}, + Cmd: []string{"-jar", "DynamoDBLocal.jar"}, + WaitingFor: wait.ForListeningPort(port), + } + + genericContainerReq := testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + } + + for _, opt := range opts { + if err := opt.Customize(&genericContainerReq); err != nil { + return nil, fmt.Errorf("customize: %w", err) + } + } + + container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *DynamoDBContainer + if container != nil { + c = &DynamoDBContainer{Container: container} + } + + if err != nil { + return c, fmt.Errorf("generic container: %w", err) + } + + return c, nil +} + +// ConnectionString returns DynamoDB local endpoint host and port in : format +func (c *DynamoDBContainer) ConnectionString(ctx context.Context) (string, error) { + mappedPort, err := c.MappedPort(ctx, port) + if err != nil { + return "", err + } + + hostIP, err := c.Host(ctx) + if err != nil { + return "", err + } + + return hostIP + ":" + mappedPort.Port(), nil +} + +// WithSharedDB allows container reuse between successive runs. Data will be persisted +func WithSharedDB() testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + req.Cmd = append(req.Cmd, "-sharedDb") + + req.Reuse = true + req.Name = containerName + + return nil + } +} + +// WithDisableTelemetry - DynamoDB local will not send any telemetry +func WithDisableTelemetry() testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + // if other flags (e.g. -sharedDb) exist, append to them + req.Cmd = append(req.Cmd, "-disableTelemetry") + + return nil + } +} diff --git a/modules/dynamodb/dynamodb_test.go b/modules/dynamodb/dynamodb_test.go new file mode 100644 index 0000000000..b62766d813 --- /dev/null +++ b/modules/dynamodb/dynamodb_test.go @@ -0,0 +1,260 @@ +package dynamodb_test + +import ( + "context" + "errors" + "fmt" + "net/url" + "testing" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/dynamodb" + "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + smithyendpoints "github.com/aws/smithy-go/endpoints" + "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go" + tcdynamodb "github.com/testcontainers/testcontainers-go/modules/dynamodb" +) + +const ( + tableName string = "demo_table" + pkColumnName string = "demo_pk" + baseImage string = "amazon/dynamodb-local:" +) + +var image2_2_1 string = baseImage + "2.2.1" + +func TestRun(t *testing.T) { + ctx := context.Background() + + ctr, err := tcdynamodb.Run(ctx, image2_2_1) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + cli := getDynamoDBClient(t, ctr) + require.NoError(t, err, "failed to get dynamodb client handle") + + requireTableExists(t, cli, tableName) + + value := "test_value" + addDataToTable(t, cli, value) + + queryResult := queryItem(t, cli, value) + require.Equal(t, value, queryResult) +} + +func TestRun_withCustomImageVersion(t *testing.T) { + ctx := context.Background() + + ctr, err := tcdynamodb.Run(ctx, "amazon/dynamodb-local:2.2.0") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) +} + +func TestRun_withInvalidCustomImageVersion(t *testing.T) { + ctx := context.Background() + + _, err := tcdynamodb.Run(ctx, "amazon/dynamodb-local:0.0.7") + require.Error(t, err) +} + +func TestRun_withoutEndpointResolver(t *testing.T) { + ctx := context.Background() + + ctr, err := tcdynamodb.Run(ctx, image2_2_1) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err, "container should start successfully") + + cli := dynamodb.New(dynamodb.Options{}) + + err = createTable(cli) + require.Error(t, err) +} + +func TestRun_withSharedDB(t *testing.T) { + ctx := context.Background() + + ctr, err := tcdynamodb.Run(ctx, image2_2_1, tcdynamodb.WithSharedDB()) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + cli1 := getDynamoDBClient(t, ctr) + + requireTableExists(t, cli1, tableName) + + // create a second container: it should have the table created in the first container + ctr2, err := tcdynamodb.Run(ctx, image2_2_1, tcdynamodb.WithSharedDB()) + testcontainers.CleanupContainer(t, ctr2) + require.NoError(t, err) + + // fetch client handle again + cli2 := getDynamoDBClient(t, ctr2) + require.NoError(t, err, "failed to get dynamodb client handle") + + // list tables and verify + + result, err := cli2.ListTables(context.Background(), nil) + require.NoError(t, err, "dynamodb list tables operation failed") + + actualTableName := result.TableNames[0] + require.Equal(t, tableName, actualTableName) + + // add and query data from the second container + value := "test_value" + addDataToTable(t, cli2, value) + + // read data from the first container + queryResult := queryItem(t, cli1, value) + require.NoError(t, err) + require.Equal(t, value, queryResult) +} + +func TestRun_withoutSharedDB(t *testing.T) { + ctx := context.Background() + + ctr1, err := tcdynamodb.Run(ctx, image2_2_1) + testcontainers.CleanupContainer(t, ctr1) + require.NoError(t, err) + + cli := getDynamoDBClient(t, ctr1) + require.NoError(t, err, "failed to get dynamodb client handle") + + requireTableExists(t, cli, tableName) + + // create a second container: it should not have the table created in the first container + ctr2, err := tcdynamodb.Run(ctx, image2_2_1) + testcontainers.CleanupContainer(t, ctr2) + require.NoError(t, err) + + // fetch client handle again + cli = getDynamoDBClient(t, ctr2) + require.NoError(t, err, "failed to get dynamodb client handle") + + // list tables and verify + + result, err := cli.ListTables(context.Background(), nil) + require.NoError(t, err, "dynamodb list tables operation failed") + require.Empty(t, result.TableNames, "table should not exist after restarting container") +} + +func TestRun_shouldStartWithTelemetryDisabled(t *testing.T) { + ctx := context.Background() + + ctr, err := tcdynamodb.Run(ctx, image2_2_1, tcdynamodb.WithDisableTelemetry()) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) +} + +func TestRun_shouldStartWithSharedDBEnabledAndTelemetryDisabled(t *testing.T) { + ctx := context.Background() + + ctr, err := tcdynamodb.Run(ctx, image2_2_1, tcdynamodb.WithSharedDB(), tcdynamodb.WithDisableTelemetry()) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) +} + +func createTable(client *dynamodb.Client) error { + _, err := client.CreateTable(context.Background(), &dynamodb.CreateTableInput{ + TableName: aws.String(tableName), + KeySchema: []types.KeySchemaElement{ + { + AttributeName: aws.String(pkColumnName), + KeyType: types.KeyTypeHash, + }, + }, + AttributeDefinitions: []types.AttributeDefinition{ + { + AttributeName: aws.String(pkColumnName), + AttributeType: types.ScalarAttributeTypeS, + }, + }, + BillingMode: types.BillingModePayPerRequest, + }) + if err != nil { + return fmt.Errorf("create table: %w", err) + } + + return nil +} + +func addDataToTable(t *testing.T, client *dynamodb.Client, val string) { + t.Helper() + + _, err := client.PutItem(context.Background(), &dynamodb.PutItemInput{ + TableName: aws.String(tableName), + Item: map[string]types.AttributeValue{ + pkColumnName: &types.AttributeValueMemberS{Value: val}, + }, + }) + require.NoError(t, err) +} + +func queryItem(t *testing.T, client *dynamodb.Client, val string) string { + t.Helper() + + output, err := client.GetItem(context.Background(), &dynamodb.GetItemInput{ + TableName: aws.String(tableName), + Key: map[string]types.AttributeValue{ + pkColumnName: &types.AttributeValueMemberS{Value: val}, + }, + }) + require.NoError(t, err) + + result := output.Item[pkColumnName].(*types.AttributeValueMemberS) + + return result.Value +} + +type dynamoDBResolver struct { + HostPort string +} + +func (r *dynamoDBResolver) ResolveEndpoint(ctx context.Context, params dynamodb.EndpointParameters) (smithyendpoints.Endpoint, error) { + return smithyendpoints.Endpoint{ + URI: url.URL{Host: r.HostPort, Scheme: "http"}, + }, nil +} + +// getDynamoDBClient returns a new DynamoDB client with the endpoint resolver set to the DynamoDB container's host and port +func getDynamoDBClient(t *testing.T, c *tcdynamodb.DynamoDBContainer) *dynamodb.Client { + t.Helper() + + // createClient { + var errs []error + + hostPort, err := c.ConnectionString(context.Background()) + if err != nil { + errs = append(errs, fmt.Errorf("get connection string: %w", err)) + } + + cfg, err := config.LoadDefaultConfig(context.Background(), config.WithCredentialsProvider(credentials.StaticCredentialsProvider{ + Value: aws.Credentials{ + AccessKeyID: "DUMMYIDEXAMPLE", + SecretAccessKey: "DUMMYEXAMPLEKEY", + }, + })) + if err != nil { + errs = append(errs, fmt.Errorf("load default config: %w", err)) + } + + require.NoError(t, errors.Join(errs...)) + + return dynamodb.NewFromConfig(cfg, dynamodb.WithEndpointResolverV2(&dynamoDBResolver{HostPort: hostPort})) + // } +} + +func requireTableExists(t *testing.T, cli *dynamodb.Client, tableName string) { + t.Helper() + + err := createTable(cli) + require.NoError(t, err) + + result, err := cli.ListTables(context.Background(), nil) + require.NoError(t, err, "dynamodb list tables operation failed") + + actualTableName := result.TableNames[0] + require.Equal(t, tableName, actualTableName) +} diff --git a/modules/dynamodb/examples_test.go b/modules/dynamodb/examples_test.go new file mode 100644 index 0000000000..e4e478b943 --- /dev/null +++ b/modules/dynamodb/examples_test.go @@ -0,0 +1,38 @@ +package dynamodb_test + +import ( + "context" + "fmt" + "log" + + "github.com/testcontainers/testcontainers-go" + tcdynamodb "github.com/testcontainers/testcontainers-go/modules/dynamodb" +) + +func ExampleRun() { + // runDynamoDBContainer { + ctx := context.Background() + + ctr, err := tcdynamodb.Run(ctx, "amazon/dynamodb-local:2.2.1") + defer func() { + if err := testcontainers.TerminateContainer(ctr); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() + if err != nil { + log.Printf("failed to run dynamodb container: %s", err) + return + } + // } + + state, err := ctr.State(ctx) + if err != nil { + log.Printf("failed to get container state: %s", err) + return + } + + fmt.Println(state.Running) + + // Output: + // true +} diff --git a/modules/dynamodb/go.mod b/modules/dynamodb/go.mod new file mode 100644 index 0000000000..08d4eab7c1 --- /dev/null +++ b/modules/dynamodb/go.mod @@ -0,0 +1,76 @@ +module github.com/testcontainers/testcontainers-go/modules/dynamodb + +go 1.22 + +require ( + github.com/aws/aws-sdk-go-v2 v1.31.0 + github.com/aws/aws-sdk-go-v2/config v1.27.37 + github.com/aws/aws-sdk-go-v2/credentials v1.17.35 + github.com/aws/aws-sdk-go-v2/service/dynamodb v1.35.1 + github.com/aws/smithy-go v1.21.0 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.33.0 +) + +require ( + dario.cat/mergo v1.0.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.19 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.23.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.31.1 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/containerd/containerd v1.7.18 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v27.1.1+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/sys v0.21.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/dynamodb/go.sum b/modules/dynamodb/go.sum new file mode 100644 index 0000000000..bae52466e0 --- /dev/null +++ b/modules/dynamodb/go.sum @@ -0,0 +1,228 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +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/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/aws/aws-sdk-go-v2 v1.31.0 h1:3V05LbxTSItI5kUqNwhJrrrY1BAXxXt0sN0l72QmG5U= +github.com/aws/aws-sdk-go-v2 v1.31.0/go.mod h1:ztolYtaEUtdpf9Wftr31CJfLVjOnD/CVRkKOOYgF8hA= +github.com/aws/aws-sdk-go-v2/config v1.27.37 h1:xaoIwzHVuRWRHFI0jhgEdEGc8xE1l91KaeRDsWEIncU= +github.com/aws/aws-sdk-go-v2/config v1.27.37/go.mod h1:S2e3ax9/8KnMSyRVNd3sWTKs+1clJ2f1U6nE0lpvQRg= +github.com/aws/aws-sdk-go-v2/credentials v1.17.35 h1:7QknrZhYySEB1lEXJxGAmuD5sWwys5ZXNr4m5oEz0IE= +github.com/aws/aws-sdk-go-v2/credentials v1.17.35/go.mod h1:8Vy4kk7at4aPSmibr7K+nLTzG6qUQAUO4tW49fzUV4E= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14 h1:C/d03NAmh8C4BZXhuRNboF/DqhBkBCeDiJDcaqIT5pA= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.14/go.mod h1:7I0Ju7p9mCIdlrfS+JCgqcYD0VXz/N4yozsox+0o078= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18 h1:kYQ3H1u0ANr9KEKlGs/jTLrBFPo8P8NaH/w7A01NeeM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.18/go.mod h1:r506HmK5JDUh9+Mw4CfGJGSSoqIiLCndAuqXuhbv67Y= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18 h1:Z7IdFUONvTcvS7YuhtVxN99v2cCoHRXOS4mTr0B/pUc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.18/go.mod h1:DkKMmksZVVyat+Y+r1dEOgJEfUeA7UngIHWeKsi0yNc= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.35.1 h1:DDN8yqYzFUDy2W5zk3tLQNKaO/1t0h3fNixPJacu264= +github.com/aws/aws-sdk-go-v2/service/dynamodb v1.35.1/go.mod h1:k5XW8MoMxsNZ20RJmsokakvENUwQyjv69R9GqrI4xdQ= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5 h1:QFASJGfT8wMXtuP3D5CRmMjARHv9ZmzFUMJznHDOY3w= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.5/go.mod h1:QdZ3OmoIjSX+8D1OPAzPxDfjXASbBMDsz9qvtyIhtik= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.19 h1:dOxqOlOEa2e2heC/74+ZzcJOa27+F1aXFZpYgY/4QfA= +github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.19/go.mod h1:aV6U1beLFvk3qAgognjS3wnGGoDId8hlPEiBsLHXVZE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20 h1:Xbwbmk44URTiHNx6PNo0ujDE6ERlsCKJD3u1zfnzAPg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.20/go.mod h1:oAfOFzUB14ltPZj1rWwRc3d/6OgD76R8KlvU3EqM9Fg= +github.com/aws/aws-sdk-go-v2/service/sso v1.23.1 h1:2jrVsMHqdLD1+PA4BA6Nh1eZp0Gsy3mFSB5MxDvcJtU= +github.com/aws/aws-sdk-go-v2/service/sso v1.23.1/go.mod h1:XRlMvmad0ZNL+75C5FYdMvbbLkd6qiqz6foR1nA1PXY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.1 h1:0L7yGCg3Hb3YQqnSgBTZM5wepougtL1aEccdcdYhHME= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.1/go.mod h1:FnvDM4sfa+isJ3kDXIzAB9GAwVSzFzSy97uZ3IsHo4E= +github.com/aws/aws-sdk-go-v2/service/sts v1.31.1 h1:8K0UNOkZiK9Uh3HIF6Bx0rcNCftqGCeKmOaR7Gp5BSo= +github.com/aws/aws-sdk-go-v2/service/sts v1.31.1/go.mod h1:yMWe0F+XG0DkRZK5ODZhG7BEFYhLXi2dqGsv6tX0cgI= +github.com/aws/smithy-go v1.21.0 h1:H7L8dtDRk0P1Qm6y0ji7MCYMQObJ5R9CRpyPhRUkLYA= +github.com/aws/smithy-go v1.21.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= +github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +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.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +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.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +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/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20230920204549-e6e6cdab5c13 h1:vlzZttNJGVqTsRFU9AmdnrcO1Znh8Ew9kCD//yjigk0= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= +google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.2.8/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/sonar-project.properties b/sonar-project.properties index 5a6dd117bb..8c7946ed8e 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -18,4 +18,4 @@ sonar.test.inclusions=**/*_test.go sonar.test.exclusions=**/vendor/** sonar.go.coverage.reportPaths=**/coverage.out -sonar.go.tests.reportPaths=TEST-unit.xml,examples/nginx/TEST-unit.xml,examples/toxiproxy/TEST-unit.xml,modulegen/TEST-unit.xml,modules/artemis/TEST-unit.xml,modules/azurite/TEST-unit.xml,modules/cassandra/TEST-unit.xml,modules/chroma/TEST-unit.xml,modules/clickhouse/TEST-unit.xml,modules/cockroachdb/TEST-unit.xml,modules/compose/TEST-unit.xml,modules/consul/TEST-unit.xml,modules/couchbase/TEST-unit.xml,modules/databend/TEST-unit.xml,modules/dolt/TEST-unit.xml,modules/elasticsearch/TEST-unit.xml,modules/gcloud/TEST-unit.xml,modules/grafana-lgtm/TEST-unit.xml,modules/inbucket/TEST-unit.xml,modules/influxdb/TEST-unit.xml,modules/k3s/TEST-unit.xml,modules/k6/TEST-unit.xml,modules/kafka/TEST-unit.xml,modules/localstack/TEST-unit.xml,modules/mariadb/TEST-unit.xml,modules/milvus/TEST-unit.xml,modules/minio/TEST-unit.xml,modules/mockserver/TEST-unit.xml,modules/mongodb/TEST-unit.xml,modules/mssql/TEST-unit.xml,modules/mysql/TEST-unit.xml,modules/nats/TEST-unit.xml,modules/neo4j/TEST-unit.xml,modules/ollama/TEST-unit.xml,modules/openfga/TEST-unit.xml,modules/openldap/TEST-unit.xml,modules/opensearch/TEST-unit.xml,modules/postgres/TEST-unit.xml,modules/pulsar/TEST-unit.xml,modules/qdrant/TEST-unit.xml,modules/rabbitmq/TEST-unit.xml,modules/redis/TEST-unit.xml,modules/redpanda/TEST-unit.xml,modules/registry/TEST-unit.xml,modules/surrealdb/TEST-unit.xml,modules/valkey/TEST-unit.xml,modules/vault/TEST-unit.xml,modules/vearch/TEST-unit.xml,modules/weaviate/TEST-unit.xml +sonar.go.tests.reportPaths=TEST-unit.xml,examples/nginx/TEST-unit.xml,examples/toxiproxy/TEST-unit.xml,modulegen/TEST-unit.xml,modules/artemis/TEST-unit.xml,modules/azurite/TEST-unit.xml,modules/cassandra/TEST-unit.xml,modules/chroma/TEST-unit.xml,modules/clickhouse/TEST-unit.xml,modules/cockroachdb/TEST-unit.xml,modules/compose/TEST-unit.xml,modules/consul/TEST-unit.xml,modules/couchbase/TEST-unit.xml,modules/databend/TEST-unit.xml,modules/dolt/TEST-unit.xml,modules/dynamodb/TEST-unit.xml,modules/elasticsearch/TEST-unit.xml,modules/gcloud/TEST-unit.xml,modules/grafana-lgtm/TEST-unit.xml,modules/inbucket/TEST-unit.xml,modules/influxdb/TEST-unit.xml,modules/k3s/TEST-unit.xml,modules/k6/TEST-unit.xml,modules/kafka/TEST-unit.xml,modules/localstack/TEST-unit.xml,modules/mariadb/TEST-unit.xml,modules/milvus/TEST-unit.xml,modules/minio/TEST-unit.xml,modules/mockserver/TEST-unit.xml,modules/mongodb/TEST-unit.xml,modules/mssql/TEST-unit.xml,modules/mysql/TEST-unit.xml,modules/nats/TEST-unit.xml,modules/neo4j/TEST-unit.xml,modules/ollama/TEST-unit.xml,modules/openfga/TEST-unit.xml,modules/openldap/TEST-unit.xml,modules/opensearch/TEST-unit.xml,modules/postgres/TEST-unit.xml,modules/pulsar/TEST-unit.xml,modules/qdrant/TEST-unit.xml,modules/rabbitmq/TEST-unit.xml,modules/redis/TEST-unit.xml,modules/redpanda/TEST-unit.xml,modules/registry/TEST-unit.xml,modules/surrealdb/TEST-unit.xml,modules/valkey/TEST-unit.xml,modules/vault/TEST-unit.xml,modules/vearch/TEST-unit.xml,modules/weaviate/TEST-unit.xml From f954f6d4a1be80f6eaa2234d8c6247da284b150e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 30 Sep 2024 18:16:33 +0200 Subject: [PATCH 082/126] feat: add etcd module (#2788) * chore: scaffolding for etcd module * feat: add etcd with cluster support * feat: support for AutoTLS * chore: add unit test for cmd * fix: remove non-existent module * chore: simplify removing auto-tls support * docs: remove old deprecated function * docs: document functions * docs: remove commented code * chore: more readable tests * chore: move logic to the functional option * chore: simplify passing current node opts * fix: return the parent node when creating the child nodes * chore: move to constant * chore: use zero values * fix: typo after wrong copy&paste * chore: remove must methods * chore: use private fields in the container * chore: use private fields in the options struct * chore: simplify public API * chore: make constants private * fix: lint * chore: rename field to childNodes * docs: enrich container comments * fix: assert on the right node * chore: bump dockercfg * feat: implement termination of the cluster * chore: use require.Zero * chore: proper test name * chore: preallocate slice * chore: do not allow single-node clusters * fix: join errors on terminate cluster * fix: check parent container is terminated * chore: extract to function * fix: check if container is not nil * chor: do not orphan the network * chore: simplify * docs: fix comment * chore: wrap errors in endpoint functions * Revert "chore: wrap errors in endpoint functions" This reverts commit 1c4361b2210d538438fbfb6bbea68dc949bc0379. * chore: simplify eval * fix: not needed * chore: simplify container initialisation * chore: simplify even more --- .github/workflows/ci.yml | 2 +- .vscode/.testcontainers-go.code-workspace | 4 + docs/modules/etcd.md | 95 ++++++++ mkdocs.yml | 1 + modules/etcd/Makefile | 5 + modules/etcd/cmd_test.go | 108 +++++++++ modules/etcd/etcd.go | 272 ++++++++++++++++++++++ modules/etcd/etcd_test.go | 60 +++++ modules/etcd/etcd_unit_test.go | 113 +++++++++ modules/etcd/examples_test.go | 97 ++++++++ modules/etcd/go.mod | 75 ++++++ modules/etcd/go.sum | 216 +++++++++++++++++ modules/etcd/options.go | 107 +++++++++ sonar-project.properties | 2 +- 14 files changed, 1155 insertions(+), 2 deletions(-) create mode 100644 docs/modules/etcd.md create mode 100644 modules/etcd/Makefile create mode 100644 modules/etcd/cmd_test.go create mode 100644 modules/etcd/etcd.go create mode 100644 modules/etcd/etcd_test.go create mode 100644 modules/etcd/etcd_unit_test.go create mode 100644 modules/etcd/examples_test.go create mode 100644 modules/etcd/go.mod create mode 100644 modules/etcd/go.sum create mode 100644 modules/etcd/options.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 49dfc336c4..0fea7eaeb0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: matrix: go-version: [1.22.x, 1.x] platform: [ubuntu-latest] - module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, dynamodb, elasticsearch, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate] + module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, dynamodb, elasticsearch, etcd, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate] uses: ./.github/workflows/ci-test-go.yml with: go-version: ${{ matrix.go-version }} diff --git a/.vscode/.testcontainers-go.code-workspace b/.vscode/.testcontainers-go.code-workspace index df74747a48..68a2751a5d 100644 --- a/.vscode/.testcontainers-go.code-workspace +++ b/.vscode/.testcontainers-go.code-workspace @@ -65,6 +65,10 @@ "name": "module / elasticsearch", "path": "../modules/elasticsearch" }, + { + "name": "module / etcd", + "path": "../modules/etcd" + }, { "name": "module / gcloud", "path": "../modules/gcloud" diff --git a/docs/modules/etcd.md b/docs/modules/etcd.md new file mode 100644 index 0000000000..f83816c986 --- /dev/null +++ b/docs/modules/etcd.md @@ -0,0 +1,95 @@ +# etcd + +Not available until the next release of testcontainers-go :material-tag: main + +## Introduction + +The Testcontainers module for etcd. + +## Adding this module to your project dependencies + +Please run the following command to add the etcd module to your Go dependencies: + +``` +go get github.com/testcontainers/testcontainers-go/modules/etcd +``` + +## Usage example + + +[Creating a etcd container](../../modules/etcd/examples_test.go) inside_block:runetcdContainer + + +## Module Reference + +### Run function + +- Not available until the next release of testcontainers-go :material-tag: main + +The etcd module exposes one entrypoint function to create the etcd container, and this function receives three parameters: + +```golang +func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*etcdContainer, error) +``` + +- `context.Context`, the Go context. +- `string`, the Docker image to use. +- `testcontainers.ContainerCustomizer`, a variadic argument for passing options. + +### Container Options + +When starting the etcd container, you can pass options in a variadic way to configure it. + +#### Image + +If you need to set a different etcd Docker image, you can set a valid Docker image as the second argument in the `Run` function. +E.g. `Run(context.Background(), "bitnami/etcd:latest")`. + +{% include "../features/common_functional_options.md" %} + +#### WithAdditionalArgs + +- Not available until the next release of testcontainers-go :material-tag: main + +You can pass additional arguments to the etcd container by using the `WithAdditionalArgs` option. The arguments are passed to the CMD of the etcd container. + +#### WithDataDir + +- Not available until the next release of testcontainers-go :material-tag: main + +You can set the data directory for the etcd container by using the `WithDataDir` boolean option. The data directory where the etcd data is stored is `/data.etcd`. + +#### WithNodes + +- Not available until the next release of testcontainers-go :material-tag: main + +You can set the number of nodes for the etcd cluster by using the `WithNodes` option, passing the node names for each of the nodes. Single-node clusters are not allowed, +for that reason the functional option receives three string arguments: the first node, the second node, and a variadic argument for the rest of the nodes. +The module starts a container for each node, having the first node a reference to the other nodes. E.g. `WithNodes("etcd-1", "etcd-2")`, `WithNodes("etcd-1", "etcd-2", "etcd-3")` and so on. + +The module creates a Docker network for the etcd cluster, and the nodes are connected to this network, so that they can communicate with each other through the network. + +#### WithClusterToken + +- Not available until the next release of testcontainers-go :material-tag: main + +Sets the cluster token for the etcd cluster. The cluster token is used to identify the etcd cluster. The default value is `mys3cr3ttok3n`. +The etcd container holds a reference to the cluster token, so you can use it with e.g. `ctr.ClusterToken`. + +### Container Methods + +- Not available until the next release of testcontainers-go :material-tag: main + +The etcd container exposes the following methods: + +#### ClientEndpoint + +- Not available until the next release of testcontainers-go :material-tag: main + +Returns the client endpoint for the etcd container and an error, if any. In the case of a cluster, it returns the client endpoint for the first node. + +#### PeerEndpoint + +- Not available until the next release of testcontainers-go :material-tag: main + +Returns the peer endpoint for the etcd container and an error, if any. In the case of a cluster, it returns the peer endpoint for the first node. diff --git a/mkdocs.yml b/mkdocs.yml index f5dfafebdd..824f5091e1 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -78,6 +78,7 @@ nav: - modules/dolt.md - modules/dynamodb.md - modules/elasticsearch.md + - modules/etcd.md - modules/gcloud.md - modules/grafana-lgtm.md - modules/inbucket.md diff --git a/modules/etcd/Makefile b/modules/etcd/Makefile new file mode 100644 index 0000000000..7531baef98 --- /dev/null +++ b/modules/etcd/Makefile @@ -0,0 +1,5 @@ +include ../../commons-test.mk + +.PHONY: test +test: + $(MAKE) test-etcd diff --git a/modules/etcd/cmd_test.go b/modules/etcd/cmd_test.go new file mode 100644 index 0000000000..918c68dc84 --- /dev/null +++ b/modules/etcd/cmd_test.go @@ -0,0 +1,108 @@ +package etcd + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_configureCMD(t *testing.T) { + t.Run("default", func(t *testing.T) { + got := configureCMD(options{}) + want := []string{"etcd", "--name=default"} + require.Equal(t, want, got) + }) + + t.Run("with-node", func(t *testing.T) { + got := configureCMD(options{ + nodeNames: []string{"node1"}, + }) + want := []string{ + "etcd", + "--name=node1", + "--initial-advertise-peer-urls=http://node1:2380", + "--advertise-client-urls=http://node1:2379", + "--listen-peer-urls=http://0.0.0.0:2380", + "--listen-client-urls=http://0.0.0.0:2379", + "--initial-cluster-state=new", + "--initial-cluster=node1=http://node1:2380", + } + require.Equal(t, want, got) + }) + + t.Run("with-node-datadir", func(t *testing.T) { + got := configureCMD(options{ + nodeNames: []string{"node1"}, + mountDataDir: true, + }) + want := []string{ + "etcd", + "--name=node1", + "--initial-advertise-peer-urls=http://node1:2380", + "--advertise-client-urls=http://node1:2379", + "--listen-peer-urls=http://0.0.0.0:2380", + "--listen-client-urls=http://0.0.0.0:2379", + "--initial-cluster-state=new", + "--initial-cluster=node1=http://node1:2380", + "--data-dir=/data.etcd", + } + require.Equal(t, want, got) + }) + + t.Run("with-node-datadir-additional-args", func(t *testing.T) { + got := configureCMD(options{ + nodeNames: []string{"node1"}, + mountDataDir: true, + additionalArgs: []string{"--auto-compaction-retention=1"}, + }) + want := []string{ + "etcd", + "--name=node1", + "--initial-advertise-peer-urls=http://node1:2380", + "--advertise-client-urls=http://node1:2379", + "--listen-peer-urls=http://0.0.0.0:2380", + "--listen-client-urls=http://0.0.0.0:2379", + "--initial-cluster-state=new", + "--initial-cluster=node1=http://node1:2380", + "--data-dir=/data.etcd", + "--auto-compaction-retention=1", + } + require.Equal(t, want, got) + }) + + t.Run("with-cluster", func(t *testing.T) { + got := configureCMD(options{ + nodeNames: []string{"node1", "node2"}, + }) + want := []string{ + "etcd", + "--name=node1", + "--initial-advertise-peer-urls=http://node1:2380", + "--advertise-client-urls=http://node1:2379", + "--listen-peer-urls=http://0.0.0.0:2380", + "--listen-client-urls=http://0.0.0.0:2379", + "--initial-cluster-state=new", + "--initial-cluster=node1=http://node1:2380,node2=http://node2:2380", + } + require.Equal(t, want, got) + }) + + t.Run("with-cluster-token", func(t *testing.T) { + got := configureCMD(options{ + nodeNames: []string{"node1", "node2"}, + clusterToken: "token", + }) + want := []string{ + "etcd", + "--name=node1", + "--initial-advertise-peer-urls=http://node1:2380", + "--advertise-client-urls=http://node1:2379", + "--listen-peer-urls=http://0.0.0.0:2380", + "--listen-client-urls=http://0.0.0.0:2379", + "--initial-cluster-state=new", + "--initial-cluster=node1=http://node1:2380,node2=http://node2:2380", + "--initial-cluster-token=token", + } + require.Equal(t, want, got) + }) +} diff --git a/modules/etcd/etcd.go b/modules/etcd/etcd.go new file mode 100644 index 0000000000..7ea78b4385 --- /dev/null +++ b/modules/etcd/etcd.go @@ -0,0 +1,272 @@ +package etcd + +import ( + "context" + "errors" + "fmt" + "strings" + + "github.com/testcontainers/testcontainers-go" + tcnetwork "github.com/testcontainers/testcontainers-go/network" +) + +const ( + clientPort = "2379" + peerPort = "2380" + dataDir = "/data.etcd" + defaultClusterToken = "mys3cr3ttok3n" + scheme = "http" +) + +// EtcdContainer represents the etcd container type used in the module. It can be used to create a single-node instance or a cluster. +// For the cluster, the first node creates the cluster and the other nodes join it as child nodes. +type EtcdContainer struct { + testcontainers.Container + // childNodes contains the child nodes of the current node, forming a cluster + childNodes []*EtcdContainer + opts options +} + +// Terminate terminates the etcd container, its child nodes, and the network in which the cluster is running +// to communicate between the nodes. +func (c *EtcdContainer) Terminate(ctx context.Context) error { + var errs []error + + // child nodes has no other children + for i, child := range c.childNodes { + if err := child.Terminate(ctx); err != nil { + errs = append(errs, fmt.Errorf("terminate child node(%d): %w", i, err)) + } + } + + if c.Container != nil { + if err := c.Container.Terminate(ctx); err != nil { + errs = append(errs, fmt.Errorf("terminate cluster node: %w", err)) + } + } + + // remove the cluster network if it was created, but only for the first node + // we could check if the current node is the first one (index 0), + // and/or check that there are no child nodes + if c.opts.clusterNetwork != nil && c.opts.currentNode == 0 { + if err := c.opts.clusterNetwork.Remove(ctx); err != nil { + errs = append(errs, fmt.Errorf("remove cluster network: %w", err)) + } + } + + return errors.Join(errs...) +} + +// Run creates an instance of the etcd container type +func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*EtcdContainer, error) { + req := testcontainers.ContainerRequest{ + Image: img, + Cmd: []string{}, + } + + genericContainerReq := testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + } + + settings := defaultOptions(&req) + for _, opt := range opts { + if apply, ok := opt.(Option); ok { + apply(&settings) + } + if err := opt.Customize(&genericContainerReq); err != nil { + return nil, err + } + } + + clusterOpts, err := configureCluster(ctx, &settings, opts) + if err != nil { + return nil, fmt.Errorf("configure cluster: %w", err) + } + + // configure CMD with the nodes + genericContainerReq.Cmd = configureCMD(settings) + + // Initialise the etcd container with the current settings. + // The cluster network, if needed, is already part of the settings, + // so the following error handling returns a partially initialised container, + // allowing the caller to clean up the resources with the Terminate method. + c := &EtcdContainer{opts: settings} + + if settings.clusterNetwork != nil { + // apply the network to the current node + err := tcnetwork.WithNetwork([]string{settings.nodeNames[settings.currentNode]}, settings.clusterNetwork)(&genericContainerReq) + if err != nil { + return c, fmt.Errorf("with network: %w", err) + } + } + + if c.Container, err = testcontainers.GenericContainer(ctx, genericContainerReq); err != nil { + return c, fmt.Errorf("generic container: %w", err) + } + + // only the first node creates the cluster + if settings.currentNode == 0 { + for i := 1; i < len(settings.nodeNames); i++ { + // move to the next node + childNode, err := Run(ctx, req.Image, append(clusterOpts, withCurrentNode(i))...) + if err != nil { + // return the parent cluster node and the error, so the caller can clean up. + return c, fmt.Errorf("run cluster node: %w", err) + } + + c.childNodes = append(c.childNodes, childNode) + } + } + + return c, nil +} + +// configureCluster configures the cluster settings, ensuring that the cluster is properly configured with the necessary network and options, +// avoiding duplicate application of options to be passed to the successive nodes. +func configureCluster(ctx context.Context, settings *options, opts []testcontainers.ContainerCustomizer) ([]testcontainers.ContainerCustomizer, error) { + var clusterOpts []testcontainers.ContainerCustomizer + if len(settings.nodeNames) == 0 { + return clusterOpts, nil + } + + // pass cluster options to each node + etcdOpts := []Option{} + for _, opt := range opts { + // if the option is of type Option, it won't be applied to the settings + // this prevents the same option from being applied multiple times (e.g. updating the current node) + if apply, ok := opt.(Option); ok { + etcdOpts = append(etcdOpts, apply) + } else { + clusterOpts = append(clusterOpts, opt) + } + } + + if settings.clusterNetwork == nil { // the first time the network is created + newNetwork, err := tcnetwork.New(ctx) + if err != nil { + return clusterOpts, fmt.Errorf("new network: %w", err) + } + + // set the network for the first node + settings.clusterNetwork = newNetwork + + clusterOpts = append(clusterOpts, withClusterNetwork(newNetwork)) // save the network for the next nodes + } + + // we finally need to re-apply all the etcd-specific options + clusterOpts = append(clusterOpts, withClusterOptions(etcdOpts)) + + return clusterOpts, nil +} + +// configureCMD configures the etcd command line arguments, based on the settings provided, +// in order to create a cluster or a single-node instance. +func configureCMD(settings options) []string { + cmds := []string{"etcd"} + + if len(settings.nodeNames) == 0 { + cmds = append(cmds, "--name=default") + } else { + clusterCmds := []string{ + "--name=" + settings.nodeNames[settings.currentNode], + "--initial-advertise-peer-urls=" + scheme + "://" + settings.nodeNames[settings.currentNode] + ":" + peerPort, + "--advertise-client-urls=" + scheme + "://" + settings.nodeNames[settings.currentNode] + ":" + clientPort, + "--listen-peer-urls=" + scheme + "://0.0.0.0:" + peerPort, + "--listen-client-urls=" + scheme + "://0.0.0.0:" + clientPort, + "--initial-cluster-state=new", + } + + clusterStateValues := make([]string, len(settings.nodeNames)) + for i, node := range settings.nodeNames { + clusterStateValues[i] = node + "=" + scheme + "://" + node + ":" + peerPort + } + clusterCmds = append(clusterCmds, "--initial-cluster="+strings.Join(clusterStateValues, ",")) + + if settings.clusterToken != "" { + clusterCmds = append(clusterCmds, "--initial-cluster-token="+settings.clusterToken) + } + + cmds = append(cmds, clusterCmds...) + } + + if settings.mountDataDir { + cmds = append(cmds, "--data-dir="+dataDir) + } + + cmds = append(cmds, settings.additionalArgs...) + + return cmds +} + +// ClientEndpoint returns the client endpoint for the etcd container, and an error if any. +// For a cluster, it returns the client endpoint of the first node. +func (c *EtcdContainer) ClientEndpoint(ctx context.Context) (string, error) { + host, err := c.Host(ctx) + if err != nil { + return "", err + } + + port, err := c.MappedPort(ctx, clientPort) + if err != nil { + return "", err + } + + return fmt.Sprintf("http://%s:%s", host, port.Port()), nil +} + +// ClientEndpoints returns the client endpoints for the etcd cluster. +func (c *EtcdContainer) ClientEndpoints(ctx context.Context) ([]string, error) { + endpoint, err := c.ClientEndpoint(ctx) + if err != nil { + return nil, err + } + + endpoints := []string{endpoint} + + for _, node := range c.childNodes { + endpoint, err := node.ClientEndpoint(ctx) + if err != nil { + return nil, err + } + endpoints = append(endpoints, endpoint) + } + + return endpoints, nil +} + +// PeerEndpoint returns the peer endpoint for the etcd container, and an error if any. +// For a cluster, it returns the peer endpoint of the first node. +func (c *EtcdContainer) PeerEndpoint(ctx context.Context) (string, error) { + host, err := c.Host(ctx) + if err != nil { + return "", err + } + + port, err := c.MappedPort(ctx, peerPort) + if err != nil { + return "", err + } + + return fmt.Sprintf("http://%s:%s", host, port.Port()), nil +} + +// PeerEndpoints returns the peer endpoints for the etcd cluster. +func (c *EtcdContainer) PeerEndpoints(ctx context.Context) ([]string, error) { + endpoint, err := c.PeerEndpoint(ctx) + if err != nil { + return nil, err + } + + endpoints := []string{endpoint} + + for _, node := range c.childNodes { + endpoint, err := node.PeerEndpoint(ctx) + if err != nil { + return nil, err + } + endpoints = append(endpoints, endpoint) + } + + return endpoints, nil +} diff --git a/modules/etcd/etcd_test.go b/modules/etcd/etcd_test.go new file mode 100644 index 0000000000..5095ba8429 --- /dev/null +++ b/modules/etcd/etcd_test.go @@ -0,0 +1,60 @@ +package etcd_test + +import ( + "context" + "io" + "testing" + "time" + + "github.com/stretchr/testify/require" + clientv3 "go.etcd.io/etcd/client/v3" + + "github.com/testcontainers/testcontainers-go" + tcexec "github.com/testcontainers/testcontainers-go/exec" + "github.com/testcontainers/testcontainers-go/modules/etcd" +) + +func TestRun(t *testing.T) { + ctx := context.Background() + + ctr, err := etcd.Run(ctx, "gcr.io/etcd-development/etcd:v3.5.14") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + c, r, err := ctr.Exec(ctx, []string{"etcdctl", "member", "list"}, tcexec.Multiplexed()) + require.NoError(t, err) + require.Equal(t, 0, c) + + output, err := io.ReadAll(r) + require.NoError(t, err) + require.Contains(t, string(output), "default") +} + +func TestRun_PutGet(t *testing.T) { + ctx := context.Background() + + ctr, err := etcd.Run(ctx, "gcr.io/etcd-development/etcd:v3.5.14", etcd.WithNodes("etcd-1", "etcd-2", "etcd-3")) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + clientEndpoints, err := ctr.ClientEndpoints(ctx) + require.NoError(t, err) + + cli, err := clientv3.New(clientv3.Config{ + Endpoints: clientEndpoints, + DialTimeout: 5 * time.Second, + }) + require.NoError(t, err) + defer cli.Close() + + ctx, cancel := context.WithTimeout(ctx, 2*time.Second) + defer cancel() + _, err = cli.Put(ctx, "sample_key", "sample_value") + require.NoError(t, err) + + resp, err := cli.Get(ctx, "sample_key") + require.NoError(t, err) + + require.Len(t, resp.Kvs, 1) + require.Equal(t, "sample_value", string(resp.Kvs[0].Value)) +} diff --git a/modules/etcd/etcd_unit_test.go b/modules/etcd/etcd_unit_test.go new file mode 100644 index 0000000000..d32b9519f7 --- /dev/null +++ b/modules/etcd/etcd_unit_test.go @@ -0,0 +1,113 @@ +package etcd + +import ( + "context" + "fmt" + "io" + "testing" + + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/errdefs" + "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go" + tcexec "github.com/testcontainers/testcontainers-go/exec" + tcnetwork "github.com/testcontainers/testcontainers-go/network" +) + +func TestRunCluster1Node(t *testing.T) { + ctx := context.Background() + + ctr, err := Run(ctx, "gcr.io/etcd-development/etcd:v3.5.14") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + // the topology has only one node with no children + require.Empty(t, ctr.childNodes) + require.Equal(t, defaultClusterToken, ctr.opts.clusterToken) +} + +func TestRunClusterMultipleNodes(t *testing.T) { + t.Run("2-nodes", testCluster(t, "etcd-1", "etcd-2")) + t.Run("3-nodes", testCluster(t, "etcd-1", "etcd-2", "etcd-3")) +} + +func TestTerminate(t *testing.T) { + ctx := context.Background() + + ctr, err := Run(ctx, "gcr.io/etcd-development/etcd:v3.5.14", WithNodes("etcd-1", "etcd-2", "etcd-3")) + require.NoError(t, err) + require.NoError(t, ctr.Terminate(ctx)) + + // verify that the network and the containers does no longer exist + + cli, err := testcontainers.NewDockerClientWithOpts(context.Background()) + require.NoError(t, err) + defer cli.Close() + + _, err = cli.ContainerInspect(context.Background(), ctr.GetContainerID()) + require.True(t, errdefs.IsNotFound(err)) + + for _, child := range ctr.childNodes { + _, err := cli.ContainerInspect(context.Background(), child.GetContainerID()) + require.True(t, errdefs.IsNotFound(err)) + } + + _, err = cli.NetworkInspect(context.Background(), ctr.opts.clusterNetwork.ID, network.InspectOptions{}) + require.True(t, errdefs.IsNotFound(err)) +} + +func TestTerminate_partiallyInitialised(t *testing.T) { + newNetwork, err := tcnetwork.New(context.Background()) + require.NoError(t, err) + + ctr := &EtcdContainer{ + opts: options{ + clusterNetwork: newNetwork, + }, + } + + require.NoError(t, ctr.Terminate(context.Background())) + + cli, err := testcontainers.NewDockerClientWithOpts(context.Background()) + require.NoError(t, err) + defer cli.Close() + + _, err = cli.NetworkInspect(context.Background(), ctr.opts.clusterNetwork.ID, network.InspectOptions{}) + require.True(t, errdefs.IsNotFound(err)) +} + +// testCluster is a helper function to test the creation of an etcd cluster with the specified nodes. +func testCluster(t *testing.T, node1 string, node2 string, nodes ...string) func(t *testing.T) { + t.Helper() + + return func(tt *testing.T) { + const clusterToken string = "My-cluster-t0k3n" + + ctx := context.Background() + + ctr, err := Run(ctx, "gcr.io/etcd-development/etcd:v3.5.14", WithNodes(node1, node2, nodes...), WithClusterToken(clusterToken)) + testcontainers.CleanupContainer(t, ctr) + require.NoError(tt, err) + + require.Equal(tt, clusterToken, ctr.opts.clusterToken) + + // the topology has one parent node, one child node and optionally more child nodes + // depending on the number of nodes specified + require.Len(tt, ctr.childNodes, 1+len(nodes)) + + for i, node := range ctr.childNodes { + require.Empty(t, node.childNodes) // child nodes has no children + + c, r, err := node.Exec(ctx, []string{"etcdctl", "member", "list"}, tcexec.Multiplexed()) + require.NoError(tt, err) + + output, err := io.ReadAll(r) + require.NoError(t, err) + require.Contains(t, string(output), fmt.Sprintf("etcd-%d", i+1)) + + require.Zero(tt, c) + require.Equal(tt, clusterToken, node.opts.clusterToken) + } + } +} diff --git a/modules/etcd/examples_test.go b/modules/etcd/examples_test.go new file mode 100644 index 0000000000..950d5ecd05 --- /dev/null +++ b/modules/etcd/examples_test.go @@ -0,0 +1,97 @@ +package etcd_test + +import ( + "context" + "fmt" + "log" + "time" + + clientv3 "go.etcd.io/etcd/client/v3" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/etcd" +) + +func ExampleRun() { + // runetcdContainer { + ctx := context.Background() + + etcdContainer, err := etcd.Run(ctx, "gcr.io/etcd-development/etcd:v3.5.14") + defer func() { + if err := testcontainers.TerminateContainer(etcdContainer); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + // } + + state, err := etcdContainer.State(ctx) + if err != nil { + log.Printf("failed to get container state: %s", err) + return + } + + fmt.Println(state.Running) + + // Output: + // true +} + +func ExampleRun_cluster() { + ctx := context.Background() + + ctr, err := etcd.Run(ctx, "gcr.io/etcd-development/etcd:v3.5.14", etcd.WithNodes("etcd-1", "etcd-2", "etcd-3")) + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + defer func() { + if err := testcontainers.TerminateContainer(ctr); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() + + clientEndpoints, err := ctr.ClientEndpoints(ctx) + if err != nil { + log.Printf("failed to get client endpoints: %s", err) + return + } + + // we have 3 nodes, 1 cluster node and 2 child nodes + fmt.Println(len(clientEndpoints)) + + cli, err := clientv3.New(clientv3.Config{ + Endpoints: clientEndpoints, + DialTimeout: 5 * time.Second, + }) + if err != nil { + log.Printf("failed to create etcd client: %s", err) + return + } + defer cli.Close() + + ctx, cancel := context.WithTimeout(ctx, 2*time.Second) + defer cancel() + _, err = cli.Put(ctx, "sample_key", "sample_value") + if err != nil { + log.Printf("failed to put key: %s", err) + return + } + + resp, err := cli.Get(ctx, "sample_key") + if err != nil { + log.Printf("failed to get key: %s", err) + return + } + + fmt.Println(len(resp.Kvs)) + fmt.Println(string(resp.Kvs[0].Value)) + + // Output: + // 3 + // 1 + // sample_value +} diff --git a/modules/etcd/go.mod b/modules/etcd/go.mod new file mode 100644 index 0000000000..fb5e7f39d8 --- /dev/null +++ b/modules/etcd/go.mod @@ -0,0 +1,75 @@ +module github.com/testcontainers/testcontainers-go/modules/etcd + +go 1.22 + +require ( + github.com/docker/docker v27.1.1+incompatible + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.33.0 + go.etcd.io/etcd/client/v3 v3.5.16 +) + +require ( + dario.cat/mergo v1.0.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/containerd/containerd v1.7.18 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/coreos/go-semver v0.3.0 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.etcd.io/etcd/api/v3 v3.5.16 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.16 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/zap v1.17.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + google.golang.org/grpc v1.64.1 // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/etcd/go.sum b/modules/etcd/go.sum new file mode 100644 index 0000000000..3de88cadb9 --- /dev/null +++ b/modules/etcd/go.sum @@ -0,0 +1,216 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +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/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= +github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +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.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +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.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.etcd.io/etcd/api/v3 v3.5.16 h1:WvmyJVbjWqK4R1E+B12RRHz3bRGy9XVfh++MgbN+6n0= +go.etcd.io/etcd/api/v3 v3.5.16/go.mod h1:1P4SlIP/VwkDmGo3OlOD7faPeP8KDIFhqvciH5EfN28= +go.etcd.io/etcd/client/pkg/v3 v3.5.16 h1:ZgY48uH6UvB+/7R9Yf4x574uCO3jIx0TRDyetSfId3Q= +go.etcd.io/etcd/client/pkg/v3 v3.5.16/go.mod h1:V8acl8pcEK0Y2g19YlOV9m9ssUe6MgiDSobSoaBAM0E= +go.etcd.io/etcd/client/v3 v3.5.16 h1:sSmVYOAHeC9doqi0gv7v86oY/BTld0SEFGaxsU9eRhE= +go.etcd.io/etcd/client/v3 v3.5.16/go.mod h1:X+rExSGkyqxvu276cr2OwPLBaeqFu1cIl4vmRjAD/50= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +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/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.2.8/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/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/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/modules/etcd/options.go b/modules/etcd/options.go new file mode 100644 index 0000000000..1359e4a3b4 --- /dev/null +++ b/modules/etcd/options.go @@ -0,0 +1,107 @@ +package etcd + +import ( + "context" + "fmt" + + "github.com/testcontainers/testcontainers-go" + tcexec "github.com/testcontainers/testcontainers-go/exec" +) + +type options struct { + currentNode int + clusterNetwork *testcontainers.DockerNetwork + nodeNames []string + clusterToken string + additionalArgs []string + mountDataDir bool // flag needed to avoid extra calculations with the lifecycle hooks + containerRequest *testcontainers.ContainerRequest +} + +func defaultOptions(req *testcontainers.ContainerRequest) options { + return options{ + clusterToken: defaultClusterToken, + containerRequest: req, + } +} + +// Compiler check to ensure that Option implements the testcontainers.ContainerCustomizer interface. +var _ testcontainers.ContainerCustomizer = (Option)(nil) + +// Option is an option for the Etcd container. +type Option func(*options) + +// Customize is a NOOP. It's defined to satisfy the testcontainers.ContainerCustomizer interface. +func (o Option) Customize(*testcontainers.GenericContainerRequest) error { + // NOOP to satisfy interface. + return nil +} + +// WithAdditionalArgs is an option to pass additional arguments to the etcd container. +// They will be appended last to the command line. +func WithAdditionalArgs(args ...string) Option { + return func(o *options) { + o.additionalArgs = args + } +} + +// WithDataDir is an option to mount the data directory, which is located at /data.etcd. +// The option will add a lifecycle hook to the container to change the permissions of the data directory. +func WithDataDir() Option { + return func(o *options) { + // Avoid extra calculations with the lifecycle hooks + o.mountDataDir = true + + o.containerRequest.LifecycleHooks = append(o.containerRequest.LifecycleHooks, testcontainers.ContainerLifecycleHooks{ + PostStarts: []testcontainers.ContainerHook{ + func(ctx context.Context, c testcontainers.Container) error { + _, _, err := c.Exec(ctx, []string{"chmod", "o+rwx", "-R", dataDir}, tcexec.Multiplexed()) + if err != nil { + return fmt.Errorf("chmod etcd data dir: %w", err) + } + + return nil + }, + }, + }) + } +} + +// WithNodes is an option to set the nodes of the etcd cluster. +// It should be used to create a cluster with more than one node. +func WithNodes(node1 string, node2 string, nodes ...string) Option { + return func(o *options) { + o.nodeNames = append([]string{node1, node2}, nodes...) + } +} + +// withCurrentNode is an option to set the current node index. +// It's an internal option and should not be used by the user. +func withCurrentNode(i int) Option { + return func(o *options) { + o.currentNode = i + } +} + +// withClusterNetwork is an option to set the cluster network. +// It's an internal option and should not be used by the user. +func withClusterNetwork(n *testcontainers.DockerNetwork) Option { + return func(o *options) { + o.clusterNetwork = n + } +} + +// WithClusterToken is an option to set the cluster token. +func WithClusterToken(token string) Option { + return func(o *options) { + o.clusterToken = token + } +} + +func withClusterOptions(opts []Option) Option { + return func(o *options) { + for _, opt := range opts { + opt(o) + } + } +} diff --git a/sonar-project.properties b/sonar-project.properties index 8c7946ed8e..1b5cb92513 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -18,4 +18,4 @@ sonar.test.inclusions=**/*_test.go sonar.test.exclusions=**/vendor/** sonar.go.coverage.reportPaths=**/coverage.out -sonar.go.tests.reportPaths=TEST-unit.xml,examples/nginx/TEST-unit.xml,examples/toxiproxy/TEST-unit.xml,modulegen/TEST-unit.xml,modules/artemis/TEST-unit.xml,modules/azurite/TEST-unit.xml,modules/cassandra/TEST-unit.xml,modules/chroma/TEST-unit.xml,modules/clickhouse/TEST-unit.xml,modules/cockroachdb/TEST-unit.xml,modules/compose/TEST-unit.xml,modules/consul/TEST-unit.xml,modules/couchbase/TEST-unit.xml,modules/databend/TEST-unit.xml,modules/dolt/TEST-unit.xml,modules/dynamodb/TEST-unit.xml,modules/elasticsearch/TEST-unit.xml,modules/gcloud/TEST-unit.xml,modules/grafana-lgtm/TEST-unit.xml,modules/inbucket/TEST-unit.xml,modules/influxdb/TEST-unit.xml,modules/k3s/TEST-unit.xml,modules/k6/TEST-unit.xml,modules/kafka/TEST-unit.xml,modules/localstack/TEST-unit.xml,modules/mariadb/TEST-unit.xml,modules/milvus/TEST-unit.xml,modules/minio/TEST-unit.xml,modules/mockserver/TEST-unit.xml,modules/mongodb/TEST-unit.xml,modules/mssql/TEST-unit.xml,modules/mysql/TEST-unit.xml,modules/nats/TEST-unit.xml,modules/neo4j/TEST-unit.xml,modules/ollama/TEST-unit.xml,modules/openfga/TEST-unit.xml,modules/openldap/TEST-unit.xml,modules/opensearch/TEST-unit.xml,modules/postgres/TEST-unit.xml,modules/pulsar/TEST-unit.xml,modules/qdrant/TEST-unit.xml,modules/rabbitmq/TEST-unit.xml,modules/redis/TEST-unit.xml,modules/redpanda/TEST-unit.xml,modules/registry/TEST-unit.xml,modules/surrealdb/TEST-unit.xml,modules/valkey/TEST-unit.xml,modules/vault/TEST-unit.xml,modules/vearch/TEST-unit.xml,modules/weaviate/TEST-unit.xml +sonar.go.tests.reportPaths=TEST-unit.xml,examples/nginx/TEST-unit.xml,examples/toxiproxy/TEST-unit.xml,modulegen/TEST-unit.xml,modules/artemis/TEST-unit.xml,modules/azurite/TEST-unit.xml,modules/cassandra/TEST-unit.xml,modules/chroma/TEST-unit.xml,modules/clickhouse/TEST-unit.xml,modules/cockroachdb/TEST-unit.xml,modules/compose/TEST-unit.xml,modules/consul/TEST-unit.xml,modules/couchbase/TEST-unit.xml,modules/databend/TEST-unit.xml,modules/dolt/TEST-unit.xml,modules/dynamodb/TEST-unit.xml,modules/elasticsearch/TEST-unit.xml,modules/etcd/TEST-unit.xml,modules/gcloud/TEST-unit.xml,modules/grafana-lgtm/TEST-unit.xml,modules/inbucket/TEST-unit.xml,modules/influxdb/TEST-unit.xml,modules/k3s/TEST-unit.xml,modules/k6/TEST-unit.xml,modules/kafka/TEST-unit.xml,modules/localstack/TEST-unit.xml,modules/mariadb/TEST-unit.xml,modules/milvus/TEST-unit.xml,modules/minio/TEST-unit.xml,modules/mockserver/TEST-unit.xml,modules/mongodb/TEST-unit.xml,modules/mssql/TEST-unit.xml,modules/mysql/TEST-unit.xml,modules/nats/TEST-unit.xml,modules/neo4j/TEST-unit.xml,modules/ollama/TEST-unit.xml,modules/openfga/TEST-unit.xml,modules/openldap/TEST-unit.xml,modules/opensearch/TEST-unit.xml,modules/postgres/TEST-unit.xml,modules/pulsar/TEST-unit.xml,modules/qdrant/TEST-unit.xml,modules/rabbitmq/TEST-unit.xml,modules/redis/TEST-unit.xml,modules/redpanda/TEST-unit.xml,modules/registry/TEST-unit.xml,modules/surrealdb/TEST-unit.xml,modules/valkey/TEST-unit.xml,modules/vault/TEST-unit.xml,modules/vearch/TEST-unit.xml,modules/weaviate/TEST-unit.xml From 7c536674f43c91a4dab859aa1aa2e8c23c9f17ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 13:39:10 +0200 Subject: [PATCH 083/126] chore(deps): bump release-drafter/release-drafter from 5.25.0 to 6.0.0 (#2805) Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.25.0 to 6.0.0. - [Release notes](https://github.com/release-drafter/release-drafter/releases) - [Commits](https://github.com/release-drafter/release-drafter/compare/09c613e259eb8d4e7c81c2cb00618eb5fc4575a7...3f0f87098bd6b5c5b9a36d49c41d998ea58f9348) --- updated-dependencies: - dependency-name: release-drafter/release-drafter dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 29c2b72ee0..7bab45a5aa 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -16,6 +16,6 @@ jobs: pull-requests: write # for release-drafter/release-drafter to add label to PR runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@09c613e259eb8d4e7c81c2cb00618eb5fc4575a7 # v5.19.0 + - uses: release-drafter/release-drafter@3f0f87098bd6b5c5b9a36d49c41d998ea58f9348 # v5.19.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From e41374cd5c9aaa6dfb22d78e529216ef7c3edcd3 Mon Sep 17 00:00:00 2001 From: Ashutosh Dubey Date: Sun, 6 Oct 2024 02:04:53 +0530 Subject: [PATCH 084/126] feat: add require for critical checks (#2812) * add require for critial checks * feat: change assert to require for critical check --------- Co-authored-by: Apple --- container_test.go | 2 +- docker_test.go | 6 +++--- internal/core/docker_host_test.go | 14 +++++++------- internal/core/docker_rootless_test.go | 4 ++-- internal/core/images_test.go | 2 +- lifecycle_test.go | 2 +- modulegen/main_test.go | 6 +++++- modulegen/mkdocs_test.go | 6 +++--- modules/compose/compose_api_test.go | 2 +- modules/localstack/v1/s3_test.go | 8 ++++---- modules/localstack/v2/s3_test.go | 8 ++++---- 11 files changed, 32 insertions(+), 28 deletions(-) diff --git a/container_test.go b/container_test.go index 0cca97e6f5..562eb038a4 100644 --- a/container_test.go +++ b/container_test.go @@ -320,7 +320,7 @@ func TestCustomLabelsImage(t *testing.T) { ctr, err := testcontainers.GenericContainer(ctx, req) require.NoError(t, err) - t.Cleanup(func() { assert.NoError(t, ctr.Terminate(ctx)) }) + t.Cleanup(func() { require.NoError(t, ctr.Terminate(ctx)) }) ctrJSON, err := ctr.Inspect(ctx) require.NoError(t, err) diff --git a/docker_test.go b/docker_test.go index bbbe519c28..1a6f406c85 100644 --- a/docker_test.go +++ b/docker_test.go @@ -307,7 +307,7 @@ func TestContainerStateAfterTermination(t *testing.T) { state, err := nginx.State(ctx) require.Error(t, err, "expected error from container inspect.") - assert.Nil(t, state, "expected nil container inspect.") + require.Nil(t, state, "expected nil container inspect.") }) t.Run("Nil State after termination if raw as already set", func(t *testing.T) { @@ -1339,7 +1339,7 @@ func TestContainerInspect_RawInspectIsCleanedOnStop(t *testing.T) { inspect, err := ctr.Inspect(context.Background()) require.NoError(t, err) - assert.NotEmpty(t, inspect.ID) + require.NotEmpty(t, inspect.ID) require.NoError(t, ctr.Stop(context.Background(), nil)) } @@ -1698,7 +1698,7 @@ func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { if err != nil { t.Fatal(err) } - assert.Empty(t, fileContentFromContainer) + require.Empty(t, fileContentFromContainer) } func TestDockerContainerResources(t *testing.T) { diff --git a/internal/core/docker_host_test.go b/internal/core/docker_host_test.go index eceee573fc..5454ab5f95 100644 --- a/internal/core/docker_host_test.go +++ b/internal/core/docker_host_test.go @@ -192,7 +192,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := testcontainersHostFromProperties(context.Background()) require.ErrorIs(t, err, ErrTestcontainersHostNotSetInProperties) - assert.Empty(t, socket) + require.Empty(t, socket) }) t.Run("DOCKER_HOST is set", func(t *testing.T) { @@ -212,7 +212,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := dockerHostFromEnv(context.Background()) require.ErrorIs(t, err, ErrDockerHostNotSet) - assert.Empty(t, socket) + require.Empty(t, socket) }) t.Run("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE is set", func(t *testing.T) { @@ -236,7 +236,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := dockerSocketOverridePath() require.ErrorIs(t, err, ErrDockerSocketOverrideNotSet) - assert.Empty(t, socket) + require.Empty(t, socket) }) t.Run("Context sets the Docker socket", func(t *testing.T) { @@ -252,7 +252,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := dockerHostFromContext(context.WithValue(ctx, DockerHostContextKey, "path-to-docker-sock")) require.Error(t, err) - assert.Empty(t, socket) + require.Empty(t, socket) }) t.Run("Context sets a malformed schema for the Docker socket", func(t *testing.T) { @@ -260,7 +260,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := dockerHostFromContext(context.WithValue(ctx, DockerHostContextKey, "http://example.com/docker.sock")) require.ErrorIs(t, err, ErrNoUnixSchema) - assert.Empty(t, socket) + require.Empty(t, socket) }) t.Run("Docker socket exists", func(t *testing.T) { @@ -289,7 +289,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := dockerHostFromProperties(context.Background()) require.ErrorIs(t, err, ErrDockerSocketNotSetInProperties) - assert.Empty(t, socket) + require.Empty(t, socket) }) t.Run("Docker socket does not exist", func(t *testing.T) { @@ -297,7 +297,7 @@ func TestExtractDockerHost(t *testing.T) { socket, err := dockerSocketPath(context.Background()) require.ErrorIs(t, err, ErrSocketNotFoundInPath) - assert.Empty(t, socket) + require.Empty(t, socket) }) }) } diff --git a/internal/core/docker_rootless_test.go b/internal/core/docker_rootless_test.go index 7897f35783..687aa24707 100644 --- a/internal/core/docker_rootless_test.go +++ b/internal/core/docker_rootless_test.go @@ -70,7 +70,7 @@ func TestRootlessDockerSocketPathNotSupportedOnWindows(t *testing.T) { t.Setenv("GOOS", "windows") socketPath, err := rootlessDockerSocketPath(context.Background()) require.ErrorIs(t, err, ErrRootlessDockerNotSupportedWindows) - assert.Empty(t, socketPath) + require.Empty(t, socketPath) } func TestRootlessDockerSocketPath(t *testing.T) { @@ -179,7 +179,7 @@ func TestRootlessDockerSocketPath(t *testing.T) { socketPath, err := rootlessDockerSocketPath(context.Background()) require.ErrorIs(t, err, ErrRootlessDockerNotFoundXDGRuntimeDir) - assert.Empty(t, socketPath) + require.Empty(t, socketPath) }) } diff --git a/internal/core/images_test.go b/internal/core/images_test.go index 760a5cb857..509a117c80 100644 --- a/internal/core/images_test.go +++ b/internal/core/images_test.go @@ -67,7 +67,7 @@ func TestExtractImagesFromDockerfile(t *testing.T) { images, err := ExtractImagesFromDockerfile(tt.dockerfile, tt.buildArgs) if tt.expectedError { require.Error(t, err) - assert.Empty(t, images) + require.Empty(t, images) } else { require.NoError(t, err) assert.Equal(t, tt.expected, images) diff --git a/lifecycle_test.go b/lifecycle_test.go index 66c4ad8a8a..b1cff8dad8 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -281,7 +281,7 @@ func TestPreCreateModifierHook(t *testing.T) { // assertions - assert.Empty( + require.Empty( t, inputNetworkingConfig.EndpointsConfig[networkName].Aliases, "Networking config's aliases should be empty", diff --git a/modulegen/main_test.go b/modulegen/main_test.go index 322cb25920..10e4b32131 100644 --- a/modulegen/main_test.go +++ b/modulegen/main_test.go @@ -148,7 +148,11 @@ func TestModule_Validate(outer *testing.T) { for _, test := range tests { outer.Run(test.name, func(t *testing.T) { - assert.Equal(t, test.expectedErr, test.module.Validate()) + if test.expectedErr != nil { + require.EqualError(t, test.module.Validate(), test.expectedErr.Error()) + } else { + require.NoError(t, test.module.Validate()) + } }) } } diff --git a/modulegen/mkdocs_test.go b/modulegen/mkdocs_test.go index 5fcf7c93ba..a43afcc388 100644 --- a/modulegen/mkdocs_test.go +++ b/modulegen/mkdocs_test.go @@ -51,9 +51,9 @@ func TestReadMkDocsConfig(t *testing.T) { // nav bar nav := config.Nav assert.Equal(t, "index.md", nav[0].Home) - assert.NotEmpty(t, nav[2].Features) - assert.NotEmpty(t, nav[3].Modules) - assert.NotEmpty(t, nav[4].Examples) + require.NotEmpty(t, nav[2].Features) + require.NotEmpty(t, nav[3].Modules) + require.NotEmpty(t, nav[4].Examples) } func TestNavItems(t *testing.T) { diff --git a/modules/compose/compose_api_test.go b/modules/compose/compose_api_test.go index 7879dabfa9..e40129ede8 100644 --- a/modules/compose/compose_api_test.go +++ b/modules/compose/compose_api_test.go @@ -641,7 +641,7 @@ func TestDockerComposeAPIVolumesDeletedOnDown(t *testing.T) { volumeList, err := compose.dockerClient.VolumeList(ctx, volume.ListOptions{Filters: volumeListFilters}) require.NoError(t, err, "compose.dockerClient.VolumeList()") - assert.Empty(t, volumeList.Volumes, "Volumes are not cleaned up") + require.Empty(t, volumeList.Volumes, "Volumes are not cleaned up") } func TestDockerComposeAPIWithBuild(t *testing.T) { diff --git a/modules/localstack/v1/s3_test.go b/modules/localstack/v1/s3_test.go index 87eba46080..aa4dea378e 100644 --- a/modules/localstack/v1/s3_test.go +++ b/modules/localstack/v1/s3_test.go @@ -82,7 +82,7 @@ func TestS3(t *testing.T) { Bucket: aws.String(bucketName), }) require.NoError(t, err) - assert.NotNil(t, outputBucket) + require.NotNil(t, outputBucket) // put object s3Key1 := "key1" @@ -96,12 +96,12 @@ func TestS3(t *testing.T) { ContentDisposition: aws.String("attachment"), }) require.NoError(t, err) - assert.NotNil(t, outputObject) + require.NotNil(t, outputObject) t.Run("List Buckets", func(t *testing.T) { output, err := s3API.ListBuckets(nil) require.NoError(t, err) - assert.NotNil(t, output) + require.NotNil(t, output) buckets := output.Buckets assert.Len(t, buckets, 1) @@ -113,7 +113,7 @@ func TestS3(t *testing.T) { Bucket: aws.String(bucketName), }) require.NoError(t, err) - assert.NotNil(t, output) + require.NotNil(t, output) objects := output.Contents diff --git a/modules/localstack/v2/s3_test.go b/modules/localstack/v2/s3_test.go index 477549fb9c..09380a7665 100644 --- a/modules/localstack/v2/s3_test.go +++ b/modules/localstack/v2/s3_test.go @@ -88,7 +88,7 @@ func TestS3(t *testing.T) { Bucket: aws.String(bucketName), }) require.NoError(t, err) - assert.NotNil(t, outputBucket) + require.NotNil(t, outputBucket) // put object s3Key1 := "key1" @@ -102,12 +102,12 @@ func TestS3(t *testing.T) { ContentDisposition: aws.String("attachment"), }) require.NoError(t, err) - assert.NotNil(t, outputObject) + require.NotNil(t, outputObject) t.Run("List Buckets", func(t *testing.T) { output, err := s3Client.ListBuckets(ctx, &s3.ListBucketsInput{}) require.NoError(t, err) - assert.NotNil(t, output) + require.NotNil(t, output) buckets := output.Buckets assert.Len(t, buckets, 1) @@ -119,7 +119,7 @@ func TestS3(t *testing.T) { Bucket: aws.String(bucketName), }) require.NoError(t, err) - assert.NotNil(t, output) + require.NotNil(t, output) objects := output.Contents From 37cc44b1c25154aa15ba91f8a444566098c2a248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 9 Oct 2024 14:21:47 +0200 Subject: [PATCH 085/126] chore: bump ryuk to latest release (#2818) --- internal/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/config/config.go b/internal/config/config.go index a172fa3a16..35c9918e82 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -11,7 +11,7 @@ import ( "github.com/magiconair/properties" ) -const ReaperDefaultImage = "testcontainers/ryuk:0.9.0" +const ReaperDefaultImage = "testcontainers/ryuk:0.10.0" var ( tcConfig Config From cc71645e576a0afb003123eb3e03d7955f342792 Mon Sep 17 00:00:00 2001 From: Joel Lau Date: Mon, 14 Oct 2024 23:56:47 +0800 Subject: [PATCH 086/126] chore: replace 'assert' with 'require' for critical checks (#2824) --- from_dockerfile_test.go | 7 +++---- modules/etcd/etcd_test.go | 2 +- modules/vault/vault_test.go | 2 +- options_test.go | 8 ++++---- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/from_dockerfile_test.go b/from_dockerfile_test.go index f6f7512ae3..854492fbfd 100644 --- a/from_dockerfile_test.go +++ b/from_dockerfile_test.go @@ -12,7 +12,6 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/image" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -38,7 +37,7 @@ func TestBuildImageFromDockerfile(t *testing.T) { // } }) require.NoError(t, err) - assert.Equal(t, "test-repo:test-tag", tag) + require.Equal(t, "test-repo:test-tag", tag) _, _, err = cli.ImageInspectWithRaw(ctx, tag) require.NoError(t, err) @@ -73,7 +72,7 @@ func TestBuildImageFromDockerfile_NoRepo(t *testing.T) { }, }) require.NoError(t, err) - assert.True(t, strings.HasPrefix(tag, "test-repo:")) + require.True(t, strings.HasPrefix(tag, "test-repo:")) _, _, err = cli.ImageInspectWithRaw(ctx, tag) require.NoError(t, err) @@ -130,7 +129,7 @@ func TestBuildImageFromDockerfile_NoTag(t *testing.T) { }, }) require.NoError(t, err) - assert.True(t, strings.HasSuffix(tag, ":test-tag")) + require.True(t, strings.HasSuffix(tag, ":test-tag")) _, _, err = cli.ImageInspectWithRaw(ctx, tag) require.NoError(t, err) diff --git a/modules/etcd/etcd_test.go b/modules/etcd/etcd_test.go index 5095ba8429..046e277cac 100644 --- a/modules/etcd/etcd_test.go +++ b/modules/etcd/etcd_test.go @@ -23,7 +23,7 @@ func TestRun(t *testing.T) { c, r, err := ctr.Exec(ctx, []string{"etcdctl", "member", "list"}, tcexec.Multiplexed()) require.NoError(t, err) - require.Equal(t, 0, c) + require.Zero(t, c) output, err := io.ReadAll(r) require.NoError(t, err) diff --git a/modules/vault/vault_test.go b/modules/vault/vault_test.go index c55f792c2c..22b87930bb 100644 --- a/modules/vault/vault_test.go +++ b/modules/vault/vault_test.go @@ -50,7 +50,7 @@ func TestVault(t *testing.T) { exec, reader, err := vaultContainer.Exec(ctx, []string{"vault", "kv", "get", "-format=json", "secret/test1"}) // } require.NoError(t, err) - assert.Equal(t, 0, exec) + require.Zero(t, exec) bytes, err := io.ReadAll(reader) require.NoError(t, err) diff --git a/options_test.go b/options_test.go index c8a67b0b06..dbbb2964d6 100644 --- a/options_test.go +++ b/options_test.go @@ -115,8 +115,8 @@ func TestWithStartupCommand(t *testing.T) { err := testcontainers.WithStartupCommand(testExec)(&req) require.NoError(t, err) - assert.Len(t, req.LifecycleHooks, 1) - assert.Len(t, req.LifecycleHooks[0].PostStarts, 1) + require.Len(t, req.LifecycleHooks, 1) + require.Len(t, req.LifecycleHooks[0].PostStarts, 1) c, err := testcontainers.GenericContainer(context.Background(), req) testcontainers.CleanupContainer(t, c) @@ -144,8 +144,8 @@ func TestWithAfterReadyCommand(t *testing.T) { err := testcontainers.WithAfterReadyCommand(testExec)(&req) require.NoError(t, err) - assert.Len(t, req.LifecycleHooks, 1) - assert.Len(t, req.LifecycleHooks[0].PostReadies, 1) + require.Len(t, req.LifecycleHooks, 1) + require.Len(t, req.LifecycleHooks[0].PostReadies, 1) c, err := testcontainers.GenericContainer(context.Background(), req) testcontainers.CleanupContainer(t, c) From fb6a4ba574ecfebc2a14de987e3fe958f04a14f0 Mon Sep 17 00:00:00 2001 From: Joel Lau Date: Wed, 16 Oct 2024 23:57:14 +0800 Subject: [PATCH 087/126] chore: replace 'assert' with 'require' (#2827) --- container_ignore_test.go | 3 ++- internal/config/config_test.go | 3 ++- internal/core/docker_host_test.go | 2 +- modulegen/main_test.go | 4 +-- modulegen/mkdocs_test.go | 6 ++--- modules/artemis/artemis_test.go | 2 +- modules/compose/compose_api_test.go | 42 ++++++++++++++--------------- modules/redpanda/redpanda_test.go | 12 ++++----- 8 files changed, 38 insertions(+), 36 deletions(-) diff --git a/container_ignore_test.go b/container_ignore_test.go index ca89db4d89..505b9edd6d 100644 --- a/container_ignore_test.go +++ b/container_ignore_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestParseDockerIgnore(t *testing.T) { @@ -37,7 +38,7 @@ func TestParseDockerIgnore(t *testing.T) { for _, testCase := range testCases { exists, excluded, err := parseDockerIgnore(testCase.filePath) assert.Equal(t, testCase.exists, exists) - assert.Equal(t, testCase.expectedErr, err) + require.ErrorIs(t, testCase.expectedErr, err) assert.Equal(t, testCase.expectedExcluded, excluded) } } diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 319deb85b7..6f78a430b8 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const ( @@ -44,7 +45,7 @@ func TestReadConfig(t *testing.T) { Host: "", // docker socket is empty at the properties file } - assert.Equal(t, expected, config) + require.Equal(t, expected, config) t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "false") diff --git a/internal/core/docker_host_test.go b/internal/core/docker_host_test.go index 5454ab5f95..ea8779f217 100644 --- a/internal/core/docker_host_test.go +++ b/internal/core/docker_host_test.go @@ -73,7 +73,7 @@ func TestExtractDockerHost(t *testing.T) { host := MustExtractDockerHost(context.Background()) - assert.Equal(t, expected, host) + require.Equal(t, expected, host) t.Setenv("DOCKER_HOST", "/path/to/another/docker.sock") diff --git a/modulegen/main_test.go b/modulegen/main_test.go index 10e4b32131..f3dcfc15d8 100644 --- a/modulegen/main_test.go +++ b/modulegen/main_test.go @@ -281,7 +281,7 @@ func TestGenerate(t *testing.T) { moduleDirFileInfo, err := os.Stat(moduleDirPath) require.NoError(t, err) // error nil implies the file exist - assert.True(t, moduleDirFileInfo.IsDir()) + require.True(t, moduleDirFileInfo.IsDir()) moduleDocFile := filepath.Join(examplesDocTmp, moduleNameLower+".md") _, err = os.Stat(moduleDocFile) @@ -337,7 +337,7 @@ func TestGenerateModule(t *testing.T) { moduleDirFileInfo, err := os.Stat(moduleDirPath) require.NoError(t, err) // error nil implies the file exist - assert.True(t, moduleDirFileInfo.IsDir()) + require.True(t, moduleDirFileInfo.IsDir()) moduleDocFile := filepath.Join(modulesDocTmp, moduleNameLower+".md") _, err = os.Stat(moduleDocFile) diff --git a/modulegen/mkdocs_test.go b/modulegen/mkdocs_test.go index a43afcc388..9ca3b3860c 100644 --- a/modulegen/mkdocs_test.go +++ b/modulegen/mkdocs_test.go @@ -40,9 +40,9 @@ func TestReadMkDocsConfig(t *testing.T) { require.NoError(t, err) require.NotNil(t, config) - assert.Equal(t, "Testcontainers for Go", config.SiteName) - assert.Equal(t, "https://github.com/testcontainers/testcontainers-go", config.RepoURL) - assert.Equal(t, "edit/main/docs/", config.EditURI) + require.Equal(t, "Testcontainers for Go", config.SiteName) + require.Equal(t, "https://github.com/testcontainers/testcontainers-go", config.RepoURL) + require.Equal(t, "edit/main/docs/", config.EditURI) // theme theme := config.Theme diff --git a/modules/artemis/artemis_test.go b/modules/artemis/artemis_test.go index 01097463b2..74f150b031 100644 --- a/modules/artemis/artemis_test.go +++ b/modules/artemis/artemis_test.go @@ -76,7 +76,7 @@ func TestArtemis(t *testing.T) { res, err := http.Get(u) require.NoError(t, err, "failed to access console") res.Body.Close() - assert.Equal(t, http.StatusOK, res.StatusCode, "failed to access console") + require.Equal(t, http.StatusOK, res.StatusCode, "failed to access console") if test.user != "" { assert.Equal(t, test.user, ctr.User(), "unexpected user") diff --git a/modules/compose/compose_api_test.go b/modules/compose/compose_api_test.go index e40129ede8..9a0a4841b1 100644 --- a/modules/compose/compose_api_test.go +++ b/modules/compose/compose_api_test.go @@ -73,9 +73,9 @@ func TestDockerComposeAPIWithWaitLogStrategy(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 2) - assert.Contains(t, serviceNames, "api-nginx") - assert.Contains(t, serviceNames, "api-mysql") + require.Len(t, serviceNames, 2) + require.Contains(t, serviceNames, "api-nginx") + require.Contains(t, serviceNames, "api-mysql") } func TestDockerComposeAPIWithRunServices(t *testing.T) { @@ -170,9 +170,9 @@ func TestDockerComposeAPI_TestcontainersLabelsArePresent(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 2) - assert.Contains(t, serviceNames, "api-nginx") - assert.Contains(t, serviceNames, "api-mysql") + require.Len(t, serviceNames, 2) + require.Contains(t, serviceNames, "api-nginx") + require.Contains(t, serviceNames, "api-mysql") // all the services in the compose has the Testcontainers Labels for _, serviceName := range serviceNames { @@ -213,9 +213,9 @@ func TestDockerComposeAPI_WithReaper(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 2) - assert.Contains(t, serviceNames, "api-nginx") - assert.Contains(t, serviceNames, "api-mysql") + require.Len(t, serviceNames, 2) + require.Contains(t, serviceNames, "api-nginx") + require.Contains(t, serviceNames, "api-mysql") } func TestDockerComposeAPI_WithoutReaper(t *testing.T) { @@ -240,9 +240,9 @@ func TestDockerComposeAPI_WithoutReaper(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 2) - assert.Contains(t, serviceNames, "api-nginx") - assert.Contains(t, serviceNames, "api-mysql") + require.Len(t, serviceNames, 2) + require.Contains(t, serviceNames, "api-nginx") + require.Contains(t, serviceNames, "api-mysql") } func TestDockerComposeAPIWithStopServices(t *testing.T) { @@ -261,9 +261,9 @@ func TestDockerComposeAPIWithStopServices(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 2) - assert.Contains(t, serviceNames, "api-nginx") - assert.Contains(t, serviceNames, "api-mysql") + require.Len(t, serviceNames, 2) + require.Contains(t, serviceNames, "api-nginx") + require.Contains(t, serviceNames, "api-mysql") // close mysql container in purpose mysqlContainer, err := compose.ServiceContainer(context.Background(), "api-mysql") @@ -386,9 +386,9 @@ func TestDockerComposeAPIWithMultipleWaitStrategies(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 2) - assert.Contains(t, serviceNames, "api-nginx") - assert.Contains(t, serviceNames, "api-mysql") + require.Len(t, serviceNames, 2) + require.Contains(t, serviceNames, "api-nginx") + require.Contains(t, serviceNames, "api-mysql") } func TestDockerComposeAPIWithFailedStrategy(t *testing.T) { @@ -430,9 +430,9 @@ func TestDockerComposeAPIComplex(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 2) - assert.Contains(t, serviceNames, "api-nginx") - assert.Contains(t, serviceNames, "api-mysql") + require.Len(t, serviceNames, 2) + require.Contains(t, serviceNames, "api-nginx") + require.Contains(t, serviceNames, "api-mysql") } func TestDockerComposeAPIWithStackReader(t *testing.T) { diff --git a/modules/redpanda/redpanda_test.go b/modules/redpanda/redpanda_test.go index 09d391f794..3983b7f8ba 100644 --- a/modules/redpanda/redpanda_test.go +++ b/modules/redpanda/redpanda_test.go @@ -44,7 +44,7 @@ func TestRedpanda(t *testing.T) { kafkaAdmCl := kadm.NewClient(kafkaCl) metadata, err := kafkaAdmCl.Metadata(ctx) require.NoError(t, err) - assert.Len(t, metadata.Brokers, 1) + require.Len(t, metadata.Brokers, 1) // Test Schema Registry API httpCl := &http.Client{Timeout: 5 * time.Second} @@ -55,7 +55,7 @@ func TestRedpanda(t *testing.T) { resp, err := httpCl.Do(req) require.NoError(t, err) defer resp.Body.Close() - assert.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, http.StatusOK, resp.StatusCode) // Test Admin API // adminAPIAddress { @@ -67,7 +67,7 @@ func TestRedpanda(t *testing.T) { resp, err = httpCl.Do(req) require.NoError(t, err) defer resp.Body.Close() - assert.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, http.StatusOK, resp.StatusCode) // Test produce to unknown topic results := kafkaCl.ProduceSync(ctx, &kgo.Record{Topic: "test", Value: []byte("test message")}) @@ -289,7 +289,7 @@ func TestRedpandaWithOldVersionAndWasm(t *testing.T) { require.NoError(t, err) resp, err := httpCl.Do(req) require.NoError(t, err) - assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) + require.Equal(t, http.StatusUnauthorized, resp.StatusCode) resp.Body.Close() // Successful authentication @@ -357,7 +357,7 @@ func TestRedpandaWithTLS(t *testing.T) { require.NoError(t, err) resp, err := httpCl.Do(req) require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, http.StatusOK, resp.StatusCode) resp.Body.Close() // Test Schema Registry API @@ -368,7 +368,7 @@ func TestRedpandaWithTLS(t *testing.T) { require.NoError(t, err) resp, err = httpCl.Do(req) require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) + require.Equal(t, http.StatusOK, resp.StatusCode) resp.Body.Close() brokers, err := ctr.KafkaSeedBroker(ctx) From 00e7002d6cf57519e482796186a1f664dad48c07 Mon Sep 17 00:00:00 2001 From: Henri Parquet <56651131+henripqt@users.noreply.github.com> Date: Fri, 18 Oct 2024 08:30:46 +0200 Subject: [PATCH 088/126] fix: update module container struct name and missing imports (#2831) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: update module container struct name and missing imports * fix: update tests --------- Co-authored-by: Manuel de la Peña --- modulegen/_template/examples_test.go.tmpl | 4 +- modulegen/_template/module.go.tmpl | 10 ++--- modulegen/_template/module.md.tmpl | 4 +- modulegen/_template/module_test.go.tmpl | 1 + modulegen/internal/context/types.go | 13 +----- modulegen/main_test.go | 48 +++++++++++------------ 6 files changed, 33 insertions(+), 47 deletions(-) diff --git a/modulegen/_template/examples_test.go.tmpl b/modulegen/_template/examples_test.go.tmpl index f02ab36021..ca55c61e44 100644 --- a/modulegen/_template/examples_test.go.tmpl +++ b/modulegen/_template/examples_test.go.tmpl @@ -1,15 +1,15 @@ -{{ $entrypoint := Entrypoint }}{{ $image := Image }}{{ $lower := ToLower }}{{ $title := Title }}package {{ $lower }}_test +{{ $entrypoint := Entrypoint }}{{ $image := Image }}{{ $lower := ToLower }}package {{ $lower }}_test import ( "context" "fmt" "log" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/{{ ParentDir }}/{{ $lower }}" ) func Example{{ $entrypoint }}() { - // run{{ $title }}Container { ctx := context.Background() {{ $lower }}Container, err := {{ $lower }}.{{ $entrypoint }}(ctx, "{{ $image }}") diff --git a/modulegen/_template/module.go.tmpl b/modulegen/_template/module.go.tmpl index 31e50981d0..585e853fba 100644 --- a/modulegen/_template/module.go.tmpl +++ b/modulegen/_template/module.go.tmpl @@ -7,13 +7,13 @@ import ( "github.com/testcontainers/testcontainers-go" ) -// {{ $containerName }} represents the {{ $title }} container type used in the module -type {{ $containerName }} struct { +// Container represents the {{ $title }} container type used in the module +type Container struct { testcontainers.Container } // {{ $entrypoint }} creates an instance of the {{ $title }} container type -func {{ $entrypoint }}(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*{{ $containerName }}, error) { +func {{ $entrypoint }}(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*Container, error) { req := testcontainers.ContainerRequest{ Image: img, } @@ -30,9 +30,9 @@ func {{ $entrypoint }}(ctx context.Context, img string, opts ...testcontainers.C } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) - var c *{{ $containerName }} + var c *Container if container != nil { - c = &{{ $containerName }}{Container: container} + c = &Container{Container: container} } if err != nil { diff --git a/modulegen/_template/module.md.tmpl b/modulegen/_template/module.md.tmpl index ac29fb3337..91945bd254 100644 --- a/modulegen/_template/module.md.tmpl +++ b/modulegen/_template/module.md.tmpl @@ -1,4 +1,4 @@ -{{ $lower := ToLower }}{{ $title := Title }}# {{ $title }} +{{ $entrypoint := Entrypoint }}{{ $lower := ToLower }}{{ $title := Title }}# {{ $title }} Not available until the next release of testcontainers-go :material-tag: main @@ -17,7 +17,7 @@ go get github.com/testcontainers/testcontainers-go/{{ ParentDir }}/{{ $lower }} ## Usage example -[Creating a {{ $title }} container](../../{{ ParentDir }}/{{ $lower }}/examples_test.go) inside_block:run{{ $title }}Container +[Creating a {{ $title }} container](../../{{ ParentDir }}/{{ $lower }}/examples_test.go) inside_block:Example{{ $entrypoint }} ## Module Reference diff --git a/modulegen/_template/module_test.go.tmpl b/modulegen/_template/module_test.go.tmpl index 351ba5c8d5..1850e568c9 100644 --- a/modulegen/_template/module_test.go.tmpl +++ b/modulegen/_template/module_test.go.tmpl @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/{{ ParentDir }}/{{ $lower }}" ) diff --git a/modulegen/internal/context/types.go b/modulegen/internal/context/types.go index 0792c249df..61d0e6217e 100644 --- a/modulegen/internal/context/types.go +++ b/modulegen/internal/context/types.go @@ -4,8 +4,6 @@ import ( "fmt" "regexp" "strings" - "unicode" - "unicode/utf8" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -22,16 +20,7 @@ type TestcontainersModule struct { // ContainerName returns the name of the container, which is the lower-cased title of the example // If the title is set, it will be used instead of the name func (m *TestcontainersModule) ContainerName() string { - name := m.Lower() - - if m.IsModule { - name = m.Title() - } else if m.TitleName != "" { - r, n := utf8.DecodeRuneInString(m.TitleName) - name = string(unicode.ToLower(r)) + m.TitleName[n:] - } - - return name + "Container" + return "Container" } // Entrypoint returns the name of the entrypoint function, which is the lower-cased title of the example diff --git a/modulegen/main_test.go b/modulegen/main_test.go index f3dcfc15d8..ad9a946236 100644 --- a/modulegen/main_test.go +++ b/modulegen/main_test.go @@ -17,11 +17,10 @@ import ( func TestModule(t *testing.T) { tests := []struct { - name string - module context.TestcontainersModule - expectedContainerName string - expectedEntrypoint string - expectedTitle string + name string + module context.TestcontainersModule + expectedEntrypoint string + expectedTitle string }{ { name: "Module with title", @@ -31,9 +30,8 @@ func TestModule(t *testing.T) { Image: "mongodb:latest", TitleName: "MongoDB", }, - expectedContainerName: "MongoDBContainer", - expectedEntrypoint: "Run", - expectedTitle: "MongoDB", + expectedEntrypoint: "Run", + expectedTitle: "MongoDB", }, { name: "Module without title", @@ -42,9 +40,8 @@ func TestModule(t *testing.T) { IsModule: true, Image: "mongodb:latest", }, - expectedContainerName: "MongodbContainer", - expectedEntrypoint: "Run", - expectedTitle: "Mongodb", + expectedEntrypoint: "Run", + expectedTitle: "Mongodb", }, { name: "Example with title", @@ -54,9 +51,8 @@ func TestModule(t *testing.T) { Image: "mongodb:latest", TitleName: "MongoDB", }, - expectedContainerName: "mongoDBContainer", - expectedEntrypoint: "run", - expectedTitle: "MongoDB", + expectedEntrypoint: "run", + expectedTitle: "MongoDB", }, { name: "Example without title", @@ -65,9 +61,9 @@ func TestModule(t *testing.T) { IsModule: false, Image: "mongodb:latest", }, - expectedContainerName: "mongodbContainer", - expectedEntrypoint: "run", - expectedTitle: "Mongodb", + + expectedEntrypoint: "run", + expectedTitle: "Mongodb", }, } @@ -77,7 +73,7 @@ func TestModule(t *testing.T) { assert.Equal(t, "mongodb", module.Lower()) assert.Equal(t, test.expectedTitle, module.Title()) - assert.Equal(t, test.expectedContainerName, module.ContainerName()) + assert.Equal(t, "Container", module.ContainerName()) assert.Equal(t, test.expectedEntrypoint, module.Entrypoint()) }) } @@ -366,6 +362,7 @@ func assertModuleDocContent(t *testing.T, module context.TestcontainersModule, m lower := module.Lower() title := module.Title() + entrypoint := module.Entrypoint() data := sanitiseContent(content) assert.Equal(t, "# "+title, data[0]) @@ -376,7 +373,7 @@ func assertModuleDocContent(t *testing.T, module context.TestcontainersModule, m assert.Equal(t, "Please run the following command to add the "+title+" module to your Go dependencies:", data[10]) assert.Equal(t, "go get github.com/testcontainers/testcontainers-go/"+module.ParentDir()+"/"+lower, data[13]) assert.Equal(t, "", data[18]) - assert.Equal(t, "[Creating a "+title+" container](../../"+module.ParentDir()+"/"+lower+"/examples_test.go) inside_block:run"+title+"Container", data[19]) + assert.Equal(t, "[Creating a "+title+" container](../../"+module.ParentDir()+"/"+lower+"/examples_test.go) inside_block:Example"+entrypoint, data[19]) assert.Equal(t, "", data[20]) assert.Equal(t, "The "+title+" module exposes one entrypoint function to create the "+title+" container, and this function receives three parameters:", data[31]) assert.True(t, strings.HasSuffix(data[34], "(*"+title+"Container, error)")) @@ -391,13 +388,12 @@ func assertExamplesTestContent(t *testing.T, module context.TestcontainersModule lower := module.Lower() entrypoint := module.Entrypoint() - title := module.Title() data := sanitiseContent(content) assert.Equal(t, "package "+lower+"_test", data[0]) - assert.Equal(t, "\t\"github.com/testcontainers/testcontainers-go/modules/"+lower+"\"", data[7]) - assert.Equal(t, "func Example"+entrypoint+"() {", data[10]) - assert.Equal(t, "\t// run"+title+"Container {", data[11]) + assert.Equal(t, "\t\"github.com/testcontainers/testcontainers-go\"", data[7]) + assert.Equal(t, "\t\"github.com/testcontainers/testcontainers-go/modules/"+lower+"\"", data[8]) + assert.Equal(t, "func Example"+entrypoint+"() {", data[11]) assert.Equal(t, "\t"+lower+"Container, err := "+lower+"."+entrypoint+"(ctx, \""+module.Image+"\")", data[14]) assert.Equal(t, "\tfmt.Println(state.Running)", data[32]) assert.Equal(t, "\t// Output:", data[34]) @@ -411,8 +407,8 @@ func assertModuleTestContent(t *testing.T, module context.TestcontainersModule, data := sanitiseContent(content) assert.Equal(t, "package "+module.Lower()+"_test", data[0]) - assert.Equal(t, "func Test"+module.Title()+"(t *testing.T) {", data[11]) - assert.Equal(t, "\tctr, err := "+module.Lower()+"."+module.Entrypoint()+"(ctx, \""+module.Image+"\")", data[14]) + assert.Equal(t, "func Test"+module.Title()+"(t *testing.T) {", data[12]) + assert.Equal(t, "\tctr, err := "+module.Lower()+"."+module.Entrypoint()+"(ctx, \""+module.Image+"\")", data[15]) } // assert content module @@ -427,7 +423,7 @@ func assertModuleContent(t *testing.T, module context.TestcontainersModule, exam data := sanitiseContent(content) require.Equal(t, "package "+lower, data[0]) - require.Equal(t, "// "+containerName+" represents the "+exampleName+" container type used in the module", data[9]) + require.Equal(t, "// Container represents the "+exampleName+" container type used in the module", data[9]) require.Equal(t, "type "+containerName+" struct {", data[10]) require.Equal(t, "// "+entrypoint+" creates an instance of the "+exampleName+" container type", data[14]) require.Equal(t, "func "+entrypoint+"(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*"+containerName+", error) {", data[15]) From 27f699b43aa02e1d0bf7fe6efd7631f00e768319 Mon Sep 17 00:00:00 2001 From: Henri Parquet <56651131+henripqt@users.noreply.github.com> Date: Fri, 18 Oct 2024 11:41:46 +0200 Subject: [PATCH 089/126] feat: add yugabytedb module (#2825) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add yugabytedb module * fix: documentation links * fix: codeinclude target * feat: add test example for custom methods * Update modules/yugabytedb/yugabytedb_test.go Co-authored-by: Steven Hartland * Update modules/yugabytedb/yugabytedb.go Co-authored-by: Steven Hartland * Update modules/yugabytedb/yugabytedb_test.go Co-authored-by: Steven Hartland * fix: attended review issues * Update modules/yugabytedb/examples_test.go Co-authored-by: Steven Hartland * fix: cleanup and review adjustements * fix: remove test in comments and renamed struct * feat: add documentation for options * Update modules/yugabytedb/yugabytedb_test.go Co-authored-by: Manuel de la Peña * Update modules/yugabytedb/yugabytedb_test.go Co-authored-by: Manuel de la Peña * fix: add additional wait strategy for data constraint log * fix: remove customer method for ycql config and update test code * chore: run mod tidy * chore: rename testable example to fix lint "refers to unknown field or method: Container.YCQLConfigureClusterConfig" * fix: wrong cluster addr in example test * fix: update code snippet run example --------- Co-authored-by: Steven Hartland Co-authored-by: Manuel de la Peña Co-authored-by: Manuel de la Peña --- .github/workflows/ci.yml | 2 +- .vscode/.testcontainers-go.code-workspace | 4 + docs/modules/yugabytedb.md | 94 ++++++++++ mkdocs.yml | 1 + modules/yugabytedb/Makefile | 5 + modules/yugabytedb/examples_test.go | 155 ++++++++++++++++ modules/yugabytedb/go.mod | 65 +++++++ modules/yugabytedb/go.sum | 209 ++++++++++++++++++++++ modules/yugabytedb/options.go | 53 ++++++ modules/yugabytedb/yugabytedb.go | 126 +++++++++++++ modules/yugabytedb/yugabytedb_test.go | 129 +++++++++++++ sonar-project.properties | 2 +- 12 files changed, 843 insertions(+), 2 deletions(-) create mode 100644 docs/modules/yugabytedb.md create mode 100644 modules/yugabytedb/Makefile create mode 100644 modules/yugabytedb/examples_test.go create mode 100644 modules/yugabytedb/go.mod create mode 100644 modules/yugabytedb/go.sum create mode 100644 modules/yugabytedb/options.go create mode 100644 modules/yugabytedb/yugabytedb.go create mode 100644 modules/yugabytedb/yugabytedb_test.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0fea7eaeb0..5d45d9b70a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: matrix: go-version: [1.22.x, 1.x] platform: [ubuntu-latest] - module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, dynamodb, elasticsearch, etcd, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate] + module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, dynamodb, elasticsearch, etcd, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate, yugabytedb] uses: ./.github/workflows/ci-test-go.yml with: go-version: ${{ matrix.go-version }} diff --git a/.vscode/.testcontainers-go.code-workspace b/.vscode/.testcontainers-go.code-workspace index 68a2751a5d..73e2699036 100644 --- a/.vscode/.testcontainers-go.code-workspace +++ b/.vscode/.testcontainers-go.code-workspace @@ -201,6 +201,10 @@ "name": "module / weaviate", "path": "../modules/weaviate" }, + { + "name": "module / yugabytedb", + "path": "../modules/yugabytedb" + }, { "name": "modulegen", "path": "../modulegen" diff --git a/docs/modules/yugabytedb.md b/docs/modules/yugabytedb.md new file mode 100644 index 0000000000..b645d678c9 --- /dev/null +++ b/docs/modules/yugabytedb.md @@ -0,0 +1,94 @@ +# YugabyteDB + +Not available until the next release of testcontainers-go :material-tag: main + +## Introduction + +The Testcontainers module for yugabyteDB. + +## Adding this module to your project dependencies + +Please run the following command to add the yugabyteDB module to your Go dependencies: + +``` +go get github.com/testcontainers/testcontainers-go/modules/yugabytedb +``` + +## Usage example + + +[Creating a yugabyteDB container](../../modules/yugabytedb/examples_test.go) inside_block:runyugabyteDBContainer + + +## Module Reference + +### Run function + +The yugabyteDB module exposes one entrypoint function to create the yugabyteDB container, and this function receives three parameters: + +```golang +func Run( + ctx context.Context, + img string, + opts ...testcontainers.ContainerCustomizer, +) (*Container, error) +``` + +- `context.Context`, the Go context. +- `string`, the Docker image to use. +- `testcontainers.ContainerCustomizer`, a variadic argument for passing options. + +### Container Options + +When starting the yugabyteDB container, you can pass options in a variadic way to configure it. + +#### Image + +If you need to set a different yugabyteDB Docker image, you can set a valid Docker image as the second argument in the `Run` function. +E.g. `Run(context.Background(), "yugabytedb/yugabyte")`. + +{% include "../features/common_functional_options.md" %} + +#### Initial Database + +By default the yugabyteDB container will start with a database named `yugabyte` and the default credentials `yugabyte` and `yugabyte`. + +If you need to set a different database, and its credentials, you can use the `WithDatabaseName(dbName string)`, `WithDatabaseUser(dbUser string)` and `WithDatabasePassword(dbPassword string)` options. + +#### Initial Cluster Configuration + +By default the yugabyteDB container will start with a cluster keyspace named `yugabyte` and the default credentials `yugabyte` and `yugabyte`. + +If you need to set a different cluster keyspace, and its credentials, you can use the `WithKeyspace(keyspace string)`, `WithUser(user string)` and `WithPassword(password string)` options. + +### Container Methods + +The yugabyteDB container exposes the following methods: + +#### YSQLConnectionString + +This method returns the connection string for the yugabyteDB container when using +the YSQL query language. +The connection string can then be used to connect to the yugabyteDB container using +a standard PostgreSQL client. + + +[Create a postgres client using the connection string](../../modules/yugabytedb/examples_test.go) block:ExampleContainer_YSQLConnectionString + + +### Usage examples + +#### Usage with YSQL and gocql + +To use the YCQL query language, you need to configure the cluster +with the keyspace, user, and password. + +By default, the yugabyteDB container will start with a cluster keyspace named `yugabyte` and the default credentials `yugabyte` and `yugabyte` but you can change it using the `WithKeyspace`, `WithUser` and `WithPassword` options. + +In order to get the appropriate host and port to connect to the yugabyteDB container, +you can use the `GetHost` and `GetMappedPort` methods on the Container struct. +See the examples below: + + +[Create a yugabyteDB client using the cluster configuration](../../modules/yugabytedb/yugabytedb_test.go) block:TestYugabyteDB_YCQL + \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 824f5091e1..c861b37ac8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -112,6 +112,7 @@ nav: - modules/vault.md - modules/vearch.md - modules/weaviate.md + - modules/yugabytedb.md - Examples: - examples/index.md - examples/nginx.md diff --git a/modules/yugabytedb/Makefile b/modules/yugabytedb/Makefile new file mode 100644 index 0000000000..a56dee99f2 --- /dev/null +++ b/modules/yugabytedb/Makefile @@ -0,0 +1,5 @@ +include ../../commons-test.mk + +.PHONY: test +test: + $(MAKE) test-yugabytedb diff --git a/modules/yugabytedb/examples_test.go b/modules/yugabytedb/examples_test.go new file mode 100644 index 0000000000..641fc5a53f --- /dev/null +++ b/modules/yugabytedb/examples_test.go @@ -0,0 +1,155 @@ +package yugabytedb_test + +import ( + "context" + "database/sql" + "fmt" + "log" + "net" + + _ "github.com/lib/pq" + "github.com/yugabyte/gocql" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/yugabytedb" +) + +func ExampleRun() { + // runyugabyteDBContainer { + ctx := context.Background() + + yugabytedbContainer, err := yugabytedb.Run( + ctx, + "yugabytedb/yugabyte:2024.1.3.0-b105", + yugabytedb.WithKeyspace("custom-keyspace"), + yugabytedb.WithUser("custom-user"), + yugabytedb.WithDatabaseName("custom-db"), + yugabytedb.WithDatabaseUser("custom-user"), + yugabytedb.WithDatabasePassword("custom-password"), + ) + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + + defer func() { + if err := testcontainers.TerminateContainer(yugabytedbContainer); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() + // } + + state, err := yugabytedbContainer.State(ctx) + if err != nil { + log.Printf("failed to get container state: %s", err) + return + } + + fmt.Println(state.Running) + + // Output: true +} + +func ExampleContainer_YSQLConnectionString() { + ctx := context.Background() + + yugabytedbContainer, err := yugabytedb.Run( + ctx, + "yugabytedb/yugabyte:2024.1.3.0-b105", + ) + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + + defer func() { + if err := testcontainers.TerminateContainer(yugabytedbContainer); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() + + connStr, err := yugabytedbContainer.YSQLConnectionString(ctx, "sslmode=disable") + if err != nil { + log.Printf("failed to get connection string: %s", err) + return + } + + db, err := sql.Open("postgres", connStr) + if err != nil { + log.Printf("failed to open connection: %s", err) + return + } + + defer db.Close() + + var i int + row := db.QueryRowContext(ctx, "SELECT 1") + if err := row.Scan(&i); err != nil { + log.Printf("failed to scan row: %s", err) + return + } + + fmt.Println(i) + + // Output: 1 +} + +func ExampleContainer_newCluster() { + ctx := context.Background() + + yugabytedbContainer, err := yugabytedb.Run( + ctx, + "yugabytedb/yugabyte:2024.1.3.0-b105", + ) + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + + defer func() { + if err := testcontainers.TerminateContainer(yugabytedbContainer); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() + + yugabytedbContainerHost, err := yugabytedbContainer.Host(ctx) + if err != nil { + log.Printf("failed to get container host: %s", err) + return + } + + yugabyteContainerPort, err := yugabytedbContainer.MappedPort(ctx, "9042/tcp") + if err != nil { + log.Printf("failed to get container port: %s", err) + return + } + + cluster := gocql.NewCluster(net.JoinHostPort(yugabytedbContainerHost, yugabyteContainerPort.Port())) + cluster.Keyspace = "yugabyte" + cluster.Authenticator = gocql.PasswordAuthenticator{ + Username: "yugabyte", + Password: "yugabyte", + } + + session, err := cluster.CreateSession() + if err != nil { + log.Printf("failed to create session: %s", err) + return + } + + defer session.Close() + + var i int + if err := session.Query(` + SELECT COUNT(*) + FROM system_schema.keyspaces + WHERE keyspace_name = 'yugabyte' + `).Scan(&i); err != nil { + log.Printf("failed to scan row: %s", err) + return + } + + fmt.Println(i) + + // Output: 1 +} diff --git a/modules/yugabytedb/go.mod b/modules/yugabytedb/go.mod new file mode 100644 index 0000000000..53295d1d26 --- /dev/null +++ b/modules/yugabytedb/go.mod @@ -0,0 +1,65 @@ +module github.com/testcontainers/testcontainers-go/modules/yugabytedb + +go 1.22 + +require ( + github.com/lib/pq v1.10.9 + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.33.0 + github.com/yugabyte/gocql v1.6.0-yb-1 +) + +require ( + dario.cat/mergo v1.0.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/containerd/containerd v1.7.18 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v27.1.1+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/snappy v0.0.3 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/sys v0.21.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/yugabytedb/go.sum b/modules/yugabytedb/go.sum new file mode 100644 index 0000000000..188e4bba97 --- /dev/null +++ b/modules/yugabytedb/go.sum @@ -0,0 +1,209 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +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/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY= +github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= +github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +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.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +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.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/yugabyte/gocql v1.6.0-yb-1 h1:3anNiHsJwKQ8Dn7RdmkTEuIzV1l7e9QJZ8wkOZ87ELg= +github.com/yugabyte/gocql v1.6.0-yb-1/go.mod h1:LAokR6+vevDCrTxk52U7p6ki+4qELu4XU7JUGYa2O2M= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +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/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20230920204549-e6e6cdab5c13 h1:vlzZttNJGVqTsRFU9AmdnrcO1Znh8Ew9kCD//yjigk0= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= +google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/modules/yugabytedb/options.go b/modules/yugabytedb/options.go new file mode 100644 index 0000000000..485b979468 --- /dev/null +++ b/modules/yugabytedb/options.go @@ -0,0 +1,53 @@ +package yugabytedb + +import ( + "github.com/testcontainers/testcontainers-go" +) + +// WithDatabaseName sets the initial database name for the yugabyteDB container. +func WithDatabaseName(dbName string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + req.Env[ysqlDatabaseNameEnv] = dbName + return nil + } +} + +// WithDatabaseUser sets the initial database user for the yugabyteDB container. +func WithDatabaseUser(dbUser string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + req.Env[ysqlDatabaseUserEnv] = dbUser + return nil + } +} + +// WithDatabasePassword sets the initial database password for the yugabyteDB container. +func WithDatabasePassword(dbPassword string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + req.Env[ysqlDatabasePasswordEnv] = dbPassword + return nil + } +} + +// WithKeyspace sets the initial keyspace for the yugabyteDB container. +func WithKeyspace(keyspace string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + req.Env[ycqlKeyspaceEnv] = keyspace + return nil + } +} + +// WithUser sets the initial user for the yugabyteDB container. +func WithUser(user string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + req.Env[ycqlUserNameEnv] = user + return nil + } +} + +// WithPassword sets the initial password for the yugabyteDB container. +func WithPassword(password string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + req.Env[ycqlPasswordEnv] = password + return nil + } +} diff --git a/modules/yugabytedb/yugabytedb.go b/modules/yugabytedb/yugabytedb.go new file mode 100644 index 0000000000..13d6e9ccb0 --- /dev/null +++ b/modules/yugabytedb/yugabytedb.go @@ -0,0 +1,126 @@ +package yugabytedb + +import ( + "context" + "fmt" + "net" + "strings" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +const ( + ycqlPort = "9042/tcp" + + ycqlKeyspaceEnv = "YCQL_KEYSPACE" + ycqlUserNameEnv = "YCQL_USER" + ycqlPasswordEnv = "YCQL_PASSWORD" + + ycqlKeyspace = "yugabyte" + ycqlUserName = "yugabyte" + ycqlPassword = "yugabyte" +) + +const ( + ysqlPort = "5433/tcp" + + ysqlDatabaseNameEnv = "YSQL_DB" + ysqlDatabaseUserEnv = "YSQL_USER" + ysqlDatabasePasswordEnv = "YSQL_PASSWORD" + + ysqlDatabaseName = "yugabyte" + ysqlDatabaseUser = "yugabyte" + ysqlDatabasePassword = "yugabyte" +) + +// Container represents the yugabyteDB container type used in the module +type Container struct { + testcontainers.Container + + ysqlDatabaseName string + ysqlDatabaseUser string + ysqlDatabasePassword string +} + +// Run creates an instance of the yugabyteDB container type and automatically starts it. +// A default configuration is used for the container, but it can be customized using the +// provided options. +// When using default configuration values it is recommended to use the provided +// [*Container.YSQLConnectionString] and [*Container.YCQLConfigureClusterConfig] +// methods to use the container in their respective clients. +func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*Container, error) { + req := testcontainers.ContainerRequest{ + Image: img, + Cmd: []string{"bin/yugabyted", "start", "--background=false"}, + WaitingFor: wait.ForAll( + wait.ForLog("YugabyteDB Started").WithOccurrence(1), + wait.ForLog("Data placement constraint successfully verified").WithOccurrence(1), + wait.ForListeningPort(ysqlPort), + wait.ForListeningPort(ycqlPort), + ), + ExposedPorts: []string{ycqlPort, ysqlPort}, + Env: map[string]string{ + ycqlKeyspaceEnv: ycqlKeyspace, + ycqlUserNameEnv: ycqlUserName, + ycqlPasswordEnv: ycqlPassword, + ysqlDatabaseNameEnv: ysqlDatabaseName, + ysqlDatabaseUserEnv: ysqlDatabaseUser, + ysqlDatabasePasswordEnv: ysqlDatabasePassword, + }, + } + + genericContainerReq := testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + } + + for _, opt := range opts { + if err := opt.Customize(&genericContainerReq); err != nil { + return nil, fmt.Errorf("customize: %w", err) + } + } + + container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *Container + if container != nil { + c = &Container{ + Container: container, + ysqlDatabaseName: req.Env[ysqlDatabaseNameEnv], + ysqlDatabaseUser: req.Env[ysqlDatabaseUserEnv], + ysqlDatabasePassword: req.Env[ysqlDatabasePasswordEnv], + } + } + + if err != nil { + return c, fmt.Errorf("generic container: %w", err) + } + + return c, nil +} + +// YSQLConnectionString returns a connection string for the yugabyteDB container +// using the configured database name, user, password, port, host and additional +// arguments. +// Additional arguments are appended to the connection string as query parameters +// in the form of key=value pairs separated by "&". +func (y *Container) YSQLConnectionString(ctx context.Context, args ...string) (string, error) { + host, err := y.Host(ctx) + if err != nil { + return "", fmt.Errorf("host: %w", err) + } + + mappedPort, err := y.MappedPort(ctx, ysqlPort) + if err != nil { + return "", fmt.Errorf("mapped port: %w", err) + } + + return fmt.Sprintf( + "postgres://%s:%s@%s/%s?%s", + y.ysqlDatabaseUser, + y.ysqlDatabasePassword, + net.JoinHostPort(host, mappedPort.Port()), + y.ysqlDatabaseName, + strings.Join(args, "&"), + ), nil +} diff --git a/modules/yugabytedb/yugabytedb_test.go b/modules/yugabytedb/yugabytedb_test.go new file mode 100644 index 0000000000..38a93f0c89 --- /dev/null +++ b/modules/yugabytedb/yugabytedb_test.go @@ -0,0 +1,129 @@ +package yugabytedb_test + +import ( + "context" + "database/sql" + "fmt" + "net" + "testing" + + _ "github.com/lib/pq" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/yugabyte/gocql" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/yugabytedb" +) + +func TestYugabyteDB_YSQL(t *testing.T) { + t.Run("Run", func(t *testing.T) { + ctx := context.Background() + + ctr, err := yugabytedb.Run(ctx, "yugabytedb/yugabyte:2024.1.3.0-b105") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + ctrHost, err := ctr.Host(ctx) + require.NoError(t, err) + + ctrPort, err := ctr.MappedPort(ctx, "5433/tcp") + require.NoError(t, err) + + ysqlConnStr, err := ctr.YSQLConnectionString(ctx, "sslmode=disable") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("postgres://yugabyte:yugabyte@%s:%s/yugabyte?sslmode=disable", ctrHost, ctrPort.Port()), ysqlConnStr) + + db, err := sql.Open("postgres", ysqlConnStr) + require.NoError(t, err) + require.NotNil(t, db) + + err = db.Ping() + require.NoError(t, err) + }) + + t.Run("custom-options", func(t *testing.T) { + ctx := context.Background() + ctr, err := yugabytedb.Run(ctx, "yugabytedb/yugabyte:2024.1.3.0-b105", + yugabytedb.WithDatabaseName("custom-db"), + yugabytedb.WithDatabaseUser("custom-user"), + yugabytedb.WithDatabasePassword("custom-password"), + ) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + ctrHost, err := ctr.Host(ctx) + require.NoError(t, err) + + ctrPort, err := ctr.MappedPort(ctx, "5433/tcp") + require.NoError(t, err) + + ysqlConnStr, err := ctr.YSQLConnectionString(ctx, "sslmode=disable") + require.NoError(t, err) + assert.Equal(t, fmt.Sprintf("postgres://custom-user:custom-password@%s:%s/custom-db?sslmode=disable", ctrHost, ctrPort.Port()), ysqlConnStr) + + db, err := sql.Open("postgres", ysqlConnStr) + require.NoError(t, err) + require.NotNil(t, db) + + err = db.Ping() + require.NoError(t, err) + }) +} + +func TestYugabyteDB_YCQL(t *testing.T) { + t.Run("Run", func(t *testing.T) { + ctx := context.Background() + + ctr, err := yugabytedb.Run(ctx, "yugabytedb/yugabyte:2024.1.3.0-b105") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + ctrHost, err := ctr.Host(ctx) + require.NoError(t, err) + + ctrPort, err := ctr.MappedPort(ctx, "9042/tcp") + require.NoError(t, err) + + cluster := gocql.NewCluster(net.JoinHostPort(ctrHost, ctrPort.Port())) + cluster.Keyspace = "yugabyte" + cluster.Authenticator = gocql.PasswordAuthenticator{ + Username: "yugabyte", + Password: "yugabyte", + } + + session, err := cluster.CreateSession() + require.NoError(t, err) + session.Close() + }) + + t.Run("custom-options", func(t *testing.T) { + ctx := context.Background() + + ctr, err := yugabytedb.Run(ctx, "yugabytedb/yugabyte:2024.1.3.0-b105", + yugabytedb.WithKeyspace("custom-keyspace"), + yugabytedb.WithUser("custom-user"), + yugabytedb.WithPassword("custom-password"), + ) + + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + ctrHost, err := ctr.Host(ctx) + require.NoError(t, err) + + ctrPort, err := ctr.MappedPort(ctx, "9042/tcp") + require.NoError(t, err) + + cluster := gocql.NewCluster(net.JoinHostPort(ctrHost, ctrPort.Port())) + cluster.Keyspace = "custom-keyspace" + cluster.Authenticator = gocql.PasswordAuthenticator{ + Username: "custom-user", + Password: "custom-password", + } + + session, err := cluster.CreateSession() + require.NoError(t, err) + session.Close() + }) +} diff --git a/sonar-project.properties b/sonar-project.properties index 1b5cb92513..b0531a66c1 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -18,4 +18,4 @@ sonar.test.inclusions=**/*_test.go sonar.test.exclusions=**/vendor/** sonar.go.coverage.reportPaths=**/coverage.out -sonar.go.tests.reportPaths=TEST-unit.xml,examples/nginx/TEST-unit.xml,examples/toxiproxy/TEST-unit.xml,modulegen/TEST-unit.xml,modules/artemis/TEST-unit.xml,modules/azurite/TEST-unit.xml,modules/cassandra/TEST-unit.xml,modules/chroma/TEST-unit.xml,modules/clickhouse/TEST-unit.xml,modules/cockroachdb/TEST-unit.xml,modules/compose/TEST-unit.xml,modules/consul/TEST-unit.xml,modules/couchbase/TEST-unit.xml,modules/databend/TEST-unit.xml,modules/dolt/TEST-unit.xml,modules/dynamodb/TEST-unit.xml,modules/elasticsearch/TEST-unit.xml,modules/etcd/TEST-unit.xml,modules/gcloud/TEST-unit.xml,modules/grafana-lgtm/TEST-unit.xml,modules/inbucket/TEST-unit.xml,modules/influxdb/TEST-unit.xml,modules/k3s/TEST-unit.xml,modules/k6/TEST-unit.xml,modules/kafka/TEST-unit.xml,modules/localstack/TEST-unit.xml,modules/mariadb/TEST-unit.xml,modules/milvus/TEST-unit.xml,modules/minio/TEST-unit.xml,modules/mockserver/TEST-unit.xml,modules/mongodb/TEST-unit.xml,modules/mssql/TEST-unit.xml,modules/mysql/TEST-unit.xml,modules/nats/TEST-unit.xml,modules/neo4j/TEST-unit.xml,modules/ollama/TEST-unit.xml,modules/openfga/TEST-unit.xml,modules/openldap/TEST-unit.xml,modules/opensearch/TEST-unit.xml,modules/postgres/TEST-unit.xml,modules/pulsar/TEST-unit.xml,modules/qdrant/TEST-unit.xml,modules/rabbitmq/TEST-unit.xml,modules/redis/TEST-unit.xml,modules/redpanda/TEST-unit.xml,modules/registry/TEST-unit.xml,modules/surrealdb/TEST-unit.xml,modules/valkey/TEST-unit.xml,modules/vault/TEST-unit.xml,modules/vearch/TEST-unit.xml,modules/weaviate/TEST-unit.xml +sonar.go.tests.reportPaths=TEST-unit.xml,examples/nginx/TEST-unit.xml,examples/toxiproxy/TEST-unit.xml,modulegen/TEST-unit.xml,modules/artemis/TEST-unit.xml,modules/azurite/TEST-unit.xml,modules/cassandra/TEST-unit.xml,modules/chroma/TEST-unit.xml,modules/clickhouse/TEST-unit.xml,modules/cockroachdb/TEST-unit.xml,modules/compose/TEST-unit.xml,modules/consul/TEST-unit.xml,modules/couchbase/TEST-unit.xml,modules/databend/TEST-unit.xml,modules/dolt/TEST-unit.xml,modules/dynamodb/TEST-unit.xml,modules/elasticsearch/TEST-unit.xml,modules/etcd/TEST-unit.xml,modules/gcloud/TEST-unit.xml,modules/grafana-lgtm/TEST-unit.xml,modules/inbucket/TEST-unit.xml,modules/influxdb/TEST-unit.xml,modules/k3s/TEST-unit.xml,modules/k6/TEST-unit.xml,modules/kafka/TEST-unit.xml,modules/localstack/TEST-unit.xml,modules/mariadb/TEST-unit.xml,modules/milvus/TEST-unit.xml,modules/minio/TEST-unit.xml,modules/mockserver/TEST-unit.xml,modules/mongodb/TEST-unit.xml,modules/mssql/TEST-unit.xml,modules/mysql/TEST-unit.xml,modules/nats/TEST-unit.xml,modules/neo4j/TEST-unit.xml,modules/ollama/TEST-unit.xml,modules/openfga/TEST-unit.xml,modules/openldap/TEST-unit.xml,modules/opensearch/TEST-unit.xml,modules/postgres/TEST-unit.xml,modules/pulsar/TEST-unit.xml,modules/qdrant/TEST-unit.xml,modules/rabbitmq/TEST-unit.xml,modules/redis/TEST-unit.xml,modules/redpanda/TEST-unit.xml,modules/registry/TEST-unit.xml,modules/surrealdb/TEST-unit.xml,modules/valkey/TEST-unit.xml,modules/vault/TEST-unit.xml,modules/vearch/TEST-unit.xml,modules/weaviate/TEST-unit.xml,modules/yugabytedb/TEST-unit.xml From 56bb5015d460f67e7c185293a62b2707bd1e2ddb Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 18 Oct 2024 11:27:19 +0100 Subject: [PATCH 090/126] chore: update ryuk to 0.10.2 (#2833) Update the ryuk version so that shutdown processing is fast after a TERM signal. --- internal/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/config/config.go b/internal/config/config.go index 35c9918e82..b0bcc24d3b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -11,7 +11,7 @@ import ( "github.com/magiconair/properties" ) -const ReaperDefaultImage = "testcontainers/ryuk:0.10.0" +const ReaperDefaultImage = "testcontainers/ryuk:0.10.2" var ( tcConfig Config From 5e988ffd21778f56f494cd744a0a288c2c8f3f6d Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Fri, 18 Oct 2024 12:54:36 +0100 Subject: [PATCH 091/126] fix(reaper): refactor to allow retries and fix races (#2728) Refactor how the reaper is created to allow for proper retries of temporary errors such as container not found issues during startup or shutdown races. This eliminates the use of sync.Once which wasn't solving the problem at hand and replaces it with a singleton spawner with locked access. Wrap reaper errors so we can determine the cause of failures more easily. Fix race condition in port wait when loading from container by always waiting for the port first. Remove unnecessary use of buffering and invalid retry logic in reaper connection handling which could never recover correctly from a partial read. Move the reaper creation just before connections are established in compose to ensure its still running when the Connect calls are made. Previously the reaper was requested in NewDockerComposeWith which means it could have already shutdown before connections are made during the later sections of Up if the startup took over 1 minute. This was causing consistent failures for: TestDockerComposeAPIWithWaitLogStrategy Ensure that resource labels are correct so that resources aren't reaped when the reaper is disabled by excluding session id when reaper is disabled. Error when creating a reaper when the config says it's disabled so that we avoid hard to debug issues because a reaper is running when it shouldn't be. Set org.testcontainers.reap label for containers which should be reaped by the reaper, to prevent containers which disable the reaper from being incorrectly reaped. --- container.go | 22 +- docker.go | 102 ++--- docker_mounts.go | 4 +- generic.go | 12 +- internal/core/labels.go | 44 +- lifecycle.go | 2 +- modules/compose/compose.go | 18 - modules/compose/compose_api.go | 96 ++-- modules/compose/compose_api_test.go | 3 +- reaper.go | 585 +++++++++++++++--------- reaper_test.go | 672 +++++++++++++--------------- testing.go | 4 +- 12 files changed, 857 insertions(+), 707 deletions(-) diff --git a/container.go b/container.go index 1e95fb09d4..d114a5988a 100644 --- a/container.go +++ b/container.go @@ -37,17 +37,17 @@ type DeprecatedContainer interface { // Container allows getting info about and controlling a single container instance type Container interface { - GetContainerID() string // get the container id from the provider - Endpoint(context.Context, string) (string, error) // get proto://ip:port string for the lowest exposed port - PortEndpoint(context.Context, nat.Port, string) (string, error) // get proto://ip:port string for the given exposed port - Host(context.Context) (string, error) // get host where the container port is exposed - Inspect(context.Context) (*types.ContainerJSON, error) // get container info - MappedPort(context.Context, nat.Port) (nat.Port, error) // get externally mapped port for a container port - Ports(context.Context) (nat.PortMap, error) // Deprecated: Use c.Inspect(ctx).NetworkSettings.Ports instead - SessionID() string // get session id - IsRunning() bool // IsRunning returns true if the container is running, false otherwise. - Start(context.Context) error // start the container - Stop(context.Context, *time.Duration) error // stop the container + GetContainerID() string // get the container id from the provider + Endpoint(context.Context, string) (string, error) // get proto://ip:port string for the lowest exposed port + PortEndpoint(ctx context.Context, port nat.Port, proto string) (string, error) // get proto://ip:port string for the given exposed port + Host(context.Context) (string, error) // get host where the container port is exposed + Inspect(context.Context) (*types.ContainerJSON, error) // get container info + MappedPort(context.Context, nat.Port) (nat.Port, error) // get externally mapped port for a container port + Ports(context.Context) (nat.PortMap, error) // Deprecated: Use c.Inspect(ctx).NetworkSettings.Ports instead + SessionID() string // get session id + IsRunning() bool // IsRunning returns true if the container is running, false otherwise. + Start(context.Context) error // start the container + Stop(context.Context, *time.Duration) error // stop the container // Terminate stops and removes the container and its image if it was built and not flagged as kept. Terminate(ctx context.Context) error diff --git a/docker.go b/docker.go index 9319c630dd..2ef8c6973a 100644 --- a/docker.go +++ b/docker.go @@ -183,7 +183,7 @@ func (c *DockerContainer) Inspect(ctx context.Context) (*types.ContainerJSON, er func (c *DockerContainer) MappedPort(ctx context.Context, port nat.Port) (nat.Port, error) { inspect, err := c.Inspect(ctx) if err != nil { - return "", err + return "", fmt.Errorf("inspect: %w", err) } if inspect.ContainerJSONBase.HostConfig.NetworkMode == "host" { return port, nil @@ -204,7 +204,7 @@ func (c *DockerContainer) MappedPort(ctx context.Context, port nat.Port) (nat.Po return nat.NewPort(k.Proto(), p[0].HostPort) } - return "", errors.New("port not found") + return "", errdefs.NotFound(fmt.Errorf("port %q not found", port)) } // Deprecated: use c.Inspect(ctx).NetworkSettings.Ports instead. @@ -980,9 +980,7 @@ func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (st } // CreateContainer fulfils a request for a container without starting it -func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerRequest) (Container, error) { - var err error - +func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerRequest) (con Container, err error) { //nolint:nonamedreturns // Needed for error checking. // defer the close of the Docker client connection the soonest defer p.Close() @@ -1027,22 +1025,23 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque // the reaper does not need to start a reaper for itself isReaperContainer := strings.HasSuffix(imageName, config.ReaperDefaultImage) if !p.config.RyukDisabled && !isReaperContainer { - r, err := reuseOrCreateReaper(context.WithValue(ctx, core.DockerHostContextKey, p.host), core.SessionID(), p) + r, err := spawner.reaper(context.WithValue(ctx, core.DockerHostContextKey, p.host), core.SessionID(), p) if err != nil { - return nil, fmt.Errorf("%w: creating reaper failed", err) + return nil, fmt.Errorf("reaper: %w", err) } - termSignal, err = r.Connect() + + termSignal, err := r.Connect() if err != nil { - return nil, fmt.Errorf("%w: connecting to reaper failed", err) + return nil, fmt.Errorf("reaper connect: %w", err) } - } - // Cleanup on error, otherwise set termSignal to nil before successful return. - defer func() { - if termSignal != nil { - termSignal <- true - } - }() + // Cleanup on error. + defer func() { + if err != nil { + termSignal <- true + } + }() + } if err = req.Validate(); err != nil { return nil, err @@ -1108,10 +1107,9 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque } if !isReaperContainer { - // add the labels that the reaper will use to terminate the container to the request - for k, v := range core.DefaultLabels(core.SessionID()) { - req.Labels[k] = v - } + // Add the labels that identify this as a testcontainers container and + // allow the reaper to terminate it if requested. + AddGenericLabels(req.Labels) } dockerInput := &container.Config{ @@ -1205,9 +1203,6 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque return nil, err } - // Disable cleanup on success - termSignal = nil - return c, nil } @@ -1256,7 +1251,7 @@ func (p *DockerProvider) waitContainerCreation(ctx context.Context, name string) ) } -func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req ContainerRequest) (Container, error) { +func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req ContainerRequest) (con Container, err error) { //nolint:nonamedreturns // Needed for error check. c, err := p.findContainerByName(ctx, req.Name) if err != nil { return nil, err @@ -1279,14 +1274,22 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain var termSignal chan bool if !p.config.RyukDisabled { - r, err := reuseOrCreateReaper(context.WithValue(ctx, core.DockerHostContextKey, p.host), sessionID, p) + r, err := spawner.reaper(context.WithValue(ctx, core.DockerHostContextKey, p.host), sessionID, p) if err != nil { return nil, fmt.Errorf("reaper: %w", err) } - termSignal, err = r.Connect() + + termSignal, err := r.Connect() if err != nil { - return nil, fmt.Errorf("%w: connecting to reaper failed", err) + return nil, fmt.Errorf("reaper connect: %w", err) } + + // Cleanup on error. + defer func() { + if err != nil { + termSignal <- true + } + }() } // default hooks include logger hook and pre-create hook @@ -1454,9 +1457,7 @@ func daemonHost(ctx context.Context, p *DockerProvider) (string, error) { // Deprecated: use network.New instead // CreateNetwork returns the object representing a new network identified by its name -func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) (Network, error) { - var err error - +func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) (net Network, err error) { //nolint:nonamedreturns // Needed for error check. // defer the close of the Docker client connection the soonest defer p.Close() @@ -1485,31 +1486,30 @@ func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) var termSignal chan bool if !p.config.RyukDisabled { - r, err := reuseOrCreateReaper(context.WithValue(ctx, core.DockerHostContextKey, p.host), sessionID, p) + r, err := spawner.reaper(context.WithValue(ctx, core.DockerHostContextKey, p.host), sessionID, p) if err != nil { - return nil, fmt.Errorf("%w: creating network reaper failed", err) + return nil, fmt.Errorf("reaper: %w", err) } - termSignal, err = r.Connect() + + termSignal, err := r.Connect() if err != nil { - return nil, fmt.Errorf("%w: connecting to network reaper failed", err) + return nil, fmt.Errorf("reaper connect: %w", err) } - } - // add the labels that the reaper will use to terminate the network to the request - for k, v := range core.DefaultLabels(sessionID) { - req.Labels[k] = v + // Cleanup on error. + defer func() { + if err != nil { + termSignal <- true + } + }() } - // Cleanup on error, otherwise set termSignal to nil before successful return. - defer func() { - if termSignal != nil { - termSignal <- true - } - }() + // add the labels that the reaper will use to terminate the network to the request + core.AddDefaultLabels(sessionID, req.Labels) response, err := p.client.NetworkCreate(ctx, req.Name, nc) if err != nil { - return &DockerNetwork{}, err + return &DockerNetwork{}, fmt.Errorf("create network: %w", err) } n := &DockerNetwork{ @@ -1520,9 +1520,6 @@ func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) provider: p, } - // Disable cleanup on success - termSignal = nil - return n, nil } @@ -1592,9 +1589,12 @@ func (p *DockerProvider) getDefaultNetwork(ctx context.Context, cli client.APICl _, err = cli.NetworkCreate(ctx, reaperNetwork, network.CreateOptions{ Driver: Bridge, Attachable: true, - Labels: core.DefaultLabels(core.SessionID()), + Labels: GenericLabels(), }) - if err != nil { + // If the network already exists, we can ignore the error as that can + // happen if we are running multiple tests in parallel and we only + // need to ensure that the network exists. + if err != nil && !errdefs.IsConflict(err) { return "", err } } @@ -1632,7 +1632,7 @@ func containerFromDockerResponse(ctx context.Context, response types.Container) // populate the raw representation of the container jsonRaw, err := ctr.inspectRawContainer(ctx) if err != nil { - return nil, err + return nil, fmt.Errorf("inspect raw container: %w", err) } // the health status of the container, if any diff --git a/docker_mounts.go b/docker_mounts.go index aed3010361..d8af3fae3e 100644 --- a/docker_mounts.go +++ b/docker_mounts.go @@ -126,9 +126,7 @@ func mapToDockerMounts(containerMounts ContainerMounts) []mount.Mount { Labels: make(map[string]string), } } - for k, v := range GenericLabels() { - containerMount.VolumeOptions.Labels[k] = v - } + AddGenericLabels(containerMount.VolumeOptions.Labels) } mounts = append(mounts, containerMount) diff --git a/generic.go b/generic.go index 9052287b51..fd13a607de 100644 --- a/generic.go +++ b/generic.go @@ -101,7 +101,17 @@ type GenericProvider interface { ImageProvider } -// GenericLabels returns a map of labels that can be used to identify containers created by this library +// GenericLabels returns a map of labels that can be used to identify resources +// created by this library. This includes the standard LabelSessionID if the +// reaper is enabled, otherwise this is excluded to prevent resources being +// incorrectly reaped. func GenericLabels() map[string]string { return core.DefaultLabels(core.SessionID()) } + +// AddGenericLabels adds the generic labels to target. +func AddGenericLabels(target map[string]string) { + for k, v := range GenericLabels() { + target[k] = v + } +} diff --git a/internal/core/labels.go b/internal/core/labels.go index b5da2fb29d..0814924234 100644 --- a/internal/core/labels.go +++ b/internal/core/labels.go @@ -6,23 +6,53 @@ import ( "strings" "github.com/testcontainers/testcontainers-go/internal" + "github.com/testcontainers/testcontainers-go/internal/config" ) const ( - LabelBase = "org.testcontainers" - LabelLang = LabelBase + ".lang" - LabelReaper = LabelBase + ".reaper" - LabelRyuk = LabelBase + ".ryuk" + // LabelBase is the base label for all testcontainers labels. + LabelBase = "org.testcontainers" + + // LabelLang specifies the language which created the test container. + LabelLang = LabelBase + ".lang" + + // LabelReaper identifies the container as a reaper. + LabelReaper = LabelBase + ".reaper" + + // LabelRyuk identifies the container as a ryuk. + LabelRyuk = LabelBase + ".ryuk" + + // LabelSessionID specifies the session ID of the container. LabelSessionID = LabelBase + ".sessionId" - LabelVersion = LabelBase + ".version" + + // LabelVersion specifies the version of testcontainers which created the container. + LabelVersion = LabelBase + ".version" + + // LabelReap specifies the container should be reaped by the reaper. + LabelReap = LabelBase + ".reap" ) +// DefaultLabels returns the standard set of labels which +// includes LabelSessionID if the reaper is enabled. func DefaultLabels(sessionID string) map[string]string { - return map[string]string{ + labels := map[string]string{ LabelBase: "true", LabelLang: "go", - LabelSessionID: sessionID, LabelVersion: internal.Version, + LabelSessionID: sessionID, + } + + if !config.Read().RyukDisabled { + labels[LabelReap] = "true" + } + + return labels +} + +// AddDefaultLabels adds the default labels for sessionID to target. +func AddDefaultLabels(sessionID string, target map[string]string) { + for k, v := range DefaultLabels(sessionID) { + target[k] = v } } diff --git a/lifecycle.go b/lifecycle.go index ff1472d043..57833dafc1 100644 --- a/lifecycle.go +++ b/lifecycle.go @@ -33,7 +33,7 @@ type ContainerRequestHook func(ctx context.Context, req ContainerRequest) error // - Terminating // - Terminated // For that, it will receive a Container, modify it and return an error if needed. -type ContainerHook func(ctx context.Context, container Container) error +type ContainerHook func(ctx context.Context, ctr Container) error // ContainerLifecycleHooks is a struct that contains all the hooks that can be used // to modify the container lifecycle. All the container lifecycle hooks except the PreCreates hooks diff --git a/modules/compose/compose.go b/modules/compose/compose.go index c63eb73bb1..fa02cde077 100644 --- a/modules/compose/compose.go +++ b/modules/compose/compose.go @@ -153,23 +153,6 @@ func NewDockerComposeWith(opts ...ComposeStackOption) (*dockerCompose, error) { return nil, fmt.Errorf("initialize docker client: %w", err) } - reaperProvider, err := testcontainers.NewDockerProvider() - if err != nil { - return nil, fmt.Errorf("failed to create reaper provider for compose: %w", err) - } - - var composeReaper *testcontainers.Reaper - if !reaperProvider.Config().Config.RyukDisabled { - // NewReaper is deprecated: we need to find a way to create the reaper for compose - // bypassing the deprecation. - r, err := testcontainers.NewReaper(context.Background(), testcontainers.SessionID(), reaperProvider, "") - if err != nil { - return nil, fmt.Errorf("failed to create reaper for compose: %w", err) - } - - composeReaper = r - } - composeAPI := &dockerCompose{ name: composeOptions.Identifier, configs: composeOptions.Paths, @@ -182,7 +165,6 @@ func NewDockerComposeWith(opts ...ComposeStackOption) (*dockerCompose, error) { containers: make(map[string]*testcontainers.DockerContainer), networks: make(map[string]*testcontainers.DockerNetwork), sessionID: testcontainers.SessionID(), - reaper: composeReaper, } return composeAPI, nil diff --git a/modules/compose/compose_api.go b/modules/compose/compose_api.go index 9f21d09e87..2c852bdaff 100644 --- a/modules/compose/compose_api.go +++ b/modules/compose/compose_api.go @@ -2,6 +2,7 @@ package compose import ( "context" + "errors" "fmt" "io" "os" @@ -228,9 +229,6 @@ type dockerCompose struct { // sessionID is used to identify the reaper session sessionID string - - // reaper is used to clean up containers after the stack is stopped - reaper *testcontainers.Reaper } func (d *dockerCompose) ServiceContainer(ctx context.Context, svcName string) (*testcontainers.DockerContainer, error) { @@ -269,12 +267,10 @@ func (d *dockerCompose) Down(ctx context.Context, opts ...StackDownOption) error return d.composeService.Down(ctx, d.name, options.DownOptions) } -func (d *dockerCompose) Up(ctx context.Context, opts ...StackUpOption) error { +func (d *dockerCompose) Up(ctx context.Context, opts ...StackUpOption) (err error) { d.lock.Lock() defer d.lock.Unlock() - var err error - d.project, err = d.compileProject(ctx) if err != nil { return err @@ -329,27 +325,61 @@ func (d *dockerCompose) Up(ctx context.Context, opts ...StackUpOption) error { return err } - if d.reaper != nil { + provider, err := testcontainers.NewDockerProvider(testcontainers.WithLogger(d.logger)) + if err != nil { + return fmt.Errorf("new docker provider: %w", err) + } + + var termSignals []chan bool + var reaper *testcontainers.Reaper + if !provider.Config().Config.RyukDisabled { + // NewReaper is deprecated: we need to find a way to create the reaper for compose + // bypassing the deprecation. + reaper, err = testcontainers.NewReaper(ctx, testcontainers.SessionID(), provider, "") + if err != nil { + return fmt.Errorf("create reaper: %w", err) + } + + // Cleanup on error, otherwise set termSignal to nil before successful return. + defer func() { + if len(termSignals) == 0 { + // Need to call Connect at least once to ensure the initial + // connection is cleaned up. + termSignal, errc := reaper.Connect() + if errc != nil { + err = errors.Join(err, fmt.Errorf("reaper connect: %w", errc)) + } else { + termSignal <- true + } + } + + if err == nil { + // No need to cleanup. + return + } + + for _, ts := range termSignals { + ts <- true + } + }() + + // Connect to the reaper and set the termination signal for each network. for _, n := range d.networks { - termSignal, err := d.reaper.Connect() + termSignal, err := reaper.Connect() if err != nil { - return fmt.Errorf("failed to connect to reaper: %w", err) + return fmt.Errorf("reaper connect: %w", err) } - n.SetTerminationSignal(termSignal) - // Cleanup on error, otherwise set termSignal to nil before successful return. - defer func() { - if termSignal != nil { - termSignal <- true - } - }() + n.SetTerminationSignal(termSignal) + termSignals = append(termSignals, termSignal) } } errGrpContainers, errGrpCtx := errgroup.WithContext(ctx) + // Lookup the containers for each service and connect them + // to the reaper if needed. for _, srv := range d.project.Services { - // we are going to connect each container to the reaper srv := srv errGrpContainers.Go(func() error { dc, err := d.lookupContainer(errGrpCtx, srv.Name) @@ -357,19 +387,14 @@ func (d *dockerCompose) Up(ctx context.Context, opts ...StackUpOption) error { return err } - if d.reaper != nil { - termSignal, err := d.reaper.Connect() + if reaper != nil { + termSignal, err := reaper.Connect() if err != nil { - return fmt.Errorf("failed to connect to reaper: %w", err) + return fmt.Errorf("reaper connect: %w", err) } - dc.SetTerminationSignal(termSignal) - // Cleanup on error, otherwise set termSignal to nil before successful return. - defer func() { - if termSignal != nil { - termSignal <- true - } - }() + dc.SetTerminationSignal(termSignal) + termSignals = append(termSignals, termSignal) } return nil @@ -401,7 +426,11 @@ func (d *dockerCompose) Up(ctx context.Context, opts ...StackUpOption) error { }) } - return errGrpWait.Wait() + if err := errGrpWait.Wait(); err != nil { + return fmt.Errorf("wait for services: %w", err) + } + + return nil } func (d *dockerCompose) WaitForService(s string, strategy wait.Strategy) ComposeStack { @@ -486,6 +515,9 @@ func (d *dockerCompose) lookupContainer(ctx context.Context, svcName string) (*t return ctr, nil } +// lookupNetworks is used to retrieve the networks that are part of the compose stack. +// +// Safe for concurrent calls. func (d *dockerCompose) lookupNetworks(ctx context.Context) error { networks, err := d.dockerClient.NetworkList(ctx, dockernetwork.ListOptions{ Filters: filters.NewArgs( @@ -543,9 +575,7 @@ func (d *dockerCompose) compileProject(ctx context.Context) (*types.Project, err api.OneoffLabel: "False", // default, will be overridden by `run` command } - for k, label := range testcontainers.GenericLabels() { - s.CustomLabels[k] = label - } + testcontainers.AddGenericLabels(s.CustomLabels) for i, envFile := range compiledOptions.EnvFiles { // add a label for each env file, indexed by its position @@ -562,9 +592,7 @@ func (d *dockerCompose) compileProject(ctx context.Context) (*types.Project, err api.VersionLabel: api.ComposeVersion, } - for k, label := range testcontainers.GenericLabels() { - n.Labels[k] = label - } + testcontainers.AddGenericLabels(n.Labels) proj.Networks[key] = n } diff --git a/modules/compose/compose_api_test.go b/modules/compose/compose_api_test.go index 9a0a4841b1..e5f30a5257 100644 --- a/modules/compose/compose_api_test.go +++ b/modules/compose/compose_api_test.go @@ -48,8 +48,7 @@ func TestDockerComposeAPIStrategyForInvalidService(t *testing.T) { WaitForService("non-existent-srv-1", wait.NewLogStrategy("started").WithStartupTimeout(10*time.Second).WithOccurrence(1)). Up(ctx, Wait(true)) cleanup(t, compose) - require.Error(t, err, "Expected error to be thrown because service with wait strategy is not running") - require.Equal(t, "no container found for service name non-existent-srv-1", err.Error()) + require.EqualError(t, err, "wait for services: no container found for service name non-existent-srv-1") serviceNames := compose.Services() diff --git a/reaper.go b/reaper.go index c41520b5b7..8f2bde8ab6 100644 --- a/reaper.go +++ b/reaper.go @@ -1,13 +1,16 @@ package testcontainers import ( - "bufio" + "bytes" "context" + "errors" "fmt" - "math/rand" + "io" "net" + "os" "strings" "sync" + "syscall" "time" "github.com/cenkalti/backoff/v4" @@ -34,9 +37,23 @@ const ( var ( // Deprecated: it has been replaced by an internal value ReaperDefaultImage = config.ReaperDefaultImage - reaperInstance *Reaper // We would like to create reaper only once - reaperMutex sync.Mutex - reaperOnce sync.Once + + // defaultReaperPort is the default port that the reaper listens on if not + // overridden by the RYUK_PORT environment variable. + defaultReaperPort = nat.Port("8080/tcp") + + // errReaperNotFound is returned when no reaper container is found. + errReaperNotFound = errors.New("reaper not found") + + // errReaperDisabled is returned if a reaper is requested but the + // config has it disabled. + errReaperDisabled = errors.New("reaper disabled") + + // spawner is the singleton instance of reaperSpawner. + spawner = &reaperSpawner{} + + // reaperAck is the expected response from the reaper container. + reaperAck = []byte("ACK\n") ) // ReaperProvider represents a provider for the reaper to run itself with @@ -47,10 +64,18 @@ type ReaperProvider interface { } // NewReaper creates a Reaper with a sessionID to identify containers and a provider to use -// Deprecated: it's not possible to create a reaper anymore. Compose module uses this method +// Deprecated: it's not possible to create a reaper any more. Compose module uses this method // to create a reaper for the compose stack. +// +// The caller must call Connect at least once on the returned Reaper and use the returned +// result otherwise the reaper will be kept open until the process exits. func NewReaper(ctx context.Context, sessionID string, provider ReaperProvider, reaperImageName string) (*Reaper, error) { - return reuseOrCreateReaper(ctx, sessionID, provider) + reaper, err := spawner.reaper(ctx, sessionID, provider) + if err != nil { + return nil, fmt.Errorf("reaper: %w", err) + } + + return reaper, nil } // reaperContainerNameFromSessionID returns the container name that uniquely @@ -61,31 +86,80 @@ func reaperContainerNameFromSessionID(sessionID string) string { return fmt.Sprintf("reaper_%s", sessionID) } -// lookUpReaperContainer returns a DockerContainer type with the reaper container in the case -// it's found in the running state, and including the labels for sessionID, reaper, and ryuk. -// It will perform a retry with exponential backoff to allow for the container to be started and -// avoid potential false negatives. -func lookUpReaperContainer(ctx context.Context, sessionID string) (*DockerContainer, error) { - dockerClient, err := NewDockerClientWithOpts(ctx) - if err != nil { - return nil, err +// reaperSpawner is a singleton that manages the reaper container. +type reaperSpawner struct { + instance *Reaper + mtx sync.Mutex +} + +// port returns the port that a new reaper should listens on. +func (r *reaperSpawner) port() nat.Port { + if port := os.Getenv("RYUK_PORT"); port != "" { + natPort, err := nat.NewPort("tcp", port) + if err != nil { + panic(fmt.Sprintf("invalid RYUK_PORT value %q: %s", port, err)) + } + return natPort } - defer dockerClient.Close() - // the backoff will take at most 5 seconds to find the reaper container - // doing each attempt every 100ms - exp := backoff.NewExponentialBackOff() + return defaultReaperPort +} - // we want random intervals between 100ms and 500ms for concurrent executions +// backoff returns a backoff policy for the reaper spawner. +// It will take at most 20 seconds, doing each attempt every 100ms - 250ms. +func (r *reaperSpawner) backoff() *backoff.ExponentialBackOff { + // We want random intervals between 100ms and 250ms for concurrent executions // to not be synchronized: it could be the case that multiple executions of this // function happen at the same time (specifically when called from a different test // process execution), and we want to avoid that they all try to find the reaper // container at the same time. - exp.InitialInterval = time.Duration(rand.Intn(5)*100) * time.Millisecond - exp.RandomizationFactor = rand.Float64() * 0.5 - exp.Multiplier = rand.Float64() * 2.0 - exp.MaxInterval = 5.0 * time.Second // max interval between attempts - exp.MaxElapsedTime = 1 * time.Minute // max time to keep trying + b := &backoff.ExponentialBackOff{ + InitialInterval: time.Millisecond * 100, + RandomizationFactor: backoff.DefaultRandomizationFactor, + Multiplier: backoff.DefaultMultiplier, + // Adjust MaxInterval to compensate for randomization factor which can be added to + // returned interval so we have a maximum of 250ms. + MaxInterval: time.Duration(float64(time.Millisecond*250) * backoff.DefaultRandomizationFactor), + MaxElapsedTime: time.Second * 20, + Stop: backoff.Stop, + Clock: backoff.SystemClock, + } + b.Reset() + + return b +} + +// cleanup terminates the reaper container if set. +func (r *reaperSpawner) cleanup() error { + r.mtx.Lock() + defer r.mtx.Unlock() + + return r.cleanupLocked() +} + +// cleanupLocked terminates the reaper container if set. +// It must be called with the lock held. +func (r *reaperSpawner) cleanupLocked() error { + if r.instance == nil { + return nil + } + + err := TerminateContainer(r.instance.container) + r.instance = nil + + return err +} + +// lookupContainer returns a DockerContainer type with the reaper container in the case +// it's found in the running state, and including the labels for sessionID, reaper, and ryuk. +// It will perform a retry with exponential backoff to allow for the container to be started and +// avoid potential false negatives. +func (r *reaperSpawner) lookupContainer(ctx context.Context, sessionID string) (*DockerContainer, error) { + dockerClient, err := NewDockerClientWithOpts(ctx) + if err != nil { + return nil, fmt.Errorf("new client: %w", err) + } + defer dockerClient.Close() opts := container.ListOptions{ All: true, @@ -97,159 +171,212 @@ func lookUpReaperContainer(ctx context.Context, sessionID string) (*DockerContai ), } - return backoff.RetryNotifyWithData( + return backoff.RetryWithData( func() (*DockerContainer, error) { resp, err := dockerClient.ContainerList(ctx, opts) if err != nil { - return nil, err + return nil, fmt.Errorf("container list: %w", err) } if len(resp) == 0 { - // reaper container not found in the running state: do not look for it again - return nil, nil + // No reaper container not found. + return nil, backoff.Permanent(errReaperNotFound) } if len(resp) > 1 { - return nil, fmt.Errorf("not possible to have multiple reaper containers found for session ID %s", sessionID) + return nil, fmt.Errorf("multiple reaper containers found for session ID %s", sessionID) } - r, err := containerFromDockerResponse(ctx, resp[0]) + container := resp[0] + r, err := containerFromDockerResponse(ctx, container) if err != nil { - return nil, err + return nil, fmt.Errorf("from docker: %w", err) } - if r.healthStatus == types.Healthy || r.healthStatus == types.NoHealthcheck { + switch { + case r.healthStatus == types.Healthy, + r.healthStatus == types.NoHealthcheck: return r, nil - } - - // if a health status is present on the container, and the container is healthy, error - if r.healthStatus != "" { - return nil, fmt.Errorf("container %s is not healthy, wanted status=%s, got status=%s", resp[0].ID[:8], types.Healthy, r.healthStatus) + case r.healthStatus != "": + return nil, fmt.Errorf("container not healthy: %s", r.healthStatus) } return r, nil }, - backoff.WithContext(exp, ctx), - func(err error, duration time.Duration) { - Logger.Printf("Error looking up reaper container, will retry: %v", err) - }, + backoff.WithContext(r.backoff(), ctx), ) } -// reuseOrCreateReaper returns an existing Reaper instance if it exists and is running. Otherwise, a new Reaper instance -// will be created with a sessionID to identify containers in the same test session/program. -func reuseOrCreateReaper(ctx context.Context, sessionID string, provider ReaperProvider) (*Reaper, error) { - reaperMutex.Lock() - defer reaperMutex.Unlock() - - // 1. if the reaper instance has been already created, return it - if reaperInstance != nil { - // Verify this instance is still running by checking state. - // Can't use Container.IsRunning because the bool is not updated when Reaper is terminated - state, err := reaperInstance.container.State(ctx) - if err != nil { - if !errdefs.IsNotFound(err) { - return nil, err +// isRunning returns an error if the container is not running. +func (r *reaperSpawner) isRunning(ctx context.Context, ctr Container) error { + state, err := ctr.State(ctx) + if err != nil { + return fmt.Errorf("container state: %w", err) + } + + if !state.Running { + // Use NotFound error to indicate the container is not running + // and should be recreated. + return errdefs.NotFound(fmt.Errorf("container state: %s", state.Status)) + } + + return nil +} + +// retryError returns a permanent error if the error is not considered retryable. +func (r *reaperSpawner) retryError(err error) error { + var timeout interface { + Timeout() bool + } + switch { + case isCleanupSafe(err), + createContainerFailDueToNameConflictRegex.MatchString(err.Error()), + errors.Is(err, syscall.ECONNREFUSED), + errors.Is(err, syscall.ECONNRESET), + errors.Is(err, syscall.ECONNABORTED), + errors.Is(err, syscall.ETIMEDOUT), + errors.Is(err, os.ErrDeadlineExceeded), + errors.As(err, &timeout) && timeout.Timeout(), + errors.Is(err, context.DeadlineExceeded), + errors.Is(err, context.Canceled): + // Retryable error. + return err + default: + return backoff.Permanent(err) + } +} + +// reaper returns an existing Reaper instance if it exists and is running, otherwise +// a new Reaper instance will be created with a sessionID to identify containers in +// the same test session/program. If connect is true, the reaper will be connected +// to the reaper container. +// Returns an error if config.RyukDisabled is true. +// +// Safe for concurrent calls. +func (r *reaperSpawner) reaper(ctx context.Context, sessionID string, provider ReaperProvider) (*Reaper, error) { + if config.Read().RyukDisabled { + return nil, errReaperDisabled + } + + r.mtx.Lock() + defer r.mtx.Unlock() + + return backoff.RetryWithData( + r.retryLocked(ctx, sessionID, provider), + backoff.WithContext(r.backoff(), ctx), + ) +} + +// retryLocked returns a function that can be used to create or reuse a reaper container. +// If connect is true, the reaper will be connected to the reaper container. +// It must be called with the lock held. +func (r *reaperSpawner) retryLocked(ctx context.Context, sessionID string, provider ReaperProvider) func() (*Reaper, error) { + return func() (reaper *Reaper, err error) { //nolint:nonamedreturns // Needed for deferred error check. + reaper, err = r.reuseOrCreate(ctx, sessionID, provider) + // Ensure that the reaper is terminated if an error occurred. + defer func() { + if err != nil { + if reaper != nil { + err = errors.Join(err, TerminateContainer(reaper.container)) + } + err = r.retryError(errors.Join(err, r.cleanupLocked())) } - } else if state.Running { - return reaperInstance, nil - } - // else: the reaper instance has been terminated, so we need to create a new one - reaperOnce = sync.Once{} - } - - // 2. because the reaper instance has not been created yet, look for it in the Docker daemon, which - // will happen if the reaper container has been created in the same test session but in a different - // test process execution (e.g. when running tests in parallel), not having initialized the reaper - // instance yet. - reaperContainer, err := lookUpReaperContainer(context.Background(), sessionID) - if err == nil && reaperContainer != nil { - // The reaper container exists as a Docker container: re-use it - Logger.Printf("🔥 Reaper obtained from Docker for this test session %s", reaperContainer.ID) - reaperInstance, err = reuseReaperContainer(ctx, sessionID, provider, reaperContainer) + }() if err != nil { return nil, err } - return reaperInstance, nil - } + if err = r.isRunning(ctx, reaper.container); err != nil { + return nil, err + } - // 3. the reaper container does not exist in the Docker daemon: create it, and do it using the - // synchronization primitive to avoid multiple executions of this function to create the reaper - var reaperErr error - reaperOnce.Do(func() { - r, err := newReaper(ctx, sessionID, provider) + // Check we can still connect. + termSignal, err := reaper.connect(ctx) if err != nil { - reaperErr = err - return + return nil, fmt.Errorf("connect: %w", err) } - reaperInstance, reaperErr = r, nil - }) - if reaperErr != nil { - reaperOnce = sync.Once{} - return nil, reaperErr - } + reaper.setOrSignal(termSignal) + + r.instance = reaper - return reaperInstance, nil + return reaper, nil + } } -// reuseReaperContainer constructs a Reaper from an already running reaper -// DockerContainer. -func reuseReaperContainer(ctx context.Context, sessionID string, provider ReaperProvider, reaperContainer *DockerContainer) (*Reaper, error) { - endpoint, err := reaperContainer.PortEndpoint(ctx, "8080", "") +// reuseOrCreate returns an existing Reaper instance if it exists, otherwise a new Reaper instance. +func (r *reaperSpawner) reuseOrCreate(ctx context.Context, sessionID string, provider ReaperProvider) (*Reaper, error) { + if r.instance != nil { + // We already have an associated reaper. + return r.instance, nil + } + + // Look for an existing reaper created in the same test session but in a + // different test process execution e.g. when running tests in parallel. + container, err := r.lookupContainer(context.Background(), sessionID) if err != nil { - return nil, err + if !errors.Is(err, errReaperNotFound) { + return nil, fmt.Errorf("look up container: %w", err) + } + + // The reaper container was not found, continue to create a new one. + reaper, err := r.newReaper(ctx, sessionID, provider) + if err != nil { + return nil, fmt.Errorf("new reaper: %w", err) + } + + return reaper, nil } - Logger.Printf("⏳ Waiting for Reaper port to be ready") + // A reaper container exists re-use it. + reaper, err := r.fromContainer(ctx, sessionID, provider, container) + if err != nil { + return nil, fmt.Errorf("from container %q: %w", container.ID[:8], err) + } + + return reaper, nil +} - var containerJson *types.ContainerJSON +// fromContainer constructs a Reaper from an already running reaper DockerContainer. +func (r *reaperSpawner) fromContainer(ctx context.Context, sessionID string, provider ReaperProvider, dockerContainer *DockerContainer) (*Reaper, error) { + Logger.Printf("⏳ Waiting for Reaper %q to be ready", dockerContainer.ID[:8]) - if containerJson, err = reaperContainer.Inspect(ctx); err != nil { - return nil, fmt.Errorf("failed to inspect reaper container %s: %w", reaperContainer.ID[:8], err) + // Reusing an existing container so we determine the port from the container's exposed ports. + if err := wait.ForExposedPort(). + WithPollInterval(100*time.Millisecond). + SkipInternalCheck(). + WaitUntilReady(ctx, dockerContainer); err != nil { + return nil, fmt.Errorf("wait for reaper %s: %w", dockerContainer.ID[:8], err) } - if containerJson != nil && containerJson.NetworkSettings != nil { - for port := range containerJson.NetworkSettings.Ports { - err := wait.ForListeningPort(port). - WithPollInterval(100*time.Millisecond). - WaitUntilReady(ctx, reaperContainer) - if err != nil { - return nil, fmt.Errorf("failed waiting for reaper container %s port %s/%s to be ready: %w", - reaperContainer.ID[:8], port.Proto(), port.Port(), err) - } - } + endpoint, err := dockerContainer.Endpoint(ctx, "") + if err != nil { + return nil, fmt.Errorf("port endpoint: %w", err) } + Logger.Printf("🔥 Reaper obtained from Docker for this test session %s", dockerContainer.ID[:8]) + return &Reaper{ Provider: provider, SessionID: sessionID, Endpoint: endpoint, - container: reaperContainer, + container: dockerContainer, }, nil } -// newReaper creates a Reaper with a sessionID to identify containers and a -// provider to use. Do not call this directly, use reuseOrCreateReaper instead. -func newReaper(ctx context.Context, sessionID string, provider ReaperProvider) (*Reaper, error) { +// newReaper creates a connected Reaper with a sessionID to identify containers +// and a provider to use. +func (r *reaperSpawner) newReaper(ctx context.Context, sessionID string, provider ReaperProvider) (reaper *Reaper, err error) { //nolint:nonamedreturns // Needed for deferred error check. dockerHostMount := core.MustExtractDockerSocket(ctx) - reaper := &Reaper{ - Provider: provider, - SessionID: sessionID, - } - - listeningPort := nat.Port("8080/tcp") - + port := r.port() tcConfig := provider.Config().Config - req := ContainerRequest{ Image: config.ReaperDefaultImage, - ExposedPorts: []string{string(listeningPort)}, + ExposedPorts: []string{string(port)}, Labels: core.DefaultLabels(sessionID), Privileged: tcConfig.RyukPrivileged, - WaitingFor: wait.ForListeningPort(listeningPort), + WaitingFor: wait.ForListeningPort(port), Name: reaperContainerNameFromSessionID(sessionID), HostConfigModifier: func(hc *container.HostConfig) { hc.AutoRemove = true @@ -268,9 +395,10 @@ func newReaper(ctx context.Context, sessionID string, provider ReaperProvider) ( req.Env["RYUK_VERBOSE"] = "true" } - // include reaper-specific labels to the reaper container + // Setup reaper-specific labels for the reaper container. req.Labels[core.LabelReaper] = "true" req.Labels[core.LabelRyuk] = "true" + delete(req.Labels, core.LabelReap) // Attach reaper container to a requested network if it is specified if p, ok := provider.(*DockerProvider); ok { @@ -278,123 +406,158 @@ func newReaper(ctx context.Context, sessionID string, provider ReaperProvider) ( } c, err := provider.RunContainer(ctx, req) - if err != nil { - // We need to check whether the error is caused by a container with the same name - // already existing due to race conditions. We manually match the error message - // as we do not have any error types to check against. - if createContainerFailDueToNameConflictRegex.MatchString(err.Error()) { - // Manually retrieve the already running reaper container. However, we need to - // use retries here as there are two possible race conditions that might lead to - // errors: In most cases, there is a small delay between container creation and - // actually being visible in list-requests. This means that creation might fail - // due to name conflicts, but when we list containers with this name, we do not - // get any results. In another case, the container might have simply died in the - // meantime and therefore cannot be found. - const timeout = 5 * time.Second - const cooldown = 100 * time.Millisecond - start := time.Now() - var reaperContainer *DockerContainer - for time.Since(start) < timeout { - reaperContainer, err = lookUpReaperContainer(ctx, sessionID) - if err == nil && reaperContainer != nil { - break - } - select { - case <-ctx.Done(): - case <-time.After(cooldown): - } - } - if err != nil { - return nil, fmt.Errorf("look up reaper container due to name conflict failed: %w", err) - } - // If the reaper container was not found, it is most likely to have died in - // between as we can exclude any client errors because of the previous error - // check. Because the reaper should only die if it performed clean-ups, we can - // fail here as the reaper timeout needs to be increased, anyway. - if reaperContainer == nil { - return nil, fmt.Errorf("look up reaper container returned nil although creation failed due to name conflict") - } - Logger.Printf("🔥 Reaper obtained from Docker for this test session %s", reaperContainer.ID) - reaper, err := reuseReaperContainer(ctx, sessionID, provider, reaperContainer) - if err != nil { - return nil, err - } - return reaper, nil + defer func() { + if err != nil { + err = errors.Join(err, TerminateContainer(c)) } - return nil, err + }() + if err != nil { + return nil, fmt.Errorf("run container: %w", err) } - reaper.container = c - endpoint, err := c.PortEndpoint(ctx, "8080", "") + endpoint, err := c.PortEndpoint(ctx, port, "") if err != nil { - return nil, err + return nil, fmt.Errorf("port endpoint: %w", err) } - reaper.Endpoint = endpoint - return reaper, nil + return &Reaper{ + Provider: provider, + SessionID: sessionID, + Endpoint: endpoint, + container: c, + }, nil } // Reaper is used to start a sidecar container that cleans up resources type Reaper struct { - Provider ReaperProvider - SessionID string - Endpoint string - container Container + Provider ReaperProvider + SessionID string + Endpoint string + container Container + mtx sync.Mutex // Protects termSignal. + termSignal chan bool } -// Connect runs a goroutine which can be terminated by sending true into the returned channel +// Connect connects to the reaper container and sends the labels to it +// so that it can clean up the containers with the same labels. +// +// It returns a channel that can be closed to terminate the connection. +// Returns an error if config.RyukDisabled is true. func (r *Reaper) Connect() (chan bool, error) { - conn, err := net.DialTimeout("tcp", r.Endpoint, 10*time.Second) - if err != nil { - return nil, fmt.Errorf("%w: Connecting to Ryuk on %s failed", err, r.Endpoint) + if config.Read().RyukDisabled { + return nil, errReaperDisabled } - terminationSignal := make(chan bool) - go func(conn net.Conn) { - sock := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) - defer conn.Close() + if termSignal := r.useTermSignal(); termSignal != nil { + return termSignal, nil + } - labelFilters := []string{} - for l, v := range core.DefaultLabels(r.SessionID) { - labelFilters = append(labelFilters, fmt.Sprintf("label=%s=%s", l, v)) - } + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() - retryLimit := 3 - for retryLimit > 0 { - retryLimit-- + return r.connect(ctx) +} - if _, err := sock.WriteString(strings.Join(labelFilters, "&")); err != nil { - continue - } +// close signals the connection to close if needed. +// Safe for concurrent calls. +func (r *Reaper) close() { + r.mtx.Lock() + defer r.mtx.Unlock() - if _, err := sock.WriteString("\n"); err != nil { - continue - } + if r.termSignal != nil { + r.termSignal <- true + r.termSignal = nil + } +} - if err := sock.Flush(); err != nil { - continue - } +// setOrSignal sets the reapers termSignal field if nil +// otherwise consumes by sending true to it. +// Safe for concurrent calls. +func (r *Reaper) setOrSignal(termSignal chan bool) { + r.mtx.Lock() + defer r.mtx.Unlock() + + if r.termSignal != nil { + // Already have an existing connection, close the new one. + termSignal <- true + return + } - resp, err := sock.ReadString('\n') - if err != nil { - continue - } + // First or new unused termSignal, assign for caller to reuse. + r.termSignal = termSignal +} - if resp == "ACK\n" { - break - } - } +// useTermSignal if termSignal is not nil returns it +// and sets it to nil, otherwise returns nil. +// +// Safe for concurrent calls. +func (r *Reaper) useTermSignal() chan bool { + r.mtx.Lock() + defer r.mtx.Unlock() + + if r.termSignal == nil { + return nil + } + + // Use existing connection. + term := r.termSignal + r.termSignal = nil + + return term +} +// connect connects to the reaper container and sends the labels to it +// so that it can clean up the containers with the same labels. +// +// It returns a channel that can be sent true to terminate the connection. +// Returns an error if config.RyukDisabled is true. +func (r *Reaper) connect(ctx context.Context) (chan bool, error) { + var d net.Dialer + conn, err := d.DialContext(ctx, "tcp", r.Endpoint) + if err != nil { + return nil, fmt.Errorf("dial reaper %s: %w", r.Endpoint, err) + } + + terminationSignal := make(chan bool) + go func() { + defer conn.Close() + if err := r.handshake(conn); err != nil { + Logger.Printf("Reaper handshake failed: %s", err) + } <-terminationSignal - }(conn) + }() return terminationSignal, nil } +// handshake sends the labels to the reaper container and reads the ACK. +func (r *Reaper) handshake(conn net.Conn) error { + labels := core.DefaultLabels(r.SessionID) + labelFilters := make([]string, 0, len(labels)) + for l, v := range labels { + labelFilters = append(labelFilters, fmt.Sprintf("label=%s=%s", l, v)) + } + + filters := []byte(strings.Join(labelFilters, "&") + "\n") + buf := make([]byte, 4) + if _, err := conn.Write(filters); err != nil { + return fmt.Errorf("writing filters: %w", err) + } + + n, err := io.ReadFull(conn, buf) + if err != nil { + return fmt.Errorf("read ack: %w", err) + } + + if !bytes.Equal(reaperAck, buf[:n]) { + // We have received the ACK so all done. + return fmt.Errorf("unexpected reaper response: %s", buf[:n]) + } + + return nil +} + // Labels returns the container labels to use so that this Reaper cleans them up // Deprecated: internally replaced by core.DefaultLabels(sessionID) func (r *Reaper) Labels() map[string]string { - return map[string]string{ - core.LabelLang: "go", - core.LabelSessionID: r.SessionID, - } + return GenericLabels() } diff --git a/reaper_test.go b/reaper_test.go index f421c2686d..2cef02de6e 100644 --- a/reaper_test.go +++ b/reaper_test.go @@ -4,14 +4,15 @@ import ( "context" "errors" "os" + "strconv" "sync" "testing" "time" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" + "github.com/docker/docker/errdefs" "github.com/docker/go-connections/nat" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/testcontainers/testcontainers-go/internal/config" @@ -23,48 +24,29 @@ import ( const testSessionID = "this-is-a-different-session-id" type mockReaperProvider struct { - req ContainerRequest - hostConfig *container.HostConfig - enpointSettings map[string]*network.EndpointSettings - config TestcontainersConfig - initialReaper *Reaper - initialReaperOnce sync.Once - t *testing.T + req ContainerRequest + hostConfig *container.HostConfig + endpointSettings map[string]*network.EndpointSettings + config TestcontainersConfig } -func newMockReaperProvider(t *testing.T) *mockReaperProvider { +func newMockReaperProvider(cfg config.Config) *mockReaperProvider { m := &mockReaperProvider{ config: TestcontainersConfig{ - Config: config.Config{}, + Config: cfg, }, - t: t, - initialReaper: reaperInstance, - //nolint:govet - initialReaperOnce: reaperOnce, } - // explicitly reset the reaperInstance to nil to start from a fresh state - reaperInstance = nil - reaperOnce = sync.Once{} - return m } var errExpected = errors.New("expected") -func (m *mockReaperProvider) RestoreReaperState() { - m.t.Cleanup(func() { - reaperInstance = m.initialReaper - //nolint:govet - reaperOnce = m.initialReaperOnce - }) -} - func (m *mockReaperProvider) RunContainer(ctx context.Context, req ContainerRequest) (Container, error) { m.req = req m.hostConfig = &container.HostConfig{} - m.enpointSettings = map[string]*network.EndpointSettings{} + m.endpointSettings = map[string]*network.EndpointSettings{} if req.HostConfigModifier == nil { req.HostConfigModifier = defaultHostConfigModifier(req) @@ -72,7 +54,7 @@ func (m *mockReaperProvider) RunContainer(ctx context.Context, req ContainerRequ req.HostConfigModifier(m.hostConfig) if req.EnpointSettingsModifier != nil { - req.EnpointSettingsModifier(m.enpointSettings) + req.EnpointSettingsModifier(m.endpointSettings) } // we're only interested in the request, so instead of mocking the Docker client @@ -84,8 +66,8 @@ func (m *mockReaperProvider) Config() TestcontainersConfig { return m.config } -// createContainerRequest creates the expected request and allows for customization -func createContainerRequest(customize func(ContainerRequest) ContainerRequest) ContainerRequest { +// expectedReaperRequest creates the expected reaper container request with the given customizations. +func expectedReaperRequest(customize ...func(*ContainerRequest)) ContainerRequest { req := ContainerRequest{ Image: config.ReaperDefaultImage, ExposedPorts: []string{"8080/tcp"}, @@ -102,21 +84,26 @@ func createContainerRequest(customize func(ContainerRequest) ContainerRequest) C req.Labels[core.LabelReaper] = "true" req.Labels[core.LabelRyuk] = "true" + delete(req.Labels, core.LabelReap) - if customize == nil { - return req + for _, customize := range customize { + customize(&req) } - return customize(req) + return req } -func TestContainerStartsWithoutTheReaper(t *testing.T) { - config.Reset() // reset the config using the internal method to avoid the sync.Once - tcConfig := config.Read() - if !tcConfig.RyukDisabled { - t.Skip("Ryuk is enabled, skipping test") - } +// reaperDisable disables / enables the reaper for the duration of the test. +func reaperDisable(t *testing.T, disabled bool) { + t.Helper() + + config.Reset() + t.Setenv("TESTCONTAINERS_RYUK_DISABLED", strconv.FormatBool(disabled)) + t.Cleanup(config.Reset) +} +func testContainerStart(t *testing.T) { + t.Helper() ctx := context.Background() ctr, err := GenericContainer(ctx, GenericContainerRequest{ @@ -131,59 +118,55 @@ func TestContainerStartsWithoutTheReaper(t *testing.T) { }) CleanupContainer(t, ctr) require.NoError(t, err) +} - sessionID := core.SessionID() +// testReaperRunning validates that a reaper is running. +func testReaperRunning(t *testing.T) { + t.Helper() - reaperContainer, err := lookUpReaperContainer(ctx, sessionID) - if err != nil { - t.Fatal(err, "expected reaper container not found.") - } - if reaperContainer != nil { - t.Fatal("expected zero reaper running.") - } + ctx := context.Background() + sessionID := core.SessionID() + reaperContainer, err := spawner.lookupContainer(ctx, sessionID) + require.NoError(t, err) + require.NotNil(t, reaperContainer) } -func TestContainerStartsWithTheReaper(t *testing.T) { - config.Reset() // reset the config using the internal method to avoid the sync.Once - tcConfig := config.Read() - if tcConfig.RyukDisabled { - t.Skip("Ryuk is disabled, skipping test") - } +func TestContainer(t *testing.T) { + reaperDisable(t, false) - ctx := context.Background() + t.Run("start/reaper-enabled", func(t *testing.T) { + testContainerStart(t) + testReaperRunning(t) + }) - c, err := GenericContainer(ctx, GenericContainerRequest{ - ProviderType: providerType, - ContainerRequest: ContainerRequest{ - Image: nginxAlpineImage, - ExposedPorts: []string{ - nginxDefaultPort, - }, - }, - Started: true, + t.Run("stop/reaper-enabled", func(t *testing.T) { + testContainerStop(t) + testReaperRunning(t) }) - CleanupContainer(t, c) - if err != nil { - t.Fatal(err) - } - sessionID := core.SessionID() + t.Run("terminate/reaper-enabled", func(t *testing.T) { + testContainerTerminate(t) + testReaperRunning(t) + }) - reaperContainer, err := lookUpReaperContainer(ctx, sessionID) - if err != nil { - t.Fatal(err, "expected reaper container running.") - } - if reaperContainer == nil { - t.Fatal("expected one reaper to be running.") - } + reaperDisable(t, true) + + t.Run("start/reaper-disabled", func(t *testing.T) { + testContainerStart(t) + }) + + t.Run("stop/reaper-disabled", func(t *testing.T) { + testContainerStop(t) + }) + + t.Run("terminate/reaper-disabled", func(t *testing.T) { + testContainerTerminate(t) + }) } -func TestContainerStopWithReaper(t *testing.T) { - config.Reset() // reset the config using the internal method to avoid the sync.Once - tcConfig := config.Read() - if tcConfig.RyukDisabled { - t.Skip("Ryuk is disabled, skipping test") - } +// testContainerStop tests stopping a container. +func testContainerStop(t *testing.T) { + t.Helper() ctx := context.Background() @@ -201,37 +184,21 @@ func TestContainerStopWithReaper(t *testing.T) { require.NoError(t, err) state, err := nginxA.State(ctx) - if err != nil { - t.Fatal(err) - } - if state.Running != true { - t.Fatal("The container shoud be in running state") - } + require.NoError(t, err) + require.True(t, state.Running) + stopTimeout := 10 * time.Second err = nginxA.Stop(ctx, &stopTimeout) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) state, err = nginxA.State(ctx) - if err != nil { - t.Fatal(err) - } - if state.Running != false { - t.Fatal("The container shoud not be running") - } - if state.Status != "exited" { - t.Fatal("The container shoud be in exited state") - } + require.NoError(t, err) + require.False(t, state.Running) + require.Equal(t, "exited", state.Status) } -func TestContainerTerminationWithReaper(t *testing.T) { - config.Reset() // reset the config using the internal method to avoid the sync.Once - tcConfig := config.Read() - if tcConfig.RyukDisabled { - t.Skip("Ryuk is disabled, skipping test") - } - +// testContainerTerminate tests terminating a container. +func testContainerTerminate(t *testing.T) { ctx := context.Background() nginxA, err := GenericContainer(ctx, GenericContainerRequest{ @@ -258,324 +225,274 @@ func TestContainerTerminationWithReaper(t *testing.T) { require.Error(t, err) } -func TestContainerTerminationWithoutReaper(t *testing.T) { - config.Reset() // reset the config using the internal method to avoid the sync.Once - tcConfig := config.Read() - if !tcConfig.RyukDisabled { - t.Skip("Ryuk is enabled, skipping test") - } +func Test_NewReaper(t *testing.T) { + reaperDisable(t, false) ctx := context.Background() - nginxA, err := GenericContainer(ctx, GenericContainerRequest{ - ProviderType: providerType, - ContainerRequest: ContainerRequest{ - Image: nginxAlpineImage, - ExposedPorts: []string{ - nginxDefaultPort, + t.Run("non-privileged", func(t *testing.T) { + testNewReaper(ctx, t, + config.Config{ + RyukConnectionTimeout: time.Minute, + RyukReconnectionTimeout: 10 * time.Second, }, - }, - Started: true, + expectedReaperRequest(), + ) }) - CleanupContainer(t, nginxA) - if err != nil { - t.Fatal(err) - } - - state, err := nginxA.State(ctx) - if err != nil { - t.Fatal(err) - } - if state.Running != true { - t.Fatal("The container shoud be in running state") - } - err = nginxA.Terminate(ctx) - if err != nil { - t.Fatal(err) - } - - _, err = nginxA.State(ctx) - if err == nil { - t.Fatal("expected error from container inspect.") - } -} - -func Test_NewReaper(t *testing.T) { - config.Reset() // reset the config using the internal method to avoid the sync.Once - tcConfig := config.Read() - if tcConfig.RyukDisabled { - t.Skip("Ryuk is disabled, skipping test") - } - - type cases struct { - name string - req ContainerRequest - config TestcontainersConfig - ctx context.Context - env map[string]string - } - tests := []cases{ - { - name: "non-privileged", - req: createContainerRequest(nil), - config: TestcontainersConfig{Config: config.Config{ - RyukConnectionTimeout: time.Minute, - RyukReconnectionTimeout: 10 * time.Second, - }}, - }, - { - name: "privileged", - req: createContainerRequest(func(req ContainerRequest) ContainerRequest { - req.Privileged = true - return req - }), - config: TestcontainersConfig{Config: config.Config{ + t.Run("privileged", func(t *testing.T) { + testNewReaper(ctx, t, + config.Config{ RyukPrivileged: true, RyukConnectionTimeout: time.Minute, RyukReconnectionTimeout: 10 * time.Second, - }}, - }, - { - name: "configured non-default timeouts", - req: createContainerRequest(func(req ContainerRequest) ContainerRequest { - req.Env = map[string]string{ - "RYUK_CONNECTION_TIMEOUT": "1m0s", - "RYUK_RECONNECTION_TIMEOUT": "10m0s", - } - return req - }), - config: TestcontainersConfig{Config: config.Config{ + }, + expectedReaperRequest(), + ) + }) + + t.Run("custom-timeouts", func(t *testing.T) { + testNewReaper(ctx, t, + config.Config{ RyukPrivileged: true, - RyukConnectionTimeout: time.Minute, - RyukReconnectionTimeout: 10 * time.Minute, - }}, - }, - { - name: "configured verbose mode", - req: createContainerRequest(func(req ContainerRequest) ContainerRequest { + RyukConnectionTimeout: 2 * time.Minute, + RyukReconnectionTimeout: 20 * time.Second, + }, + expectedReaperRequest(func(req *ContainerRequest) { req.Env = map[string]string{ - "RYUK_VERBOSE": "true", + "RYUK_CONNECTION_TIMEOUT": "2m0s", + "RYUK_RECONNECTION_TIMEOUT": "20s", } - return req }), - config: TestcontainersConfig{Config: config.Config{ + ) + }) + + t.Run("verbose", func(t *testing.T) { + testNewReaper(ctx, t, + config.Config{ RyukPrivileged: true, RyukVerbose: true, - }}, - }, - { - name: "docker-host in context", - req: createContainerRequest(func(req ContainerRequest) ContainerRequest { - req.HostConfigModifier = func(hostConfig *container.HostConfig) { - hostConfig.Binds = []string{core.MustExtractDockerSocket(context.Background()) + ":/var/run/docker.sock"} + }, + expectedReaperRequest(func(req *ContainerRequest) { + req.Env = map[string]string{ + "RYUK_VERBOSE": "true", } - return req }), - config: TestcontainersConfig{Config: config.Config{ + ) + }) + + t.Run("docker-host", func(t *testing.T) { + testNewReaper(context.WithValue(ctx, core.DockerHostContextKey, core.DockerSocketPathWithSchema), t, + config.Config{ RyukConnectionTimeout: time.Minute, RyukReconnectionTimeout: 10 * time.Second, - }}, - ctx: context.WithValue(context.TODO(), core.DockerHostContextKey, core.DockerSocketPathWithSchema), - }, - { - name: "Reaper including custom Hub prefix", - req: createContainerRequest(func(req ContainerRequest) ContainerRequest { - req.Image = config.ReaperDefaultImage - req.Privileged = true - return req + }, + expectedReaperRequest(func(req *ContainerRequest) { + req.HostConfigModifier = func(hostConfig *container.HostConfig) { + hostConfig.Binds = []string{core.MustExtractDockerSocket(ctx) + ":/var/run/docker.sock"} + } }), - config: TestcontainersConfig{Config: config.Config{ + ) + }) + + t.Run("hub-prefix", func(t *testing.T) { + testNewReaper(context.WithValue(ctx, core.DockerHostContextKey, core.DockerSocketPathWithSchema), t, + config.Config{ HubImageNamePrefix: "registry.mycompany.com/mirror", RyukPrivileged: true, RyukConnectionTimeout: time.Minute, RyukReconnectionTimeout: 10 * time.Second, - }}, - }, - { - name: "Reaper including custom Hub prefix as env var", - req: createContainerRequest(func(req ContainerRequest) ContainerRequest { + }, + expectedReaperRequest(func(req *ContainerRequest) { req.Image = config.ReaperDefaultImage req.Privileged = true - return req }), - config: TestcontainersConfig{Config: config.Config{ + ) + }) + + t.Run("hub-prefix-env", func(t *testing.T) { + config.Reset() + t.Cleanup(config.Reset) + + t.Setenv("TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX", "registry.mycompany.com/mirror") + testNewReaper(context.WithValue(ctx, core.DockerHostContextKey, core.DockerSocketPathWithSchema), t, + config.Config{ RyukPrivileged: true, RyukConnectionTimeout: time.Minute, RyukReconnectionTimeout: 10 * time.Second, - }}, - env: map[string]string{ - "TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX": "registry.mycompany.com/mirror", }, - }, - } + expectedReaperRequest(func(req *ContainerRequest) { + req.Image = config.ReaperDefaultImage + req.Privileged = true + }), + ) + }) +} - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - if test.env != nil { - config.Reset() // reset the config using the internal method to avoid the sync.Once - for k, v := range test.env { - t.Setenv(k, v) - } - } +func testNewReaper(ctx context.Context, t *testing.T, cfg config.Config, expected ContainerRequest) { + t.Helper() - if prefix := os.Getenv("TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX"); prefix != "" { - test.config.Config.HubImageNamePrefix = prefix - } - - provider := newMockReaperProvider(t) - provider.config = test.config - t.Cleanup(provider.RestoreReaperState) + if prefix := os.Getenv("TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX"); prefix != "" { + cfg.HubImageNamePrefix = prefix + } - if test.ctx == nil { - test.ctx = context.TODO() - } + provider := newMockReaperProvider(cfg) - _, err := reuseOrCreateReaper(test.ctx, testSessionID, provider) - // we should have errored out see mockReaperProvider.RunContainer - require.EqualError(t, err, "expected") + // We need a new reaperSpawner for each test case to avoid reusing + // an existing reaper instance. + spawner := &reaperSpawner{} + reaper, err := spawner.reaper(ctx, testSessionID, provider) + cleanupReaper(t, reaper, spawner) + // We should have errored out see mockReaperProvider.RunContainer. + require.ErrorIs(t, err, errExpected) - assert.Equal(t, test.req.Image, provider.req.Image, "expected image doesn't match the submitted request") - assert.Equal(t, test.req.ExposedPorts, provider.req.ExposedPorts, "expected exposed ports don't match the submitted request") - assert.Equal(t, test.req.Labels, provider.req.Labels, "expected labels don't match the submitted request") - assert.Equal(t, test.req.Mounts, provider.req.Mounts, "expected mounts don't match the submitted request") - assert.Equal(t, test.req.WaitingFor, provider.req.WaitingFor, "expected waitingFor don't match the submitted request") - assert.Equal(t, test.req.Env, provider.req.Env, "expected env doesn't match the submitted request") + require.Equal(t, expected.Image, provider.req.Image, "expected image doesn't match the submitted request") + require.Equal(t, expected.ExposedPorts, provider.req.ExposedPorts, "expected exposed ports don't match the submitted request") + require.Equal(t, expected.Labels, provider.req.Labels, "expected labels don't match the submitted request") + require.Equal(t, expected.Mounts, provider.req.Mounts, "expected mounts don't match the submitted request") + require.Equal(t, expected.WaitingFor, provider.req.WaitingFor, "expected waitingFor don't match the submitted request") + require.Equal(t, expected.Env, provider.req.Env, "expected env doesn't match the submitted request") - // checks for reaper's preCreationCallback fields - assert.Equal(t, container.NetworkMode(Bridge), provider.hostConfig.NetworkMode, "expected networkMode doesn't match the submitted request") - assert.True(t, provider.hostConfig.AutoRemove, "expected networkMode doesn't match the submitted request") - }) - } + // checks for reaper's preCreationCallback fields + require.Equal(t, container.NetworkMode(Bridge), provider.hostConfig.NetworkMode, "expected networkMode doesn't match the submitted request") + require.True(t, provider.hostConfig.AutoRemove, "expected networkMode doesn't match the submitted request") } func Test_ReaperReusedIfHealthy(t *testing.T) { - config.Reset() // reset the config using the internal method to avoid the sync.Once - tcConfig := config.Read() - if tcConfig.RyukDisabled { - t.Skip("Ryuk is disabled, skipping test") - } - - testProvider := newMockReaperProvider(t) - t.Cleanup(testProvider.RestoreReaperState) + reaperDisable(t, false) SkipIfProviderIsNotHealthy(t) ctx := context.Background() // As other integration tests run with the (shared) Reaper as well, re-use the instance to not interrupt other tests - wasReaperRunning := reaperInstance != nil + if spawner.instance != nil { + t.Cleanup(func() { + require.NoError(t, spawner.cleanup()) + }) + } + + provider, err := ProviderDocker.GetProvider() + require.NoError(t, err) - provider, _ := ProviderDocker.GetProvider() - reaper, err := reuseOrCreateReaper(context.WithValue(ctx, core.DockerHostContextKey, provider.(*DockerProvider).host), testSessionID, provider) + reaper, err := spawner.reaper(context.WithValue(ctx, core.DockerHostContextKey, provider.(*DockerProvider).host), testSessionID, provider) + cleanupReaper(t, reaper, spawner) require.NoError(t, err, "creating the Reaper should not error") - reaperReused, err := reuseOrCreateReaper(context.WithValue(ctx, core.DockerHostContextKey, provider.(*DockerProvider).host), testSessionID, provider) + reaperReused, err := spawner.reaper(context.WithValue(ctx, core.DockerHostContextKey, provider.(*DockerProvider).host), testSessionID, provider) + cleanupReaper(t, reaper, spawner) require.NoError(t, err, "reusing the Reaper should not error") - // assert that the internal state of both reaper instances is the same - assert.Equal(t, reaper.SessionID, reaperReused.SessionID, "expecting the same SessionID") - assert.Equal(t, reaper.Endpoint, reaperReused.Endpoint, "expecting the same reaper endpoint") - assert.Equal(t, reaper.Provider, reaperReused.Provider, "expecting the same container provider") - assert.Equal(t, reaper.container.GetContainerID(), reaperReused.container.GetContainerID(), "expecting the same container ID") - assert.Equal(t, reaper.container.SessionID(), reaperReused.container.SessionID(), "expecting the same session ID") - - terminate, err := reaper.Connect() - defer func(term chan bool) { - term <- true - }(terminate) - require.NoError(t, err, "connecting to Reaper should be successful") - if !wasReaperRunning { - CleanupContainer(t, reaper.container) - } + // Ensure the internal state of both reaper instances is the same + require.Equal(t, reaper.SessionID, reaperReused.SessionID, "expecting the same SessionID") + require.Equal(t, reaper.Endpoint, reaperReused.Endpoint, "expecting the same reaper endpoint") + require.Equal(t, reaper.Provider, reaperReused.Provider, "expecting the same container provider") + require.Equal(t, reaper.container.GetContainerID(), reaperReused.container.GetContainerID(), "expecting the same container ID") + require.Equal(t, reaper.container.SessionID(), reaperReused.container.SessionID(), "expecting the same session ID") + + termSignal, err := reaper.Connect() + cleanupTermSignal(t, termSignal) + require.NoError(t, err, "connecting to Reaper should be successful") } func Test_RecreateReaperIfTerminated(t *testing.T) { - config.Reset() // reset the config using the internal method to avoid the sync.Once - tcConfig := config.Read() - if tcConfig.RyukDisabled { - t.Skip("Ryuk is disabled, skipping test") - } - - mockProvider := newMockReaperProvider(t) - t.Cleanup(mockProvider.RestoreReaperState) + reaperDisable(t, false) SkipIfProviderIsNotHealthy(t) - provider, _ := ProviderDocker.GetProvider() + provider, err := ProviderDocker.GetProvider() + require.NoError(t, err) + ctx := context.Background() - reaper, err := reuseOrCreateReaper(context.WithValue(ctx, core.DockerHostContextKey, provider.(*DockerProvider).host), testSessionID, provider) + reaper, err := spawner.reaper(context.WithValue(ctx, core.DockerHostContextKey, provider.(*DockerProvider).host), testSessionID, provider) + cleanupReaper(t, reaper, spawner) require.NoError(t, err, "creating the Reaper should not error") - terminate, err := reaper.Connect() - require.NoError(t, err, "connecting to Reaper should be successful") - terminate <- true + termSignal, err := reaper.Connect() + if termSignal != nil { + termSignal <- true + } + require.NoError(t, err) - // Wait for ryuk's default timeout (10s) + 1s to allow for a graceful shutdown/cleanup of the container. - time.Sleep(11 * time.Second) + // Wait for up to ryuk's default reconnect timeout + 1s to allow for a graceful shutdown/cleanup of the container. + timeout := time.NewTimer(time.Second * 11) + t.Cleanup(func() { + timeout.Stop() + }) + for { + state, err := reaper.container.State(ctx) + if err != nil { + if errdefs.IsNotFound(err) { + break + } + require.NoError(t, err) + } + + if !state.Running { + break + } + + select { + case <-timeout.C: + t.Fatal("reaper container should have been terminated") + default: + } - recreatedReaper, err := reuseOrCreateReaper(context.WithValue(ctx, core.DockerHostContextKey, provider.(*DockerProvider).host), testSessionID, provider) + time.Sleep(time.Millisecond * 100) + } + + recreatedReaper, err := spawner.reaper(context.WithValue(ctx, core.DockerHostContextKey, provider.(*DockerProvider).host), testSessionID, provider) + cleanupReaper(t, recreatedReaper, spawner) require.NoError(t, err, "creating the Reaper should not error") - assert.NotEqual(t, reaper.container.GetContainerID(), recreatedReaper.container.GetContainerID(), "expected different container ID") + require.NotEqual(t, reaper.container.GetContainerID(), recreatedReaper.container.GetContainerID(), "expected different container ID") - terminate, err = recreatedReaper.Connect() - defer func(term chan bool) { - term <- true - }(terminate) + recreatedTermSignal, err := recreatedReaper.Connect() + cleanupTermSignal(t, recreatedTermSignal) require.NoError(t, err, "connecting to Reaper should be successful") - CleanupContainer(t, recreatedReaper.container) } func TestReaper_reuseItFromOtherTestProgramUsingDocker(t *testing.T) { - config.Reset() // reset the config using the internal method to avoid the sync.Once - tcConfig := config.Read() - if tcConfig.RyukDisabled { - t.Skip("Ryuk is disabled, skipping test") - } + reaperDisable(t, false) - mockProvider := &mockReaperProvider{ - initialReaper: reaperInstance, - //nolint:govet - initialReaperOnce: reaperOnce, - t: t, - } - t.Cleanup(mockProvider.RestoreReaperState) - - // explicitly set the reaperInstance to nil to simulate another test program in the same session accessing the same reaper - reaperInstance = nil - reaperOnce = sync.Once{} + // Explicitly set the reaper instance to nil to simulate another test + // program in the same session accessing the same reaper. + spawner.instance = nil SkipIfProviderIsNotHealthy(t) ctx := context.Background() - // As other integration tests run with the (shared) Reaper as well, re-use the instance to not interrupt other tests - wasReaperRunning := reaperInstance != nil + // As other integration tests run with the (shared) Reaper as well, + // re-use the instance to not interrupt other tests. + if spawner.instance != nil { + t.Cleanup(func() { + require.NoError(t, spawner.cleanup()) + }) + } - provider, _ := ProviderDocker.GetProvider() - reaper, err := reuseOrCreateReaper(context.WithValue(ctx, core.DockerHostContextKey, provider.(*DockerProvider).host), testSessionID, provider) + provider, err := ProviderDocker.GetProvider() + require.NoError(t, err) + + reaper, err := spawner.reaper(context.WithValue(ctx, core.DockerHostContextKey, provider.(*DockerProvider).host), testSessionID, provider) + cleanupReaper(t, reaper, spawner) require.NoError(t, err, "creating the Reaper should not error") - // explicitly reset the reaperInstance to nil to simulate another test program in the same session accessing the same reaper - reaperInstance = nil - reaperOnce = sync.Once{} + // Explicitly reset the reaper instance to nil to simulate another test + // program in the same session accessing the same reaper. + spawner.instance = nil - reaperReused, err := reuseOrCreateReaper(context.WithValue(ctx, core.DockerHostContextKey, provider.(*DockerProvider).host), testSessionID, provider) + reaperReused, err := spawner.reaper(context.WithValue(ctx, core.DockerHostContextKey, provider.(*DockerProvider).host), testSessionID, provider) + cleanupReaper(t, reaper, spawner) require.NoError(t, err, "reusing the Reaper should not error") - // assert that the internal state of both reaper instances is the same - assert.Equal(t, reaper.SessionID, reaperReused.SessionID, "expecting the same SessionID") - assert.Equal(t, reaper.Endpoint, reaperReused.Endpoint, "expecting the same reaper endpoint") - assert.Equal(t, reaper.Provider, reaperReused.Provider, "expecting the same container provider") - assert.Equal(t, reaper.container.GetContainerID(), reaperReused.container.GetContainerID(), "expecting the same container ID") - assert.Equal(t, reaper.container.SessionID(), reaperReused.container.SessionID(), "expecting the same session ID") - - terminate, err := reaper.Connect() - defer func(term chan bool) { - term <- true - }(terminate) - require.NoError(t, err, "connecting to Reaper should be successful") - if !wasReaperRunning { - CleanupContainer(t, reaper.container) - } + // Ensure that the internal state of both reaper instances is the same. + require.Equal(t, reaper.SessionID, reaperReused.SessionID, "expecting the same SessionID") + require.Equal(t, reaper.Endpoint, reaperReused.Endpoint, "expecting the same reaper endpoint") + require.Equal(t, reaper.Provider, reaperReused.Provider, "expecting the same container provider") + require.Equal(t, reaper.container.GetContainerID(), reaperReused.container.GetContainerID(), "expecting the same container ID") + require.Equal(t, reaper.container.SessionID(), reaperReused.container.SessionID(), "expecting the same session ID") + + termSignal, err := reaper.Connect() + cleanupTermSignal(t, termSignal) + require.NoError(t, err, "connecting to Reaper should be successful") } // TestReaper_ReuseRunning tests whether reusing the reaper if using @@ -586,15 +503,11 @@ func TestReaper_reuseItFromOtherTestProgramUsingDocker(t *testing.T) { // already running for the same session id by returning its container instance // instead. func TestReaper_ReuseRunning(t *testing.T) { - config.Reset() // reset the config using the internal method to avoid the sync.Once - tcConfig := config.Read() - if tcConfig.RyukDisabled { - t.Skip("Ryuk is disabled, skipping test") - } + reaperDisable(t, false) const concurrency = 64 - timeout, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + timeout, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() sessionID := SessionID() @@ -605,27 +518,54 @@ func TestReaper_ReuseRunning(t *testing.T) { obtainedReaperContainerIDs := make([]string, concurrency) var wg sync.WaitGroup for i := 0; i < concurrency; i++ { - i := i wg.Add(1) - go func() { + go func(i int) { defer wg.Done() - reaperContainer, err := lookUpReaperContainer(timeout, sessionID) - if err == nil && reaperContainer != nil { - // Found. - obtainedReaperContainerIDs[i] = reaperContainer.GetContainerID() - return - } - // Not found -> create. - createdReaper, err := newReaper(timeout, sessionID, dockerProvider) - require.NoError(t, err, "new reaper should not fail") - obtainedReaperContainerIDs[i] = createdReaper.container.GetContainerID() - }() + spawner := &reaperSpawner{} + reaper, err := spawner.reaper(timeout, sessionID, dockerProvider) + cleanupReaper(t, reaper, spawner) + require.NoError(t, err) + + obtainedReaperContainerIDs[i] = reaper.container.GetContainerID() + }(i) } wg.Wait() // Assure that all calls returned the same container. firstContainerID := obtainedReaperContainerIDs[0] for i, containerID := range obtainedReaperContainerIDs { - assert.Equal(t, firstContainerID, containerID, "call %d should have returned same container id", i) + require.Equal(t, firstContainerID, containerID, "call %d should have returned same container id", i) + } +} + +func TestSpawnerBackoff(t *testing.T) { + b := spawner.backoff() + for i := 0; i < 100; i++ { + require.LessOrEqual(t, b.NextBackOff(), time.Millisecond*250, "backoff should not exceed max interval") + } +} + +// cleanupReaper schedules reaper for cleanup if it's not nil. +func cleanupReaper(t *testing.T, reaper *Reaper, spawner *reaperSpawner) { + t.Helper() + + if reaper == nil { + return } + + t.Cleanup(func() { + reaper.close() + require.NoError(t, spawner.cleanup()) + }) +} + +// cleanupTermSignal ensures that termSignal +func cleanupTermSignal(t *testing.T, termSignal chan bool) { + t.Helper() + + t.Cleanup(func() { + if termSignal != nil { + termSignal <- true + } + }) } diff --git a/testing.go b/testing.go index 41391519de..cafd4fe920 100644 --- a/testing.go +++ b/testing.go @@ -68,11 +68,11 @@ func (lc *StdoutLogConsumer) Accept(l Log) { // container is stopped when the function ends. // // before any error check. If container is nil, its a no-op. -func CleanupContainer(tb testing.TB, container Container, options ...TerminateOption) { +func CleanupContainer(tb testing.TB, ctr Container, options ...TerminateOption) { tb.Helper() tb.Cleanup(func() { - noErrorOrIgnored(tb, TerminateContainer(container, options...)) + noErrorOrIgnored(tb, TerminateContainer(ctr, options...)) }) } From b74984d043f27c31e3611b7d61dfb34e04ef0480 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Fri, 18 Oct 2024 14:47:37 +0200 Subject: [PATCH 092/126] golangci-lint: enable thelper linter (#2834) Signed-off-by: Matthieu MOREL --- .golangci.yml | 17 ++++------------- docker_auth_test.go | 3 +++ docker_test.go | 2 ++ generic_test.go | 1 + internal/config/config_test.go | 1 + internal/core/docker_host_test.go | 5 +++++ internal/core/docker_rootless_test.go | 1 + modulegen/context_test.go | 1 + modulegen/main_test.go | 8 ++++++++ modulegen/mkdocs_test.go | 1 + modules/artemis/artemis_test.go | 1 + modules/clickhouse/clickhouse_test.go | 2 ++ modules/compose/compose_builder_test.go | 1 + modules/compose/compose_test.go | 2 ++ modules/couchbase/couchbase_test.go | 1 + modules/dolt/dolt_test.go | 1 + modules/kafka/consumer_test.go | 1 + modules/kafka/kafka_test.go | 1 + modules/mariadb/mariadb_test.go | 1 + modules/neo4j/neo4j_test.go | 2 ++ modules/ollama/ollama_test.go | 1 + modules/redis/redis_test.go | 2 ++ modules/valkey/valkey_test.go | 2 ++ port_forwarding_test.go | 3 +++ reaper_test.go | 1 + testing.go | 2 ++ 26 files changed, 51 insertions(+), 13 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 861e0cbc5c..26f8f8a3c2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,14 +1,15 @@ linters: enable: + - errcheck - errorlint - gci - gocritic - gofumpt - misspell + - nolintlint - nonamedreturns - testifylint - - errcheck - - nolintlint + - thelper linters-settings: errorlint: @@ -30,16 +31,6 @@ linters-settings: disable: - float-compare - go-require - enable: - - bool-compare - - compares - - empty - - error-is-as - - error-nil - - expected-actual - - len - - require-error - - suite-dont-use-pkg - - suite-extra-assert-call + enable-all: true run: timeout: 5m diff --git a/docker_auth_test.go b/docker_auth_test.go index b8580a08ea..22c86783a2 100644 --- a/docker_auth_test.go +++ b/docker_auth_test.go @@ -170,6 +170,7 @@ func TestBuildContainerFromDockerfile(t *testing.T) { // removeImageFromLocalCache removes the image from the local cache func removeImageFromLocalCache(t *testing.T, img string) { + t.Helper() ctx := context.Background() testcontainersClient, err := NewDockerClientWithOpts(ctx, client.WithVersion(daemonMaxVersion)) @@ -263,6 +264,7 @@ func TestCreateContainerFromPrivateRegistry(t *testing.T) { } func prepareLocalRegistryWithAuth(t *testing.T) string { + t.Helper() ctx := context.Background() wd, err := os.Getwd() require.NoError(t, err) @@ -359,6 +361,7 @@ func setAuthConfig(t *testing.T, host, username, password string) string { // which can be used to connect to the local registry. // This avoids the issues with localhost on WSL. func localAddress(t *testing.T) string { + t.Helper() if os.Getenv("WSL_DISTRO_NAME") == "" { return "localhost" } diff --git a/docker_test.go b/docker_test.go index 1a6f406c85..0c636d2296 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1345,6 +1345,7 @@ func TestContainerInspect_RawInspectIsCleanedOnStop(t *testing.T) { } func readHostname(tb testing.TB, containerId string) string { + tb.Helper() containerClient, err := NewDockerClientWithOpts(context.Background()) if err != nil { tb.Fatalf("Failed to create Docker client: %v", err) @@ -1917,6 +1918,7 @@ func TestNetworkModeWithContainerReference(t *testing.T) { // creates a temporary dir in which the files will be extracted. Then it will compare the bytes of each file in the source with the bytes from the copied-from-container file func assertExtractedFiles(t *testing.T, ctx context.Context, container Container, hostFilePath string, containerFilePath string) { + t.Helper() // create all copied files into a temporary dir tmpDir := t.TempDir() diff --git a/generic_test.go b/generic_test.go index 99c13f5bfa..2e9bc44d6a 100644 --- a/generic_test.go +++ b/generic_test.go @@ -164,6 +164,7 @@ func TestGenericReusableContainerInSubprocess(t *testing.T) { } func createReuseContainerInSubprocess(t *testing.T) string { + t.Helper() // force verbosity in subprocesses, so that the output is printed cmd := exec.Command(os.Args[0], "-test.run=TestHelperContainerStarterProcess", "-test.v=true") cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1") diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 6f78a430b8..c5b48244bd 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -19,6 +19,7 @@ const ( // unset environment variables to avoid side effects // execute this function before each test func resetTestEnv(t *testing.T) { + t.Helper() t.Setenv("TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX", "") t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "") t.Setenv("TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED", "") diff --git a/internal/core/docker_host_test.go b/internal/core/docker_host_test.go index ea8779f217..00b2dfa2ff 100644 --- a/internal/core/docker_host_test.go +++ b/internal/core/docker_host_test.go @@ -50,6 +50,7 @@ func testCallbackCheckError(_ context.Context, _ string) error { } func mockCallbackCheck(t *testing.T, fn func(_ context.Context, _ string) error) { + t.Helper() oldCheck := dockerHostCheck dockerHostCheck = fn t.Cleanup(func() { @@ -515,10 +516,12 @@ func createTmpDockerSocket(parent string) error { // setupDockerHostNotFound sets up the environment for the test case where the DOCKER_HOST environment variable is // already set (e.g. rootless docker) therefore we need to unset it before the test func setupDockerHostNotFound(t *testing.T) { + t.Helper() t.Setenv("DOCKER_HOST", "") } func setupDockerSocket(t *testing.T) string { + t.Helper() t.Cleanup(func() { DockerSocketPath = originalDockerSocketPath DockerSocketPathWithSchema = originalDockerSocketPathWithSchema @@ -536,6 +539,7 @@ func setupDockerSocket(t *testing.T) string { } func setupDockerSocketNotFound(t *testing.T) { + t.Helper() t.Cleanup(func() { DockerSocketPath = originalDockerSocketPath DockerSocketPathWithSchema = originalDockerSocketPathWithSchema @@ -548,6 +552,7 @@ func setupDockerSocketNotFound(t *testing.T) { } func setupTestcontainersProperties(t *testing.T, content string) { + t.Helper() t.Cleanup(func() { // reset the properties file after the test config.Reset() diff --git a/internal/core/docker_rootless_test.go b/internal/core/docker_rootless_test.go index 687aa24707..40bfb948b5 100644 --- a/internal/core/docker_rootless_test.go +++ b/internal/core/docker_rootless_test.go @@ -184,6 +184,7 @@ func TestRootlessDockerSocketPath(t *testing.T) { } func setupRootlessNotFound(t *testing.T) { + t.Helper() t.Cleanup(func() { baseRunDir = originalBaseRunDir os.Setenv("XDG_RUNTIME_DIR", originalXDGRuntimeDir) diff --git a/modulegen/context_test.go b/modulegen/context_test.go index fc56ea3c5d..4023e2ed88 100644 --- a/modulegen/context_test.go +++ b/modulegen/context_test.go @@ -11,6 +11,7 @@ import ( ) func getTestRootContext(t *testing.T) context.Context { + t.Helper() current, err := os.Getwd() require.NoError(t, err) return context.New(filepath.Dir(current)) diff --git a/modulegen/main_test.go b/modulegen/main_test.go index ad9a946236..eeb836a8a5 100644 --- a/modulegen/main_test.go +++ b/modulegen/main_test.go @@ -357,6 +357,7 @@ func TestGenerateModule(t *testing.T) { // assert content module file in the docs func assertModuleDocContent(t *testing.T, module context.TestcontainersModule, moduleDocFile string) { + t.Helper() content, err := os.ReadFile(moduleDocFile) require.NoError(t, err) @@ -383,6 +384,7 @@ func assertModuleDocContent(t *testing.T, module context.TestcontainersModule, m // assert content module test func assertExamplesTestContent(t *testing.T, module context.TestcontainersModule, examplesTestFile string) { + t.Helper() content, err := os.ReadFile(examplesTestFile) require.NoError(t, err) @@ -402,6 +404,7 @@ func assertExamplesTestContent(t *testing.T, module context.TestcontainersModule // assert content module test func assertModuleTestContent(t *testing.T, module context.TestcontainersModule, exampleTestFile string) { + t.Helper() content, err := os.ReadFile(exampleTestFile) require.NoError(t, err) @@ -413,6 +416,7 @@ func assertModuleTestContent(t *testing.T, module context.TestcontainersModule, // assert content module func assertModuleContent(t *testing.T, module context.TestcontainersModule, exampleFile string) { + t.Helper() content, err := os.ReadFile(exampleFile) require.NoError(t, err) @@ -437,6 +441,7 @@ func assertModuleContent(t *testing.T, module context.TestcontainersModule, exam // assert content GitHub workflow for the module func assertModuleGithubWorkflowContent(t *testing.T, moduleWorkflowFile string) { + t.Helper() content, err := os.ReadFile(moduleWorkflowFile) require.NoError(t, err) @@ -454,6 +459,7 @@ func assertModuleGithubWorkflowContent(t *testing.T, moduleWorkflowFile string) // assert content go.mod func assertGoModContent(t *testing.T, module context.TestcontainersModule, tcVersion string, goModFile string) { + t.Helper() content, err := os.ReadFile(goModFile) require.NoError(t, err) @@ -465,6 +471,7 @@ func assertGoModContent(t *testing.T, module context.TestcontainersModule, tcVer // assert content Makefile func assertMakefileContent(t *testing.T, module context.TestcontainersModule, makefile string) { + t.Helper() content, err := os.ReadFile(makefile) require.NoError(t, err) @@ -474,6 +481,7 @@ func assertMakefileContent(t *testing.T, module context.TestcontainersModule, ma // assert content in the nav items from mkdocs.yml func assertMkdocsNavItems(t *testing.T, module context.TestcontainersModule, originalConfig *mkdocs.Config, tmpCtx context.Context) { + t.Helper() config, err := mkdocs.ReadConfig(tmpCtx.MkdocsConfigFile()) require.NoError(t, err) diff --git a/modulegen/mkdocs_test.go b/modulegen/mkdocs_test.go index 9ca3b3860c..305eeca1e4 100644 --- a/modulegen/mkdocs_test.go +++ b/modulegen/mkdocs_test.go @@ -82,6 +82,7 @@ func TestNavItems(t *testing.T) { } func copyInitialMkdocsConfig(t *testing.T, tmpCtx context.Context) error { + t.Helper() ctx := getTestRootContext(t) return mkdocs.CopyConfig(ctx.MkdocsConfigFile(), tmpCtx.MkdocsConfigFile()) } diff --git a/modules/artemis/artemis_test.go b/modules/artemis/artemis_test.go index 74f150b031..8396b562f5 100644 --- a/modules/artemis/artemis_test.go +++ b/modules/artemis/artemis_test.go @@ -57,6 +57,7 @@ func TestArtemis(t *testing.T) { user: "artemis", pass: "artemis", hook: func(t *testing.T, container *artemis.Container) { + t.Helper() expectQueue(t, container, "ArgsTestQueue") }, }, diff --git a/modules/clickhouse/clickhouse_test.go b/modules/clickhouse/clickhouse_test.go index c14814d3fe..69d05a2abc 100644 --- a/modules/clickhouse/clickhouse_test.go +++ b/modules/clickhouse/clickhouse_test.go @@ -254,6 +254,7 @@ func TestClickHouseWithZookeeper(t *testing.T) { } func performReplicatedCRUD(t *testing.T, conn driver.Conn) ([]Test, error) { + t.Helper() return backoff.RetryNotifyWithData( func() ([]Test, error) { err := conn.Exec(context.Background(), "CREATE TABLE replicated_test_table (id UInt64) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/mdb.data_transfer_cp_cdc', '{replica}') PRIMARY KEY (id) ORDER BY (id) SETTINGS index_granularity = 8192;") @@ -292,6 +293,7 @@ func performReplicatedCRUD(t *testing.T, conn driver.Conn) ([]Test, error) { } func performCRUD(t *testing.T, conn driver.Conn) ([]Test, error) { + t.Helper() return backoff.RetryNotifyWithData( func() ([]Test, error) { err := conn.Exec(context.Background(), "create table if not exists test_table (id UInt64) engine = MergeTree PRIMARY KEY (id) ORDER BY (id) SETTINGS index_granularity = 8192;") diff --git a/modules/compose/compose_builder_test.go b/modules/compose/compose_builder_test.go index 4624c1d3c2..07b3c08aba 100644 --- a/modules/compose/compose_builder_test.go +++ b/modules/compose/compose_builder_test.go @@ -135,6 +135,7 @@ func getFreePort(t *testing.T) int { } func writeTemplate(t *testing.T, templateFile string, port ...int) string { + t.Helper() return writeTemplateWithSrvType(t, templateFile, "api", port...) } diff --git a/modules/compose/compose_test.go b/modules/compose/compose_test.go index 2453507b06..066a8e8277 100644 --- a/modules/compose/compose_test.go +++ b/modules/compose/compose_test.go @@ -446,6 +446,7 @@ func TestLocalDockerComposeWithVolume(t *testing.T) { } func assertVolumeDoesNotExist(tb testing.TB, volumeName string) { + tb.Helper() containerClient, err := testcontainers.NewDockerClientWithOpts(context.Background()) if err != nil { tb.Fatalf("Failed to get provider: %v", err) @@ -471,6 +472,7 @@ func assertContainerEnvironmentVariables( present map[string]string, absent map[string]string, ) { + tb.Helper() containerClient, err := testcontainers.NewDockerClientWithOpts(context.Background()) if err != nil { tb.Fatalf("Failed to get provider: %v", err) diff --git a/modules/couchbase/couchbase_test.go b/modules/couchbase/couchbase_test.go index c873115898..4e6330e24d 100644 --- a/modules/couchbase/couchbase_test.go +++ b/modules/couchbase/couchbase_test.go @@ -113,6 +113,7 @@ func TestEventingServiceWithCommunityContainer(t *testing.T) { } func testBucketUsage(t *testing.T, bucket *gocb.Bucket) { + t.Helper() err := bucket.WaitUntilReady(5*time.Second, nil) if err != nil { t.Fatalf("could not connect bucket: %s", err) diff --git a/modules/dolt/dolt_test.go b/modules/dolt/dolt_test.go index 61787e237b..b239136e38 100644 --- a/modules/dolt/dolt_test.go +++ b/modules/dolt/dolt_test.go @@ -70,6 +70,7 @@ func TestDoltWithPublicRemoteCloneUrl(t *testing.T) { } func createTestCredsFile(t *testing.T) string { + t.Helper() file, err := os.CreateTemp(t.TempDir(), "prefix") if err != nil { t.Fatal(err) diff --git a/modules/kafka/consumer_test.go b/modules/kafka/consumer_test.go index d7305540f8..9df926e72d 100644 --- a/modules/kafka/consumer_test.go +++ b/modules/kafka/consumer_test.go @@ -16,6 +16,7 @@ type TestKafkaConsumer struct { } func NewTestKafkaConsumer(t *testing.T) (*TestKafkaConsumer, <-chan bool, <-chan bool, func()) { + t.Helper() kc := &TestKafkaConsumer{ t: t, ready: make(chan bool, 1), diff --git a/modules/kafka/kafka_test.go b/modules/kafka/kafka_test.go index 42fca78650..c1fca69fb2 100644 --- a/modules/kafka/kafka_test.go +++ b/modules/kafka/kafka_test.go @@ -84,6 +84,7 @@ func TestKafka_invalidVersion(t *testing.T) { // assertAdvertisedListeners checks that the advertised listeners are set correctly: // - The BROKER:// protocol is using the hostname of the Kafka container func assertAdvertisedListeners(t *testing.T, container testcontainers.Container) { + t.Helper() inspect, err := container.Inspect(context.Background()) require.NoError(t, err) diff --git a/modules/mariadb/mariadb_test.go b/modules/mariadb/mariadb_test.go index 8e55609ec4..f042555e51 100644 --- a/modules/mariadb/mariadb_test.go +++ b/modules/mariadb/mariadb_test.go @@ -144,6 +144,7 @@ func TestMariaDBWithScripts(t *testing.T) { } func assertDataCanBeFetched(t *testing.T, ctx context.Context, container *mariadb.MariaDBContainer) { + t.Helper() connectionString, err := container.ConnectionString(ctx) require.NoError(t, err) db, err := sql.Open("mysql", connectionString) diff --git a/modules/neo4j/neo4j_test.go b/modules/neo4j/neo4j_test.go index 466bd3ddf7..d036fb8128 100644 --- a/modules/neo4j/neo4j_test.go +++ b/modules/neo4j/neo4j_test.go @@ -163,6 +163,7 @@ func setupNeo4j(ctx context.Context) (*neo4j.Neo4jContainer, error) { } func createDriver(t *testing.T, ctx context.Context, container *neo4j.Neo4jContainer) neo.DriverWithContext { + t.Helper() // boltURL { boltUrl, err := container.BoltUrl(ctx) // } @@ -182,6 +183,7 @@ func createDriver(t *testing.T, ctx context.Context, container *neo4j.Neo4jConta } func getContainerEnv(t *testing.T, ctx context.Context, container *neo4j.Neo4jContainer) string { + t.Helper() exec, reader, err := container.Exec(ctx, []string{"env"}) if err != nil { t.Fatalf("expected env to successfully run but did not: %s", err) diff --git a/modules/ollama/ollama_test.go b/modules/ollama/ollama_test.go index 0f6614a51e..94212dc171 100644 --- a/modules/ollama/ollama_test.go +++ b/modules/ollama/ollama_test.go @@ -75,6 +75,7 @@ func TestOllama(t *testing.T) { // For that, it checks if the response of the /api/tags endpoint // contains the model name. func assertLoadedModel(t *testing.T, c *ollama.OllamaContainer) { + t.Helper() url, err := c.ConnectionString(context.Background()) require.NoError(t, err) diff --git a/modules/redis/redis_test.go b/modules/redis/redis_test.go index 0fd0a960f9..4a872a0a87 100644 --- a/modules/redis/redis_test.go +++ b/modules/redis/redis_test.go @@ -96,6 +96,7 @@ func TestRedisWithSnapshotting(t *testing.T) { } func assertSetsGets(t *testing.T, ctx context.Context, redisContainer *tcredis.RedisContainer, keyCount int) { + t.Helper() // connectionString { uri, err := redisContainer.ConnectionString(ctx) // } @@ -109,6 +110,7 @@ func assertSetsGets(t *testing.T, ctx context.Context, redisContainer *tcredis.R client := redis.NewClient(options) defer func(t *testing.T, ctx context.Context, client *redis.Client) { + t.Helper() require.NoError(t, flushRedis(ctx, *client)) }(t, ctx, client) diff --git a/modules/valkey/valkey_test.go b/modules/valkey/valkey_test.go index ed4fd75d12..484c75dabe 100644 --- a/modules/valkey/valkey_test.go +++ b/modules/valkey/valkey_test.go @@ -81,6 +81,7 @@ func TestValkeyWithSnapshotting(t *testing.T) { } func assertSetsGets(t *testing.T, ctx context.Context, valkeyContainer *tcvalkey.ValkeyContainer, keyCount int) { + t.Helper() // connectionString { uri, err := valkeyContainer.ConnectionString(ctx) // } @@ -95,6 +96,7 @@ func assertSetsGets(t *testing.T, ctx context.Context, valkeyContainer *tcvalkey client, err := valkey.NewClient(options) require.NoError(t, err) defer func(t *testing.T, ctx context.Context, client *valkey.Client) { + t.Helper() require.NoError(t, flushValkey(ctx, *client)) }(t, ctx, &client) diff --git a/port_forwarding_test.go b/port_forwarding_test.go index 7a82158147..8f8681f22c 100644 --- a/port_forwarding_test.go +++ b/port_forwarding_test.go @@ -112,6 +112,7 @@ func TestExposeHostPorts(t *testing.T) { } func httpRequest(t *testing.T, c testcontainers.Container, port int) (int, string) { + t.Helper() // wgetHostInternal { code, reader, err := c.Exec( context.Background(), @@ -129,6 +130,7 @@ func httpRequest(t *testing.T, c testcontainers.Container, port int) (int, strin } func assertContainerHasHostAccess(t *testing.T, c testcontainers.Container, ports ...int) { + t.Helper() for _, port := range ports { code, response := httpRequest(t, c, port) if code != 0 { @@ -142,6 +144,7 @@ func assertContainerHasHostAccess(t *testing.T, c testcontainers.Container, port } func assertContainerHasNoHostAccess(t *testing.T, c testcontainers.Container, ports ...int) { + t.Helper() for _, port := range ports { _, response := httpRequest(t, c, port) diff --git a/reaper_test.go b/reaper_test.go index 2cef02de6e..e9bc5ccb9f 100644 --- a/reaper_test.go +++ b/reaper_test.go @@ -199,6 +199,7 @@ func testContainerStop(t *testing.T) { // testContainerTerminate tests terminating a container. func testContainerTerminate(t *testing.T) { + t.Helper() ctx := context.Background() nginxA, err := GenericContainer(ctx, GenericContainerRequest{ diff --git a/testing.go b/testing.go index cafd4fe920..0601d9fa83 100644 --- a/testing.go +++ b/testing.go @@ -19,6 +19,7 @@ var errAlreadyInProgress = regexp.MustCompile(`removal of container .* is alread // This is a function designed to be used in your test, when Docker is not mandatory for CI/CD. // In this way tests that depend on Testcontainers won't run if the provider is provisioned correctly. func SkipIfProviderIsNotHealthy(t *testing.T) { + t.Helper() ctx := context.Background() provider, err := ProviderDocker.GetProvider() if err != nil { @@ -33,6 +34,7 @@ func SkipIfProviderIsNotHealthy(t *testing.T) { // SkipIfDockerDesktop is a utility function capable of skipping tests // if tests are run using Docker Desktop. func SkipIfDockerDesktop(t *testing.T, ctx context.Context) { + t.Helper() cli, err := NewDockerClientWithOpts(ctx) if err != nil { t.Fatalf("failed to create docker client: %s", err) From f1632b35b3a241818697aa338d54b61eb3550f39 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Sat, 19 Oct 2024 00:00:52 +0200 Subject: [PATCH 093/126] chore: use Contains or ErrorContains checks (#2839) Simplify test logic by using require.Contains and require.ErrorContains when possible. Signed-off-by: Matthieu MOREL --- container_test.go | 3 +-- docker_test.go | 2 +- generic_test.go | 5 ++-- modules/redpanda/redpanda_test.go | 7 ++--- modules/registry/registry_test.go | 3 +-- options_test.go | 3 +-- wait/host_port_test.go | 45 +++++++------------------------ 7 files changed, 17 insertions(+), 51 deletions(-) diff --git a/container_test.go b/container_test.go index 562eb038a4..16411283c6 100644 --- a/container_test.go +++ b/container_test.go @@ -376,8 +376,7 @@ func Test_GetLogsFromFailedContainer(t *testing.T) { Started: true, }) testcontainers.CleanupContainer(t, c) - require.Error(t, err) - require.Contains(t, err.Error(), "container exited with code 0") + require.ErrorContains(t, err, "container exited with code 0") logs, logErr := c.Logs(ctx) require.NoError(t, logErr) diff --git a/docker_test.go b/docker_test.go index 0c636d2296..d01f21f01f 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1478,7 +1478,7 @@ func TestDockerCreateContainerWithFiles(t *testing.T) { CleanupContainer(t, nginxC) if err != nil { - require.Contains(t, err.Error(), tc.errMsg) + require.ErrorContains(t, err, tc.errMsg) } else { for _, f := range tc.files { require.NoError(t, err) diff --git a/generic_test.go b/generic_test.go index 2e9bc44d6a..250a9aaab2 100644 --- a/generic_test.go +++ b/generic_test.go @@ -5,7 +5,6 @@ import ( "errors" "os" "os/exec" - "strings" "sync" "testing" "time" @@ -138,8 +137,8 @@ func TestGenericReusableContainerInSubprocess(t *testing.T) { t.Log(output) // check is reuse container with WaitingFor work correctly. - require.True(t, strings.Contains(output, "⏳ Waiting for container id")) - require.True(t, strings.Contains(output, "🔔 Container is ready")) + require.Contains(t, output, "⏳ Waiting for container id") + require.Contains(t, output, "🔔 Container is ready") }() } diff --git a/modules/redpanda/redpanda_test.go b/modules/redpanda/redpanda_test.go index 3983b7f8ba..9697b30525 100644 --- a/modules/redpanda/redpanda_test.go +++ b/modules/redpanda/redpanda_test.go @@ -507,8 +507,7 @@ func TestRedpandaListener_InvalidPort(t *testing.T) { network.WithNetwork([]string{"redpanda-host"}, RPNetwork), ) testcontainers.CleanupContainer(t, ctr) - require.Error(t, err) - require.Contains(t, err.Error(), "invalid port on listener redpanda:99092") + require.ErrorContains(t, err, "invalid port on listener redpanda:99092") } func TestRedpandaListener_NoNetwork(t *testing.T) { @@ -520,9 +519,7 @@ func TestRedpandaListener_NoNetwork(t *testing.T) { redpanda.WithListener("redpanda:99092"), ) testcontainers.CleanupContainer(t, ctr) - require.Error(t, err) - - require.Contains(t, err.Error(), "container must be attached to at least one network") + require.ErrorContains(t, err, "container must be attached to at least one network") } func TestRedpandaBootstrapConfig(t *testing.T) { diff --git a/modules/registry/registry_test.go b/modules/registry/registry_test.go index 6b90349ff3..2b647c2c86 100644 --- a/modules/registry/registry_test.go +++ b/modules/registry/registry_test.go @@ -207,8 +207,7 @@ func TestRunContainer_wrongData(t *testing.T) { Started: true, }) testcontainers.CleanupContainer(t, redisC) - require.Error(t, err) - require.Contains(t, err.Error(), "manifest unknown") + require.ErrorContains(t, err, "manifest unknown") } // setAuthConfig sets the DOCKER_AUTH_CONFIG environment variable with diff --git a/options_test.go b/options_test.go index dbbb2964d6..7ba1b9ef94 100644 --- a/options_test.go +++ b/options_test.go @@ -96,8 +96,7 @@ func TestWithLogConsumers(t *testing.T) { testcontainers.CleanupContainer(t, c) // we expect an error because the MySQL environment variables are not set // but this is expected because we just want to test the log consumer - require.Error(t, err) - require.Contains(t, err.Error(), "container exited with code 1") + require.ErrorContains(t, err, "container exited with code 1") require.NotEmpty(t, lc.msgs) } diff --git a/wait/host_port_test.go b/wait/host_port_test.go index 18a15aed82..1623ef95c0 100644 --- a/wait/host_port_test.go +++ b/wait/host_port_test.go @@ -155,10 +155,7 @@ func TestHostPortStrategyFailsWhileGettingPortDueToOOMKilledContainer(t *testing { err := wg.WaitUntilReady(context.Background(), target) - require.Error(t, err) - - expected := "container crashed with out-of-memory (OOMKilled)" - require.Contains(t, err.Error(), expected) + require.ErrorContains(t, err, "container crashed with out-of-memory (OOMKilled)") } } @@ -189,10 +186,7 @@ func TestHostPortStrategyFailsWhileGettingPortDueToExitedContainer(t *testing.T) { err := wg.WaitUntilReady(context.Background(), target) - require.Error(t, err) - - expected := "container exited with code 1" - require.Contains(t, err.Error(), expected) + require.ErrorContains(t, err, "container exited with code 1") } } @@ -222,10 +216,7 @@ func TestHostPortStrategyFailsWhileGettingPortDueToUnexpectedContainerStatus(t * { err := wg.WaitUntilReady(context.Background(), target) - require.Error(t, err) - - expected := "unexpected container status \"dead\"" - require.Contains(t, err.Error(), expected) + require.ErrorContains(t, err, "unexpected container status \"dead\"") } } @@ -250,10 +241,7 @@ func TestHostPortStrategyFailsWhileExternalCheckingDueToOOMKilledContainer(t *te { err := wg.WaitUntilReady(context.Background(), target) - require.Error(t, err) - - expected := "container crashed with out-of-memory (OOMKilled)" - require.Contains(t, err.Error(), expected) + require.ErrorContains(t, err, "container crashed with out-of-memory (OOMKilled)") } } @@ -279,10 +267,7 @@ func TestHostPortStrategyFailsWhileExternalCheckingDueToExitedContainer(t *testi { err := wg.WaitUntilReady(context.Background(), target) - require.Error(t, err) - - expected := "container exited with code 1" - require.Contains(t, err.Error(), expected) + require.ErrorContains(t, err, "container exited with code 1") } } @@ -307,10 +292,7 @@ func TestHostPortStrategyFailsWhileExternalCheckingDueToUnexpectedContainerStatu { err := wg.WaitUntilReady(context.Background(), target) - require.Error(t, err) - - expected := "unexpected container status \"dead\"" - require.Contains(t, err.Error(), expected) + require.ErrorContains(t, err, "unexpected container status \"dead\"") } } @@ -354,10 +336,7 @@ func TestHostPortStrategyFailsWhileInternalCheckingDueToOOMKilledContainer(t *te { err := wg.WaitUntilReady(context.Background(), target) - require.Error(t, err) - - expected := "container crashed with out-of-memory (OOMKilled)" - require.Contains(t, err.Error(), expected) + require.ErrorContains(t, err, "container crashed with out-of-memory (OOMKilled)") } } @@ -402,10 +381,7 @@ func TestHostPortStrategyFailsWhileInternalCheckingDueToExitedContainer(t *testi { err := wg.WaitUntilReady(context.Background(), target) - require.Error(t, err) - - expected := "container exited with code 1" - require.Contains(t, err.Error(), expected) + require.ErrorContains(t, err, "container exited with code 1") } } @@ -449,10 +425,7 @@ func TestHostPortStrategyFailsWhileInternalCheckingDueToUnexpectedContainerStatu { err := wg.WaitUntilReady(context.Background(), target) - require.Error(t, err) - - expected := "unexpected container status \"dead\"" - require.Contains(t, err.Error(), expected) + require.ErrorContains(t, err, "unexpected container status \"dead\"") } } From 235ab07d4c22fb7bf5ed735731d7a1aeb68018d5 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 21 Oct 2024 12:42:08 +0100 Subject: [PATCH 094/126] fix(postgres): duplicate snapshot name (#2840) Fix postgres snapshot name reuse by removing its template flag before trying to delete it. Fixes #2822 --- modules/postgres/postgres.go | 5 ++++- modules/postgres/postgres_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/modules/postgres/postgres.go b/modules/postgres/postgres.go index b4b59663a2..ac51721f82 100644 --- a/modules/postgres/postgres.go +++ b/modules/postgres/postgres.go @@ -216,7 +216,10 @@ func (c *PostgresContainer) Snapshot(ctx context.Context, opts ...SnapshotOption // execute the commands to create the snapshot, in order if err := c.execCommandsSQL(ctx, - // Drop the snapshot database if it already exists + // Update pg_database to remove the template flag, then drop the database if it exists. + // This is needed because dropping a template database will fail. + // https://www.postgresql.org/docs/current/manage-ag-templatedbs.html + fmt.Sprintf(`UPDATE pg_database SET datistemplate = FALSE WHERE datname = '%s'`, snapshotName), fmt.Sprintf(`DROP DATABASE IF EXISTS "%s"`, snapshotName), // Create a copy of the database to another database to use as a template now that it was fully migrated fmt.Sprintf(`CREATE DATABASE "%s" WITH TEMPLATE "%s" OWNER "%s"`, snapshotName, c.dbName, c.user), diff --git a/modules/postgres/postgres_test.go b/modules/postgres/postgres_test.go index 505fb3b05c..7167da5c51 100644 --- a/modules/postgres/postgres_test.go +++ b/modules/postgres/postgres_test.go @@ -340,6 +340,34 @@ func TestSnapshotWithOverrides(t *testing.T) { }) } +func TestSnapshotDuplicate(t *testing.T) { + ctx := context.Background() + + dbname := "other-db" + user := "other-user" + password := "other-password" + + ctr, err := postgres.Run( + ctx, + "docker.io/postgres:16-alpine", + postgres.WithDatabase(dbname), + postgres.WithUsername(user), + postgres.WithPassword(password), + postgres.BasicWaitStrategies(), + ) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + _, _, err = ctr.Exec(ctx, []string{"psql", "-U", user, "-d", dbname, "-c", "CREATE TABLE users (id SERIAL, name TEXT NOT NULL, age INT NOT NULL)"}) + require.NoError(t, err) + + err = ctr.Snapshot(ctx, postgres.WithSnapshotName("other-snapshot")) + require.NoError(t, err) + + err = ctr.Snapshot(ctx, postgres.WithSnapshotName("other-snapshot")) + require.NoError(t, err) +} + func TestSnapshotWithDockerExecFallback(t *testing.T) { ctx := context.Background() From 2c66f202c5cf6605cbc4cf32329dc065d9cc4d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 21 Oct 2024 13:44:02 +0200 Subject: [PATCH 095/126] feat: add meilisearch-module (#2835) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add meilisearch * fix * fix * fix * fix * fix * fix * resolve comments * chore: add module scaffolding * resolve comments * resolve comments * add test * docs: fix order * chore: clear errors * fix: use Go 1.22 * fix: run make lint * chore: customize error * docs: make explicit that dump files are used * chore: address review comments * fix: do not support updating the master key stored in the container * chore: readability * chore: not needed t.Run * chore: use the variable * chore: no need to defer --------- Co-authored-by: Mashail 🌻 Co-authored-by: Mashail Almuzaini --- .github/workflows/ci.yml | 2 +- .vscode/.testcontainers-go.code-workspace | 4 + docs/modules/meilisearch.md | 77 +++++++++ mkdocs.yml | 1 + modules/meilisearch/Makefile | 5 + modules/meilisearch/examples_test.go | 45 ++++++ modules/meilisearch/go.mod | 63 ++++++++ modules/meilisearch/go.sum | 189 ++++++++++++++++++++++ modules/meilisearch/meilisearch.go | 118 ++++++++++++++ modules/meilisearch/meilisearch_test.go | 83 ++++++++++ modules/meilisearch/options.go | 46 ++++++ modules/meilisearch/testdata/movies.dump | Bin 0 -> 2462 bytes sonar-project.properties | 2 +- 13 files changed, 633 insertions(+), 2 deletions(-) create mode 100644 docs/modules/meilisearch.md create mode 100644 modules/meilisearch/Makefile create mode 100644 modules/meilisearch/examples_test.go create mode 100644 modules/meilisearch/go.mod create mode 100644 modules/meilisearch/go.sum create mode 100644 modules/meilisearch/meilisearch.go create mode 100644 modules/meilisearch/meilisearch_test.go create mode 100644 modules/meilisearch/options.go create mode 100644 modules/meilisearch/testdata/movies.dump diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d45d9b70a..dfb4dc273b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: matrix: go-version: [1.22.x, 1.x] platform: [ubuntu-latest] - module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, dynamodb, elasticsearch, etcd, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate, yugabytedb] + module: [artemis, azurite, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, databend, dolt, dynamodb, elasticsearch, etcd, gcloud, grafana-lgtm, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, meilisearch, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, valkey, vault, vearch, weaviate, yugabytedb] uses: ./.github/workflows/ci-test-go.yml with: go-version: ${{ matrix.go-version }} diff --git a/.vscode/.testcontainers-go.code-workspace b/.vscode/.testcontainers-go.code-workspace index 73e2699036..bc7e7aead9 100644 --- a/.vscode/.testcontainers-go.code-workspace +++ b/.vscode/.testcontainers-go.code-workspace @@ -105,6 +105,10 @@ "name": "module / mariadb", "path": "../modules/mariadb" }, + { + "name": "module / meilisearch", + "path": "../modules/meilisearch" + }, { "name": "module / milvus", "path": "../modules/milvus" diff --git a/docs/modules/meilisearch.md b/docs/modules/meilisearch.md new file mode 100644 index 0000000000..51214761b4 --- /dev/null +++ b/docs/modules/meilisearch.md @@ -0,0 +1,77 @@ +# Meilisearch + +Not available until the next release of testcontainers-go :material-tag: main + +## Introduction + +The Testcontainers module for Meilisearch. + +## Adding this module to your project dependencies + +Please run the following command to add the Meilisearch module to your Go dependencies: + +``` +go get github.com/testcontainers/testcontainers-go/modules/meilisearch +``` + +## Usage example + + +[Creating a Meilisearch container](../../modules/meilisearch/examples_test.go) inside_block:runMeilisearchContainer + + +## Module Reference + +### Run function + +- Not available until the next release of testcontainers-go :material-tag: main + +The Meilisearch module exposes one entrypoint function to create the Meilisearch container, and this function receives three parameters: + +```golang +func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*MeilisearchContainer, error) +``` + +- `context.Context`, the Go context. +- `string`, the Docker image to use. +- `testcontainers.ContainerCustomizer`, a variadic argument for passing options. + +### Container Options + +When starting the Meilisearch container, you can pass options in a variadic way to configure it. + +#### Image + +If you need to set a different Meilisearch Docker image, you can set a valid Docker image as the second argument in the `Run` function. +E.g. `Run(context.Background(), "getmeili/meilisearch:v1.10.3")`. + +{% include "../features/common_functional_options.md" %} + +#### Master Key + +- Not available until the next release of testcontainers-go :material-tag: main + +If you need to set a master key, you can use the `WithMasterKey(key string)` option. Otherwise, the default will be used which is `just-a-master-key-for-test`, which is exported on the container fields. + +#### Dump Data + +- Not available until the next release of testcontainers-go :material-tag: main + +If you need to dump data in Meilisearch upon initialization for testing, you can use `WithDumpData(filepath string)` option where `filepath` can be an absolute path or relative path to a `dump` file. Please refer to the official Meilisearch documentation about dump files [here](https://www.meilisearch.com/docs/learn/advanced/snapshots_vs_dumps#dumps). + +### Container Methods + +The Meilisearch container exposes the following methods: + +#### Address + +- Not available until the next release of testcontainers-go :material-tag: main + +The `Address` method retrieves the address of the Meilisearch container. +It will use http as protocol, as TLS is not supported at the moment. + +#### MasterKey + +- Not available until the next release of testcontainers-go :material-tag: main + +The `MasterKey` method retrieves the master key of the Meilisearch container. diff --git a/mkdocs.yml b/mkdocs.yml index c861b37ac8..b09ec66557 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -88,6 +88,7 @@ nav: - modules/kafka.md - modules/localstack.md - modules/mariadb.md + - modules/meilisearch.md - modules/milvus.md - modules/minio.md - modules/mockserver.md diff --git a/modules/meilisearch/Makefile b/modules/meilisearch/Makefile new file mode 100644 index 0000000000..d1554572d4 --- /dev/null +++ b/modules/meilisearch/Makefile @@ -0,0 +1,5 @@ +include ../../commons-test.mk + +.PHONY: test +test: + $(MAKE) test-meilisearch diff --git a/modules/meilisearch/examples_test.go b/modules/meilisearch/examples_test.go new file mode 100644 index 0000000000..5d41f23f6a --- /dev/null +++ b/modules/meilisearch/examples_test.go @@ -0,0 +1,45 @@ +package meilisearch_test + +import ( + "context" + "fmt" + "log" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/meilisearch" +) + +func ExampleRun() { + // runMeilisearchContainer { + ctx := context.Background() + + meiliContainer, err := meilisearch.Run( + ctx, + "getmeili/meilisearch:v1.10.3", + meilisearch.WithMasterKey("my-master-key"), + meilisearch.WithDumpImport("testdata/movies.dump"), + ) + defer func() { + if err := testcontainers.TerminateContainer(meiliContainer); err != nil { + log.Printf("failed to terminate container: %s", err) + } + }() + if err != nil { + log.Printf("failed to start container: %s", err) + return + } + // } + + state, err := meiliContainer.State(ctx) + if err != nil { + log.Printf("failed to get container state: %s", err) + return + } + + fmt.Println(state.Running) + fmt.Printf("%s\n", meiliContainer.MasterKey()) + + // Output: + // true + // my-master-key +} diff --git a/modules/meilisearch/go.mod b/modules/meilisearch/go.mod new file mode 100644 index 0000000000..2906fdca27 --- /dev/null +++ b/modules/meilisearch/go.mod @@ -0,0 +1,63 @@ +module github.com/testcontainers/testcontainers-go/modules/meilisearch + +go 1.22 + +require ( + github.com/stretchr/testify v1.9.0 + github.com/testcontainers/testcontainers-go v0.33.0 +) + +require ( + dario.cat/mergo v1.0.0 // indirect + github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/docker v27.3.1+incompatible // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.5.0 // indirect + github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/shirou/gopsutil/v3 v3.23.12 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.31.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 // indirect + go.opentelemetry.io/otel/metric v1.31.0 // indirect + go.opentelemetry.io/otel/sdk v1.31.0 // indirect + go.opentelemetry.io/otel/trace v1.31.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/time v0.7.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/meilisearch/go.sum b/modules/meilisearch/go.sum new file mode 100644 index 0000000000..556ed40640 --- /dev/null +++ b/modules/meilisearch/go.sum @@ -0,0 +1,189 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +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/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +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.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +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.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= +github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4= +go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= +go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +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/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg= +google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/modules/meilisearch/meilisearch.go b/modules/meilisearch/meilisearch.go new file mode 100644 index 0000000000..7d184eecb0 --- /dev/null +++ b/modules/meilisearch/meilisearch.go @@ -0,0 +1,118 @@ +package meilisearch + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net" + "net/http" + "time" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +const ( + defaultMasterKey = "just-a-master-key-for-test" + defaultHTTPPort = "7700/tcp" + masterKeyEnvVar = "MEILI_MASTER_KEY" +) + +// MeilisearchContainer represents the Meilisearch container type used in the module +type MeilisearchContainer struct { + testcontainers.Container + masterKey string +} + +// MasterKey retrieves the master key of the Meilisearch container +func (c *MeilisearchContainer) MasterKey() string { + return c.masterKey +} + +// Run creates an instance of the Meilisearch container type +func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*MeilisearchContainer, error) { + req := testcontainers.ContainerRequest{ + Image: img, + ExposedPorts: []string{defaultHTTPPort}, + Env: map[string]string{ + masterKeyEnvVar: defaultMasterKey, + }, + } + + genericContainerReq := testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + } + + // Gather all config options (defaults and then apply provided options) + settings := defaultOptions() + for _, opt := range opts { + if apply, ok := opt.(Option); ok { + apply(settings) + } + if err := opt.Customize(&genericContainerReq); err != nil { + return nil, fmt.Errorf("customize: %w", err) + } + } + + if settings.DumpDataFilePath != "" { + genericContainerReq.Files = []testcontainers.ContainerFile{ + { + HostFilePath: settings.DumpDataFilePath, + ContainerFilePath: "/dumps/" + settings.DumpDataFileName, + FileMode: 0o755, + }, + } + genericContainerReq.Cmd = []string{"meilisearch", "--import-dump", fmt.Sprintf("/dumps/%s", settings.DumpDataFileName)} + } + + // the wait strategy does not support TLS at the moment, + // so we need to disable it in the strategy for now. + genericContainerReq.WaitingFor = wait.ForHTTP("/health"). + WithPort(defaultHTTPPort). + WithTLS(false). + WithStartupTimeout(120 * time.Second). + WithStatusCodeMatcher(func(status int) bool { + return status == http.StatusOK + }). + WithResponseMatcher(func(body io.Reader) bool { + decoder := json.NewDecoder(body) + r := struct { + Status string `json:"status"` + }{} + if err := decoder.Decode(&r); err != nil { + return false + } + + return r.Status == "available" + }) + + container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + var c *MeilisearchContainer + if container != nil { + c = &MeilisearchContainer{Container: container, masterKey: req.Env[masterKeyEnvVar]} + } + + if err != nil { + return c, fmt.Errorf("generic container: %w", err) + } + + return c, nil +} + +// Address retrieves the address of the Meilisearch container. +// It will use http as protocol, as TLS is not supported at the moment. +func (c *MeilisearchContainer) Address(ctx context.Context) (string, error) { + containerPort, err := c.MappedPort(ctx, defaultHTTPPort) + if err != nil { + return "", fmt.Errorf("mapped port: %w", err) + } + + host, err := c.Host(ctx) + if err != nil { + return "", fmt.Errorf("host: %w", err) + } + + return "http://" + net.JoinHostPort(host, containerPort.Port()), nil +} diff --git a/modules/meilisearch/meilisearch_test.go b/modules/meilisearch/meilisearch_test.go new file mode 100644 index 0000000000..5c351419e9 --- /dev/null +++ b/modules/meilisearch/meilisearch_test.go @@ -0,0 +1,83 @@ +package meilisearch_test + +import ( + "context" + "io" + "net/http" + "net/url" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/meilisearch" +) + +func TestMeilisearch(t *testing.T) { + ctx := context.Background() + + ctr, err := meilisearch.Run(ctx, "getmeili/meilisearch:v1.10.3") + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + address, err := ctr.Address(ctx) + require.NoError(t, err) + + req, err := http.NewRequest(http.MethodGet, address, nil) + require.NoError(t, err) + + resp, err := http.DefaultClient.Do(req) + require.NoError(t, err) + resp.Body.Close() +} + +func TestMeilisearch_WithDataDump(t *testing.T) { + ctx := context.Background() + + ctr, err := meilisearch.Run(ctx, "getmeili/meilisearch:v1.10.3", + meilisearch.WithDumpImport("testdata/movies.dump"), + meilisearch.WithMasterKey("my-master-key"), + ) + testcontainers.CleanupContainer(t, ctr) + require.NoError(t, err) + + address, err := ctr.Address(ctx) + require.NoError(t, err) + + client := http.DefaultClient + + req, err := http.NewRequest(http.MethodGet, address, nil) + require.NoError(t, err) + + resp, err := client.Do(req) + require.NoError(t, err) + resp.Body.Close() // not closing the body in a defer as it's not used anymore + + require.EqualValues(t, http.StatusOK, resp.StatusCode) + + path, err := url.JoinPath(address, "/indexes/movies/documents/1212") + require.NoError(t, err) + + req, err = http.NewRequest(http.MethodGet, path, nil) + require.NoError(t, err) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", "Bearer my-master-key") + + resp, err = client.Do(req) + require.NoError(t, err) + defer resp.Body.Close() + + require.EqualValues(t, http.StatusOK, resp.StatusCode) + + bodyBytes, err := io.ReadAll(resp.Body) + require.NoError(t, err) + + // Assert the response of that document. + require.JSONEq(t, `{ + "movie_id": 1212, + "overview": "When a scientists daughter is kidnapped, American Ninja, attempts to find her, but this time he teams up with a youngster he has trained in the ways of the ninja.", + "poster": "https://image.tmdb.org/t/p/w1280/iuAQVI4mvjI83wnirpD8GVNRVuY.jpg", + "release_date": 725846400, + "title": "American Ninja 5" +}`, string(bodyBytes)) +} diff --git a/modules/meilisearch/options.go b/modules/meilisearch/options.go new file mode 100644 index 0000000000..06df8b4435 --- /dev/null +++ b/modules/meilisearch/options.go @@ -0,0 +1,46 @@ +package meilisearch + +import ( + "path/filepath" + + "github.com/testcontainers/testcontainers-go" +) + +// Options is a struct for specifying options for the Meilisearch container. +type Options struct { + DumpDataFilePath string + DumpDataFileName string +} + +func defaultOptions() *Options { + return &Options{} +} + +// Compiler check to ensure that Option implements the testcontainers.ContainerCustomizer interface. +var _ testcontainers.ContainerCustomizer = (*Option)(nil) + +// Option is an option for the Meilisearch container. +type Option func(*Options) + +// Customize is a NOOP. It's defined to satisfy the testcontainers.ContainerCustomizer interface. +func (o Option) Customize(*testcontainers.GenericContainerRequest) error { + // NOOP to satisfy interface. + return nil +} + +// WithDumpImport sets the data dump file path for the Meilisearch container. +// dumpFilePath either relative to where you call meilisearch run or absolute path +func WithDumpImport(dumpFilePath string) Option { + return func(o *Options) { + o.DumpDataFilePath, o.DumpDataFileName = dumpFilePath, filepath.Base(dumpFilePath) + } +} + +// WithMasterKey sets the master key for the Meilisearch container +// it satisfies the testcontainers.ContainerCustomizer interface +func WithMasterKey(masterKey string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + req.Env["MEILI_MASTER_KEY"] = masterKey + return nil + } +} diff --git a/modules/meilisearch/testdata/movies.dump b/modules/meilisearch/testdata/movies.dump new file mode 100644 index 0000000000000000000000000000000000000000..f6b83419a825bdbebd0fff19fb75129cffd57fbb GIT binary patch literal 2462 zcmV;P31RjhiwFP!00000|Lt5`bKAHT*7N=fmVM|<#-afbAOO92<4No3bT`e#JI%Ty z!z5%erbw0-JF3V3eGhnXB-;_aiKR`lI5UYQ;3Ej)-~$dmQ1JFgTQ`I#;*7!H#_s-Y zK4Z!e@iAfnHtF1_bi_tGu)3^N;W(o&wYv}Zjo3n0DpHm5-j`WA+KwTNPyqh?l>aed zcl?iWVEW5w2lglT|Fs*{i~Lv@Wt^q%#61q&JvTc0n1DTuJYo_7cc>~2X#^2E#%PT3 z8-gZGObGKNa8_a=#5?z9WbIqA3%x8G?kA(I*#Q4BhP=D{CnT`^-+=-Dbr}|MUbS?8 zTWTk+oGNolt%`8&%!+K`RC8@Uq?Jx17z$FgFvGy1o~b&ioYyV#;N_9?PrZcvI*uS) z%w!ZQOvfQTV`EBWIF=DQ8`DrmnzJ*GLCdLrjg{rPQ05}fd9G^n;V;f%)?nZXvbLBkg$wffEQ!Mnjd~C*;`Cmd zYIcTn$k8~81hga#qOsDPkEM)c5a1AnQm(h@v!`oLDjB2vvCY||Z+;kA`)aN08KZ65 z?~nh@UvA_79a!i8{Y7>eZ>t-8hW`oT*!q75w(kG^ttVFtPF94(z%M zEL#7=)SegdLKRCBbabiH*n}rtfN=1@jL#>Gcs`Z^WipT}@xcRN#wQrSj0-^+3hZL> z54Jn}kFu~{=(Kv$HQ^Bd*?s;qV)?%lyZ*>=ASNbzZWULFS%@4gbP(?8|2{sVi_7;%!oN!6B0m&= zKmO^}as40feSQvQWtX~u8(%?bzs$8+5|v>LJufb+(uq`kK8IVG1=d9zr7F*LwCAi> zY0ptrr58EiVYxbkp6twZvFDuCuzsDxl~ugZkmOWaElQ`(ovXN-!;O|%ot~Q~F`07( zz(U2TjvQEUnU(I9T9!^WYd)vuP9D^^(1}*1o<@xX#t9QNpa^~ItD8IgFLhPH>bBhF z{15ui1M@$(`p+&5q>i}E6SXw6bydVbo)w*-l{M5^q94ed#R+ieUZ%M$E2@Xm3zc3# z?|M}yZ829_5t*2yTIN|3dSoBsMO+!VL-m)sZE>ytby+qwtFru;=JKZGG)rIW zT!HwK6>qW&o%S_(C^3o~c?6=I4zz^JmkY?fzA?EaP#~;sE8j~bx7B-D=rHc&@w26= zMfVJEvIH6=4dIe&SEr^4U|6k+TJO1_<{0Gb`2YF^R0q)Jer}d(^Vyv+DB>#X(q&r@ zQ^3#Z%46Q9t+y>DS^LY2U?t@R?4W#hZA+CT|} zIn{)GDjClp#IHdYeB#Z(!TmoL+#CO?jsJFH*Y2ebVSIcI|6tgfsiZW6l?D=rAwW< zR{z_+HU8iKU#)AswQbB`x?YbBUZBx}S4Y*|;hFV9u zi*%a+x4GcCkp;VOv6Bv`7wg)gi7O+}mE)v|c#q6wN9imZxJ0K-uiT_K1`s6#T)b;* zT5Ogl1#Bt^2xQ%wryKw#IX$V?k)eH_QNwTYH+hXBuKQW8{J6)nL=pcd^8bCi6?F~#GC<{8i z)Y0_z4j%`e^;GnUUelNEM42wrzf~Y`UTP3MPy6n6>fCB86X*2$#Eqj9-~$T;-8*U3 zU-*7(_ysIKbL+8o6YVKD z`B2FNl#~}rKF|g21-)ykpO}c8TfRN zk_{MkMF?SXn3D~fVZr;?85>G6OG!&fOUVtCWYi-PVd*2u1}WKsB?>qhW@G~X$4ZGn+Z$qJhbBUT3b-1#3MEx(3u9y z5Cp&=ybe3FMZ@??@oK~)?eJ=cS3A6JV5IK}%s8y|+gIr~Q__HgfP#pCA3;fj20SH_ zu5N50%Sp>g%gGI#lpcuZKBvAIrli3#v*pOxBPeOmoC)(Qh*e5rOG!&fOUX}Bl9+9M zpD+@k&7ADe!si%^RZ0>|NlQsf$&Hj09CP6ZzI+TN1t&BBM#@J~ zQgELGf9dLC68lyf*pf6rCw|~zE-{v3=ncCLED-FQ2!BxM>CpiV_}V)Im|Ayk$(?M1 zgokAyOSf#OIf#Q90;=ZRu;A!&UVJMGv)?PVp#n#!6ZV`ALL{Mme{9) z`oo+w=m0Sy$a)kTe8!93-vKT0z#HY=u@n@R`3U=Xz!}{c7RbkvYWu=;2JzSyehm0I=YMfx&;Qzmt+Lvy;lI(-+tBa7(f#vZ3G=!A c{ofAkF~j)Cnl)?ItbKR(8zx0@umEHL09)tFEdT%j literal 0 HcmV?d00001 diff --git a/sonar-project.properties b/sonar-project.properties index b0531a66c1..504e1f03ef 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -18,4 +18,4 @@ sonar.test.inclusions=**/*_test.go sonar.test.exclusions=**/vendor/** sonar.go.coverage.reportPaths=**/coverage.out -sonar.go.tests.reportPaths=TEST-unit.xml,examples/nginx/TEST-unit.xml,examples/toxiproxy/TEST-unit.xml,modulegen/TEST-unit.xml,modules/artemis/TEST-unit.xml,modules/azurite/TEST-unit.xml,modules/cassandra/TEST-unit.xml,modules/chroma/TEST-unit.xml,modules/clickhouse/TEST-unit.xml,modules/cockroachdb/TEST-unit.xml,modules/compose/TEST-unit.xml,modules/consul/TEST-unit.xml,modules/couchbase/TEST-unit.xml,modules/databend/TEST-unit.xml,modules/dolt/TEST-unit.xml,modules/dynamodb/TEST-unit.xml,modules/elasticsearch/TEST-unit.xml,modules/etcd/TEST-unit.xml,modules/gcloud/TEST-unit.xml,modules/grafana-lgtm/TEST-unit.xml,modules/inbucket/TEST-unit.xml,modules/influxdb/TEST-unit.xml,modules/k3s/TEST-unit.xml,modules/k6/TEST-unit.xml,modules/kafka/TEST-unit.xml,modules/localstack/TEST-unit.xml,modules/mariadb/TEST-unit.xml,modules/milvus/TEST-unit.xml,modules/minio/TEST-unit.xml,modules/mockserver/TEST-unit.xml,modules/mongodb/TEST-unit.xml,modules/mssql/TEST-unit.xml,modules/mysql/TEST-unit.xml,modules/nats/TEST-unit.xml,modules/neo4j/TEST-unit.xml,modules/ollama/TEST-unit.xml,modules/openfga/TEST-unit.xml,modules/openldap/TEST-unit.xml,modules/opensearch/TEST-unit.xml,modules/postgres/TEST-unit.xml,modules/pulsar/TEST-unit.xml,modules/qdrant/TEST-unit.xml,modules/rabbitmq/TEST-unit.xml,modules/redis/TEST-unit.xml,modules/redpanda/TEST-unit.xml,modules/registry/TEST-unit.xml,modules/surrealdb/TEST-unit.xml,modules/valkey/TEST-unit.xml,modules/vault/TEST-unit.xml,modules/vearch/TEST-unit.xml,modules/weaviate/TEST-unit.xml,modules/yugabytedb/TEST-unit.xml +sonar.go.tests.reportPaths=TEST-unit.xml,examples/nginx/TEST-unit.xml,examples/toxiproxy/TEST-unit.xml,modulegen/TEST-unit.xml,modules/artemis/TEST-unit.xml,modules/azurite/TEST-unit.xml,modules/cassandra/TEST-unit.xml,modules/chroma/TEST-unit.xml,modules/clickhouse/TEST-unit.xml,modules/cockroachdb/TEST-unit.xml,modules/compose/TEST-unit.xml,modules/consul/TEST-unit.xml,modules/couchbase/TEST-unit.xml,modules/databend/TEST-unit.xml,modules/dolt/TEST-unit.xml,modules/dynamodb/TEST-unit.xml,modules/elasticsearch/TEST-unit.xml,modules/etcd/TEST-unit.xml,modules/gcloud/TEST-unit.xml,modules/grafana-lgtm/TEST-unit.xml,modules/inbucket/TEST-unit.xml,modules/influxdb/TEST-unit.xml,modules/k3s/TEST-unit.xml,modules/k6/TEST-unit.xml,modules/kafka/TEST-unit.xml,modules/localstack/TEST-unit.xml,modules/mariadb/TEST-unit.xml,modules/meilisearch/TEST-unit.xml,modules/milvus/TEST-unit.xml,modules/minio/TEST-unit.xml,modules/mockserver/TEST-unit.xml,modules/mongodb/TEST-unit.xml,modules/mssql/TEST-unit.xml,modules/mysql/TEST-unit.xml,modules/nats/TEST-unit.xml,modules/neo4j/TEST-unit.xml,modules/ollama/TEST-unit.xml,modules/openfga/TEST-unit.xml,modules/openldap/TEST-unit.xml,modules/opensearch/TEST-unit.xml,modules/postgres/TEST-unit.xml,modules/pulsar/TEST-unit.xml,modules/qdrant/TEST-unit.xml,modules/rabbitmq/TEST-unit.xml,modules/redis/TEST-unit.xml,modules/redpanda/TEST-unit.xml,modules/registry/TEST-unit.xml,modules/surrealdb/TEST-unit.xml,modules/valkey/TEST-unit.xml,modules/vault/TEST-unit.xml,modules/vearch/TEST-unit.xml,modules/weaviate/TEST-unit.xml,modules/yugabytedb/TEST-unit.xml From 7d0f970ea5e25911e2f67f5fd4aff969067185a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 21 Oct 2024 14:26:26 +0200 Subject: [PATCH 096/126] chore: use new version (v0.34.0) in modules and examples --- docs/modules/databend.md | 4 ++-- docs/modules/dynamodb.md | 10 +++++----- docs/modules/etcd.md | 18 +++++++++--------- docs/modules/meilisearch.md | 12 ++++++------ docs/modules/yugabytedb.md | 2 +- examples/nginx/go.mod | 2 +- examples/toxiproxy/go.mod | 2 +- mkdocs.yml | 2 +- modules/artemis/go.mod | 2 +- modules/azurite/go.mod | 2 +- modules/cassandra/go.mod | 2 +- modules/chroma/go.mod | 2 +- modules/clickhouse/go.mod | 2 +- modules/cockroachdb/go.mod | 2 +- modules/compose/go.mod | 2 +- modules/consul/go.mod | 2 +- modules/couchbase/go.mod | 2 +- modules/databend/go.mod | 2 +- modules/dolt/go.mod | 2 +- modules/dynamodb/go.mod | 2 +- modules/elasticsearch/go.mod | 2 +- modules/etcd/go.mod | 2 +- modules/gcloud/go.mod | 2 +- modules/grafana-lgtm/go.mod | 2 +- modules/inbucket/go.mod | 2 +- modules/influxdb/go.mod | 2 +- modules/k3s/go.mod | 2 +- modules/k6/go.mod | 2 +- modules/kafka/go.mod | 2 +- modules/localstack/go.mod | 2 +- modules/mariadb/go.mod | 2 +- modules/meilisearch/go.mod | 2 +- modules/milvus/go.mod | 2 +- modules/minio/go.mod | 2 +- modules/mockserver/go.mod | 2 +- modules/mongodb/go.mod | 2 +- modules/mssql/go.mod | 2 +- modules/mysql/go.mod | 2 +- modules/nats/go.mod | 2 +- modules/neo4j/go.mod | 2 +- modules/ollama/go.mod | 2 +- modules/openfga/go.mod | 2 +- modules/openldap/go.mod | 2 +- modules/opensearch/go.mod | 2 +- modules/postgres/go.mod | 2 +- modules/pulsar/go.mod | 2 +- modules/qdrant/go.mod | 2 +- modules/rabbitmq/go.mod | 2 +- modules/redis/go.mod | 2 +- modules/redpanda/go.mod | 2 +- modules/registry/go.mod | 2 +- modules/surrealdb/go.mod | 2 +- modules/valkey/go.mod | 2 +- modules/vault/go.mod | 2 +- modules/vearch/go.mod | 2 +- modules/weaviate/go.mod | 2 +- modules/yugabytedb/go.mod | 2 +- sonar-project.properties | 2 +- 58 files changed, 76 insertions(+), 76 deletions(-) diff --git a/docs/modules/databend.md b/docs/modules/databend.md index 450595a264..0e3e2fe438 100644 --- a/docs/modules/databend.md +++ b/docs/modules/databend.md @@ -1,6 +1,6 @@ # Databend -Not available until the next release of testcontainers-go :material-tag: main +Since testcontainers-go :material-tag: v0.34.0 ## Introduction @@ -24,7 +24,7 @@ go get github.com/testcontainers/testcontainers-go/modules/databend ### Run function -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 The Databend module exposes one entrypoint function to create the Databend container, and this function receives three parameters: diff --git a/docs/modules/dynamodb.md b/docs/modules/dynamodb.md index cdc7312640..b7b53b64e9 100644 --- a/docs/modules/dynamodb.md +++ b/docs/modules/dynamodb.md @@ -1,6 +1,6 @@ # DynamoDB -Not available until the next release of testcontainers-go :material-tag: main +Since testcontainers-go :material-tag: v0.34.0 ## Introduction @@ -24,7 +24,7 @@ go get github.com/testcontainers/testcontainers-go/modules/dynamodb ### Run function -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 The DynamoDB module exposes one entrypoint function to create the DynamoDB container, and this function receives three parameters: @@ -49,13 +49,13 @@ E.g. `Run(context.Background(), "amazon/dynamodb-local:2.2.1")`. #### WithSharedDB -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 The `WithSharedDB` option tells the DynamoDB container to use a single database file. At the same time, it marks the container as reusable, which causes that successive calls to the `Run` function will return the same container instance, and therefore, the same database file. #### WithDisableTelemetry -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 You can turn off telemetry when starting the DynamoDB container, using the option `WithDisableTelemetry`. @@ -65,7 +65,7 @@ The DynamoDB container exposes the following methods: #### ConnectionString -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 The `ConnectionString` method returns the connection string to the DynamoDB container. This connection string can be used to connect to the DynamoDB container from your application, using the AWS SDK or any other DynamoDB client of your choice. diff --git a/docs/modules/etcd.md b/docs/modules/etcd.md index f83816c986..ffde87ac6b 100644 --- a/docs/modules/etcd.md +++ b/docs/modules/etcd.md @@ -1,6 +1,6 @@ # etcd -Not available until the next release of testcontainers-go :material-tag: main +Since testcontainers-go :material-tag: v0.34.0 ## Introduction @@ -24,7 +24,7 @@ go get github.com/testcontainers/testcontainers-go/modules/etcd ### Run function -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 The etcd module exposes one entrypoint function to create the etcd container, and this function receives three parameters: @@ -49,19 +49,19 @@ E.g. `Run(context.Background(), "bitnami/etcd:latest")`. #### WithAdditionalArgs -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 You can pass additional arguments to the etcd container by using the `WithAdditionalArgs` option. The arguments are passed to the CMD of the etcd container. #### WithDataDir -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 You can set the data directory for the etcd container by using the `WithDataDir` boolean option. The data directory where the etcd data is stored is `/data.etcd`. #### WithNodes -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 You can set the number of nodes for the etcd cluster by using the `WithNodes` option, passing the node names for each of the nodes. Single-node clusters are not allowed, for that reason the functional option receives three string arguments: the first node, the second node, and a variadic argument for the rest of the nodes. @@ -71,25 +71,25 @@ The module creates a Docker network for the etcd cluster, and the nodes are conn #### WithClusterToken -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 Sets the cluster token for the etcd cluster. The cluster token is used to identify the etcd cluster. The default value is `mys3cr3ttok3n`. The etcd container holds a reference to the cluster token, so you can use it with e.g. `ctr.ClusterToken`. ### Container Methods -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 The etcd container exposes the following methods: #### ClientEndpoint -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 Returns the client endpoint for the etcd container and an error, if any. In the case of a cluster, it returns the client endpoint for the first node. #### PeerEndpoint -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 Returns the peer endpoint for the etcd container and an error, if any. In the case of a cluster, it returns the peer endpoint for the first node. diff --git a/docs/modules/meilisearch.md b/docs/modules/meilisearch.md index 51214761b4..d8fe865be0 100644 --- a/docs/modules/meilisearch.md +++ b/docs/modules/meilisearch.md @@ -1,6 +1,6 @@ # Meilisearch -Not available until the next release of testcontainers-go :material-tag: main +Since testcontainers-go :material-tag: v0.34.0 ## Introduction @@ -24,7 +24,7 @@ go get github.com/testcontainers/testcontainers-go/modules/meilisearch ### Run function -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 The Meilisearch module exposes one entrypoint function to create the Meilisearch container, and this function receives three parameters: @@ -49,13 +49,13 @@ E.g. `Run(context.Background(), "getmeili/meilisearch:v1.10.3")`. #### Master Key -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 If you need to set a master key, you can use the `WithMasterKey(key string)` option. Otherwise, the default will be used which is `just-a-master-key-for-test`, which is exported on the container fields. #### Dump Data -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 If you need to dump data in Meilisearch upon initialization for testing, you can use `WithDumpData(filepath string)` option where `filepath` can be an absolute path or relative path to a `dump` file. Please refer to the official Meilisearch documentation about dump files [here](https://www.meilisearch.com/docs/learn/advanced/snapshots_vs_dumps#dumps). @@ -65,13 +65,13 @@ The Meilisearch container exposes the following methods: #### Address -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 The `Address` method retrieves the address of the Meilisearch container. It will use http as protocol, as TLS is not supported at the moment. #### MasterKey -- Not available until the next release of testcontainers-go :material-tag: main +- Since testcontainers-go :material-tag: v0.34.0 The `MasterKey` method retrieves the master key of the Meilisearch container. diff --git a/docs/modules/yugabytedb.md b/docs/modules/yugabytedb.md index b645d678c9..9922c48574 100644 --- a/docs/modules/yugabytedb.md +++ b/docs/modules/yugabytedb.md @@ -1,6 +1,6 @@ # YugabyteDB -Not available until the next release of testcontainers-go :material-tag: main +Since testcontainers-go :material-tag: v0.34.0 ## Introduction diff --git a/examples/nginx/go.mod b/examples/nginx/go.mod index 186070ac1e..19543c9484 100644 --- a/examples/nginx/go.mod +++ b/examples/nginx/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/examples/toxiproxy/go.mod b/examples/toxiproxy/go.mod index a15d130181..0862d21e8a 100644 --- a/examples/toxiproxy/go.mod +++ b/examples/toxiproxy/go.mod @@ -7,7 +7,7 @@ require ( github.com/go-redis/redis/v8 v8.11.5 github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/mkdocs.yml b/mkdocs.yml index b09ec66557..2d80a5b420 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -140,4 +140,4 @@ nav: - Getting help: getting_help.md edit_uri: edit/main/docs/ extra: - latest_version: v0.33.0 + latest_version: v0.34.0 diff --git a/modules/artemis/go.mod b/modules/artemis/go.mod index cd2c28ae3a..b2088afe4d 100644 --- a/modules/artemis/go.mod +++ b/modules/artemis/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/go-stomp/stomp/v3 v3.0.5 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/azurite/go.mod b/modules/azurite/go.mod index 0855bdcfb3..e07abe4f5f 100644 --- a/modules/azurite/go.mod +++ b/modules/azurite/go.mod @@ -9,7 +9,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue v1.0.0 github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/cassandra/go.mod b/modules/cassandra/go.mod index 7f75e81bb4..3136506c9d 100644 --- a/modules/cassandra/go.mod +++ b/modules/cassandra/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/gocql/gocql v1.6.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/chroma/go.mod b/modules/chroma/go.mod index 616f0df680..1cb622ea1d 100644 --- a/modules/chroma/go.mod +++ b/modules/chroma/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/amikos-tech/chroma-go v0.1.2 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/clickhouse/go.mod b/modules/clickhouse/go.mod index ad2e8b0033..a471fff126 100644 --- a/modules/clickhouse/go.mod +++ b/modules/clickhouse/go.mod @@ -7,7 +7,7 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/cockroachdb/go.mod b/modules/cockroachdb/go.mod index e26132e941..fd7e17baa1 100644 --- a/modules/cockroachdb/go.mod +++ b/modules/cockroachdb/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/jackc/pgx/v5 v5.5.4 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/compose/go.mod b/modules/compose/go.mod index 16f28c9da3..35ab7d526b 100644 --- a/modules/compose/go.mod +++ b/modules/compose/go.mod @@ -11,7 +11,7 @@ require ( github.com/docker/docker v27.1.1+incompatible github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 golang.org/x/sync v0.7.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/modules/consul/go.mod b/modules/consul/go.mod index ee6d9c2bd9..b77596a1b7 100644 --- a/modules/consul/go.mod +++ b/modules/consul/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/hashicorp/consul/api v1.27.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/couchbase/go.mod b/modules/couchbase/go.mod index 7eee2904d4..d31b6f080d 100644 --- a/modules/couchbase/go.mod +++ b/modules/couchbase/go.mod @@ -7,7 +7,7 @@ require ( github.com/couchbase/gocb/v2 v2.7.2 github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 github.com/tidwall/gjson v1.17.1 ) diff --git a/modules/databend/go.mod b/modules/databend/go.mod index e4892363cc..c16777822e 100644 --- a/modules/databend/go.mod +++ b/modules/databend/go.mod @@ -5,7 +5,7 @@ go 1.22.0 require ( github.com/datafuselabs/databend-go v0.7.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/dolt/go.mod b/modules/dolt/go.mod index 189b6a7701..d363787d92 100644 --- a/modules/dolt/go.mod +++ b/modules/dolt/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/go-sql-driver/mysql v1.7.1 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/dynamodb/go.mod b/modules/dynamodb/go.mod index 08d4eab7c1..75804011b0 100644 --- a/modules/dynamodb/go.mod +++ b/modules/dynamodb/go.mod @@ -9,7 +9,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/dynamodb v1.35.1 github.com/aws/smithy-go v1.21.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/elasticsearch/go.mod b/modules/elasticsearch/go.mod index a56a624637..108bc46b4e 100644 --- a/modules/elasticsearch/go.mod +++ b/modules/elasticsearch/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/elastic/go-elasticsearch/v8 v8.12.1 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 golang.org/x/mod v0.16.0 ) diff --git a/modules/etcd/go.mod b/modules/etcd/go.mod index fb5e7f39d8..a1ecca2f68 100644 --- a/modules/etcd/go.mod +++ b/modules/etcd/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/docker/docker v27.1.1+incompatible github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 go.etcd.io/etcd/client/v3 v3.5.16 ) diff --git a/modules/gcloud/go.mod b/modules/gcloud/go.mod index 8ba19423ab..ab30a75a7b 100644 --- a/modules/gcloud/go.mod +++ b/modules/gcloud/go.mod @@ -10,7 +10,7 @@ require ( cloud.google.com/go/pubsub v1.36.2 cloud.google.com/go/spanner v1.57.0 github.com/docker/go-connections v0.5.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 google.golang.org/api v0.169.0 google.golang.org/grpc v1.64.1 ) diff --git a/modules/grafana-lgtm/go.mod b/modules/grafana-lgtm/go.mod index 26abe93727..c5be803b14 100644 --- a/modules/grafana-lgtm/go.mod +++ b/modules/grafana-lgtm/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 go.opentelemetry.io/contrib/bridges/otelslog v0.3.0 go.opentelemetry.io/contrib/instrumentation/runtime v0.53.0 go.opentelemetry.io/otel v1.28.0 diff --git a/modules/inbucket/go.mod b/modules/inbucket/go.mod index e64575c11c..da34424539 100644 --- a/modules/inbucket/go.mod +++ b/modules/inbucket/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/inbucket/inbucket v2.0.0+incompatible github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/influxdb/go.mod b/modules/influxdb/go.mod index bdac56db10..9931d3bd7d 100644 --- a/modules/influxdb/go.mod +++ b/modules/influxdb/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/k3s/go.mod b/modules/k3s/go.mod index 6ef16a669d..f329ae688b 100644 --- a/modules/k3s/go.mod +++ b/modules/k3s/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.29.2 k8s.io/apimachinery v0.29.2 diff --git a/modules/k6/go.mod b/modules/k6/go.mod index 897cf23fe6..356b3750a5 100644 --- a/modules/k6/go.mod +++ b/modules/k6/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/docker/docker v27.1.1+incompatible github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/kafka/go.mod b/modules/kafka/go.mod index f8e135d941..9c447008a1 100644 --- a/modules/kafka/go.mod +++ b/modules/kafka/go.mod @@ -6,7 +6,7 @@ require ( github.com/IBM/sarama v1.42.1 github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 golang.org/x/mod v0.16.0 ) diff --git a/modules/localstack/go.mod b/modules/localstack/go.mod index 333b5279b0..52c3e446cc 100644 --- a/modules/localstack/go.mod +++ b/modules/localstack/go.mod @@ -11,7 +11,7 @@ require ( github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 golang.org/x/mod v0.16.0 ) diff --git a/modules/mariadb/go.mod b/modules/mariadb/go.mod index 8a911aaff2..17e77ad48a 100644 --- a/modules/mariadb/go.mod +++ b/modules/mariadb/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/go-sql-driver/mysql v1.7.1 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/meilisearch/go.mod b/modules/meilisearch/go.mod index 2906fdca27..e63f289944 100644 --- a/modules/meilisearch/go.mod +++ b/modules/meilisearch/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/milvus/go.mod b/modules/milvus/go.mod index d743fcd143..c11bcc5d73 100644 --- a/modules/milvus/go.mod +++ b/modules/milvus/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/milvus-io/milvus-sdk-go/v2 v2.4.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/minio/go.mod b/modules/minio/go.mod index 3ed9eac6de..be57f29aef 100644 --- a/modules/minio/go.mod +++ b/modules/minio/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/minio/minio-go/v7 v7.0.68 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/mockserver/go.mod b/modules/mockserver/go.mod index 4ce03a96e0..8c8fb8fb8f 100644 --- a/modules/mockserver/go.mod +++ b/modules/mockserver/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( github.com/BraspagDevelopers/mock-server-client v0.2.2 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/mongodb/go.mod b/modules/mongodb/go.mod index a6433e76f1..a1f0450e3f 100644 --- a/modules/mongodb/go.mod +++ b/modules/mongodb/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 go.mongodb.org/mongo-driver v1.13.1 ) diff --git a/modules/mssql/go.mod b/modules/mssql/go.mod index c61a8691f9..b9fd2f4677 100644 --- a/modules/mssql/go.mod +++ b/modules/mssql/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/microsoft/go-mssqldb v1.7.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/mysql/go.mod b/modules/mysql/go.mod index 9f2ddb5634..9605729d57 100644 --- a/modules/mysql/go.mod +++ b/modules/mysql/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/go-sql-driver/mysql v1.7.1 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) diff --git a/modules/nats/go.mod b/modules/nats/go.mod index 823cf79e58..b65abf1dce 100644 --- a/modules/nats/go.mod +++ b/modules/nats/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/nats-io/nats.go v1.33.1 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/neo4j/go.mod b/modules/neo4j/go.mod index 61893d0dfe..0f73bc4a33 100644 --- a/modules/neo4j/go.mod +++ b/modules/neo4j/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/neo4j/neo4j-go-driver/v5 v5.18.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/ollama/go.mod b/modules/ollama/go.mod index 23ae742e4d..3fb6b744ea 100644 --- a/modules/ollama/go.mod +++ b/modules/ollama/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/docker v27.1.1+incompatible github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 github.com/tmc/langchaingo v0.1.5 ) diff --git a/modules/openfga/go.mod b/modules/openfga/go.mod index 3232062282..3d01ff49dd 100644 --- a/modules/openfga/go.mod +++ b/modules/openfga/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/openfga/go-sdk v0.3.5 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/openldap/go.mod b/modules/openldap/go.mod index edab455ba4..76d3e619cb 100644 --- a/modules/openldap/go.mod +++ b/modules/openldap/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/go-ldap/ldap/v3 v3.4.6 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/opensearch/go.mod b/modules/opensearch/go.mod index 00521e4b15..10a1985601 100644 --- a/modules/opensearch/go.mod +++ b/modules/opensearch/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/docker v27.1.1+incompatible github.com/docker/go-units v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/postgres/go.mod b/modules/postgres/go.mod index e7906f03dd..d1cee777d0 100644 --- a/modules/postgres/go.mod +++ b/modules/postgres/go.mod @@ -7,7 +7,7 @@ require ( github.com/jackc/pgx/v5 v5.5.4 github.com/lib/pq v1.10.9 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) diff --git a/modules/pulsar/go.mod b/modules/pulsar/go.mod index 1b0812dfa3..a2f72c1b32 100644 --- a/modules/pulsar/go.mod +++ b/modules/pulsar/go.mod @@ -7,7 +7,7 @@ require ( github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/qdrant/go.mod b/modules/qdrant/go.mod index 19553c2a6e..752d47238d 100644 --- a/modules/qdrant/go.mod +++ b/modules/qdrant/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/qdrant/go-client v1.7.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 google.golang.org/grpc v1.64.1 ) diff --git a/modules/rabbitmq/go.mod b/modules/rabbitmq/go.mod index d908287f7e..b0e7b1f331 100644 --- a/modules/rabbitmq/go.mod +++ b/modules/rabbitmq/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/rabbitmq/amqp091-go v1.9.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/redis/go.mod b/modules/redis/go.mod index 6f0f6da6fd..48c15ca888 100644 --- a/modules/redis/go.mod +++ b/modules/redis/go.mod @@ -6,7 +6,7 @@ require ( github.com/go-redis/redis/v8 v8.11.5 github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) diff --git a/modules/redpanda/go.mod b/modules/redpanda/go.mod index 34bc34422a..4a8a1818a5 100644 --- a/modules/redpanda/go.mod +++ b/modules/redpanda/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 github.com/twmb/franz-go v1.16.1 github.com/twmb/franz-go/pkg/kadm v1.11.0 golang.org/x/mod v0.16.0 diff --git a/modules/registry/go.mod b/modules/registry/go.mod index b74bf67a98..3cbd358d34 100644 --- a/modules/registry/go.mod +++ b/modules/registry/go.mod @@ -6,7 +6,7 @@ require ( github.com/cpuguy83/dockercfg v0.3.2 github.com/docker/docker v27.1.1+incompatible github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/surrealdb/go.mod b/modules/surrealdb/go.mod index 11b0a8422d..e208dc8736 100644 --- a/modules/surrealdb/go.mod +++ b/modules/surrealdb/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/stretchr/testify v1.9.0 github.com/surrealdb/surrealdb.go v0.2.1 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/valkey/go.mod b/modules/valkey/go.mod index 07528d9ff9..4eff8cc363 100644 --- a/modules/valkey/go.mod +++ b/modules/valkey/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 github.com/valkey-io/valkey-go v1.0.41 ) diff --git a/modules/vault/go.mod b/modules/vault/go.mod index 5f03db61f5..e980b8852e 100644 --- a/modules/vault/go.mod +++ b/modules/vault/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/docker v27.1.1+incompatible github.com/hashicorp/vault-client-go v0.4.3 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 github.com/tidwall/gjson v1.17.1 ) diff --git a/modules/vearch/go.mod b/modules/vearch/go.mod index 757149cc58..963de6fed3 100644 --- a/modules/vearch/go.mod +++ b/modules/vearch/go.mod @@ -4,7 +4,7 @@ go 1.22.0 require ( github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 ) require ( diff --git a/modules/weaviate/go.mod b/modules/weaviate/go.mod index b0d02fba08..fa87e7e537 100644 --- a/modules/weaviate/go.mod +++ b/modules/weaviate/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.32.0 + github.com/testcontainers/testcontainers-go v0.34.0 github.com/weaviate/weaviate-go-client/v4 v4.13.1 google.golang.org/grpc v1.64.1 ) diff --git a/modules/yugabytedb/go.mod b/modules/yugabytedb/go.mod index 53295d1d26..68d69de42f 100644 --- a/modules/yugabytedb/go.mod +++ b/modules/yugabytedb/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( github.com/lib/pq v1.10.9 github.com/stretchr/testify v1.9.0 - github.com/testcontainers/testcontainers-go v0.33.0 + github.com/testcontainers/testcontainers-go v0.34.0 github.com/yugabyte/gocql v1.6.0-yb-1 ) diff --git a/sonar-project.properties b/sonar-project.properties index 504e1f03ef..67ef15fcd5 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -7,7 +7,7 @@ sonar.projectKey=testcontainers_testcontainers-go sonar.projectName=testcontainers-go -sonar.projectVersion=v0.33.0 +sonar.projectVersion=v0.34.0 sonar.sources=. From 5a4eec1f2e5a7e71c6285eaf3cfa501163fc6d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 21 Oct 2024 14:26:26 +0200 Subject: [PATCH 097/126] chore: prepare for next minor development cycle (0.35.0) --- internal/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/version.go b/internal/version.go index 0c688d5e3d..6e8cb510c0 100644 --- a/internal/version.go +++ b/internal/version.go @@ -1,4 +1,4 @@ package internal // Version is the next development version of the application -const Version = "0.34.0" +const Version = "0.35.0" From e94530939173164b80faf6dd5870410cd3caf7fe Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 21 Oct 2024 16:53:04 +0100 Subject: [PATCH 098/126] fix(compose): race condition (#2842) Fix a race condition in compose module when setting up multiple containers. --- modules/compose/compose_api.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/compose/compose_api.go b/modules/compose/compose_api.go index 2c852bdaff..c84f1af6ce 100644 --- a/modules/compose/compose_api.go +++ b/modules/compose/compose_api.go @@ -379,6 +379,7 @@ func (d *dockerCompose) Up(ctx context.Context, opts ...StackUpOption) (err erro // Lookup the containers for each service and connect them // to the reaper if needed. + var termSignalsMtx sync.Mutex for _, srv := range d.project.Services { srv := srv errGrpContainers.Go(func() error { @@ -394,6 +395,9 @@ func (d *dockerCompose) Up(ctx context.Context, opts ...StackUpOption) (err erro } dc.SetTerminationSignal(termSignal) + + termSignalsMtx.Lock() + defer termSignalsMtx.Unlock() termSignals = append(termSignals, termSignal) } From 7ca3d8e326eeaf546f8389f327de0b1df3aa096e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 23 Oct 2024 14:14:03 +0200 Subject: [PATCH 099/126] fix: simplify fully-qualified image names (#2846) * chore: do not prepend an invalid Docker registry Images used in the tests, and in the modules are using a wrong Docker image prefix: docker.io. It's better to ask for "nginx:latest" and let the engine deal with the image references. * fix: committed by mistake * chore: update more tests * fix: image cut * fix: removed too much * fix: removed too much Co-authored-by: Steven Hartland * chore: pin bash image * chore: extract to constant * chore: reuse constant --------- Co-authored-by: Steven Hartland --- container_test.go | 14 +++---- docker_files_test.go | 12 +++--- docker_test.go | 42 +++++++++---------- docs/features/image_name_substitution.md | 4 +- docs/features/wait/exit.md | 2 +- docs/features/wait/health.md | 2 +- docs/features/wait/host_port.md | 8 ++-- docs/features/wait/log.md | 4 +- docs/features/wait/multi.md | 2 +- docs/modules/artemis.md | 2 +- docs/modules/consul.md | 2 +- docs/modules/couchbase.md | 2 +- docs/modules/index.md | 2 +- docs/modules/k3s.md | 2 +- docs/modules/neo4j.md | 2 +- docs/modules/postgres.md | 2 +- docs/modules/pulsar.md | 2 +- docs/modules/redis.md | 2 +- docs/system_requirements/using_podman.md | 2 +- image_substitutors_test.go | 8 ++-- lifecycle_test.go | 2 +- logconsumer_test.go | 2 +- modulegen/main_test.go | 8 ++-- modules/artemis/artemis.go | 2 +- modules/artemis/artemis_test.go | 2 +- modules/artemis/examples_test.go | 2 +- modules/compose/compose_api_test.go | 4 +- .../testdata/docker-compose-complex.yml | 4 +- .../docker-compose-container-name.yml | 2 +- .../docker-compose-no-exposed-ports.yml | 2 +- .../testdata/docker-compose-override.yml | 4 +- .../testdata/docker-compose-postgres.yml | 2 +- .../testdata/docker-compose-profiles.yml | 8 ++-- .../docker-compose-short-lifespan.yml | 4 +- .../testdata/docker-compose-simple.yml | 2 +- .../testdata/docker-compose-volume.yml | 2 +- .../compose/testdata/echoserver.Dockerfile | 2 +- modules/consul/consul.go | 4 +- modules/consul/consul_test.go | 2 +- modules/consul/examples_test.go | 4 +- modules/k3s/k3s.go | 2 +- modules/k3s/k3s_example_test.go | 2 +- modules/k3s/k3s_test.go | 6 +-- modules/minio/minio.go | 2 +- modules/neo4j/examples_test.go | 2 +- modules/neo4j/neo4j_test.go | 4 +- modules/postgres/examples_test.go | 2 +- modules/postgres/postgres.go | 2 +- modules/postgres/postgres_test.go | 26 ++++++------ modules/pulsar/examples_test.go | 2 +- modules/pulsar/pulsar.go | 4 +- modules/pulsar/pulsar_test.go | 2 +- modules/redis/examples_test.go | 2 +- modules/redis/redis.go | 2 +- modules/redis/redis_test.go | 16 +++---- modules/redis/testdata/Dockerfile | 2 +- modules/valkey/examples_test.go | 2 +- modules/valkey/valkey.go | 2 +- modules/valkey/valkey_test.go | 10 ++--- network/network_test.go | 6 +-- options.go | 2 +- scripts/bump-reaper.sh | 4 +- scripts/release.sh | 2 +- testdata/Dockerfile | 2 +- testdata/args.Dockerfile | 2 +- testdata/buildlog.Dockerfile | 2 +- testdata/echo.Dockerfile | 2 +- testdata/echoserver.Dockerfile | 2 +- testdata/error.Dockerfile | 2 +- testdata/target.Dockerfile | 2 +- testhelpers_test.go | 2 +- wait/exec_test.go | 2 +- wait/file_test.go | 2 +- 73 files changed, 155 insertions(+), 153 deletions(-) diff --git a/container_test.go b/container_test.go index 16411283c6..72927bc55a 100644 --- a/container_test.go +++ b/container_test.go @@ -167,7 +167,7 @@ func Test_BuildImageWithContexts(t *testing.T) { }{ { Name: "Dockerfile", - Contents: `FROM docker.io/alpine + Contents: `FROM alpine CMD ["echo", "this is from the archive"]`, }, } @@ -216,7 +216,7 @@ func Test_BuildImageWithContexts(t *testing.T) { }, { Name: "Dockerfile", - Contents: `FROM docker.io/alpine + Contents: `FROM alpine WORKDIR /app COPY . . CMD ["sh", "./say_hi.sh"]`, @@ -365,7 +365,7 @@ func Test_GetLogsFromFailedContainer(t *testing.T) { ctx := context.Background() // directDockerHubReference { req := testcontainers.ContainerRequest{ - Image: "docker.io/alpine", + Image: "alpine", Cmd: []string{"echo", "-n", "I was not expecting this"}, WaitingFor: wait.ForLog("I was expecting this").WithStartupTimeout(5 * time.Second), } @@ -392,11 +392,11 @@ func Test_GetLogsFromFailedContainer(t *testing.T) { type dockerImageSubstitutor struct{} func (s dockerImageSubstitutor) Description() string { - return "DockerImageSubstitutor (prepends docker.io)" + return "DockerImageSubstitutor (prepends registry.hub.docker.com)" } func (s dockerImageSubstitutor) Substitute(image string) (string, error) { - return "docker.io/" + image, nil + return "registry.hub.docker.com/library/" + image, nil } // } @@ -455,7 +455,7 @@ func TestImageSubstitutors(t *testing.T) { name: "Prepend namespace", image: "alpine", substitutors: []testcontainers.ImageSubstitutor{dockerImageSubstitutor{}}, - expectedImage: "docker.io/alpine", + expectedImage: "registry.hub.docker.com/library/alpine", }, { name: "Substitution with error", @@ -554,5 +554,5 @@ func ExampleGenericContainer_withSubstitutors() { fmt.Println(dockerContainer.Image) - // Output: docker.io/alpine:latest + // Output: registry.hub.docker.com/library/alpine:latest } diff --git a/docker_files_test.go b/docker_files_test.go index 6a767e6163..9b8551f325 100644 --- a/docker_files_test.go +++ b/docker_files_test.go @@ -13,6 +13,8 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) +const testBashImage string = "bash:5.2.26" + func TestCopyFileToContainer(t *testing.T) { ctx, cnl := context.WithTimeout(context.Background(), 30*time.Second) defer cnl() @@ -30,7 +32,7 @@ func TestCopyFileToContainer(t *testing.T) { ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ - Image: "docker.io/bash", + Image: testBashImage, Files: []testcontainers.ContainerFile{ { Reader: r, @@ -66,7 +68,7 @@ func TestCopyFileToRunningContainer(t *testing.T) { ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ - Image: "docker.io/bash:5.2.26", + Image: testBashImage, Files: []testcontainers.ContainerFile{ { HostFilePath: waitForPath, @@ -104,7 +106,7 @@ func TestCopyDirectoryToContainer(t *testing.T) { ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ - Image: "docker.io/bash", + Image: testBashImage, Files: []testcontainers.ContainerFile{ { HostFilePath: dataDirectory, @@ -141,7 +143,7 @@ func TestCopyDirectoryToRunningContainerAsFile(t *testing.T) { ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ - Image: "docker.io/bash", + Image: testBashImage, Files: []testcontainers.ContainerFile{ { HostFilePath: waitForPath, @@ -183,7 +185,7 @@ func TestCopyDirectoryToRunningContainerAsDir(t *testing.T) { ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ - Image: "docker.io/bash", + Image: testBashImage, Files: []testcontainers.ContainerFile{ { HostFilePath: waitForPath, diff --git a/docker_test.go b/docker_test.go index d01f21f01f..2cc762a6aa 100644 --- a/docker_test.go +++ b/docker_test.go @@ -29,10 +29,10 @@ import ( ) const ( - mysqlImage = "docker.io/mysql:8.0.36" - nginxDelayedImage = "docker.io/menedev/delayed-nginx:1.15.2" - nginxImage = "docker.io/nginx" - nginxAlpineImage = "docker.io/nginx:alpine" + mysqlImage = "mysql:8.0.36" + nginxDelayedImage = "menedev/delayed-nginx:1.15.2" + nginxImage = "nginx" + nginxAlpineImage = "nginx:alpine" nginxDefaultPort = "80/tcp" nginxHighPort = "8080/tcp" daemonMaxVersion = "1.41" @@ -804,8 +804,8 @@ func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { temp := strings.Split(string(out), "\n") - if !regexp.MustCompile(`^Step\s*1/\d+\s*:\s*FROM docker.io/alpine$`).MatchString(temp[0]) { - t.Errorf("Expected stdout first line to be %s. Got '%s'.", "Step 1/* : FROM docker.io/alpine", temp[0]) + if !regexp.MustCompile(`^Step\s*1/\d+\s*:\s*FROM alpine$`).MatchString(temp[0]) { + t.Errorf("Expected stdout first line to be %s. Got '%s'.", "Step 1/* : FROM alpine", temp[0]) } } @@ -878,7 +878,7 @@ func TestCMD(t *testing.T) { ctx := context.Background() req := ContainerRequest{ - Image: "docker.io/alpine", + Image: "alpine", WaitingFor: wait.ForAll( wait.ForLog("command override!"), ), @@ -904,7 +904,7 @@ func TestEntrypoint(t *testing.T) { ctx := context.Background() req := ContainerRequest{ - Image: "docker.io/alpine", + Image: "alpine", WaitingFor: wait.ForAll( wait.ForLog("entrypoint override!"), ), @@ -930,7 +930,7 @@ func TestWorkingDir(t *testing.T) { ctx := context.Background() req := ContainerRequest{ - Image: "docker.io/alpine", + Image: "alpine", WaitingFor: wait.ForAll( wait.ForLog("/var/tmp/test"), ), @@ -950,7 +950,7 @@ func TestWorkingDir(t *testing.T) { func ExampleDockerProvider_CreateContainer() { ctx := context.Background() req := ContainerRequest{ - Image: "docker.io/nginx:alpine", + Image: "nginx:alpine", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/").WithStartupTimeout(10 * time.Second), } @@ -983,7 +983,7 @@ func ExampleDockerProvider_CreateContainer() { func ExampleContainer_Host() { ctx := context.Background() req := ContainerRequest{ - Image: "docker.io/nginx:alpine", + Image: "nginx:alpine", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/").WithStartupTimeout(10 * time.Second), } @@ -1025,7 +1025,7 @@ func ExampleContainer_Host() { func ExampleContainer_Start() { ctx := context.Background() req := ContainerRequest{ - Image: "docker.io/nginx:alpine", + Image: "nginx:alpine", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/").WithStartupTimeout(10 * time.Second), } @@ -1062,7 +1062,7 @@ func ExampleContainer_Start() { func ExampleContainer_Stop() { ctx := context.Background() req := ContainerRequest{ - Image: "docker.io/nginx:alpine", + Image: "nginx:alpine", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/").WithStartupTimeout(10 * time.Second), } @@ -1096,7 +1096,7 @@ func ExampleContainer_Stop() { func ExampleContainer_MappedPort() { ctx := context.Background() req := ContainerRequest{ - Image: "docker.io/nginx:alpine", + Image: "nginx:alpine", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForHTTP("/").WithStartupTimeout(10 * time.Second), } @@ -1147,7 +1147,7 @@ func TestContainerCreationWithVolumeAndFileWritingToIt(t *testing.T) { bashC, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "docker.io/bash", + Image: "bash:5.2.26", Files: []ContainerFile{ { HostFilePath: absPath, @@ -1167,7 +1167,7 @@ func TestContainerCreationWithVolumeAndFileWritingToIt(t *testing.T) { func TestContainerWithTmpFs(t *testing.T) { ctx := context.Background() req := ContainerRequest{ - Image: "docker.io/busybox", + Image: "busybox", Cmd: []string{"sleep", "10"}, Tmpfs: map[string]string{"/testtmpfs": "rw"}, } @@ -1242,7 +1242,7 @@ func TestContainerNonExistentImage(t *testing.T) { c, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "docker.io/postgres:12", + Image: "postgres:12", WaitingFor: wait.ForLog("log"), }, Started: true, @@ -1266,7 +1266,7 @@ func TestContainerCustomPlatformImage(t *testing.T) { c, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "docker.io/redis:latest", + Image: "redis:latest", ImagePlatform: nonExistentPlatform, }, Started: false, @@ -1282,7 +1282,7 @@ func TestContainerCustomPlatformImage(t *testing.T) { c, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "docker.io/mysql:8.0.36", + Image: "mysql:8.0.36", ImagePlatform: "linux/amd64", }, Started: false, @@ -1817,7 +1817,7 @@ func TestContainerRunningCheckingStatusCode(t *testing.T) { func TestContainerWithUserID(t *testing.T) { ctx := context.Background() req := ContainerRequest{ - Image: "docker.io/alpine:latest", + Image: "alpine:latest", User: "60125", Cmd: []string{"sh", "-c", "id -u"}, WaitingFor: wait.ForExit(), @@ -1846,7 +1846,7 @@ func TestContainerWithUserID(t *testing.T) { func TestContainerWithNoUserID(t *testing.T) { ctx := context.Background() req := ContainerRequest{ - Image: "docker.io/alpine:latest", + Image: "alpine:latest", Cmd: []string{"sh", "-c", "id -u"}, WaitingFor: wait.ForExit(), } diff --git a/docs/features/image_name_substitution.md b/docs/features/image_name_substitution.md index 08e9e1d6a0..4272d35c1e 100644 --- a/docs/features/image_name_substitution.md +++ b/docs/features/image_name_substitution.md @@ -45,7 +45,7 @@ _Testcontainers for Go_ will automatically apply the prefix to every image that _Testcontainers for Go_ will not apply the prefix to: * non-Hub image names (e.g. where another registry is set) -* Docker Hub image names where the hub registry is explicitly part of the name (i.e. anything with a `docker.io` or `registry.hub.docker.com` host part) +* Docker Hub image names where the hub registry is explicitly part of the name (i.e. anything with a `registry.hub.docker.com` host part) ## Developing a custom function for transforming image names on the fly @@ -68,7 +68,7 @@ You can implement a custom image name substitutor by: * implementing the `ImageNameSubstitutor` interface, exposed by the `testcontainers` package. * configuring _Testcontainers for Go_ to use your custom implementation, defined at the `ContainerRequest` level. -The following is an example image substitutor implementation prepending the `docker.io/` prefix, used in the tests: +The following is an example image substitutor implementation prepending the `registry.hub.docker.com/library/` prefix, used in the tests: [Image Substitutor Interface](../../options.go) inside_block:imageSubstitutor diff --git a/docs/features/wait/exit.md b/docs/features/wait/exit.md index 3487cb2d21..bcb1aaca36 100644 --- a/docs/features/wait/exit.md +++ b/docs/features/wait/exit.md @@ -9,7 +9,7 @@ The exit wait strategy will check that the container is not in the running state ```golang req := ContainerRequest{ - Image: "docker.io/alpine:latest", + Image: "alpine:latest", WaitingFor: wait.ForExit(), } ``` diff --git a/docs/features/wait/health.md b/docs/features/wait/health.md index d4756f47bd..f724a11010 100644 --- a/docs/features/wait/health.md +++ b/docs/features/wait/health.md @@ -7,7 +7,7 @@ The health wait strategy will check that the container is in the healthy state a ```golang req := ContainerRequest{ - Image: "docker.io/alpine:latest", + Image: "alpine:latest", WaitingFor: wait.ForHealthCheck(), } ``` diff --git a/docs/features/wait/host_port.md b/docs/features/wait/host_port.md index 1b6090b584..10531e5e64 100644 --- a/docs/features/wait/host_port.md +++ b/docs/features/wait/host_port.md @@ -14,7 +14,7 @@ Variations on the HostPort wait strategy are supported, including: ```golang req := ContainerRequest{ - Image: "docker.io/nginx:alpine", + Image: "nginx:alpine", ExposedPorts: []string{"80/tcp"}, WaitingFor: wait.ForListeningPort("80/tcp"), } @@ -26,7 +26,7 @@ The wait strategy will use the lowest exposed port from the container configurat ```golang req := ContainerRequest{ - Image: "docker.io/nginx:alpine", + Image: "nginx:alpine", WaitingFor: wait.ForExposedPort(), } ``` @@ -35,7 +35,7 @@ Said that, it could be the case that the container request included ports to be ```golang req := ContainerRequest{ - Image: "docker.io/nginx:alpine", + Image: "nginx:alpine", ExposedPorts: []string{"80/tcp", "9080/tcp"}, WaitingFor: wait.ForExposedPort(), } @@ -55,7 +55,7 @@ In this case, the `wait.ForExposedPort.SkipInternalCheck` can be used to skip th ```golang req := ContainerRequest{ - Image: "docker.io/nginx:alpine", + Image: "nginx:alpine", ExposedPorts: []string{"80/tcp", "9080/tcp"}, WaitingFor: wait.ForExposedPort().SkipInternalCheck(), } diff --git a/docs/features/wait/log.md b/docs/features/wait/log.md index 66c418b284..f1d40ff360 100644 --- a/docs/features/wait/log.md +++ b/docs/features/wait/log.md @@ -10,7 +10,7 @@ The Log wait strategy will check if a string occurs in the container logs for a ```golang req := ContainerRequest{ - Image: "docker.io/mysql:8.0.36", + Image: "mysql:8.0.36", ExposedPorts: []string{"3306/tcp", "33060/tcp"}, Env: map[string]string{ "MYSQL_ROOT_PASSWORD": "password", @@ -24,7 +24,7 @@ Using a regular expression: ```golang req := ContainerRequest{ - Image: "docker.io/mysql:8.0.36", + Image: "mysql:8.0.36", ExposedPorts: []string{"3306/tcp", "33060/tcp"}, Env: map[string]string{ "MYSQL_ROOT_PASSWORD": "password", diff --git a/docs/features/wait/multi.md b/docs/features/wait/multi.md index bfd053955b..d5f809d6c2 100644 --- a/docs/features/wait/multi.md +++ b/docs/features/wait/multi.md @@ -9,7 +9,7 @@ Available Options: ```golang req := ContainerRequest{ - Image: "docker.io/mysql:8.0.36", + Image: "mysql:8.0.36", ExposedPorts: []string{"3306/tcp", "33060/tcp"}, Env: map[string]string{ "MYSQL_ROOT_PASSWORD": "password", diff --git a/docs/modules/artemis.md b/docs/modules/artemis.md index 395f1b304b..da13e2178a 100644 --- a/docs/modules/artemis.md +++ b/docs/modules/artemis.md @@ -50,7 +50,7 @@ When starting the Artemis container, you can pass options in a variadic way to c #### Image If you need to set a different Artemis Docker image, you can set a valid Docker image as the second argument in the `Run` function. -E.g. `Run(context.Background(), "docker.io/apache/activemq-artemis:2.30.0")`. +E.g. `Run(context.Background(), "apache/activemq-artemis:2.30.0")`. {% include "../features/common_functional_options.md" %} diff --git a/docs/modules/consul.md b/docs/modules/consul.md index 813799e28a..b2b77921df 100644 --- a/docs/modules/consul.md +++ b/docs/modules/consul.md @@ -46,7 +46,7 @@ When starting the Consul container, you can pass options in a variadic way to co #### Image If you need to set a different Consul Docker image, you can set a valid Docker image as the second argument in the `Run` function. -E.g. `Run(context.Background(), "docker.io/hashicorp/consul:1.15")`. +E.g. `Run(context.Background(), "hashicorp/consul:1.15")`. {% include "../features/common_functional_options.md" %} diff --git a/docs/modules/couchbase.md b/docs/modules/couchbase.md index ac07889bfa..43b0c85007 100644 --- a/docs/modules/couchbase.md +++ b/docs/modules/couchbase.md @@ -73,7 +73,7 @@ When starting the Couchbase container, you can pass options in a variadic way to #### Image If you need to set a different Couchbase Docker image, you can set a valid Docker image as the second argument in the `Run` function. -E.g. `Run(context.Background(), "docker.io/couchbase:6.5.1")`. +E.g. `Run(context.Background(), "couchbase:6.5.1")`. You can find the Docker images that are currently tested in this module, for the Enterprise and Community editions, in the following list: diff --git a/docs/modules/index.md b/docs/modules/index.md index 629787fedf..8db41723fa 100644 --- a/docs/modules/index.md +++ b/docs/modules/index.md @@ -72,7 +72,7 @@ We have provided a command line tool to generate the scaffolding for the code of | Flag | Short | Type | Required | Description | |---------|-------|--------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------| | --name | -n | string | Yes | Name of the module, use camel-case when needed. Only alphanumerical characters are allowed (leading character must be a letter). | -| --image | -i | string | Yes | Fully-qualified name of the Docker image to be used in the examples and tests (i.e. 'docker.io/org/project:tag') | +| --image | -i | string | Yes | Fully-qualified name of the Docker image to be used in the examples and tests (i.e. 'org/project:tag') | | --title | -t | string | No | A variant of the name supporting mixed casing (i.e. 'MongoDB'). Only alphanumerical characters are allowed (leading character must be a letter). | diff --git a/docs/modules/k3s.md b/docs/modules/k3s.md index 6ada392534..617c1d4ffe 100644 --- a/docs/modules/k3s.md +++ b/docs/modules/k3s.md @@ -52,7 +52,7 @@ When starting the K3s container, you can pass options in a variadic way to confi #### Image If you need to set a different K3s Docker image, you can set a valid Docker image as the second argument in the `Run` function. -E.g. `Run(context.Background(), "docker.io/rancher/k3s:v1.27.1-k3s1")`. +E.g. `Run(context.Background(), "rancher/k3s:v1.27.1-k3s1")`. {% include "../features/common_functional_options.md" %} diff --git a/docs/modules/neo4j.md b/docs/modules/neo4j.md index aadda970e1..0431df12a1 100644 --- a/docs/modules/neo4j.md +++ b/docs/modules/neo4j.md @@ -56,7 +56,7 @@ When starting the Neo4j container, you can pass options in a variadic way to con #### Image If you need to set a different Neo4j Docker image, you can set a valid Docker image as the second argument in the `Run` function. -E.g. `Run(context.Background(), "docker.io/neo4j:4.4")`. +E.g. `Run(context.Background(), "neo4j:4.4")`. By default, the container will use the following Docker image: diff --git a/docs/modules/postgres.md b/docs/modules/postgres.md index 82b1e04351..930de50c15 100644 --- a/docs/modules/postgres.md +++ b/docs/modules/postgres.md @@ -49,7 +49,7 @@ When starting the Postgres container, you can pass options in a variadic way to #### Image If you need to set a different Postgres Docker image, you can set a valid Docker image as the second argument in the `Run` function. -E.g. `Run(context.Background(), "docker.io/postgres:16-alpine")`. +E.g. `Run(context.Background(), "postgres:16-alpine")`. {% include "../features/common_functional_options.md" %} diff --git a/docs/modules/pulsar.md b/docs/modules/pulsar.md index d8c3db5735..99f93b2222 100644 --- a/docs/modules/pulsar.md +++ b/docs/modules/pulsar.md @@ -52,7 +52,7 @@ When starting the Pulsar container, you can pass options in a variadic way to co #### Image If you need to set a different Pulsar Docker image, you can set a valid Docker image as the second argument in the `Run` function. -E.g. `Run(context.Background(), "docker.io/apachepulsar/pulsar:2.10.2")`. +E.g. `Run(context.Background(), "apachepulsar/pulsar:2.10.2")`. {% include "../features/common_functional_options.md" %} diff --git a/docs/modules/redis.md b/docs/modules/redis.md index 51e111dfff..e6bbd90851 100644 --- a/docs/modules/redis.md +++ b/docs/modules/redis.md @@ -49,7 +49,7 @@ When starting the Redis container, you can pass options in a variadic way to con #### Image If you need to set a different Redis Docker image, you can set a valid Docker image as the second argument in the `Run` function. -E.g. `Run(context.Background(), "docker.io/redis:7")`. +E.g. `Run(context.Background(), "redis:7")`. {% include "../features/common_functional_options.md" %} diff --git a/docs/system_requirements/using_podman.md b/docs/system_requirements/using_podman.md index cf65792bbd..4143306901 100644 --- a/docs/system_requirements/using_podman.md +++ b/docs/system_requirements/using_podman.md @@ -27,7 +27,7 @@ func TestSomething(t *testing.T) { req := tc.GenericContainerRequest{ ProviderType: tc.ProviderPodman, ContainerRequest: tc.ContainerRequest{ - Image: "docker.io/nginx:alpine" + Image: "nginx:alpine" }, } diff --git a/image_substitutors_test.go b/image_substitutors_test.go index 4a41f31ce6..92b42e63b3 100644 --- a/image_substitutors_test.go +++ b/image_substitutors_test.go @@ -104,16 +104,16 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { } }) - t.Run("explicitly including docker.io", func(t *testing.T) { + t.Run("explicitly including registry.hub.docker.com/library", func(t *testing.T) { s := newPrependHubRegistry("my-registry") - img, err := s.Substitute("docker.io/foo:latest") + img, err := s.Substitute("registry.hub.docker.com/library/foo:latest") if err != nil { t.Fatal(err) } - if img != "docker.io/foo:latest" { - t.Errorf("expected docker.io/foo:latest, got %s", img) + if img != "registry.hub.docker.com/library/foo:latest" { + t.Errorf("expected registry.hub.docker.com/library/foo:latest, got %s", img) } }) diff --git a/lifecycle_test.go b/lifecycle_test.go index b1cff8dad8..0d7e9c7861 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -887,7 +887,7 @@ func TestPrintContainerLogsOnError(t *testing.T) { ctx := context.Background() req := ContainerRequest{ - Image: "docker.io/alpine", + Image: "alpine", Cmd: []string{"echo", "-n", "I am expecting this"}, WaitingFor: wait.ForLog("I was expecting that").WithStartupTimeout(5 * time.Second), } diff --git a/logconsumer_test.go b/logconsumer_test.go index 9f4b0b61f9..f16c2fc007 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -251,7 +251,7 @@ func TestContainerLogWithErrClosed(t *testing.T) { dind, err := GenericContainer(ctx, GenericContainerRequest{ Started: true, ContainerRequest: ContainerRequest{ - Image: "docker.io/docker:dind", + Image: "docker:dind", ExposedPorts: []string{"2375/tcp"}, Env: map[string]string{"DOCKER_TLS_CERTDIR": ""}, WaitingFor: wait.ForListeningPort("2375/tcp"), diff --git a/modulegen/main_test.go b/modulegen/main_test.go index eeb836a8a5..bbad5a5abb 100644 --- a/modulegen/main_test.go +++ b/modulegen/main_test.go @@ -187,7 +187,7 @@ func TestGenerateWrongModuleName(t *testing.T) { for _, test := range tests { module := context.TestcontainersModule{ Name: test.name, - Image: "docker.io/example/" + test.name + ":latest", + Image: "example/" + test.name + ":latest", } err = internal.GenerateFiles(tmpCtx, module) @@ -231,7 +231,7 @@ func TestGenerateWrongModuleTitle(t *testing.T) { module := context.TestcontainersModule{ Name: "foo", TitleName: test.title, - Image: "docker.io/example/foo:latest", + Image: "example/foo:latest", } err = internal.GenerateFiles(tmpCtx, module) @@ -266,7 +266,7 @@ func TestGenerate(t *testing.T) { Name: "foodb4tw", TitleName: "FooDB4TheWin", IsModule: false, - Image: "docker.io/example/foodb:latest", + Image: "example/foodb:latest", } moduleNameLower := module.Lower() @@ -322,7 +322,7 @@ func TestGenerateModule(t *testing.T) { Name: "foodb", TitleName: "FooDB", IsModule: true, - Image: "docker.io/example/foodb:latest", + Image: "example/foodb:latest", } moduleNameLower := module.Lower() diff --git a/modules/artemis/artemis.go b/modules/artemis/artemis.go index a8721ce189..e74b542cd7 100644 --- a/modules/artemis/artemis.go +++ b/modules/artemis/artemis.go @@ -81,7 +81,7 @@ func WithExtraArgs(args string) testcontainers.CustomizeRequestOption { // Deprecated: use Run instead. // RunContainer creates an instance of the Artemis container type. func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*Container, error) { - return Run(ctx, "docker.io/apache/activemq-artemis:2.30.0-alpine", opts...) + return Run(ctx, "apache/activemq-artemis:2.30.0-alpine", opts...) } // Run creates an instance of the Artemis container type with a given image diff --git a/modules/artemis/artemis_test.go b/modules/artemis/artemis_test.go index 8396b562f5..70dcab9440 100644 --- a/modules/artemis/artemis_test.go +++ b/modules/artemis/artemis_test.go @@ -65,7 +65,7 @@ func TestArtemis(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ctr, err := artemis.Run(ctx, "docker.io/apache/activemq-artemis:2.30.0-alpine", test.opts...) + ctr, err := artemis.Run(ctx, "apache/activemq-artemis:2.30.0-alpine", test.opts...) testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) diff --git a/modules/artemis/examples_test.go b/modules/artemis/examples_test.go index 78f8c2d13d..04e973a013 100644 --- a/modules/artemis/examples_test.go +++ b/modules/artemis/examples_test.go @@ -16,7 +16,7 @@ func ExampleRun() { ctx := context.Background() artemisContainer, err := artemis.Run(ctx, - "docker.io/apache/activemq-artemis:2.30.0", + "apache/activemq-artemis:2.30.0", artemis.WithCredentials("test", "test"), ) defer func() { diff --git a/modules/compose/compose_api_test.go b/modules/compose/compose_api_test.go index e5f30a5257..e13c6ca937 100644 --- a/modules/compose/compose_api_test.go +++ b/modules/compose/compose_api_test.go @@ -440,7 +440,7 @@ func TestDockerComposeAPIWithStackReader(t *testing.T) { composeContent := ` services: api-nginx: - image: docker.io/nginx:stable-alpine + image: nginx:stable-alpine environment: bar: ${bar} foo: ${foo} @@ -481,7 +481,7 @@ func TestDockerComposeAPIWithStackReaderAndComposeFile(t *testing.T) { composeContent := ` services: api-postgres: - image: docker.io/postgres:14 + image: postgres:14 environment: POSTGRES_PASSWORD: s3cr3t ` diff --git a/modules/compose/testdata/docker-compose-complex.yml b/modules/compose/testdata/docker-compose-complex.yml index fe0636dff2..d84f39ec16 100644 --- a/modules/compose/testdata/docker-compose-complex.yml +++ b/modules/compose/testdata/docker-compose-complex.yml @@ -1,10 +1,10 @@ services: {{ .ServiceType }}-nginx: - image: docker.io/nginx:stable-alpine + image: nginx:stable-alpine ports: - "{{ .Port_0 }}:80" {{ .ServiceType }}-mysql: - image: docker.io/mysql:8.0.36 + image: mysql:8.0.36 environment: - MYSQL_DATABASE=db - MYSQL_ROOT_PASSWORD=my-secret-pw diff --git a/modules/compose/testdata/docker-compose-container-name.yml b/modules/compose/testdata/docker-compose-container-name.yml index c46ca68888..d36bf96c87 100644 --- a/modules/compose/testdata/docker-compose-container-name.yml +++ b/modules/compose/testdata/docker-compose-container-name.yml @@ -1,7 +1,7 @@ services: {{ .ServiceType }}-nginx: container_name: {{ .ServiceType }}-nginxy - image: docker.io/nginx:stable-alpine + image: nginx:stable-alpine environment: bar: ${bar} ports: diff --git a/modules/compose/testdata/docker-compose-no-exposed-ports.yml b/modules/compose/testdata/docker-compose-no-exposed-ports.yml index 3f487156c3..e59e1a6fe9 100644 --- a/modules/compose/testdata/docker-compose-no-exposed-ports.yml +++ b/modules/compose/testdata/docker-compose-no-exposed-ports.yml @@ -1,5 +1,5 @@ services: {{ .ServiceType }}-nginx: - image: docker.io/nginx:stable-alpine + image: nginx:stable-alpine ports: - "80" diff --git a/modules/compose/testdata/docker-compose-override.yml b/modules/compose/testdata/docker-compose-override.yml index c8714256e0..6112c8d595 100644 --- a/modules/compose/testdata/docker-compose-override.yml +++ b/modules/compose/testdata/docker-compose-override.yml @@ -1,8 +1,8 @@ services: {{ .ServiceType }}-nginx: - image: docker.io/nginx:stable-alpine + image: nginx:stable-alpine {{ .ServiceType }}-mysql: - image: docker.io/mysql:8.0.36 + image: mysql:8.0.36 environment: MYSQL_RANDOM_ROOT_PASSWORD: Y ports: diff --git a/modules/compose/testdata/docker-compose-postgres.yml b/modules/compose/testdata/docker-compose-postgres.yml index 9671a7bdb5..012c2e0fda 100644 --- a/modules/compose/testdata/docker-compose-postgres.yml +++ b/modules/compose/testdata/docker-compose-postgres.yml @@ -1,6 +1,6 @@ services: {{ .ServiceType }}-postgres: - image: docker.io/postgres:14 + image: postgres:14 environment: POSTGRES_PASSWORD: s3cr3t ports: diff --git a/modules/compose/testdata/docker-compose-profiles.yml b/modules/compose/testdata/docker-compose-profiles.yml index fdb92853e1..a58bf014d3 100644 --- a/modules/compose/testdata/docker-compose-profiles.yml +++ b/modules/compose/testdata/docker-compose-profiles.yml @@ -1,24 +1,24 @@ services: starts-always: - image: docker.io/nginx:stable-alpine + image: nginx:stable-alpine ports: - ":80" # profiles: none defined, therefore always starts. only-dev: - image: docker.io/nginx:stable-alpine + image: nginx:stable-alpine ports: - ":80" profiles: - dev dev-or-test: - image: docker.io/nginx:stable-alpine + image: nginx:stable-alpine ports: - ":80" profiles: - dev - test only-prod: - image: docker.io/nginx:stable-alpine + image: nginx:stable-alpine ports: - ":80" profiles: diff --git a/modules/compose/testdata/docker-compose-short-lifespan.yml b/modules/compose/testdata/docker-compose-short-lifespan.yml index 47fd1314bb..19486a792b 100644 --- a/modules/compose/testdata/docker-compose-short-lifespan.yml +++ b/modules/compose/testdata/docker-compose-short-lifespan.yml @@ -1,7 +1,7 @@ services: tzatziki: - image: docker.io/alpine:latest + image: alpine:latest command: "sleep 5" falafel: - image: docker.io/alpine:latest + image: alpine:latest command: "echo 'World is your canvas'" diff --git a/modules/compose/testdata/docker-compose-simple.yml b/modules/compose/testdata/docker-compose-simple.yml index ebf8a64b6f..a3aad440bc 100644 --- a/modules/compose/testdata/docker-compose-simple.yml +++ b/modules/compose/testdata/docker-compose-simple.yml @@ -1,6 +1,6 @@ services: {{ .ServiceType }}-nginx: - image: docker.io/nginx:stable-alpine + image: nginx:stable-alpine environment: bar: ${bar} foo: ${foo} diff --git a/modules/compose/testdata/docker-compose-volume.yml b/modules/compose/testdata/docker-compose-volume.yml index f284a71452..9f904d41d9 100644 --- a/modules/compose/testdata/docker-compose-volume.yml +++ b/modules/compose/testdata/docker-compose-volume.yml @@ -1,6 +1,6 @@ services: {{ .ServiceType }}-nginx: - image: docker.io/nginx:stable-alpine + image: nginx:stable-alpine volumes: - type: volume source: mydata diff --git a/modules/compose/testdata/echoserver.Dockerfile b/modules/compose/testdata/echoserver.Dockerfile index 546489ffac..aaf835f35a 100644 --- a/modules/compose/testdata/echoserver.Dockerfile +++ b/modules/compose/testdata/echoserver.Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/golang:1.13-alpine +FROM golang:1.13-alpine WORKDIR /app diff --git a/modules/consul/consul.go b/modules/consul/consul.go index c374938c32..0084786afb 100644 --- a/modules/consul/consul.go +++ b/modules/consul/consul.go @@ -15,7 +15,7 @@ const ( const ( // Deprecated: it will be removed in the next major version. - DefaultBaseImage = "docker.io/hashicorp/consul:1.15" + DefaultBaseImage = "hashicorp/consul:1.15" ) // ConsulContainer represents the Consul container type used in the module. @@ -65,7 +65,7 @@ func WithConfigFile(configPath string) testcontainers.CustomizeRequestOption { // Deprecated: use Run instead // RunContainer creates an instance of the Consul container type func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*ConsulContainer, error) { - return Run(ctx, "docker.io/hashicorp/consul:1.15", opts...) + return Run(ctx, "hashicorp/consul:1.15", opts...) } // Run creates an instance of the Consul container type diff --git a/modules/consul/consul_test.go b/modules/consul/consul_test.go index 79b626d359..6f359b7261 100644 --- a/modules/consul/consul_test.go +++ b/modules/consul/consul_test.go @@ -39,7 +39,7 @@ func TestConsul(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ctr, err := consul.Run(ctx, "docker.io/hashicorp/consul:1.15", test.opts...) + ctr, err := consul.Run(ctx, "hashicorp/consul:1.15", test.opts...) testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) diff --git a/modules/consul/examples_test.go b/modules/consul/examples_test.go index 32d323fe3d..d833575880 100644 --- a/modules/consul/examples_test.go +++ b/modules/consul/examples_test.go @@ -15,7 +15,7 @@ func ExampleRun() { // runConsulContainer { ctx := context.Background() - consulContainer, err := consul.Run(ctx, "docker.io/hashicorp/consul:1.15") + consulContainer, err := consul.Run(ctx, "hashicorp/consul:1.15") defer func() { if err := testcontainers.TerminateContainer(consulContainer); err != nil { log.Printf("failed to terminate container: %s", err) @@ -43,7 +43,7 @@ func ExampleRun_connect() { // connectConsul { ctx := context.Background() - consulContainer, err := consul.Run(ctx, "docker.io/hashicorp/consul:1.15") + consulContainer, err := consul.Run(ctx, "hashicorp/consul:1.15") defer func() { if err := testcontainers.TerminateContainer(consulContainer); err != nil { log.Printf("failed to terminate container: %s", err) diff --git a/modules/k3s/k3s.go b/modules/k3s/k3s.go index 509719bd64..8a3625eb65 100644 --- a/modules/k3s/k3s.go +++ b/modules/k3s/k3s.go @@ -50,7 +50,7 @@ func WithManifest(manifestPath string) testcontainers.CustomizeRequestOption { // Deprecated: use Run instead // RunContainer creates an instance of the K3s container type func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*K3sContainer, error) { - return Run(ctx, "docker.io/rancher/k3s:v1.27.1-k3s1", opts...) + return Run(ctx, "rancher/k3s:v1.27.1-k3s1", opts...) } // Run creates an instance of the K3s container type diff --git a/modules/k3s/k3s_example_test.go b/modules/k3s/k3s_example_test.go index ef2ca36538..cd1c7afc7e 100644 --- a/modules/k3s/k3s_example_test.go +++ b/modules/k3s/k3s_example_test.go @@ -17,7 +17,7 @@ func ExampleRun() { // runK3sContainer { ctx := context.Background() - k3sContainer, err := k3s.Run(ctx, "docker.io/rancher/k3s:v1.27.1-k3s1") + k3sContainer, err := k3s.Run(ctx, "rancher/k3s:v1.27.1-k3s1") defer func() { if err := testcontainers.TerminateContainer(k3sContainer); err != nil { log.Printf("failed to terminate container: %s", err) diff --git a/modules/k3s/k3s_test.go b/modules/k3s/k3s_test.go index f3970a25da..d89121dde3 100644 --- a/modules/k3s/k3s_test.go +++ b/modules/k3s/k3s_test.go @@ -23,7 +23,7 @@ func Test_LoadImages(t *testing.T) { ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(3*time.Minute)) defer cancel() - k3sContainer, err := k3s.Run(ctx, "docker.io/rancher/k3s:v1.27.1-k3s1") + k3sContainer, err := k3s.Run(ctx, "rancher/k3s:v1.27.1-k3s1") testcontainers.CleanupContainer(t, k3sContainer) require.NoError(t, err) @@ -105,7 +105,7 @@ func getTestPodState(ctx context.Context, k8s *kubernetes.Clientset) (corev1.Con func Test_APIServerReady(t *testing.T) { ctx := context.Background() - k3sContainer, err := k3s.Run(ctx, "docker.io/rancher/k3s:v1.27.1-k3s1") + k3sContainer, err := k3s.Run(ctx, "rancher/k3s:v1.27.1-k3s1") testcontainers.CleanupContainer(t, k3sContainer) require.NoError(t, err) @@ -144,7 +144,7 @@ func Test_WithManifestOption(t *testing.T) { ctx := context.Background() k3sContainer, err := k3s.Run(ctx, - "docker.io/rancher/k3s:v1.27.1-k3s1", + "rancher/k3s:v1.27.1-k3s1", k3s.WithManifest("nginx-manifest.yaml"), testcontainers.WithWaitStrategy(wait.ForExec([]string{"kubectl", "wait", "pod", "nginx", "--for=condition=Ready"})), ) diff --git a/modules/minio/minio.go b/modules/minio/minio.go index 6907b1372b..88c4f365d5 100644 --- a/modules/minio/minio.go +++ b/modules/minio/minio.go @@ -59,7 +59,7 @@ func (c *MinioContainer) ConnectionString(ctx context.Context) (string, error) { // Deprecated: use Run instead // RunContainer creates an instance of the Minio container type func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*MinioContainer, error) { - return Run(ctx, "docker.io/minio/minio:RELEASE.2024-01-16T16-07-38Z", opts...) + return Run(ctx, "minio/minio:RELEASE.2024-01-16T16-07-38Z", opts...) } // Run creates an instance of the Minio container type diff --git a/modules/neo4j/examples_test.go b/modules/neo4j/examples_test.go index 6e8c42936a..51b11bf49a 100644 --- a/modules/neo4j/examples_test.go +++ b/modules/neo4j/examples_test.go @@ -16,7 +16,7 @@ func ExampleRun() { testPassword := "letmein!" neo4jContainer, err := neo4j.Run(ctx, - "docker.io/neo4j:4.4", + "neo4j:4.4", neo4j.WithAdminPassword(testPassword), neo4j.WithLabsPlugin(neo4j.Apoc), neo4j.WithNeo4jSetting("dbms.tx_log.rotation.size", "42M"), diff --git a/modules/neo4j/neo4j_test.go b/modules/neo4j/neo4j_test.go index d036fb8128..9d41e4afe5 100644 --- a/modules/neo4j/neo4j_test.go +++ b/modules/neo4j/neo4j_test.go @@ -63,8 +63,8 @@ func TestNeo4jWithEnterpriseLicense(t *testing.T) { ctx := context.Background() images := map[string]string{ - "StandardEdition": "docker.io/neo4j:4.4", - "EnterpriseEdition": "docker.io/neo4j:4.4-enterprise", + "StandardEdition": "neo4j:4.4", + "EnterpriseEdition": "neo4j:4.4-enterprise", } for edition, img := range images { diff --git a/modules/postgres/examples_test.go b/modules/postgres/examples_test.go index 8b7f562ea9..1f5b0e1c86 100644 --- a/modules/postgres/examples_test.go +++ b/modules/postgres/examples_test.go @@ -21,7 +21,7 @@ func ExampleRun() { dbPassword := "password" postgresContainer, err := postgres.Run(ctx, - "docker.io/postgres:16-alpine", + "postgres:16-alpine", postgres.WithInitScripts(filepath.Join("testdata", "init-user-db.sh")), postgres.WithConfigFile(filepath.Join("testdata", "my-postgres.conf")), postgres.WithDatabase(dbName), diff --git a/modules/postgres/postgres.go b/modules/postgres/postgres.go index ac51721f82..8bd32a49b7 100644 --- a/modules/postgres/postgres.go +++ b/modules/postgres/postgres.go @@ -136,7 +136,7 @@ func WithUsername(user string) testcontainers.CustomizeRequestOption { // Deprecated: use Run instead // RunContainer creates an instance of the Postgres container type func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*PostgresContainer, error) { - return Run(ctx, "docker.io/postgres:16-alpine", opts...) + return Run(ctx, "postgres:16-alpine", opts...) } // Run creates an instance of the Postgres container type diff --git a/modules/postgres/postgres_test.go b/modules/postgres/postgres_test.go index 7167da5c51..05b3f8110e 100644 --- a/modules/postgres/postgres_test.go +++ b/modules/postgres/postgres_test.go @@ -34,24 +34,24 @@ func TestPostgres(t *testing.T) { }{ { name: "Postgres", - image: "docker.io/postgres:15.2-alpine", + image: "postgres:15.2-alpine", }, { name: "Timescale", // timescale { - image: "docker.io/timescale/timescaledb:2.1.0-pg11", + image: "timescale/timescaledb:2.1.0-pg11", // } }, { name: "Postgis", // postgis { - image: "docker.io/postgis/postgis:12-3.0", + image: "postgis/postgis:12-3.0", // } }, { name: "Pgvector", // pgvector { - image: "docker.io/pgvector/pgvector:pg16", + image: "pgvector/pgvector:pg16", // } }, } @@ -112,7 +112,7 @@ func TestContainerWithWaitForSQL(t *testing.T) { t.Run("default query", func(t *testing.T) { ctr, err := postgres.Run( ctx, - "docker.io/postgres:16-alpine", + "postgres:16-alpine", postgres.WithDatabase(dbname), postgres.WithUsername(user), postgres.WithPassword(password), @@ -125,7 +125,7 @@ func TestContainerWithWaitForSQL(t *testing.T) { t.Run("custom query", func(t *testing.T) { ctr, err := postgres.Run( ctx, - "docker.io/postgres:16-alpine", + "postgres:16-alpine", postgres.WithDatabase(dbname), postgres.WithUsername(user), postgres.WithPassword(password), @@ -138,7 +138,7 @@ func TestContainerWithWaitForSQL(t *testing.T) { t.Run("custom bad query", func(t *testing.T) { ctr, err := postgres.Run( ctx, - "docker.io/postgres:16-alpine", + "postgres:16-alpine", postgres.WithDatabase(dbname), postgres.WithUsername(user), postgres.WithPassword(password), @@ -153,7 +153,7 @@ func TestWithConfigFile(t *testing.T) { ctx := context.Background() ctr, err := postgres.Run(ctx, - "docker.io/postgres:16-alpine", + "postgres:16-alpine", postgres.WithConfigFile(filepath.Join("testdata", "my-postgres.conf")), postgres.WithDatabase(dbname), postgres.WithUsername(user), @@ -177,7 +177,7 @@ func TestWithInitScript(t *testing.T) { ctx := context.Background() ctr, err := postgres.Run(ctx, - "docker.io/postgres:15.2-alpine", + "postgres:15.2-alpine", postgres.WithInitScripts(filepath.Join("testdata", "init-user-db.sh")), postgres.WithDatabase(dbname), postgres.WithUsername(user), @@ -228,7 +228,7 @@ func TestSnapshot(t *testing.T) { // 1. Start the postgres ctr and run any migrations on it ctr, err := postgres.Run( ctx, - "docker.io/postgres:16-alpine", + "postgres:16-alpine", postgres.WithDatabase(dbname), postgres.WithUsername(user), postgres.WithPassword(password), @@ -303,7 +303,7 @@ func TestSnapshotWithOverrides(t *testing.T) { ctr, err := postgres.Run( ctx, - "docker.io/postgres:16-alpine", + "postgres:16-alpine", postgres.WithDatabase(dbname), postgres.WithUsername(user), postgres.WithPassword(password), @@ -349,7 +349,7 @@ func TestSnapshotDuplicate(t *testing.T) { ctr, err := postgres.Run( ctx, - "docker.io/postgres:16-alpine", + "postgres:16-alpine", postgres.WithDatabase(dbname), postgres.WithUsername(user), postgres.WithPassword(password), @@ -375,7 +375,7 @@ func TestSnapshotWithDockerExecFallback(t *testing.T) { // 1. Start the postgres container and run any migrations on it ctr, err := postgres.Run( ctx, - "docker.io/postgres:16-alpine", + "postgres:16-alpine", postgres.WithDatabase(dbname), postgres.WithUsername(user), postgres.WithPassword(password), diff --git a/modules/pulsar/examples_test.go b/modules/pulsar/examples_test.go index ad871f1494..9561914207 100644 --- a/modules/pulsar/examples_test.go +++ b/modules/pulsar/examples_test.go @@ -13,7 +13,7 @@ func ExampleRun() { // runPulsarContainer { ctx := context.Background() - pulsarContainer, err := pulsar.Run(ctx, "docker.io/apachepulsar/pulsar:2.10.2") + pulsarContainer, err := pulsar.Run(ctx, "apachepulsar/pulsar:2.10.2") defer func() { if err := testcontainers.TerminateContainer(pulsarContainer); err != nil { log.Printf("failed to terminate container: %s", err) diff --git a/modules/pulsar/pulsar.go b/modules/pulsar/pulsar.go index 26c57b5742..be9ea10925 100644 --- a/modules/pulsar/pulsar.go +++ b/modules/pulsar/pulsar.go @@ -132,12 +132,12 @@ func WithTransactions() testcontainers.CustomizeRequestOption { // Deprecated: use Run instead // RunContainer creates an instance of the Pulsar container type func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*Container, error) { - return Run(ctx, "docker.io/apachepulsar/pulsar:2.10.2", opts...) + return Run(ctx, "apachepulsar/pulsar:2.10.2", opts...) } // Run creates an instance of the Pulsar container type, being possible to pass a custom request and options // The created container will use the following defaults: -// - image: docker.io/apachepulsar/pulsar:2.10.2 +// - image: apachepulsar/pulsar:2.10.2 // - exposed ports: 6650/tcp, 8080/tcp // - waiting strategy: wait for all the following strategies: // - the Pulsar admin API ("/admin/v2/clusters") to be ready on port 8080/tcp and return the response `["standalone"]` diff --git a/modules/pulsar/pulsar_test.go b/modules/pulsar/pulsar_test.go index cd04284913..8cea6a4119 100644 --- a/modules/pulsar/pulsar_test.go +++ b/modules/pulsar/pulsar_test.go @@ -98,7 +98,7 @@ func TestPulsar(t *testing.T) { t.Run(tt.name, func(t *testing.T) { c, err := testcontainerspulsar.Run( ctx, - "docker.io/apachepulsar/pulsar:2.10.2", + "apachepulsar/pulsar:2.10.2", tt.opts..., ) testcontainers.CleanupContainer(t, c) diff --git a/modules/redis/examples_test.go b/modules/redis/examples_test.go index e5e83a01a1..86be00be85 100644 --- a/modules/redis/examples_test.go +++ b/modules/redis/examples_test.go @@ -15,7 +15,7 @@ func ExampleRun() { ctx := context.Background() redisContainer, err := redis.Run(ctx, - "docker.io/redis:7", + "redis:7", redis.WithSnapshotting(10, 1), redis.WithLogLevel(redis.LogLevelVerbose), redis.WithConfigFile(filepath.Join("testdata", "redis7.conf")), diff --git a/modules/redis/redis.go b/modules/redis/redis.go index df75ad7311..d834a6c46d 100644 --- a/modules/redis/redis.go +++ b/modules/redis/redis.go @@ -46,7 +46,7 @@ func (c *RedisContainer) ConnectionString(ctx context.Context) (string, error) { // Deprecated: use Run instead // RunContainer creates an instance of the Redis container type func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*RedisContainer, error) { - return Run(ctx, "docker.io/redis:7", opts...) + return Run(ctx, "redis:7", opts...) } // Run creates an instance of the Redis container type diff --git a/modules/redis/redis_test.go b/modules/redis/redis_test.go index 4a872a0a87..58d1c14c9c 100644 --- a/modules/redis/redis_test.go +++ b/modules/redis/redis_test.go @@ -18,7 +18,7 @@ import ( func TestIntegrationSetGet(t *testing.T) { ctx := context.Background() - redisContainer, err := tcredis.Run(ctx, "docker.io/redis:7") + redisContainer, err := tcredis.Run(ctx, "redis:7") testcontainers.CleanupContainer(t, redisContainer) require.NoError(t, err) @@ -28,7 +28,7 @@ func TestIntegrationSetGet(t *testing.T) { func TestRedisWithConfigFile(t *testing.T) { ctx := context.Background() - redisContainer, err := tcredis.Run(ctx, "docker.io/redis:7", tcredis.WithConfigFile(filepath.Join("testdata", "redis7.conf"))) + redisContainer, err := tcredis.Run(ctx, "redis:7", tcredis.WithConfigFile(filepath.Join("testdata", "redis7.conf"))) testcontainers.CleanupContainer(t, redisContainer) require.NoError(t, err) @@ -44,22 +44,22 @@ func TestRedisWithImage(t *testing.T) { }{ { name: "Redis6", - image: "docker.io/redis:6", + image: "redis:6", }, { name: "Redis7", - image: "docker.io/redis:7", + image: "redis:7", }, { name: "Redis Stack", // redisStackImage { - image: "docker.io/redis/redis-stack:latest", + image: "redis/redis-stack:latest", // } }, { name: "Redis Stack Server", // redisStackServerImage { - image: "docker.io/redis/redis-stack-server:latest", + image: "redis/redis-stack-server:latest", // } }, } @@ -78,7 +78,7 @@ func TestRedisWithImage(t *testing.T) { func TestRedisWithLogLevel(t *testing.T) { ctx := context.Background() - redisContainer, err := tcredis.Run(ctx, "docker.io/redis:7", tcredis.WithLogLevel(tcredis.LogLevelVerbose)) + redisContainer, err := tcredis.Run(ctx, "redis:7", tcredis.WithLogLevel(tcredis.LogLevelVerbose)) testcontainers.CleanupContainer(t, redisContainer) require.NoError(t, err) @@ -88,7 +88,7 @@ func TestRedisWithLogLevel(t *testing.T) { func TestRedisWithSnapshotting(t *testing.T) { ctx := context.Background() - redisContainer, err := tcredis.Run(ctx, "docker.io/redis:7", tcredis.WithSnapshotting(10, 1)) + redisContainer, err := tcredis.Run(ctx, "redis:7", tcredis.WithSnapshotting(10, 1)) testcontainers.CleanupContainer(t, redisContainer) require.NoError(t, err) diff --git a/modules/redis/testdata/Dockerfile b/modules/redis/testdata/Dockerfile index 7157611a13..14cfaf1e23 100644 --- a/modules/redis/testdata/Dockerfile +++ b/modules/redis/testdata/Dockerfile @@ -1 +1 @@ -FROM docker.io/redis:5.0-alpine@sha256:1a3c609295332f1ce603948142a132656c92a08149d7096e203058533c415b8c +FROM redis:5.0-alpine@sha256:1a3c609295332f1ce603948142a132656c92a08149d7096e203058533c415b8c diff --git a/modules/valkey/examples_test.go b/modules/valkey/examples_test.go index 7e1d261850..c700e8d3f3 100644 --- a/modules/valkey/examples_test.go +++ b/modules/valkey/examples_test.go @@ -15,7 +15,7 @@ func ExampleRun() { ctx := context.Background() valkeyContainer, err := valkey.Run(ctx, - "docker.io/valkey/valkey:7.2.5", + "valkey/valkey:7.2.5", valkey.WithSnapshotting(10, 1), valkey.WithLogLevel(valkey.LogLevelVerbose), valkey.WithConfigFile(filepath.Join("testdata", "valkey7.conf")), diff --git a/modules/valkey/valkey.go b/modules/valkey/valkey.go index 00f4e91186..e8da1ed0e2 100644 --- a/modules/valkey/valkey.go +++ b/modules/valkey/valkey.go @@ -48,7 +48,7 @@ func (c *ValkeyContainer) ConnectionString(ctx context.Context) (string, error) // Deprecated: use Run instead // RunContainer creates an instance of the Valkey container type func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*ValkeyContainer, error) { - return Run(ctx, "docker.io/valkey/valkey:7.2.5", opts...) + return Run(ctx, "valkey/valkey:7.2.5", opts...) } // Run creates an instance of the Valkey container type diff --git a/modules/valkey/valkey_test.go b/modules/valkey/valkey_test.go index 484c75dabe..26e2ea93b8 100644 --- a/modules/valkey/valkey_test.go +++ b/modules/valkey/valkey_test.go @@ -18,7 +18,7 @@ import ( func TestIntegrationSetGet(t *testing.T) { ctx := context.Background() - valkeyContainer, err := tcvalkey.Run(ctx, "docker.io/valkey/valkey:7.2.5") + valkeyContainer, err := tcvalkey.Run(ctx, "valkey/valkey:7.2.5") testcontainers.CleanupContainer(t, valkeyContainer) require.NoError(t, err) @@ -28,7 +28,7 @@ func TestIntegrationSetGet(t *testing.T) { func TestValkeyWithConfigFile(t *testing.T) { ctx := context.Background() - valkeyContainer, err := tcvalkey.Run(ctx, "docker.io/valkey/valkey:7.2.5", tcvalkey.WithConfigFile(filepath.Join("testdata", "valkey7.conf"))) + valkeyContainer, err := tcvalkey.Run(ctx, "valkey/valkey:7.2.5", tcvalkey.WithConfigFile(filepath.Join("testdata", "valkey7.conf"))) testcontainers.CleanupContainer(t, valkeyContainer) require.NoError(t, err) @@ -45,7 +45,7 @@ func TestValkeyWithImage(t *testing.T) { // There is only one release of Valkey at the time of writing { name: "Valkey7.2.5", - image: "docker.io/valkey/valkey:7.2.5", + image: "valkey/valkey:7.2.5", }, } @@ -63,7 +63,7 @@ func TestValkeyWithImage(t *testing.T) { func TestValkeyWithLogLevel(t *testing.T) { ctx := context.Background() - valkeyContainer, err := tcvalkey.Run(ctx, "docker.io/valkey/valkey:7.2.5", tcvalkey.WithLogLevel(tcvalkey.LogLevelVerbose)) + valkeyContainer, err := tcvalkey.Run(ctx, "valkey/valkey:7.2.5", tcvalkey.WithLogLevel(tcvalkey.LogLevelVerbose)) testcontainers.CleanupContainer(t, valkeyContainer) require.NoError(t, err) @@ -73,7 +73,7 @@ func TestValkeyWithLogLevel(t *testing.T) { func TestValkeyWithSnapshotting(t *testing.T) { ctx := context.Background() - valkeyContainer, err := tcvalkey.Run(ctx, "docker.io/valkey/valkey:7.2.5", tcvalkey.WithSnapshotting(10, 1)) + valkeyContainer, err := tcvalkey.Run(ctx, "valkey/valkey:7.2.5", tcvalkey.WithSnapshotting(10, 1)) testcontainers.CleanupContainer(t, valkeyContainer) require.NoError(t, err) diff --git a/network/network_test.go b/network/network_test.go index 5cee817ecc..bbe5d45c7c 100644 --- a/network/network_test.go +++ b/network/network_test.go @@ -16,7 +16,7 @@ import ( ) const ( - nginxAlpineImage = "docker.io/nginx:alpine" + nginxAlpineImage = "nginx:alpine" nginxDefaultPort = "80/tcp" ) @@ -37,7 +37,7 @@ func TestNew(t *testing.T) { nginxC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ - Image: "nginx:alpine", + Image: nginxAlpineImage, ExposedPorts: []string{ "80/tcp", }, @@ -275,7 +275,7 @@ func TestNew_withOptions(t *testing.T) { nginx, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ - Image: "nginx:alpine", + Image: nginxAlpineImage, ExposedPorts: []string{ "80/tcp", }, diff --git a/options.go b/options.go index 2849b15667..4eb39058c8 100644 --- a/options.go +++ b/options.go @@ -186,7 +186,7 @@ func (p prependHubRegistry) Description() string { // - if the prefix is empty, the image is returned as is. // - if the image is a non-hub image (e.g. where another registry is set), the image is returned as is. // - if the image is a Docker Hub image where the hub registry is explicitly part of the name -// (i.e. anything with a docker.io or registry.hub.docker.com host part), the image is returned as is. +// (i.e. anything with a registry.hub.docker.com host part), the image is returned as is. func (p prependHubRegistry) Substitute(image string) (string, error) { registry := core.ExtractRegistry(image, "") diff --git a/scripts/bump-reaper.sh b/scripts/bump-reaper.sh index 34d17ce463..86af6b31c0 100755 --- a/scripts/bump-reaper.sh +++ b/scripts/bump-reaper.sh @@ -5,11 +5,11 @@ # dry-run mode, which will print the commands that would be executed, without actually # executing them. # -# Usage: ./scripts/bump-reaper.sh "docker.io/testcontainers/ryuk:1.2.3" +# Usage: ./scripts/bump-reaper.sh "testcontainers/ryuk:1.2.3" # # It's possible to run the script without dry-run mode actually executing the commands. # -# Usage: DRY_RUN="false" ./scripts/bump-reaper.sh "docker.io/testcontainers/ryuk:1.2.3" +# Usage: DRY_RUN="false" ./scripts/bump-reaper.sh "testcontainers/ryuk:1.2.3" readonly CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" readonly DRY_RUN="${DRY_RUN:-true}" diff --git a/scripts/release.sh b/scripts/release.sh index 6709c5c358..b675cb51e2 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -13,7 +13,7 @@ # Usage: DRY_RUN="false" ./scripts/release.sh readonly BUMP_TYPE="${BUMP_TYPE:-minor}" -readonly DOCKER_IMAGE_SEMVER="docker.io/mdelapenya/semver-tool:3.4.0" +readonly DOCKER_IMAGE_SEMVER="mdelapenya/semver-tool:3.4.0" readonly DRY_RUN="${DRY_RUN:-true}" readonly CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" readonly ROOT_DIR="$(dirname "$CURRENT_DIR")" diff --git a/testdata/Dockerfile b/testdata/Dockerfile index 7157611a13..14cfaf1e23 100644 --- a/testdata/Dockerfile +++ b/testdata/Dockerfile @@ -1 +1 @@ -FROM docker.io/redis:5.0-alpine@sha256:1a3c609295332f1ce603948142a132656c92a08149d7096e203058533c415b8c +FROM redis:5.0-alpine@sha256:1a3c609295332f1ce603948142a132656c92a08149d7096e203058533c415b8c diff --git a/testdata/args.Dockerfile b/testdata/args.Dockerfile index 984ef51eee..0260639719 100644 --- a/testdata/args.Dockerfile +++ b/testdata/args.Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/golang:1.13-alpine +FROM golang:1.13-alpine ARG FOO diff --git a/testdata/buildlog.Dockerfile b/testdata/buildlog.Dockerfile index 0a9bc82c98..67fd379018 100644 --- a/testdata/buildlog.Dockerfile +++ b/testdata/buildlog.Dockerfile @@ -1 +1 @@ -FROM docker.io/alpine +FROM alpine diff --git a/testdata/echo.Dockerfile b/testdata/echo.Dockerfile index 10ab9febf4..36951e1aa6 100644 --- a/testdata/echo.Dockerfile +++ b/testdata/echo.Dockerfile @@ -1,3 +1,3 @@ -FROM docker.io/alpine +FROM alpine CMD ["echo", "this is from the echo test Dockerfile"] \ No newline at end of file diff --git a/testdata/echoserver.Dockerfile b/testdata/echoserver.Dockerfile index 546489ffac..aaf835f35a 100644 --- a/testdata/echoserver.Dockerfile +++ b/testdata/echoserver.Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/golang:1.13-alpine +FROM golang:1.13-alpine WORKDIR /app diff --git a/testdata/error.Dockerfile b/testdata/error.Dockerfile index 1284e7285f..5d31293182 100644 --- a/testdata/error.Dockerfile +++ b/testdata/error.Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/alpine +FROM alpine RUN exit 1 diff --git a/testdata/target.Dockerfile b/testdata/target.Dockerfile index 996a83552f..f6a20273c7 100644 --- a/testdata/target.Dockerfile +++ b/testdata/target.Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/alpine AS target0 +FROM alpine AS target0 CMD ["echo", "target0"] FROM target0 AS target1 diff --git a/testhelpers_test.go b/testhelpers_test.go index 4f268a8aee..8d7587c17c 100644 --- a/testhelpers_test.go +++ b/testhelpers_test.go @@ -1,6 +1,6 @@ package testcontainers_test const ( - nginxAlpineImage = "docker.io/nginx:alpine" + nginxAlpineImage = "nginx:alpine" nginxDefaultPort = "80/tcp" ) diff --git a/wait/exec_test.go b/wait/exec_test.go index 8a82fb0211..4d2d97c51d 100644 --- a/wait/exec_test.go +++ b/wait/exec_test.go @@ -192,7 +192,7 @@ func TestExecStrategyWaitUntilReady_withExitCode(t *testing.T) { func TestExecStrategyWaitUntilReady_CustomResponseMatcher(t *testing.T) { // waitForExecExitCodeResponse { dockerReq := testcontainers.ContainerRequest{ - Image: "docker.io/nginx:latest", + Image: "nginx:latest", WaitingFor: wait.ForExec([]string{"echo", "hello world!"}). WithStartupTimeout(time.Second * 10). WithExitCodeMatcher(func(exitCode int) bool { diff --git a/wait/file_test.go b/wait/file_test.go index a25d8aa65f..22133ba349 100644 --- a/wait/file_test.go +++ b/wait/file_test.go @@ -79,7 +79,7 @@ func TestFileStrategyWaitUntilReady_WithMatcher(t *testing.T) { // waitForFileWithMatcher { var out bytes.Buffer dockerReq := testcontainers.ContainerRequest{ - Image: "docker.io/nginx:latest", + Image: "nginx:latest", WaitingFor: wait.ForFile("/etc/nginx/nginx.conf"). WithStartupTimeout(time.Second * 10). WithPollInterval(time.Second). From b7511cd05427318872e29e3b7b8e6ad4d2ec6889 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Mon, 28 Oct 2024 10:25:18 +0100 Subject: [PATCH 100/126] chore: use require.(No)Error(t,err) instead of t.Fatal(err) (#2851) Signed-off-by: Matthieu MOREL --- container_file_test.go | 6 +- docker_files_test.go | 36 +--- docker_test.go | 184 +++++--------------- file_test.go | 36 +--- from_dockerfile_test.go | 24 +-- image_substitutors_test.go | 46 ++--- image_test.go | 6 +- lifecycle_test.go | 8 +- logconsumer_test.go | 29 +-- modules/cassandra/cassandra_test.go | 12 +- modules/dolt/dolt_test.go | 8 +- modules/elasticsearch/elasticsearch_test.go | 14 +- modules/k6/k6_test.go | 8 +- modules/neo4j/neo4j_test.go | 8 +- modules/rabbitmq/rabbitmq_test.go | 29 +-- modules/weaviate/weaviate_test.go | 20 +-- wait/exec_test.go | 20 +-- wait/exit_test.go | 5 +- wait/host_port_test.go | 50 ++---- wait/sql_test.go | 6 +- 20 files changed, 150 insertions(+), 405 deletions(-) diff --git a/container_file_test.go b/container_file_test.go index 31273c9966..166225f327 100644 --- a/container_file_test.go +++ b/container_file_test.go @@ -7,6 +7,8 @@ import ( "os" "path/filepath" "testing" + + "github.com/stretchr/testify/require" ) func TestContainerFileValidation(t *testing.T) { @@ -17,9 +19,7 @@ func TestContainerFileValidation(t *testing.T) { } f, err := os.Open(filepath.Join(".", "testdata", "hello.sh")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) testTable := []ContainerFileValidationTestCase{ { diff --git a/docker_files_test.go b/docker_files_test.go index 9b8551f325..6b32168081 100644 --- a/docker_files_test.go +++ b/docker_files_test.go @@ -21,14 +21,10 @@ func TestCopyFileToContainer(t *testing.T) { // copyFileOnCreate { absPath, err := filepath.Abs(filepath.Join(".", "testdata", "hello.sh")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) r, err := os.Open(absPath) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ @@ -58,13 +54,9 @@ func TestCopyFileToRunningContainer(t *testing.T) { // Not using the assertations here to avoid leaking the library into the example // copyFileAfterCreate { waitForPath, err := filepath.Abs(filepath.Join(".", "testdata", "waitForHello.sh")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) helloPath, err := filepath.Abs(filepath.Join(".", "testdata", "hello.sh")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ @@ -100,9 +92,7 @@ func TestCopyDirectoryToContainer(t *testing.T) { // Not using the assertations here to avoid leaking the library into the example // copyDirectoryToContainer { dataDirectory, err := filepath.Abs(filepath.Join(".", "testdata")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ @@ -133,13 +123,9 @@ func TestCopyDirectoryToRunningContainerAsFile(t *testing.T) { // copyDirectoryToRunningContainerAsFile { dataDirectory, err := filepath.Abs(filepath.Join(".", "testdata")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) waitForPath, err := filepath.Abs(filepath.Join(dataDirectory, "waitForHello.sh")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ @@ -175,13 +161,9 @@ func TestCopyDirectoryToRunningContainerAsDir(t *testing.T) { // Not using the assertations here to avoid leaking the library into the example // copyDirectoryToRunningContainerAsDir { waitForPath, err := filepath.Abs(filepath.Join(".", "testdata", "waitForHello.sh")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) dataDirectory, err := filepath.Abs(filepath.Join(".", "testdata")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) ctr, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: testcontainers.ContainerRequest{ diff --git a/docker_test.go b/docker_test.go index 2cc762a6aa..a9fcbd03d6 100644 --- a/docker_test.go +++ b/docker_test.go @@ -55,9 +55,7 @@ func TestContainerWithHostNetworkOptions(t *testing.T) { SkipIfDockerDesktop(t, ctx) absPath, err := filepath.Abs(filepath.Join("testdata", "nginx-highport.conf")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) gcr := GenericContainerRequest{ ProviderType: providerType, @@ -114,9 +112,7 @@ func TestContainerWithHostNetworkOptions_UseExposePortsFromImageConfigs(t *testi nginxC, err := GenericContainer(ctx, gcr) CleanupContainer(t, nginxC) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) endpoint, err := nginxC.Endpoint(ctx, "http") if err != nil { @@ -124,9 +120,7 @@ func TestContainerWithHostNetworkOptions_UseExposePortsFromImageConfigs(t *testi } resp, err := http.Get(endpoint) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { @@ -173,9 +167,7 @@ func TestContainerWithHostNetwork(t *testing.T) { SkipIfDockerDesktop(t, ctx) absPath, err := filepath.Abs(filepath.Join("testdata", "nginx-highport.conf")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) gcr := GenericContainerRequest{ ProviderType: providerType, @@ -334,9 +326,7 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { t.Run("if not built from Dockerfile", func(t *testing.T) { ctx := context.Background() dockerClient, err := NewDockerClientWithOpts(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer dockerClient.Close() ctr, err := GenericContainer(ctx, GenericContainerRequest{ @@ -364,9 +354,7 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { t.Run("if built from Dockerfile", func(t *testing.T) { ctx := context.Background() dockerClient, err := NewDockerClientWithOpts(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer dockerClient.Close() req := ContainerRequest{ @@ -382,20 +370,14 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { Started: true, }) CleanupContainer(t, ctr) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) containerID := ctr.GetContainerID() resp, err := dockerClient.ContainerInspect(ctx, containerID) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) imageID := resp.Config.Image err = ctr.Terminate(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) _, _, err = dockerClient.ImageInspectWithRaw(ctx, imageID) if err == nil { @@ -438,9 +420,7 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { require.NoError(t, err) resp, err := http.Get(endpointA) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { @@ -448,14 +428,10 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { } endpointB, err := nginxB.PortEndpoint(ctx, nginxDefaultPort, "http") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) resp, err = http.Get(endpointB) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { @@ -484,25 +460,19 @@ func TestContainerCreation(t *testing.T) { require.NoError(t, err) resp, err := http.Get(endpoint) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Errorf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) } networkIP, err := nginxC.ContainerIP(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if len(networkIP) == 0 { t.Errorf("Expected an IP address, got %v", networkIP) } networkAliases, err := nginxC.NetworkAliases(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if len(networkAliases) != 1 { fmt.Printf("%v", networkAliases) t.Errorf("Expected number of connected networks %d. Got %d.", 0, len(networkAliases)) @@ -536,18 +506,14 @@ func TestContainerCreationWithName(t *testing.T) { require.NoError(t, err) inspect, err := nginxC.Inspect(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) name := inspect.Name if name != expectedName { t.Errorf("Expected container name '%s'. Got '%s'.", expectedName, name) } networks, err := nginxC.Networks(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if len(networks) != 1 { t.Errorf("Expected networks 1. Got '%d'.", len(networks)) } @@ -567,9 +533,7 @@ func TestContainerCreationWithName(t *testing.T) { require.NoError(t, err) resp, err := http.Get(endpoint) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { @@ -596,13 +560,9 @@ func TestContainerCreationAndWaitForListeningPortLongEnough(t *testing.T) { require.NoError(t, err) origin, err := nginxC.PortEndpoint(ctx, nginxDefaultPort, "http") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) resp, err := http.Get(origin) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { @@ -649,13 +609,9 @@ func TestContainerRespondsWithHttp200ForIndex(t *testing.T) { require.NoError(t, err) origin, err := nginxC.PortEndpoint(ctx, nginxDefaultPort, "http") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) resp, err := http.Get(origin) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { @@ -1134,9 +1090,7 @@ func ExampleContainer_MappedPort() { func TestContainerCreationWithVolumeAndFileWritingToIt(t *testing.T) { absPath, err := filepath.Abs(filepath.Join(".", "testdata", "hello.sh")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) ctx, cnl := context.WithTimeout(context.Background(), 30*time.Second) defer cnl() @@ -1184,18 +1138,14 @@ func TestContainerWithTmpFs(t *testing.T) { // exec_reader_example { c, reader, err := ctr.Exec(ctx, []string{"ls", path}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if c != 1 { t.Fatalf("File %s should not have existed, expected return code 1, got %v", path, c) } buf := new(strings.Builder) _, err = io.Copy(buf, reader) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // See the logs from the command execution. t.Log(buf.String()) @@ -1203,18 +1153,14 @@ func TestContainerWithTmpFs(t *testing.T) { // exec_example { c, _, err = ctr.Exec(ctx, []string{"touch", path}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if c != 0 { t.Fatalf("File %s should have been created successfully, expected return code 0, got %v", path, c) } // } c, _, err = ctr.Exec(ctx, []string{"ls", path}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if c != 0 { t.Fatalf("File %s should exist, expected return code 0, got %v", path, c) } @@ -1393,9 +1339,7 @@ func TestDockerContainerCopyFileToContainer(t *testing.T) { _ = nginxC.CopyFileToContainer(ctx, filepath.Join(".", "testdata", "hello.sh"), tc.copiedFileName, 700) c, _, err := nginxC.Exec(ctx, []string{"bash", tc.copiedFileName}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if c != 0 { t.Fatalf("File %s should exist, expected return code 0, got %v", tc.copiedFileName, c) } @@ -1424,9 +1368,7 @@ func TestDockerContainerCopyDirToContainer(t *testing.T) { p = filepath.Join(".", "testdata") err = nginxC.CopyDirToContainer(ctx, p, "/tmp/testdata", 700) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) assertExtractedFiles(t, ctx, nginxC, p, "/tmp/testdata/") } @@ -1604,17 +1546,11 @@ func TestDockerContainerCopyToContainer(t *testing.T) { require.NoError(t, err) fileContent, err := os.ReadFile(filepath.Join(".", "testdata", "hello.sh")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) err = nginxC.CopyToContainer(ctx, fileContent, tc.copiedFileName, 700) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) c, _, err := nginxC.Exec(ctx, []string{"bash", tc.copiedFileName}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if c != 0 { t.Fatalf("File %s should exist, expected return code 0, got %v", tc.copiedFileName, c) } @@ -1624,9 +1560,7 @@ func TestDockerContainerCopyToContainer(t *testing.T) { func TestDockerContainerCopyFileFromContainer(t *testing.T) { fileContent, err := os.ReadFile(filepath.Join(".", "testdata", "hello.sh")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) ctx := context.Background() nginxC, err := GenericContainer(ctx, GenericContainerRequest{ @@ -1644,23 +1578,17 @@ func TestDockerContainerCopyFileFromContainer(t *testing.T) { copiedFileName := "hello_copy.sh" _ = nginxC.CopyFileToContainer(ctx, filepath.Join(".", "testdata", "hello.sh"), "/"+copiedFileName, 700) c, _, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, 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) - } + require.NoError(t, err) defer reader.Close() fileContentFromContainer, err := io.ReadAll(reader) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) assert.Equal(t, fileContent, fileContentFromContainer) } @@ -1682,23 +1610,17 @@ func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { copiedFileName := "hello_copy.sh" _ = nginxC.CopyFileToContainer(ctx, filepath.Join(".", "testdata", "empty.sh"), "/"+copiedFileName, 700) c, _, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, 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) - } + require.NoError(t, err) defer reader.Close() fileContentFromContainer, err := io.ReadAll(reader) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) require.Empty(t, fileContentFromContainer) } @@ -1809,9 +1731,7 @@ func TestContainerRunningCheckingStatusCode(t *testing.T) { Started: true, }) CleanupContainer(t, influx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } func TestContainerWithUserID(t *testing.T) { @@ -1831,14 +1751,10 @@ func TestContainerWithUserID(t *testing.T) { require.NoError(t, err) r, err := ctr.Logs(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer r.Close() b, err := io.ReadAll(r) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) actual := regexp.MustCompile(`\D+`).ReplaceAllString(string(b), "") assert.Equal(t, req.User, actual) } @@ -1859,14 +1775,10 @@ func TestContainerWithNoUserID(t *testing.T) { require.NoError(t, err) r, err := ctr.Logs(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer r.Close() b, err := io.ReadAll(r) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) actual := regexp.MustCompile(`\D+`).ReplaceAllString(string(b), "") assert.Equal(t, "0", actual) } @@ -1875,15 +1787,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 provider, err := providerType.GetProvider(WithLogger(TestLogger(t))) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer provider.Close() ip, err := provider.(*DockerProvider).GetGatewayIP(context.Background()) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if ip == "" { t.Fatal("could not get gateway ip") } diff --git a/file_test.go b/file_test.go index 1128304df7..06ef8905e7 100644 --- a/file_test.go +++ b/file_test.go @@ -78,34 +78,24 @@ func Test_TarDir(t *testing.T) { } buff, err := tarDir(src, 0o755) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) tmpDir := filepath.Join(t.TempDir(), "subfolder") err = untar(tmpDir, bytes.NewReader(buff.Bytes())) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) srcFiles, err := os.ReadDir(src) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) for _, srcFile := range srcFiles { if srcFile.IsDir() { continue } srcBytes, err := os.ReadFile(filepath.Join(src, srcFile.Name())) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) untarBytes, err := os.ReadFile(filepath.Join(tmpDir, "testdata", srcFile.Name())) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) assert.Equal(t, srcBytes, untarBytes) } }) @@ -114,28 +104,20 @@ func Test_TarDir(t *testing.T) { func Test_TarFile(t *testing.T) { b, err := os.ReadFile(filepath.Join(".", "testdata", "Dockerfile")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) buff, err := tarFile("Docker.file", func(tw io.Writer) error { _, err := tw.Write(b) return err }, int64(len(b)), 0o755) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) tmpDir := t.TempDir() err = untar(tmpDir, bytes.NewReader(buff.Bytes())) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) untarBytes, err := os.ReadFile(filepath.Join(tmpDir, "Docker.file")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) assert.Equal(t, b, untarBytes) } diff --git a/from_dockerfile_test.go b/from_dockerfile_test.go index 854492fbfd..75f80537d2 100644 --- a/from_dockerfile_test.go +++ b/from_dockerfile_test.go @@ -17,9 +17,7 @@ import ( func TestBuildImageFromDockerfile(t *testing.T) { provider, err := NewDockerProvider() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer provider.Close() cli := provider.Client() @@ -47,17 +45,13 @@ func TestBuildImageFromDockerfile(t *testing.T) { Force: true, PruneChildren: true, }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) }) } func TestBuildImageFromDockerfile_NoRepo(t *testing.T) { provider, err := NewDockerProvider() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer provider.Close() cli := provider.Client() @@ -82,9 +76,7 @@ func TestBuildImageFromDockerfile_NoRepo(t *testing.T) { Force: true, PruneChildren: true, }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) }) } @@ -112,9 +104,7 @@ func TestBuildImageFromDockerfile_BuildError(t *testing.T) { func TestBuildImageFromDockerfile_NoTag(t *testing.T) { provider, err := NewDockerProvider() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer provider.Close() cli := provider.Client() @@ -139,9 +129,7 @@ func TestBuildImageFromDockerfile_NoTag(t *testing.T) { Force: true, PruneChildren: true, }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) }) } diff --git a/image_substitutors_test.go b/image_substitutors_test.go index 92b42e63b3..4a168254e6 100644 --- a/image_substitutors_test.go +++ b/image_substitutors_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go/internal/config" ) @@ -12,9 +14,7 @@ func TestCustomHubSubstitutor(t *testing.T) { s := NewCustomHubSubstitutor("quay.io") img, err := s.Substitute("foo/foo:latest") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if img != "quay.io/foo/foo:latest" { t.Errorf("expected quay.io/foo/foo:latest, got %s", img) @@ -24,9 +24,7 @@ func TestCustomHubSubstitutor(t *testing.T) { s := NewCustomHubSubstitutor("quay.io") img, err := s.Substitute("quay.io/foo/foo:latest") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if img != "quay.io/foo/foo:latest" { t.Errorf("expected quay.io/foo/foo:latest, got %s", img) @@ -39,9 +37,7 @@ func TestCustomHubSubstitutor(t *testing.T) { s := NewCustomHubSubstitutor("quay.io") img, err := s.Substitute("foo/foo:latest") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if img != "foo/foo:latest" { t.Errorf("expected foo/foo:latest, got %s", img) @@ -55,9 +51,7 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { s := newPrependHubRegistry("my-registry") img, err := s.Substitute("foo:latest") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if img != "my-registry/foo:latest" { t.Errorf("expected my-registry/foo, got %s", img) @@ -67,9 +61,7 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { s := newPrependHubRegistry("my-registry") img, err := s.Substitute("user/foo:latest") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if img != "my-registry/user/foo:latest" { t.Errorf("expected my-registry/foo, got %s", img) @@ -80,9 +72,7 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { s := newPrependHubRegistry("my-registry") img, err := s.Substitute("org/user/foo:latest") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if img != "my-registry/org/user/foo:latest" { t.Errorf("expected my-registry/org/foo:latest, got %s", img) @@ -95,9 +85,7 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { s := newPrependHubRegistry("my-registry") img, err := s.Substitute("quay.io/foo:latest") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if img != "quay.io/foo:latest" { t.Errorf("expected quay.io/foo:latest, got %s", img) @@ -108,9 +96,7 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { s := newPrependHubRegistry("my-registry") img, err := s.Substitute("registry.hub.docker.com/library/foo:latest") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if img != "registry.hub.docker.com/library/foo:latest" { t.Errorf("expected registry.hub.docker.com/library/foo:latest, got %s", img) @@ -121,9 +107,7 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { s := newPrependHubRegistry("my-registry") img, err := s.Substitute("registry.hub.docker.com/foo:latest") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if img != "registry.hub.docker.com/foo:latest" { t.Errorf("expected registry.hub.docker.com/foo:latest, got %s", img) @@ -150,14 +134,10 @@ func TestSubstituteBuiltImage(t *testing.T) { config.Reset() c, err := GenericContainer(context.Background(), req) CleanupContainer(t, c) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) json, err := c.Inspect(context.Background()) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if json.Config.Image != "my-registry/my-repo:my-image" { t.Errorf("expected my-registry/my-repo:my-image, got %s", json.Config.Image) diff --git a/image_test.go b/image_test.go index 2344c5063d..39f8134acd 100644 --- a/image_test.go +++ b/image_test.go @@ -6,6 +6,8 @@ import ( "path/filepath" "testing" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go/internal/core" ) @@ -79,9 +81,7 @@ func TestSaveImages(t *testing.T) { } info, err := os.Stat(output) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if info.Size() == 0 { t.Fatalf("output file is empty") diff --git a/lifecycle_test.go b/lifecycle_test.go index 0d7e9c7861..374d45bf80 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -904,14 +904,10 @@ func TestPrintContainerLogsOnError(t *testing.T) { }) CleanupContainer(t, ctr) // it should fail because the waiting for condition is not met - if err == nil { - t.Fatal(err) - } + require.Error(t, err) containerLogs, err := ctr.Logs(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer containerLogs.Close() // read container logs line by line, checking that each line is present in the stdout diff --git a/logconsumer_test.go b/logconsumer_test.go index f16c2fc007..e4ee916e0f 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -285,9 +285,7 @@ func TestContainerLogWithErrClosed(t *testing.T) { opts := []client.Opt{client.WithHost(remoteDocker), client.WithAPIVersionNegotiation()} dockerClient, err := NewDockerClientWithOpts(ctx, opts...) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer dockerClient.Close() provider := &DockerProvider{ @@ -313,18 +311,13 @@ func TestContainerLogWithErrClosed(t *testing.T) { Consumers: []LogConsumer{&consumer}, }, }) - if err != nil { - t.Fatal(err) - } - if err := nginx.Start(ctx); err != nil { - t.Fatal(err) - } + require.NoError(t, err) + err = nginx.Start(ctx) + require.NoError(t, err) CleanupContainer(t, nginx) port, err := nginx.MappedPort(ctx, "80/tcp") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // Gather the initial container logs time.Sleep(time.Second * 1) @@ -384,19 +377,13 @@ func TestContainerLogsShouldBeWithoutStreamHeader(t *testing.T) { Started: true, }) CleanupContainer(t, ctr) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) r, err := ctr.Logs(ctx) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer r.Close() b, err := io.ReadAll(r) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) assert.Equal(t, "0", strings.TrimSpace(string(b))) } diff --git a/modules/cassandra/cassandra_test.go b/modules/cassandra/cassandra_test.go index 3c8cd1e918..f4979dff5f 100644 --- a/modules/cassandra/cassandra_test.go +++ b/modules/cassandra/cassandra_test.go @@ -62,9 +62,7 @@ func TestCassandraWithConfigFile(t *testing.T) { cluster := gocql.NewCluster(connectionHost) session, err := cluster.CreateSession() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer session.Close() var result string @@ -90,9 +88,7 @@ func TestCassandraWithInitScripts(t *testing.T) { cluster := gocql.NewCluster(connectionHost) session, err := cluster.CreateSession() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer session.Close() var test Test @@ -113,9 +109,7 @@ func TestCassandraWithInitScripts(t *testing.T) { cluster := gocql.NewCluster(connectionHost) session, err := cluster.CreateSession() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer session.Close() var test Test diff --git a/modules/dolt/dolt_test.go b/modules/dolt/dolt_test.go index b239136e38..a1e46cc976 100644 --- a/modules/dolt/dolt_test.go +++ b/modules/dolt/dolt_test.go @@ -72,14 +72,10 @@ func TestDoltWithPublicRemoteCloneUrl(t *testing.T) { func createTestCredsFile(t *testing.T) string { t.Helper() file, err := os.CreateTemp(t.TempDir(), "prefix") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer file.Close() _, err = file.WriteString("some-fake-creds") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) return file.Name() } diff --git a/modules/elasticsearch/elasticsearch_test.go b/modules/elasticsearch/elasticsearch_test.go index 69c4149fc4..fdfe636769 100644 --- a/modules/elasticsearch/elasticsearch_test.go +++ b/modules/elasticsearch/elasticsearch_test.go @@ -138,9 +138,8 @@ func TestElasticsearch(t *testing.T) { } var esResp ElasticsearchResponse - if err := json.NewDecoder(resp.Body).Decode(&esResp); err != nil { - t.Fatal(err) - } + err = json.NewDecoder(resp.Body).Decode(&esResp) + require.NoError(t, err) if tt.image == baseImage7 && esResp.Version.Number != "7.9.2" { t.Fatal("expected version to be 7.9.2 but got", esResp.Version.Number) @@ -203,9 +202,7 @@ func TestElasticsearch8WithoutCredentials(t *testing.T) { httpClient := configureHTTPClient(ctr) req, err := http.NewRequest("GET", ctr.Settings.Address, nil) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // elastic:changeme are the default credentials for Elasticsearch 8 req.SetBasicAuth(ctr.Settings.Username, ctr.Settings.Password) @@ -218,9 +215,8 @@ func TestElasticsearch8WithoutCredentials(t *testing.T) { defer resp.Body.Close() var esResp ElasticsearchResponse - if err := json.NewDecoder(resp.Body).Decode(&esResp); err != nil { - t.Fatal(err) - } + err = json.NewDecoder(resp.Body).Decode(&esResp) + require.NoError(t, err) if esResp.Tagline != "You Know, for Search" { t.Fatal("expected tagline to be 'You Know, for Search' but got", esResp.Tagline) diff --git a/modules/k6/k6_test.go b/modules/k6/k6_test.go index f2cc39ef72..bc40bd13a6 100644 --- a/modules/k6/k6_test.go +++ b/modules/k6/k6_test.go @@ -63,16 +63,12 @@ func TestK6(t *testing.T) { var options testcontainers.CustomizeRequestOption if !strings.HasPrefix(tc.script, "http") { absPath, err := filepath.Abs(filepath.Join("scripts", tc.script)) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) options = k6.WithTestScript(absPath) } else { uri, err := url.Parse(tc.script) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) desc := k6.DownloadableFile{Uri: *uri, DownloadDir: t.TempDir()} options = k6.WithRemoteTestScript(desc) diff --git a/modules/neo4j/neo4j_test.go b/modules/neo4j/neo4j_test.go index 9d41e4afe5..a5cff51182 100644 --- a/modules/neo4j/neo4j_test.go +++ b/modules/neo4j/neo4j_test.go @@ -167,13 +167,9 @@ func createDriver(t *testing.T, ctx context.Context, container *neo4j.Neo4jConta // boltURL { boltUrl, err := container.BoltUrl(ctx) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) driver, err := neo.NewDriverWithContext(boltUrl, neo.BasicAuth("neo4j", testPassword, "")) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) t.Cleanup(func() { if err := driver.Close(ctx); err != nil { t.Fatalf("failed to close neo: %s", err) diff --git a/modules/rabbitmq/rabbitmq_test.go b/modules/rabbitmq/rabbitmq_test.go index f0b82ca2db..6c4cca0c8c 100644 --- a/modules/rabbitmq/rabbitmq_test.go +++ b/modules/rabbitmq/rabbitmq_test.go @@ -93,9 +93,8 @@ func TestRunContainer_connectUsingAmqps(t *testing.T) { if amqpsConnection.IsClosed() { t.Fatal(fmt.Errorf("AMQPS Connection unexpectdely closed")) } - if err = amqpsConnection.Close(); err != nil { - t.Fatal(err) - } + err = amqpsConnection.Close() + require.NoError(t, err) } func TestRunContainer_withAllSettings(t *testing.T) { @@ -248,14 +247,10 @@ func assertEntity(t *testing.T, container testcontainers.Container, listCommand cmd := []string{"rabbitmqadmin", "list", listCommand} _, out, err := container.Exec(ctx, cmd) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) check, err := io.ReadAll(out) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) for _, e := range entities { if !strings.Contains(string(check), e) { @@ -277,14 +272,10 @@ func assertEntityWithVHost(t *testing.T, container testcontainers.Container, lis } _, out, err := container.Exec(ctx, cmd) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) check, err := io.ReadAll(out) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) for _, e := range entities { if !strings.Contains(string(check), e) { @@ -303,14 +294,10 @@ func assertPluginIsEnabled(t *testing.T, container testcontainers.Container, plu for _, plugin := range plugins { _, out, err := container.Exec(ctx, []string{"rabbitmq-plugins", "is_enabled", plugin}) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) check, err := io.ReadAll(out) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) if !strings.Contains(string(check), plugin+" is enabled") { return false diff --git a/modules/weaviate/weaviate_test.go b/modules/weaviate/weaviate_test.go index d6dae679e6..faf8e42f92 100644 --- a/modules/weaviate/weaviate_test.go +++ b/modules/weaviate/weaviate_test.go @@ -42,9 +42,7 @@ func TestWeaviate(t *testing.T) { // gRPCHostAddress { host, err := ctr.GrpcHostAddress(ctx) // } - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) var opts []grpc.DialOption @@ -65,22 +63,14 @@ func TestWeaviate(t *testing.T) { t.Run("Weaviate client", func(tt *testing.T) { httpScheme, httpHost, err := ctr.HttpHostAddress(ctx) - if err != nil { - tt.Fatal(err) - } + require.NoError(tt, err) grpcHost, err := ctr.GrpcHostAddress(ctx) - if err != nil { - tt.Fatal(err) - } + require.NoError(tt, err) config := wvt.Config{Scheme: httpScheme, Host: httpHost, GrpcConfig: &wvtgrpc.Config{Host: grpcHost}} client, err := wvt.NewClient(config) - if err != nil { - tt.Fatal(err) - } + require.NoError(tt, err) meta, err := client.Misc().MetaGetter().Do(ctx) - if err != nil { - tt.Fatal(err) - } + require.NoError(tt, err) if meta == nil || meta.Version == "" { tt.Fatal("failed to get /v1/meta response") diff --git a/wait/exec_test.go b/wait/exec_test.go index 4d2d97c51d..ab84fabd17 100644 --- a/wait/exec_test.go +++ b/wait/exec_test.go @@ -114,18 +114,14 @@ func TestExecStrategyWaitUntilReady(t *testing.T) { wg := wait.NewExecStrategy([]string{"true"}). WithStartupTimeout(30 * time.Second) err := wg.WaitUntilReady(context.Background(), target) - if err != nil { - t.Fatal(err) - } + require.NoError(t, 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) - } + require.NoError(t, err) } func TestExecStrategyWaitUntilReady_MultipleChecks(t *testing.T) { @@ -136,9 +132,7 @@ func TestExecStrategyWaitUntilReady_MultipleChecks(t *testing.T) { wg := wait.NewExecStrategy([]string{"true"}). WithPollInterval(500 * time.Millisecond) err := wg.WaitUntilReady(context.Background(), target) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } func TestExecStrategyWaitUntilReady_DeadlineExceeded(t *testing.T) { @@ -163,9 +157,7 @@ func TestExecStrategyWaitUntilReady_CustomExitCode(t *testing.T) { return exitCode == 10 }) err := wg.WaitUntilReady(context.Background(), target) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } func TestExecStrategyWaitUntilReady_withExitCode(t *testing.T) { @@ -176,9 +168,7 @@ func TestExecStrategyWaitUntilReady_withExitCode(t *testing.T) { // Default is 60. Let's shorten that wg.WithStartupTimeout(time.Second * 2) err := wg.WaitUntilReady(context.Background(), target) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // Ensure we aren't spuriously returning on any code wg = wait.NewExecStrategy([]string{"true"}).WithExitCode(0) diff --git a/wait/exit_test.go b/wait/exit_test.go index 4795fd4ad6..5c2ec004db 100644 --- a/wait/exit_test.go +++ b/wait/exit_test.go @@ -9,6 +9,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/go-connections/nat" + "github.com/stretchr/testify/require" tcexec "github.com/testcontainers/testcontainers-go/exec" ) @@ -56,7 +57,5 @@ func TestWaitForExit(t *testing.T) { } wg := NewExitStrategy().WithExitTimeout(100 * time.Millisecond) err := wg.WaitUntilReady(context.Background(), target) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } diff --git a/wait/host_port_test.go b/wait/host_port_test.go index 1623ef95c0..4dbaad741f 100644 --- a/wait/host_port_test.go +++ b/wait/host_port_test.go @@ -19,16 +19,12 @@ import ( func TestWaitForListeningPortSucceeds(t *testing.T) { listener, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer listener.Close() rawPort := listener.Addr().(*net.TCPAddr).Port port, err := nat.NewPort("tcp", strconv.Itoa(rawPort)) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) var mappedPortCount, execCount int target := &MockStrategyTarget{ @@ -60,23 +56,18 @@ func TestWaitForListeningPortSucceeds(t *testing.T) { WithStartupTimeout(5 * time.Second). WithPollInterval(100 * time.Millisecond) - if err := wg.WaitUntilReady(context.Background(), target); err != nil { - t.Fatal(err) - } + err = wg.WaitUntilReady(context.Background(), target) + require.NoError(t, err) } func TestWaitForExposedPortSucceeds(t *testing.T) { listener, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer listener.Close() rawPort := listener.Addr().(*net.TCPAddr).Port port, err := nat.NewPort("tcp", strconv.Itoa(rawPort)) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) var mappedPortCount, execCount int target := &MockStrategyTarget{ @@ -124,9 +115,8 @@ func TestWaitForExposedPortSucceeds(t *testing.T) { WithStartupTimeout(5 * time.Second). WithPollInterval(100 * time.Millisecond) - if err := wg.WaitUntilReady(context.Background(), target); err != nil { - t.Fatal(err) - } + err = wg.WaitUntilReady(context.Background(), target) + require.NoError(t, err) } func TestHostPortStrategyFailsWhileGettingPortDueToOOMKilledContainer(t *testing.T) { @@ -298,16 +288,12 @@ func TestHostPortStrategyFailsWhileExternalCheckingDueToUnexpectedContainerStatu func TestHostPortStrategyFailsWhileInternalCheckingDueToOOMKilledContainer(t *testing.T) { listener, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer listener.Close() rawPort := listener.Addr().(*net.TCPAddr).Port port, err := nat.NewPort("tcp", strconv.Itoa(rawPort)) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) var stateCount int target := &MockStrategyTarget{ @@ -342,16 +328,12 @@ func TestHostPortStrategyFailsWhileInternalCheckingDueToOOMKilledContainer(t *te func TestHostPortStrategyFailsWhileInternalCheckingDueToExitedContainer(t *testing.T) { listener, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer listener.Close() rawPort := listener.Addr().(*net.TCPAddr).Port port, err := nat.NewPort("tcp", strconv.Itoa(rawPort)) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) var stateCount int target := &MockStrategyTarget{ @@ -387,16 +369,12 @@ func TestHostPortStrategyFailsWhileInternalCheckingDueToExitedContainer(t *testi func TestHostPortStrategyFailsWhileInternalCheckingDueToUnexpectedContainerStatus(t *testing.T) { listener, err := net.Listen("tcp", "localhost:0") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) defer listener.Close() rawPort := listener.Addr().(*net.TCPAddr).Port port, err := nat.NewPort("tcp", strconv.Itoa(rawPort)) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) var stateCount int target := &MockStrategyTarget{ diff --git a/wait/sql_test.go b/wait/sql_test.go index 053ed965e8..2a7db5b330 100644 --- a/wait/sql_test.go +++ b/wait/sql_test.go @@ -9,6 +9,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/go-connections/nat" + "github.com/stretchr/testify/require" ) func Test_waitForSql_WithQuery(t *testing.T) { @@ -102,9 +103,8 @@ func TestWaitForSQLSucceeds(t *testing.T) { WithStartupTimeout(500 * time.Millisecond). WithPollInterval(100 * time.Millisecond) - if err := wg.WaitUntilReady(context.Background(), target); err != nil { - t.Fatal(err) - } + err := wg.WaitUntilReady(context.Background(), target) + require.NoError(t, err) } func TestWaitForSQLFailsWhileGettingPortDueToOOMKilledContainer(t *testing.T) { From 11eb809752b0a8fbe86d5da84a075b54cc4f330d Mon Sep 17 00:00:00 2001 From: abhipranay Date: Mon, 28 Oct 2024 10:55:21 +0100 Subject: [PATCH 101/126] fix: mongodb replicaset should work with auth (#2847) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added custom entrypoint to setup keyfile with proper user permissions * added testcases for replicaset with auth * implementation to support replicaset with auth * removed unnecessary files * cleanup * added autodetection for user:group and entrypoint * added tests for replica set and auth for different images * renamed entrypoint to differentiate between custom entrypoint of testcontainers * code cleanup * renamed newly added tests * fixed names of tests to use slash separated options * fix: lint --------- Co-authored-by: Manuel de la Peña --- modules/mongodb/cli.go | 32 ++++++ modules/mongodb/mongodb.go | 129 +++++++++++++++++++------ modules/mongodb/mongodb_test.go | 59 ++++++++++- modules/mongodb/mount/entrypoint-tc.sh | 32 ++++++ 4 files changed, 218 insertions(+), 34 deletions(-) create mode 100644 modules/mongodb/cli.go create mode 100644 modules/mongodb/mount/entrypoint-tc.sh diff --git a/modules/mongodb/cli.go b/modules/mongodb/cli.go new file mode 100644 index 0000000000..f990bf17c8 --- /dev/null +++ b/modules/mongodb/cli.go @@ -0,0 +1,32 @@ +package mongodb + +import "fmt" + +// mongoCli is cli to interact with MongoDB. If username and password are provided +// it will use credentials to authenticate. +type mongoCli struct { + mongoshBaseCmd string + mongoBaseCmd string +} + +func newMongoCli(username string, password string) mongoCli { + authArgs := "" + if username != "" && password != "" { + authArgs = fmt.Sprintf("--username %s --password %s", username, password) + } + + return mongoCli{ + mongoshBaseCmd: fmt.Sprintf("mongosh %s --quiet", authArgs), + mongoBaseCmd: fmt.Sprintf("mongo %s --quiet", authArgs), + } +} + +func (m mongoCli) eval(command string, args ...any) []string { + command = "\"" + fmt.Sprintf(command, args...) + "\"" + + return []string{ + "sh", + "-c", + m.mongoshBaseCmd + " --eval " + command + " || " + m.mongoBaseCmd + " --eval " + command, + } +} diff --git a/modules/mongodb/mongodb.go b/modules/mongodb/mongodb.go index 3f73e5dc70..8acbf98ee2 100644 --- a/modules/mongodb/mongodb.go +++ b/modules/mongodb/mongodb.go @@ -1,7 +1,9 @@ package mongodb import ( + "bytes" "context" + _ "embed" "fmt" "time" @@ -9,11 +11,21 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) +//go:embed mount/entrypoint-tc.sh +var entrypointContent []byte + +const ( + entrypointPath = "/tmp/entrypoint-tc.sh" + keyFilePath = "/tmp/mongo_keyfile" + replicaSetOptEnvKey = "testcontainers.mongodb.replicaset_name" +) + // MongoDBContainer represents the MongoDB container type used in the module type MongoDBContainer struct { testcontainers.Container - username string - password string + username string + password string + replicaSet string } // Deprecated: use Run instead @@ -50,10 +62,17 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom return nil, fmt.Errorf("if you specify username or password, you must provide both of them") } + replicaSet := req.Env[replicaSetOptEnvKey] + if replicaSet != "" { + if err := configureRequestForReplicaset(username, password, replicaSet, &genericContainerReq); err != nil { + return nil, err + } + } + container, err := testcontainers.GenericContainer(ctx, genericContainerReq) var c *MongoDBContainer if container != nil { - c = &MongoDBContainer{Container: container, username: username, password: password} + c = &MongoDBContainer{Container: container, username: username, password: password, replicaSet: replicaSet} } if err != nil { @@ -85,28 +104,10 @@ func WithPassword(password string) testcontainers.CustomizeRequestOption { } } -// WithReplicaSet configures the container to run a single-node MongoDB replica set named "rs". -// It will wait until the replica set is ready. +// WithReplicaSet sets the replica set name for Single node MongoDB replica set. func WithReplicaSet(replSetName string) testcontainers.CustomizeRequestOption { return func(req *testcontainers.GenericContainerRequest) error { - req.Cmd = append(req.Cmd, "--replSet", replSetName) - req.WaitingFor = wait.ForAll( - req.WaitingFor, - wait.ForExec(eval("rs.status().ok")), - ).WithDeadline(60 * time.Second) - req.LifecycleHooks = append(req.LifecycleHooks, testcontainers.ContainerLifecycleHooks{ - PostStarts: []testcontainers.ContainerHook{ - func(ctx context.Context, c testcontainers.Container) error { - ip, err := c.ContainerIP(ctx) - if err != nil { - return fmt.Errorf("container ip: %w", err) - } - - cmd := eval("rs.initiate({ _id: '%s', members: [ { _id: 0, host: '%s:27017' } ] })", replSetName, ip) - return wait.ForExec(cmd).WaitUntilReady(ctx, c) - }, - }, - }) + req.Env[replicaSetOptEnvKey] = replSetName return nil } @@ -129,14 +130,80 @@ func (c *MongoDBContainer) ConnectionString(ctx context.Context) (string, error) return c.Endpoint(ctx, "mongodb") } -// eval builds an mongosh|mongo eval command. -func eval(command string, args ...any) []string { - command = "\"" + fmt.Sprintf(command, args...) + "\"" +func setupEntrypointForAuth(req *testcontainers.GenericContainerRequest) { + req.Files = append( + req.Files, testcontainers.ContainerFile{ + Reader: bytes.NewReader(entrypointContent), + ContainerFilePath: entrypointPath, + FileMode: 0o755, + }, + ) + req.Entrypoint = []string{entrypointPath} + req.Env["MONGO_KEYFILE"] = keyFilePath +} + +func configureRequestForReplicaset( + username string, + password string, + replicaSet string, + genericContainerReq *testcontainers.GenericContainerRequest, +) error { + if !(username != "" && password != "") { + return noAuthReplicaSet(replicaSet)(genericContainerReq) + } - return []string{ - "sh", - "-c", - // In previous versions, the binary "mongosh" was named "mongo". - "mongosh --quiet --eval " + command + " || mongo --quiet --eval " + command, + return withAuthReplicaset(replicaSet, username, password)(genericContainerReq) +} + +func noAuthReplicaSet(replSetName string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + cli := newMongoCli("", "") + req.Cmd = append(req.Cmd, "--replSet", replSetName) + initiateReplicaSet(req, cli, replSetName) + + return nil + } +} + +func initiateReplicaSet(req *testcontainers.GenericContainerRequest, cli mongoCli, replSetName string) { + req.WaitingFor = wait.ForAll( + req.WaitingFor, + wait.ForExec(cli.eval("rs.status().ok")), + ).WithDeadline(60 * time.Second) + + req.LifecycleHooks = append( + req.LifecycleHooks, testcontainers.ContainerLifecycleHooks{ + PostStarts: []testcontainers.ContainerHook{ + func(ctx context.Context, c testcontainers.Container) error { + ip, err := c.ContainerIP(ctx) + if err != nil { + return fmt.Errorf("container ip: %w", err) + } + + cmd := cli.eval( + "rs.initiate({ _id: '%s', members: [ { _id: 0, host: '%s:27017' } ] })", + replSetName, + ip, + ) + + return wait.ForExec(cmd).WaitUntilReady(ctx, c) + }, + }, + }, + ) +} + +func withAuthReplicaset( + replSetName string, + username string, + password string, +) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) error { + setupEntrypointForAuth(req) + cli := newMongoCli(username, password) + req.Cmd = append(req.Cmd, "--replSet", replSetName, "--keyFile", keyFilePath) + initiateReplicaSet(req, cli, replSetName) + + return nil } } diff --git a/modules/mongodb/mongodb_test.go b/modules/mongodb/mongodb_test.go index 03d669bb7e..8cc49e629c 100644 --- a/modules/mongodb/mongodb_test.go +++ b/modules/mongodb/mongodb_test.go @@ -36,26 +36,79 @@ func TestMongoDB(t *testing.T) { opts: []testcontainers.ContainerCustomizer{}, }, { - name: "With Replica set and mongo:4", + name: "with-replica/mongo:4", img: "mongo:4", opts: []testcontainers.ContainerCustomizer{ mongodb.WithReplicaSet("rs"), }, }, { - name: "With Replica set and mongo:6", + name: "with-replica/mongo:6", img: "mongo:6", opts: []testcontainers.ContainerCustomizer{ mongodb.WithReplicaSet("rs"), }, }, { - name: "With Replica set and mongo:7", + name: "with-replica/mongo:7", img: "mongo:7", opts: []testcontainers.ContainerCustomizer{ mongodb.WithReplicaSet("rs"), }, }, + { + name: "with-auth/replica/mongo:7", + img: "mongo:7", + opts: []testcontainers.ContainerCustomizer{ + mongodb.WithReplicaSet("rs"), + mongodb.WithUsername("tester"), + mongodb.WithPassword("testerpass"), + }, + }, + { + name: "with-auth/replica/mongo:6", + img: "mongo:6", + opts: []testcontainers.ContainerCustomizer{ + mongodb.WithReplicaSet("rs"), + mongodb.WithUsername("tester"), + mongodb.WithPassword("testerpass"), + }, + }, + { + name: "with-auth/mongo:6", + img: "mongo:6", + opts: []testcontainers.ContainerCustomizer{ + mongodb.WithUsername("tester"), + mongodb.WithPassword("testerpass"), + }, + }, + { + name: "with-auth/replica/mongodb-enterprise-server:7.0.0-ubi8", + img: "mongodb/mongodb-enterprise-server:7.0.0-ubi8", + opts: []testcontainers.ContainerCustomizer{ + mongodb.WithReplicaSet("rs"), + mongodb.WithUsername("tester"), + mongodb.WithPassword("testerpass"), + }, + }, + { + name: "with-auth/replica/mongodb-community-server:7.0.2-ubi8", + img: "mongodb/mongodb-community-server:7.0.2-ubi8", + opts: []testcontainers.ContainerCustomizer{ + mongodb.WithReplicaSet("rs"), + mongodb.WithUsername("tester"), + mongodb.WithPassword("testerpass"), + }, + }, + { + name: "with-auth/replica/mongo:4", + img: "mongo:4", + opts: []testcontainers.ContainerCustomizer{ + mongodb.WithReplicaSet("rs"), + mongodb.WithUsername("tester"), + mongodb.WithPassword("testerpass"), + }, + }, } for _, tc := range testCases { diff --git a/modules/mongodb/mount/entrypoint-tc.sh b/modules/mongodb/mount/entrypoint-tc.sh new file mode 100644 index 0000000000..1561415aad --- /dev/null +++ b/modules/mongodb/mount/entrypoint-tc.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -Eeuo pipefail + +# detect mongo user and group +function get_user_group() { + user_group=$(cut -d: -f1,5 /etc/passwd | grep mongo) + echo "${user_group}" +} + +# detect the entrypoint +function get_entrypoint() { + entrypoint=$(find /usr/local/bin -name 'docker-entrypoint.*') + if [[ "${entrypoint}" == *.py ]]; then + entrypoint="python3 ${entrypoint}" + else + entrypoint="exec ${entrypoint}" + fi + echo "${entrypoint}" +} + +ENTRYPOINT=$(get_entrypoint) +MONGO_USER_GROUP=$(get_user_group) + +# Create the keyfile +openssl rand -base64 756 > "${MONGO_KEYFILE}" + +# Set the permissions and ownership of the keyfile +chown "${MONGO_USER_GROUP}" "${MONGO_KEYFILE}" +chmod 400 "${MONGO_KEYFILE}" + +${ENTRYPOINT} "$@" From 032a69fc28557cefebf3040ffcf947e9ef5b64f8 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 28 Oct 2024 11:36:34 +0000 Subject: [PATCH 102/126] fix!: data races (#2843) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci: enable test race checks Enable race checks for all tests in CI. * fix!: data various data races Fix data race when determining default network, this required making DockerProviderOptions.DefaultNetwork field private which is a breaking change. Fix data race in test bufLogger. Fix data races on log production context cancellation and context timeout not being cancelled in read loop. BREAKING_CHANGE! --------- Co-authored-by: Manuel de la Peña --- commons-test.mk | 3 +- docker.go | 179 ++++++++++++++++++++++++++---------------------- docker_test.go | 11 +-- network.go | 4 +- provider.go | 2 +- reaper.go | 7 +- 6 files changed, 115 insertions(+), 91 deletions(-) diff --git a/commons-test.mk b/commons-test.mk index d168ff5c65..91ed6a1244 100644 --- a/commons-test.mk +++ b/commons-test.mk @@ -47,7 +47,8 @@ test-%: $(GOBIN)/gotestsum -- \ -v \ -coverprofile=coverage.out \ - -timeout=30m + -timeout=30m \ + -race .PHONY: tools tools: diff --git a/docker.go b/docker.go index 2ef8c6973a..f82cd55381 100644 --- a/docker.go +++ b/docker.go @@ -16,6 +16,7 @@ import ( "path/filepath" "regexp" "strings" + "sync" "time" "github.com/cenkalti/backoff/v4" @@ -762,11 +763,15 @@ func (c *DockerContainer) startLogProduction(ctx context.Context, opts ...LogPro // Setup the log production context which will be used to stop the log production. c.logProductionCtx, c.logProductionCancel = context.WithCancelCause(ctx) - go func() { - err := c.logProducer(stdout, stderr) - // Set context cancel cause, if not already set. - c.logProductionCancel(err) - }() + // We capture context cancel function to avoid data race with multiple + // calls to startLogProduction. + go func(cancel context.CancelCauseFunc) { + // Ensure the context is cancelled when log productions completes + // so that GetLogProductionErrorChannel functions correctly. + defer cancel(nil) + + c.logProducer(stdout, stderr) + }(c.logProductionCancel) return nil } @@ -775,40 +780,49 @@ func (c *DockerContainer) startLogProduction(ctx context.Context, opts ...LogPro // - logProductionCtx is done // - A fatal error occurs // - No more logs are available -func (c *DockerContainer) logProducer(stdout, stderr io.Writer) error { +func (c *DockerContainer) logProducer(stdout, stderr io.Writer) { // Clean up idle client connections. defer c.provider.Close() // Setup the log options, start from the beginning. - options := container.LogsOptions{ + options := &container.LogsOptions{ ShowStdout: true, ShowStderr: true, Follow: true, } - for { - timeoutCtx, cancel := context.WithTimeout(c.logProductionCtx, *c.logProductionTimeout) - defer cancel() + // Use a separate method so that timeout cancel function is + // called correctly. + for c.copyLogsTimeout(stdout, stderr, options) { + } +} - err := c.copyLogs(timeoutCtx, stdout, stderr, options) - switch { - case err == nil: - // No more logs available. - return nil - case c.logProductionCtx.Err() != nil: - // Log production was stopped or caller context is done. - return nil - case timeoutCtx.Err() != nil, errors.Is(err, net.ErrClosed): - // Timeout or client connection closed, retry. - default: - // Unexpected error, retry. - Logger.Printf("Unexpected error reading logs: %v", err) - } +// copyLogsTimeout copies logs from the container to stdout and stderr with a timeout. +// It returns true if the log production should be retried, false otherwise. +func (c *DockerContainer) copyLogsTimeout(stdout, stderr io.Writer, options *container.LogsOptions) bool { + timeoutCtx, cancel := context.WithTimeout(c.logProductionCtx, *c.logProductionTimeout) + defer cancel() - // Retry from the last log received. - now := time.Now() - options.Since = fmt.Sprintf("%d.%09d", now.Unix(), int64(now.Nanosecond())) + err := c.copyLogs(timeoutCtx, stdout, stderr, *options) + switch { + case err == nil: + // No more logs available. + return false + case c.logProductionCtx.Err() != nil: + // Log production was stopped or caller context is done. + return false + case timeoutCtx.Err() != nil, errors.Is(err, net.ErrClosed): + // Timeout or client connection closed, retry. + default: + // Unexpected error, retry. + Logger.Printf("Unexpected error reading logs: %v", err) } + + // Retry from the last log received. + now := time.Now() + options.Since = fmt.Sprintf("%d.%09d", now.Unix(), int64(now.Nanosecond())) + + return true } // copyLogs copies logs from the container to stdout and stderr. @@ -866,10 +880,12 @@ func (c *DockerContainer) GetLogProductionErrorChannel() <-chan error { } errCh := make(chan error, 1) - go func() { - <-c.logProductionCtx.Done() - errCh <- context.Cause(c.logProductionCtx) - }() + go func(ctx context.Context) { + <-ctx.Done() + errCh <- context.Cause(ctx) + close(errCh) + }(c.logProductionCtx) + return errCh } @@ -906,6 +922,7 @@ type DockerProvider struct { host string hostCache string config config.Config + mtx sync.Mutex } // Client gets the docker client used by the provider @@ -984,29 +1001,26 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque // defer the close of the Docker client connection the soonest defer p.Close() - // Make sure that bridge network exists - // In case it is disabled we will create reaper_default network - if p.DefaultNetwork == "" { - p.DefaultNetwork, err = p.getDefaultNetwork(ctx, p.client) - if err != nil { - return nil, err - } + var defaultNetwork string + defaultNetwork, err = p.ensureDefaultNetwork(ctx) + if err != nil { + return nil, fmt.Errorf("ensure default network: %w", err) } // If default network is not bridge make sure it is attached to the request // as container won't be attached to it automatically // in case of Podman the bridge network is called 'podman' as 'bridge' would conflict - if p.DefaultNetwork != p.defaultBridgeNetworkName { + if defaultNetwork != p.defaultBridgeNetworkName { isAttached := false for _, net := range req.Networks { - if net == p.DefaultNetwork { + if net == defaultNetwork { isAttached = true break } } if !isAttached { - req.Networks = append(req.Networks, p.DefaultNetwork) + req.Networks = append(req.Networks, defaultNetwork) } } @@ -1461,12 +1475,8 @@ func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) // defer the close of the Docker client connection the soonest defer p.Close() - // Make sure that bridge network exists - // In case it is disabled we will create reaper_default network - if p.DefaultNetwork == "" { - if p.DefaultNetwork, err = p.getDefaultNetwork(ctx, p.client); err != nil { - return nil, err - } + if _, err = p.ensureDefaultNetwork(ctx); err != nil { + return nil, fmt.Errorf("ensure default network: %w", err) } if req.Labels == nil { @@ -1537,14 +1547,12 @@ func (p *DockerProvider) GetNetwork(ctx context.Context, req NetworkRequest) (ne 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 = p.getDefaultNetwork(ctx, p.client) - if err != nil { - return "", err - } + defaultNetwork, err := p.ensureDefaultNetwork(ctx) + if err != nil { + return "", fmt.Errorf("ensure default network: %w", err) } - nw, err := p.GetNetwork(ctx, NetworkRequest{Name: p.DefaultNetwork}) + + nw, err := p.GetNetwork(ctx, NetworkRequest{Name: defaultNetwork}) if err != nil { return "", err } @@ -1563,43 +1571,50 @@ func (p *DockerProvider) GetGatewayIP(ctx context.Context) (string, error) { return ip, nil } -func (p *DockerProvider) getDefaultNetwork(ctx context.Context, cli client.APIClient) (string, error) { - // Get list of available networks - networkResources, err := cli.NetworkList(ctx, network.ListOptions{}) - if err != nil { - return "", err - } +// ensureDefaultNetwork ensures that defaultNetwork is set and creates +// it if it does not exist, returning its value. +// It is safe to call this method concurrently. +func (p *DockerProvider) ensureDefaultNetwork(ctx context.Context) (string, error) { + p.mtx.Lock() + defer p.mtx.Unlock() - reaperNetwork := ReaperDefault + if p.defaultNetwork != "" { + // Already set. + return p.defaultNetwork, nil + } - reaperNetworkExists := false + networkResources, err := p.client.NetworkList(ctx, network.ListOptions{}) + if err != nil { + return "", fmt.Errorf("network list: %w", err) + } for _, net := range networkResources { - if net.Name == p.defaultBridgeNetworkName { - return p.defaultBridgeNetworkName, nil - } - - if net.Name == reaperNetwork { - reaperNetworkExists = true + switch net.Name { + case p.defaultBridgeNetworkName: + p.defaultNetwork = p.defaultBridgeNetworkName + return p.defaultNetwork, nil + case ReaperDefault: + p.defaultNetwork = ReaperDefault + return p.defaultNetwork, nil } } - // Create a bridge network for the container communications - if !reaperNetworkExists { - _, err = cli.NetworkCreate(ctx, reaperNetwork, network.CreateOptions{ - Driver: Bridge, - Attachable: true, - Labels: GenericLabels(), - }) - // If the network already exists, we can ignore the error as that can - // happen if we are running multiple tests in parallel and we only - // need to ensure that the network exists. - if err != nil && !errdefs.IsConflict(err) { - return "", err - } + // Create a bridge network for the container communications. + _, err = p.client.NetworkCreate(ctx, ReaperDefault, network.CreateOptions{ + Driver: Bridge, + Attachable: true, + Labels: GenericLabels(), + }) + // If the network already exists, we can ignore the error as that can + // happen if we are running multiple tests in parallel and we only + // need to ensure that the network exists. + if err != nil && !errdefs.IsConflict(err) { + return "", fmt.Errorf("network create: %w", err) } - return reaperNetwork, nil + p.defaultNetwork = ReaperDefault + + return p.defaultNetwork, nil } // containerFromDockerResponse builds a Docker container struct from the response of the Docker API diff --git a/docker_test.go b/docker_test.go index a9fcbd03d6..4be29f8fcd 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1790,11 +1790,14 @@ func TestGetGatewayIP(t *testing.T) { require.NoError(t, err) defer provider.Close() - ip, err := provider.(*DockerProvider).GetGatewayIP(context.Background()) - require.NoError(t, err) - if ip == "" { - t.Fatal("could not get gateway ip") + dockerProvider, ok := provider.(*DockerProvider) + if !ok { + t.Skip("provider is not a DockerProvider") } + + ip, err := dockerProvider.GetGatewayIP(context.Background()) + require.NoError(t, err) + require.NotEmpty(t, ip) } func TestNetworkModeWithContainerReference(t *testing.T) { diff --git a/network.go b/network.go index 9544bee129..5a145ac668 100644 --- a/network.go +++ b/network.go @@ -23,12 +23,12 @@ type DefaultNetwork string // Deprecated: will be removed in the future. func (n DefaultNetwork) ApplyGenericTo(opts *GenericProviderOptions) { - opts.DefaultNetwork = string(n) + opts.defaultNetwork = string(n) } // Deprecated: will be removed in the future. func (n DefaultNetwork) ApplyDockerTo(opts *DockerProviderOptions) { - opts.DefaultNetwork = string(n) + opts.defaultNetwork = string(n) } // Deprecated: will be removed in the future diff --git a/provider.go b/provider.go index b5e5ffa997..31714c0c14 100644 --- a/provider.go +++ b/provider.go @@ -25,7 +25,7 @@ type ( // GenericProviderOptions defines options applicable to all providers GenericProviderOptions struct { Logger Logging - DefaultNetwork string + defaultNetwork string } // GenericProviderOption defines a common interface to modify GenericProviderOptions diff --git a/reaper.go b/reaper.go index 8f2bde8ab6..650bfad0bd 100644 --- a/reaper.go +++ b/reaper.go @@ -402,7 +402,12 @@ func (r *reaperSpawner) newReaper(ctx context.Context, sessionID string, provide // Attach reaper container to a requested network if it is specified if p, ok := provider.(*DockerProvider); ok { - req.Networks = append(req.Networks, p.DefaultNetwork) + defaultNetwork, err := p.ensureDefaultNetwork(ctx) + if err != nil { + return nil, fmt.Errorf("ensure default network: %w", err) + } + + req.Networks = append(req.Networks, defaultNetwork) } c, err := provider.RunContainer(ctx, req) From 66f17a75956f3ef960a96837e3844b587422061c Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Mon, 28 Oct 2024 12:51:02 +0000 Subject: [PATCH 103/126] fix(compose): container initialisation (#2844) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix compose to fully initialise the containers it returns. This ensures that running things like checks for running behave as expected. Extracts the functionality to connect to reaper into a helper method so its consistent across uses. Fix data race in daemonHost function converting it to a method to make use of encapsulation. Fix container and network requests so they use sessionID from labels if available so that user specified values are respected. Export the functionality to create a container from a ContainerList response via provider.ContainerFromType. Enforce no bare returns instead of no named returns as that was the original intention. Fixes #2667 Co-authored-by: Manuel de la Peña --- .golangci.yml | 4 +- container.go | 9 ++ docker.go | 158 ++++++++++++++++------------ generic_test.go | 6 +- modules/compose/compose.go | 11 +- modules/compose/compose_api.go | 31 ++---- modules/compose/compose_api_test.go | 6 ++ network.go | 11 ++ reaper.go | 17 ++- 9 files changed, 154 insertions(+), 99 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 26f8f8a3c2..7c421f0be6 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -7,11 +7,13 @@ linters: - gofumpt - misspell - nolintlint - - nonamedreturns + - nakedret - testifylint - thelper linters-settings: + nakedret: + max-func-lines: 0 errorlint: # Check whether fmt.Errorf uses the %w verb for formatting errors. # See the https://github.com/polyfloyd/go-errorlint for caveats. diff --git a/container.go b/container.go index d114a5988a..c0ae935f07 100644 --- a/container.go +++ b/container.go @@ -167,6 +167,15 @@ type ContainerRequest struct { LogConsumerCfg *LogConsumerConfig // define the configuration for the log producer and its log consumers to follow the logs } +// sessionID returns the session ID for the container request. +func (c *ContainerRequest) sessionID() string { + if sessionID := c.Labels[core.LabelSessionID]; sessionID != "" { + return sessionID + } + + return core.SessionID() +} + // containerOptions functional options for a container type containerOptions struct { ImageName string diff --git a/docker.go b/docker.go index f82cd55381..66ac42eda6 100644 --- a/docker.go +++ b/docker.go @@ -15,7 +15,6 @@ import ( "os" "path/filepath" "regexp" - "strings" "sync" "time" @@ -889,6 +888,32 @@ func (c *DockerContainer) GetLogProductionErrorChannel() <-chan error { return errCh } +// connectReaper connects the reaper to the container if it is needed. +func (c *DockerContainer) connectReaper(ctx context.Context) error { + if c.provider.config.RyukDisabled || isReaperImage(c.Image) { + // Reaper is disabled or we are the reaper container. + return nil + } + + reaper, err := spawner.reaper(context.WithValue(ctx, core.DockerHostContextKey, c.provider.host), core.SessionID(), c.provider) + if err != nil { + return fmt.Errorf("reaper: %w", err) + } + + if c.terminationSignal, err = reaper.Connect(); err != nil { + return fmt.Errorf("reaper connect: %w", err) + } + + return nil +} + +// cleanupTermSignal triggers the termination signal if it was created and an error occurred. +func (c *DockerContainer) cleanupTermSignal(err error) { + if c.terminationSignal != nil && err != nil { + c.terminationSignal <- true + } +} + // DockerNetwork represents a network started using Docker type DockerNetwork struct { ID string // Network ID from Docker @@ -1035,28 +1060,6 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque req.Labels = make(map[string]string) } - var termSignal chan bool - // the reaper does not need to start a reaper for itself - isReaperContainer := strings.HasSuffix(imageName, config.ReaperDefaultImage) - if !p.config.RyukDisabled && !isReaperContainer { - r, err := spawner.reaper(context.WithValue(ctx, core.DockerHostContextKey, p.host), core.SessionID(), p) - if err != nil { - return nil, fmt.Errorf("reaper: %w", err) - } - - termSignal, err := r.Connect() - if err != nil { - return nil, fmt.Errorf("reaper connect: %w", err) - } - - // Cleanup on error. - defer func() { - if err != nil { - termSignal <- true - } - }() - } - if err = req.Validate(); err != nil { return nil, err } @@ -1120,7 +1123,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque } } - if !isReaperContainer { + if !isReaperImage(imageName) { // Add the labels that identify this as a testcontainers container and // allow the reaper to terminate it if requested. AddGenericLabels(req.Labels) @@ -1198,26 +1201,35 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque } } - c := &DockerContainer{ - ID: resp.ID, - WaitingFor: req.WaitingFor, - Image: imageName, - imageWasBuilt: req.ShouldBuildImage(), - keepBuiltImage: req.ShouldKeepBuiltImage(), - sessionID: core.SessionID(), - exposedPorts: req.ExposedPorts, - provider: p, - terminationSignal: termSignal, - logger: p.Logger, - lifecycleHooks: req.LifecycleHooks, + // This should match the fields set in ContainerFromDockerResponse. + ctr := &DockerContainer{ + ID: resp.ID, + WaitingFor: req.WaitingFor, + Image: imageName, + imageWasBuilt: req.ShouldBuildImage(), + keepBuiltImage: req.ShouldKeepBuiltImage(), + sessionID: req.sessionID(), + exposedPorts: req.ExposedPorts, + provider: p, + logger: p.Logger, + lifecycleHooks: req.LifecycleHooks, } - err = c.createdHook(ctx) - if err != nil { - return nil, err + if err = ctr.connectReaper(ctx); err != nil { + return ctr, err // No wrap as it would stutter. } - return c, nil + // Wrapped so the returned error is passed to the cleanup function. + defer func(ctr *DockerContainer) { + ctr.cleanupTermSignal(err) + }(ctr) + + if err = ctr.createdHook(ctx); err != nil { + // Return the container to allow caller to clean up. + return ctr, fmt.Errorf("created hook: %w", err) + } + + return ctr, nil } func (p *DockerProvider) findContainerByName(ctx context.Context, name string) (*types.Container, error) { @@ -1229,7 +1241,7 @@ func (p *DockerProvider) findContainerByName(ctx context.Context, name string) ( filter := filters.NewArgs(filters.Arg("name", fmt.Sprintf("^%s$", name))) containers, err := p.client.ContainerList(ctx, container.ListOptions{Filters: filter}) if err != nil { - return nil, err + return nil, fmt.Errorf("container list: %w", err) } defer p.Close() @@ -1284,7 +1296,7 @@ func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req Contain } } - sessionID := core.SessionID() + sessionID := req.sessionID() var termSignal chan bool if !p.config.RyukDisabled { @@ -1425,10 +1437,13 @@ func (p *DockerProvider) Config() TestcontainersConfig { // Warning: this is based on your Docker host setting. Will fail if using an SSH tunnel // You can use the "TESTCONTAINERS_HOST_OVERRIDE" env variable to set this yourself func (p *DockerProvider) DaemonHost(ctx context.Context) (string, error) { - return daemonHost(ctx, p) + p.mtx.Lock() + defer p.mtx.Unlock() + + return p.daemonHostLocked(ctx) } -func daemonHost(ctx context.Context, p *DockerProvider) (string, error) { +func (p *DockerProvider) daemonHostLocked(ctx context.Context) (string, error) { if p.hostCache != "" { return p.hostCache, nil } @@ -1492,7 +1507,7 @@ func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) IPAM: req.IPAM, } - sessionID := core.SessionID() + sessionID := req.sessionID() var termSignal chan bool if !p.config.RyukDisabled { @@ -1617,37 +1632,42 @@ func (p *DockerProvider) ensureDefaultNetwork(ctx context.Context) (string, erro return p.defaultNetwork, nil } -// containerFromDockerResponse builds a Docker container struct from the response of the Docker API -func containerFromDockerResponse(ctx context.Context, response types.Container) (*DockerContainer, error) { - provider, err := NewDockerProvider() - if err != nil { - return nil, err +// ContainerFromType builds a Docker container struct from the response of the Docker API +func (p *DockerProvider) ContainerFromType(ctx context.Context, response types.Container) (ctr *DockerContainer, err error) { + exposedPorts := make([]string, len(response.Ports)) + for i, port := range response.Ports { + exposedPorts[i] = fmt.Sprintf("%d/%s", port.PublicPort, port.Type) + } + + // This should match the fields set in CreateContainer. + ctr = &DockerContainer{ + ID: response.ID, + Image: response.Image, + imageWasBuilt: false, + sessionID: response.Labels[core.LabelSessionID], + isRunning: response.State == "running", + exposedPorts: exposedPorts, + provider: p, + logger: p.Logger, + lifecycleHooks: []ContainerLifecycleHooks{ + DefaultLoggingHook(p.Logger), + }, } - ctr := DockerContainer{} - - ctr.ID = response.ID - ctr.WaitingFor = nil - ctr.Image = response.Image - ctr.imageWasBuilt = false - - ctr.logger = provider.Logger - ctr.lifecycleHooks = []ContainerLifecycleHooks{ - DefaultLoggingHook(ctr.logger), + if err = ctr.connectReaper(ctx); err != nil { + return nil, err } - ctr.provider = provider - - ctr.sessionID = core.SessionID() - ctr.consumers = []LogConsumer{} - ctr.isRunning = response.State == "running" - // the termination signal should be obtained from the reaper - ctr.terminationSignal = nil + // Wrapped so the returned error is passed to the cleanup function. + defer func(ctr *DockerContainer) { + ctr.cleanupTermSignal(err) + }(ctr) // populate the raw representation of the container jsonRaw, err := ctr.inspectRawContainer(ctx) if err != nil { - return nil, fmt.Errorf("inspect raw container: %w", err) + // Return the container to allow caller to clean up. + return ctr, fmt.Errorf("inspect raw container: %w", err) } // the health status of the container, if any @@ -1655,7 +1675,7 @@ func containerFromDockerResponse(ctx context.Context, response types.Container) ctr.healthStatus = health.Status } - return &ctr, nil + return ctr, nil } // ListImages list images from the provider. If an image has multiple Tags, each tag is reported diff --git a/generic_test.go b/generic_test.go index 250a9aaab2..7c0de2a246 100644 --- a/generic_test.go +++ b/generic_test.go @@ -156,10 +156,14 @@ func TestGenericReusableContainerInSubprocess(t *testing.T) { require.NoError(t, err) require.Len(t, ctrs, 1) - nginxC, err := containerFromDockerResponse(context.Background(), ctrs[0]) + provider, err := NewDockerProvider() require.NoError(t, err) + provider.SetClient(cli) + + nginxC, err := provider.ContainerFromType(context.Background(), ctrs[0]) CleanupContainer(t, nginxC) + require.NoError(t, err) } func createReuseContainerInSubprocess(t *testing.T) string { diff --git a/modules/compose/compose.go b/modules/compose/compose.go index fa02cde077..be829f4575 100644 --- a/modules/compose/compose.go +++ b/modules/compose/compose.go @@ -153,6 +153,14 @@ func NewDockerComposeWith(opts ...ComposeStackOption) (*dockerCompose, error) { return nil, fmt.Errorf("initialize docker client: %w", err) } + provider, err := testcontainers.NewDockerProvider(testcontainers.WithLogger(composeOptions.Logger)) + if err != nil { + return nil, fmt.Errorf("new docker provider: %w", err) + } + + dockerClient := dockerCli.Client() + provider.SetClient(dockerClient) + composeAPI := &dockerCompose{ name: composeOptions.Identifier, configs: composeOptions.Paths, @@ -160,11 +168,12 @@ func NewDockerComposeWith(opts ...ComposeStackOption) (*dockerCompose, error) { logger: composeOptions.Logger, projectProfiles: composeOptions.Profiles, composeService: compose.NewComposeService(dockerCli), - dockerClient: dockerCli.Client(), + dockerClient: dockerClient, waitStrategies: make(map[string]wait.Strategy), containers: make(map[string]*testcontainers.DockerContainer), networks: make(map[string]*testcontainers.DockerNetwork), sessionID: testcontainers.SessionID(), + provider: provider, } return composeAPI, nil diff --git a/modules/compose/compose_api.go b/modules/compose/compose_api.go index c84f1af6ce..45dd72c6e0 100644 --- a/modules/compose/compose_api.go +++ b/modules/compose/compose_api.go @@ -229,6 +229,9 @@ type dockerCompose struct { // sessionID is used to identify the reaper session sessionID string + + // provider is used to docker operations. + provider *testcontainers.DockerProvider } func (d *dockerCompose) ServiceContainer(ctx context.Context, svcName string) (*testcontainers.DockerContainer, error) { @@ -325,17 +328,12 @@ func (d *dockerCompose) Up(ctx context.Context, opts ...StackUpOption) (err erro return err } - provider, err := testcontainers.NewDockerProvider(testcontainers.WithLogger(d.logger)) - if err != nil { - return fmt.Errorf("new docker provider: %w", err) - } - var termSignals []chan bool var reaper *testcontainers.Reaper - if !provider.Config().Config.RyukDisabled { + if !d.provider.Config().Config.RyukDisabled { // NewReaper is deprecated: we need to find a way to create the reaper for compose // bypassing the deprecation. - reaper, err = testcontainers.NewReaper(ctx, testcontainers.SessionID(), provider, "") + reaper, err = testcontainers.NewReaper(ctx, testcontainers.SessionID(), d.provider, "") if err != nil { return fmt.Errorf("create reaper: %w", err) } @@ -492,26 +490,11 @@ func (d *dockerCompose) lookupContainer(ctx context.Context, svcName string) (*t return nil, fmt.Errorf("no container found for service name %s", svcName) } - containerInstance := containers[0] - // TODO: Fix as this is only setting a subset of the fields - // and the container is not fully initialized, for example - // the isRunning flag is not set. - // See: https://github.com/testcontainers/testcontainers-go/issues/2667 - ctr := &testcontainers.DockerContainer{ - ID: containerInstance.ID, - Image: containerInstance.Image, - } - ctr.SetLogger(d.logger) - - dockerProvider, err := testcontainers.NewDockerProvider(testcontainers.WithLogger(d.logger)) + ctr, err := d.provider.ContainerFromType(ctx, containers[0]) if err != nil { - return nil, fmt.Errorf("new docker provider: %w", err) + return nil, fmt.Errorf("container from type: %w", err) } - dockerProvider.SetClient(d.dockerClient) - - ctr.SetProvider(dockerProvider) - d.containersLock.Lock() defer d.containersLock.Unlock() d.containers[svcName] = ctr diff --git a/modules/compose/compose_api_test.go b/modules/compose/compose_api_test.go index e13c6ca937..310057ff49 100644 --- a/modules/compose/compose_api_test.go +++ b/modules/compose/compose_api_test.go @@ -33,6 +33,12 @@ func TestDockerComposeAPI(t *testing.T) { err = compose.Up(ctx, Wait(true)) cleanup(t, compose) require.NoError(t, err, "compose.Up()") + + for _, service := range compose.Services() { + container, err := compose.ServiceContainer(context.Background(), service) + require.NoError(t, err, "compose.ServiceContainer()") + require.True(t, container.IsRunning()) + } } func TestDockerComposeAPIStrategyForInvalidService(t *testing.T) { diff --git a/network.go b/network.go index 5a145ac668..e0cc83f510 100644 --- a/network.go +++ b/network.go @@ -4,6 +4,8 @@ import ( "context" "github.com/docker/docker/api/types/network" + + "github.com/testcontainers/testcontainers-go/internal/core" ) // NetworkProvider allows the creation of networks on an arbitrary system @@ -47,3 +49,12 @@ type NetworkRequest struct { ReaperImage string // Deprecated: use WithImageName ContainerOption instead. Alternative reaper registry ReaperOptions []ContainerOption // Deprecated: the reaper is configured at the properties level, for an entire test session } + +// sessionID returns the session ID for the network request. +func (r NetworkRequest) sessionID() string { + if sessionID := r.Labels[core.LabelSessionID]; sessionID != "" { + return sessionID + } + + return core.SessionID() +} diff --git a/reaper.go b/reaper.go index 650bfad0bd..dfdcea5c5f 100644 --- a/reaper.go +++ b/reaper.go @@ -161,6 +161,13 @@ func (r *reaperSpawner) lookupContainer(ctx context.Context, sessionID string) ( } defer dockerClient.Close() + provider, err := NewDockerProvider() + if err != nil { + return nil, fmt.Errorf("new provider: %w", err) + } + + provider.SetClient(dockerClient) + opts := container.ListOptions{ All: true, Filters: filters.NewArgs( @@ -184,11 +191,10 @@ func (r *reaperSpawner) lookupContainer(ctx context.Context, sessionID string) ( } if len(resp) > 1 { - return nil, fmt.Errorf("multiple reaper containers found for session ID %s", sessionID) + return nil, fmt.Errorf("found %d reaper containers for session ID %q", len(resp), sessionID) } - container := resp[0] - r, err := containerFromDockerResponse(ctx, container) + r, err := provider.ContainerFromType(ctx, resp[0]) if err != nil { return nil, fmt.Errorf("from docker: %w", err) } @@ -566,3 +572,8 @@ func (r *Reaper) handshake(conn net.Conn) error { func (r *Reaper) Labels() map[string]string { return GenericLabels() } + +// isReaperImage returns true if the image name is the reaper image. +func isReaperImage(name string) bool { + return strings.HasSuffix(name, config.ReaperDefaultImage) +} From 9ed332a5b0d6e0e349a3afa08e52c5a47579c6c8 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Mon, 28 Oct 2024 14:12:23 +0100 Subject: [PATCH 104/126] chore: enable usestdlibvars linter (#2850) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matthieu MOREL Co-authored-by: Manuel de la Peña Co-authored-by: Steven Hartland --- .golangci.yml | 1 + modules/elasticsearch/elasticsearch_test.go | 4 ++-- modules/ollama/examples_test.go | 2 +- modules/opensearch/opensearch_test.go | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 7c421f0be6..b8391990ac 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -10,6 +10,7 @@ linters: - nakedret - testifylint - thelper + - usestdlibvars linters-settings: nakedret: diff --git a/modules/elasticsearch/elasticsearch_test.go b/modules/elasticsearch/elasticsearch_test.go index fdfe636769..99829e94d3 100644 --- a/modules/elasticsearch/elasticsearch_test.go +++ b/modules/elasticsearch/elasticsearch_test.go @@ -87,7 +87,7 @@ func TestElasticsearch(t *testing.T) { httpClient := configureHTTPClient(esContainer) - req, err := http.NewRequest("GET", esContainer.Settings.Address, nil) + req, err := http.NewRequest(http.MethodGet, esContainer.Settings.Address, nil) require.NoError(t, err) // set the password for the request using the Authentication header @@ -201,7 +201,7 @@ func TestElasticsearch8WithoutCredentials(t *testing.T) { httpClient := configureHTTPClient(ctr) - req, err := http.NewRequest("GET", ctr.Settings.Address, nil) + req, err := http.NewRequest(http.MethodGet, ctr.Settings.Address, nil) require.NoError(t, err) // elastic:changeme are the default credentials for Elasticsearch 8 diff --git a/modules/ollama/examples_test.go b/modules/ollama/examples_test.go index 46d65ebe0a..e9ac3ce0fa 100644 --- a/modules/ollama/examples_test.go +++ b/modules/ollama/examples_test.go @@ -85,7 +85,7 @@ func ExampleRun_withModel_llama2_http() { "prompt":"Why is the sky blue?" }` - req, err := http.NewRequest("POST", fmt.Sprintf("%s/api/generate", connectionStr), strings.NewReader(payload)) + req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/generate", connectionStr), strings.NewReader(payload)) if err != nil { log.Printf("failed to create request: %s", err) return diff --git a/modules/opensearch/opensearch_test.go b/modules/opensearch/opensearch_test.go index 3829ea2dfb..15304dbfd6 100644 --- a/modules/opensearch/opensearch_test.go +++ b/modules/opensearch/opensearch_test.go @@ -24,7 +24,7 @@ func TestOpenSearch(t *testing.T) { client := &http.Client{} - req, err := http.NewRequest("GET", address, nil) + req, err := http.NewRequest(http.MethodGet, address, nil) require.NoError(t, err) resp, err := client.Do(req) From 2cec4a1a76724a031360f03afefbb70a5e5c4bfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Tue, 29 Oct 2024 01:41:04 +0100 Subject: [PATCH 105/126] chore: bump ryuk to 0.11.0 (#2853) * chore: bump ryuk * chore: use new ryuk variables, with a deprecation path --- docs/features/configuration.md | 12 +++++++++--- internal/config/config.go | 29 ++++++++++++++++++++++------- internal/config/config_test.go | 32 ++++++++++++++++---------------- 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/docs/features/configuration.md b/docs/features/configuration.md index ee5b6a4d69..8da214e977 100644 --- a/docs/features/configuration.md +++ b/docs/features/configuration.md @@ -50,9 +50,9 @@ Please read more about customizing images in the [Image name substitution](image 1. If your environment already implements automatic cleanup of containers after the execution, but does not allow starting privileged containers, you can turn off the Ryuk container by setting `TESTCONTAINERS_RYUK_DISABLED` **environment variable** , or the `ryuk.disabled` **property** to `true`. -1. You can specify the connection timeout for Ryuk by setting the `TESTCONTAINERS_RYUK_CONNECTION_TIMEOUT` **environment variable**, or the `ryuk.connection.timeout` **property**. The default value is 1 minute. -1. You can specify the reconnection timeout for Ryuk by setting the `TESTCONTAINERS_RYUK_RECONNECTION_TIMEOUT` **environment variable**, or the `ryuk.reconnection.timeout` **property**. The default value is 10 seconds. -1. You can configure Ryuk to run in verbose mode by setting any of the `ryuk.verbose` **property** or the `TESTCONTAINERS_RYUK_VERBOSE` **environment variable**. The default value is `false`. +1. You can specify the connection timeout for Ryuk by setting the `RYUK_CONNECTION_TIMEOUT` **environment variable**, or the `ryuk.connection.timeout` **property**. The default value is 1 minute. +1. You can specify the reconnection timeout for Ryuk by setting the `RYUK_RECONNECTION_TIMEOUT` **environment variable**, or the `ryuk.reconnection.timeout` **property**. The default value is 10 seconds. +1. You can configure Ryuk to run in verbose mode by setting any of the `ryuk.verbose` **property** or the `RYUK_VERBOSE` **environment variable**. The default value is `false`. !!!info For more information about Ryuk, see [Garbage Collector](garbage_collector.md). @@ -62,6 +62,12 @@ but does not allow starting privileged containers, you can turn off the Ryuk con This is because the Compose module may take longer to start all the services. Besides, the `ryuk.reconnection.timeout` should be increased to at least 30 seconds. For further information, please check [https://github.com/testcontainers/testcontainers-go/pull/2485](https://github.com/testcontainers/testcontainers-go/pull/2485). +!!!warn + The following environment variables for configuring Ryuk have been deprecated: + `TESTCONTAINERS_RYUK_CONNECTION_TIMEOUT`, `TESTCONTAINERS_RYUK_RECONNECTION_TIMEOUT` and + `TESTCONTAINERS_RYUK_VERBOSE` have been replaced by `RYUK_CONNECTION_TIMEOUT` + `RYUK_RECONNECTION_TIMEOUT` and `RYUK_VERBOSE` respectively. + ## Docker host detection _Testcontainers for Go_ will attempt to detect the Docker environment and configure everything to work automatically. diff --git a/internal/config/config.go b/internal/config/config.go index b0bcc24d3b..85be6acd86 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -11,7 +11,7 @@ import ( "github.com/magiconair/properties" ) -const ReaperDefaultImage = "testcontainers/ryuk:0.10.2" +const ReaperDefaultImage = "testcontainers/ryuk:0.11.0" var ( tcConfig Config @@ -68,17 +68,17 @@ type Config struct { // RyukReconnectionTimeout is the time to wait before attempting to reconnect to the Garbage Collector container. // - // Environment variable: TESTCONTAINERS_RYUK_RECONNECTION_TIMEOUT + // Environment variable: RYUK_RECONNECTION_TIMEOUT RyukReconnectionTimeout time.Duration `properties:"ryuk.reconnection.timeout,default=10s"` // RyukConnectionTimeout is the time to wait before timing out when connecting to the Garbage Collector container. // - // Environment variable: TESTCONTAINERS_RYUK_CONNECTION_TIMEOUT + // Environment variable: RYUK_CONNECTION_TIMEOUT RyukConnectionTimeout time.Duration `properties:"ryuk.connection.timeout,default=1m"` // RyukVerbose is a flag to enable or disable verbose logging for the Garbage Collector. // - // Environment variable: TESTCONTAINERS_RYUK_VERBOSE + // Environment variable: RYUK_VERBOSE RyukVerbose bool `properties:"ryuk.verbose,default=false"` // TestcontainersHost is the address of the Testcontainers host. @@ -126,17 +126,17 @@ func read() Config { config.RyukPrivileged = ryukPrivilegedEnv == "true" } - ryukVerboseEnv := os.Getenv("TESTCONTAINERS_RYUK_VERBOSE") + ryukVerboseEnv := readTestcontainersEnv("RYUK_VERBOSE") if parseBool(ryukVerboseEnv) { config.RyukVerbose = ryukVerboseEnv == "true" } - ryukReconnectionTimeoutEnv := os.Getenv("TESTCONTAINERS_RYUK_RECONNECTION_TIMEOUT") + ryukReconnectionTimeoutEnv := readTestcontainersEnv("RYUK_RECONNECTION_TIMEOUT") if timeout, err := time.ParseDuration(ryukReconnectionTimeoutEnv); err == nil { config.RyukReconnectionTimeout = timeout } - ryukConnectionTimeoutEnv := os.Getenv("TESTCONTAINERS_RYUK_CONNECTION_TIMEOUT") + ryukConnectionTimeoutEnv := readTestcontainersEnv("RYUK_CONNECTION_TIMEOUT") if timeout, err := time.ParseDuration(ryukConnectionTimeoutEnv); err == nil { config.RyukConnectionTimeout = timeout } @@ -168,3 +168,18 @@ func parseBool(input string) bool { _, err := strconv.ParseBool(input) return err == nil } + +// readTestcontainersEnv reads the environment variable with the given name. +// It checks for the environment variable with the given name first, and then +// checks for the environment variable with the given name prefixed with "TESTCONTAINERS_". +func readTestcontainersEnv(envVar string) string { + value := os.Getenv(envVar) + if value != "" { + return value + } + + // TODO: remove this prefix after the next major release + const prefix string = "TESTCONTAINERS_" + + return os.Getenv(prefix + envVar) +} diff --git a/internal/config/config_test.go b/internal/config/config_test.go index c5b48244bd..f1c7d3bbf3 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -23,9 +23,9 @@ func resetTestEnv(t *testing.T) { t.Setenv("TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX", "") t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "") t.Setenv("TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED", "") - t.Setenv("TESTCONTAINERS_RYUK_VERBOSE", "") - t.Setenv("TESTCONTAINERS_RYUK_RECONNECTION_TIMEOUT", "") - t.Setenv("TESTCONTAINERS_RYUK_CONNECTION_TIMEOUT", "") + t.Setenv("RYUK_VERBOSE", "") + t.Setenv("RYUK_RECONNECTION_TIMEOUT", "") + t.Setenv("RYUK_CONNECTION_TIMEOUT", "") } func TestReadConfig(t *testing.T) { @@ -77,8 +77,8 @@ func TestReadTCConfig(t *testing.T) { t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true") t.Setenv("TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX", defaultHubPrefix) t.Setenv("TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED", "true") - t.Setenv("TESTCONTAINERS_RYUK_RECONNECTION_TIMEOUT", "13s") - t.Setenv("TESTCONTAINERS_RYUK_CONNECTION_TIMEOUT", "12s") + t.Setenv("RYUK_RECONNECTION_TIMEOUT", "13s") + t.Setenv("RYUK_CONNECTION_TIMEOUT", "12s") config := read() @@ -125,9 +125,9 @@ func TestReadTCConfig(t *testing.T) { t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true") t.Setenv("TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX", defaultHubPrefix) t.Setenv("TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED", "true") - t.Setenv("TESTCONTAINERS_RYUK_VERBOSE", "true") - t.Setenv("TESTCONTAINERS_RYUK_RECONNECTION_TIMEOUT", "13s") - t.Setenv("TESTCONTAINERS_RYUK_CONNECTION_TIMEOUT", "12s") + t.Setenv("RYUK_VERBOSE", "true") + t.Setenv("RYUK_RECONNECTION_TIMEOUT", "13s") + t.Setenv("RYUK_CONNECTION_TIMEOUT", "12s") config := read() expected := Config{ @@ -278,8 +278,8 @@ func TestReadTCConfig(t *testing.T) { "With Ryuk container timeouts configured using env vars", ``, map[string]string{ - "TESTCONTAINERS_RYUK_RECONNECTION_TIMEOUT": "13s", - "TESTCONTAINERS_RYUK_CONNECTION_TIMEOUT": "12s", + "RYUK_RECONNECTION_TIMEOUT": "13s", + "RYUK_CONNECTION_TIMEOUT": "12s", }, Config{ RyukReconnectionTimeout: 13 * time.Second, @@ -291,8 +291,8 @@ func TestReadTCConfig(t *testing.T) { `ryuk.connection.timeout=22s ryuk.reconnection.timeout=23s`, map[string]string{ - "TESTCONTAINERS_RYUK_RECONNECTION_TIMEOUT": "13s", - "TESTCONTAINERS_RYUK_CONNECTION_TIMEOUT": "12s", + "RYUK_RECONNECTION_TIMEOUT": "13s", + "RYUK_CONNECTION_TIMEOUT": "12s", }, Config{ RyukReconnectionTimeout: 13 * time.Second, @@ -377,7 +377,7 @@ func TestReadTCConfig(t *testing.T) { "With Ryuk verbose using an env var and properties. Env var wins (0)", `ryuk.verbose=true`, map[string]string{ - "TESTCONTAINERS_RYUK_VERBOSE": "true", + "RYUK_VERBOSE": "true", }, Config{ RyukVerbose: true, @@ -389,7 +389,7 @@ func TestReadTCConfig(t *testing.T) { "With Ryuk verbose using an env var and properties. Env var wins (1)", `ryuk.verbose=false`, map[string]string{ - "TESTCONTAINERS_RYUK_VERBOSE": "true", + "RYUK_VERBOSE": "true", }, Config{ RyukVerbose: true, @@ -401,7 +401,7 @@ func TestReadTCConfig(t *testing.T) { "With Ryuk verbose using an env var and properties. Env var wins (2)", `ryuk.verbose=true`, map[string]string{ - "TESTCONTAINERS_RYUK_VERBOSE": "false", + "RYUK_VERBOSE": "false", }, defaultConfig, }, @@ -409,7 +409,7 @@ func TestReadTCConfig(t *testing.T) { "With Ryuk verbose using an env var and properties. Env var wins (3)", `ryuk.verbose=false`, map[string]string{ - "TESTCONTAINERS_RYUK_VERBOSE": "false", + "RYUK_VERBOSE": "false", }, defaultConfig, }, From 950d06bf2fd5e45574a84a7151d66456b1f727b3 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Tue, 29 Oct 2024 10:00:53 +0100 Subject: [PATCH 106/126] chore: use require.Len instead of assert.Len (#2854) Signed-off-by: Matthieu MOREL --- lifecycle_test.go | 2 +- modulegen/main_test.go | 2 +- modulegen/mkdocs_test.go | 2 +- modules/compose/compose_api_test.go | 24 ++++++++++++------------ modules/compose/compose_test.go | 24 ++++++++++++------------ modules/localstack/v1/s3_test.go | 4 ++-- modules/localstack/v2/s3_test.go | 4 ++-- options_test.go | 2 +- 8 files changed, 32 insertions(+), 32 deletions(-) diff --git a/lifecycle_test.go b/lifecycle_test.go index 374d45bf80..c683a4146c 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -781,7 +781,7 @@ func TestCombineLifecycleHooks(t *testing.T) { // There are 5 lifecycles (create, start, ready, stop, terminate), // but ready has only half of the hooks (it only has post), so we have 90 hooks in total. - assert.Len(t, prints, 90) + require.Len(t, prints, 90) // The order of the hooks is: // - pre-X hooks: first default (2*2), then user-defined (3*2) diff --git a/modulegen/main_test.go b/modulegen/main_test.go index bbad5a5abb..d90c0da5be 100644 --- a/modulegen/main_test.go +++ b/modulegen/main_test.go @@ -494,7 +494,7 @@ func assertMkdocsNavItems(t *testing.T, module context.TestcontainersModule, ori expectedEntries = originalConfig.Nav[3].Modules } - assert.Len(t, navItems, len(expectedEntries)+1) + require.Len(t, navItems, len(expectedEntries)+1) // the module should be in the nav found := false diff --git a/modulegen/mkdocs_test.go b/modulegen/mkdocs_test.go index 305eeca1e4..96391769de 100644 --- a/modulegen/mkdocs_test.go +++ b/modulegen/mkdocs_test.go @@ -64,7 +64,7 @@ func TestNavItems(t *testing.T) { require.NoError(t, err) // we have to remove the index.md file from the examples docs - assert.Len(t, examples, len(examplesDocs)-1) + require.Len(t, examples, len(examplesDocs)-1) // all example modules exist in the documentation for _, example := range examples { diff --git a/modules/compose/compose_api_test.go b/modules/compose/compose_api_test.go index 310057ff49..e3f080fcca 100644 --- a/modules/compose/compose_api_test.go +++ b/modules/compose/compose_api_test.go @@ -58,7 +58,7 @@ func TestDockerComposeAPIStrategyForInvalidService(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 1) + require.Len(t, serviceNames, 1) assert.Contains(t, serviceNames, "api-nginx") } @@ -102,7 +102,7 @@ func TestDockerComposeAPIWithRunServices(t *testing.T) { _, err = compose.ServiceContainer(context.Background(), "api-mysql") require.Error(t, err, "Make sure there is no mysql container") - assert.Len(t, serviceNames, 1) + require.Len(t, serviceNames, 1) assert.Contains(t, serviceNames, "api-nginx") } @@ -304,7 +304,7 @@ func TestDockerComposeAPIWithWaitForService(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 1) + require.Len(t, serviceNames, 1) assert.Contains(t, serviceNames, "api-nginx") } @@ -327,7 +327,7 @@ func TestDockerComposeAPIWithWaitHTTPStrategy(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 1) + require.Len(t, serviceNames, 1) assert.Contains(t, serviceNames, "api-nginx") } @@ -350,7 +350,7 @@ func TestDockerComposeAPIWithContainerName(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 1) + require.Len(t, serviceNames, 1) assert.Contains(t, serviceNames, "api-nginx") } @@ -370,7 +370,7 @@ func TestDockerComposeAPIWithWaitStrategy_NoExposedPorts(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 1) + require.Len(t, serviceNames, 1) assert.Contains(t, serviceNames, "api-nginx") } @@ -417,7 +417,7 @@ func TestDockerComposeAPIWithFailedStrategy(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 1) + require.Len(t, serviceNames, 1) assert.Contains(t, serviceNames, "api-nginx") } @@ -469,7 +469,7 @@ services: serviceNames := compose.Services() - assert.Len(t, serviceNames, 1) + require.Len(t, serviceNames, 1) assert.Contains(t, serviceNames, "api-nginx") require.NoError(t, compose.Down(context.Background(), RemoveOrphans(true), RemoveVolumes(true), RemoveImagesLocal), "compose.Down()") @@ -513,7 +513,7 @@ services: serviceNames := compose.Services() - assert.Len(t, serviceNames, 2) + require.Len(t, serviceNames, 2) assert.Contains(t, serviceNames, "api-nginx") assert.Contains(t, serviceNames, "api-postgres") @@ -546,7 +546,7 @@ func TestDockerComposeAPIWithEnvironment(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 1) + require.Len(t, serviceNames, 1) assert.Contains(t, serviceNames, "api-nginx") present := map[string]string{ @@ -583,7 +583,7 @@ func TestDockerComposeAPIWithMultipleComposeFiles(t *testing.T) { serviceNames := compose.Services() - assert.Len(t, serviceNames, 3) + require.Len(t, serviceNames, 3) assert.Contains(t, serviceNames, "api-nginx") assert.Contains(t, serviceNames, "api-mysql") assert.Contains(t, serviceNames, "api-postgres") @@ -684,7 +684,7 @@ func TestDockerComposeApiWithWaitForShortLifespanService(t *testing.T) { services := compose.Services() - assert.Len(t, services, 2) + require.Len(t, services, 2) assert.Contains(t, services, "falafel") assert.Contains(t, services, "tzatziki") } diff --git a/modules/compose/compose_test.go b/modules/compose/compose_test.go index 066a8e8277..39f502fcf3 100644 --- a/modules/compose/compose_test.go +++ b/modules/compose/compose_test.go @@ -134,7 +134,7 @@ func TestLocalDockerComposeStrategyForInvalidService(t *testing.T) { Invoke() require.Error(t, err.Error, "Expected error to be thrown because service with wait strategy is not running") - assert.Len(t, compose.Services, 1) + require.Len(t, compose.Services, 1) assert.Contains(t, compose.Services, "local-nginx") } @@ -157,7 +157,7 @@ func TestLocalDockerComposeWithWaitLogStrategy(t *testing.T) { Invoke() checkIfError(t, err) - assert.Len(t, compose.Services, 2) + require.Len(t, compose.Services, 2) assert.Contains(t, compose.Services, "local-nginx") assert.Contains(t, compose.Services, "local-mysql") } @@ -183,7 +183,7 @@ func TestLocalDockerComposeWithWaitForService(t *testing.T) { Invoke() checkIfError(t, err) - assert.Len(t, compose.Services, 1) + require.Len(t, compose.Services, 1) assert.Contains(t, compose.Services, "local-nginx") } @@ -207,7 +207,7 @@ func TestLocalDockerComposeWithWaitForShortLifespanService(t *testing.T) { Invoke() checkIfError(t, err) - assert.Len(t, compose.Services, 2) + require.Len(t, compose.Services, 2) assert.Contains(t, compose.Services, "falafel") assert.Contains(t, compose.Services, "tzatziki") } @@ -233,7 +233,7 @@ func TestLocalDockerComposeWithWaitHTTPStrategy(t *testing.T) { Invoke() checkIfError(t, err) - assert.Len(t, compose.Services, 1) + require.Len(t, compose.Services, 1) assert.Contains(t, compose.Services, "local-nginx") } @@ -258,7 +258,7 @@ func TestLocalDockerComposeWithContainerName(t *testing.T) { Invoke() checkIfError(t, err) - assert.Len(t, compose.Services, 1) + require.Len(t, compose.Services, 1) assert.Contains(t, compose.Services, "local-nginx") } @@ -280,7 +280,7 @@ func TestLocalDockerComposeWithWaitStrategy_NoExposedPorts(t *testing.T) { Invoke() checkIfError(t, err) - assert.Len(t, compose.Services, 1) + require.Len(t, compose.Services, 1) assert.Contains(t, compose.Services, "local-nginx") } @@ -303,7 +303,7 @@ func TestLocalDockerComposeWithMultipleWaitStrategies(t *testing.T) { Invoke() checkIfError(t, err) - assert.Len(t, compose.Services, 2) + require.Len(t, compose.Services, 2) assert.Contains(t, compose.Services, "local-nginx") assert.Contains(t, compose.Services, "local-mysql") } @@ -331,7 +331,7 @@ func TestLocalDockerComposeWithFailedStrategy(t *testing.T) { // A specific error message matcher is not asserted since the docker library can change the return message, breaking this test require.Error(t, err.Error, "Expected error to be thrown because of a wrong suplied wait strategy") - assert.Len(t, compose.Services, 1) + require.Len(t, compose.Services, 1) assert.Contains(t, compose.Services, "local-nginx") } @@ -352,7 +352,7 @@ func TestLocalDockerComposeComplex(t *testing.T) { Invoke() checkIfError(t, err) - assert.Len(t, compose.Services, 2) + require.Len(t, compose.Services, 2) assert.Contains(t, compose.Services, "local-nginx") assert.Contains(t, compose.Services, "local-mysql") } @@ -377,7 +377,7 @@ func TestLocalDockerComposeWithEnvironment(t *testing.T) { Invoke() checkIfError(t, err) - assert.Len(t, compose.Services, 1) + require.Len(t, compose.Services, 1) assert.Contains(t, compose.Services, "local-nginx") present := map[string]string{ @@ -413,7 +413,7 @@ func TestLocalDockerComposeWithMultipleComposeFiles(t *testing.T) { Invoke() checkIfError(t, err) - assert.Len(t, compose.Services, 3) + require.Len(t, compose.Services, 3) assert.Contains(t, compose.Services, "local-nginx") assert.Contains(t, compose.Services, "local-mysql") assert.Contains(t, compose.Services, "local-postgres") diff --git a/modules/localstack/v1/s3_test.go b/modules/localstack/v1/s3_test.go index aa4dea378e..a35bbe98b2 100644 --- a/modules/localstack/v1/s3_test.go +++ b/modules/localstack/v1/s3_test.go @@ -104,7 +104,7 @@ func TestS3(t *testing.T) { require.NotNil(t, output) buckets := output.Buckets - assert.Len(t, buckets, 1) + require.Len(t, buckets, 1) assert.Equal(t, bucketName, *buckets[0].Name) }) @@ -117,7 +117,7 @@ func TestS3(t *testing.T) { objects := output.Contents - assert.Len(t, objects, 1) + require.Len(t, objects, 1) assert.Equal(t, s3Key1, *objects[0].Key) assert.Equal(t, int64(len(body1)), *objects[0].Size) }) diff --git a/modules/localstack/v2/s3_test.go b/modules/localstack/v2/s3_test.go index 09380a7665..10c608ed8f 100644 --- a/modules/localstack/v2/s3_test.go +++ b/modules/localstack/v2/s3_test.go @@ -110,7 +110,7 @@ func TestS3(t *testing.T) { require.NotNil(t, output) buckets := output.Buckets - assert.Len(t, buckets, 1) + require.Len(t, buckets, 1) assert.Equal(t, bucketName, *buckets[0].Name) }) @@ -123,7 +123,7 @@ func TestS3(t *testing.T) { objects := output.Contents - assert.Len(t, objects, 1) + require.Len(t, objects, 1) assert.Equal(t, s3Key1, *objects[0].Key) assert.Equal(t, aws.Int64(int64(len(body1))), objects[0].Size) }) diff --git a/options_test.go b/options_test.go index 7ba1b9ef94..a1d5af0fa5 100644 --- a/options_test.go +++ b/options_test.go @@ -54,7 +54,7 @@ func TestOverrideContainerRequest(t *testing.T) { // toBeMergedRequest should not be changed assert.Equal(t, "", toBeMergedRequest.Env["BAR"]) - assert.Len(t, toBeMergedRequest.ExposedPorts, 1) + require.Len(t, toBeMergedRequest.ExposedPorts, 1) assert.Equal(t, "67890/tcp", toBeMergedRequest.ExposedPorts[0]) // req should be merged with toBeMergedRequest From 09a54823a44817fd3541aef31eab5ad2c9483563 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Tue, 29 Oct 2024 11:18:39 +0100 Subject: [PATCH 107/126] chore: use require instead of t.Fatal (#2855) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: use require instead of t.Fatal Signed-off-by: Matthieu MOREL * Apply suggestions from code review Co-authored-by: Manuel de la Peña * Update kafka_helpers_test.go --------- Signed-off-by: Matthieu MOREL Co-authored-by: Manuel de la Peña --- container_test.go | 4 +- docker_test.go | 61 ++++++++-------------------- image_test.go | 32 ++++----------- logconsumer_test.go | 18 +++------ modules/influxdb/influxdb_test.go | 8 +--- modules/kafka/kafka_helpers_test.go | 16 ++++---- modules/kafka/kafka_test.go | 16 ++------ modules/mariadb/mariadb_test.go | 4 +- modules/neo4j/neo4j_test.go | 49 ++++++----------------- modules/pulsar/pulsar_test.go | 4 +- modules/rabbitmq/rabbitmq_test.go | 36 +++++------------ modules/redis/redis_test.go | 8 +--- modules/valkey/valkey_test.go | 8 +--- modules/weaviate/weaviate_test.go | 12 ++---- port_forwarding_test.go | 12 ++---- provider_test.go | 6 +-- testing.go | 8 +--- wait/exec_test.go | 8 +--- wait/sql_test.go | 62 ++++------------------------- 19 files changed, 93 insertions(+), 279 deletions(-) diff --git a/container_test.go b/container_test.go index 72927bc55a..632ede9d26 100644 --- a/container_test.go +++ b/container_test.go @@ -137,9 +137,7 @@ func Test_GetDockerfile(t *testing.T) { for _, testCase := range testTable { t.Run(testCase.name, func(t *testing.T) { n := testCase.ContainerRequest.GetDockerfile() - if n != testCase.ExpectedDockerfileName { - t.Fatalf("expected Dockerfile name: %s, received: %s", testCase.ExpectedDockerfileName, n) - } + require.Equalf(t, n, testCase.ExpectedDockerfileName, "expected Dockerfile name: %s, received: %s", testCase.ExpectedDockerfileName, n) }) } } diff --git a/docker_test.go b/docker_test.go index 4be29f8fcd..dc3b245d1b 100644 --- a/docker_test.go +++ b/docker_test.go @@ -346,9 +346,7 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { require.NoError(t, err) _, _, err = dockerClient.ImageInspectWithRaw(ctx, nginxAlpineImage) - if err != nil { - t.Fatal("nginx image should not have been removed") - } + require.NoErrorf(t, err, "nginx image should not have been removed") }) t.Run("if built from Dockerfile", func(t *testing.T) { @@ -380,9 +378,7 @@ func TestContainerTerminationRemovesDockerImage(t *testing.T) { require.NoError(t, err) _, _, err = dockerClient.ImageInspectWithRaw(ctx, imageID) - if err == nil { - t.Fatal("custom built image should have been removed", err) - } + require.Errorf(t, err, "custom built image should have been removed") }) } @@ -785,9 +781,7 @@ func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { Started: true, }) CleanupContainer(t, c) - if err == nil { - t.Fatal("Expected timeout") - } + require.Errorf(t, err, "Expected timeout") } func TestContainerCreationWaitingForHostPort(t *testing.T) { @@ -1139,9 +1133,7 @@ func TestContainerWithTmpFs(t *testing.T) { // exec_reader_example { c, reader, err := ctr.Exec(ctx, []string{"ls", path}) require.NoError(t, err) - if c != 1 { - t.Fatalf("File %s should not have existed, expected return code 1, got %v", path, c) - } + require.Equalf(t, 1, c, "File %s should not have existed, expected return code 1, got %v", path, c) buf := new(strings.Builder) _, err = io.Copy(buf, reader) @@ -1154,16 +1146,12 @@ func TestContainerWithTmpFs(t *testing.T) { // exec_example { c, _, err = ctr.Exec(ctx, []string{"touch", path}) require.NoError(t, err) - if c != 0 { - t.Fatalf("File %s should have been created successfully, expected return code 0, got %v", path, c) - } + require.Zerof(t, c, "File %s should have been created successfully, expected return code 0, got %v", path, c) // } c, _, err = ctr.Exec(ctx, []string{"ls", path}) require.NoError(t, err) - if c != 0 { - t.Fatalf("File %s should exist, expected return code 0, got %v", path, c) - } + require.Zerof(t, c, "File %s should exist, expected return code 0, got %v", path, c) } func TestContainerNonExistentImage(t *testing.T) { @@ -1177,9 +1165,7 @@ func TestContainerNonExistentImage(t *testing.T) { CleanupContainer(t, ctr) var nf errdefs.ErrNotFound - if !errors.As(err, &nf) { - t.Fatalf("the error should have been an errdefs.ErrNotFound: %v", err) - } + require.ErrorAsf(t, err, &nf, "the error should have been an errdefs.ErrNotFound: %v", err) }) t.Run("the context cancellation is propagated to container creation", func(t *testing.T) { @@ -1194,9 +1180,7 @@ func TestContainerNonExistentImage(t *testing.T) { Started: true, }) CleanupContainer(t, c) - if !errors.Is(err, ctx.Err()) { - t.Fatalf("err should be a ctx cancelled error %v", err) - } + require.ErrorIsf(t, err, ctx.Err(), "err should be a ctx cancelled error %v", err) }) } @@ -1267,9 +1251,8 @@ func TestContainerWithCustomHostname(t *testing.T) { CleanupContainer(t, ctr) require.NoError(t, err) - if actualHostname := readHostname(t, ctr.GetContainerID()); actualHostname != hostname { - t.Fatalf("expected hostname %s, got %s", hostname, actualHostname) - } + actualHostname := readHostname(t, ctr.GetContainerID()) + require.Equalf(t, actualHostname, hostname, "expected hostname %s, got %s", hostname, actualHostname) } func TestContainerInspect_RawInspectIsCleanedOnStop(t *testing.T) { @@ -1293,15 +1276,11 @@ func TestContainerInspect_RawInspectIsCleanedOnStop(t *testing.T) { func readHostname(tb testing.TB, containerId string) string { tb.Helper() containerClient, err := NewDockerClientWithOpts(context.Background()) - if err != nil { - tb.Fatalf("Failed to create Docker client: %v", err) - } + require.NoErrorf(tb, err, "Failed to create Docker client") defer containerClient.Close() containerDetails, err := containerClient.ContainerInspect(context.Background(), containerId) - if err != nil { - tb.Fatalf("Failed to inspect container: %v", err) - } + require.NoErrorf(tb, err, "Failed to inspect container") return containerDetails.Config.Hostname } @@ -1340,9 +1319,7 @@ func TestDockerContainerCopyFileToContainer(t *testing.T) { _ = nginxC.CopyFileToContainer(ctx, filepath.Join(".", "testdata", "hello.sh"), tc.copiedFileName, 700) c, _, err := nginxC.Exec(ctx, []string{"bash", tc.copiedFileName}) require.NoError(t, err) - if c != 0 { - t.Fatalf("File %s should exist, expected return code 0, got %v", tc.copiedFileName, c) - } + require.Zerof(t, c, "File %s should exist, expected return code 0, got %v", tc.copiedFileName, c) }) } } @@ -1551,9 +1528,7 @@ func TestDockerContainerCopyToContainer(t *testing.T) { require.NoError(t, err) c, _, err := nginxC.Exec(ctx, []string{"bash", tc.copiedFileName}) require.NoError(t, err) - if c != 0 { - t.Fatalf("File %s should exist, expected return code 0, got %v", tc.copiedFileName, c) - } + require.Zerof(t, c, "File %s should exist, expected return code 0, got %v", tc.copiedFileName, c) }) } } @@ -1579,9 +1554,7 @@ func TestDockerContainerCopyFileFromContainer(t *testing.T) { _ = nginxC.CopyFileToContainer(ctx, filepath.Join(".", "testdata", "hello.sh"), "/"+copiedFileName, 700) c, _, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) require.NoError(t, err) - if c != 0 { - t.Fatalf("File %s should exist, expected return code 0, got %v", copiedFileName, c) - } + require.Zerof(t, c, "File %s should exist, expected return code 0, got %v", copiedFileName, c) reader, err := nginxC.CopyFileFromContainer(ctx, "/"+copiedFileName) require.NoError(t, err) @@ -1611,9 +1584,7 @@ func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) { _ = nginxC.CopyFileToContainer(ctx, filepath.Join(".", "testdata", "empty.sh"), "/"+copiedFileName, 700) c, _, err := nginxC.Exec(ctx, []string{"bash", copiedFileName}) require.NoError(t, err) - if c != 0 { - t.Fatalf("File %s should exist, expected return code 0, got %v", copiedFileName, c) - } + require.Zerof(t, c, "File %s should exist, expected return code 0, got %v", copiedFileName, c) reader, err := nginxC.CopyFileFromContainer(ctx, "/"+copiedFileName) require.NoError(t, err) diff --git a/image_test.go b/image_test.go index 39f8134acd..b5a95640a8 100644 --- a/image_test.go +++ b/image_test.go @@ -15,9 +15,7 @@ func TestImageList(t *testing.T) { t.Setenv("DOCKER_HOST", core.MustExtractDockerHost(context.Background())) provider, err := ProviderDocker.GetProvider() - if err != nil { - t.Fatalf("failed to get provider %v", err) - } + require.NoErrorf(t, err, "failed to get provider") defer func() { _ = provider.Close() @@ -29,18 +27,12 @@ func TestImageList(t *testing.T) { ctr, err := provider.CreateContainer(context.Background(), req) CleanupContainer(t, ctr) - if err != nil { - t.Fatalf("creating test container %v", err) - } + require.NoErrorf(t, err, "creating test container") images, err := provider.ListImages(context.Background()) - if err != nil { - t.Fatalf("listing images %v", err) - } + require.NoErrorf(t, err, "listing images") - if len(images) == 0 { - t.Fatal("no images retrieved") - } + require.NotEmptyf(t, images, "no images retrieved") // look if the list contains the container image for _, img := range images { @@ -56,9 +48,7 @@ func TestSaveImages(t *testing.T) { t.Setenv("DOCKER_HOST", core.MustExtractDockerHost(context.Background())) provider, err := ProviderDocker.GetProvider() - if err != nil { - t.Fatalf("failed to get provider %v", err) - } + require.NoErrorf(t, err, "failed to get provider") defer func() { _ = provider.Close() @@ -70,20 +60,14 @@ func TestSaveImages(t *testing.T) { ctr, err := provider.CreateContainer(context.Background(), req) CleanupContainer(t, ctr) - if err != nil { - t.Fatalf("creating test container %v", err) - } + require.NoErrorf(t, err, "creating test container") output := filepath.Join(t.TempDir(), "images.tar") err = provider.SaveImages(context.Background(), output, req.Image) - if err != nil { - t.Fatalf("saving image %q: %v", req.Image, err) - } + require.NoErrorf(t, err, "saving image %q", req.Image) info, err := os.Stat(output) require.NoError(t, err) - if info.Size() == 0 { - t.Fatalf("output file is empty") - } + require.NotZerof(t, info.Size(), "output file is empty") } diff --git a/logconsumer_test.go b/logconsumer_test.go index e4ee916e0f..900c8d8ae1 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -278,9 +278,7 @@ func TestContainerLogWithErrClosed(t *testing.T) { time.Sleep(10 * time.Millisecond) t.Log("retrying get endpoint") } - if err != nil { - t.Fatal("get endpoint:", err) - } + require.NoErrorf(t, err, "get endpoint") opts := []client.Opt{client.WithHost(remoteDocker), client.WithAPIVersionNegotiation()} @@ -333,9 +331,7 @@ func TestContainerLogWithErrClosed(t *testing.T) { hitNginx() time.Sleep(time.Second * 1) msgs := consumer.Msgs() - if len(msgs)-existingLogs != 1 { - t.Fatalf("logConsumer should have 1 new log message, instead has: %v", msgs[existingLogs:]) - } + require.Equalf(t, 1, len(msgs)-existingLogs, "logConsumer should have 1 new log message, instead has: %v", msgs[existingLogs:]) existingLogs = len(consumer.Msgs()) iptableArgs := []string{ @@ -357,12 +353,10 @@ func TestContainerLogWithErrClosed(t *testing.T) { hitNginx() time.Sleep(time.Second * 1) msgs = consumer.Msgs() - if len(msgs)-existingLogs != 2 { - t.Fatalf( - "LogConsumer should have 2 new log messages after detecting closed connection and"+ - " re-requesting logs. Instead has:\n%s", msgs[existingLogs:], - ) - } + require.Equalf(t, 2, len(msgs)-existingLogs, + "LogConsumer should have 2 new log messages after detecting closed connection and"+ + " re-requesting logs. Instead has:\n%s", msgs[existingLogs:], + ) } func TestContainerLogsShouldBeWithoutStreamHeader(t *testing.T) { diff --git a/modules/influxdb/influxdb_test.go b/modules/influxdb/influxdb_test.go index e04a800dc6..08d9a72126 100644 --- a/modules/influxdb/influxdb_test.go +++ b/modules/influxdb/influxdb_test.go @@ -43,9 +43,7 @@ func TestV2Container(t *testing.T) { state, err := influxDbContainer.State(ctx) require.NoError(t, err) - if !state.Running { - t.Fatal("InfluxDB container is not running") - } + require.Truef(t, state.Running, "InfluxDB container is not running") } func TestWithInitDb(t *testing.T) { @@ -72,9 +70,7 @@ func TestWithInitDb(t *testing.T) { response, err := cli.Query(q) require.NoError(t, err) - if response.Error() != nil { - t.Fatal(response.Error()) - } + require.NoError(t, response.Error()) testJson, err := json.Marshal(response.Results) require.NoError(t, err) diff --git a/modules/kafka/kafka_helpers_test.go b/modules/kafka/kafka_helpers_test.go index 4a49a00f50..6ef7deb60f 100644 --- a/modules/kafka/kafka_helpers_test.go +++ b/modules/kafka/kafka_helpers_test.go @@ -3,6 +3,8 @@ package kafka import ( "testing" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go" ) @@ -55,9 +57,7 @@ func TestConfigureQuorumVoters(t *testing.T) { t.Run(test.name, func(t *testing.T) { configureControllerQuorumVoters(test.req) - if test.req.Env["KAFKA_CONTROLLER_QUORUM_VOTERS"] != test.expectedVoters { - t.Fatalf("expected KAFKA_CONTROLLER_QUORUM_VOTERS to be %s, got %s", test.expectedVoters, test.req.Env["KAFKA_CONTROLLER_QUORUM_VOTERS"]) - } + require.Equalf(t, test.expectedVoters, test.req.Env["KAFKA_CONTROLLER_QUORUM_VOTERS"], "expected KAFKA_CONTROLLER_QUORUM_VOTERS to be %s, got %s", test.expectedVoters, test.req.Env["KAFKA_CONTROLLER_QUORUM_VOTERS"]) }) } } @@ -99,12 +99,10 @@ func TestValidateKRaftVersion(t *testing.T) { t.Run(test.name, func(t *testing.T) { err := validateKRaftVersion(test.image) - if test.wantErr && err == nil { - t.Fatalf("expected error, got nil") - } - - if !test.wantErr && err != nil { - t.Fatalf("expected no error, got %s", err) + if test.wantErr { + require.Errorf(t, err, "expected error, got nil") + } else { + require.NoErrorf(t, err, "expected no error, got %s", err) } }) } diff --git a/modules/kafka/kafka_test.go b/modules/kafka/kafka_test.go index c1fca69fb2..763f29e3e0 100644 --- a/modules/kafka/kafka_test.go +++ b/modules/kafka/kafka_test.go @@ -24,9 +24,7 @@ func TestKafka(t *testing.T) { assertAdvertisedListeners(t, kafkaContainer) - if !strings.EqualFold(kafkaContainer.ClusterID, "kraftCluster") { - t.Fatalf("expected clusterID to be %s, got %s", "kraftCluster", kafkaContainer.ClusterID) - } + require.Truef(t, strings.EqualFold(kafkaContainer.ClusterID, "kraftCluster"), "expected clusterID to be %s, got %s", "kraftCluster", kafkaContainer.ClusterID) // getBrokers { brokers, err := kafkaContainer.Brokers(ctx) @@ -65,12 +63,8 @@ func TestKafka(t *testing.T) { <-done - if !strings.EqualFold(string(consumer.message.Key), "key") { - t.Fatalf("expected key to be %s, got %s", "key", string(consumer.message.Key)) - } - if !strings.EqualFold(string(consumer.message.Value), "value") { - t.Fatalf("expected value to be %s, got %s", "value", string(consumer.message.Value)) - } + require.Truef(t, strings.EqualFold(string(consumer.message.Key), "key"), "expected key to be %s, got %s", "key", string(consumer.message.Key)) + require.Truef(t, strings.EqualFold(string(consumer.message.Value), "value"), "expected value to be %s, got %s", "value", string(consumer.message.Value)) } func TestKafka_invalidVersion(t *testing.T) { @@ -98,7 +92,5 @@ func assertAdvertisedListeners(t *testing.T, container testcontainers.Container) bs, err := io.ReadAll(r) require.NoError(t, err) - if !strings.Contains(string(bs), "BROKER://"+hostname+":9092") { - t.Fatalf("expected advertised listeners to contain %s, got %s", "BROKER://"+hostname+":9092", string(bs)) - } + require.Containsf(t, string(bs), "BROKER://"+hostname+":9092", "expected advertised listeners to contain %s, got %s", "BROKER://"+hostname+":9092", string(bs)) } diff --git a/modules/mariadb/mariadb_test.go b/modules/mariadb/mariadb_test.go index f042555e51..706ee2eb76 100644 --- a/modules/mariadb/mariadb_test.go +++ b/modules/mariadb/mariadb_test.go @@ -53,9 +53,7 @@ func TestMariaDBWithNonRootUserAndEmptyPassword(t *testing.T) { mariadb.WithDatabase("foo"), mariadb.WithUsername("test"), mariadb.WithPassword("")) - if err.Error() != "empty password can be used only with the root user" { - t.Fatal(err) - } + require.EqualError(t, err, "empty password can be used only with the root user") } func TestMariaDBWithRootUserAndEmptyPassword(t *testing.T) { diff --git a/modules/neo4j/neo4j_test.go b/modules/neo4j/neo4j_test.go index a5cff51182..5918b7dc31 100644 --- a/modules/neo4j/neo4j_test.go +++ b/modules/neo4j/neo4j_test.go @@ -29,9 +29,7 @@ func TestNeo4j(outer *testing.T) { driver := createDriver(t, ctx, ctr) err := driver.VerifyConnectivity(ctx) - if err != nil { - t.Fatalf("should have successfully connected to server but did not: %s", err) - } + require.NoErrorf(t, err, "should have successfully connected to server but did not") }) outer.Run("exercises APOC plugin", func(t *testing.T) { @@ -40,9 +38,7 @@ func TestNeo4j(outer *testing.T) { result, err := neo.ExecuteQuery(ctx, driver, "RETURN apoc.number.arabicToRoman(1986) AS output", nil, neo.EagerResultTransformer) - if err != nil { - t.Fatalf("expected APOC query to successfully run but did not: %s", err) - } + require.NoErrorf(t, err, "expected APOC query to successfully run but did not") if value, _ := result.Records[0].Get("output"); value != "MCMLXXXVI" { t.Fatalf("did not get expected roman number: %s", value) } @@ -51,9 +47,7 @@ func TestNeo4j(outer *testing.T) { outer.Run("is configured with custom Neo4j settings", func(t *testing.T) { env := getContainerEnv(t, ctx, ctr) - if !strings.Contains(env, "NEO4J_dbms_tx__log_rotation_size=42M") { - t.Fatal("expected to custom setting to be exported but was not") - } + require.Containsf(t, env, "NEO4J_dbms_tx__log_rotation_size=42M", "expected to custom setting to be exported but was not") }) } @@ -81,9 +75,7 @@ func TestNeo4jWithEnterpriseLicense(t *testing.T) { env := getContainerEnv(t, ctx, ctr) - if !strings.Contains(env, "NEO4J_ACCEPT_LICENSE_AGREEMENT=yes") { - t.Fatal("expected to accept license agreement but did not") - } + require.Containsf(t, env, "NEO4J_ACCEPT_LICENSE_AGREEMENT=yes", "expected to accept license agreement but did not") }) } } @@ -106,12 +98,8 @@ func TestNeo4jWithWrongSettings(outer *testing.T) { neo4j.WithNeo4jSetting("AUTH", "neo4j/thisisgonnafail"), ) testcontainers.CleanupContainer(t, ctr) - if err == nil { - t.Fatalf("expected env to fail due to conflicting auth settings but did not") - } - if ctr != nil { - t.Fatalf("container must not be created with conflicting auth settings") - } + require.Errorf(t, err, "expected env to fail due to conflicting auth settings but did not") + require.Nilf(t, ctr, "container must not be created with conflicting auth settings") }) outer.Run("warns about overwrites of setting keys", func(t *testing.T) { @@ -134,17 +122,13 @@ func TestNeo4jWithWrongSettings(outer *testing.T) { !Contains(errorLogs, `setting "some.key" with value "value2" is now overwritten with value "value3"`+"\n") { t.Fatalf("expected setting overwrites to be logged") } - if !strings.Contains(getContainerEnv(t, ctx, ctr), "NEO4J_some_key=value3") { - t.Fatalf("expected custom setting to be set with last value") - } + require.Containsf(t, getContainerEnv(t, ctx, ctr), "NEO4J_some_key=value3", "expected custom setting to be set with last value") }) outer.Run("rejects nil logger", func(t *testing.T) { ctr, err := neo4j.Run(ctx, "neo4j:4.4", neo4j.WithLogger(nil)) testcontainers.CleanupContainer(t, ctr) - if ctr != nil { - t.Fatalf("container must not be created with nil logger") - } + require.Nilf(t, ctr, "container must not be created with nil logger") if err == nil || err.Error() != "nil logger is not permitted" { t.Fatalf("expected config validation error but got no error") } @@ -171,9 +155,8 @@ func createDriver(t *testing.T, ctx context.Context, container *neo4j.Neo4jConta driver, err := neo.NewDriverWithContext(boltUrl, neo.BasicAuth("neo4j", testPassword, "")) require.NoError(t, err) t.Cleanup(func() { - if err := driver.Close(ctx); err != nil { - t.Fatalf("failed to close neo: %s", err) - } + err := driver.Close(ctx) + require.NoErrorf(t, err, "failed to close neo: %s", err) }) return driver } @@ -181,16 +164,10 @@ func createDriver(t *testing.T, ctx context.Context, container *neo4j.Neo4jConta func getContainerEnv(t *testing.T, ctx context.Context, container *neo4j.Neo4jContainer) string { t.Helper() exec, reader, err := container.Exec(ctx, []string{"env"}) - if err != nil { - t.Fatalf("expected env to successfully run but did not: %s", err) - } - if exec != 0 { - t.Fatalf("expected env to exit with status 0 but exited with: %d", exec) - } + require.NoErrorf(t, err, "expected env to successfully run but did not") + require.Zerof(t, exec, "expected env to exit with status 0 but exited with: %d", exec) envVars, err := io.ReadAll(reader) - if err != nil { - t.Fatalf("expected to read all bytes from env output but did not: %s", err) - } + require.NoErrorf(t, err, "expected to read all bytes from env output but did not") return string(envVars) } diff --git a/modules/pulsar/pulsar_test.go b/modules/pulsar/pulsar_test.go index 8cea6a4119..de2c4bd437 100644 --- a/modules/pulsar/pulsar_test.go +++ b/modules/pulsar/pulsar_test.go @@ -166,9 +166,7 @@ func TestPulsar(t *testing.T) { case <-ticker.C: t.Fatal("did not receive message in time") case msg := <-msgChan: - if string(msg) != "hello world" { - t.Fatal("received unexpected message bytes") - } + require.Equalf(t, "hello world", string(msg), "received unexpected message bytes") } // get topic statistics using the Admin endpoint diff --git a/modules/rabbitmq/rabbitmq_test.go b/modules/rabbitmq/rabbitmq_test.go index 6c4cca0c8c..45c0f5e2c1 100644 --- a/modules/rabbitmq/rabbitmq_test.go +++ b/modules/rabbitmq/rabbitmq_test.go @@ -46,9 +46,7 @@ func TestRunContainer_connectUsingAmqps(t *testing.T) { IsCA: true, ParentDir: tmpDir, }) - if caCert == nil { - t.Fatal("failed to generate CA certificate") - } + require.NotNilf(t, caCert, "failed to generate CA certificate") cert := tlscert.SelfSignedFromRequest(tlscert.Request{ Name: "client", @@ -57,9 +55,7 @@ func TestRunContainer_connectUsingAmqps(t *testing.T) { Parent: caCert, ParentDir: tmpDir, }) - if cert == nil { - t.Fatal("failed to generate certificate") - } + require.NotNilf(t, cert, "failed to generate certificate") sslSettings := rabbitmq.SSLSettings{ CACertFile: caCert.CertPath, @@ -216,27 +212,13 @@ func TestRunContainer_withAllSettings(t *testing.T) { testcontainers.CleanupContainer(t, rabbitmqContainer) require.NoError(t, err) - if !assertEntity(t, rabbitmqContainer, "queues", "queue1", "queue2", "queue3", "queue4") { - t.Fatal(err) - } - if !assertEntity(t, rabbitmqContainer, "exchanges", "direct-exchange", "topic-exchange", "topic-exchange-2", "topic-exchange-3", "topic-exchange-4") { - t.Fatal(err) - } - if !assertEntity(t, rabbitmqContainer, "users", "user1", "user2") { - t.Fatal(err) - } - if !assertEntity(t, rabbitmqContainer, "policies", "max length policy", "alternate exchange policy") { - t.Fatal(err) - } - if !assertEntityWithVHost(t, rabbitmqContainer, "policies", 2, "max length policy", "alternate exchange policy") { - t.Fatal(err) - } - if !assertEntity(t, rabbitmqContainer, "operator_policies", "operator policy 1") { - t.Fatal(err) - } - if !assertPluginIsEnabled(t, rabbitmqContainer, "rabbitmq_shovel", "rabbitmq_random_exchange") { - t.Fatal(err) - } + require.True(t, assertEntity(t, rabbitmqContainer, "queues", "queue1", "queue2", "queue3", "queue4")) + require.True(t, assertEntity(t, rabbitmqContainer, "exchanges", "direct-exchange", "topic-exchange", "topic-exchange-2", "topic-exchange-3", "topic-exchange-4")) + require.True(t, assertEntity(t, rabbitmqContainer, "users", "user1", "user2")) + require.True(t, assertEntity(t, rabbitmqContainer, "policies", "max length policy", "alternate exchange policy")) + require.True(t, assertEntityWithVHost(t, rabbitmqContainer, "policies", 2, "max length policy", "alternate exchange policy")) + require.True(t, assertEntity(t, rabbitmqContainer, "operator_policies", "operator policy 1")) + require.True(t, assertPluginIsEnabled(t, rabbitmqContainer, "rabbitmq_shovel", "rabbitmq_random_exchange")) } func assertEntity(t *testing.T, container testcontainers.Container, listCommand string, entities ...string) bool { diff --git a/modules/redis/redis_test.go b/modules/redis/redis_test.go index 58d1c14c9c..e2352a1bf6 100644 --- a/modules/redis/redis_test.go +++ b/modules/redis/redis_test.go @@ -120,9 +120,7 @@ func assertSetsGets(t *testing.T, ctx context.Context, redisContainer *tcredis.R t.Log("received response from redis") - if pong != "PONG" { - t.Fatalf("received unexpected response from redis: %s", pong) - } + require.Equalf(t, "PONG", pong, "received unexpected response from redis: %s", pong) for i := 0; i < keyCount; i++ { // Set data @@ -137,9 +135,7 @@ func assertSetsGets(t *testing.T, ctx context.Context, redisContainer *tcredis.R savedValue, err := client.Get(ctx, key).Result() require.NoError(t, err) - if savedValue != value { - t.Fatalf("Expected value %s. Got %s.", savedValue, value) - } + require.Equal(t, savedValue, value) } } diff --git a/modules/valkey/valkey_test.go b/modules/valkey/valkey_test.go index 26e2ea93b8..44412afa4a 100644 --- a/modules/valkey/valkey_test.go +++ b/modules/valkey/valkey_test.go @@ -109,9 +109,7 @@ func assertSetsGets(t *testing.T, ctx context.Context, valkeyContainer *tcvalkey msg, err := res.ToString() require.NoError(t, err) - if msg != "PONG" { - t.Fatalf("received unexpected response from valkey: %s", res.String()) - } + require.Equalf(t, "PONG", msg, "received unexpected response from valkey: %s", res.String()) for i := 0; i < keyCount; i++ { // Set data @@ -132,9 +130,7 @@ func assertSetsGets(t *testing.T, ctx context.Context, valkeyContainer *tcvalkey retVal, err := resp.ToString() require.NoError(t, err) - if retVal != value { - t.Fatalf("Expected value %s. Got %s.", value, retVal) - } + require.Equal(t, retVal, value) } } diff --git a/modules/weaviate/weaviate_test.go b/modules/weaviate/weaviate_test.go index faf8e42f92..f1d6de3eeb 100644 --- a/modules/weaviate/weaviate_test.go +++ b/modules/weaviate/weaviate_test.go @@ -48,17 +48,11 @@ func TestWeaviate(t *testing.T) { opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) conn, err := grpc.NewClient(host, opts...) - if err != nil { - tt.Fatalf("failed to dial connection: %v", err) - } + require.NoErrorf(t, err, "failed to dial connection") client := grpc_health_v1.NewHealthClient(conn) check, err := client.Check(context.TODO(), &grpc_health_v1.HealthCheckRequest{}) - if err != nil { - tt.Fatalf("failed to get a health check: %v", err) - } - if grpc_health_v1.HealthCheckResponse_SERVING.Enum().Number() != check.Status.Number() { - tt.Fatalf("unexpected status code: %d", check.Status.Number()) - } + require.NoErrorf(t, err, "failed to get a health check") + require.Equalf(t, grpc_health_v1.HealthCheckResponse_SERVING.Enum().Number(), check.Status.Number(), "unexpected status code: %d", check.Status.Number()) }) t.Run("Weaviate client", func(tt *testing.T) { diff --git a/port_forwarding_test.go b/port_forwarding_test.go index 8f8681f22c..2936a46457 100644 --- a/port_forwarding_test.go +++ b/port_forwarding_test.go @@ -133,13 +133,9 @@ func assertContainerHasHostAccess(t *testing.T, c testcontainers.Container, port t.Helper() for _, port := range ports { code, response := httpRequest(t, c, port) - if code != 0 { - t.Fatalf("expected status code [%d] but got [%d]", 0, code) - } + require.Zerof(t, code, "expected status code [%d] but got [%d]", 0, code) - if response != expectedResponse { - t.Fatalf("expected [%s] but got [%s]", expectedResponse, response) - } + require.Equalf(t, expectedResponse, response, "expected [%s] but got [%s]", expectedResponse, response) } } @@ -148,8 +144,6 @@ func assertContainerHasNoHostAccess(t *testing.T, c testcontainers.Container, po for _, port := range ports { _, response := httpRequest(t, c, port) - if response == expectedResponse { - t.Fatalf("expected not to get [%s] but got [%s]", expectedResponse, response) - } + require.NotEqualf(t, expectedResponse, response, "expected not to get [%s] but got [%s]", expectedResponse, response) } } diff --git a/provider_test.go b/provider_test.go index 097c83a02c..e4937a49d0 100644 --- a/provider_test.go +++ b/provider_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go/internal/core" ) @@ -70,9 +72,7 @@ func TestProviderTypeGetProviderAutodetect(t *testing.T) { return } provider, ok := got.(*DockerProvider) - if !ok { - t.Fatalf("ProviderType.GetProvider() = %T, want %T", got, &DockerProvider{}) - } + require.Truef(t, ok, "ProviderType.GetProvider() = %T, want %T", got, &DockerProvider{}) if provider.defaultBridgeNetworkName != tt.want { t.Errorf("ProviderType.GetProvider() = %v, want %v", provider.defaultBridgeNetworkName, tt.want) } diff --git a/testing.go b/testing.go index 0601d9fa83..1670d7c059 100644 --- a/testing.go +++ b/testing.go @@ -36,14 +36,10 @@ func SkipIfProviderIsNotHealthy(t *testing.T) { func SkipIfDockerDesktop(t *testing.T, ctx context.Context) { t.Helper() cli, err := NewDockerClientWithOpts(ctx) - if err != nil { - t.Fatalf("failed to create docker client: %s", err) - } + require.NoErrorf(t, err, "failed to create docker client: %s", err) info, err := cli.Info(ctx) - if err != nil { - t.Fatalf("failed to get docker info: %s", err) - } + require.NoErrorf(t, err, "failed to get docker info: %s", err) if info.OperatingSystem == "Docker Desktop" { t.Skip("Skipping test that requires host network access when running in Docker Desktop") diff --git a/wait/exec_test.go b/wait/exec_test.go index ab84fabd17..a431b146da 100644 --- a/wait/exec_test.go +++ b/wait/exec_test.go @@ -144,9 +144,7 @@ func TestExecStrategyWaitUntilReady_DeadlineExceeded(t *testing.T) { } wg := wait.NewExecStrategy([]string{"true"}) err := wg.WaitUntilReady(ctx, target) - if !errors.Is(err, context.DeadlineExceeded) { - t.Fatal(err) - } + require.ErrorIs(t, err, context.DeadlineExceeded) } func TestExecStrategyWaitUntilReady_CustomExitCode(t *testing.T) { @@ -174,9 +172,7 @@ func TestExecStrategyWaitUntilReady_withExitCode(t *testing.T) { wg = wait.NewExecStrategy([]string{"true"}).WithExitCode(0) wg.WithStartupTimeout(time.Second * 2) err = wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatalf("Expected strategy to timeout out") - } + require.Errorf(t, err, "Expected strategy to timeout out") } func TestExecStrategyWaitUntilReady_CustomResponseMatcher(t *testing.T) { diff --git a/wait/sql_test.go b/wait/sql_test.go index 2a7db5b330..63179ee8ab 100644 --- a/wait/sql_test.go +++ b/wait/sql_test.go @@ -18,9 +18,7 @@ func Test_waitForSql_WithQuery(t *testing.T) { return "fake-url" }) - if got := w.query; got != defaultForSqlQuery { - t.Fatalf("expected %s, got %s", defaultForSqlQuery, got) - } + require.Equal(t, defaultForSqlQuery, w.query) }) t.Run("custom query", func(t *testing.T) { const q = "SELECT 100;" @@ -29,9 +27,7 @@ func Test_waitForSql_WithQuery(t *testing.T) { return "fake-url" }).WithQuery(q) - if got := w.query; got != q { - t.Fatalf("expected %s, got %s", q, got) - } + require.Equal(t, q, w.query) }) } @@ -133,14 +129,7 @@ func TestWaitForSQLFailsWhileGettingPortDueToOOMKilledContainer(t *testing.T) { { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "container crashed with out-of-memory (OOMKilled)" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.EqualError(t, err, "container crashed with out-of-memory (OOMKilled)") } } @@ -171,14 +160,7 @@ func TestWaitForSQLFailsWhileGettingPortDueToExitedContainer(t *testing.T) { { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "container exited with code 1" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.EqualError(t, err, "container exited with code 1") } } @@ -208,14 +190,7 @@ func TestWaitForSQLFailsWhileGettingPortDueToUnexpectedContainerStatus(t *testin { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "unexpected container status \"dead\"" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.EqualError(t, err, "unexpected container status \"dead\"") } } @@ -240,14 +215,7 @@ func TestWaitForSQLFailsWhileQueryExecutingDueToOOMKilledContainer(t *testing.T) { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "container crashed with out-of-memory (OOMKilled)" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.EqualError(t, err, "container crashed with out-of-memory (OOMKilled)") } } @@ -273,14 +241,7 @@ func TestWaitForSQLFailsWhileQueryExecutingDueToExitedContainer(t *testing.T) { { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "container exited with code 1" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.EqualError(t, err, "container exited with code 1") } } @@ -305,13 +266,6 @@ func TestWaitForSQLFailsWhileQueryExecutingDueToUnexpectedContainerStatus(t *tes { err := wg.WaitUntilReady(context.Background(), target) - if err == nil { - t.Fatal("no error") - } - - expected := "unexpected container status \"dead\"" - if err.Error() != expected { - t.Fatalf("expected %q, got %q", expected, err.Error()) - } + require.EqualError(t, err, "unexpected container status \"dead\"") } } From 2ee47e448f63c2f9748a05ea5cab5d034b2c02c3 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Wed, 30 Oct 2024 12:56:54 +0100 Subject: [PATCH 108/126] chore(rabbitmq): refactor assertEntity in tests (#2856) Signed-off-by: Matthieu MOREL --- modules/rabbitmq/rabbitmq_test.go | 60 +++++++++---------------------- testing.go | 16 +++++++++ 2 files changed, 33 insertions(+), 43 deletions(-) diff --git a/modules/rabbitmq/rabbitmq_test.go b/modules/rabbitmq/rabbitmq_test.go index 45c0f5e2c1..1e05b8f3aa 100644 --- a/modules/rabbitmq/rabbitmq_test.go +++ b/modules/rabbitmq/rabbitmq_test.go @@ -5,7 +5,6 @@ import ( "crypto/tls" "crypto/x509" "fmt" - "io" "os" "strings" "testing" @@ -212,38 +211,29 @@ func TestRunContainer_withAllSettings(t *testing.T) { testcontainers.CleanupContainer(t, rabbitmqContainer) require.NoError(t, err) - require.True(t, assertEntity(t, rabbitmqContainer, "queues", "queue1", "queue2", "queue3", "queue4")) - require.True(t, assertEntity(t, rabbitmqContainer, "exchanges", "direct-exchange", "topic-exchange", "topic-exchange-2", "topic-exchange-3", "topic-exchange-4")) - require.True(t, assertEntity(t, rabbitmqContainer, "users", "user1", "user2")) - require.True(t, assertEntity(t, rabbitmqContainer, "policies", "max length policy", "alternate exchange policy")) - require.True(t, assertEntityWithVHost(t, rabbitmqContainer, "policies", 2, "max length policy", "alternate exchange policy")) - require.True(t, assertEntity(t, rabbitmqContainer, "operator_policies", "operator policy 1")) - require.True(t, assertPluginIsEnabled(t, rabbitmqContainer, "rabbitmq_shovel", "rabbitmq_random_exchange")) + requireEntity(t, rabbitmqContainer, "queues", "queue1", "queue2", "queue3", "queue4") + requireEntity(t, rabbitmqContainer, "exchanges", "direct-exchange", "topic-exchange", "topic-exchange-2", "topic-exchange-3", "topic-exchange-4") + requireEntity(t, rabbitmqContainer, "users", "user1", "user2") + requireEntity(t, rabbitmqContainer, "policies", "max length policy", "alternate exchange policy") + requireEntityWithVHost(t, rabbitmqContainer, "policies", 2, "max length policy", "alternate exchange policy") + requireEntity(t, rabbitmqContainer, "operator_policies", "operator policy 1") + requirePluginIsEnabled(t, rabbitmqContainer, "rabbitmq_shovel", "rabbitmq_random_exchange") } -func assertEntity(t *testing.T, container testcontainers.Container, listCommand string, entities ...string) bool { +func requireEntity(t *testing.T, container testcontainers.Container, listCommand string, entities ...string) { t.Helper() ctx := context.Background() cmd := []string{"rabbitmqadmin", "list", listCommand} - _, out, err := container.Exec(ctx, cmd) - require.NoError(t, err) - - check, err := io.ReadAll(out) - require.NoError(t, err) - + check := testcontainers.RequireContainerExec(ctx, t, container, cmd) for _, e := range entities { - if !strings.Contains(string(check), e) { - return false - } + require.Contains(t, check, e) } - - return true } -func assertEntityWithVHost(t *testing.T, container testcontainers.Container, listCommand string, vhostID int, entities ...string) bool { +func requireEntityWithVHost(t *testing.T, container testcontainers.Container, listCommand string, vhostID int, entities ...string) { t.Helper() ctx := context.Background() @@ -253,38 +243,22 @@ func assertEntityWithVHost(t *testing.T, container testcontainers.Container, lis cmd = append(cmd, fmt.Sprintf("--vhost=vhost%d", vhostID)) } - _, out, err := container.Exec(ctx, cmd) - require.NoError(t, err) - - check, err := io.ReadAll(out) - require.NoError(t, err) - + check := testcontainers.RequireContainerExec(ctx, t, container, cmd) for _, e := range entities { - if !strings.Contains(string(check), e) { - return false - } + require.Contains(t, check, e) } - - return true } -func assertPluginIsEnabled(t *testing.T, container testcontainers.Container, plugins ...string) bool { +func requirePluginIsEnabled(t *testing.T, container testcontainers.Container, plugins ...string) { t.Helper() ctx := context.Background() for _, plugin := range plugins { - _, out, err := container.Exec(ctx, []string{"rabbitmq-plugins", "is_enabled", plugin}) - require.NoError(t, err) - - check, err := io.ReadAll(out) - require.NoError(t, err) + cmd := []string{"rabbitmq-plugins", "is_enabled", plugin} - if !strings.Contains(string(check), plugin+" is enabled") { - return false - } + check := testcontainers.RequireContainerExec(ctx, t, container, cmd) + require.Contains(t, check, plugin+" is enabled") } - - return true } diff --git a/testing.go b/testing.go index 1670d7c059..35ce4f0a39 100644 --- a/testing.go +++ b/testing.go @@ -3,6 +3,7 @@ package testcontainers import ( "context" "fmt" + "io" "regexp" "testing" @@ -147,3 +148,18 @@ func isCleanupSafe(err error) bool { return false } } + +// RequireContainerExec is a helper function that executes a command in a container +// It insures that there is no error during the execution +// Finally returns the output of its execution +func RequireContainerExec(ctx context.Context, t *testing.T, container Container, cmd []string) string { + t.Helper() + + code, out, err := container.Exec(ctx, cmd) + require.NoError(t, err) + require.Zero(t, code) + + checkBytes, err := io.ReadAll(out) + require.NoError(t, err) + return string(checkBytes) +} From 3f2f0d06dd1f97b65b68a2dfd1450795de7d41e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 30 Oct 2024 13:44:39 +0100 Subject: [PATCH 109/126] docs(mysql|neo4j): remove default image codeblock (#2860) --- docs/modules/mysql.md | 6 ------ docs/modules/neo4j.md | 6 ------ 2 files changed, 12 deletions(-) diff --git a/docs/modules/mysql.md b/docs/modules/mysql.md index ca81ba3974..5ef38d56da 100644 --- a/docs/modules/mysql.md +++ b/docs/modules/mysql.md @@ -52,12 +52,6 @@ When starting the MySQL container, you can pass options in a variadic way to con If you need to set a different MySQL Docker image, you can set a valid Docker image as the second argument in the `Run` function. E.g. `Run(context.Background(), "mysql:8.0.36")`. -By default, the container will use the following Docker image: - - -[Default Docker image](../../modules/mysql/mysql.go) inside_block:defaultImage - - {% include "../features/common_functional_options.md" %} #### Set username, password and database name diff --git a/docs/modules/neo4j.md b/docs/modules/neo4j.md index 0431df12a1..e0188e015d 100644 --- a/docs/modules/neo4j.md +++ b/docs/modules/neo4j.md @@ -58,12 +58,6 @@ When starting the Neo4j container, you can pass options in a variadic way to con If you need to set a different Neo4j Docker image, you can set a valid Docker image as the second argument in the `Run` function. E.g. `Run(context.Background(), "neo4j:4.4")`. -By default, the container will use the following Docker image: - - -[Default Docker image](../../modules/neo4j/neo4j.go) inside_block:defaultImage - - {% include "../features/common_functional_options.md" %} #### Logger From a489482650fbd8305586ee01cfcf1ccd32cf4f7d Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 30 Oct 2024 16:54:19 +0000 Subject: [PATCH 110/126] fix: log test data race (#2863) Fix a data race when accessing logger in consumer test. --- logconsumer_test.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/logconsumer_test.go b/logconsumer_test.go index 900c8d8ae1..35fc98ae8a 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -503,12 +503,24 @@ func Test_StartLogProductionStillStartsWithTooHighTimeout(t *testing.T) { // bufLogger is a Logging implementation that writes to a bytes.Buffer. type bufLogger struct { - bytes.Buffer + mtx sync.Mutex + buf bytes.Buffer } // Printf implements Logging. func (l *bufLogger) Printf(format string, v ...any) { - fmt.Fprintf(l, format, v...) + l.mtx.Lock() + defer l.mtx.Unlock() + + fmt.Fprintf(&l.buf, format, v...) +} + +// String returns the contents of the buffer as a string. +func (l *bufLogger) String() string { + l.mtx.Lock() + defer l.mtx.Unlock() + + return l.buf.String() } func Test_MultiContainerLogConsumer_CancelledContext(t *testing.T) { From 606369dba87e03488eaa642a815c2fff17b73012 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 30 Oct 2024 19:23:55 +0000 Subject: [PATCH 111/126] chore: remove unused lint directives (#2864) Remove unused nonamedreturns directives as this linter was replaced by nakedret. --- docker.go | 6 +++--- modules/grafana-lgtm/examples_test.go | 2 +- port_forwarding.go | 2 +- reaper.go | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docker.go b/docker.go index 66ac42eda6..cb003c6630 100644 --- a/docker.go +++ b/docker.go @@ -1022,7 +1022,7 @@ func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (st } // CreateContainer fulfils a request for a container without starting it -func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerRequest) (con Container, err error) { //nolint:nonamedreturns // Needed for error checking. +func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerRequest) (con Container, err error) { // defer the close of the Docker client connection the soonest defer p.Close() @@ -1277,7 +1277,7 @@ func (p *DockerProvider) waitContainerCreation(ctx context.Context, name string) ) } -func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req ContainerRequest) (con Container, err error) { //nolint:nonamedreturns // Needed for error check. +func (p *DockerProvider) ReuseOrCreateContainer(ctx context.Context, req ContainerRequest) (con Container, err error) { c, err := p.findContainerByName(ctx, req.Name) if err != nil { return nil, err @@ -1486,7 +1486,7 @@ func (p *DockerProvider) daemonHostLocked(ctx context.Context) (string, error) { // Deprecated: use network.New instead // CreateNetwork returns the object representing a new network identified by its name -func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) (net Network, err error) { //nolint:nonamedreturns // Needed for error check. +func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest) (net Network, err error) { // defer the close of the Docker client connection the soonest defer p.Close() diff --git a/modules/grafana-lgtm/examples_test.go b/modules/grafana-lgtm/examples_test.go index 2510e07b1e..a3602b7685 100644 --- a/modules/grafana-lgtm/examples_test.go +++ b/modules/grafana-lgtm/examples_test.go @@ -104,7 +104,7 @@ func ExampleRun_otelCollector() { // setupOTelSDK bootstraps the OpenTelemetry pipeline. // If it does not return an error, make sure to call shutdown for proper cleanup. -func setupOTelSDK(ctx context.Context, ctr *grafanalgtm.GrafanaLGTMContainer) (shutdown func(context.Context) error, err error) { //nolint:nonamedreturns // this is a pattern in the OpenTelemetry Go SDK +func setupOTelSDK(ctx context.Context, ctr *grafanalgtm.GrafanaLGTMContainer) (shutdown func(context.Context) error, err error) { var shutdownFuncs []func(context.Context) error // shutdown calls cleanup functions registered via shutdownFuncs. diff --git a/port_forwarding.go b/port_forwarding.go index 88f14f2d72..ff7db9b465 100644 --- a/port_forwarding.go +++ b/port_forwarding.go @@ -38,7 +38,7 @@ var sshPassword = uuid.NewString() // 1. Create a new SSHD container. // 2. Expose the host ports to the container after the container is ready. // 3. Close the SSH sessions before killing the container. -func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) (sshdConnectHook ContainerLifecycleHooks, err error) { //nolint:nonamedreturns // Required for error check. +func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) (sshdConnectHook ContainerLifecycleHooks, err error) { if len(ports) == 0 { return sshdConnectHook, fmt.Errorf("no ports to expose") } diff --git a/reaper.go b/reaper.go index dfdcea5c5f..9987b9944a 100644 --- a/reaper.go +++ b/reaper.go @@ -277,7 +277,7 @@ func (r *reaperSpawner) reaper(ctx context.Context, sessionID string, provider R // If connect is true, the reaper will be connected to the reaper container. // It must be called with the lock held. func (r *reaperSpawner) retryLocked(ctx context.Context, sessionID string, provider ReaperProvider) func() (*Reaper, error) { - return func() (reaper *Reaper, err error) { //nolint:nonamedreturns // Needed for deferred error check. + return func() (reaper *Reaper, err error) { reaper, err = r.reuseOrCreate(ctx, sessionID, provider) // Ensure that the reaper is terminated if an error occurred. defer func() { @@ -372,7 +372,7 @@ func (r *reaperSpawner) fromContainer(ctx context.Context, sessionID string, pro // newReaper creates a connected Reaper with a sessionID to identify containers // and a provider to use. -func (r *reaperSpawner) newReaper(ctx context.Context, sessionID string, provider ReaperProvider) (reaper *Reaper, err error) { //nolint:nonamedreturns // Needed for deferred error check. +func (r *reaperSpawner) newReaper(ctx context.Context, sessionID string, provider ReaperProvider) (reaper *Reaper, err error) { dockerHostMount := core.MustExtractDockerSocket(ctx) port := r.port() From bed56328cd9e98593e093d8cfbd15ebfe8944507 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Thu, 31 Oct 2024 11:53:27 +0100 Subject: [PATCH 112/126] chore: use require instead of t.Fatal (part 2) (#2857) Signed-off-by: Matthieu MOREL --- lifecycle_test.go | 11 ++- logconsumer_test.go | 15 ++-- modules/chroma/chroma_test.go | 20 ++--- modules/compose/compose_builder_test.go | 26 +++---- modules/compose/compose_test.go | 39 +++------- modules/couchbase/couchbase_test.go | 16 +--- modules/elasticsearch/elasticsearch_test.go | 82 +++++++-------------- modules/influxdb/influxdb_test.go | 4 +- modules/neo4j/neo4j_test.go | 16 ++-- modules/rabbitmq/rabbitmq_test.go | 8 +- modules/weaviate/weaviate_test.go | 5 +- 11 files changed, 76 insertions(+), 166 deletions(-) diff --git a/lifecycle_test.go b/lifecycle_test.go index c683a4146c..0faefa8769 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -3,7 +3,9 @@ package testcontainers import ( "bufio" "context" + "errors" "fmt" + "io" "strings" "testing" "time" @@ -914,13 +916,10 @@ func TestPrintContainerLogsOnError(t *testing.T) { rd := bufio.NewReader(containerLogs) for { line, err := rd.ReadString('\n') - if err != nil { - if err.Error() == "EOF" { - break - } - - t.Fatal("Read Error:", err) + if errors.Is(err, io.EOF) { + break } + require.NoErrorf(t, err, "Read Error") // the last line of the array should contain the line of interest, // but we are checking all the lines to make sure that is present diff --git a/logconsumer_test.go b/logconsumer_test.go index 35fc98ae8a..dae1ea0b5a 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -323,9 +323,8 @@ func TestContainerLogWithErrClosed(t *testing.T) { 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") - } + require.NoError(t, err, "Can't make request to nginx container from dind container") + require.Zerof(t, i, "Can't make request to nginx container from dind container") } hitNginx() @@ -340,13 +339,11 @@ func TestContainerLogWithErrClosed(t *testing.T) { } // 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(%d), err %v", i, err) - } + require.NoErrorf(t, err, "Failed to close connection to dind daemon: i(%d), err %v", i, err) + require.Zerof(t, i, "Failed to close connection to dind daemon: i(%d), err %v", i, err) 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: i(%d), err %v", i, err) - } + require.NoErrorf(t, err, "Failed to re-open connection to dind daemon: i(%d), err %v", i, err) + require.Zerof(t, i, "Failed to re-open connection to dind daemon: i(%d), err %v", i, err) time.Sleep(time.Second * 3) hitNginx() diff --git a/modules/chroma/chroma_test.go b/modules/chroma/chroma_test.go index 5bf44b3282..5d975c3602 100644 --- a/modules/chroma/chroma_test.go +++ b/modules/chroma/chroma_test.go @@ -23,33 +23,23 @@ func TestChroma(t *testing.T) { // restEndpoint { restEndpoint, err := ctr.RESTEndpoint(ctx) // } - if err != nil { - tt.Fatalf("failed to get REST endpoint: %s", err) - } + require.NoErrorf(tt, err, "failed to get REST endpoint") cli := &http.Client{} resp, err := cli.Get(restEndpoint + "/docs") - if err != nil { - tt.Fatalf("failed to perform GET request: %s", err) - } + require.NoErrorf(tt, err, "failed to perform GET request") defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - tt.Fatalf("unexpected status code: %d", resp.StatusCode) - } + require.Equalf(tt, http.StatusOK, resp.StatusCode, "unexpected status code: %d", resp.StatusCode) }) t.Run("GetClient", func(tt *testing.T) { // restEndpoint { endpoint, err := ctr.RESTEndpoint(context.Background()) - if err != nil { - tt.Fatalf("failed to get REST endpoint: %s", err) - } + require.NoErrorf(tt, err, "failed to get REST endpoint") chromaClient, err := chromago.NewClient(endpoint) // } - if err != nil { - tt.Fatalf("failed to create client: %s", err) - } + require.NoErrorf(tt, err, "failed to create client") hb, err := chromaClient.Heartbeat(context.TODO()) require.NoError(tt, err) diff --git a/modules/compose/compose_builder_test.go b/modules/compose/compose_builder_test.go index 07b3c08aba..048bac241b 100644 --- a/modules/compose/compose_builder_test.go +++ b/modules/compose/compose_builder_test.go @@ -8,6 +8,8 @@ import ( "os" "path/filepath" "testing" + + "github.com/stretchr/testify/require" ) const ( @@ -121,14 +123,10 @@ func getFreePort(t *testing.T) int { t.Helper() addr, err := net.ResolveTCPAddr("tcp", "localhost:0") - if err != nil { - t.Fatalf("failed to resolve TCP address: %v", err) - } + require.NoErrorf(t, err, "failed to resolve TCP address") l, err := net.ListenTCP("tcp", addr) - if err != nil { - t.Fatalf("failed to listen on TCP address: %v", err) - } + require.NoErrorf(t, err, "failed to listen on TCP address") defer l.Close() return l.Addr().(*net.TCPAddr).Port @@ -146,9 +144,7 @@ func writeTemplateWithSrvType(t *testing.T, templateFile string, srvType string, composeFile := filepath.Join(tmpDir, "docker-compose.yml") tmpl, err := template.ParseFiles(filepath.Join(testdataPackage, templateFile)) - if err != nil { - t.Fatalf("parsing template file: %s", err) - } + require.NoErrorf(t, err, "parsing template file") values := map[string]interface{}{} for i, p := range port { @@ -158,19 +154,17 @@ func writeTemplateWithSrvType(t *testing.T, templateFile string, srvType string, values["ServiceType"] = srvType output, err := os.Create(composeFile) - if err != nil { - t.Fatalf("creating output file: %s", err) - } - defer output.Close() + require.NoErrorf(t, err, "creating output file") + defer func() { + require.NoError(t, output.Close()) + }() executeTemplateFile := func(templateFile *template.Template, wr io.Writer, data any) error { return templateFile.Execute(wr, data) } err = executeTemplateFile(tmpl, output, values) - if err != nil { - t.Fatalf("executing template file: %s", err) - } + require.NoErrorf(t, err, "executing template file") return composeFile } diff --git a/modules/compose/compose_test.go b/modules/compose/compose_test.go index 39f502fcf3..24c0c6c635 100644 --- a/modules/compose/compose_test.go +++ b/modules/compose/compose_test.go @@ -448,22 +448,16 @@ func TestLocalDockerComposeWithVolume(t *testing.T) { func assertVolumeDoesNotExist(tb testing.TB, volumeName string) { tb.Helper() containerClient, err := testcontainers.NewDockerClientWithOpts(context.Background()) - if err != nil { - tb.Fatalf("Failed to get provider: %v", err) - } + require.NoErrorf(tb, err, "Failed to get provider") volumeList, err := containerClient.VolumeList(context.Background(), volume.ListOptions{Filters: filters.NewArgs(filters.Arg("name", volumeName))}) - if err != nil { - tb.Fatalf("Failed to list volumes: %v", err) - } + require.NoErrorf(tb, err, "Failed to list volumes") if len(volumeList.Warnings) > 0 { tb.Logf("Volume list warnings: %v", volumeList.Warnings) } - if len(volumeList.Volumes) > 0 { - tb.Fatalf("Volume list is not empty") - } + require.Emptyf(tb, volumeList.Volumes, "Volume list is not empty") } func assertContainerEnvironmentVariables( @@ -474,16 +468,11 @@ func assertContainerEnvironmentVariables( ) { tb.Helper() containerClient, err := testcontainers.NewDockerClientWithOpts(context.Background()) - if err != nil { - tb.Fatalf("Failed to get provider: %v", err) - } + require.NoErrorf(tb, err, "Failed to get provider") containers, err := containerClient.ContainerList(context.Background(), container.ListOptions{}) - if err != nil { - tb.Fatalf("Failed to list containers: %v", err) - } else if len(containers) == 0 { - tb.Fatalf("container list empty") - } + require.NoErrorf(tb, err, "Failed to list containers") + require.NotEmptyf(tb, containers, "container list empty") containerNameRegexp := regexp.MustCompile(fmt.Sprintf(`^\/?%s(_|-)%s(_|-)\d$`, composeIdentifier, serviceName)) var containerID string @@ -499,9 +488,7 @@ containerLoop: } details, err := containerClient.ContainerInspect(context.Background(), containerID) - if err != nil { - tb.Fatalf("Failed to inspect container: %v", err) - } + require.NoErrorf(tb, err, "Failed to inspect container") for k, v := range present { keyVal := k + "=" + v @@ -516,17 +503,11 @@ containerLoop: func checkIfError(t *testing.T, err ExecError) { t.Helper() - if err.Error != nil { - t.Fatalf("Failed when running %v: %v", err.Command, err.Error) - } + require.NoErrorf(t, err.Error, "Failed when running %v", err.Command) - if err.Stdout != nil { - t.Fatalf("An error in Stdout happened when running %v: %v", err.Command, err.Stdout) - } + require.NoErrorf(t, err.Stdout, "An error in Stdout happened when running %v", err.Command) - if err.Stderr != nil { - t.Fatalf("An error in Stderr happened when running %v: %v", err.Command, err.Stderr) - } + require.NoErrorf(t, err.Stderr, "An error in Stderr happened when running %v", err.Command) assert.NotNil(t, err.StdoutOutput) assert.NotNil(t, err.StderrOutput) diff --git a/modules/couchbase/couchbase_test.go b/modules/couchbase/couchbase_test.go index 4e6330e24d..2e2122e01b 100644 --- a/modules/couchbase/couchbase_test.go +++ b/modules/couchbase/couchbase_test.go @@ -115,29 +115,21 @@ func TestEventingServiceWithCommunityContainer(t *testing.T) { func testBucketUsage(t *testing.T, bucket *gocb.Bucket) { t.Helper() err := bucket.WaitUntilReady(5*time.Second, nil) - if err != nil { - t.Fatalf("could not connect bucket: %s", err) - } + require.NoErrorf(t, err, "could not connect bucket") key := "foo" data := map[string]string{"key": "value"} collection := bucket.DefaultCollection() _, err = collection.Upsert(key, data, nil) - if err != nil { - t.Fatalf("could not upsert data: %s", err) - } + require.NoErrorf(t, err, "could not upsert data") result, err := collection.Get(key, nil) - if err != nil { - t.Fatalf("could not get data: %s", err) - } + require.NoErrorf(t, err, "could not get data") var resultData map[string]string err = result.Content(&resultData) - if err != nil { - t.Fatalf("could not assign content: %s", err) - } + require.NoErrorf(t, err, "could not assign content") if resultData["key"] != "value" { t.Errorf("Expected value to be [%s], got %s", "value", resultData["key"]) diff --git a/modules/elasticsearch/elasticsearch_test.go b/modules/elasticsearch/elasticsearch_test.go index 99829e94d3..14c5640e72 100644 --- a/modules/elasticsearch/elasticsearch_test.go +++ b/modules/elasticsearch/elasticsearch_test.go @@ -92,9 +92,7 @@ func TestElasticsearch(t *testing.T) { // set the password for the request using the Authentication header if tt.passwordCustomiser != nil { - if esContainer.Settings.Username != "elastic" { - t.Fatal("expected username to be elastic but got", esContainer.Settings.Username) - } + require.Equalf(t, "elastic", esContainer.Settings.Username, "expected username to be elastic but got: %s", esContainer.Settings.Username) // basicAuthHeader { req.SetBasicAuth(esContainer.Settings.Username, esContainer.Settings.Password) @@ -102,55 +100,33 @@ func TestElasticsearch(t *testing.T) { } resp, err := httpClient.Do(req) - if resp != nil { - defer resp.Body.Close() - } + require.NoError(t, err) + require.NotNil(t, resp) + defer resp.Body.Close() + + if tt.image == baseImage8 && tt.passwordCustomiser == nil { + // Elasticsearch 8 should return 401 Unauthorized, not an error in the request + require.Equalf(t, http.StatusUnauthorized, resp.StatusCode, "expected 401 status code for unauthorised HTTP client using TLS, but got: %s", resp.StatusCode) - if tt.image != baseImage8 && err != nil { - if tt.passwordCustomiser != nil { - t.Fatal(err, "should access with authorised HTTP client.") - } else if tt.passwordCustomiser == nil { - t.Fatal(err, "should access with unauthorised HTTP client.") - } + // finish validating the response when the request is unauthorised + return } - if tt.image == baseImage8 { - if tt.passwordCustomiser != nil && err != nil { - t.Fatal(err, "should access with authorised HTTP client using TLS.") - } - if tt.passwordCustomiser == nil && err == nil { - // Elasticsearch 8 should return 401 Unauthorized, not an error in the request - if resp.StatusCode != http.StatusUnauthorized { - t.Fatal("expected 401 status code for unauthorised HTTP client using TLS, but got", resp.StatusCode) - } + // validate Elasticsearch response + require.Equalf(t, http.StatusOK, resp.StatusCode, "expected 200 status code but got: %s", resp.StatusCode) - // finish validating the response when the request is unauthorised - return - } + var esResp ElasticsearchResponse + err = json.NewDecoder(resp.Body).Decode(&esResp) + require.NoError(t, err) + switch tt.image { + case baseImage7: + require.Equalf(t, "7.9.2", esResp.Version.Number, "expected version to be 7.9.2 but got: %s", esResp.Version.Number) + case baseImage8: + require.Equalf(t, "8.9.0", esResp.Version.Number, "expected version to be 8.9.0 but got: %s", esResp.Version.Number) } - // validate response - if resp != nil { - // validate Elasticsearch response - if resp.StatusCode != http.StatusOK { - t.Fatal("expected 200 status code but got", resp.StatusCode) - } - - var esResp ElasticsearchResponse - err = json.NewDecoder(resp.Body).Decode(&esResp) - require.NoError(t, err) - - if tt.image == baseImage7 && esResp.Version.Number != "7.9.2" { - t.Fatal("expected version to be 7.9.2 but got", esResp.Version.Number) - } else if tt.image == baseImage8 && esResp.Version.Number != "8.9.0" { - t.Fatal("expected version to be 8.9.0 but got", esResp.Version.Number) - } - - if esResp.Tagline != "You Know, for Search" { - t.Fatal("expected tagline to be 'You Know, for Search' but got", esResp.Tagline) - } - } + require.Equalf(t, "You Know, for Search", esResp.Tagline, "expected tagline to be 'You Know, for Search' but got: %s", esResp.Tagline) }) } } @@ -185,9 +161,7 @@ func TestElasticsearch8WithoutSSL(t *testing.T) { testcontainers.CleanupContainer(t, ctr) require.NoError(t, err) - if len(ctr.Settings.CACert) > 0 { - t.Fatal("expected CA cert to be empty") - } + require.Emptyf(t, ctr.Settings.CACert, "expected CA cert to be empty") }) } } @@ -208,9 +182,7 @@ func TestElasticsearch8WithoutCredentials(t *testing.T) { req.SetBasicAuth(ctr.Settings.Username, ctr.Settings.Password) resp, err := httpClient.Do(req) - if err != nil { - t.Fatal(err, "Should be able to access / URI with client using default password over HTTPS.") - } + require.NoErrorf(t, err, "Should be able to access / URI with client using default password over HTTPS.") defer resp.Body.Close() @@ -218,9 +190,7 @@ func TestElasticsearch8WithoutCredentials(t *testing.T) { err = json.NewDecoder(resp.Body).Decode(&esResp) require.NoError(t, err) - if esResp.Tagline != "You Know, for Search" { - t.Fatal("expected tagline to be 'You Know, for Search' but got", esResp.Tagline) - } + require.Equalf(t, "You Know, for Search", esResp.Tagline, "expected tagline to be 'You Know, for Search' but got: %s", esResp.Tagline) } func TestElasticsearchOSSCannotuseWithPassword(t *testing.T) { @@ -230,9 +200,7 @@ func TestElasticsearchOSSCannotuseWithPassword(t *testing.T) { ctr, err := elasticsearch.Run(ctx, ossImage, elasticsearch.WithPassword("foo")) testcontainers.CleanupContainer(t, ctr) - if err == nil { - t.Fatal(err, "Should not be able to use WithPassword with OSS image.") - } + require.Errorf(t, err, "Should not be able to use WithPassword with OSS image.") } // configureHTTPClient configures an HTTP client for the Elasticsearch container. diff --git a/modules/influxdb/influxdb_test.go b/modules/influxdb/influxdb_test.go index 08d9a72126..3c4379c66c 100644 --- a/modules/influxdb/influxdb_test.go +++ b/modules/influxdb/influxdb_test.go @@ -24,9 +24,7 @@ func TestV1Container(t *testing.T) { state, err := influxDbContainer.State(ctx) require.NoError(t, err) - if !state.Running { - t.Fatal("InfluxDB container is not running") - } + require.Truef(t, state.Running, "InfluxDB container is not running") } func TestV2Container(t *testing.T) { diff --git a/modules/neo4j/neo4j_test.go b/modules/neo4j/neo4j_test.go index 5918b7dc31..84272c93e9 100644 --- a/modules/neo4j/neo4j_test.go +++ b/modules/neo4j/neo4j_test.go @@ -39,9 +39,9 @@ func TestNeo4j(outer *testing.T) { "RETURN apoc.number.arabicToRoman(1986) AS output", nil, neo.EagerResultTransformer) require.NoErrorf(t, err, "expected APOC query to successfully run but did not") - if value, _ := result.Records[0].Get("output"); value != "MCMLXXXVI" { - t.Fatalf("did not get expected roman number: %s", value) - } + require.NotEmpty(t, result.Records) + value, _ := result.Records[0].Get("output") + require.Equalf(t, "MCMLXXXVI", value, "did not get expected roman number: %s", value) }) outer.Run("is configured with custom Neo4j settings", func(t *testing.T) { @@ -118,10 +118,8 @@ func TestNeo4jWithWrongSettings(outer *testing.T) { require.NoError(t, err) errorLogs := logger.Logs() - if !Contains(errorLogs, `setting "some.key" with value "value1" is now overwritten with value "value2"`+"\n") || - !Contains(errorLogs, `setting "some.key" with value "value2" is now overwritten with value "value3"`+"\n") { - t.Fatalf("expected setting overwrites to be logged") - } + require.Containsf(t, errorLogs, `setting "some.key" with value "value1" is now overwritten with value "value2"`+"\n", "expected setting overwrites to be logged") + require.Containsf(t, errorLogs, `setting "some.key" with value "value2" is now overwritten with value "value3"`+"\n", "expected setting overwrites to be logged") require.Containsf(t, getContainerEnv(t, ctx, ctr), "NEO4J_some_key=value3", "expected custom setting to be set with last value") }) @@ -129,9 +127,7 @@ func TestNeo4jWithWrongSettings(outer *testing.T) { ctr, err := neo4j.Run(ctx, "neo4j:4.4", neo4j.WithLogger(nil)) testcontainers.CleanupContainer(t, ctr) require.Nilf(t, ctr, "container must not be created with nil logger") - if err == nil || err.Error() != "nil logger is not permitted" { - t.Fatalf("expected config validation error but got no error") - } + require.EqualErrorf(t, err, "nil logger is not permitted", "expected config validation error but got no error") }) } diff --git a/modules/rabbitmq/rabbitmq_test.go b/modules/rabbitmq/rabbitmq_test.go index 1e05b8f3aa..1cdd7e9137 100644 --- a/modules/rabbitmq/rabbitmq_test.go +++ b/modules/rabbitmq/rabbitmq_test.go @@ -72,9 +72,7 @@ func TestRunContainer_connectUsingAmqps(t *testing.T) { amqpsURL, err := rabbitmqContainer.AmqpsURL(ctx) require.NoError(t, err) - if !strings.HasPrefix(amqpsURL, "amqps") { - t.Fatal(fmt.Errorf("AMQPS Url should begin with `amqps`")) - } + require.Truef(t, strings.HasPrefix(amqpsURL, "amqps"), "AMQPS Url should begin with `amqps`") certs := x509.NewCertPool() @@ -85,9 +83,7 @@ func TestRunContainer_connectUsingAmqps(t *testing.T) { amqpsConnection, err := amqp.DialTLS(amqpsURL, &tls.Config{InsecureSkipVerify: false, RootCAs: certs}) require.NoError(t, err) - if amqpsConnection.IsClosed() { - t.Fatal(fmt.Errorf("AMQPS Connection unexpectdely closed")) - } + require.Falsef(t, amqpsConnection.IsClosed(), "AMQPS Connection unexpectdely closed") err = amqpsConnection.Close() require.NoError(t, err) } diff --git a/modules/weaviate/weaviate_test.go b/modules/weaviate/weaviate_test.go index f1d6de3eeb..c85a25726c 100644 --- a/modules/weaviate/weaviate_test.go +++ b/modules/weaviate/weaviate_test.go @@ -66,8 +66,7 @@ func TestWeaviate(t *testing.T) { meta, err := client.Misc().MetaGetter().Do(ctx) require.NoError(tt, err) - if meta == nil || meta.Version == "" { - tt.Fatal("failed to get /v1/meta response") - } + require.NotNilf(tt, meta, "failed to get /v1/meta response") + require.NotEmptyf(tt, meta.Version, "failed to get /v1/meta response") }) } From 72a3f1f8ec182f2b50ed3f53f42a04c26fe006f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Thu, 31 Oct 2024 13:05:17 +0000 Subject: [PATCH 113/126] feat(ci): Test against the nightly master moby (#2861) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rootless is not supported yet. Signed-off-by: Paweł Gronowski --- .github/workflows/docker-moby-latest.yml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker-moby-latest.yml b/.github/workflows/docker-moby-latest.yml index 39cb96df3d..6c11df2af2 100644 --- a/.github/workflows/docker-moby-latest.yml +++ b/.github/workflows/docker-moby-latest.yml @@ -10,6 +10,12 @@ jobs: strategy: matrix: rootless-docker: [true, false] + containerd-integration: [true, false] + # ghaction-setup-docker doesn't work with rootless yet + exclude: + - rootless-docker: true + container-integration: true + name: "Core tests using latest moby/moby" runs-on: 'ubuntu-latest' continue-on-error: true @@ -42,7 +48,22 @@ jobs: - name: modTidy run: go mod tidy - - name: Install Latest Docker + - name: Install Nightly Docker + # rootless not supported with ghaction-setup-docker yet + if: ${{ matrix.rootless-docker == false }} + uses: crazy-max/ghaction-setup-docker@master + with: + daemon-config: | + { + "debug": true, + "features": { + "containerd-snapshotter": ${{ matrix.containerd-integration }} + } + } + version: type=image,tag=master + + - name: Install test Docker + if: ${{ matrix.rootless-docker }} run: curl https://get.docker.com | CHANNEL=test sh - name: go test From 47764d4bb3684a3b0cafea1fddbc9226e7350288 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Thu, 31 Oct 2024 15:32:48 +0000 Subject: [PATCH 114/126] fix: docker auth for identity tokens (#2866) Fix docker authentication look up so it supports the case where the username is blank which means that the second returned value is an identity token not a password. --- docker_auth.go | 50 +++++++++++++++++++++-------------- docker_auth_test.go | 64 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 88 insertions(+), 26 deletions(-) diff --git a/docker_auth.go b/docker_auth.go index af0d415de9..58b3ef2637 100644 --- a/docker_auth.go +++ b/docker_auth.go @@ -21,6 +21,9 @@ import ( // defaultRegistryFn is variable overwritten in tests to check for behaviour with different default values. var defaultRegistryFn = defaultRegistry +// getRegistryCredentials is a variable overwritten in tests to mock the dockercfg.GetRegistryCredentials function. +var getRegistryCredentials = dockercfg.GetRegistryCredentials + // DockerImageAuth returns the auth config for the given Docker image, extracting first its Docker registry. // Finally, it will use the credential helpers to extract the information from the docker config file // for that registry, if it exists. @@ -111,9 +114,28 @@ type credentials struct { var creds = &credentialsCache{entries: map[string]credentials{}} -// Get returns the username and password for the given hostname +// AuthConfig updates the details in authConfig for the given hostname +// as determined by the details in configKey. +func (c *credentialsCache) AuthConfig(hostname, configKey string, authConfig *registry.AuthConfig) error { + u, p, err := creds.get(hostname, configKey) + if err != nil { + return err + } + + if u != "" { + authConfig.Username = u + authConfig.Password = p + } else { + authConfig.IdentityToken = p + } + + return nil +} + +// get returns the username and password for the given hostname // as determined by the details in configPath. -func (c *credentialsCache) Get(hostname, configKey string) (string, string, error) { +// If the username is empty, the password is an identity token. +func (c *credentialsCache) get(hostname, configKey string) (string, string, error) { key := configKey + ":" + hostname c.mtx.RLock() entry, ok := c.entries[key] @@ -124,7 +146,7 @@ func (c *credentialsCache) Get(hostname, configKey string) (string, string, erro } // No entry found, request and cache. - user, password, err := dockercfg.GetRegistryCredentials(hostname) + user, password, err := getRegistryCredentials(hostname) if err != nil { return "", "", fmt.Errorf("getting credentials for %s: %w", hostname, err) } @@ -186,14 +208,10 @@ func getDockerAuthConfigs() (map[string]registry.AuthConfig, error) { switch { case ac.Username == "" && ac.Password == "": // Look up credentials from the credential store. - u, p, err := creds.Get(k, key) - if err != nil { + if err := creds.AuthConfig(k, key, &ac); err != nil { results <- authConfigResult{err: err} return } - - ac.Username = u - ac.Password = p case ac.Auth == "": // Create auth from the username and password encoding. ac.Auth = base64.StdEncoding.EncodeToString([]byte(ac.Username + ":" + ac.Password)) @@ -203,25 +221,19 @@ func getDockerAuthConfigs() (map[string]registry.AuthConfig, error) { }(k, v) } - // in the case where the auth field in the .docker/conf.json is empty, and the user has credential helpers registered - // the auth comes from there + // In the case where the auth field in the .docker/conf.json is empty, and the user has + // credential helpers registered the auth comes from there. for k := range cfg.CredentialHelpers { go func(k string) { defer wg.Done() - u, p, err := creds.Get(k, key) - if err != nil { + var ac registry.AuthConfig + if err := creds.AuthConfig(k, key, &ac); err != nil { results <- authConfigResult{err: err} return } - results <- authConfigResult{ - key: k, - cfg: registry.AuthConfig{ - Username: u, - Password: p, - }, - } + results <- authConfigResult{key: k, cfg: ac} }(k) } diff --git a/docker_auth_test.go b/docker_auth_test.go index 22c86783a2..8f18a62d9d 100644 --- a/docker_auth_test.go +++ b/docker_auth_test.go @@ -20,14 +20,18 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) -const exampleAuth = "https://example-auth.com" +const ( + exampleAuth = "https://example-auth.com" + privateRegistry = "https://my.private.registry" + exampleRegistry = "https://example.com" +) func Test_getDockerConfig(t *testing.T) { expectedConfig := &dockercfg.Config{ AuthConfigs: map[string]dockercfg.AuthConfig{ - core.IndexDockerIO: {}, - "https://example.com": {}, - "https://my.private.registry": {}, + core.IndexDockerIO: {}, + exampleRegistry: {}, + privateRegistry: {}, }, CredentialsStore: "desktop", } @@ -378,6 +382,13 @@ func localAddress(t *testing.T) string { //go:embed testdata/.docker/config.json var dockerConfig string +// reset resets the credentials cache. +func (c *credentialsCache) reset() { + c.mtx.Lock() + defer c.mtx.Unlock() + c.entries = make(map[string]credentials) +} + func Test_getDockerAuthConfigs(t *testing.T) { t.Run("HOME/valid", func(t *testing.T) { testDockerConfigHome(t, "testdata") @@ -418,6 +429,45 @@ func Test_getDockerAuthConfigs(t *testing.T) { require.Nil(t, authConfigs) }) + t.Run("DOCKER_AUTH_CONFIG/identity-token", func(t *testing.T) { + testDockerConfigHome(t, "testdata", "not-exist") + + // Reset the credentials cache to ensure our mocked method is called. + creds.reset() + + // Mock getRegistryCredentials to return identity-token for index.docker.io. + old := getRegistryCredentials + t.Cleanup(func() { + getRegistryCredentials = old + creds.reset() // Ensure our mocked results aren't cached. + }) + getRegistryCredentials = func(hostname string) (string, string, error) { + switch hostname { + case core.IndexDockerIO: + return "", "identity-token", nil + default: + return "username", "password", nil + } + } + t.Setenv("DOCKER_AUTH_CONFIG", dockerConfig) + + authConfigs, err := getDockerAuthConfigs() + require.NoError(t, err) + require.Equal(t, map[string]registry.AuthConfig{ + core.IndexDockerIO: { + IdentityToken: "identity-token", + }, + privateRegistry: { + Username: "username", + Password: "password", + }, + exampleRegistry: { + Username: "username", + Password: "password", + }, + }, authConfigs) + }) + t.Run("DOCKER_CONFIG/valid", func(t *testing.T) { testDockerConfigHome(t, "testdata", "not-found") t.Setenv("DOCKER_CONFIG", filepath.Join("testdata", ".docker")) @@ -445,9 +495,9 @@ func requireValidAuthConfig(t *testing.T) { // We can only check the keys as the values are not deterministic as they depend // on users environment. expected := map[string]registry.AuthConfig{ - "https://index.docker.io/v1/": {}, - "https://example.com": {}, - "https://my.private.registry": {}, + core.IndexDockerIO: {}, + exampleRegistry: {}, + privateRegistry: {}, } for k := range authConfigs { authConfigs[k] = registry.AuthConfig{} From 8283ba8cedf93d5c6a2dab7494bb499f8ace3167 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 16:34:51 +0000 Subject: [PATCH 115/126] chore(deps): bump golangci/golangci-lint-action from 6.1.0 to 6.1.1 (#2868) Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.1.0 to 6.1.1. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/aaa42aa0628b4ae2578232a66b541047968fac86...971e284b6050e8a5849b72094c50ab08da042db8) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-test-go.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-test-go.yml b/.github/workflows/ci-test-go.yml index badbed8b72..a76df75d4d 100644 --- a/.github/workflows/ci-test-go.yml +++ b/.github/workflows/ci-test-go.yml @@ -73,7 +73,7 @@ jobs: - name: golangci-lint if: ${{ inputs.platform == 'ubuntu-latest' }} - uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0 + uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version version: v1.61.0 From ffcb8b642f7e428fcaf6b00feda694d13f8cf327 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Sat, 2 Nov 2024 13:47:06 +0100 Subject: [PATCH 116/126] chore: use testcontainers.RequireContainerExec (#2870) Use testcontainers.RequireContainerExec to simplify tests. Signed-off-by: Matthieu MOREL --- modules/kafka/kafka_test.go | 13 ++++--------- modules/neo4j/neo4j_test.go | 8 +------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/modules/kafka/kafka_test.go b/modules/kafka/kafka_test.go index 763f29e3e0..af858f849f 100644 --- a/modules/kafka/kafka_test.go +++ b/modules/kafka/kafka_test.go @@ -2,7 +2,6 @@ package kafka_test import ( "context" - "io" "strings" "testing" @@ -82,15 +81,11 @@ func assertAdvertisedListeners(t *testing.T, container testcontainers.Container) inspect, err := container.Inspect(context.Background()) require.NoError(t, err) - hostname := inspect.Config.Hostname + brokerURL := "BROKER://" + inspect.Config.Hostname + ":9092" - code, r, err := container.Exec(context.Background(), []string{"cat", "/usr/sbin/testcontainers_start.sh"}) - require.NoError(t, err) - - require.Zero(t, code) + ctx := context.Background() - bs, err := io.ReadAll(r) - require.NoError(t, err) + bs := testcontainers.RequireContainerExec(ctx, t, container, []string{"cat", "/usr/sbin/testcontainers_start.sh"}) - require.Containsf(t, string(bs), "BROKER://"+hostname+":9092", "expected advertised listeners to contain %s, got %s", "BROKER://"+hostname+":9092", string(bs)) + require.Containsf(t, bs, brokerURL, "expected advertised listeners to contain %s, got %s", brokerURL, bs) } diff --git a/modules/neo4j/neo4j_test.go b/modules/neo4j/neo4j_test.go index 84272c93e9..51a01817ce 100644 --- a/modules/neo4j/neo4j_test.go +++ b/modules/neo4j/neo4j_test.go @@ -3,7 +3,6 @@ package neo4j_test import ( "context" "fmt" - "io" "strings" "testing" @@ -159,12 +158,7 @@ func createDriver(t *testing.T, ctx context.Context, container *neo4j.Neo4jConta func getContainerEnv(t *testing.T, ctx context.Context, container *neo4j.Neo4jContainer) string { t.Helper() - exec, reader, err := container.Exec(ctx, []string{"env"}) - require.NoErrorf(t, err, "expected env to successfully run but did not") - require.Zerof(t, exec, "expected env to exit with status 0 but exited with: %d", exec) - envVars, err := io.ReadAll(reader) - require.NoErrorf(t, err, "expected to read all bytes from env output but did not") - return string(envVars) + return testcontainers.RequireContainerExec(ctx, t, container, []string{"env"}) } const logSeparator = "---$$$---" From 1819e7099e56a9e89c3a63be295c88a2052393e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Nov 2024 15:13:30 +0000 Subject: [PATCH 117/126] chore(deps): bump mkdocs-markdownextradata-plugin from 0.2.5 to 0.2.6 (#2807) Bumps [mkdocs-markdownextradata-plugin](https://github.com/rosscdh/mkdocs-markdownextradata-plugin) from 0.2.5 to 0.2.6. - [Release notes](https://github.com/rosscdh/mkdocs-markdownextradata-plugin/releases) - [Commits](https://github.com/rosscdh/mkdocs-markdownextradata-plugin/compare/0.2.5...0.2.6) --- updated-dependencies: - dependency-name: mkdocs-markdownextradata-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Steven Hartland --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 83689b0f87..44a81bdecf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,4 @@ mkdocs==1.5.3 mkdocs-codeinclude-plugin==0.2.1 mkdocs-include-markdown-plugin==6.0.4 mkdocs-material==9.5.18 -mkdocs-markdownextradata-plugin==0.2.5 +mkdocs-markdownextradata-plugin==0.2.6 From cc5a516f1766e48b9595bdc50d076387c86ceef7 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Sat, 2 Nov 2024 17:33:12 +0100 Subject: [PATCH 118/126] ci: enable perfsprint linter (#2872) Enable perfsprint linter for golangci-lint Signed-off-by: Matthieu MOREL Co-authored-by: Steven Hartland --- .golangci.yml | 1 + docker.go | 2 +- docker_auth_test.go | 4 +-- file_test.go | 3 ++- internal/core/bootstrap.go | 3 ++- internal/core/docker_host_test.go | 4 +-- internal/core/docker_rootless.go | 4 +-- internal/core/docker_rootless_test.go | 6 ++--- modules/chroma/chroma.go | 3 ++- modules/cockroachdb/certs.go | 8 +++--- modules/cockroachdb/cockroachdb.go | 5 ++-- modules/compose/compose_api_test.go | 6 ++--- modules/dolt/dolt.go | 3 ++- modules/elasticsearch/elasticsearch.go | 3 ++- modules/elasticsearch/version.go | 2 +- modules/gcloud/spanner_test.go | 2 +- modules/inbucket/inbucket.go | 2 +- modules/k3s/k3s.go | 2 +- modules/k6/k6.go | 2 +- modules/kafka/kafka.go | 8 +++--- modules/localstack/localstack.go | 6 ++--- modules/localstack/localstack_test.go | 5 ++-- modules/mariadb/mariadb.go | 3 ++- modules/meilisearch/meilisearch.go | 2 +- modules/minio/minio.go | 3 ++- modules/mongodb/mongodb.go | 3 ++- modules/mysql/mysql.go | 3 ++- modules/neo4j/config.go | 4 +-- modules/neo4j/neo4j.go | 6 ++--- modules/ollama/examples_test.go | 2 +- modules/openfga/openfga.go | 2 +- modules/openldap/openldap.go | 2 +- modules/postgres/postgres.go | 3 ++- modules/qdrant/qdrant.go | 5 ++-- modules/rabbitmq/types_test.go | 34 +++++++++++++------------- modules/redis/redis.go | 3 ++- modules/redpanda/redpanda.go | 7 +++--- modules/redpanda/redpanda_test.go | 16 ++++++------ modules/registry/registry.go | 3 ++- modules/valkey/valkey.go | 3 ++- modules/vearch/vearch.go | 3 ++- modules/weaviate/examples_test.go | 4 +-- modules/weaviate/weaviate.go | 5 ++-- port_forwarding.go | 4 +-- reaper.go | 2 +- wait/all.go | 4 +-- wait/host_port.go | 2 +- 47 files changed, 116 insertions(+), 96 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index b8391990ac..d708f003e3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,6 +8,7 @@ linters: - misspell - nolintlint - nakedret + - perfsprint - testifylint - thelper - usestdlibvars diff --git a/docker.go b/docker.go index cb003c6630..2063f92fc8 100644 --- a/docker.go +++ b/docker.go @@ -152,7 +152,7 @@ func (c *DockerContainer) PortEndpoint(ctx context.Context, port nat.Port, proto protoFull := "" if proto != "" { - protoFull = fmt.Sprintf("%s://", proto) + protoFull = proto + "://" } return fmt.Sprintf("%s%s:%s", protoFull, host, outerPort.Port()), nil diff --git a/docker_auth_test.go b/docker_auth_test.go index 8f18a62d9d..5d397d53c8 100644 --- a/docker_auth_test.go +++ b/docker_auth_test.go @@ -284,11 +284,11 @@ func prepareLocalRegistryWithAuth(t *testing.T) string { }, Files: []ContainerFile{ { - HostFilePath: fmt.Sprintf("%s/testdata/auth", wd), + HostFilePath: wd + "/testdata/auth", ContainerFilePath: "/auth", }, { - HostFilePath: fmt.Sprintf("%s/testdata/data", wd), + HostFilePath: wd + "/testdata/data", ContainerFilePath: "/data", }, }, diff --git a/file_test.go b/file_test.go index 06ef8905e7..edf12af3b3 100644 --- a/file_test.go +++ b/file_test.go @@ -6,6 +6,7 @@ import ( "archive/tar" "bytes" "compress/gzip" + "errors" "fmt" "io" "os" @@ -37,7 +38,7 @@ func Test_IsDir(t *testing.T) { { filepath: "foobar.doc", expected: false, - err: fmt.Errorf("does not exist"), + err: errors.New("does not exist"), }, } diff --git a/internal/core/bootstrap.go b/internal/core/bootstrap.go index cf06dde7e2..1c45297704 100644 --- a/internal/core/bootstrap.go +++ b/internal/core/bootstrap.go @@ -2,6 +2,7 @@ package core import ( "crypto/sha256" + "encoding/hex" "fmt" "os" @@ -89,7 +90,7 @@ func init() { return } - sessionID = fmt.Sprintf("%x", hasher.Sum(nil)) + sessionID = hex.EncodeToString(hasher.Sum(nil)) } func ProcessID() string { diff --git a/internal/core/docker_host_test.go b/internal/core/docker_host_test.go index 00b2dfa2ff..41ce4f25e5 100644 --- a/internal/core/docker_host_test.go +++ b/internal/core/docker_host_test.go @@ -2,7 +2,7 @@ package core import ( "context" - "fmt" + "errors" "os" "path/filepath" "testing" @@ -46,7 +46,7 @@ func testCallbackCheckPassing(_ context.Context, _ string) error { } func testCallbackCheckError(_ context.Context, _ string) error { - return fmt.Errorf("could not check the Docker host") + return errors.New("could not check the Docker host") } func mockCallbackCheck(t *testing.T, fn func(_ context.Context, _ string) error) { diff --git a/internal/core/docker_rootless.go b/internal/core/docker_rootless.go index b8e0f6e17e..70cdebf240 100644 --- a/internal/core/docker_rootless.go +++ b/internal/core/docker_rootless.go @@ -3,11 +3,11 @@ package core import ( "context" "errors" - "fmt" "net/url" "os" "path/filepath" "runtime" + "strconv" ) var ( @@ -144,7 +144,7 @@ func rootlessSocketPathFromHomeDesktopDir() (string, error) { // rootlessSocketPathFromRunDir returns the path to the rootless Docker socket from the /run/user//docker.sock file. func rootlessSocketPathFromRunDir() (string, error) { uid := os.Getuid() - f := filepath.Join(baseRunDir, "user", fmt.Sprintf("%d", uid), "docker.sock") + f := filepath.Join(baseRunDir, "user", strconv.Itoa(uid), "docker.sock") if fileExists(f) { return f, nil } diff --git a/internal/core/docker_rootless_test.go b/internal/core/docker_rootless_test.go index 40bfb948b5..d6a338acdb 100644 --- a/internal/core/docker_rootless_test.go +++ b/internal/core/docker_rootless_test.go @@ -2,9 +2,9 @@ package core import ( "context" - "fmt" "os" "path/filepath" + "strconv" "testing" "github.com/stretchr/testify/assert" @@ -161,7 +161,7 @@ func TestRootlessDockerSocketPath(t *testing.T) { }) uid := os.Getuid() - runDir := filepath.Join(tmpDir, "user", fmt.Sprintf("%d", uid)) + runDir := filepath.Join(tmpDir, "user", strconv.Itoa(uid)) err = createTmpDockerSocket(runDir) require.NoError(t, err) @@ -208,7 +208,7 @@ func setupRootlessNotFound(t *testing.T) { baseRunDir = tmpDir uid := os.Getuid() - runDir := filepath.Join(tmpDir, "run", "user", fmt.Sprintf("%d", uid)) + runDir := filepath.Join(tmpDir, "run", "user", strconv.Itoa(uid)) err = createTmpDir(runDir) require.NoError(t, err) } diff --git a/modules/chroma/chroma.go b/modules/chroma/chroma.go index d0919e899f..e1c3d6e3bc 100644 --- a/modules/chroma/chroma.go +++ b/modules/chroma/chroma.go @@ -2,6 +2,7 @@ package chroma import ( "context" + "errors" "fmt" "github.com/testcontainers/testcontainers-go" @@ -66,7 +67,7 @@ func (c *ChromaContainer) RESTEndpoint(ctx context.Context) (string, error) { host, err := c.Host(ctx) if err != nil { - return "", fmt.Errorf("failed to get container host") + return "", errors.New("failed to get container host") } return fmt.Sprintf("http://%s:%s", host, containerPort.Port()), nil diff --git a/modules/cockroachdb/certs.go b/modules/cockroachdb/certs.go index dab738192a..afa12fcd1a 100644 --- a/modules/cockroachdb/certs.go +++ b/modules/cockroachdb/certs.go @@ -2,7 +2,7 @@ package cockroachdb import ( "crypto/x509" - "fmt" + "errors" "net" "time" @@ -28,7 +28,7 @@ func NewTLSConfig() (*TLSConfig, error) { ValidFor: time.Hour, }) if caCert == nil { - return nil, fmt.Errorf("failed to generate CA certificate") + return nil, errors.New("failed to generate CA certificate") } // } @@ -42,7 +42,7 @@ func NewTLSConfig() (*TLSConfig, error) { Parent: caCert, // using the CA certificate as parent }) if nodeCert == nil { - return nil, fmt.Errorf("failed to generate node certificate") + return nil, errors.New("failed to generate node certificate") } // } @@ -54,7 +54,7 @@ func NewTLSConfig() (*TLSConfig, error) { Parent: caCert, // using the CA certificate as parent }) if clientCert == nil { - return nil, fmt.Errorf("failed to generate client certificate") + return nil, errors.New("failed to generate client certificate") } return &TLSConfig{ diff --git a/modules/cockroachdb/cockroachdb.go b/modules/cockroachdb/cockroachdb.go index 4d412f04d3..092efa4e2a 100644 --- a/modules/cockroachdb/cockroachdb.go +++ b/modules/cockroachdb/cockroachdb.go @@ -5,6 +5,7 @@ import ( "crypto/tls" "crypto/x509" "encoding/pem" + "errors" "fmt" "net" "net/url" @@ -18,7 +19,7 @@ import ( "github.com/testcontainers/testcontainers-go/wait" ) -var ErrTLSNotEnabled = fmt.Errorf("tls not enabled") +var ErrTLSNotEnabled = errors.New("tls not enabled") const ( certsDir = "/tmp" @@ -144,7 +145,7 @@ func addCmd(req *testcontainers.GenericContainerRequest, opts options) error { return fmt.Errorf("unsupported user %s with TLS, use %s", opts.User, defaultUser) } if opts.Password != "" { - return fmt.Errorf("cannot use password authentication with TLS") + return errors.New("cannot use password authentication with TLS") } } diff --git a/modules/compose/compose_api_test.go b/modules/compose/compose_api_test.go index e3f080fcca..808433f513 100644 --- a/modules/compose/compose_api_test.go +++ b/modules/compose/compose_api_test.go @@ -2,7 +2,7 @@ package compose import ( "context" - "fmt" + "encoding/hex" "hash/fnv" "os" "path/filepath" @@ -642,7 +642,7 @@ func TestDockerComposeAPIVolumesDeletedOnDown(t *testing.T) { volumeListFilters := filters.NewArgs() // the "mydata" identifier comes from the "testdata/docker-compose-volume.yml" file - volumeListFilters.Add("name", fmt.Sprintf("%s_mydata", identifier)) + volumeListFilters.Add("name", identifier+"_mydata") volumeList, err := compose.dockerClient.VolumeList(ctx, volume.ListOptions{Filters: volumeListFilters}) require.NoError(t, err, "compose.dockerClient.VolumeList()") @@ -690,7 +690,7 @@ func TestDockerComposeApiWithWaitForShortLifespanService(t *testing.T) { } func testNameHash(name string) StackIdentifier { - return StackIdentifier(fmt.Sprintf("%x", fnv.New32a().Sum([]byte(name)))) + return StackIdentifier(hex.EncodeToString(fnv.New32a().Sum([]byte(name)))) } // cleanup is a helper function that schedules the compose stack to be stopped when the test ends. diff --git a/modules/dolt/dolt.go b/modules/dolt/dolt.go index 87713233d8..9309ce4475 100644 --- a/modules/dolt/dolt.go +++ b/modules/dolt/dolt.go @@ -3,6 +3,7 @@ package dolt import ( "context" "database/sql" + "errors" "fmt" "path/filepath" "strings" @@ -84,7 +85,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom } if len(password) == 0 && password == "" && !strings.EqualFold(rootUser, username) { - return nil, fmt.Errorf("empty password can be used only with the root user") + return nil, errors.New("empty password can be used only with the root user") } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) diff --git a/modules/elasticsearch/elasticsearch.go b/modules/elasticsearch/elasticsearch.go index e878c3e6ef..96f97ef8c1 100644 --- a/modules/elasticsearch/elasticsearch.go +++ b/modules/elasticsearch/elasticsearch.go @@ -4,6 +4,7 @@ import ( "context" "crypto/tls" "crypto/x509" + "errors" "fmt" "io" "os" @@ -212,7 +213,7 @@ func configurePassword(settings *Options, req *testcontainers.GenericContainerRe if settings.Password != "" { if isOSS(req.Image) { - return fmt.Errorf("it's not possible to activate security on Elastic OSS Image. Please switch to the default distribution.") + return errors.New("it's not possible to activate security on Elastic OSS Image. Please switch to the default distribution.") } if _, ok := req.Env["ELASTIC_PASSWORD"]; !ok { diff --git a/modules/elasticsearch/version.go b/modules/elasticsearch/version.go index 9ddc2836ad..3124e312ab 100644 --- a/modules/elasticsearch/version.go +++ b/modules/elasticsearch/version.go @@ -22,7 +22,7 @@ func isAtLeastVersion(image string, major int) bool { } if !strings.HasPrefix(version, "v") { - version = fmt.Sprintf("v%s", version) + version = "v" + version } if semver.IsValid(version) { diff --git a/modules/gcloud/spanner_test.go b/modules/gcloud/spanner_test.go index 0e976c3dff..02a1be1c78 100644 --- a/modules/gcloud/spanner_test.go +++ b/modules/gcloud/spanner_test.go @@ -63,7 +63,7 @@ func ExampleRunSpannerContainer() { // } instanceOp, err := instanceAdmin.CreateInstance(ctx, &instancepb.CreateInstanceRequest{ - Parent: fmt.Sprintf("projects/%s", projectId), + Parent: "projects/" + projectId, InstanceId: instanceId, Instance: &instancepb.Instance{ DisplayName: instanceId, diff --git a/modules/inbucket/inbucket.go b/modules/inbucket/inbucket.go index 565bc4253e..56695cb581 100644 --- a/modules/inbucket/inbucket.go +++ b/modules/inbucket/inbucket.go @@ -44,7 +44,7 @@ func (c *InbucketContainer) WebInterface(ctx context.Context) (string, error) { return "", err } - return fmt.Sprintf("http://%s", net.JoinHostPort(host, containerPort.Port())), nil + return "http://" + net.JoinHostPort(host, containerPort.Port()), nil } // Deprecated: use Run instead diff --git a/modules/k3s/k3s.go b/modules/k3s/k3s.go index 8a3625eb65..f223c08c2b 100644 --- a/modules/k3s/k3s.go +++ b/modules/k3s/k3s.go @@ -220,7 +220,7 @@ func (c *K3sContainer) LoadImages(ctx context.Context, images ...string) error { return fmt.Errorf("saving images %w", err) } - containerPath := fmt.Sprintf("/tmp/%s", filepath.Base(imagesTar.Name())) + containerPath := "/tmp/" + filepath.Base(imagesTar.Name()) err = c.Container.CopyFileToContainer(ctx, imagesTar.Name(), containerPath, 0x644) if err != nil { return fmt.Errorf("copying image to container %w", err) diff --git a/modules/k6/k6.go b/modules/k6/k6.go index ea99db3a88..e44c354d2d 100644 --- a/modules/k6/k6.go +++ b/modules/k6/k6.go @@ -143,7 +143,7 @@ func WithCache() testcontainers.CustomizeRequestOption { cacheVol := os.Getenv("TC_K6_BUILD_CACHE") // if no volume is provided, create one and ensure add labels for garbage collection if cacheVol == "" { - cacheVol = fmt.Sprintf("k6-cache-%s", testcontainers.SessionID()) + cacheVol = "k6-cache-" + testcontainers.SessionID() volOptions = &mount.VolumeOptions{ Labels: testcontainers.GenericLabels(), } diff --git a/modules/kafka/kafka.go b/modules/kafka/kafka.go index d4f070b8a1..73e392e1d2 100644 --- a/modules/kafka/kafka.go +++ b/modules/kafka/kafka.go @@ -2,8 +2,10 @@ package kafka import ( "context" + "errors" "fmt" "math" + "strconv" "strings" "github.com/docker/go-connections/nat" @@ -58,7 +60,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom "KAFKA_OFFSETS_TOPIC_NUM_PARTITIONS": "1", "KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR": "1", "KAFKA_TRANSACTION_STATE_LOG_MIN_ISR": "1", - "KAFKA_LOG_FLUSH_INTERVAL_MESSAGES": fmt.Sprintf("%d", math.MaxInt), + "KAFKA_LOG_FLUSH_INTERVAL_MESSAGES": strconv.Itoa(math.MaxInt), "KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS": "0", "KAFKA_NODE_ID": "1", "KAFKA_PROCESS_ROLES": "broker,controller", @@ -203,7 +205,7 @@ func configureControllerQuorumVoters(req *testcontainers.GenericContainerRequest // which is available since version 7.0.0. func validateKRaftVersion(fqName string) error { if fqName == "" { - return fmt.Errorf("image cannot be empty") + return errors.New("image cannot be empty") } image := fqName[:strings.LastIndex(fqName, ":")] @@ -218,7 +220,7 @@ func validateKRaftVersion(fqName string) error { // semver requires the version to start with a "v" if !strings.HasPrefix(version, "v") { - version = fmt.Sprintf("v%s", version) + version = "v" + version } if semver.Compare(version, "v7.4.0") < 0 { // version < v7.4.0 diff --git a/modules/localstack/localstack.go b/modules/localstack/localstack.go index 5cfe054a85..9754adba71 100644 --- a/modules/localstack/localstack.go +++ b/modules/localstack/localstack.go @@ -29,7 +29,7 @@ func isLegacyMode(image string) bool { } if !strings.HasPrefix(version, "v") { - version = fmt.Sprintf("v%s", version) + version = "v" + version } if semver.IsValid(version) { @@ -48,7 +48,7 @@ func isVersion2(image string) bool { } if !strings.HasPrefix(version, "v") { - version = fmt.Sprintf("v%s", version) + version = "v" + version } if semver.IsValid(version) { @@ -82,7 +82,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom ExposedPorts: []string{fmt.Sprintf("%d/tcp", defaultPort)}, Env: map[string]string{}, HostConfigModifier: func(hostConfig *container.HostConfig) { - hostConfig.Binds = []string{fmt.Sprintf("%s:/var/run/docker.sock", dockerHost)} + hostConfig.Binds = []string{dockerHost + ":/var/run/docker.sock"} }, } diff --git a/modules/localstack/localstack_test.go b/modules/localstack/localstack_test.go index 5991c52fbf..e9ad8c8330 100644 --- a/modules/localstack/localstack_test.go +++ b/modules/localstack/localstack_test.go @@ -2,7 +2,6 @@ package localstack import ( "context" - "fmt" "io" "strings" "testing" @@ -100,7 +99,7 @@ func TestIsLegacyMode(t *testing.T) { for _, tt := range tests { t.Run(tt.version, func(t *testing.T) { - got := isLegacyMode(fmt.Sprintf("localstack/localstack:%s", tt.version)) + got := isLegacyMode("localstack/localstack:" + tt.version) require.Equal(t, tt.want, got, "runInLegacyMode() = %v, want %v", got, tt.want) }) } @@ -119,7 +118,7 @@ func TestRunContainer(t *testing.T) { ctr, err := Run( ctx, - fmt.Sprintf("localstack/localstack:%s", tt.version), + "localstack/localstack:"+tt.version, ) testcontainers.CleanupContainer(t, ctr) diff --git a/modules/mariadb/mariadb.go b/modules/mariadb/mariadb.go index 1d0b553e41..4036cacc76 100644 --- a/modules/mariadb/mariadb.go +++ b/modules/mariadb/mariadb.go @@ -2,6 +2,7 @@ package mariadb import ( "context" + "errors" "fmt" "path/filepath" "strings" @@ -165,7 +166,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom password := req.Env["MARIADB_PASSWORD"] if len(password) == 0 && password == "" && !strings.EqualFold(rootUser, username) { - return nil, fmt.Errorf("empty password can be used only with the root user") + return nil, errors.New("empty password can be used only with the root user") } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) diff --git a/modules/meilisearch/meilisearch.go b/modules/meilisearch/meilisearch.go index 7d184eecb0..687a1d61ca 100644 --- a/modules/meilisearch/meilisearch.go +++ b/modules/meilisearch/meilisearch.go @@ -64,7 +64,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom FileMode: 0o755, }, } - genericContainerReq.Cmd = []string{"meilisearch", "--import-dump", fmt.Sprintf("/dumps/%s", settings.DumpDataFileName)} + genericContainerReq.Cmd = []string{"meilisearch", "--import-dump", "/dumps/" + settings.DumpDataFileName} } // the wait strategy does not support TLS at the moment, diff --git a/modules/minio/minio.go b/modules/minio/minio.go index 88c4f365d5..6547a9003b 100644 --- a/modules/minio/minio.go +++ b/modules/minio/minio.go @@ -2,6 +2,7 @@ package minio import ( "context" + "errors" "fmt" "github.com/testcontainers/testcontainers-go" @@ -89,7 +90,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom username := req.Env["MINIO_ROOT_USER"] password := req.Env["MINIO_ROOT_PASSWORD"] if username == "" || password == "" { - return nil, fmt.Errorf("username or password has not been set") + return nil, errors.New("username or password has not been set") } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) diff --git a/modules/mongodb/mongodb.go b/modules/mongodb/mongodb.go index 8acbf98ee2..b2fa8bb023 100644 --- a/modules/mongodb/mongodb.go +++ b/modules/mongodb/mongodb.go @@ -4,6 +4,7 @@ import ( "bytes" "context" _ "embed" + "errors" "fmt" "time" @@ -59,7 +60,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom username := req.Env["MONGO_INITDB_ROOT_USERNAME"] password := req.Env["MONGO_INITDB_ROOT_PASSWORD"] if username != "" && password == "" || username == "" && password != "" { - return nil, fmt.Errorf("if you specify username or password, you must provide both of them") + return nil, errors.New("if you specify username or password, you must provide both of them") } replicaSet := req.Env[replicaSetOptEnvKey] diff --git a/modules/mysql/mysql.go b/modules/mysql/mysql.go index 4eee6e654e..44c3688ab2 100644 --- a/modules/mysql/mysql.go +++ b/modules/mysql/mysql.go @@ -2,6 +2,7 @@ package mysql import ( "context" + "errors" "fmt" "path/filepath" "strings" @@ -82,7 +83,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom password := req.Env["MYSQL_PASSWORD"] if len(password) == 0 && password == "" && !strings.EqualFold(rootUser, username) { - return nil, fmt.Errorf("empty password can be used only with the root user") + return nil, errors.New("empty password can be used only with the root user") } container, err := testcontainers.GenericContainer(ctx, genericContainerReq) diff --git a/modules/neo4j/config.go b/modules/neo4j/config.go index 91eb3e415b..aff88d4f20 100644 --- a/modules/neo4j/config.go +++ b/modules/neo4j/config.go @@ -35,7 +35,7 @@ func WithAdminPassword(adminPassword string) testcontainers.CustomizeRequestOpti return func(req *testcontainers.GenericContainerRequest) error { pwd := "none" if adminPassword != "" { - pwd = fmt.Sprintf("neo4j/%s", adminPassword) + pwd = "neo4j/" + adminPassword } req.Env["NEO4J_AUTH"] = pwd @@ -127,7 +127,7 @@ func validate(req *testcontainers.GenericContainerRequest) error { func formatNeo4jConfig(name string) string { result := strings.ReplaceAll(name, "_", "__") result = strings.ReplaceAll(result, ".", "_") - return fmt.Sprintf("NEO4J_%s", result) + return "NEO4J_" + result } // WithAcceptCommercialLicenseAgreement sets the environment variable diff --git a/modules/neo4j/neo4j.go b/modules/neo4j/neo4j.go index 36cac5e4be..ed9579d46d 100644 --- a/modules/neo4j/neo4j.go +++ b/modules/neo4j/neo4j.go @@ -56,9 +56,9 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom "NEO4J_AUTH": "none", }, ExposedPorts: []string{ - fmt.Sprintf("%s/tcp", defaultBoltPort), - fmt.Sprintf("%s/tcp", defaultHttpPort), - fmt.Sprintf("%s/tcp", defaultHttpsPort), + defaultBoltPort + "/tcp", + defaultHttpPort + "/tcp", + defaultHttpsPort + "/tcp", }, WaitingFor: &wait.MultiStrategy{ Strategies: []wait.Strategy{ diff --git a/modules/ollama/examples_test.go b/modules/ollama/examples_test.go index e9ac3ce0fa..741db846be 100644 --- a/modules/ollama/examples_test.go +++ b/modules/ollama/examples_test.go @@ -85,7 +85,7 @@ func ExampleRun_withModel_llama2_http() { "prompt":"Why is the sky blue?" }` - req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/generate", connectionStr), strings.NewReader(payload)) + req, err := http.NewRequest(http.MethodPost, connectionStr+"/api/generate", strings.NewReader(payload)) if err != nil { log.Printf("failed to create request: %s", err) return diff --git a/modules/openfga/openfga.go b/modules/openfga/openfga.go index d6a3930a1d..67f79b30e1 100644 --- a/modules/openfga/openfga.go +++ b/modules/openfga/openfga.go @@ -36,7 +36,7 @@ func (c *OpenFGAContainer) PlaygroundEndpoint(ctx context.Context) (string, erro return "", fmt.Errorf("failed to get playground endpoint: %w", err) } - return fmt.Sprintf("%s/playground", endpoint), nil + return endpoint + "/playground", nil } // Deprecated: use Run instead diff --git a/modules/openldap/openldap.go b/modules/openldap/openldap.go index 940897f4dd..5a1bdf24f8 100644 --- a/modules/openldap/openldap.go +++ b/modules/openldap/openldap.go @@ -38,7 +38,7 @@ func (c *OpenLDAPContainer) ConnectionString(ctx context.Context, args ...string return "", err } - connStr := fmt.Sprintf("ldap://%s", net.JoinHostPort(host, containerPort.Port())) + connStr := "ldap://" + net.JoinHostPort(host, containerPort.Port()) return connStr, nil } diff --git a/modules/postgres/postgres.go b/modules/postgres/postgres.go index 8bd32a49b7..ce3719575d 100644 --- a/modules/postgres/postgres.go +++ b/modules/postgres/postgres.go @@ -3,6 +3,7 @@ package postgres import ( "context" "database/sql" + "errors" "fmt" "io" "net" @@ -262,7 +263,7 @@ func (c *PostgresContainer) checkSnapshotConfig(opts []SnapshotOption) (string, } if c.dbName == "postgres" { - return "", fmt.Errorf("cannot restore the postgres system database as it cannot be dropped to be restored") + return "", errors.New("cannot restore the postgres system database as it cannot be dropped to be restored") } return snapshotName, nil } diff --git a/modules/qdrant/qdrant.go b/modules/qdrant/qdrant.go index 5a2b6d365f..d4eb11b95a 100644 --- a/modules/qdrant/qdrant.go +++ b/modules/qdrant/qdrant.go @@ -2,6 +2,7 @@ package qdrant import ( "context" + "errors" "fmt" "time" @@ -64,7 +65,7 @@ func (c *QdrantContainer) RESTEndpoint(ctx context.Context) (string, error) { host, err := c.Host(ctx) if err != nil { - return "", fmt.Errorf("failed to get container host") + return "", errors.New("failed to get container host") } return fmt.Sprintf("http://%s:%s", host, containerPort.Port()), nil @@ -79,7 +80,7 @@ func (c *QdrantContainer) GRPCEndpoint(ctx context.Context) (string, error) { host, err := c.Host(ctx) if err != nil { - return "", fmt.Errorf("failed to get container host") + return "", errors.New("failed to get container host") } return fmt.Sprintf("%s:%s", host, containerPort.Port()), nil diff --git a/modules/rabbitmq/types_test.go b/modules/rabbitmq/types_test.go index 8b607f6632..e29bf2d88a 100644 --- a/modules/rabbitmq/types_test.go +++ b/modules/rabbitmq/types_test.go @@ -46,16 +46,16 @@ func (b Binding) AsCommand() []string { cmd := []string{"rabbitmqadmin"} if b.VHost != "" { - cmd = append(cmd, fmt.Sprintf("--vhost=%s", b.VHost)) + cmd = append(cmd, "--vhost="+b.VHost) } - cmd = append(cmd, "declare", "binding", fmt.Sprintf("source=%s", b.Source), fmt.Sprintf("destination=%s", b.Destination)) + cmd = append(cmd, "declare", "binding", "source="+b.Source, "destination="+b.Destination) if b.DestinationType != "" { - cmd = append(cmd, fmt.Sprintf("destination_type=%s", b.DestinationType)) + cmd = append(cmd, "destination_type="+b.DestinationType) } if b.RoutingKey != "" { - cmd = append(cmd, fmt.Sprintf("routing_key=%s", b.RoutingKey)) + cmd = append(cmd, "routing_key="+b.RoutingKey) } if len(b.Args) > 0 { @@ -92,7 +92,7 @@ func (e Exchange) AsCommand() []string { cmd = append(cmd, "--vhost="+e.VHost) } - cmd = append(cmd, "declare", "exchange", fmt.Sprintf("name=%s", e.Name), fmt.Sprintf("type=%s", e.Type)) + cmd = append(cmd, "declare", "exchange", "name="+e.Name, "type="+e.Type) if e.AutoDelete { cmd = append(cmd, "auto_delete=true") @@ -130,13 +130,13 @@ type OperatorPolicy struct { } func (op OperatorPolicy) AsCommand() []string { - cmd := []string{"rabbitmqadmin", "declare", "operator_policy", fmt.Sprintf("name=%s", op.Name), fmt.Sprintf("pattern=%s", op.Pattern)} + cmd := []string{"rabbitmqadmin", "declare", "operator_policy", "name=" + op.Name, "pattern=" + op.Pattern} if op.Priority > 0 { cmd = append(cmd, fmt.Sprintf("priority=%d", op.Priority)) } if op.ApplyTo != "" { - cmd = append(cmd, fmt.Sprintf("apply-to=%s", op.ApplyTo)) + cmd = append(cmd, "apply-to="+op.ApplyTo) } if len(op.Definition) > 0 { @@ -173,7 +173,7 @@ func NewParameter(component string, name string, value string) Parameter { func (p Parameter) AsCommand() []string { return []string{ "rabbitmqadmin", "declare", "parameter", - fmt.Sprintf("component=%s", p.Component), fmt.Sprintf("name=%s", p.Name), fmt.Sprintf("value=%s", p.Value), + "component=" + p.Component, "name=" + p.Name, "value=" + p.Value, } } @@ -203,8 +203,8 @@ func NewPermission(vhost string, user string, configure string, write string, re func (p Permission) AsCommand() []string { return []string{ "rabbitmqadmin", "declare", "permission", - fmt.Sprintf("vhost=%s", p.VHost), fmt.Sprintf("user=%s", p.User), - fmt.Sprintf("configure=%s", p.Configure), fmt.Sprintf("write=%s", p.Write), fmt.Sprintf("read=%s", p.Read), + "vhost=" + p.VHost, "user=" + p.User, + "configure=" + p.Configure, "write=" + p.Write, "read=" + p.Read, } } @@ -242,13 +242,13 @@ func (p Policy) AsCommand() []string { cmd = append(cmd, "--vhost="+p.VHost) } - cmd = append(cmd, "declare", "policy", fmt.Sprintf("name=%s", p.Name), fmt.Sprintf("pattern=%s", p.Pattern)) + cmd = append(cmd, "declare", "policy", "name="+p.Name, "pattern="+p.Pattern) if p.Priority > 0 { cmd = append(cmd, fmt.Sprintf("priority=%d", p.Priority)) } if p.ApplyTo != "" { - cmd = append(cmd, fmt.Sprintf("apply-to=%s", p.ApplyTo)) + cmd = append(cmd, "apply-to="+p.ApplyTo) } if len(p.Definition) > 0 { @@ -283,7 +283,7 @@ func (q Queue) AsCommand() []string { cmd = append(cmd, "--vhost="+q.VHost) } - cmd = append(cmd, "declare", "queue", fmt.Sprintf("name=%s", q.Name)) + cmd = append(cmd, "declare", "queue", "name="+q.Name) if q.AutoDelete { cmd = append(cmd, "auto_delete=true") @@ -328,8 +328,8 @@ func (u User) AsCommand() []string { return []string{ "rabbitmqadmin", "declare", "user", - fmt.Sprintf("name=%s", u.Name), fmt.Sprintf("password=%s", u.Password), - fmt.Sprintf("tags=%s", strings.Join(uniqueTags, ",")), + "name=" + u.Name, "password=" + u.Password, + "tags=" + strings.Join(uniqueTags, ","), } } @@ -344,7 +344,7 @@ type VirtualHost struct { } func (v VirtualHost) AsCommand() []string { - cmd := []string{"rabbitmqadmin", "declare", "vhost", fmt.Sprintf("name=%s", v.Name)} + cmd := []string{"rabbitmqadmin", "declare", "vhost", "name=" + v.Name} if v.Tracing { cmd = append(cmd, "tracing=true") @@ -361,7 +361,7 @@ type VirtualHostLimit struct { } func (v VirtualHostLimit) AsCommand() []string { - return []string{"rabbitmqadmin", "declare", "vhost_limit", fmt.Sprintf("vhost=%s", v.VHost), fmt.Sprintf("name=%s", v.Name), fmt.Sprintf("value=%d", v.Value)} + return []string{"rabbitmqadmin", "declare", "vhost_limit", "vhost=" + v.VHost, "name=" + v.Name, fmt.Sprintf("value=%d", v.Value)} } // --------- Virtual Hosts --------- diff --git a/modules/redis/redis.go b/modules/redis/redis.go index d834a6c46d..d824036642 100644 --- a/modules/redis/redis.go +++ b/modules/redis/redis.go @@ -3,6 +3,7 @@ package redis import ( "context" "fmt" + "strconv" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" @@ -135,7 +136,7 @@ func WithSnapshotting(seconds int, changedKeys int) testcontainers.CustomizeRequ } return func(req *testcontainers.GenericContainerRequest) error { - processRedisServerArgs(req, []string{"--save", fmt.Sprintf("%d", seconds), fmt.Sprintf("%d", changedKeys)}) + processRedisServerArgs(req, []string{"--save", strconv.Itoa(seconds), strconv.Itoa(changedKeys)}) return nil } } diff --git a/modules/redpanda/redpanda.go b/modules/redpanda/redpanda.go index c0936637d3..4a13318aa4 100644 --- a/modules/redpanda/redpanda.go +++ b/modules/redpanda/redpanda.go @@ -6,6 +6,7 @@ import ( "crypto/tls" "crypto/x509" _ "embed" + "errors" "fmt" "math" "net/http" @@ -329,7 +330,7 @@ func registerListeners(settings options, req testcontainers.GenericContainerRequ } if len(req.Networks) == 0 { - return fmt.Errorf("container must be attached to at least one network") + return errors.New("container must be attached to at least one network") } for _, listener := range settings.Listeners { @@ -418,11 +419,11 @@ func isAtLeastVersion(image, major string) bool { } if !strings.HasPrefix(version, "v") { - version = fmt.Sprintf("v%s", version) + version = "v" + version } if semver.IsValid(version) { - return semver.Compare(version, fmt.Sprintf("v%s", major)) >= 0 // version >= v8.x + return semver.Compare(version, "v"+major) >= 0 // version >= v8.x } return false diff --git a/modules/redpanda/redpanda_test.go b/modules/redpanda/redpanda_test.go index 9697b30525..112c83f882 100644 --- a/modules/redpanda/redpanda_test.go +++ b/modules/redpanda/redpanda_test.go @@ -50,7 +50,7 @@ func TestRedpanda(t *testing.T) { httpCl := &http.Client{Timeout: 5 * time.Second} schemaRegistryURL, err := ctr.SchemaRegistryAddress(ctx) require.NoError(t, err) - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/subjects", schemaRegistryURL), nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, schemaRegistryURL+"/subjects", nil) require.NoError(t, err) resp, err := httpCl.Do(req) require.NoError(t, err) @@ -62,7 +62,7 @@ func TestRedpanda(t *testing.T) { adminAPIURL, err := ctr.AdminAPIAddress(ctx) // } require.NoError(t, err) - req, err = http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v1/cluster/health_overview", adminAPIURL), nil) + req, err = http.NewRequestWithContext(ctx, http.MethodGet, adminAPIURL+"/v1/cluster/health_overview", nil) require.NoError(t, err) resp, err = httpCl.Do(req) require.NoError(t, err) @@ -162,7 +162,7 @@ func TestRedpandaWithAuthentication(t *testing.T) { require.NoError(t, err) // Failed authentication - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/subjects", schemaRegistryURL), nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, schemaRegistryURL+"/subjects", nil) require.NoError(t, err) resp, err := httpCl.Do(req) require.NoError(t, err) @@ -285,7 +285,7 @@ func TestRedpandaWithOldVersionAndWasm(t *testing.T) { require.NoError(t, err) // Failed authentication - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/subjects", schemaRegistryURL), nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, schemaRegistryURL+"/subjects", nil) require.NoError(t, err) resp, err := httpCl.Do(req) require.NoError(t, err) @@ -353,7 +353,7 @@ func TestRedpandaWithTLS(t *testing.T) { adminAPIURL, err := ctr.AdminAPIAddress(ctx) require.NoError(t, err) require.True(t, strings.HasPrefix(adminAPIURL, "https://"), "AdminAPIAddress should return https url") - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v1/cluster/health_overview", adminAPIURL), nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, adminAPIURL+"/v1/cluster/health_overview", nil) require.NoError(t, err) resp, err := httpCl.Do(req) require.NoError(t, err) @@ -364,7 +364,7 @@ func TestRedpandaWithTLS(t *testing.T) { schemaRegistryURL, err := ctr.SchemaRegistryAddress(ctx) require.NoError(t, err) require.True(t, strings.HasPrefix(adminAPIURL, "https://"), "SchemaRegistryAddress should return https url") - req, err = http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/subjects", schemaRegistryURL), nil) + req, err = http.NewRequestWithContext(ctx, http.MethodGet, schemaRegistryURL+"/subjects", nil) require.NoError(t, err) resp, err = httpCl.Do(req) require.NoError(t, err) @@ -545,7 +545,7 @@ func TestRedpandaBootstrapConfig(t *testing.T) { { // Check that the configs reflect specified values - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v1/cluster_config", adminAPIUrl), nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, adminAPIUrl+"/v1/cluster_config", nil) require.NoError(t, err) resp, err := httpCl.Do(req) require.NoError(t, err) @@ -562,7 +562,7 @@ func TestRedpandaBootstrapConfig(t *testing.T) { { // Check that no restart is required. i.e. that the configs were applied via bootstrap config - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v1/cluster_config/status", adminAPIUrl), nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, adminAPIUrl+"/v1/cluster_config/status", nil) require.NoError(t, err) resp, err := httpCl.Do(req) require.NoError(t, err) diff --git a/modules/registry/registry.go b/modules/registry/registry.go index 22aa86be54..1b1c42017c 100644 --- a/modules/registry/registry.go +++ b/modules/registry/registry.go @@ -4,6 +4,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "net" "net/http" @@ -286,7 +287,7 @@ func SetDockerAuthConfig(host, username, password string, additional ...string) // triples to add more auth configurations. func DockerAuthConfig(host, username, password string, additional ...string) (map[string]dockercfg.AuthConfig, error) { if len(additional)%3 != 0 { - return nil, fmt.Errorf("additional must be a multiple of 3") + return nil, errors.New("additional must be a multiple of 3") } additional = append(additional, host, username, password) diff --git a/modules/valkey/valkey.go b/modules/valkey/valkey.go index e8da1ed0e2..ac50d54797 100644 --- a/modules/valkey/valkey.go +++ b/modules/valkey/valkey.go @@ -3,6 +3,7 @@ package valkey import ( "context" "fmt" + "strconv" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" @@ -137,7 +138,7 @@ func WithSnapshotting(seconds int, changedKeys int) testcontainers.CustomizeRequ } return func(req *testcontainers.GenericContainerRequest) error { - processValkeyServerArgs(req, []string{"--save", fmt.Sprintf("%d", seconds), fmt.Sprintf("%d", changedKeys)}) + processValkeyServerArgs(req, []string{"--save", strconv.Itoa(seconds), strconv.Itoa(changedKeys)}) return nil } } diff --git a/modules/vearch/vearch.go b/modules/vearch/vearch.go index 3338eac0fe..a7bcb69083 100644 --- a/modules/vearch/vearch.go +++ b/modules/vearch/vearch.go @@ -2,6 +2,7 @@ package vearch import ( "context" + "errors" "fmt" "time" @@ -73,7 +74,7 @@ func (c *VearchContainer) RESTEndpoint(ctx context.Context) (string, error) { host, err := c.Host(ctx) if err != nil { - return "", fmt.Errorf("failed to get container host") + return "", errors.New("failed to get container host") } return fmt.Sprintf("http://%s:%s", host, containerPort.Port()), nil diff --git a/modules/weaviate/examples_test.go b/modules/weaviate/examples_test.go index 2f8e4f84a4..443f782413 100644 --- a/modules/weaviate/examples_test.go +++ b/modules/weaviate/examples_test.go @@ -73,7 +73,7 @@ func ExampleRun_connectWithClient() { connectionClient := &http.Client{} headers := map[string]string{ // put here the custom API key, e.g. for OpenAPI - "Authorization": fmt.Sprintf("Bearer %s", "custom-api-key"), + "Authorization": "Bearer custom-api-key", } cli := weaviate.New(weaviate.Config{ @@ -142,7 +142,7 @@ func ExampleRun_connectWithClientWithModules() { connectionClient := &http.Client{} headers := map[string]string{ // put here the custom API key, e.g. for OpenAPI - "Authorization": fmt.Sprintf("Bearer %s", "custom-api-key"), + "Authorization": "Bearer custom-api-key", } cli := weaviate.New(weaviate.Config{ diff --git a/modules/weaviate/weaviate.go b/modules/weaviate/weaviate.go index 3e0830fe3b..e773174d57 100644 --- a/modules/weaviate/weaviate.go +++ b/modules/weaviate/weaviate.go @@ -2,6 +2,7 @@ package weaviate import ( "context" + "errors" "fmt" "time" @@ -76,7 +77,7 @@ func (c *WeaviateContainer) HttpHostAddress(ctx context.Context) (string, string host, err := c.Host(ctx) if err != nil { - return "", "", fmt.Errorf("failed to get container host") + return "", "", errors.New("failed to get container host") } return "http", fmt.Sprintf("%s:%s", host, port.Port()), nil @@ -92,7 +93,7 @@ func (c *WeaviateContainer) GrpcHostAddress(ctx context.Context) (string, error) host, err := c.Host(ctx) if err != nil { - return "", fmt.Errorf("failed to get container host") + return "", errors.New("failed to get container host") } return fmt.Sprintf("%s:%s", host, port.Port()), nil diff --git a/port_forwarding.go b/port_forwarding.go index ff7db9b465..dbb570461b 100644 --- a/port_forwarding.go +++ b/port_forwarding.go @@ -40,7 +40,7 @@ var sshPassword = uuid.NewString() // 3. Close the SSH sessions before killing the container. func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) (sshdConnectHook ContainerLifecycleHooks, err error) { if len(ports) == 0 { - return sshdConnectHook, fmt.Errorf("no ports to expose") + return sshdConnectHook, errors.New("no ports to expose") } // Use the first network of the container to connect to the SSHD container. @@ -252,7 +252,7 @@ func configureSSHConfig(ctx context.Context, sshdC *sshdContainer) (*ssh.ClientC func (sshdC *sshdContainer) exposeHostPort(ctx context.Context, ports ...int) error { for _, port := range ports { - pw := NewPortForwarder(fmt.Sprintf("localhost:%s", sshdC.port), sshdC.sshConfig, port, port) + pw := NewPortForwarder("localhost:"+sshdC.port, sshdC.sshConfig, port, port) sshdC.portForwarders = append(sshdC.portForwarders, *pw) go pw.Forward(ctx) //nolint:errcheck // Nothing we can usefully do with the error diff --git a/reaper.go b/reaper.go index 9987b9944a..1d97a36ffa 100644 --- a/reaper.go +++ b/reaper.go @@ -83,7 +83,7 @@ func NewReaper(ctx context.Context, sessionID string, provider ReaperProvider, r func reaperContainerNameFromSessionID(sessionID string) string { // The session id is 64 characters, so we will not hit the limit of 128 // characters for container names. - return fmt.Sprintf("reaper_%s", sessionID) + return "reaper_" + sessionID } // reaperSpawner is a singleton that manages the reaper container. diff --git a/wait/all.go b/wait/all.go index fb097fb5ea..fb7eb4e5f3 100644 --- a/wait/all.go +++ b/wait/all.go @@ -2,7 +2,7 @@ package wait import ( "context" - "fmt" + "errors" "time" ) @@ -58,7 +58,7 @@ func (ms *MultiStrategy) WaitUntilReady(ctx context.Context, target StrategyTarg } if len(ms.Strategies) == 0 { - return fmt.Errorf("no wait strategy supplied") + return errors.New("no wait strategy supplied") } for _, strategy := range ms.Strategies { diff --git a/wait/host_port.go b/wait/host_port.go index 9360517a04..7d8b9e76ff 100644 --- a/wait/host_port.go +++ b/wait/host_port.go @@ -126,7 +126,7 @@ func (hp *HostPortStrategy) WaitUntilReady(ctx context.Context, target StrategyT } if internalPort == "" { - return fmt.Errorf("no port to wait for") + return errors.New("no port to wait for") } var port nat.Port From 19c126815308937a534bc7dd31b2a4f1a113f116 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Sun, 3 Nov 2024 11:13:29 +0100 Subject: [PATCH 119/126] chore: use testify instead of t.Error (#2871) Switch to using testify require instead of manual comparisons and t.Error to simplify and make tests more consistent. Signed-off-by: Matthieu MOREL Co-authored-by: Steven Hartland --- container_file_test.go | 20 ++--- container_test.go | 30 +++----- docker_test.go | 110 +++++++--------------------- image_substitutors_test.go | 40 +++------- internal/config/config_test.go | 6 +- internal/core/docker_host_test.go | 6 +- modules/couchbase/couchbase_test.go | 6 +- modules/postgres/postgres_test.go | 4 +- provider_test.go | 10 +-- testcontainers_test.go | 26 ++----- wait/all_test.go | 9 ++- wait/http_test.go | 15 +--- 12 files changed, 82 insertions(+), 200 deletions(-) diff --git a/container_file_test.go b/container_file_test.go index 166225f327..12d2240604 100644 --- a/container_file_test.go +++ b/container_file_test.go @@ -3,7 +3,6 @@ package testcontainers import ( - "errors" "os" "path/filepath" "testing" @@ -14,7 +13,7 @@ import ( func TestContainerFileValidation(t *testing.T) { type ContainerFileValidationTestCase struct { Name string - ExpectedError error + ExpectedError string File ContainerFile } @@ -38,7 +37,7 @@ func TestContainerFileValidation(t *testing.T) { }, { Name: "invalid container file", - ExpectedError: errors.New("either HostFilePath or Reader must be specified"), + ExpectedError: "either HostFilePath or Reader must be specified", File: ContainerFile{ HostFilePath: "", Reader: nil, @@ -47,7 +46,7 @@ func TestContainerFileValidation(t *testing.T) { }, { Name: "invalid container file", - ExpectedError: errors.New("ContainerFilePath must be specified"), + ExpectedError: "ContainerFilePath must be specified", File: ContainerFile{ HostFilePath: "/path/to/host", ContainerFilePath: "", @@ -58,15 +57,10 @@ func TestContainerFileValidation(t *testing.T) { for _, testCase := range testTable { t.Run(testCase.Name, func(t *testing.T) { err := testCase.File.validate() - switch { - case err == nil && testCase.ExpectedError == nil: - return - case err == nil && testCase.ExpectedError != nil: - t.Errorf("did not receive expected error: %s", testCase.ExpectedError.Error()) - case err != nil && testCase.ExpectedError == nil: - t.Errorf("received unexpected error: %s", err.Error()) - case err.Error() != testCase.ExpectedError.Error(): - t.Errorf("errors mismatch: %s != %s", err.Error(), testCase.ExpectedError.Error()) + if testCase.ExpectedError != "" { + require.EqualError(t, err, testCase.ExpectedError) + } else { + require.NoError(t, err) } }) } diff --git a/container_test.go b/container_test.go index 632ede9d26..c3581a379e 100644 --- a/container_test.go +++ b/container_test.go @@ -23,14 +23,14 @@ import ( func Test_ContainerValidation(t *testing.T) { type ContainerValidationTestCase struct { Name string - ExpectedError error + ExpectedError string ContainerRequest testcontainers.ContainerRequest } testTable := []ContainerValidationTestCase{ { Name: "cannot set both context and image", - ExpectedError: errors.New("you cannot specify both an Image and Context in a ContainerRequest"), + ExpectedError: "you cannot specify both an Image and Context in a ContainerRequest", ContainerRequest: testcontainers.ContainerRequest{ FromDockerfile: testcontainers.FromDockerfile{ Context: ".", @@ -39,15 +39,13 @@ func Test_ContainerValidation(t *testing.T) { }, }, { - Name: "can set image without context", - ExpectedError: nil, + Name: "can set image without context", ContainerRequest: testcontainers.ContainerRequest{ Image: "redis:latest", }, }, { - Name: "can set context without image", - ExpectedError: nil, + Name: "can set context without image", ContainerRequest: testcontainers.ContainerRequest{ FromDockerfile: testcontainers.FromDockerfile{ Context: ".", @@ -55,8 +53,7 @@ func Test_ContainerValidation(t *testing.T) { }, }, { - Name: "Can mount same source to multiple targets", - ExpectedError: nil, + Name: "Can mount same source to multiple targets", ContainerRequest: testcontainers.ContainerRequest{ Image: "redis:latest", HostConfigModifier: func(hc *container.HostConfig) { @@ -66,7 +63,7 @@ func Test_ContainerValidation(t *testing.T) { }, { Name: "Cannot mount multiple sources to same target", - ExpectedError: errors.New("duplicate mount target detected: /data"), + ExpectedError: "duplicate mount target detected: /data", ContainerRequest: testcontainers.ContainerRequest{ Image: "redis:latest", HostConfigModifier: func(hc *container.HostConfig) { @@ -76,7 +73,7 @@ func Test_ContainerValidation(t *testing.T) { }, { Name: "Invalid bind mount", - ExpectedError: errors.New("invalid bind mount: /data:/data:/data"), + ExpectedError: "invalid bind mount: /data:/data:/data", ContainerRequest: testcontainers.ContainerRequest{ Image: "redis:latest", HostConfigModifier: func(hc *container.HostConfig) { @@ -89,15 +86,10 @@ func Test_ContainerValidation(t *testing.T) { for _, testCase := range testTable { t.Run(testCase.Name, func(t *testing.T) { err := testCase.ContainerRequest.Validate() - switch { - case err == nil && testCase.ExpectedError == nil: - return - case err == nil && testCase.ExpectedError != nil: - t.Errorf("did not receive expected error: %s", testCase.ExpectedError.Error()) - case err != nil && testCase.ExpectedError == nil: - t.Errorf("received unexpected error: %s", err.Error()) - case err.Error() != testCase.ExpectedError.Error(): - t.Errorf("errors mismatch: %s != %s", err.Error(), testCase.ExpectedError.Error()) + if testCase.ExpectedError != "" { + require.EqualError(t, err, testCase.ExpectedError) + } else { + require.NoError(t, err) } }) } diff --git a/docker_test.go b/docker_test.go index dc3b245d1b..3fa686632f 100644 --- a/docker_test.go +++ b/docker_test.go @@ -83,20 +83,11 @@ func TestContainerWithHostNetworkOptions(t *testing.T) { CleanupContainer(t, nginxC) require.NoError(t, err) - // host, err := nginxC.Host(ctx) - // if err != nil { - // t.Errorf("Expected host %s. Got '%d'.", host, err) - // } - // endpoint, err := nginxC.PortEndpoint(ctx, nginxHighPort, "http") - if err != nil { - t.Errorf("Expected server endpoint. Got '%v'.", err) - } + require.NoErrorf(t, err, "Expected server endpoint") _, err = http.Get(endpoint) - if err != nil { - t.Errorf("Expected OK response. Got '%d'.", err) - } + require.NoErrorf(t, err, "Expected OK response") } func TestContainerWithHostNetworkOptions_UseExposePortsFromImageConfigs(t *testing.T) { @@ -115,17 +106,13 @@ func TestContainerWithHostNetworkOptions_UseExposePortsFromImageConfigs(t *testi require.NoError(t, err) endpoint, err := nginxC.Endpoint(ctx, "http") - if err != nil { - t.Errorf("Expected server endpoint. Got '%v'.", err) - } + require.NoErrorf(t, err, "Expected server endpoint") resp, err := http.Get(endpoint) require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Errorf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) - } + require.Equalf(t, http.StatusOK, resp.StatusCode, "Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) } func TestContainerWithNetworkModeAndNetworkTogether(t *testing.T) { @@ -192,25 +179,17 @@ func TestContainerWithHostNetwork(t *testing.T) { require.NoError(t, err) portEndpoint, err := nginxC.PortEndpoint(ctx, nginxHighPort, "http") - if err != nil { - t.Errorf("Expected port endpoint %s. Got '%d'.", portEndpoint, err) - } + require.NoErrorf(t, err, "Expected port endpoint %s", portEndpoint) t.Log(portEndpoint) _, err = http.Get(portEndpoint) - if err != nil { - t.Errorf("Expected OK response. Got '%v'.", err) - } + require.NoErrorf(t, err, "Expected OK response") host, err := nginxC.Host(ctx) - if err != nil { - t.Errorf("Expected host %s. Got '%d'.", host, err) - } + require.NoErrorf(t, err, "Expected host %s", host) _, err = http.Get("http://" + host + ":8080") - if err != nil { - t.Errorf("Expected OK response. Got '%v'.", err) - } + assert.NoErrorf(t, err, "Expected OK response") } func TestContainerReturnItsContainerID(t *testing.T) { @@ -227,9 +206,7 @@ func TestContainerReturnItsContainerID(t *testing.T) { CleanupContainer(t, nginxA) require.NoError(t, err) - if nginxA.GetContainerID() == "" { - t.Errorf("expected a containerID but we got an empty string.") - } + assert.NotEmptyf(t, nginxA.GetContainerID(), "expected a containerID but we got an empty string.") } // testLogConsumer is a simple implementation of LogConsumer that logs to the test output. @@ -419,9 +396,7 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Errorf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) - } + require.Equalf(t, http.StatusOK, resp.StatusCode, "Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) endpointB, err := nginxB.PortEndpoint(ctx, nginxDefaultPort, "http") require.NoError(t, err) @@ -430,9 +405,7 @@ func TestTwoContainersExposingTheSamePort(t *testing.T) { require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Errorf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) - } + require.Equalf(t, http.StatusOK, resp.StatusCode, "Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) } func TestContainerCreation(t *testing.T) { @@ -459,24 +432,15 @@ func TestContainerCreation(t *testing.T) { require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Errorf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) - } + require.Equalf(t, http.StatusOK, resp.StatusCode, "Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) networkIP, err := nginxC.ContainerIP(ctx) require.NoError(t, err) - if len(networkIP) == 0 { - t.Errorf("Expected an IP address, got %v", networkIP) - } + require.NotEmptyf(t, networkIP, "Expected an IP address, got %v", networkIP) networkAliases, err := nginxC.NetworkAliases(ctx) require.NoError(t, err) - if len(networkAliases) != 1 { - fmt.Printf("%v", networkAliases) - t.Errorf("Expected number of connected networks %d. Got %d.", 0, len(networkAliases)) - } - - if len(networkAliases["bridge"]) != 0 { - t.Errorf("Expected number of aliases for 'bridge' network %d. Got %d.", 0, len(networkAliases["bridge"])) - } + require.Lenf(t, networkAliases, 1, "Expected number of connected networks %d. Got %d.", 0, len(networkAliases)) + require.Contains(t, networkAliases, "bridge") + assert.Emptyf(t, networkAliases["bridge"], "Expected number of aliases for 'bridge' network %d. Got %d.", 0, len(networkAliases["bridge"])) } func TestContainerCreationWithName(t *testing.T) { @@ -505,24 +469,16 @@ func TestContainerCreationWithName(t *testing.T) { require.NoError(t, err) name := inspect.Name - if name != expectedName { - t.Errorf("Expected container name '%s'. Got '%s'.", expectedName, name) - } + assert.Equalf(t, expectedName, name, "Expected container name '%s'. Got '%s'.", expectedName, name) networks, err := nginxC.Networks(ctx) require.NoError(t, err) - if len(networks) != 1 { - t.Errorf("Expected networks 1. Got '%d'.", len(networks)) - } + require.Lenf(t, networks, 1, "Expected networks 1. Got '%d'.", len(networks)) network := networks[0] switch providerType { case ProviderDocker: - if network != Bridge { - t.Errorf("Expected network name '%s'. Got '%s'.", Bridge, network) - } + assert.Equalf(t, Bridge, network, "Expected network name '%s'. Got '%s'.", Bridge, network) case ProviderPodman: - if network != Podman { - t.Errorf("Expected network name '%s'. Got '%s'.", Podman, network) - } + assert.Equalf(t, Podman, network, "Expected network name '%s'. Got '%s'.", Podman, network) } endpoint, err := nginxC.PortEndpoint(ctx, nginxDefaultPort, "http") @@ -532,9 +488,7 @@ func TestContainerCreationWithName(t *testing.T) { require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Errorf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) - } + require.Equalf(t, http.StatusOK, resp.StatusCode, "Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) } func TestContainerCreationAndWaitForListeningPortLongEnough(t *testing.T) { @@ -561,9 +515,7 @@ func TestContainerCreationAndWaitForListeningPortLongEnough(t *testing.T) { require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Errorf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) - } + require.Equalf(t, http.StatusOK, resp.StatusCode, "Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) } func TestContainerCreationTimesOut(t *testing.T) { @@ -582,9 +534,7 @@ func TestContainerCreationTimesOut(t *testing.T) { }) CleanupContainer(t, nginxC) - if err == nil { - t.Error("Expected timeout") - } + assert.Errorf(t, err, "Expected timeout") } func TestContainerRespondsWithHttp200ForIndex(t *testing.T) { @@ -610,9 +560,7 @@ func TestContainerRespondsWithHttp200ForIndex(t *testing.T) { require.NoError(t, err) defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - t.Errorf("Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) - } + require.Equalf(t, http.StatusOK, resp.StatusCode, "Expected status code %d. Got %d.", http.StatusOK, resp.StatusCode) } func TestContainerCreationTimesOutWithHttp(t *testing.T) { @@ -650,9 +598,7 @@ func TestContainerCreationWaitsForLogContextTimeout(t *testing.T) { Started: true, }) CleanupContainer(t, c) - if err == nil { - t.Error("Expected timeout") - } + assert.Errorf(t, err, "Expected timeout") } func TestContainerCreationWaitsForLog(t *testing.T) { @@ -755,10 +701,8 @@ func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) { require.NoError(t, err) temp := strings.Split(string(out), "\n") - - if !regexp.MustCompile(`^Step\s*1/\d+\s*:\s*FROM alpine$`).MatchString(temp[0]) { - t.Errorf("Expected stdout first line to be %s. Got '%s'.", "Step 1/* : FROM alpine", temp[0]) - } + require.NotEmpty(t, temp) + assert.Regexpf(t, `^Step\s*1/\d+\s*:\s*FROM alpine$`, temp[0], "Expected stdout first line to be %s. Got '%s'.", "Step 1/* : FROM alpine", temp[0]) } func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) { diff --git a/image_substitutors_test.go b/image_substitutors_test.go index 4a168254e6..c9d6aee244 100644 --- a/image_substitutors_test.go +++ b/image_substitutors_test.go @@ -16,9 +16,7 @@ func TestCustomHubSubstitutor(t *testing.T) { img, err := s.Substitute("foo/foo:latest") require.NoError(t, err) - if img != "quay.io/foo/foo:latest" { - t.Errorf("expected quay.io/foo/foo:latest, got %s", img) - } + require.Equalf(t, "quay.io/foo/foo:latest", img, "expected quay.io/foo/foo:latest, got %s", img) }) t.Run("should not substitute the image if it is already using the provided hub", func(t *testing.T) { s := NewCustomHubSubstitutor("quay.io") @@ -26,9 +24,7 @@ func TestCustomHubSubstitutor(t *testing.T) { img, err := s.Substitute("quay.io/foo/foo:latest") require.NoError(t, err) - if img != "quay.io/foo/foo:latest" { - t.Errorf("expected quay.io/foo/foo:latest, got %s", img) - } + require.Equalf(t, "quay.io/foo/foo:latest", img, "expected quay.io/foo/foo:latest, got %s", img) }) t.Run("should not substitute the image if hub image name prefix config exist", func(t *testing.T) { t.Cleanup(config.Reset) @@ -39,9 +35,7 @@ func TestCustomHubSubstitutor(t *testing.T) { img, err := s.Substitute("foo/foo:latest") require.NoError(t, err) - if img != "foo/foo:latest" { - t.Errorf("expected foo/foo:latest, got %s", img) - } + require.Equalf(t, "foo/foo:latest", img, "expected foo/foo:latest, got %s", img) }) } @@ -53,9 +47,7 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { img, err := s.Substitute("foo:latest") require.NoError(t, err) - if img != "my-registry/foo:latest" { - t.Errorf("expected my-registry/foo, got %s", img) - } + require.Equalf(t, "my-registry/foo:latest", img, "expected my-registry/foo, got %s", img) }) t.Run("image with user", func(t *testing.T) { s := newPrependHubRegistry("my-registry") @@ -63,9 +55,7 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { img, err := s.Substitute("user/foo:latest") require.NoError(t, err) - if img != "my-registry/user/foo:latest" { - t.Errorf("expected my-registry/foo, got %s", img) - } + require.Equalf(t, "my-registry/user/foo:latest", img, "expected my-registry/foo, got %s", img) }) t.Run("image with organization and user", func(t *testing.T) { @@ -74,9 +64,7 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { img, err := s.Substitute("org/user/foo:latest") require.NoError(t, err) - if img != "my-registry/org/user/foo:latest" { - t.Errorf("expected my-registry/org/foo:latest, got %s", img) - } + require.Equalf(t, "my-registry/org/user/foo:latest", img, "expected my-registry/org/foo:latest, got %s", img) }) }) @@ -87,9 +75,7 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { img, err := s.Substitute("quay.io/foo:latest") require.NoError(t, err) - if img != "quay.io/foo:latest" { - t.Errorf("expected quay.io/foo:latest, got %s", img) - } + require.Equalf(t, "quay.io/foo:latest", img, "expected quay.io/foo:latest, got %s", img) }) t.Run("explicitly including registry.hub.docker.com/library", func(t *testing.T) { @@ -98,9 +84,7 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { img, err := s.Substitute("registry.hub.docker.com/library/foo:latest") require.NoError(t, err) - if img != "registry.hub.docker.com/library/foo:latest" { - t.Errorf("expected registry.hub.docker.com/library/foo:latest, got %s", img) - } + require.Equalf(t, "registry.hub.docker.com/library/foo:latest", img, "expected registry.hub.docker.com/library/foo:latest, got %s", img) }) t.Run("explicitly including registry.hub.docker.com", func(t *testing.T) { @@ -109,9 +93,7 @@ func TestPrependHubRegistrySubstitutor(t *testing.T) { img, err := s.Substitute("registry.hub.docker.com/foo:latest") require.NoError(t, err) - if img != "registry.hub.docker.com/foo:latest" { - t.Errorf("expected registry.hub.docker.com/foo:latest, got %s", img) - } + require.Equalf(t, "registry.hub.docker.com/foo:latest", img, "expected registry.hub.docker.com/foo:latest, got %s", img) }) }) } @@ -139,8 +121,6 @@ func TestSubstituteBuiltImage(t *testing.T) { json, err := c.Inspect(context.Background()) require.NoError(t, err) - if json.Config.Image != "my-registry/my-repo:my-image" { - t.Errorf("expected my-registry/my-repo:my-image, got %s", json.Config.Image) - } + require.Equalf(t, "my-registry/my-repo:my-image", json.Config.Image, "expected my-registry/my-repo:my-image, got %s", json.Config.Image) }) } diff --git a/internal/config/config_test.go b/internal/config/config_test.go index f1c7d3bbf3..591fcff11c 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -525,10 +525,8 @@ func TestReadTCConfig(t *testing.T) { for k, v := range tt.env { t.Setenv(k, v) } - if err := os.WriteFile(filepath.Join(tmpDir, ".testcontainers.properties"), []byte(tt.content), 0o600); err != nil { - t.Errorf("Failed to create the file: %v", err) - return - } + err := os.WriteFile(filepath.Join(tmpDir, ".testcontainers.properties"), []byte(tt.content), 0o600) + require.NoErrorf(t, err, "Failed to create the file") // config := read() diff --git a/internal/core/docker_host_test.go b/internal/core/docker_host_test.go index 41ce4f25e5..6faac45776 100644 --- a/internal/core/docker_host_test.go +++ b/internal/core/docker_host_test.go @@ -567,8 +567,6 @@ func setupTestcontainersProperties(t *testing.T, content string) { t.Setenv("HOME", homeDir) t.Setenv("USERPROFILE", homeDir) // Windows support - if err := os.WriteFile(filepath.Join(homeDir, ".testcontainers.properties"), []byte(content), 0o600); err != nil { - t.Errorf("Failed to create the file: %v", err) - return - } + err = os.WriteFile(filepath.Join(homeDir, ".testcontainers.properties"), []byte(content), 0o600) + require.NoErrorf(t, err, "Failed to create the file") } diff --git a/modules/couchbase/couchbase_test.go b/modules/couchbase/couchbase_test.go index 2e2122e01b..37f7a086a3 100644 --- a/modules/couchbase/couchbase_test.go +++ b/modules/couchbase/couchbase_test.go @@ -130,10 +130,8 @@ func testBucketUsage(t *testing.T, bucket *gocb.Bucket) { var resultData map[string]string err = result.Content(&resultData) require.NoErrorf(t, err, "could not assign content") - - if resultData["key"] != "value" { - t.Errorf("Expected value to be [%s], got %s", "value", resultData["key"]) - } + require.Contains(t, resultData, "key") + require.Equalf(t, "value", resultData["key"], "Expected value to be [%s], got %s", "value", resultData["key"]) } func connectCluster(ctx context.Context, container *tccouchbase.CouchbaseContainer) (*gocb.Cluster, error) { diff --git a/modules/postgres/postgres_test.go b/modules/postgres/postgres_test.go index 05b3f8110e..8c02e68476 100644 --- a/modules/postgres/postgres_test.go +++ b/modules/postgres/postgres_test.go @@ -75,9 +75,7 @@ func TestPostgres(t *testing.T) { require.NoError(t, err) mustConnStr := ctr.MustConnectionString(ctx, "sslmode=disable", "application_name=test") - if mustConnStr != connStr { - t.Errorf("ConnectionString was not equal to MustConnectionString") - } + require.Equalf(t, mustConnStr, connStr, "ConnectionString was not equal to MustConnectionString") // Ensure connection string is using generic format id, err := ctr.MappedPort(ctx, "5432/tcp") diff --git a/provider_test.go b/provider_test.go index e4937a49d0..94206e46bf 100644 --- a/provider_test.go +++ b/provider_test.go @@ -18,7 +18,6 @@ func TestProviderTypeGetProviderAutodetect(t *testing.T) { tr ProviderType DockerHost string want string - wantErr bool }{ { name: "default provider without podman.socket", @@ -67,15 +66,10 @@ func TestProviderTypeGetProviderAutodetect(t *testing.T) { t.Setenv("DOCKER_HOST", tt.DockerHost) got, err := tt.tr.GetProvider() - if (err != nil) != tt.wantErr { - t.Errorf("ProviderType.GetProvider() error = %v, wantErr %v", err, tt.wantErr) - return - } + require.NoErrorf(t, err, "ProviderType.GetProvider()") provider, ok := got.(*DockerProvider) require.Truef(t, ok, "ProviderType.GetProvider() = %T, want %T", got, &DockerProvider{}) - if provider.defaultBridgeNetworkName != tt.want { - t.Errorf("ProviderType.GetProvider() = %v, want %v", provider.defaultBridgeNetworkName, tt.want) - } + require.Equalf(t, tt.want, provider.defaultBridgeNetworkName, "ProviderType.GetProvider() = %v, want %v", provider.defaultBridgeNetworkName, tt.want) }) } } diff --git a/testcontainers_test.go b/testcontainers_test.go index 5ff914051c..6c06d87483 100644 --- a/testcontainers_test.go +++ b/testcontainers_test.go @@ -5,22 +5,20 @@ import ( "os/exec" "regexp" "testing" + + "github.com/stretchr/testify/require" ) func TestSessionID(t *testing.T) { t.Run("SessionID() returns a non-empty string", func(t *testing.T) { sessionID := SessionID() - if sessionID == "" { - t.Error("SessionID() returned an empty string") - } + require.NotEmptyf(t, sessionID, "SessionID() returned an empty string") }) t.Run("Multiple calls to SessionID() return the same value", func(t *testing.T) { sessionID1 := SessionID() sessionID2 := SessionID() - if sessionID1 != sessionID2 { - t.Errorf("SessionID() returned different values: %s != %s", sessionID1, sessionID2) - } + require.Equalf(t, sessionID1, sessionID2, "SessionID() returned different values: %s != %s", sessionID1, sessionID2) }) t.Run("Multiple calls to SessionID() in multiple goroutines return the same value", func(t *testing.T) { @@ -41,9 +39,7 @@ func TestSessionID(t *testing.T) { <-done <-done - if sessionID1 != sessionID2 { - t.Errorf("SessionID() returned different values: %s != %s", sessionID1, sessionID2) - } + require.Equalf(t, sessionID1, sessionID2, "SessionID() returned different values: %s != %s", sessionID1, sessionID2) }) t.Run("SessionID() from different child processes returns the same value", func(t *testing.T) { @@ -55,22 +51,16 @@ func TestSessionID(t *testing.T) { cmd1 := exec.Command("go", args...) cmd1.Env = env stdoutStderr1, err := cmd1.CombinedOutput() - if err != nil { - t.Errorf("cmd1.Run() failed with %s", err) - } + require.NoErrorf(t, err, "cmd1.Run() failed with %s", err) sessionID1 := re.FindString(string(stdoutStderr1)) cmd2 := exec.Command("go", args...) cmd2.Env = env stdoutStderr2, err := cmd2.CombinedOutput() - if err != nil { - t.Errorf("cmd2.Run() failed with %s", err) - } + require.NoErrorf(t, err, "cmd2.Run() failed with %s", err) sessionID2 := re.FindString(string(stdoutStderr2)) - if sessionID1 != sessionID2 { - t.Errorf("SessionID() returned different values: %s != %s", sessionID1, sessionID2) - } + require.Equalf(t, sessionID1, sessionID2, "SessionID() returned different values: %s != %s", sessionID1, sessionID2) }) } diff --git a/wait/all_test.go b/wait/all_test.go index 770a54f32c..87b00bb5ee 100644 --- a/wait/all_test.go +++ b/wait/all_test.go @@ -7,6 +7,8 @@ import ( "io" "testing" "time" + + "github.com/stretchr/testify/require" ) func TestMultiStrategy_WaitUntilReady(t *testing.T) { @@ -113,8 +115,11 @@ func TestMultiStrategy_WaitUntilReady(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - if err := tt.strategy.WaitUntilReady(tt.args.ctx, tt.args.target); (err != nil) != tt.wantErr { - t.Errorf("ForAll.WaitUntilReady() error = %v, wantErr = %v", err, tt.wantErr) + err := tt.strategy.WaitUntilReady(tt.args.ctx, tt.args.target) + if tt.wantErr { + require.Error(t, err, "ForAll.WaitUntilReady()") + } else { + require.NoErrorf(t, err, "ForAll.WaitUntilReady()") } }) } diff --git a/wait/http_test.go b/wait/http_test.go index 8e30210065..32479bddd4 100644 --- a/wait/http_test.go +++ b/wait/http_test.go @@ -235,10 +235,7 @@ func TestHTTPStrategyWaitUntilReady(t *testing.T) { require.NoError(t, err) certpool := x509.NewCertPool() - if !certpool.AppendCertsFromPEM(cafile) { - t.Errorf("the ca file isn't valid") - return - } + require.Truef(t, certpool.AppendCertsFromPEM(cafile), "the ca file isn't valid") tlsconfig := &tls.Config{RootCAs: certpool, ServerName: "testcontainer.go.test"} dockerReq := testcontainers.ContainerRequest{ @@ -299,10 +296,7 @@ func TestHTTPStrategyWaitUntilReadyWithQueryString(t *testing.T) { require.NoError(t, err) certpool := x509.NewCertPool() - if !certpool.AppendCertsFromPEM(cafile) { - t.Errorf("the ca file isn't valid") - return - } + require.Truef(t, certpool.AppendCertsFromPEM(cafile), "the ca file isn't valid") tlsconfig := &tls.Config{RootCAs: certpool, ServerName: "testcontainer.go.test"} dockerReq := testcontainers.ContainerRequest{ @@ -362,10 +356,7 @@ func TestHTTPStrategyWaitUntilReadyNoBasicAuth(t *testing.T) { require.NoError(t, err) certpool := x509.NewCertPool() - if !certpool.AppendCertsFromPEM(cafile) { - t.Errorf("the ca file isn't valid") - return - } + require.Truef(t, certpool.AppendCertsFromPEM(cafile), "the ca file isn't valid") // waitForHTTPStatusCode { tlsconfig := &tls.Config{RootCAs: certpool, ServerName: "testcontainer.go.test"} From d1b4e5ae64df3eefe1b34780f66227c903c6d419 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 3 Nov 2024 16:41:38 +0000 Subject: [PATCH 120/126] chore(deps): bump mkdocs-include-markdown-plugin from 6.0.4 to 6.2.2 (#2806) Bumps [mkdocs-include-markdown-plugin](https://github.com/mondeja/mkdocs-include-markdown-plugin) from 6.0.4 to 6.2.2. - [Release notes](https://github.com/mondeja/mkdocs-include-markdown-plugin/releases) - [Commits](https://github.com/mondeja/mkdocs-include-markdown-plugin/compare/v6.0.4...v6.2.2) --- updated-dependencies: - dependency-name: mkdocs-include-markdown-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Steven Hartland --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 44a81bdecf..e4db8827e3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ mkdocs==1.5.3 mkdocs-codeinclude-plugin==0.2.1 -mkdocs-include-markdown-plugin==6.0.4 +mkdocs-include-markdown-plugin==6.2.2 mkdocs-material==9.5.18 mkdocs-markdownextradata-plugin==0.2.6 From 9204291519a8405d042810667fdddf009b6b467a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Mon, 4 Nov 2024 14:26:56 +0100 Subject: [PATCH 121/126] fix: typo in containerd integration (#2873) --- .github/workflows/docker-moby-latest.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker-moby-latest.yml b/.github/workflows/docker-moby-latest.yml index 6c11df2af2..a5902d1fe3 100644 --- a/.github/workflows/docker-moby-latest.yml +++ b/.github/workflows/docker-moby-latest.yml @@ -14,7 +14,7 @@ jobs: # ghaction-setup-docker doesn't work with rootless yet exclude: - rootless-docker: true - container-integration: true + containerd-integration: true name: "Core tests using latest moby/moby" runs-on: 'ubuntu-latest' @@ -23,6 +23,7 @@ jobs: - name: Set the Docker Install type run: | echo "docker_install_type=${{ matrix.rootless-docker == true && 'Rootless' || 'Rootful' }}" >> "$GITHUB_ENV" + echo "containerd_integration=${{ matrix.containerd-integration == true && 'containerd' || '' }}" >> "$GITHUB_ENV" - name: Setup rootless Docker if: ${{ matrix.rootless-docker }} @@ -77,6 +78,7 @@ jobs: { "tc_project": "testcontainers-go", "tc_docker_install_type": "${docker_install_type}", + "tc_containerd_integration": "${containerd_integration}", "tc_github_action_url": "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}/attempts/${GITHUB_RUN_ATTEMPT}", "tc_github_action_status": "FAILED", "tc_slack_channel_id": "${{ secrets.SLACK_DOCKER_LATEST_CHANNEL_ID }}" From ac572ca322318772acade1c801b0cdb6de0c3f8f Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Tue, 5 Nov 2024 10:40:39 +0000 Subject: [PATCH 122/126] feat: add build to life cycle hooks (#2653) Add pre and post build life cycle hooks so the user can see when an image build is occurring and what it's tag is. Refactor combineContainerHooks to support additional fields automatically. Reduce overhead of hook error handling by starting with an nil error slice and use append to allocate only if needed, in other words assume the happy path by default hence minimising allocations. Minimise code used in hook handling by using helper methods. Eliminate unused / shadowed parameters from defaultPreCreateHook. GetRepo and GetTag now return a consistent UUID if the Repo or Tag field aren't set by setting their values. This was needed to enable the output of the image we're going to build in the log. --- container.go | 32 +++--- docker.go | 28 ++++- docs/features/creating_container.md | 2 + lifecycle.go | 161 ++++++++++++++++++---------- lifecycle_test.go | 103 ++++++++++++++++++ 5 files changed, 247 insertions(+), 79 deletions(-) diff --git a/container.go b/container.go index c0ae935f07..90a7ba91cb 100644 --- a/container.go +++ b/container.go @@ -74,7 +74,7 @@ type Container interface { type ImageBuildInfo interface { BuildOptions() (types.ImageBuildOptions, error) // converts the ImageBuildInfo to a types.ImageBuildOptions GetContext() (io.Reader, error) // the path to the build context - GetDockerfile() string // the relative path to the Dockerfile, including the fileitself + GetDockerfile() string // the relative path to the Dockerfile, including the file itself GetRepo() string // get repo label for image GetTag() string // get tag label for image ShouldPrintBuildLog() bool // allow build log to be printed to stdout @@ -286,34 +286,34 @@ func (c *ContainerRequest) GetBuildArgs() map[string]*string { return c.FromDockerfile.BuildArgs } -// GetDockerfile returns the Dockerfile from the ContainerRequest, defaults to "Dockerfile" +// GetDockerfile returns the Dockerfile from the ContainerRequest, defaults to "Dockerfile". +// Sets FromDockerfile.Dockerfile to the default if blank. func (c *ContainerRequest) GetDockerfile() string { - f := c.FromDockerfile.Dockerfile - if f == "" { - return "Dockerfile" + if c.FromDockerfile.Dockerfile == "" { + c.FromDockerfile.Dockerfile = "Dockerfile" } - return f + return c.FromDockerfile.Dockerfile } -// GetRepo returns the Repo label for image from the ContainerRequest, defaults to UUID +// GetRepo returns the Repo label for image from the ContainerRequest, defaults to UUID. +// Sets FromDockerfile.Repo to the default value if blank. func (c *ContainerRequest) GetRepo() string { - r := c.FromDockerfile.Repo - if r == "" { - return uuid.NewString() + if c.FromDockerfile.Repo == "" { + c.FromDockerfile.Repo = uuid.NewString() } - return strings.ToLower(r) + return strings.ToLower(c.FromDockerfile.Repo) } -// GetTag returns the Tag label for image from the ContainerRequest, defaults to UUID +// GetTag returns the Tag label for image from the ContainerRequest, defaults to UUID. +// Sets FromDockerfile.Tag to the default value if blank. func (c *ContainerRequest) GetTag() string { - t := c.FromDockerfile.Tag - if t == "" { - return uuid.NewString() + if c.FromDockerfile.Tag == "" { + c.FromDockerfile.Tag = uuid.NewString() } - return strings.ToLower(t) + return strings.ToLower(c.FromDockerfile.Tag) } // Deprecated: Testcontainers will detect registry credentials automatically, and it will be removed in the next major release. diff --git a/docker.go b/docker.go index 2063f92fc8..bc5b5276fc 100644 --- a/docker.go +++ b/docker.go @@ -1069,11 +1069,29 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque var platform *specs.Platform + defaultHooks := []ContainerLifecycleHooks{ + DefaultLoggingHook(p.Logger), + } + + origLifecycleHooks := req.LifecycleHooks + req.LifecycleHooks = []ContainerLifecycleHooks{ + combineContainerHooks(defaultHooks, req.LifecycleHooks), + } + if req.ShouldBuildImage() { + if err = req.buildingHook(ctx); err != nil { + return nil, err + } + imageName, err = p.BuildImage(ctx, &req) if err != nil { return nil, err } + + req.Image = imageName + if err = req.builtHook(ctx); err != nil { + return nil, err + } } else { for _, is := range req.ImageSubstitutors { modifiedTag, err := is.Substitute(imageName) @@ -1149,13 +1167,12 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque networkingConfig := &network.NetworkingConfig{} // default hooks include logger hook and pre-create hook - defaultHooks := []ContainerLifecycleHooks{ - DefaultLoggingHook(p.Logger), + defaultHooks = append(defaultHooks, defaultPreCreateHook(p, dockerInput, hostConfig, networkingConfig), defaultCopyFileToContainerHook(req.Files), defaultLogConsumersHook(req.LogConsumerCfg), defaultReadinessHook(), - } + ) // in the case the container needs to access a local port // we need to forward the local port to the container @@ -1171,7 +1188,10 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque defaultHooks = append(defaultHooks, sshdForwardPortsHook) } - req.LifecycleHooks = []ContainerLifecycleHooks{combineContainerHooks(defaultHooks, req.LifecycleHooks)} + // Combine with the original LifecycleHooks to avoid duplicate logging hooks. + req.LifecycleHooks = []ContainerLifecycleHooks{ + combineContainerHooks(defaultHooks, origLifecycleHooks), + } err = req.creatingHook(ctx) if err != nil { diff --git a/docs/features/creating_container.md b/docs/features/creating_container.md index ec33bdb014..6a87477d0d 100644 --- a/docs/features/creating_container.md +++ b/docs/features/creating_container.md @@ -106,6 +106,8 @@ _Testcontainers for Go_ allows you to define your own lifecycle hooks for better You'll be able to pass multiple lifecycle hooks at the `ContainerRequest` as an array of `testcontainers.ContainerLifecycleHooks`. The `testcontainers.ContainerLifecycleHooks` struct defines the following lifecycle hooks, each of them backed by an array of functions representing the hooks: +* `PreBuilds` - hooks that are executed before the container is built +* `PostBuilds` - hooks that are executed after the container is built * `PreCreates` - hooks that are executed before the container is created * `PostCreates` - hooks that are executed after the container is created * `PreStarts` - hooks that are executed before the container is started diff --git a/lifecycle.go b/lifecycle.go index 57833dafc1..63446f715d 100644 --- a/lifecycle.go +++ b/lifecycle.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "reflect" "strings" "time" @@ -39,6 +40,8 @@ type ContainerHook func(ctx context.Context, ctr Container) error // to modify the container lifecycle. All the container lifecycle hooks except the PreCreates hooks // will be passed to the container once it's created type ContainerLifecycleHooks struct { + PreBuilds []ContainerRequestHook + PostBuilds []ContainerRequestHook PreCreates []ContainerRequestHook PostCreates []ContainerHook PreStarts []ContainerHook @@ -57,6 +60,18 @@ var DefaultLoggingHook = func(logger Logging) ContainerLifecycleHooks { } return ContainerLifecycleHooks{ + PreBuilds: []ContainerRequestHook{ + func(ctx context.Context, req ContainerRequest) error { + logger.Printf("🐳 Building image %s:%s", req.GetRepo(), req.GetTag()) + return nil + }, + }, + PostBuilds: []ContainerRequestHook{ + func(ctx context.Context, req ContainerRequest) error { + logger.Printf("✅ Built image %s", req.Image) + return nil + }, + }, PreCreates: []ContainerRequestHook{ func(ctx context.Context, req ContainerRequest) error { logger.Printf("🐳 Creating container for image %s", req.Image) @@ -284,11 +299,34 @@ var defaultReadinessHook = func() ContainerLifecycleHooks { } } +// buildingHook is a hook that will be called before a container image is built. +func (req ContainerRequest) buildingHook(ctx context.Context) error { + return req.applyLifecycleHooks(func(lifecycleHooks ContainerLifecycleHooks) error { + return lifecycleHooks.Building(ctx)(req) + }) +} + +// builtHook is a hook that will be called after a container image is built. +func (req ContainerRequest) builtHook(ctx context.Context) error { + return req.applyLifecycleHooks(func(lifecycleHooks ContainerLifecycleHooks) error { + return lifecycleHooks.Built(ctx)(req) + }) +} + // creatingHook is a hook that will be called before a container is created. func (req ContainerRequest) creatingHook(ctx context.Context) error { - errs := make([]error, len(req.LifecycleHooks)) - for i, lifecycleHooks := range req.LifecycleHooks { - errs[i] = lifecycleHooks.Creating(ctx)(req) + return req.applyLifecycleHooks(func(lifecycleHooks ContainerLifecycleHooks) error { + return lifecycleHooks.Creating(ctx)(req) + }) +} + +// applyLifecycleHooks calls hook on all LifecycleHooks. +func (req ContainerRequest) applyLifecycleHooks(hook func(lifecycleHooks ContainerLifecycleHooks) error) error { + var errs []error + for _, lifecycleHooks := range req.LifecycleHooks { + if err := hook(lifecycleHooks); err != nil { + errs = append(errs, err) + } } return errors.Join(errs...) @@ -370,9 +408,11 @@ func (c *DockerContainer) terminatedHook(ctx context.Context) error { // applyLifecycleHooks applies all lifecycle hooks reporting the container logs on error if logError is true. func (c *DockerContainer) applyLifecycleHooks(ctx context.Context, logError bool, hooks func(lifecycleHooks ContainerLifecycleHooks) []ContainerHook) error { - errs := make([]error, len(c.lifecycleHooks)) - for i, lifecycleHooks := range c.lifecycleHooks { - errs[i] = containerHookFn(ctx, hooks(lifecycleHooks))(c) + var errs []error + for _, lifecycleHooks := range c.lifecycleHooks { + if err := containerHookFn(ctx, hooks(lifecycleHooks))(c); err != nil { + errs = append(errs, err) + } } if err := errors.Join(errs...); err != nil { @@ -394,10 +434,26 @@ func (c *DockerContainer) applyLifecycleHooks(ctx context.Context, logError bool return nil } +// Building is a hook that will be called before a container image is built. +func (c ContainerLifecycleHooks) Building(ctx context.Context) func(req ContainerRequest) error { + return containerRequestHook(ctx, c.PreBuilds) +} + +// Building is a hook that will be called before a container image is built. +func (c ContainerLifecycleHooks) Built(ctx context.Context) func(req ContainerRequest) error { + return containerRequestHook(ctx, c.PostBuilds) +} + // Creating is a hook that will be called before a container is created. func (c ContainerLifecycleHooks) Creating(ctx context.Context) func(req ContainerRequest) error { + return containerRequestHook(ctx, c.PreCreates) +} + +// containerRequestHook returns a function that will iterate over all +// the hooks and call them one by one until there is an error. +func containerRequestHook(ctx context.Context, hooks []ContainerRequestHook) func(req ContainerRequest) error { return func(req ContainerRequest) error { - for _, hook := range c.PreCreates { + for _, hook := range hooks { if err := hook(ctx, req); err != nil { return err } @@ -411,9 +467,11 @@ func (c ContainerLifecycleHooks) Creating(ctx context.Context) func(req Containe // container lifecycle hooks. The created function will iterate over all the hooks and call them one by one. func containerHookFn(ctx context.Context, containerHook []ContainerHook) func(container Container) error { return func(ctr Container) error { - errs := make([]error, len(containerHook)) - for i, hook := range containerHook { - errs[i] = hook(ctx, ctr) + var errs []error + for _, hook := range containerHook { + if err := hook(ctx, ctr); err != nil { + errs = append(errs, err) + } } return errors.Join(errs...) @@ -532,65 +590,50 @@ func (p *DockerProvider) preCreateContainerHook(ctx context.Context, req Contain return nil } -// combineContainerHooks it returns just one ContainerLifecycle hook, as the result of combining -// the default hooks with the user-defined hooks. The function will loop over all the default hooks, -// storing each of the hooks in a slice, and then it will loop over all the user-defined hooks, -// appending or prepending them to the slice of hooks. The order of hooks is the following: -// - for Pre-hooks, always run the default hooks first, then append the user-defined hooks -// - for Post-hooks, always run the user-defined hooks first, then the default hooks +// combineContainerHooks returns a ContainerLifecycle hook as the result +// of combining the default hooks with the user-defined hooks. +// +// The order of hooks is the following: +// - Pre-hooks run the default hooks first then the user-defined hooks +// - Post-hooks run the user-defined hooks first then the default hooks func combineContainerHooks(defaultHooks, userDefinedHooks []ContainerLifecycleHooks) ContainerLifecycleHooks { - preCreates := []ContainerRequestHook{} - postCreates := []ContainerHook{} - preStarts := []ContainerHook{} - postStarts := []ContainerHook{} - postReadies := []ContainerHook{} - preStops := []ContainerHook{} - postStops := []ContainerHook{} - preTerminates := []ContainerHook{} - postTerminates := []ContainerHook{} - + // We use reflection here to ensure that any new hooks are handled. + var hooks ContainerLifecycleHooks + hooksVal := reflect.ValueOf(&hooks).Elem() + hooksType := reflect.TypeOf(hooks) for _, defaultHook := range defaultHooks { - preCreates = append(preCreates, defaultHook.PreCreates...) - preStarts = append(preStarts, defaultHook.PreStarts...) - preStops = append(preStops, defaultHook.PreStops...) - preTerminates = append(preTerminates, defaultHook.PreTerminates...) + defaultVal := reflect.ValueOf(defaultHook) + for i := 0; i < hooksType.NumField(); i++ { + if strings.HasPrefix(hooksType.Field(i).Name, "Pre") { + field := hooksVal.Field(i) + field.Set(reflect.AppendSlice(field, defaultVal.Field(i))) + } + } } - // append the user-defined hooks after the default pre-hooks - // and because the post hooks are still empty, the user-defined post-hooks - // will be the first ones to be executed + // Append the user-defined hooks after the default pre-hooks + // and because the post hooks are still empty, the user-defined + // post-hooks will be the first ones to be executed. for _, userDefinedHook := range userDefinedHooks { - preCreates = append(preCreates, userDefinedHook.PreCreates...) - postCreates = append(postCreates, userDefinedHook.PostCreates...) - preStarts = append(preStarts, userDefinedHook.PreStarts...) - postStarts = append(postStarts, userDefinedHook.PostStarts...) - postReadies = append(postReadies, userDefinedHook.PostReadies...) - preStops = append(preStops, userDefinedHook.PreStops...) - postStops = append(postStops, userDefinedHook.PostStops...) - preTerminates = append(preTerminates, userDefinedHook.PreTerminates...) - postTerminates = append(postTerminates, userDefinedHook.PostTerminates...) + userVal := reflect.ValueOf(userDefinedHook) + for i := 0; i < hooksType.NumField(); i++ { + field := hooksVal.Field(i) + field.Set(reflect.AppendSlice(field, userVal.Field(i))) + } } - // finally, append the default post-hooks + // Finally, append the default post-hooks. for _, defaultHook := range defaultHooks { - postCreates = append(postCreates, defaultHook.PostCreates...) - postStarts = append(postStarts, defaultHook.PostStarts...) - postReadies = append(postReadies, defaultHook.PostReadies...) - postStops = append(postStops, defaultHook.PostStops...) - postTerminates = append(postTerminates, defaultHook.PostTerminates...) + defaultVal := reflect.ValueOf(defaultHook) + for i := 0; i < hooksType.NumField(); i++ { + if strings.HasPrefix(hooksType.Field(i).Name, "Post") { + field := hooksVal.Field(i) + field.Set(reflect.AppendSlice(field, defaultVal.Field(i))) + } + } } - return ContainerLifecycleHooks{ - PreCreates: preCreates, - PostCreates: postCreates, - PreStarts: preStarts, - PostStarts: postStarts, - PostReadies: postReadies, - PreStops: preStops, - PostStops: postStops, - PreTerminates: preTerminates, - PostTerminates: postTerminates, - } + return hooks } func mergePortBindings(configPortMap, exposedPortMap nat.PortMap, exposedPorts []string) nat.PortMap { diff --git a/lifecycle_test.go b/lifecycle_test.go index 0faefa8769..91102ccf82 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "reflect" "strings" "testing" "time" @@ -971,3 +972,105 @@ func lifecycleHooksIsHonouredFn(t *testing.T, prints []string) { require.Equal(t, expects, prints) } + +func Test_combineContainerHooks(t *testing.T) { + var funcID string + defaultContainerRequestHook := func(ctx context.Context, req ContainerRequest) error { + funcID = "defaultContainerRequestHook" + return nil + } + userContainerRequestHook := func(ctx context.Context, req ContainerRequest) error { + funcID = "userContainerRequestHook" + return nil + } + defaultContainerHook := func(ctx context.Context, container Container) error { + funcID = "defaultContainerHook" + return nil + } + userContainerHook := func(ctx context.Context, container Container) error { + funcID = "userContainerHook" + return nil + } + + defaultHooks := []ContainerLifecycleHooks{ + { + PreBuilds: []ContainerRequestHook{defaultContainerRequestHook}, + PostBuilds: []ContainerRequestHook{defaultContainerRequestHook}, + PreCreates: []ContainerRequestHook{defaultContainerRequestHook}, + PostCreates: []ContainerHook{defaultContainerHook}, + PreStarts: []ContainerHook{defaultContainerHook}, + PostStarts: []ContainerHook{defaultContainerHook}, + PostReadies: []ContainerHook{defaultContainerHook}, + PreStops: []ContainerHook{defaultContainerHook}, + PostStops: []ContainerHook{defaultContainerHook}, + PreTerminates: []ContainerHook{defaultContainerHook}, + PostTerminates: []ContainerHook{defaultContainerHook}, + }, + } + userDefinedHooks := []ContainerLifecycleHooks{ + { + PreBuilds: []ContainerRequestHook{userContainerRequestHook}, + PostBuilds: []ContainerRequestHook{userContainerRequestHook}, + PreCreates: []ContainerRequestHook{userContainerRequestHook}, + PostCreates: []ContainerHook{userContainerHook}, + PreStarts: []ContainerHook{userContainerHook}, + PostStarts: []ContainerHook{userContainerHook}, + PostReadies: []ContainerHook{userContainerHook}, + PreStops: []ContainerHook{userContainerHook}, + PostStops: []ContainerHook{userContainerHook}, + PreTerminates: []ContainerHook{userContainerHook}, + PostTerminates: []ContainerHook{userContainerHook}, + }, + } + expects := ContainerLifecycleHooks{ + PreBuilds: []ContainerRequestHook{defaultContainerRequestHook, userContainerRequestHook}, + PostBuilds: []ContainerRequestHook{userContainerRequestHook, defaultContainerRequestHook}, + PreCreates: []ContainerRequestHook{defaultContainerRequestHook, userContainerRequestHook}, + PostCreates: []ContainerHook{userContainerHook, defaultContainerHook}, + PreStarts: []ContainerHook{defaultContainerHook, userContainerHook}, + PostStarts: []ContainerHook{userContainerHook, defaultContainerHook}, + PostReadies: []ContainerHook{userContainerHook, defaultContainerHook}, + PreStops: []ContainerHook{defaultContainerHook, userContainerHook}, + PostStops: []ContainerHook{userContainerHook, defaultContainerHook}, + PreTerminates: []ContainerHook{defaultContainerHook, userContainerHook}, + PostTerminates: []ContainerHook{userContainerHook, defaultContainerHook}, + } + + ctx := context.Background() + ctxVal := reflect.ValueOf(ctx) + var req ContainerRequest + reqVal := reflect.ValueOf(req) + container := &DockerContainer{} + containerVal := reflect.ValueOf(container) + + got := combineContainerHooks(defaultHooks, userDefinedHooks) + + // Compare for equal. This can't be done with deep equals as functions + // are not comparable so we us the unique value stored in funcID when + // the function is called to determine if they are the same. + gotVal := reflect.ValueOf(got) + gotType := reflect.TypeOf(got) + expectedVal := reflect.ValueOf(expects) + for i := 0; i < gotVal.NumField(); i++ { + fieldName := gotType.Field(i).Name + gotField := gotVal.Field(i) + expectedField := expectedVal.Field(i) + require.Equalf(t, expectedField.Len(), 2, "field %q not setup len expected %d got %d", fieldName, 2, expectedField.Len()) //nolint:testifylint // False positive. + require.Equalf(t, expectedField.Len(), gotField.Len(), "field %q len expected %d got %d", fieldName, gotField.Len(), expectedField.Len()) + for j := 0; j < gotField.Len(); j++ { + gotIndex := gotField.Index(j) + expectedIndex := expectedField.Index(j) + var gotID string + if gotIndex.Type().Name() == "ContainerRequestHook" { + gotIndex.Call([]reflect.Value{ctxVal, reqVal}) + gotID = funcID + expectedIndex.Call([]reflect.Value{ctxVal, reqVal}) + } else { + gotIndex.Call([]reflect.Value{ctxVal, containerVal}) + gotID = funcID + expectedIndex.Call([]reflect.Value{ctxVal, containerVal}) + } + require.Equalf(t, funcID, gotID, "field %q[%d] func expected %s got %s", fieldName, j, funcID, gotID) + } + } +} From 42e9a55166030da5032e2face95757873ed7ae64 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Wed, 6 Nov 2024 11:13:09 +0000 Subject: [PATCH 123/126] fix: host access port instability (#2867) * fix: host access port instability Fix clean up of sshd container used for HostAccessPorts if the container setup fails. Fix ensureDefaultNetwork instability by preferring the default network if available. This prevents random port forwarding test failures due to different network bindings between the containers. Fix data race when reading exec command with Multiplexed enabled. Fix deadlock if an error was encountered reading from a container exec command. Refactor port forwarding tests so they can be run individually from code editors. Add timeout to port forwarding requests so that we don't need to wait for a full test timeout to identify failures. * chore: address PR feedback Add TODO's and missing tests, renaming to they are more consistent. * chore: speed up host port access test Speed up host port access test by using explicit cancellation instead of timeout. Only allocate the ports once to reduce resource usage. --- docker.go | 20 ++++- exec/processor.go | 46 ++++++++++- port_forwarding.go | 31 +++++-- port_forwarding_test.go | 173 ++++++++++++++++++++-------------------- 4 files changed, 173 insertions(+), 97 deletions(-) diff --git a/docker.go b/docker.go index bc5b5276fc..296fe6743c 100644 --- a/docker.go +++ b/docker.go @@ -1185,6 +1185,18 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque return nil, fmt.Errorf("expose host ports: %w", err) } + defer func() { + if err != nil && con == nil { + // Container setup failed so ensure we clean up the sshd container too. + ctr := &DockerContainer{ + provider: p, + logger: p.Logger, + lifecycleHooks: []ContainerLifecycleHooks{sshdForwardPortsHook}, + } + err = errors.Join(ctr.terminatingHook(ctx)) + } + }() + defaultHooks = append(defaultHooks, sshdForwardPortsHook) } @@ -1623,6 +1635,9 @@ func (p *DockerProvider) ensureDefaultNetwork(ctx context.Context) (string, erro return "", fmt.Errorf("network list: %w", err) } + // TODO: remove once we have docker context support via #2810 + // Prefer the default bridge network if it exists. + // This makes the results stable as network list order is not guaranteed. for _, net := range networkResources { switch net.Name { case p.defaultBridgeNetworkName: @@ -1630,10 +1645,13 @@ func (p *DockerProvider) ensureDefaultNetwork(ctx context.Context) (string, erro return p.defaultNetwork, nil case ReaperDefault: p.defaultNetwork = ReaperDefault - return p.defaultNetwork, nil } } + if p.defaultNetwork != "" { + return p.defaultNetwork, nil + } + // Create a bridge network for the container communications. _, err = p.client.NetworkCreate(ctx, ReaperDefault, network.CreateOptions{ Driver: Bridge, diff --git a/exec/processor.go b/exec/processor.go index 2b79583609..9c852fb5aa 100644 --- a/exec/processor.go +++ b/exec/processor.go @@ -2,7 +2,9 @@ package exec import ( "bytes" + "fmt" "io" + "sync" "github.com/docker/docker/api/types/container" "github.com/docker/docker/pkg/stdcopy" @@ -60,6 +62,43 @@ func WithEnv(env []string) ProcessOption { }) } +// safeBuffer is a goroutine safe buffer. +type safeBuffer struct { + mtx sync.Mutex + buf bytes.Buffer + err error +} + +// Error sets an error for the next read. +func (sb *safeBuffer) Error(err error) { + sb.mtx.Lock() + defer sb.mtx.Unlock() + + sb.err = err +} + +// Write writes p to the buffer. +// It is safe for concurrent use by multiple goroutines. +func (sb *safeBuffer) Write(p []byte) (n int, err error) { + sb.mtx.Lock() + defer sb.mtx.Unlock() + + return sb.buf.Write(p) +} + +// Read reads up to len(p) bytes into p from the buffer. +// It is safe for concurrent use by multiple goroutines. +func (sb *safeBuffer) Read(p []byte) (n int, err error) { + sb.mtx.Lock() + defer sb.mtx.Unlock() + + if sb.err != nil { + return 0, sb.err + } + + return sb.buf.Read(p) +} + // Multiplexed returns a [ProcessOption] that configures the command execution // to combine stdout and stderr into a single stream without Docker's multiplexing headers. func Multiplexed() ProcessOption { @@ -73,13 +112,14 @@ func Multiplexed() ProcessOption { done := make(chan struct{}) - var outBuff bytes.Buffer - var errBuff bytes.Buffer + var outBuff safeBuffer + var errBuff safeBuffer go func() { + defer close(done) if _, err := stdcopy.StdCopy(&outBuff, &errBuff, opts.Reader); err != nil { + outBuff.Error(fmt.Errorf("copying output: %w", err)) return } - close(done) }() <-done diff --git a/port_forwarding.go b/port_forwarding.go index dbb570461b..b892768d56 100644 --- a/port_forwarding.go +++ b/port_forwarding.go @@ -99,10 +99,26 @@ func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) ( return sshdConnectHook, fmt.Errorf("new sshd container: %w", err) } - // IP in the first network of the container - sshdIP, err := sshdContainer.ContainerIP(context.Background()) + // IP in the first network of the container. + inspect, err := sshdContainer.Inspect(ctx) if err != nil { - return sshdConnectHook, fmt.Errorf("get sshd container IP: %w", err) + return sshdConnectHook, fmt.Errorf("inspect sshd container: %w", err) + } + + // TODO: remove once we have docker context support via #2810 + sshdIP := inspect.NetworkSettings.IPAddress + if sshdIP == "" { + single := len(inspect.NetworkSettings.Networks) == 1 + for name, network := range inspect.NetworkSettings.Networks { + if name == sshdFirstNetwork || single { + sshdIP = network.IPAddress + break + } + } + } + + if sshdIP == "" { + return sshdConnectHook, errors.New("sshd container IP not found") } if req.HostConfigModifier == nil { @@ -166,11 +182,10 @@ func exposeHostPorts(ctx context.Context, req *ContainerRequest, ports ...int) ( func newSshdContainer(ctx context.Context, opts ...ContainerCustomizer) (*sshdContainer, error) { req := GenericContainerRequest{ ContainerRequest: ContainerRequest{ - Image: sshdImage, - HostAccessPorts: []int{}, // empty list because it does not need any port - ExposedPorts: []string{sshPort}, - Env: map[string]string{"PASSWORD": sshPassword}, - WaitingFor: wait.ForListeningPort(sshPort), + Image: sshdImage, + ExposedPorts: []string{sshPort}, + Env: map[string]string{"PASSWORD": sshPassword}, + WaitingFor: wait.ForListeningPort(sshPort), }, Started: true, } diff --git a/port_forwarding_test.go b/port_forwarding_test.go index 2936a46457..9d336ddb96 100644 --- a/port_forwarding_test.go +++ b/port_forwarding_test.go @@ -22,101 +22,104 @@ const ( ) func TestExposeHostPorts(t *testing.T) { - tests := []struct { - name string - numberOfPorts int - hasNetwork bool - hasHostAccess bool - }{ - { - name: "single port", - numberOfPorts: 1, - hasHostAccess: true, - }, - { - name: "single port using a network", - numberOfPorts: 1, - hasNetwork: true, - hasHostAccess: true, - }, - { - name: "multiple ports", - numberOfPorts: 3, - hasHostAccess: true, - }, - { - name: "single port with cancellation", - numberOfPorts: 1, - hasHostAccess: false, + hostPorts := make([]int, 3) + for i := range hostPorts { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, expectedResponse) + })) + hostPorts[i] = server.Listener.Addr().(*net.TCPAddr).Port + t.Cleanup(func() { + server.Close() + }) + } + + singlePort := hostPorts[0:1] + + t.Run("single-port", func(t *testing.T) { + testExposeHostPorts(t, singlePort, false, false) + }) + + t.Run("single-port-network", func(t *testing.T) { + testExposeHostPorts(t, singlePort, true, false) + }) + + t.Run("single-port-host-access", func(t *testing.T) { + testExposeHostPorts(t, singlePort, false, true) + }) + + t.Run("single-port-network-host-access", func(t *testing.T) { + testExposeHostPorts(t, singlePort, true, true) + }) + + t.Run("multi-port", func(t *testing.T) { + testExposeHostPorts(t, hostPorts, false, false) + }) + + t.Run("multi-port-network", func(t *testing.T) { + testExposeHostPorts(t, hostPorts, true, false) + }) + + t.Run("multi-port-host-access", func(t *testing.T) { + testExposeHostPorts(t, hostPorts, false, true) + }) + + t.Run("multi-port-network-host-access", func(t *testing.T) { + testExposeHostPorts(t, hostPorts, true, true) + }) +} + +func testExposeHostPorts(t *testing.T, hostPorts []int, hasNetwork, hasHostAccess bool) { + t.Helper() + + req := testcontainers.GenericContainerRequest{ + // hostAccessPorts { + ContainerRequest: testcontainers.ContainerRequest{ + Image: "alpine:3.17", + HostAccessPorts: hostPorts, + Cmd: []string{"top"}, }, + // } + Started: true, } - for _, tc := range tests { - t.Run(tc.name, func(tt *testing.T) { - freePorts := make([]int, tc.numberOfPorts) - for i := range freePorts { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, expectedResponse) - })) - freePorts[i] = server.Listener.Addr().(*net.TCPAddr).Port - tt.Cleanup(func() { - server.Close() - }) - } - - req := testcontainers.GenericContainerRequest{ - // hostAccessPorts { - ContainerRequest: testcontainers.ContainerRequest{ - Image: "alpine:3.17", - HostAccessPorts: freePorts, - Cmd: []string{"top"}, - }, - // } - Started: true, - } - - var nw *testcontainers.DockerNetwork - if tc.hasNetwork { - var err error - nw, err = network.New(context.Background()) - require.NoError(tt, err) - testcontainers.CleanupNetwork(t, nw) - - req.Networks = []string{nw.Name} - req.NetworkAliases = map[string][]string{nw.Name: {"myalpine"}} - } - - ctx := context.Background() - if !tc.hasHostAccess { - var cancel context.CancelFunc - ctx, cancel = context.WithTimeout(ctx, 10*time.Second) - defer cancel() - } - - c, err := testcontainers.GenericContainer(ctx, req) - testcontainers.CleanupContainer(t, c) - require.NoError(tt, err) - - if tc.hasHostAccess { - // create a container that has host access, which will - // automatically forward the port to the container - assertContainerHasHostAccess(tt, c, freePorts...) - } else { - // force cancellation because of timeout - time.Sleep(11 * time.Second) - - assertContainerHasNoHostAccess(tt, c, freePorts...) - } - }) + if hasNetwork { + nw, err := network.New(context.Background()) + require.NoError(t, err) + testcontainers.CleanupNetwork(t, nw) + + req.Networks = []string{nw.Name} + req.NetworkAliases = map[string][]string{nw.Name: {"myalpine"}} + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + c, err := testcontainers.GenericContainer(ctx, req) + testcontainers.CleanupContainer(t, c) + require.NoError(t, err) + + if hasHostAccess { + // Create a container that has host access, which will + // automatically forward the port to the container. + assertContainerHasHostAccess(t, c, hostPorts...) + return } + + // Force cancellation. + cancel() + + assertContainerHasNoHostAccess(t, c, hostPorts...) } func httpRequest(t *testing.T, c testcontainers.Container, port int) (int, string) { t.Helper() + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + // wgetHostInternal { code, reader, err := c.Exec( - context.Background(), - []string{"wget", "-q", "-O", "-", fmt.Sprintf("http://%s:%d", testcontainers.HostInternal, port)}, + ctx, + []string{"wget", "-q", "-O", "-", "-T", "2", fmt.Sprintf("http://%s:%d", testcontainers.HostInternal, port)}, tcexec.Multiplexed(), ) // } From 0aa5c1a9034f60c6455570c16076365a7246afe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Wed, 6 Nov 2024 12:20:45 +0100 Subject: [PATCH 124/126] docs: fix new lifecycle hooks section (#2875) --- docs/features/creating_container.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/features/creating_container.md b/docs/features/creating_container.md index 6a87477d0d..35e53d003e 100644 --- a/docs/features/creating_container.md +++ b/docs/features/creating_container.md @@ -106,8 +106,8 @@ _Testcontainers for Go_ allows you to define your own lifecycle hooks for better You'll be able to pass multiple lifecycle hooks at the `ContainerRequest` as an array of `testcontainers.ContainerLifecycleHooks`. The `testcontainers.ContainerLifecycleHooks` struct defines the following lifecycle hooks, each of them backed by an array of functions representing the hooks: -* `PreBuilds` - hooks that are executed before the container is built -* `PostBuilds` - hooks that are executed after the container is built +* `PreBuilds` - hooks that are executed before the image is built. This hook is only available when creating a container from a Dockerfile +* `PostBuilds` - hooks that are executed after the image is built. This hook is only available when creating a container from a Dockerfile * `PreCreates` - hooks that are executed before the container is created * `PostCreates` - hooks that are executed after the container is created * `PreStarts` - hooks that are executed before the container is started From aceb7070e6bc78e8037485fd481a23ea15175a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20de=20la=20Pe=C3=B1a?= Date: Thu, 7 Nov 2024 14:09:03 +0100 Subject: [PATCH 125/126] chore: resolve AWS deprecations for localstack (#2879) * fix: resolve AWS deprecations for localstack * docs: include resolver * chore: simplify fmt.Sprintf Co-authored-by: Steven Hartland * fix: proper format Co-authored-by: Steven Hartland * fix: remove unused import --------- Co-authored-by: Steven Hartland --- docs/modules/localstack.md | 1 + modules/localstack/go.mod | 2 +- modules/localstack/go.sum | 4 ++-- modules/localstack/v2/s3_test.go | 29 ++++++++++++++++++----------- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/docs/modules/localstack.md b/docs/modules/localstack.md index cf209162af..77cc522907 100644 --- a/docs/modules/localstack.md +++ b/docs/modules/localstack.md @@ -103,6 +103,7 @@ For further reference on the SDK v1, please check out the AWS docs [here](https: ### Using the AWS SDK v2 +[EndpointResolver](../../modules/localstack/v2/s3_test.go) inside_block:awsResolverV2 [AWS SDK v2](../../modules/localstack/v2/s3_test.go) inside_block:awsSDKClientV2 diff --git a/modules/localstack/go.mod b/modules/localstack/go.mod index 52c3e446cc..a0c994cc3a 100644 --- a/modules/localstack/go.mod +++ b/modules/localstack/go.mod @@ -8,6 +8,7 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.27.5 github.com/aws/aws-sdk-go-v2/credentials v1.17.5 github.com/aws/aws-sdk-go-v2/service/s3 v1.51.2 + github.com/aws/smithy-go v1.21.0 github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/stretchr/testify v1.9.0 @@ -32,7 +33,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.28.2 // indirect - github.com/aws/smithy-go v1.20.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/log v0.1.0 // indirect diff --git a/modules/localstack/go.sum b/modules/localstack/go.sum index 265c675ed5..a6341a7c78 100644 --- a/modules/localstack/go.sum +++ b/modules/localstack/go.sum @@ -42,8 +42,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 h1:9/GylMS45hGGFCcMrUZDVayQ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1/go.mod h1:YjAPFn4kGFqKC54VsHs5fn5B6d+PCY2tziEa3U/GB5Y= github.com/aws/aws-sdk-go-v2/service/sts v1.28.2 h1:0YjXuWdYHvsm0HnT4vO8XpwG1D+i2roxSCBoN6deJ7M= github.com/aws/aws-sdk-go-v2/service/sts v1.28.2/go.mod h1:jI+FWmYkSMn+4APWmZiZTgt0oM0TrvymD51FMqCnWgA= -github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw= -github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/aws/smithy-go v1.21.0 h1:H7L8dtDRk0P1Qm6y0ji7MCYMQObJ5R9CRpyPhRUkLYA= +github.com/aws/smithy-go v1.21.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= diff --git a/modules/localstack/v2/s3_test.go b/modules/localstack/v2/s3_test.go index 10c608ed8f..2df71dcb39 100644 --- a/modules/localstack/v2/s3_test.go +++ b/modules/localstack/v2/s3_test.go @@ -3,13 +3,13 @@ package v2_test import ( "bytes" "context" - "fmt" "testing" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/service/s3" + smithyendpoints "github.com/aws/smithy-go/endpoints" "github.com/docker/go-connections/nat" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -25,6 +25,20 @@ const ( region = "us-east-1" ) +// awsResolverV2 { +type resolverV2 struct { + // you could inject additional application context here as well +} + +func (*resolverV2) ResolveEndpoint(ctx context.Context, params s3.EndpointParameters) ( + smithyendpoints.Endpoint, error, +) { + // delegate back to the default v2 resolver otherwise + return s3.NewDefaultEndpointResolverV2().ResolveEndpoint(ctx, params) +} + +// } + // awsSDKClientV2 { func s3Client(ctx context.Context, l *localstack.LocalStackContainer) (*s3.Client, error) { mappedPort, err := l.MappedPort(ctx, nat.Port("4566/tcp")) @@ -43,25 +57,18 @@ func s3Client(ctx context.Context, l *localstack.LocalStackContainer) (*s3.Clien return nil, err } - customResolver := aws.EndpointResolverWithOptionsFunc( - func(service, region string, opts ...interface{}) (aws.Endpoint, error) { - return aws.Endpoint{ - PartitionID: "aws", - URL: fmt.Sprintf("http://%s:%d", host, mappedPort.Int()), - SigningRegion: region, - }, nil - }) - awsCfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region), - config.WithEndpointResolverWithOptions(customResolver), config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accesskey, secretkey, token)), ) if err != nil { return nil, err } + // reference: https://aws.github.io/aws-sdk-go-v2/docs/configuring-sdk/endpoints/#with-both client := s3.NewFromConfig(awsCfg, func(o *s3.Options) { + o.BaseEndpoint = aws.String("http://" + host + ":" + mappedPort.Port()) + o.EndpointResolverV2 = &resolverV2{} o.UsePathStyle = true }) From d87206018dc7e6a7dc372fd52e62b9e848fed0d5 Mon Sep 17 00:00:00 2001 From: Steven Hartland Date: Thu, 7 Nov 2024 16:07:24 +0000 Subject: [PATCH 126/126] fix!: port forwarding clean up and make private (#2881) Ensure that when the port forward container is shutdown all forwarding is also stopped by switching to a context to handle cancellation correctly. Ensure that port forwarding connection attempts are cancelled correctly when the container context is cancelled, previously these could wait for a longer timeout. Don't cancel port forwarding when the context used to start a container is cancelled as this is unexpected behaviour as its a non-explicit use of the context after the function has returned. Ensure forwarding clean up errors are reported on container stop and termination. Ensure port forwarding connections are cleaned up if one of the requested ports reports an error on setup. Port forwarding test style clean up. Update sshd module to the latest version. BREAKING_CHANGE: make port forwarding type and constructor private. --- examples/nginx/go.mod | 4 +- examples/nginx/go.sum | 16 +-- examples/toxiproxy/go.mod | 4 +- examples/toxiproxy/go.sum | 16 +-- go.mod | 4 +- go.sum | 16 +-- modules/artemis/go.mod | 4 +- modules/artemis/go.sum | 16 +-- modules/azurite/go.mod | 6 +- modules/azurite/go.sum | 16 +-- modules/cassandra/go.mod | 4 +- modules/cassandra/go.sum | 16 +-- modules/chroma/go.mod | 4 +- modules/chroma/go.sum | 16 +-- modules/clickhouse/go.mod | 4 +- modules/clickhouse/go.sum | 16 +-- modules/cockroachdb/go.mod | 8 +- modules/cockroachdb/go.sum | 20 +-- modules/compose/go.mod | 10 +- modules/compose/go.sum | 20 +-- modules/consul/go.mod | 4 +- modules/consul/go.sum | 16 +-- modules/couchbase/go.mod | 6 +- modules/couchbase/go.sum | 16 +-- modules/databend/go.mod | 4 +- modules/databend/go.sum | 16 +-- modules/dolt/go.mod | 4 +- modules/dolt/go.sum | 16 +-- modules/dynamodb/go.mod | 4 +- modules/dynamodb/go.sum | 16 +-- modules/elasticsearch/go.mod | 4 +- modules/elasticsearch/go.sum | 16 +-- modules/etcd/go.mod | 6 +- modules/etcd/go.sum | 16 +-- modules/gcloud/go.mod | 8 +- modules/gcloud/go.sum | 20 +-- modules/grafana-lgtm/go.mod | 8 +- modules/grafana-lgtm/go.sum | 20 +-- modules/inbucket/go.mod | 4 +- modules/inbucket/go.sum | 16 +-- modules/influxdb/go.mod | 4 +- modules/influxdb/go.sum | 16 +-- modules/k3s/go.mod | 8 +- modules/k3s/go.sum | 16 +-- modules/k6/go.mod | 4 +- modules/k6/go.sum | 16 +-- modules/kafka/go.mod | 4 +- modules/kafka/go.sum | 16 +-- modules/localstack/go.mod | 4 +- modules/localstack/go.sum | 16 +-- modules/mariadb/go.mod | 4 +- modules/mariadb/go.sum | 16 +-- modules/meilisearch/go.mod | 2 +- modules/meilisearch/go.sum | 8 +- modules/milvus/go.mod | 6 +- modules/milvus/go.sum | 16 +-- modules/minio/go.mod | 6 +- modules/minio/go.sum | 16 +-- modules/mockserver/go.mod | 4 +- modules/mockserver/go.sum | 16 +-- modules/mongodb/go.mod | 8 +- modules/mongodb/go.sum | 20 +-- modules/mssql/go.mod | 6 +- modules/mssql/go.sum | 16 +-- modules/mysql/go.mod | 4 +- modules/mysql/go.sum | 16 +-- modules/nats/go.mod | 4 +- modules/nats/go.sum | 16 +-- modules/neo4j/go.mod | 4 +- modules/neo4j/go.sum | 16 +-- modules/ollama/go.mod | 4 +- modules/ollama/go.sum | 16 +-- modules/openfga/go.mod | 4 +- modules/openfga/go.sum | 16 +-- modules/openldap/go.mod | 4 +- modules/openldap/go.sum | 16 +-- modules/opensearch/go.mod | 4 +- modules/opensearch/go.sum | 16 +-- modules/postgres/go.mod | 8 +- modules/postgres/go.sum | 20 +-- modules/pulsar/go.mod | 6 +- modules/pulsar/go.sum | 16 +-- modules/qdrant/go.mod | 6 +- modules/qdrant/go.sum | 16 +-- modules/rabbitmq/go.mod | 4 +- modules/rabbitmq/go.sum | 16 +-- modules/redis/go.mod | 4 +- modules/redis/go.sum | 16 +-- modules/redpanda/go.mod | 4 +- modules/redpanda/go.sum | 16 +-- modules/registry/go.mod | 4 +- modules/registry/go.sum | 16 +-- modules/surrealdb/go.mod | 4 +- modules/surrealdb/go.sum | 16 +-- modules/valkey/go.mod | 4 +- modules/valkey/go.sum | 16 +-- modules/vault/go.mod | 4 +- modules/vault/go.sum | 16 +-- modules/vearch/go.mod | 4 +- modules/vearch/go.sum | 16 +-- modules/weaviate/go.mod | 6 +- modules/weaviate/go.sum | 16 +-- modules/yugabytedb/go.mod | 4 +- modules/yugabytedb/go.sum | 16 +-- port_forwarding.go | 237 ++++++++++++++++++++--------------- port_forwarding_test.go | 50 ++++---- 106 files changed, 716 insertions(+), 673 deletions(-) diff --git a/examples/nginx/go.mod b/examples/nginx/go.mod index 19543c9484..a31fbd366e 100644 --- a/examples/nginx/go.mod +++ b/examples/nginx/go.mod @@ -54,9 +54,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/examples/nginx/go.sum b/examples/nginx/go.sum index afea3b1fff..447eec4038 100644 --- a/examples/nginx/go.sum +++ b/examples/nginx/go.sum @@ -131,8 +131,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -154,14 +154,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/examples/toxiproxy/go.mod b/examples/toxiproxy/go.mod index 0862d21e8a..644c7a9a0d 100644 --- a/examples/toxiproxy/go.mod +++ b/examples/toxiproxy/go.mod @@ -56,9 +56,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/examples/toxiproxy/go.sum b/examples/toxiproxy/go.sum index 5759c448e0..dbbd37fcaf 100644 --- a/examples/toxiproxy/go.sum +++ b/examples/toxiproxy/go.sum @@ -147,8 +147,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -170,14 +170,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/go.mod b/go.mod index 39c52eea45..78b747b76e 100644 --- a/go.mod +++ b/go.mod @@ -16,8 +16,8 @@ require ( github.com/opencontainers/image-spec v1.1.0 github.com/shirou/gopsutil/v3 v3.23.12 github.com/stretchr/testify v1.9.0 - golang.org/x/crypto v0.22.0 - golang.org/x/sys v0.21.0 + golang.org/x/crypto v0.28.0 + golang.org/x/sys v0.26.0 ) require ( diff --git a/go.sum b/go.sum index ae807b42af..38497f9611 100644 --- a/go.sum +++ b/go.sum @@ -137,8 +137,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -160,14 +160,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/artemis/go.mod b/modules/artemis/go.mod index b2088afe4d..68ed4a2090 100644 --- a/modules/artemis/go.mod +++ b/modules/artemis/go.mod @@ -52,9 +52,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/artemis/go.sum b/modules/artemis/go.sum index 5960b48221..8c89aa58bb 100644 --- a/modules/artemis/go.sum +++ b/modules/artemis/go.sum @@ -137,8 +137,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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= @@ -166,15 +166,15 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/azurite/go.mod b/modules/azurite/go.mod index e07abe4f5f..451d3fef9c 100644 --- a/modules/azurite/go.mod +++ b/modules/azurite/go.mod @@ -57,10 +57,10 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/azurite/go.sum b/modules/azurite/go.sum index 3c4a74cf45..abcbc8cec7 100644 --- a/modules/azurite/go.sum +++ b/modules/azurite/go.sum @@ -156,8 +156,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -179,14 +179,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/cassandra/go.mod b/modules/cassandra/go.mod index 3136506c9d..8b0cf9a058 100644 --- a/modules/cassandra/go.mod +++ b/modules/cassandra/go.mod @@ -54,9 +54,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/modules/cassandra/go.sum b/modules/cassandra/go.sum index 90f2553cd8..4937474970 100644 --- a/modules/cassandra/go.sum +++ b/modules/cassandra/go.sum @@ -143,8 +143,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -166,14 +166,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/chroma/go.mod b/modules/chroma/go.mod index 1cb622ea1d..aece8e62e9 100644 --- a/modules/chroma/go.mod +++ b/modules/chroma/go.mod @@ -55,9 +55,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/chroma/go.sum b/modules/chroma/go.sum index 3efa70b786..c7325de7ae 100644 --- a/modules/chroma/go.sum +++ b/modules/chroma/go.sum @@ -138,8 +138,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -161,14 +161,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/clickhouse/go.mod b/modules/clickhouse/go.mod index a471fff126..2c14eff644 100644 --- a/modules/clickhouse/go.mod +++ b/modules/clickhouse/go.mod @@ -60,9 +60,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/clickhouse/go.sum b/modules/clickhouse/go.sum index 015f3a6d09..f451caeaf6 100644 --- a/modules/clickhouse/go.sum +++ b/modules/clickhouse/go.sum @@ -165,8 +165,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk 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-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -193,17 +193,17 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/cockroachdb/go.mod b/modules/cockroachdb/go.mod index fd7e17baa1..fbc0fd6f7a 100644 --- a/modules/cockroachdb/go.mod +++ b/modules/cockroachdb/go.mod @@ -62,10 +62,10 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/modules/cockroachdb/go.sum b/modules/cockroachdb/go.sum index 2bef2696ee..e8661eb69a 100644 --- a/modules/cockroachdb/go.sum +++ b/modules/cockroachdb/go.sum @@ -142,8 +142,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -155,8 +155,8 @@ golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= 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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -167,14 +167,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/compose/go.mod b/modules/compose/go.mod index 35ab7d526b..24ced86c72 100644 --- a/modules/compose/go.mod +++ b/modules/compose/go.mod @@ -12,7 +12,7 @@ require ( github.com/google/uuid v1.6.0 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.34.0 - golang.org/x/sync v0.7.0 + golang.org/x/sync v0.8.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -170,13 +170,13 @@ require ( go.opentelemetry.io/otel/trace v1.24.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/mock v0.4.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/term v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/term v0.25.0 // indirect + golang.org/x/text v0.19.0 // indirect golang.org/x/time v0.3.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect diff --git a/modules/compose/go.sum b/modules/compose/go.sum index f6bc950a37..c42e635113 100644 --- a/modules/compose/go.sum +++ b/modules/compose/go.sum @@ -545,8 +545,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -575,8 +575,8 @@ 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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -603,20 +603,20 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/consul/go.mod b/modules/consul/go.mod index b77596a1b7..21db7d081e 100644 --- a/modules/consul/go.mod +++ b/modules/consul/go.mod @@ -66,10 +66,10 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/consul/go.sum b/modules/consul/go.sum index 150864f08a..b261343e8c 100644 --- a/modules/consul/go.sum +++ b/modules/consul/go.sum @@ -283,8 +283,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -335,17 +335,17 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/couchbase/go.mod b/modules/couchbase/go.mod index d31b6f080d..26739fb6e3 100644 --- a/modules/couchbase/go.mod +++ b/modules/couchbase/go.mod @@ -63,10 +63,10 @@ require ( go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/grpc v1.64.1 // indirect google.golang.org/protobuf v1.33.0 // indirect diff --git a/modules/couchbase/go.sum b/modules/couchbase/go.sum index eda139da73..1abe707bb5 100644 --- a/modules/couchbase/go.sum +++ b/modules/couchbase/go.sum @@ -196,8 +196,8 @@ go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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= @@ -234,14 +234,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/databend/go.mod b/modules/databend/go.mod index c16777822e..c6c0254315 100644 --- a/modules/databend/go.mod +++ b/modules/databend/go.mod @@ -55,8 +55,8 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/sys v0.26.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/modules/databend/go.sum b/modules/databend/go.sum index 82d0c95ad2..a9ef44ba75 100644 --- a/modules/databend/go.sum +++ b/modules/databend/go.sum @@ -139,8 +139,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -162,14 +162,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/dolt/go.mod b/modules/dolt/go.mod index d363787d92..e79f82e78c 100644 --- a/modules/dolt/go.mod +++ b/modules/dolt/go.mod @@ -53,9 +53,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/dolt/go.sum b/modules/dolt/go.sum index 5ec2f1b6fa..96aef09c5a 100644 --- a/modules/dolt/go.sum +++ b/modules/dolt/go.sum @@ -133,8 +133,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -156,14 +156,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/dynamodb/go.mod b/modules/dynamodb/go.mod index 75804011b0..4a3b063bd4 100644 --- a/modules/dynamodb/go.mod +++ b/modules/dynamodb/go.mod @@ -68,8 +68,8 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/sys v0.26.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/modules/dynamodb/go.sum b/modules/dynamodb/go.sum index bae52466e0..80a9c6e219 100644 --- a/modules/dynamodb/go.sum +++ b/modules/dynamodb/go.sum @@ -165,8 +165,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -188,14 +188,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/elasticsearch/go.mod b/modules/elasticsearch/go.mod index 108bc46b4e..daaa6e8fac 100644 --- a/modules/elasticsearch/go.mod +++ b/modules/elasticsearch/go.mod @@ -55,9 +55,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/elasticsearch/go.sum b/modules/elasticsearch/go.sum index 8ad3562871..42bbadf11f 100644 --- a/modules/elasticsearch/go.sum +++ b/modules/elasticsearch/go.sum @@ -136,8 +136,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= @@ -161,14 +161,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/etcd/go.mod b/modules/etcd/go.mod index a1ecca2f68..b0946686cc 100644 --- a/modules/etcd/go.mod +++ b/modules/etcd/go.mod @@ -61,10 +61,10 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.17.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/grpc v1.64.1 // indirect diff --git a/modules/etcd/go.sum b/modules/etcd/go.sum index 3de88cadb9..505f9ae432 100644 --- a/modules/etcd/go.sum +++ b/modules/etcd/go.sum @@ -153,8 +153,8 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -176,14 +176,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/gcloud/go.mod b/modules/gcloud/go.mod index ab30a75a7b..5c05fce458 100644 --- a/modules/gcloud/go.mod +++ b/modules/gcloud/go.mod @@ -85,13 +85,13 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect diff --git a/modules/gcloud/go.sum b/modules/gcloud/go.sum index da1d6d6919..f8036b37f9 100644 --- a/modules/gcloud/go.sum +++ b/modules/gcloud/go.sum @@ -246,8 +246,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk 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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= @@ -281,8 +281,8 @@ 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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -299,18 +299,18 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/grafana-lgtm/go.mod b/modules/grafana-lgtm/go.mod index c5be803b14..cab19dc60a 100644 --- a/modules/grafana-lgtm/go.mod +++ b/modules/grafana-lgtm/go.mod @@ -19,7 +19,7 @@ require ( go.opentelemetry.io/otel/sdk v1.28.0 go.opentelemetry.io/otel/sdk/log v0.4.0 go.opentelemetry.io/otel/sdk/metric v1.28.0 - golang.org/x/sync v0.7.0 + golang.org/x/sync v0.8.0 ) require ( @@ -72,10 +72,10 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/grpc v1.64.1 // indirect diff --git a/modules/grafana-lgtm/go.sum b/modules/grafana-lgtm/go.sum index c19cef2137..d637aca1fa 100644 --- a/modules/grafana-lgtm/go.sum +++ b/modules/grafana-lgtm/go.sum @@ -160,8 +160,8 @@ go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -173,8 +173,8 @@ golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= 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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -185,14 +185,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/inbucket/go.mod b/modules/inbucket/go.mod index da34424539..65a656dad5 100644 --- a/modules/inbucket/go.mod +++ b/modules/inbucket/go.mod @@ -54,9 +54,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/inbucket/go.sum b/modules/inbucket/go.sum index 0a2d246379..84749386ff 100644 --- a/modules/inbucket/go.sum +++ b/modules/inbucket/go.sum @@ -135,8 +135,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -158,14 +158,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/influxdb/go.mod b/modules/influxdb/go.mod index 9931d3bd7d..43041bf961 100644 --- a/modules/influxdb/go.mod +++ b/modules/influxdb/go.mod @@ -53,9 +53,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/influxdb/go.sum b/modules/influxdb/go.sum index 49dede80c1..4007c33ccd 100644 --- a/modules/influxdb/go.sum +++ b/modules/influxdb/go.sum @@ -134,8 +134,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -157,14 +157,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/k3s/go.mod b/modules/k3s/go.mod index f329ae688b..5a382b7739 100644 --- a/modules/k3s/go.mod +++ b/modules/k3s/go.mod @@ -70,12 +70,12 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/term v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/term v0.25.0 // indirect + golang.org/x/text v0.19.0 // indirect golang.org/x/time v0.3.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect diff --git a/modules/k3s/go.sum b/modules/k3s/go.sum index c086e351c5..4584dcf7ac 100644 --- a/modules/k3s/go.sum +++ b/modules/k3s/go.sum @@ -182,8 +182,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk 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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -215,18 +215,18 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/k6/go.mod b/modules/k6/go.mod index 356b3750a5..cd1600f0f7 100644 --- a/modules/k6/go.mod +++ b/modules/k6/go.mod @@ -52,9 +52,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/k6/go.sum b/modules/k6/go.sum index afea3b1fff..447eec4038 100644 --- a/modules/k6/go.sum +++ b/modules/k6/go.sum @@ -131,8 +131,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -154,14 +154,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/kafka/go.mod b/modules/kafka/go.mod index 9c447008a1..da1366a692 100644 --- a/modules/kafka/go.mod +++ b/modules/kafka/go.mod @@ -68,10 +68,10 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/kafka/go.sum b/modules/kafka/go.sum index 7c3a427da5..dfa6758b3f 100644 --- a/modules/kafka/go.sum +++ b/modules/kafka/go.sum @@ -174,8 +174,8 @@ 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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -213,19 +213,19 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/localstack/go.mod b/modules/localstack/go.mod index a0c994cc3a..a96a35a1ba 100644 --- a/modules/localstack/go.mod +++ b/modules/localstack/go.mod @@ -73,9 +73,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/localstack/go.sum b/modules/localstack/go.sum index a6341a7c78..cd93facea9 100644 --- a/modules/localstack/go.sum +++ b/modules/localstack/go.sum @@ -178,8 +178,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= @@ -204,14 +204,14 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/mariadb/go.mod b/modules/mariadb/go.mod index 17e77ad48a..319e67d627 100644 --- a/modules/mariadb/go.mod +++ b/modules/mariadb/go.mod @@ -53,9 +53,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/mariadb/go.sum b/modules/mariadb/go.sum index 5ec2f1b6fa..96aef09c5a 100644 --- a/modules/mariadb/go.sum +++ b/modules/mariadb/go.sum @@ -133,8 +133,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -156,14 +156,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/meilisearch/go.mod b/modules/meilisearch/go.mod index e63f289944..2ce7f8b066 100644 --- a/modules/meilisearch/go.mod +++ b/modules/meilisearch/go.mod @@ -54,7 +54,7 @@ require ( go.opentelemetry.io/otel/metric v1.31.0 // indirect go.opentelemetry.io/otel/sdk v1.31.0 // indirect go.opentelemetry.io/otel/trace v1.31.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/time v0.7.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/meilisearch/go.sum b/modules/meilisearch/go.sum index 556ed40640..58b56bee63 100644 --- a/modules/meilisearch/go.sum +++ b/modules/meilisearch/go.sum @@ -130,8 +130,8 @@ go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -155,8 +155,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= diff --git a/modules/milvus/go.mod b/modules/milvus/go.mod index c11bcc5d73..53ac64489c 100644 --- a/modules/milvus/go.mod +++ b/modules/milvus/go.mod @@ -65,10 +65,10 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/grpc v1.64.1 // indirect google.golang.org/protobuf v1.33.0 // indirect diff --git a/modules/milvus/go.sum b/modules/milvus/go.sum index 6666d6eae0..1fe9c4270a 100644 --- a/modules/milvus/go.sum +++ b/modules/milvus/go.sum @@ -343,8 +343,8 @@ golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 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= @@ -410,19 +410,19 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/modules/minio/go.mod b/modules/minio/go.mod index be57f29aef..53e4caa164 100644 --- a/modules/minio/go.mod +++ b/modules/minio/go.mod @@ -61,10 +61,10 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/modules/minio/go.sum b/modules/minio/go.sum index 4bd2ff7754..f1ac4ddea7 100644 --- a/modules/minio/go.sum +++ b/modules/minio/go.sum @@ -153,8 +153,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -177,14 +177,14 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/mockserver/go.mod b/modules/mockserver/go.mod index 8c8fb8fb8f..2c67de0eb5 100644 --- a/modules/mockserver/go.mod +++ b/modules/mockserver/go.mod @@ -54,9 +54,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/mockserver/go.sum b/modules/mockserver/go.sum index cea4315677..5588ff118a 100644 --- a/modules/mockserver/go.sum +++ b/modules/mockserver/go.sum @@ -135,8 +135,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -160,14 +160,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/mongodb/go.mod b/modules/mongodb/go.mod index a1f0450e3f..18d13a4cae 100644 --- a/modules/mongodb/go.mod +++ b/modules/mongodb/go.mod @@ -59,11 +59,11 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/mongodb/go.sum b/modules/mongodb/go.sum index 4255434867..2b2714addd 100644 --- a/modules/mongodb/go.sum +++ b/modules/mongodb/go.sum @@ -150,8 +150,8 @@ 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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -168,8 +168,8 @@ 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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -185,20 +185,20 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/mssql/go.mod b/modules/mssql/go.mod index b9fd2f4677..93217a8b80 100644 --- a/modules/mssql/go.mod +++ b/modules/mssql/go.mod @@ -55,10 +55,10 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/mssql/go.sum b/modules/mssql/go.sum index 0d6c8ec14b..a0079e350c 100644 --- a/modules/mssql/go.sum +++ b/modules/mssql/go.sum @@ -155,8 +155,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -178,14 +178,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/mysql/go.mod b/modules/mysql/go.mod index 9605729d57..a6984fead4 100644 --- a/modules/mysql/go.mod +++ b/modules/mysql/go.mod @@ -54,9 +54,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/mysql/go.sum b/modules/mysql/go.sum index 5ec2f1b6fa..96aef09c5a 100644 --- a/modules/mysql/go.sum +++ b/modules/mysql/go.sum @@ -133,8 +133,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -156,14 +156,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/nats/go.mod b/modules/nats/go.mod index b65abf1dce..d055e61dd1 100644 --- a/modules/nats/go.mod +++ b/modules/nats/go.mod @@ -55,9 +55,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/nats/go.sum b/modules/nats/go.sum index 71e540e367..bb69595f80 100644 --- a/modules/nats/go.sum +++ b/modules/nats/go.sum @@ -137,8 +137,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -160,14 +160,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/neo4j/go.mod b/modules/neo4j/go.mod index 0f73bc4a33..a9ca222a30 100644 --- a/modules/neo4j/go.mod +++ b/modules/neo4j/go.mod @@ -53,9 +53,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/neo4j/go.sum b/modules/neo4j/go.sum index 1311c05d5f..b7d1b4f201 100644 --- a/modules/neo4j/go.sum +++ b/modules/neo4j/go.sum @@ -133,8 +133,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -156,14 +156,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/ollama/go.mod b/modules/ollama/go.mod index 3fb6b744ea..b3a1b1e5c2 100644 --- a/modules/ollama/go.mod +++ b/modules/ollama/go.mod @@ -54,9 +54,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/ollama/go.sum b/modules/ollama/go.sum index 9e203cb685..87536fd72c 100644 --- a/modules/ollama/go.sum +++ b/modules/ollama/go.sum @@ -136,8 +136,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -159,14 +159,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/openfga/go.mod b/modules/openfga/go.mod index 3d01ff49dd..2a0c0d9df8 100644 --- a/modules/openfga/go.mod +++ b/modules/openfga/go.mod @@ -53,10 +53,10 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/openfga/go.sum b/modules/openfga/go.sum index 485a6b769f..21cf8ea02c 100644 --- a/modules/openfga/go.sum +++ b/modules/openfga/go.sum @@ -135,8 +135,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -160,14 +160,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/openldap/go.mod b/modules/openldap/go.mod index 76d3e619cb..fcf3aa4677 100644 --- a/modules/openldap/go.mod +++ b/modules/openldap/go.mod @@ -55,9 +55,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/openldap/go.sum b/modules/openldap/go.sum index 6b65a59a24..35bec868a2 100644 --- a/modules/openldap/go.sum +++ b/modules/openldap/go.sum @@ -143,8 +143,8 @@ 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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -180,23 +180,23 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/opensearch/go.mod b/modules/opensearch/go.mod index 10a1985601..0712f43830 100644 --- a/modules/opensearch/go.mod +++ b/modules/opensearch/go.mod @@ -52,9 +52,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/opensearch/go.sum b/modules/opensearch/go.sum index afea3b1fff..447eec4038 100644 --- a/modules/opensearch/go.sum +++ b/modules/opensearch/go.sum @@ -131,8 +131,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -154,14 +154,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/postgres/go.mod b/modules/postgres/go.mod index d1cee777d0..ac70814b3d 100644 --- a/modules/postgres/go.mod +++ b/modules/postgres/go.mod @@ -58,11 +58,11 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/postgres/go.sum b/modules/postgres/go.sum index 09dfe64dce..e12245f686 100644 --- a/modules/postgres/go.sum +++ b/modules/postgres/go.sum @@ -142,8 +142,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -155,8 +155,8 @@ golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= 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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -167,14 +167,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/pulsar/go.mod b/modules/pulsar/go.mod index a2f72c1b32..e65e5f8da4 100644 --- a/modules/pulsar/go.mod +++ b/modules/pulsar/go.mod @@ -80,12 +80,12 @@ require ( go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/atomic v1.7.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/mod v0.16.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/term v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/term v0.25.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect diff --git a/modules/pulsar/go.sum b/modules/pulsar/go.sum index 89361ee568..0d29f7e91b 100644 --- a/modules/pulsar/go.sum +++ b/modules/pulsar/go.sum @@ -389,8 +389,8 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U 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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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= @@ -530,12 +530,12 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= 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= @@ -544,8 +544,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 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= diff --git a/modules/qdrant/go.mod b/modules/qdrant/go.mod index 752d47238d..d5b28b795a 100644 --- a/modules/qdrant/go.mod +++ b/modules/qdrant/go.mod @@ -54,10 +54,10 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/qdrant/go.sum b/modules/qdrant/go.sum index a0015288c5..98e982016f 100644 --- a/modules/qdrant/go.sum +++ b/modules/qdrant/go.sum @@ -133,8 +133,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -156,14 +156,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/rabbitmq/go.mod b/modules/rabbitmq/go.mod index b0e7b1f331..de71df8704 100644 --- a/modules/rabbitmq/go.mod +++ b/modules/rabbitmq/go.mod @@ -53,9 +53,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/rabbitmq/go.sum b/modules/rabbitmq/go.sum index 07a95eaae0..e7d5675b93 100644 --- a/modules/rabbitmq/go.sum +++ b/modules/rabbitmq/go.sum @@ -138,8 +138,8 @@ go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -161,14 +161,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/redis/go.mod b/modules/redis/go.mod index 48c15ca888..774b7e677e 100644 --- a/modules/redis/go.mod +++ b/modules/redis/go.mod @@ -58,9 +58,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/redis/go.sum b/modules/redis/go.sum index 2c86fe53c0..8ca0c6da81 100644 --- a/modules/redis/go.sum +++ b/modules/redis/go.sum @@ -146,8 +146,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -169,14 +169,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/redpanda/go.mod b/modules/redpanda/go.mod index 4a8a1818a5..9c5065458d 100644 --- a/modules/redpanda/go.mod +++ b/modules/redpanda/go.mod @@ -63,8 +63,8 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/modules/redpanda/go.sum b/modules/redpanda/go.sum index d5a1dff81f..740496f896 100644 --- a/modules/redpanda/go.sum +++ b/modules/redpanda/go.sum @@ -142,8 +142,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= @@ -167,14 +167,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/registry/go.mod b/modules/registry/go.mod index 3cbd358d34..c796908087 100644 --- a/modules/registry/go.mod +++ b/modules/registry/go.mod @@ -52,9 +52,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/registry/go.sum b/modules/registry/go.sum index afea3b1fff..447eec4038 100644 --- a/modules/registry/go.sum +++ b/modules/registry/go.sum @@ -131,8 +131,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -154,14 +154,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/surrealdb/go.mod b/modules/surrealdb/go.mod index e208dc8736..8af514ae28 100644 --- a/modules/surrealdb/go.mod +++ b/modules/surrealdb/go.mod @@ -54,9 +54,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/surrealdb/go.sum b/modules/surrealdb/go.sum index 25e6634a3d..059e8ac355 100644 --- a/modules/surrealdb/go.sum +++ b/modules/surrealdb/go.sum @@ -135,8 +135,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -158,14 +158,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/valkey/go.mod b/modules/valkey/go.mod index 4eff8cc363..1b4105c155 100644 --- a/modules/valkey/go.mod +++ b/modules/valkey/go.mod @@ -55,9 +55,9 @@ require ( go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect - golang.org/x/crypto v0.25.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.22.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/valkey/go.sum b/modules/valkey/go.sum index 20d81e13fc..19e158d82c 100644 --- a/modules/valkey/go.sum +++ b/modules/valkey/go.sum @@ -130,8 +130,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -151,14 +151,14 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/vault/go.mod b/modules/vault/go.mod index e980b8852e..3109854195 100644 --- a/modules/vault/go.mod +++ b/modules/vault/go.mod @@ -62,9 +62,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect golang.org/x/time v0.3.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect diff --git a/modules/vault/go.sum b/modules/vault/go.sum index 0fd470dc49..09d227fcfe 100644 --- a/modules/vault/go.sum +++ b/modules/vault/go.sum @@ -160,8 +160,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -183,14 +183,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/vearch/go.mod b/modules/vearch/go.mod index 963de6fed3..596be1a7f8 100644 --- a/modules/vearch/go.mod +++ b/modules/vearch/go.mod @@ -52,9 +52,9 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/vearch/go.sum b/modules/vearch/go.sum index afea3b1fff..447eec4038 100644 --- a/modules/vearch/go.sum +++ b/modules/vearch/go.sum @@ -131,8 +131,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -154,14 +154,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/weaviate/go.mod b/modules/weaviate/go.mod index fa87e7e537..e99308f1f5 100644 --- a/modules/weaviate/go.mod +++ b/modules/weaviate/go.mod @@ -72,11 +72,11 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/protobuf v1.33.0 // indirect diff --git a/modules/weaviate/go.sum b/modules/weaviate/go.sum index 9f06fcd049..da152d0a52 100644 --- a/modules/weaviate/go.sum +++ b/modules/weaviate/go.sum @@ -264,8 +264,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -310,20 +310,20 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/modules/yugabytedb/go.mod b/modules/yugabytedb/go.mod index 68d69de42f..57d7f8b64b 100644 --- a/modules/yugabytedb/go.mod +++ b/modules/yugabytedb/go.mod @@ -56,8 +56,8 @@ require ( go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/sys v0.26.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/modules/yugabytedb/go.sum b/modules/yugabytedb/go.sum index 188e4bba97..4fa4e1cea6 100644 --- a/modules/yugabytedb/go.sum +++ b/modules/yugabytedb/go.sum @@ -147,8 +147,8 @@ go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v8 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -170,14 +170,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/port_forwarding.go b/port_forwarding.go index b892768d56..bb6bae2393 100644 --- a/port_forwarding.go +++ b/port_forwarding.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net" + "sync" "time" "github.com/docker/docker/api/types/container" @@ -206,183 +207,221 @@ func newSshdContainer(ctx context.Context, opts ...ContainerCustomizer) (*sshdCo return sshd, fmt.Errorf("generic container: %w", err) } - sshClientConfig, err := configureSSHConfig(ctx, sshd) - if err != nil { - // return the container and the error to the caller to handle it + if err = sshd.clientConfig(ctx); err != nil { + // Return the container and the error to the caller to handle it. return sshd, err } - sshd.sshConfig = sshClientConfig - return sshd, nil } // sshdContainer represents the SSHD container type used for the port forwarding container. -// It's an internal type that extends the DockerContainer type, to add the SSH tunneling capabilities. +// It's an internal type that extends the DockerContainer type, to add the SSH tunnelling capabilities. type sshdContainer struct { Container port string sshConfig *ssh.ClientConfig - portForwarders []PortForwarder + portForwarders []*portForwarder } // Terminate stops the container and closes the SSH session func (sshdC *sshdContainer) Terminate(ctx context.Context) error { - sshdC.closePorts(ctx) - - return sshdC.Container.Terminate(ctx) + return errors.Join( + sshdC.closePorts(), + sshdC.Container.Terminate(ctx), + ) } // Stop stops the container and closes the SSH session func (sshdC *sshdContainer) Stop(ctx context.Context, timeout *time.Duration) error { - sshdC.closePorts(ctx) - - return sshdC.Container.Stop(ctx, timeout) + return errors.Join( + sshdC.closePorts(), + sshdC.Container.Stop(ctx, timeout), + ) } // closePorts closes all port forwarders. -func (sshdC *sshdContainer) closePorts(ctx context.Context) { +func (sshdC *sshdContainer) closePorts() error { + var errs []error for _, pfw := range sshdC.portForwarders { - pfw.Close(ctx) + if err := pfw.Close(); err != nil { + errs = append(errs, err) + } } sshdC.portForwarders = nil // Ensure the port forwarders are not used after closing. + return errors.Join(errs...) } -func configureSSHConfig(ctx context.Context, sshdC *sshdContainer) (*ssh.ClientConfig, error) { +// clientConfig sets up the the SSHD client configuration. +func (sshdC *sshdContainer) clientConfig(ctx context.Context) error { mappedPort, err := sshdC.MappedPort(ctx, sshPort) if err != nil { - return nil, fmt.Errorf("mapped port: %w", err) + return fmt.Errorf("mapped port: %w", err) } - sshdC.port = mappedPort.Port() - sshConfig := ssh.ClientConfig{ + sshdC.port = mappedPort.Port() + sshdC.sshConfig = &ssh.ClientConfig{ User: user, HostKeyCallback: ssh.InsecureIgnoreHostKey(), Auth: []ssh.AuthMethod{ssh.Password(sshPassword)}, - Timeout: 30 * time.Second, } - return &sshConfig, nil + return nil } -func (sshdC *sshdContainer) exposeHostPort(ctx context.Context, ports ...int) error { +// exposeHostPort exposes the host ports to the container. +func (sshdC *sshdContainer) exposeHostPort(ctx context.Context, ports ...int) (err error) { + defer func() { + if err != nil { + err = errors.Join(err, sshdC.closePorts()) + } + }() for _, port := range ports { - pw := NewPortForwarder("localhost:"+sshdC.port, sshdC.sshConfig, port, port) - sshdC.portForwarders = append(sshdC.portForwarders, *pw) - - go pw.Forward(ctx) //nolint:errcheck // Nothing we can usefully do with the error - } - - var err error + pf, err := newPortForwarder(ctx, "localhost:"+sshdC.port, sshdC.sshConfig, port) + if err != nil { + return fmt.Errorf("new port forwarder: %w", err) + } - // continue when all port forwarders have created the connection - for _, pfw := range sshdC.portForwarders { - err = errors.Join(err, <-pfw.connectionCreated) + sshdC.portForwarders = append(sshdC.portForwarders, pf) } - return err + return nil } -type PortForwarder struct { - sshDAddr string - sshConfig *ssh.ClientConfig - remotePort int - localPort int - connectionCreated chan error // used to signal that the connection has been created, so the caller can proceed - terminateChan chan struct{} // used to signal that the connection has been terminated +// portForwarder forwards a port from the container to the host. +type portForwarder struct { + client *ssh.Client + listener net.Listener + dialTimeout time.Duration + localAddr string + ctx context.Context + cancel context.CancelFunc + + // closeMtx protects the close operation + closeMtx sync.Mutex + closeErr error } -func NewPortForwarder(sshDAddr string, sshConfig *ssh.ClientConfig, remotePort, localPort int) *PortForwarder { - return &PortForwarder{ - sshDAddr: sshDAddr, - sshConfig: sshConfig, - remotePort: remotePort, - localPort: localPort, - connectionCreated: make(chan error), - terminateChan: make(chan struct{}), +// newPortForwarder creates a new running portForwarder for the given port. +// The context is only used for the initial SSH connection. +func newPortForwarder(ctx context.Context, sshDAddr string, sshConfig *ssh.ClientConfig, port int) (pf *portForwarder, err error) { + var d net.Dialer + conn, err := d.DialContext(ctx, "tcp", sshDAddr) + if err != nil { + return nil, fmt.Errorf("ssh dial: %w", err) } -} -func (pf *PortForwarder) Close(ctx context.Context) { - close(pf.terminateChan) - close(pf.connectionCreated) -} + // Ensure the connection is closed in case of error. + defer func() { + if err != nil { + err = errors.Join(err, conn.Close()) + } + }() -func (pf *PortForwarder) Forward(ctx context.Context) error { - client, err := ssh.Dial("tcp", pf.sshDAddr, pf.sshConfig) + c, chans, reqs, err := ssh.NewClientConn(conn, sshDAddr, sshConfig) if err != nil { - err = fmt.Errorf("error dialing ssh server: %w", err) - pf.connectionCreated <- err - return err + return nil, fmt.Errorf("ssh new client conn: %w", err) } - defer client.Close() - listener, err := client.Listen("tcp", fmt.Sprintf("localhost:%d", pf.remotePort)) + client := ssh.NewClient(c, chans, reqs) + + listener, err := client.Listen("tcp", fmt.Sprintf("localhost:%d", port)) if err != nil { - err = fmt.Errorf("error listening on remote port: %w", err) - pf.connectionCreated <- err - return err + return nil, fmt.Errorf("listening on remote port %d: %w", port, err) + } + + ctx, cancel := context.WithCancel(context.Background()) + + pf = &portForwarder{ + client: client, + listener: listener, + localAddr: fmt.Sprintf("localhost:%d", port), + ctx: ctx, + cancel: cancel, + dialTimeout: time.Second * 2, } - defer listener.Close() - // signal that the connection has been created - pf.connectionCreated <- nil + go pf.run() + + return pf, nil +} + +// Close closes the port forwarder. +func (pf *portForwarder) Close() error { + pf.closeMtx.Lock() + defer pf.closeMtx.Unlock() - // check if the context or the terminateChan has been closed select { - case <-ctx.Done(): - if err := listener.Close(); err != nil { - return fmt.Errorf("error closing listener: %w", err) - } - if err := client.Close(); err != nil { - return fmt.Errorf("error closing client: %w", err) - } - return nil - case <-pf.terminateChan: - if err := listener.Close(); err != nil { - return fmt.Errorf("error closing listener: %w", err) - } - if err := client.Close(); err != nil { - return fmt.Errorf("error closing client: %w", err) - } - return nil + case <-pf.ctx.Done(): + // Already closed. + return pf.closeErr default: } + var errs []error + if err := pf.listener.Close(); err != nil { + errs = append(errs, fmt.Errorf("close listener: %w", err)) + } + if err := pf.client.Close(); err != nil { + errs = append(errs, fmt.Errorf("close client: %w", err)) + } + + pf.closeErr = errors.Join(errs...) + pf.cancel() + + return pf.closeErr +} + +// run forwards the port from the remote connection to the local connection. +func (pf *portForwarder) run() { for { - remote, err := listener.Accept() + remote, err := pf.listener.Accept() if err != nil { - return fmt.Errorf("error accepting connection: %w", err) + if errors.Is(err, io.EOF) { + // The listener has been closed. + return + } + + // Ignore errors as they are transient and we want requests to + // continue to be accepted. + continue } - go pf.runTunnel(ctx, remote) + go pf.tunnel(remote) } } -// runTunnel runs a tunnel between two connections; as soon as one connection -// reaches EOF or reports an error, both connections are closed and this -// function returns. -func (pf *PortForwarder) runTunnel(ctx context.Context, remote net.Conn) { +// tunnel runs a tunnel between two connections; as soon as the forwarder +// context is cancelled or one connection copies returns, irrespective of +// the error, both connections are closed. +func (pf *portForwarder) tunnel(remote net.Conn) { + defer remote.Close() + + ctx, cancel := context.WithTimeout(pf.ctx, pf.dialTimeout) + defer cancel() + var dialer net.Dialer - local, err := dialer.DialContext(ctx, "tcp", fmt.Sprintf("localhost:%d", pf.localPort)) + local, err := dialer.DialContext(ctx, "tcp", pf.localAddr) if err != nil { - remote.Close() + // Nothing we can do with the error. return } defer local.Close() - defer remote.Close() - done := make(chan struct{}, 2) + ctx, cancel = context.WithCancel(pf.ctx) go func() { - io.Copy(local, remote) //nolint:errcheck // Nothing we can usefully do with the error - done <- struct{}{} + defer cancel() + io.Copy(local, remote) //nolint:errcheck // Nothing useful we can do with the error. }() go func() { - io.Copy(remote, local) //nolint:errcheck // Nothing we can usefully do with the error - done <- struct{}{} + defer cancel() + io.Copy(remote, local) //nolint:errcheck // Nothing useful we can do with the error. }() - <-done + // Wait for the context to be done before returning which triggers + // both connections to close. This is done to to prevent the copies + // blocking forever on unused connections. + <-ctx.Done() } diff --git a/port_forwarding_test.go b/port_forwarding_test.go index 9d336ddb96..d6395b20a7 100644 --- a/port_forwarding_test.go +++ b/port_forwarding_test.go @@ -28,9 +28,7 @@ func TestExposeHostPorts(t *testing.T) { fmt.Fprint(w, expectedResponse) })) hostPorts[i] = server.Listener.Addr().(*net.TCPAddr).Port - t.Cleanup(func() { - server.Close() - }) + t.Cleanup(server.Close) } singlePort := hostPorts[0:1] @@ -71,11 +69,18 @@ func TestExposeHostPorts(t *testing.T) { func testExposeHostPorts(t *testing.T, hostPorts []int, hasNetwork, hasHostAccess bool) { t.Helper() + ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + + var hostAccessPorts []int + if hasHostAccess { + hostAccessPorts = hostPorts + } req := testcontainers.GenericContainerRequest{ // hostAccessPorts { ContainerRequest: testcontainers.ContainerRequest{ Image: "alpine:3.17", - HostAccessPorts: hostPorts, + HostAccessPorts: hostAccessPorts, Cmd: []string{"top"}, }, // } @@ -83,7 +88,7 @@ func testExposeHostPorts(t *testing.T, hostPorts []int, hasNetwork, hasHostAcces } if hasNetwork { - nw, err := network.New(context.Background()) + nw, err := network.New(ctx) require.NoError(t, err) testcontainers.CleanupNetwork(t, nw) @@ -91,26 +96,22 @@ func testExposeHostPorts(t *testing.T, hostPorts []int, hasNetwork, hasHostAcces req.NetworkAliases = map[string][]string{nw.Name: {"myalpine"}} } - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - c, err := testcontainers.GenericContainer(ctx, req) testcontainers.CleanupContainer(t, c) require.NoError(t, err) if hasHostAccess { - // Create a container that has host access, which will - // automatically forward the port to the container. - assertContainerHasHostAccess(t, c, hostPorts...) + // Verify that the container can access the host ports. + containerHasHostAccess(t, c, hostPorts...) return } - // Force cancellation. - cancel() - - assertContainerHasNoHostAccess(t, c, hostPorts...) + // Verify that the container cannot access the host ports. + containerHasNoHostAccess(t, c, hostPorts...) } +// httpRequest sends an HTTP request from the container to the host port via +// [testcontainers.HostInternal] address. func httpRequest(t *testing.T, c testcontainers.Container, port int) (int, string) { t.Helper() ctx, cancel := context.WithTimeout(context.Background(), time.Second) @@ -132,21 +133,24 @@ func httpRequest(t *testing.T, c testcontainers.Container, port int) (int, strin return code, string(bs) } -func assertContainerHasHostAccess(t *testing.T, c testcontainers.Container, ports ...int) { +// containerHasHostAccess verifies that the container can access the host ports +// via [testcontainers.HostInternal] address. +func containerHasHostAccess(t *testing.T, c testcontainers.Container, ports ...int) { t.Helper() for _, port := range ports { code, response := httpRequest(t, c, port) - require.Zerof(t, code, "expected status code [%d] but got [%d]", 0, code) - - require.Equalf(t, expectedResponse, response, "expected [%s] but got [%s]", expectedResponse, response) + require.Zero(t, code) + require.Equal(t, expectedResponse, response) } } -func assertContainerHasNoHostAccess(t *testing.T, c testcontainers.Container, ports ...int) { +// containerHasNoHostAccess verifies that the container cannot access the host ports +// via [testcontainers.HostInternal] address. +func containerHasNoHostAccess(t *testing.T, c testcontainers.Container, ports ...int) { t.Helper() for _, port := range ports { - _, response := httpRequest(t, c, port) - - require.NotEqualf(t, expectedResponse, response, "expected not to get [%s] but got [%s]", expectedResponse, response) + code, response := httpRequest(t, c, port) + require.NotZero(t, code) + require.Contains(t, response, "bad address") } }