diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1231cabf86..46668391e9 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,4 +1,5 @@ -# This file is autogenerated by the modulegen code generator. Please look at the generator code when updating it. +# This file is autogenerated by the 'modulegen' tool. +# Please look at the generator code when updating it. version: 2 updates: - package-ecosystem: github-actions @@ -213,6 +214,17 @@ updates: all: patterns: - '*' + - package-ecosystem: gomod + directory: /modules/mariadb + schedule: + interval: monthly + day: sunday + open-pull-requests-limit: 3 + rebase-strategy: disabled + groups: + all: + patterns: + - '*' - package-ecosystem: gomod directory: /modules/mongodb schedule: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3adf6cc31..25d102efdb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,16 +1,22 @@ +# This file is autogenerated by the 'modulegen' tool. +# Please update the 'ci.yml' template instead. name: Main pipeline on: push: + branches: + - main paths-ignore: - - 'mkdocs.yml' - - 'docs/**' - - 'README.md' + - '.vscode/**' + - 'mkdocs.yml' + - 'docs/**' + - 'README.md' pull_request: paths-ignore: - - 'mkdocs.yml' - - 'docs/**' - - 'README.md' + - '.vscode/**' + - 'mkdocs.yml' + - 'docs/**' + - 'README.md' concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.sha }} @@ -86,7 +92,7 @@ jobs: matrix: go-version: [1.20.x, 1.x] platform: [ubuntu-latest, macos-latest] - module: [artemis, clickhouse, compose, couchbase, k3s, localstack, mongodb, mysql, neo4j, postgres, pulsar, redis, redpanda, vault] + module: [artemis, clickhouse, compose, couchbase, k3s, localstack, mariadb, mongodb, mysql, neo4j, postgres, pulsar, redis, redpanda, vault] 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 new file mode 100644 index 0000000000..9fc20fb09f --- /dev/null +++ b/.vscode/.testcontainers-go.code-workspace @@ -0,0 +1,113 @@ +// This file is autogenerated by the 'modulegen' tool. +{ + "folders": [ + { + "name": "testcontainers-go", + "path": "../" + }, + { + "name": "example / bigtable", + "path": "../examples/bigtable" + }, + { + "name": "example / cockroachdb", + "path": "../examples/cockroachdb" + }, + { + "name": "example / consul", + "path": "../examples/consul" + }, + { + "name": "example / datastore", + "path": "../examples/datastore" + }, + { + "name": "example / firestore", + "path": "../examples/firestore" + }, + { + "name": "example / nats", + "path": "../examples/nats" + }, + { + "name": "example / nginx", + "path": "../examples/nginx" + }, + { + "name": "example / pubsub", + "path": "../examples/pubsub" + }, + { + "name": "example / spanner", + "path": "../examples/spanner" + }, + { + "name": "example / toxiproxy", + "path": "../examples/toxiproxy" + }, + { + "name": "module / artemis", + "path": "../modules/artemis" + }, + { + "name": "module / clickhouse", + "path": "../modules/clickhouse" + }, + { + "name": "module / compose", + "path": "../modules/compose" + }, + { + "name": "module / couchbase", + "path": "../modules/couchbase" + }, + { + "name": "module / k3s", + "path": "../modules/k3s" + }, + { + "name": "module / localstack", + "path": "../modules/localstack" + }, + { + "name": "module / mariadb", + "path": "../modules/mariadb" + }, + { + "name": "module / mongodb", + "path": "../modules/mongodb" + }, + { + "name": "module / mysql", + "path": "../modules/mysql" + }, + { + "name": "module / neo4j", + "path": "../modules/neo4j" + }, + { + "name": "module / postgres", + "path": "../modules/postgres" + }, + { + "name": "module / pulsar", + "path": "../modules/pulsar" + }, + { + "name": "module / redis", + "path": "../modules/redis" + }, + { + "name": "module / redpanda", + "path": "../modules/redpanda" + }, + { + "name": "module / vault", + "path": "../modules/vault" + }, + { + "name": "modulegen", + "path": "../modulegen" + } + ] +} \ No newline at end of file diff --git a/config_test.go b/config_test.go index e2c803b904..85a7f8bba7 100644 --- a/config_test.go +++ b/config_test.go @@ -17,6 +17,9 @@ func resetTestEnv(t *testing.T) { func TestReadConfig(t *testing.T) { resetTestEnv(t) + t.Cleanup(func() { + config.Reset() + }) t.Run("Config is read just once", func(t *testing.T) { t.Setenv("HOME", "") diff --git a/container.go b/container.go index 7dbd544ff2..a0bf8ce3e5 100644 --- a/container.go +++ b/container.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "path/filepath" + "strings" "time" "github.com/docker/docker/api/types" @@ -14,6 +15,7 @@ import ( "github.com/docker/docker/api/types/registry" "github.com/docker/docker/pkg/archive" "github.com/docker/go-connections/nat" + "github.com/google/uuid" tcexec "github.com/testcontainers/testcontainers-go/exec" "github.com/testcontainers/testcontainers-go/internal/testcontainersdocker" @@ -63,6 +65,8 @@ type Container interface { type ImageBuildInfo interface { GetContext() (io.Reader, error) // the path to the build context GetDockerfile() string // the relative path to the Dockerfile, including the fileitself + GetRepo() string // get repo label for image + GetTag() string // get tag label for image ShouldPrintBuildLog() bool // allow build log to be printed to stdout ShouldBuildImage() bool // return true if the image needs to be built GetBuildArgs() map[string]*string // return the environment args used to build the from Dockerfile @@ -72,9 +76,11 @@ type ImageBuildInfo interface { // FromDockerfile represents the parameters needed to build an image from a Dockerfile // rather than using a pre-built one type FromDockerfile struct { - Context string // the path to the context of of the docker build + 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 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 BuildArgs map[string]*string // enable user to pass build args to docker daemon PrintBuildLog bool // enable user to print build log AuthConfigs map[string]registry.AuthConfig // Deprecated. Testcontainers will detect registry credentials automatically. Enable auth configs to be able to pull from an authenticated docker registry @@ -205,6 +211,26 @@ func (c *ContainerRequest) GetDockerfile() string { return f } +// GetRepo returns the Repo label for image from the ContainerRequest, defaults to UUID +func (c *ContainerRequest) GetRepo() string { + r := c.FromDockerfile.Repo + if r == "" { + return uuid.NewString() + } + + return strings.ToLower(r) +} + +// GetTag returns the Tag label for image from the ContainerRequest, defaults to UUID +func (c *ContainerRequest) GetTag() string { + t := c.FromDockerfile.Tag + if t == "" { + return uuid.NewString() + } + + return strings.ToLower(t) +} + // GetAuthConfigs returns the auth configs to be able to pull from an authenticated docker registry func (c *ContainerRequest) GetAuthConfigs() map[string]registry.AuthConfig { images, err := testcontainersdocker.ExtractImagesFromDockerfile(filepath.Join(c.Context, c.GetDockerfile()), c.GetBuildArgs()) diff --git a/container_test.go b/container_test.go index b417822986..c3c12dcbfe 100644 --- a/container_test.go +++ b/container_test.go @@ -139,6 +139,7 @@ func Test_BuildImageWithContexts(t *testing.T) { testCases := []TestCase{ { Name: "test build from context archive", + // fromDockerfileWithContextArchive { ContextArchive: func() (io.Reader, error) { var buf bytes.Buffer tarWriter := tar.NewWriter(&buf) @@ -179,6 +180,7 @@ func Test_BuildImageWithContexts(t *testing.T) { return reader, nil }, + // } ExpectedEchoOutput: "this is from the archive", }, { diff --git a/docker.go b/docker.go index 5a2fb1865c..c47d7c1f62 100644 --- a/docker.go +++ b/docker.go @@ -773,10 +773,7 @@ var _ ContainerProvider = (*DockerProvider)(nil) // BuildImage will build and image from context and Dockerfile, then return the tag func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (string, error) { - repo := uuid.New() - tag := uuid.New() - - repoTag := fmt.Sprintf("%s:%s", repo, tag) + repoTag := fmt.Sprintf("%s:%s", img.GetRepo(), img.GetTag()) buildContext, err := img.GetContext() if err != nil { diff --git a/docker_test.go b/docker_test.go index d09f5f33eb..0fda265344 100644 --- a/docker_test.go +++ b/docker_test.go @@ -1059,9 +1059,11 @@ 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" - t.Log("got ctx, creating container request") req := ContainerRequest{ FromDockerfile: FromDockerfile{ Context: filepath.Join(".", "testdata"), @@ -1073,6 +1075,7 @@ func Test_BuildContainerFromDockerfileWithBuildArgs(t *testing.T) { ExposedPorts: []string{"8080/tcp"}, WaitingFor: wait.ForLog("ready"), } + // } genContainerReq := GenericContainerRequest{ ProviderType: providerType, diff --git a/docs/features/build_from_dockerfile.md b/docs/features/build_from_dockerfile.md index 8eec645374..349c4a24c9 100644 --- a/docs/features/build_from_dockerfile.md +++ b/docs/features/build_from_dockerfile.md @@ -7,14 +7,12 @@ You can do so by specifying a `Context` (the filepath to the build context on your local filesystem) and optionally a `Dockerfile` (defaults to "Dockerfile") like so: -```go -req := ContainerRequest{ - FromDockerfile: testcontainers.FromDockerfile{ - Context: "/path/to/build/context", - Dockerfile: "CustomDockerfile", - }, - } -``` + +[Building From a Dockerfile including Repository and Tag](../../from_dockerfile_test.go) inside_block:fromDockerfileIncludingRepo + + +As you can see, you can also specify the `Repo` and `Tag` optional fields to use for the image. If not passed, the +image will be built with a random name and tag. If your Dockerfile expects build args: @@ -26,18 +24,10 @@ ARG FOO ``` You can specify them like: -```go -val := "BAR" -req := ContainerRequest{ - FromDockerfile: testcontainers.FromDockerfile{ - Context: "/path/to/build/context", - Dockerfile: "CustomDockerfile", - BuildArgs: map[string]*string { - "FOO": &val, - }, - }, - } -``` + +[Building From a Dockerfile including build arguments](../../docker_test.go) inside_block:fromDockerfileWithBuildArgs + + ## Dynamic Build Context If you would like to send a build context that you created in code (maybe you have a dynamic Dockerfile), you can diff --git a/docs/modules/index.md b/docs/modules/index.md index 85c463200b..b5d8f23ff8 100644 --- a/docs/modules/index.md +++ b/docs/modules/index.md @@ -24,6 +24,7 @@ We have provided a command line tool to generate the scaffolding for the code of - a new Nav entry for the module in the docs site, adding it to the `mkdocs.yml` file located at the root directory of the project. - a GitHub workflow file in the .github/workflows directory to run the tests for the example. - an entry in Dependabot's configuration file, in order to receive dependency updates. +- an entry in the VSCode workspace file, in order to include the new module in the project's workspace. ### Command line flags diff --git a/docs/modules/mariadb.md b/docs/modules/mariadb.md new file mode 100644 index 0000000000..58adb2a6fc --- /dev/null +++ b/docs/modules/mariadb.md @@ -0,0 +1,123 @@ +# MariaDB + +Not available until the next release of testcontainers-go :material-tag: main + +## Introduction + +The Testcontainers module for MariaDB. + +## Adding this module to your project dependencies + +Please run the following command to add the MariaDB module to your Go dependencies: + +``` +go get github.com/testcontainers/testcontainers-go/modules/mariadb +``` + +## Usage example + + +[Creating a MariaDB container](../../modules/mariadb/mariadb_test.go) inside_block:createMariaDBContainer + + +## Module reference + +The MariaDB module exposes one entrypoint function to create the MariaDB container, and this function receives two parameters: + +```golang +func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*MariaDBContainer, error) +``` + +- `context.Context`, the Go context. +- `testcontainers.ContainerCustomizer`, a variadic argument for passing options. + +### Container Options + +When starting the MariaDB container, you can pass options in a variadic way to configure it. + +!!!tip + + You can find all the available configuration and environment variables for the MariaDB Docker image on [Docker Hub](https://hub.docker.com/_/mariadb). + +#### Image + +If you need to set a different MariaDB Docker image, you can use `testcontainers.WithImage` with a valid Docker image +for MariaDB. E.g. `testcontainers.WithImage("mariadb:11.0.3")`. + + +[Custom Image](../../modules/mariadb/mariadb_test.go) inside_block:withConfigFile + + +!!!info + From MariaDB [docs](https://github.com/docker-library/docs/tree/master/mariadb#environment-variables): + + From tag 10.2.38, 10.3.29, 10.4.19, 10.5.10 onwards, and all 10.6 and later tags, + the `MARIADB_*` equivalent variables are provided. `MARIADB_*` variants will always be + used in preference to `MYSQL_*` variants. + +The MariaDB module will take all the environment variables that start with `MARIADB_` and duplicate them with the `MYSQL_` prefix. + +#### Wait Strategies + +If you need to set a different wait strategy for MariaDB, you can use `testcontainers.WithWaitStrategy` with a valid wait strategy +for MariaDB. + +!!!info + The default deadline for the wait strategy is 60 seconds. + +At the same time, it's possible to set a wait strategy and a custom deadline with `testcontainers.WithWaitStrategyAndDeadline`. + +#### Docker type modifiers + +If you need an advanced configuration for MariaDB, you can leverage the following Docker type modifiers: + +- `testcontainers.WithConfigModifier` +- `testcontainers.WithHostConfigModifier` +- `testcontainers.WithEndpointSettingsModifier` + +Please read the [Create containers: Advanced Settings](../features/creating_container.md#advanced-settings) documentation for more information. + +#### Set username, password and database name + +If you need to set a different database, and its credentials, you can use `WithUsername`, `WithPassword`, `WithDatabase` +options. By default, the username, the password and the database name is `test`. + + +[Custom Database initialization](../../modules/mariadb/mariadb_test.go) inside_block:customInitialization + + +!!!info + The default values for the username is `root`, for password is `test` and for the default database name is `test`. + +#### Init Scripts + +If you would like to perform DDL or DML operations in the MariaDB container, add one or more `*.sql`, `*.sql.gz`, or `*.sh` +scripts to the container request. Those files will be copied under `/docker-entrypoint-initdb.d`. + + +[Include init scripts](../../modules/mariadb/mariadb_test.go) inside_block:withScripts + + +#### Custom configuration + +If you need to set a custom configuration, you can use `WithConfigFile` option. + + +[Custom MariaDB config file](../../modules/mariadb/mariadb_test.go) inside_block:withConfigFile + + +### Container Methods + +The MariaDB container exposes the following methods: + +#### ConnectionString + +This method returns the connection string to connect to the MariaDB container, using the default `3306` port. +It's possible to pass extra parameters to the connection string, e.g. `tls=false`, in a variadic way. + +!!!info + By default, MariaDB transmits data between the server and clients without encrypting it. + + +[Get connection string](../../modules/mariadb/mariadb_test.go) inside_block:connectionString + diff --git a/docs/modules/mysql.md b/docs/modules/mysql.md index cd16e4cea8..e5bec3f968 100644 --- a/docs/modules/mysql.md +++ b/docs/modules/mysql.md @@ -108,7 +108,7 @@ If you need to set a custom configuration, you can use `WithConfigFile` option. #### ConnectionString This method returns the connection string to connect to the MySQL container, using the default `3306` port. -It's possible to pass extra parameters to the connection string, e.g. `sslmode=disable` or `application_name=myapp`, in a variadic way. +It's possible to pass extra parameters to the connection string, e.g. `tls=skip-verify` or `application_name=myapp`, in a variadic way. [Get connection string](../../modules/mysql/mysql_test.go) inside_block:connectionString diff --git a/docs/modules/pulsar.md b/docs/modules/pulsar.md index 97ea00d2a6..acc9ea4b77 100644 --- a/docs/modules/pulsar.md +++ b/docs/modules/pulsar.md @@ -30,7 +30,7 @@ where the `tt.opts` are the options to configure the container. See the [Contain ## Module Reference -The Redis module exposes one entrypoint function to create the containerr, and this function receives two parameters: +The Pulsar module exposes one entrypoint function to create the containerr, and this function receives two parameters: ```golang func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*Container, error) diff --git a/docs/modules/redpanda.md b/docs/modules/redpanda.md index 02e6ea33ec..2663570a3c 100644 --- a/docs/modules/redpanda.md +++ b/docs/modules/redpanda.md @@ -55,6 +55,10 @@ for Redpanda. At the same time, it's possible to set a wait strategy and a custom deadline with `testcontainers.WithWaitStrategyAndDeadline`. +#### TLS Encryption + +If you need to enable TLS use `WithTLS` with a valid PEM encoded certificate and key. + #### Docker type modifiers If you need an advanced configuration for Redpanda, you can leverage the following Docker type modifiers: diff --git a/examples/bigtable/go.mod b/examples/bigtable/go.mod index c795f7ed57..10488a596d 100644 --- a/examples/bigtable/go.mod +++ b/examples/bigtable/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( cloud.google.com/go/bigtable v1.19.0 github.com/testcontainers/testcontainers-go v0.23.0 - google.golang.org/api v0.136.0 + google.golang.org/api v0.138.0 google.golang.org/grpc v1.57.0 ) @@ -35,7 +35,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/s2a-go v0.1.4 // indirect + github.com/google/s2a-go v0.1.5 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect diff --git a/examples/bigtable/go.sum b/examples/bigtable/go.sum index 65c6cf6fdc..c954722381 100644 --- a/examples/bigtable/go.sum +++ b/examples/bigtable/go.sum @@ -113,8 +113,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= -github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.5 h1:8IYp3w9nysqv3JH+NJgXJzGbDHzLOTj43BmSkp+O7qg= +github.com/google/s2a-go v0.1.5/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -280,8 +280,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.136.0 h1:e/6enzUE1s4tGPa6Q3ZYShKTtvRc+1Jq0rrafhppmOs= -google.golang.org/api v0.136.0/go.mod h1:XtJfF+V2zgUxelOn5Zs3kECtluMxneJG8ZxUTlLNTPA= +google.golang.org/api v0.138.0 h1:K/tVp05MxNVbHShRw9m7e9VJGdagNeTdMzqPH7AUqr0= +google.golang.org/api v0.138.0/go.mod h1:4xyob8CxC+0GChNBvEUAk8VBKNvYOTWM9T3v3UfRxuY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= diff --git a/examples/cockroachdb/go.mod b/examples/cockroachdb/go.mod index 8efc2494bf..b57d481c0e 100644 --- a/examples/cockroachdb/go.mod +++ b/examples/cockroachdb/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/examples/cockroachdb go 1.20 require ( - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.3.1 github.com/jackc/pgx/v4 v4.18.1 github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.23.0 diff --git a/examples/cockroachdb/go.sum b/examples/cockroachdb/go.sum index c67189cae7..798c9c420a 100644 --- a/examples/cockroachdb/go.sum +++ b/examples/cockroachdb/go.sum @@ -58,8 +58,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= diff --git a/examples/datastore/go.mod b/examples/datastore/go.mod index 7f38964de4..4910b32636 100644 --- a/examples/datastore/go.mod +++ b/examples/datastore/go.mod @@ -3,14 +3,14 @@ module github.com/testcontainers/testcontainers-go/examples/datastore go 1.20 require ( - cloud.google.com/go/datastore v1.13.0 + cloud.google.com/go/datastore v1.14.0 github.com/testcontainers/testcontainers-go v0.23.0 - google.golang.org/api v0.136.0 + google.golang.org/api v0.138.0 google.golang.org/grpc v1.57.0 ) require ( - cloud.google.com/go v0.110.6 // indirect + cloud.google.com/go v0.110.7 // indirect cloud.google.com/go/compute v1.23.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect dario.cat/mergo v1.0.0 // indirect @@ -27,7 +27,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/s2a-go v0.1.4 // indirect + github.com/google/s2a-go v0.1.5 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect @@ -54,7 +54,7 @@ require ( golang.org/x/tools v0.7.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect + google.golang.org/genproto v0.0.0-20230821184602-ccc8af3d0e93 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect google.golang.org/protobuf v1.31.0 // indirect diff --git a/examples/datastore/go.sum b/examples/datastore/go.sum index d1abe91f73..4fff24139d 100644 --- a/examples/datastore/go.sum +++ b/examples/datastore/go.sum @@ -1,13 +1,13 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.110.6 h1:8uYAkj3YHTP/1iwReuHPxLSbdcyc+dSBbzFMrVwDR6Q= -cloud.google.com/go v0.110.6/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= +cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o= +cloud.google.com/go v0.110.7/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/datastore v1.13.0 h1:ktbC66bOQB3HJPQe8qNI1/aiQ77PMu7hD4mzE6uxe3w= -cloud.google.com/go/datastore v1.13.0/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70= +cloud.google.com/go/datastore v1.14.0 h1:Mq0ApTRdLW3/dyiw+DkjTk0+iGIUvkbzaC8sfPwWTH4= +cloud.google.com/go/datastore v1.14.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8= 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-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic= @@ -96,8 +96,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= -github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.5 h1:8IYp3w9nysqv3JH+NJgXJzGbDHzLOTj43BmSkp+O7qg= +github.com/google/s2a-go v0.1.5/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -263,8 +263,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.136.0 h1:e/6enzUE1s4tGPa6Q3ZYShKTtvRc+1Jq0rrafhppmOs= -google.golang.org/api v0.136.0/go.mod h1:XtJfF+V2zgUxelOn5Zs3kECtluMxneJG8ZxUTlLNTPA= +google.golang.org/api v0.138.0 h1:K/tVp05MxNVbHShRw9m7e9VJGdagNeTdMzqPH7AUqr0= +google.golang.org/api v0.138.0/go.mod h1:4xyob8CxC+0GChNBvEUAk8VBKNvYOTWM9T3v3UfRxuY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= @@ -273,8 +273,8 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= +google.golang.org/genproto v0.0.0-20230821184602-ccc8af3d0e93 h1:zv6ieVm8jNcN33At1+APsRISkRgynuWUxUhv6G123jY= +google.golang.org/genproto v0.0.0-20230821184602-ccc8af3d0e93/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 h1:nIgk/EEq3/YlnmVVXVnm14rC2oxgs1o0ong4sD/rd44= google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q= google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 h1:wukfNtZmZUurLN/atp2hiIeTKn7QJWIQdHzqmsOnAOk= diff --git a/examples/firestore/go.mod b/examples/firestore/go.mod index 6ac1c786ce..fc77a2f82e 100644 --- a/examples/firestore/go.mod +++ b/examples/firestore/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( cloud.google.com/go/firestore v1.12.0 github.com/testcontainers/testcontainers-go v0.23.0 - google.golang.org/api v0.136.0 + google.golang.org/api v0.138.0 google.golang.org/grpc v1.57.0 ) @@ -28,7 +28,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/s2a-go v0.1.4 // indirect + github.com/google/s2a-go v0.1.5 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect diff --git a/examples/firestore/go.sum b/examples/firestore/go.sum index 7b9cdcd210..e559a7b397 100644 --- a/examples/firestore/go.sum +++ b/examples/firestore/go.sum @@ -98,8 +98,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= -github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.5 h1:8IYp3w9nysqv3JH+NJgXJzGbDHzLOTj43BmSkp+O7qg= +github.com/google/s2a-go v0.1.5/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -266,8 +266,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.136.0 h1:e/6enzUE1s4tGPa6Q3ZYShKTtvRc+1Jq0rrafhppmOs= -google.golang.org/api v0.136.0/go.mod h1:XtJfF+V2zgUxelOn5Zs3kECtluMxneJG8ZxUTlLNTPA= +google.golang.org/api v0.138.0 h1:K/tVp05MxNVbHShRw9m7e9VJGdagNeTdMzqPH7AUqr0= +google.golang.org/api v0.138.0/go.mod h1:4xyob8CxC+0GChNBvEUAk8VBKNvYOTWM9T3v3UfRxuY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= diff --git a/examples/pubsub/go.mod b/examples/pubsub/go.mod index bf2a83bf1a..24c18f551f 100644 --- a/examples/pubsub/go.mod +++ b/examples/pubsub/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( cloud.google.com/go/pubsub v1.33.0 github.com/testcontainers/testcontainers-go v0.23.0 - google.golang.org/api v0.136.0 + google.golang.org/api v0.138.0 google.golang.org/grpc v1.57.0 ) @@ -28,7 +28,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/s2a-go v0.1.4 // indirect + github.com/google/s2a-go v0.1.5 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect diff --git a/examples/pubsub/go.sum b/examples/pubsub/go.sum index 84dc02ba2e..948df7df89 100644 --- a/examples/pubsub/go.sum +++ b/examples/pubsub/go.sum @@ -99,8 +99,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= -github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.5 h1:8IYp3w9nysqv3JH+NJgXJzGbDHzLOTj43BmSkp+O7qg= +github.com/google/s2a-go v0.1.5/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -264,8 +264,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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/api v0.136.0 h1:e/6enzUE1s4tGPa6Q3ZYShKTtvRc+1Jq0rrafhppmOs= -google.golang.org/api v0.136.0/go.mod h1:XtJfF+V2zgUxelOn5Zs3kECtluMxneJG8ZxUTlLNTPA= +google.golang.org/api v0.138.0 h1:K/tVp05MxNVbHShRw9m7e9VJGdagNeTdMzqPH7AUqr0= +google.golang.org/api v0.138.0/go.mod h1:4xyob8CxC+0GChNBvEUAk8VBKNvYOTWM9T3v3UfRxuY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= diff --git a/examples/spanner/go.mod b/examples/spanner/go.mod index a0ce3ef922..3a0460c9e3 100644 --- a/examples/spanner/go.mod +++ b/examples/spanner/go.mod @@ -3,9 +3,9 @@ module github.com/testcontainers/testcontainers-go/examples/spanner go 1.20 require ( - cloud.google.com/go/spanner v1.47.0 + cloud.google.com/go/spanner v1.49.0 github.com/testcontainers/testcontainers-go v0.23.0 - google.golang.org/api v0.136.0 + google.golang.org/api v0.138.0 google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 google.golang.org/grpc v1.57.0 ) @@ -36,7 +36,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/s2a-go v0.1.4 // indirect + github.com/google/s2a-go v0.1.5 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect diff --git a/examples/spanner/go.sum b/examples/spanner/go.sum index 1c7246b525..fa15202026 100644 --- a/examples/spanner/go.sum +++ b/examples/spanner/go.sum @@ -10,8 +10,8 @@ cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y= cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI= cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= -cloud.google.com/go/spanner v1.47.0 h1:aqiMP8dhsEXgn9K5EZBWxPG7dxIiyM2VaikqeU4iteg= -cloud.google.com/go/spanner v1.47.0/go.mod h1:IXsJwVW2j4UKs0eYDqodab6HgGuA1bViSqW4uH9lfUI= +cloud.google.com/go/spanner v1.49.0 h1:+HY8C4uztU7XyLz3xMi/LCXdetLEOExhvRFJu2NiVXM= +cloud.google.com/go/spanner v1.49.0/go.mod h1:eGj9mQGK8+hkgSVbHNQ06pQ4oS+cyc4tXXd6Dif1KoM= 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-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic= @@ -112,8 +112,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= -github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.5 h1:8IYp3w9nysqv3JH+NJgXJzGbDHzLOTj43BmSkp+O7qg= +github.com/google/s2a-go v0.1.5/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -279,8 +279,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.136.0 h1:e/6enzUE1s4tGPa6Q3ZYShKTtvRc+1Jq0rrafhppmOs= -google.golang.org/api v0.136.0/go.mod h1:XtJfF+V2zgUxelOn5Zs3kECtluMxneJG8ZxUTlLNTPA= +google.golang.org/api v0.138.0 h1:K/tVp05MxNVbHShRw9m7e9VJGdagNeTdMzqPH7AUqr0= +google.golang.org/api v0.138.0/go.mod h1:4xyob8CxC+0GChNBvEUAk8VBKNvYOTWM9T3v3UfRxuY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= diff --git a/examples/toxiproxy/go.mod b/examples/toxiproxy/go.mod index 0afad0d44e..ef101f1e8f 100644 --- a/examples/toxiproxy/go.mod +++ b/examples/toxiproxy/go.mod @@ -3,9 +3,9 @@ module github.com/testcontainers/testcontainers-go/examples/toxiproxy go 1.20 require ( - github.com/Shopify/toxiproxy/v2 v2.5.0 + github.com/Shopify/toxiproxy/v2 v2.6.0 github.com/go-redis/redis/v8 v8.11.5 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.3.1 github.com/testcontainers/testcontainers-go v0.23.0 ) @@ -38,6 +38,7 @@ require ( golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea // indirect golang.org/x/mod v0.9.0 // indirect golang.org/x/net v0.9.0 // indirect + golang.org/x/sync v0.2.0 // indirect golang.org/x/sys v0.11.0 // indirect golang.org/x/tools v0.7.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect diff --git a/examples/toxiproxy/go.sum b/examples/toxiproxy/go.sum index 61e92458b4..73fa33681c 100644 --- a/examples/toxiproxy/go.sum +++ b/examples/toxiproxy/go.sum @@ -7,8 +7,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= -github.com/Shopify/toxiproxy/v2 v2.5.0 h1:i4LPT+qrSlKNtQf5QliVjdP08GyAH8+BUIc9gT0eahc= -github.com/Shopify/toxiproxy/v2 v2.5.0/go.mod h1:yhM2epWtAmel9CB8r2+L+PCmhH6yH2pITaPAo7jxJl0= +github.com/Shopify/toxiproxy/v2 v2.6.0 h1:qAHKkHlGuB31epYq/nE7CJsdVVn8Nn88vBRuRhNWC9g= +github.com/Shopify/toxiproxy/v2 v2.6.0/go.mod h1:RQ4MED2Cw96l+VbfXq85MXYSwVyXoZvaZKkVznD+yrc= 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/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -53,8 +53,8 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= @@ -124,7 +124,8 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= 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.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/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-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/from_dockerfile_test.go b/from_dockerfile_test.go new file mode 100644 index 0000000000..833ff451cd --- /dev/null +++ b/from_dockerfile_test.go @@ -0,0 +1,119 @@ +package testcontainers + +import ( + "context" + "path/filepath" + "strings" + "testing" + + "github.com/docker/docker/api/types" + "github.com/stretchr/testify/assert" +) + +func TestBuildImageFromDockerfile(t *testing.T) { + provider, err := NewDockerProvider() + if err != nil { + t.Fatal(err) + } + defer provider.Close() + + cli := provider.Client() + + ctx := context.Background() + + tag, err := provider.BuildImage(ctx, &ContainerRequest{ + // fromDockerfileIncludingRepo { + FromDockerfile: FromDockerfile{ + Context: filepath.Join("testdata"), + Dockerfile: "echo.Dockerfile", + Repo: "test-repo", + Tag: "test-tag", + }, + // } + }) + assert.Nil(t, err) + assert.Equal(t, "test-repo:test-tag", tag) + + _, _, err = cli.ImageInspectWithRaw(ctx, tag) + assert.Nil(t, err) + + t.Cleanup(func() { + _, err := cli.ImageRemove(ctx, tag, types.ImageRemoveOptions{ + Force: true, + PruneChildren: true, + }) + if err != nil { + t.Fatal(err) + } + }) +} + +func TestBuildImageFromDockerfile_NoRepo(t *testing.T) { + provider, err := NewDockerProvider() + if err != nil { + t.Fatal(err) + } + defer provider.Close() + + cli := provider.Client() + + ctx := context.Background() + + tag, err := provider.BuildImage(ctx, &ContainerRequest{ + FromDockerfile: FromDockerfile{ + Context: filepath.Join("testdata"), + Dockerfile: "echo.Dockerfile", + Repo: "test-repo", + }, + }) + assert.Nil(t, err) + assert.True(t, strings.HasPrefix(tag, "test-repo:")) + + _, _, err = cli.ImageInspectWithRaw(ctx, tag) + assert.Nil(t, err) + + t.Cleanup(func() { + _, err := cli.ImageRemove(ctx, tag, types.ImageRemoveOptions{ + Force: true, + PruneChildren: true, + }) + if err != nil { + t.Fatal(err) + } + }) +} + +func TestBuildImageFromDockerfile_NoTag(t *testing.T) { + provider, err := NewDockerProvider() + if err != nil { + t.Fatal(err) + } + defer provider.Close() + + cli := provider.Client() + + ctx := context.Background() + + tag, err := provider.BuildImage(ctx, &ContainerRequest{ + FromDockerfile: FromDockerfile{ + Context: filepath.Join("testdata"), + Dockerfile: "echo.Dockerfile", + Tag: "test-tag", + }, + }) + assert.Nil(t, err) + assert.True(t, strings.HasSuffix(tag, ":test-tag")) + + _, _, err = cli.ImageInspectWithRaw(ctx, tag) + assert.Nil(t, err) + + t.Cleanup(func() { + _, err := cli.ImageRemove(ctx, tag, types.ImageRemoveOptions{ + Force: true, + PruneChildren: true, + }) + if err != nil { + t.Fatal(err) + } + }) +} diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 6118ee881c..350c9a9ff4 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -26,6 +26,10 @@ func TestReadConfig(t *testing.T) { resetTestEnv(t) t.Run("Config is read just once", func(t *testing.T) { + t.Cleanup(func() { + Reset() + }) + t.Setenv("HOME", "") t.Setenv("USERPROFILE", "") // Windows support t.Setenv("DOCKER_HOST", "") diff --git a/internal/testcontainersdocker/docker_host.go b/internal/testcontainersdocker/docker_host.go index 6d96029a9c..f6ee5b9a50 100644 --- a/internal/testcontainersdocker/docker_host.go +++ b/internal/testcontainersdocker/docker_host.go @@ -212,12 +212,7 @@ func dockerHostFromProperties(ctx context.Context) (string, error) { cfg := config.Read() socketPath := cfg.Host if socketPath != "" { - parsed, err := parseURL(socketPath) - if err != nil { - return "", err - } - - return parsed, nil + return socketPath, nil } return "", ErrDockerSocketNotSetInProperties diff --git a/internal/testcontainersdocker/docker_host_test.go b/internal/testcontainersdocker/docker_host_test.go index 45684e134b..90ded428e6 100644 --- a/internal/testcontainersdocker/docker_host_test.go +++ b/internal/testcontainersdocker/docker_host_test.go @@ -107,6 +107,18 @@ func TestExtractDockerHost(t *testing.T) { assert.Equal(t, "/this/is/a/sample.sock", host) }) + t.Run("Unix Docker Host is passed as docker.host", func(t *testing.T) { + setupDockerSocketNotFound(t) + setupRootlessNotFound(t) + content := "docker.host=" + DockerSocketSchema + "/this/is/a/sample.sock" + + setupTestcontainersProperties(t, content) + + host := extractDockerHost(context.Background()) + + assert.Equal(t, DockerSocketSchema+"/this/is/a/sample.sock", host) + }) + t.Run("Default Docker socket", func(t *testing.T) { setupRootlessNotFound(t) tmpSocket := setupDockerSocket(t) @@ -225,8 +237,8 @@ func TestExtractDockerHost(t *testing.T) { }) t.Run("Docker host is defined in properties", func(t *testing.T) { - tmpSocket := "/this/is/a/sample.sock" - content := "docker.host=unix://" + tmpSocket + tmpSocket := "unix:///this/is/a/sample.sock" + content := "docker.host=" + tmpSocket setupTestcontainersProperties(t, content) @@ -383,6 +395,22 @@ func TestExtractDockerSocketFromClient(t *testing.T) { socket = extractDockerSocketFromClient(ctx, mockCli{OS: "Ubuntu"}) assert.Equal(t, DockerSocketPath, socket) }) + + t.Run("Unix Docker Socket is passed as docker.host property", func(t *testing.T) { + content := "docker.host=" + DockerSocketSchema + "/this/is/a/sample.sock" + setupTestcontainersProperties(t, content) + setupDockerSocketNotFound(t) + + t.Cleanup(resetSocketOverrideFn) + + ctx := context.Background() + os.Unsetenv("TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE") + os.Unsetenv("DOCKER_HOST") + + socket := extractDockerSocketFromClient(ctx, mockCli{OS: "Ubuntu"}) + + assert.Equal(t, "/this/is/a/sample.sock", socket) + }) } func TestInAContainer(t *testing.T) { diff --git a/logconsumer_test.go b/logconsumer_test.go index 05f8d558a6..478557828d 100644 --- a/logconsumer_test.go +++ b/logconsumer_test.go @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/testcontainers/testcontainers-go/internal/config" "github.com/testcontainers/testcontainers-go/wait" ) @@ -253,6 +254,10 @@ func Test_StartStop(t *testing.T) { } func TestContainerLogWithErrClosed(t *testing.T) { + t.Cleanup(func() { + config.Reset() + }) + if providerType == ProviderPodman { t.Skip("Docker-in-Docker does not work with rootless Podman") } diff --git a/mkdocs.yml b/mkdocs.yml index 99b10620e7..40598f89c0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,3 +1,4 @@ +# This file is autogenerated by the 'modulegen' tool. site_name: Testcontainers for Go site_url: https://golang.testcontainers.org plugins: @@ -31,8 +32,8 @@ markdown_extensions: permalink: true - attr_list - pymdownx.emoji: - emoji_index: !!python/name:materialx.emoji.twemoji emoji_generator: !!python/name:materialx.emoji.to_svg + emoji_index: !!python/name:materialx.emoji.twemoji nav: - Home: index.md - Quickstart: quickstart.md @@ -65,6 +66,7 @@ nav: - modules/couchbase.md - modules/k3s.md - modules/localstack.md + - modules/mariadb.md - modules/mongodb.md - modules/mysql.md - modules/neo4j.md diff --git a/modulegen/_template/Makefile.tmpl b/modulegen/_template/Makefile.tmpl index 1435c0a6e5..428c72e006 100644 --- a/modulegen/_template/Makefile.tmpl +++ b/modulegen/_template/Makefile.tmpl @@ -1,5 +1,5 @@ -{{ $lower := ToLower }}include ../../commons-test.mk +include ../../commons-test.mk .PHONY: test test: - $(MAKE) test-{{ $lower }} + $(MAKE) test-{{ . }} diff --git a/modulegen/_template/ci.yml.tmpl b/modulegen/_template/ci.yml.tmpl index 388d891bfc..a457cb2e5f 100644 --- a/modulegen/_template/ci.yml.tmpl +++ b/modulegen/_template/ci.yml.tmpl @@ -1,16 +1,22 @@ +# This file is autogenerated by the 'modulegen' tool. +# Please update the 'ci.yml' template instead. name: Main pipeline on: push: + branches: + - main paths-ignore: - - 'mkdocs.yml' - - 'docs/**' - - 'README.md' + - '.vscode/**' + - 'mkdocs.yml' + - 'docs/**' + - 'README.md' pull_request: paths-ignore: - - 'mkdocs.yml' - - 'docs/**' - - 'README.md' + - '.vscode/**' + - 'mkdocs.yml' + - 'docs/**' + - 'README.md' concurrency: group: {{ "${{ github.workflow }}-${{ github.head_ref || github.sha }}" }} @@ -70,7 +76,7 @@ jobs: strategy: matrix: go-version: [1.20.x, 1.x] - platform: [ubuntu-latest, macos-latest] + platform: [ubuntu-latest, macos-latest, windows-latest] uses: ./.github/workflows/ci-test-go.yml with: go-version: {{ "${{ matrix.go-version }}" }} diff --git a/modulegen/_template/docs_example.md.tmpl b/modulegen/_template/example.md.tmpl similarity index 93% rename from modulegen/_template/docs_example.md.tmpl rename to modulegen/_template/example.md.tmpl index 0d774dfa21..c25ae1fe03 100644 --- a/modulegen/_template/docs_example.md.tmpl +++ b/modulegen/_template/example.md.tmpl @@ -16,13 +16,13 @@ go get github.com/testcontainers/testcontainers-go/{{ ParentDir }}/{{ $lower }} ## Usage example -{{ codeinclude "" }} + [Creating a {{ $title }} container](../../{{ ParentDir }}/{{ $lower }}/{{ $lower }}.go) -{{ codeinclude "" }} + -{{ codeinclude "" }} + [Test for a {{ $title }} container](../../{{ ParentDir }}/{{ $lower }}/{{ $lower }}_test.go) -{{ codeinclude "" }} + ## Module reference diff --git a/modulegen/_template/example_test.go.tmpl b/modulegen/_template/example_test.go.tmpl index db824245d3..d4ade7fa56 100644 --- a/modulegen/_template/example_test.go.tmpl +++ b/modulegen/_template/example_test.go.tmpl @@ -1,4 +1,4 @@ -{{ $lower := ToLower }}{{ $title := Title }}package {{ $lower }} +{{ $entrypoint := Entrypoint }}{{ $lower := ToLower }}{{ $title := Title }}package {{ $lower }} import ( "context" @@ -8,7 +8,7 @@ import ( func Test{{ $title }}(t *testing.T) { ctx := context.Background() - container, err := RunContainer(ctx) + container, err := {{ $entrypoint }}(ctx) if err != nil { t.Fatal(err) } diff --git a/modulegen/_template/go.mod.tmpl b/modulegen/_template/go.mod.tmpl deleted file mode 100644 index 06d90bb26e..0000000000 --- a/modulegen/_template/go.mod.tmpl +++ /dev/null @@ -1,51 +0,0 @@ -{{ $lower := ToLower }}module github.com/testcontainers/testcontainers-go/{{ ParentDir }}/{{ $lower }} - -go 1.20 - -require ( - github.com/testcontainers/testcontainers-go {{ .TCVersion }} -) - -require ( - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/Microsoft/go-winio v0.5.2 // indirect - github.com/cenkalti/backoff/v4 v4.2.0 // indirect - github.com/containerd/containerd v1.6.14 // indirect - github.com/dnephin/pflag v1.0.7 // indirect - github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v20.10.20+incompatible // indirect - github.com/docker/go-connections v0.4.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/fatih/color v1.13.0 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/klauspost/compress v1.15.9 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/moby/patternmatcher v0.5.0 // indirect - github.com/moby/sys/sequential v0.5.0 // indirect - github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f // 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-rc2 // indirect - github.com/opencontainers/runc v1.1.3 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/sirupsen/logrus v1.9.0 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.3.0 // indirect - golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect - golang.org/x/tools v0.1.12 // indirect - google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad // indirect - google.golang.org/grpc v1.47.0 // indirect - google.golang.org/protobuf v1.28.0 // indirect - gotest.tools/v3 v3.4.0 // indirect -) - -replace ( - github.com/testcontainers/testcontainers-go => ../.. -) diff --git a/modulegen/context.go b/modulegen/context.go index 470cd5113c..5453625aaf 100644 --- a/modulegen/context.go +++ b/modulegen/context.go @@ -26,6 +26,10 @@ func (ctx *Context) GithubWorkflowsDir() string { return filepath.Join(ctx.GithubDir(), "workflows") } +func (ctx *Context) GoModFile() string { + return filepath.Join(ctx.RootDir, "go.mod") +} + func (ctx *Context) getModulesByBaseDir(baseDir string) ([]string, error) { dir := filepath.Join(ctx.RootDir, baseDir) @@ -45,6 +49,25 @@ func (ctx *Context) getModulesByBaseDir(baseDir string) ([]string, error) { return dirs, nil } +func (ctx *Context) getMarkdownsFromDir(baseDir string) ([]string, error) { + dir := filepath.Join(ctx.DocsDir(), baseDir) + + allFiles, err := os.ReadDir(dir) + if err != nil { + return nil, err + } + + dirs := make([]string, 0) + + for _, f := range allFiles { + if !f.IsDir() && filepath.Ext(f.Name()) == ".md" { + dirs = append(dirs, f.Name()) + } + } + sort.Strings(dirs) + return dirs, nil +} + func (ctx *Context) GetExamples() ([]string, error) { return ctx.getModulesByBaseDir("examples") } @@ -53,6 +76,22 @@ func (ctx *Context) GetModules() ([]string, error) { return ctx.getModulesByBaseDir("modules") } +func (ctx *Context) GetExamplesDocs() ([]string, error) { + return ctx.getMarkdownsFromDir("examples") +} + +func (ctx *Context) GetModulesDocs() ([]string, error) { + return ctx.getMarkdownsFromDir("modules") +} + func (ctx *Context) MkdocsConfigFile() string { return filepath.Join(ctx.RootDir, "mkdocs.yml") } + +func (ctx *Context) VSCodeWorkspaceFile() string { + return filepath.Join(ctx.RootDir, ".testcontainers-go.code-workspace") +} + +func NewContext(dir string) *Context { + return &Context{RootDir: dir} +} diff --git a/modulegen/context_test.go b/modulegen/context_test.go index 101a1a33cc..2ec8acc2dd 100644 --- a/modulegen/context_test.go +++ b/modulegen/context_test.go @@ -1,4 +1,4 @@ -package main_test +package main import ( "os" @@ -9,14 +9,11 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - main "github.com/testcontainers/testcontainers-go/modulegen" "github.com/testcontainers/testcontainers-go/modulegen/internal/dependabot" ) func TestGetDependabotConfigFile(t *testing.T) { - tmp := t.TempDir() - - ctx := &main.Context{RootDir: filepath.Join(tmp, "testcontainers-go")} + ctx := NewContext(filepath.Join(t.TempDir(), "testcontainers-go")) githubDir := ctx.GithubDir() cfgFile := ctx.DependabotConfigFile() @@ -33,9 +30,7 @@ func TestGetDependabotConfigFile(t *testing.T) { } func TestExamplesHasDependabotEntry(t *testing.T) { - rootDir, err := getRootDir() - require.NoError(t, err) - ctx := &main.Context{RootDir: rootDir} + ctx := getTestRootContext(t) examples, err := ctx.GetExamples() require.NoError(t, err) dependabotUpdates, err := dependabot.GetUpdates(ctx.DependabotConfigFile()) @@ -69,9 +64,7 @@ func TestExamplesHasDependabotEntry(t *testing.T) { } func TestModulesHasDependabotEntry(t *testing.T) { - rootDir, err := getRootDir() - require.NoError(t, err) - ctx := &main.Context{RootDir: rootDir} + ctx := getTestRootContext(t) modules, err := ctx.GetModules() require.NoError(t, err) dependabotUpdates, err := dependabot.GetUpdates(ctx.DependabotConfigFile()) @@ -103,11 +96,8 @@ func TestModulesHasDependabotEntry(t *testing.T) { } } -func getRootDir() (string, error) { +func getTestRootContext(t *testing.T) *Context { current, err := os.Getwd() - if err != nil { - return "", err - } - - return filepath.Dir(current), nil + require.NoError(t, err) + return NewContext(filepath.Dir(current)) } diff --git a/modulegen/dependabot.go b/modulegen/dependabot.go new file mode 100644 index 0000000000..4c05b90a17 --- /dev/null +++ b/modulegen/dependabot.go @@ -0,0 +1,11 @@ +package main + +import ( + "github.com/testcontainers/testcontainers-go/modulegen/internal/dependabot" +) + +// update examples in dependabot +func generateDependabotUpdates(ctx *Context, example Example) error { + directory := "/" + example.ParentDir() + "/" + example.Lower() + return dependabot.UpdateConfig(ctx.DependabotConfigFile(), directory, "gomod") +} diff --git a/modulegen/go.mod b/modulegen/go.mod index df75acc582..ad6db91a6f 100644 --- a/modulegen/go.mod +++ b/modulegen/go.mod @@ -4,6 +4,8 @@ go 1.20 require ( github.com/stretchr/testify v1.8.4 + golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb + golang.org/x/mod v0.11.0 golang.org/x/text v0.12.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/modulegen/go.sum b/modulegen/go.sum index 9981e21553..ae3231352b 100644 --- a/modulegen/go.sum +++ b/modulegen/go.sum @@ -4,6 +4,10 @@ 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/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb h1:mIKbk8weKhSeLH2GmUTrvx8CjkyJmnU1wFmg59CUjFA= +golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/modulegen/internal/dependabot/writer.go b/modulegen/internal/dependabot/writer.go index 611bd63783..0a134f827a 100644 --- a/modulegen/internal/dependabot/writer.go +++ b/modulegen/internal/dependabot/writer.go @@ -2,16 +2,21 @@ package dependabot import ( "os" + "path/filepath" "gopkg.in/yaml.v3" ) func writeConfig(configFile string, config *Config) error { + err := os.MkdirAll(filepath.Dir(configFile), 0o755) + if err != nil { + return err + } data, err := yaml.Marshal(config) if err != nil { return err } - header := "# This file is autogenerated by the modulegen code generator. Please look at the generator code when updating it.\n" + header := "# This file is autogenerated by the 'modulegen' tool.\n# Please look at the generator code when updating it.\n" data = append([]byte(header), data...) - return os.WriteFile(configFile, data, 0o777) + return os.WriteFile(configFile, data, 0o644) } diff --git a/modulegen/internal/make/main.go b/modulegen/internal/make/main.go new file mode 100644 index 0000000000..a511445549 --- /dev/null +++ b/modulegen/internal/make/main.go @@ -0,0 +1,20 @@ +package make + +import ( + "path/filepath" + "text/template" + + internal_template "github.com/testcontainers/testcontainers-go/modulegen/internal/template" +) + +func Generate(exampleDir string, exampleName string) error { + name := "Makefile.tmpl" + t, err := template.New(name).ParseFiles(filepath.Join("_template", name)) + if err != nil { + return err + } + + exampleFilePath := filepath.Join(exampleDir, "Makefile") + + return internal_template.GenerateFile(t, exampleFilePath, name, exampleName) +} diff --git a/modulegen/internal/mkdocs/main.go b/modulegen/internal/mkdocs/main.go new file mode 100644 index 0000000000..2c49480963 --- /dev/null +++ b/modulegen/internal/mkdocs/main.go @@ -0,0 +1,18 @@ +package mkdocs + +func UpdateConfig(configFile string, isModule bool, exampleMd string, indexMd string) error { + config, err := ReadConfig(configFile) + if err != nil { + return err + } + config.addExample(isModule, exampleMd, indexMd) + return writeConfig(configFile, config) +} + +func CopyConfig(configFile string, tmpFile string) error { + config, err := ReadConfig(configFile) + if err != nil { + return err + } + return writeConfig(tmpFile, config) +} diff --git a/modulegen/internal/mkdocs/reader.go b/modulegen/internal/mkdocs/reader.go new file mode 100644 index 0000000000..650d51baea --- /dev/null +++ b/modulegen/internal/mkdocs/reader.go @@ -0,0 +1,23 @@ +package mkdocs + +import ( + "os" + + "gopkg.in/yaml.v3" +) + +func ReadConfig(configFile string) (*Config, error) { + file, err := os.ReadFile(configFile) + if err != nil { + return nil, err + } + + config := &Config{} + + err = yaml.Unmarshal(file, config) + if err != nil { + return nil, err + } + + return config, nil +} diff --git a/modulegen/internal/mkdocs/template.go b/modulegen/internal/mkdocs/template.go new file mode 100644 index 0000000000..8886ae9843 --- /dev/null +++ b/modulegen/internal/mkdocs/template.go @@ -0,0 +1,18 @@ +package mkdocs + +import ( + "path/filepath" + "text/template" + + internal_template "github.com/testcontainers/testcontainers-go/modulegen/internal/template" +) + +func GenerateMdFile(filePath string, funcMap template.FuncMap, example any) error { + name := "example.md.tmpl" + t, err := template.New(name).Funcs(funcMap).ParseFiles(filepath.Join("_template", name)) + if err != nil { + return err + } + + return internal_template.GenerateFile(t, filePath, name, example) +} diff --git a/modulegen/internal/mkdocs/types.go b/modulegen/internal/mkdocs/types.go new file mode 100644 index 0000000000..5e6529af79 --- /dev/null +++ b/modulegen/internal/mkdocs/types.go @@ -0,0 +1,79 @@ +package mkdocs + +import ( + "sort" + "strings" + + "golang.org/x/exp/slices" +) + +type Config struct { + SiteName string `yaml:"site_name"` + SiteURL string `yaml:"site_url"` + Plugins []string `yaml:"plugins"` + Theme struct { + Name string `yaml:"name"` + CustomDir string `yaml:"custom_dir"` + Palette struct { + Scheme string `yaml:"scheme"` + } `yaml:"palette"` + Font struct { + Text string `yaml:"text"` + Code string `yaml:"code"` + } `yaml:"font"` + Logo string `yaml:"logo"` + Favicon string `yaml:"favicon"` + } `yaml:"theme"` + ExtraCSS []string `yaml:"extra_css"` + RepoName string `yaml:"repo_name"` + RepoURL string `yaml:"repo_url"` + MarkdownExtensions []interface{} `yaml:"markdown_extensions"` + Nav []struct { + Home string `yaml:"Home,omitempty"` + Quickstart string `yaml:"Quickstart,omitempty"` + Features []interface{} `yaml:"Features,omitempty"` + Examples []string `yaml:"Examples,omitempty"` + Modules []string `yaml:"Modules,omitempty"` + SystemRequirements []interface{} `yaml:"System Requirements,omitempty"` + Contributing []string `yaml:"Contributing,omitempty"` + GettingHelp string `yaml:"Getting help,omitempty"` + } `yaml:"nav"` + EditURI string `yaml:"edit_uri"` + Extra struct { + LatestVersion string `yaml:"latest_version"` + } `yaml:"extra"` +} + +func (c *Config) addExample(isModule bool, exampleMd string, indexMd string) { + mkdocsExamplesNav := c.Nav[4].Examples + if isModule { + mkdocsExamplesNav = c.Nav[3].Modules + } + + if !slices.Contains(mkdocsExamplesNav, exampleMd) { + + // make sure the index.md is the first element in the list of examples in the nav + examplesNav := make([]string, len(mkdocsExamplesNav)-1) + j := 0 + + for _, exampleNav := range mkdocsExamplesNav { + // filter out the index.md file + if !strings.HasSuffix(exampleNav, "index.md") { + examplesNav[j] = exampleNav + j++ + } + } + + examplesNav = append(examplesNav, exampleMd) + sort.Strings(examplesNav) + + // prepend the index.md file + examplesNav = append([]string{indexMd}, examplesNav...) + + if isModule { + c.Nav[3].Modules = examplesNav + } else { + c.Nav[4].Examples = examplesNav + } + } +} diff --git a/modulegen/internal/mkdocs/writer.go b/modulegen/internal/mkdocs/writer.go new file mode 100644 index 0000000000..4d6a685af6 --- /dev/null +++ b/modulegen/internal/mkdocs/writer.go @@ -0,0 +1,36 @@ +package mkdocs + +import ( + "os" + "path/filepath" + "strings" + + "gopkg.in/yaml.v3" +) + +func writeConfig(configFile string, config *Config) error { + err := os.MkdirAll(filepath.Dir(configFile), 0o755) + if err != nil { + return err + } + data, err := yaml.Marshal(config) + if err != nil { + return err + } + return os.WriteFile(configFile, overrideData(data), 0o644) +} + +// simple solution to replace the empty strings, as mapping those fields +// into the MkDocs config is not supported yet +func overrideData(data []byte) []byte { + content := "# This file is autogenerated by the 'modulegen' tool.\n" + string(data) + content = setEmoji(content, "generator", "to_svg") + content = setEmoji(content, "index", "twemoji") + return []byte(content) +} + +func setEmoji(content string, key string, value string) string { + old := "emoji_" + key + `: ""` + new := "emoji_" + key + ": !!python/name:materialx.emoji." + value + return strings.ReplaceAll(content, old, new) +} diff --git a/modulegen/internal/modfile/main.go b/modulegen/internal/modfile/main.go new file mode 100644 index 0000000000..9fe765da9b --- /dev/null +++ b/modulegen/internal/modfile/main.go @@ -0,0 +1,43 @@ +package modfile + +import ( + "path/filepath" + + "golang.org/x/mod/modfile" +) + +func GenerateModFile(exampleDir string, rootGoModFilePath string, directory string, tcVersion string) error { + rootGoMod, err := readModFile(rootGoModFilePath) + if err != nil { + return err + } + moduleStmt := rootGoMod.Module.Mod.Path + directory + goStmt := rootGoMod.Go.Version + tcPath := rootGoMod.Module.Mod.Path + file, err := newModFile(moduleStmt, goStmt, tcPath, tcVersion) + if err != nil { + return err + } + return writeModFile(filepath.Join(exampleDir, "go.mod"), file) +} + +func newModFile(moduleStmt string, goStmt string, tcPath string, tcVersion string) (*modfile.File, error) { + file := &modfile.File{} + err := file.AddModuleStmt(moduleStmt) + if err != nil { + return nil, err + } + err = file.AddGoStmt(goStmt) + if err != nil { + return nil, err + } + err = file.AddRequire(tcPath, tcVersion) + if err != nil { + return nil, err + } + err = file.AddReplace(tcPath, "", "../..", "") + if err != nil { + return nil, err + } + return file, nil +} diff --git a/modulegen/internal/modfile/reader.go b/modulegen/internal/modfile/reader.go new file mode 100644 index 0000000000..770a6bbf81 --- /dev/null +++ b/modulegen/internal/modfile/reader.go @@ -0,0 +1,15 @@ +package modfile + +import ( + "os" + + "golang.org/x/mod/modfile" +) + +func readModFile(modFilePath string) (*modfile.File, error) { + file, err := os.ReadFile(modFilePath) + if err != nil { + return nil, err + } + return modfile.Parse(modFilePath, file, nil) +} diff --git a/modulegen/internal/modfile/writer.go b/modulegen/internal/modfile/writer.go new file mode 100644 index 0000000000..345ea1d185 --- /dev/null +++ b/modulegen/internal/modfile/writer.go @@ -0,0 +1,20 @@ +package modfile + +import ( + "os" + "path/filepath" + + "golang.org/x/mod/modfile" +) + +func writeModFile(modFilePath string, file *modfile.File) error { + err := os.MkdirAll(filepath.Dir(modFilePath), 0o755) + if err != nil { + return err + } + data, err := file.Format() + if err != nil { + return err + } + return os.WriteFile(modFilePath, data, 0o644) +} diff --git a/modulegen/internal/module/main.go b/modulegen/internal/module/main.go new file mode 100644 index 0000000000..0ef424c093 --- /dev/null +++ b/modulegen/internal/module/main.go @@ -0,0 +1,26 @@ +package module + +import ( + "path/filepath" + "strings" + "text/template" + + internal_template "github.com/testcontainers/testcontainers-go/modulegen/internal/template" +) + +func GenerateFiles(exampleDir string, exampleName string, funcMap template.FuncMap, example any) error { + for _, tmpl := range []string{"example_test.go", "example.go"} { + name := tmpl + ".tmpl" + t, err := template.New(name).Funcs(funcMap).ParseFiles(filepath.Join("_template", name)) + if err != nil { + return err + } + exampleFilePath := filepath.Join(exampleDir, strings.ReplaceAll(tmpl, "example", exampleName)) + + err = internal_template.GenerateFile(t, exampleFilePath, name, example) + if err != nil { + return err + } + } + return nil +} diff --git a/modulegen/internal/template/main.go b/modulegen/internal/template/main.go new file mode 100644 index 0000000000..9581a37abf --- /dev/null +++ b/modulegen/internal/template/main.go @@ -0,0 +1,34 @@ +package template + +import ( + "io" + "os" + "path/filepath" + "text/template" +) + +// Generate writes the template to the writer, interpolating the data. +func Generate(t *template.Template, wr io.Writer, name string, data any) error { + err := t.ExecuteTemplate(wr, name, data) + if err != nil { + return err + } + return nil +} + +// GenerateFile generates a file from a template. It will create the directory if it does not exist, +// finally calling the Generate function to perform the interpolation. +func GenerateFile(t *template.Template, exampleFilePath string, name string, data any) error { + err := os.MkdirAll(filepath.Dir(exampleFilePath), 0o755) + if err != nil { + return err + } + + exampleFile, err := os.Create(exampleFilePath) + if err != nil { + return err + } + defer exampleFile.Close() + + return Generate(t, exampleFile, name, data) +} diff --git a/modulegen/internal/tools/exec.go b/modulegen/internal/tools/exec.go new file mode 100644 index 0000000000..5d5136ddaa --- /dev/null +++ b/modulegen/internal/tools/exec.go @@ -0,0 +1,19 @@ +package tools + +import ( + "os/exec" +) + +func GoModTidy(cmdDir string) error { + return runGoCommand(cmdDir, "mod", "tidy") +} + +func GoVet(cmdDir string) error { + return runGoCommand(cmdDir, "vet", "./...") +} + +func runGoCommand(cmdDir string, args ...string) error { + cmd := exec.Command("go", args...) + cmd.Dir = cmdDir + return cmd.Run() +} diff --git a/modulegen/internal/vscode/main.go b/modulegen/internal/vscode/main.go new file mode 100644 index 0000000000..cce7c24f1e --- /dev/null +++ b/modulegen/internal/vscode/main.go @@ -0,0 +1,13 @@ +package vscode + +import ( + "path/filepath" +) + +func Generate(rootDir string, examples []string, modules []string) error { + config := newConfig(examples, modules) + + exampleFilePath := filepath.Join(rootDir, ".vscode", ".testcontainers-go.code-workspace") + + return writeConfig(exampleFilePath, config) +} diff --git a/modulegen/internal/vscode/types.go b/modulegen/internal/vscode/types.go new file mode 100644 index 0000000000..7b5a91467d --- /dev/null +++ b/modulegen/internal/vscode/types.go @@ -0,0 +1,42 @@ +package vscode + +import ( + "sort" +) + +type Config struct { + Folders []Folder `json:"folders"` +} + +type Folder struct { + Name string `json:"name"` + Path string `json:"path"` +} + +func newConfig(examples []string, modules []string) *Config { + config := Config{ + Folders: []Folder{ + { + Path: "../modulegen", + Name: "modulegen", + }, + }, + } + for _, example := range examples { + config.Folders = append(config.Folders, Folder{ + Path: "../examples/" + example, + Name: "example / " + example, + }) + } + for _, module := range modules { + config.Folders = append(config.Folders, Folder{ + Path: "../modules/" + module, + Name: "module / " + module, + }) + } + sort.Slice(config.Folders, func(i, j int) bool { return config.Folders[i].Name < config.Folders[j].Name }) + config.Folders = append([]Folder{ + {Path: "../", Name: "testcontainers-go"}, + }, config.Folders...) + return &config +} diff --git a/modulegen/internal/vscode/writer.go b/modulegen/internal/vscode/writer.go new file mode 100644 index 0000000000..5b3d4915f2 --- /dev/null +++ b/modulegen/internal/vscode/writer.go @@ -0,0 +1,21 @@ +package vscode + +import ( + "encoding/json" + "os" + "path/filepath" +) + +func writeConfig(configFile string, config *Config) error { + err := os.MkdirAll(filepath.Dir(configFile), 0o755) + if err != nil { + return err + } + data, err := json.MarshalIndent(config, "", " ") + if err != nil { + return err + } + header := "// This file is autogenerated by the 'modulegen' tool.\n" + data = append([]byte(header), data...) + return os.WriteFile(configFile, data, 0o644) +} diff --git a/modulegen/internal/workflow/main.go b/modulegen/internal/workflow/main.go new file mode 100644 index 0000000000..5b2b8d4f13 --- /dev/null +++ b/modulegen/internal/workflow/main.go @@ -0,0 +1,21 @@ +package workflow + +import ( + "path/filepath" + "text/template" + + internal_template "github.com/testcontainers/testcontainers-go/modulegen/internal/template" +) + +func Generate(githubWorkflowsDir string, examples []string, modules []string) error { + projectDirectories := newProjectDirectories(examples, modules) + name := "ci.yml.tmpl" + t, err := template.New(name).ParseFiles(filepath.Join("_template", name)) + if err != nil { + return err + } + + exampleFilePath := filepath.Join(githubWorkflowsDir, "ci.yml") + + return internal_template.GenerateFile(t, exampleFilePath, name, projectDirectories) +} diff --git a/modulegen/internal/workflow/types.go b/modulegen/internal/workflow/types.go new file mode 100644 index 0000000000..77433613fb --- /dev/null +++ b/modulegen/internal/workflow/types.go @@ -0,0 +1,17 @@ +package workflow + +import ( + "strings" +) + +type ProjectDirectories struct { + Examples string + Modules string +} + +func newProjectDirectories(examples []string, modules []string) *ProjectDirectories { + return &ProjectDirectories{ + Examples: strings.Join(examples, ", "), + Modules: strings.Join(modules, ", "), + } +} diff --git a/modulegen/main.go b/modulegen/main.go index 2b7eb9ad03..63a9536367 100644 --- a/modulegen/main.go +++ b/modulegen/main.go @@ -3,20 +3,10 @@ package main import ( "flag" "fmt" - "html/template" "os" - "os/exec" "path/filepath" - "regexp" - "sort" - "strings" - "unicode" - "unicode/utf8" - "golang.org/x/text/cases" - "golang.org/x/text/language" - - "github.com/testcontainers/testcontainers-go/modulegen/internal/dependabot" + "github.com/testcontainers/testcontainers-go/modulegen/internal/tools" ) var ( @@ -26,10 +16,6 @@ var ( imageVar string ) -var templates = []string{ - "ci.yml", "docs_example.md", "example_test.go", "example.go", "go.mod", "Makefile", -} - func init() { flag.StringVar(&nameVar, "name", "", "Name of the example. Only alphabetical characters are allowed.") flag.StringVar(&nameTitleVar, "title", "", "(Optional) Title of the example name, used to override the name in the case of mixed casing (Mongodb -> MongoDB). Use camel-case when needed. Only alphabetical characters are allowed.") @@ -37,80 +23,6 @@ func init() { flag.BoolVar(&asModuleVar, "as-module", false, "If set, the example will be generated as a Go module, under the modules directory. Otherwise, it will be generated as a subdirectory of the examples directory.") } -type Example struct { - Image string // fully qualified name of the Docker image - IsModule bool // if true, the example will be generated as a Go module - Name string - TitleName string // title of the name: e.g. "mongodb" -> "MongoDB" - TCVersion string // Testcontainers for Go version -} - -// 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 (e *Example) ContainerName() string { - name := e.Lower() - - if e.IsModule { - name = e.Title() - } else { - if e.TitleName != "" { - r, n := utf8.DecodeRuneInString(e.TitleName) - name = string(unicode.ToLower(r)) + e.TitleName[n:] - } - } - - return name + "Container" -} - -// Entrypoint returns the name of the entrypoint function, which is the lower-cased title of the example -// If the example is a module, the entrypoint will be "RunContainer" -func (e *Example) Entrypoint() string { - if e.IsModule { - return "RunContainer" - } - - return "runContainer" -} - -func (e *Example) Lower() string { - return strings.ToLower(e.Name) -} - -func (e *Example) ParentDir() string { - if e.IsModule { - return "modules" - } - - return "examples" -} - -func (e *Example) Title() string { - if e.TitleName != "" { - return e.TitleName - } - - return cases.Title(language.Und, cases.NoLower).String(e.Lower()) -} - -func (e *Example) Type() string { - if e.IsModule { - return "module" - } - return "example" -} - -func (e *Example) Validate() error { - if !regexp.MustCompile(`^[A-Za-z][A-Za-z0-9]*$`).MatchString(e.Name) { - return fmt.Errorf("invalid name: %s. Only alphanumerical characters are allowed (leading character must be a letter)", e.Name) - } - - if !regexp.MustCompile(`^[A-Za-z][A-Za-z0-9]*$`).MatchString(e.TitleName) { - return fmt.Errorf("invalid title: %s. Only alphanumerical characters are allowed (leading character must be a letter)", e.TitleName) - } - - return nil -} - func main() { required := []string{"name", "image"} flag.Parse() @@ -125,41 +37,32 @@ func main() { } } - currentDir, err := filepath.Abs(filepath.Dir(".")) + ctx, err := getRootContext() if err != nil { fmt.Printf(">> could not get the root dir: %v\n", err) os.Exit(1) } - rootDir := filepath.Dir(currentDir) - - mkdocsConfig, err := readMkdocsConfig(rootDir) - if err != nil { - fmt.Printf(">> could not read MkDocs config: %v\n", err) - os.Exit(1) - } - example := Example{ Image: imageVar, IsModule: asModuleVar, Name: nameVar, TitleName: nameTitleVar, - TCVersion: mkdocsConfig.Extra.LatestVersion, } - err = generate(example, rootDir) + err = generate(example, ctx) if err != nil { fmt.Printf(">> error generating the example: %v\n", err) os.Exit(1) } - cmdDir := filepath.Join(rootDir, example.ParentDir(), example.Lower()) - err = runGoCommand(cmdDir, "mod", "tidy") + cmdDir := filepath.Join(ctx.RootDir, example.ParentDir(), example.Lower()) + err = tools.GoModTidy(cmdDir) if err != nil { fmt.Printf(">> error synchronizing the dependencies: %v\n", err) os.Exit(1) } - err = runGoCommand(cmdDir, "vet", "./...") + err = tools.GoVet(cmdDir) if err != nil { fmt.Printf(">> error checking generated code: %v\n", err) os.Exit(1) @@ -170,208 +73,48 @@ func main() { fmt.Println("Thanks!") } -func generate(example Example, rootDir string) error { +func generate(example Example, ctx *Context) error { if err := example.Validate(); err != nil { return err } - ctx := &Context{RootDir: rootDir} - - githubWorkflowsDir := ctx.GithubWorkflowsDir() - outputDir := filepath.Join(rootDir, example.ParentDir()) - docsOuputDir := filepath.Join(ctx.DocsDir(), example.ParentDir()) - - funcMap := template.FuncMap{ - "Entrypoint": func() string { return example.Entrypoint() }, - "ContainerName": func() string { return example.ContainerName() }, - "ExampleType": func() string { return example.Type() }, - "ParentDir": func() string { return example.ParentDir() }, - "ToLower": func() string { return example.Lower() }, - "Title": func() string { return example.Title() }, - "codeinclude": func(s string) template.HTML { return template.HTML(s) }, // escape HTML comments for codeinclude + // creates Makefile for example + err := generateMakefile(ctx, example) + if err != nil { + return err } - exampleLower := example.Lower() - - // create the example dir - err := os.MkdirAll(filepath.Join(outputDir, exampleLower), 0o700) + err = generateGoModule(ctx, example) if err != nil { return err } - for _, tmpl := range templates { - name := tmpl + ".tmpl" - t, err := template.New(name).Funcs(funcMap).ParseFiles(filepath.Join("_template", name)) - if err != nil { - return err - } - - // initialize the data using the example struct, which is the default data to be used while - // doing the interpolation of the data and the template - var data any - - syncDataFn := func() any { - return example - } - - // create a new file - var exampleFilePath string - - if strings.EqualFold(tmpl, "docs_example.md") { - // docs example file will go into the docs directory - exampleFilePath = filepath.Join(docsOuputDir, exampleLower+".md") - } else if strings.EqualFold(tmpl, "ci.yml") { - // GitHub workflow file will go into the .github/workflows directory - exampleFilePath = filepath.Join(githubWorkflowsDir, "ci.yml") - - type stringsList struct { - Examples string - Modules string - } - - syncDataFn = func() any { - modulesList, err := getModulesOrExamplesAsString(true) - if err != nil { - return "" - } - examplesList, err := getModulesOrExamplesAsString(false) - if err != nil { - return "" - } - - return stringsList{ - Examples: examplesList, - Modules: modulesList, - } - } - } else { - exampleFilePath = filepath.Join(outputDir, exampleLower, strings.ReplaceAll(tmpl, "example", exampleLower)) - } - - err = os.MkdirAll(filepath.Dir(exampleFilePath), 0o777) - if err != nil { - return err - } - - exampleFile, _ := os.Create(exampleFilePath) - defer exampleFile.Close() - - data = syncDataFn() - - err = t.ExecuteTemplate(exampleFile, name, data) - if err != nil { - return err - } + // update github ci workflow + err = generateWorkFlow(ctx) + if err != nil { + return err } - // update examples in mkdocs - err = generateMkdocs(rootDir, example) + err = generateMkdocs(ctx, example) if err != nil { return err } - // update examples in dependabot err = generateDependabotUpdates(ctx, example) if err != nil { return err } - - return nil -} - -func generateDependabotUpdates(ctx *Context, example Example) error { - // update examples in dependabot - directory := "/" + example.ParentDir() + "/" + example.Lower() - return dependabot.UpdateConfig(ctx.DependabotConfigFile(), directory, "gomod") -} - -func generateMkdocs(rootDir string, example Example) error { - // update examples in mkdocs - mkdocsConfig, err := readMkdocsConfig(rootDir) + // generate vscode workspace + err = generateVSCodeWorkspace(ctx) if err != nil { return err } - - mkdocsExamplesNav := mkdocsConfig.Nav[4].Examples - if example.IsModule { - mkdocsExamplesNav = mkdocsConfig.Nav[3].Modules - } - - // make sure the index.md is the first element in the list of examples in the nav - examplesNav := make([]string, len(mkdocsExamplesNav)-1) - j := 0 - - for _, exampleNav := range mkdocsExamplesNav { - // filter out the index.md file - if !strings.HasSuffix(exampleNav, "index.md") { - examplesNav[j] = exampleNav - j++ - } - } - - examplesNav = append(examplesNav, example.ParentDir()+"/"+example.Lower()+".md") - sort.Strings(examplesNav) - - // prepend the index.md file - examplesNav = append([]string{example.ParentDir() + "/index.md"}, examplesNav...) - - if example.IsModule { - mkdocsConfig.Nav[3].Modules = examplesNav - } else { - mkdocsConfig.Nav[4].Examples = examplesNav - } - - return writeMkdocsConfig(rootDir, mkdocsConfig) + return nil } -func getModulesOrExamples(t bool) ([]os.DirEntry, error) { - baseDir := "examples" - if t { - baseDir = "modules" - } - - parent, err := getRootDir() +func getRootContext() (*Context, error) { + current, err := os.Getwd() if err != nil { return nil, err } - - dir := filepath.Join(parent, baseDir) - - allFiles, err := os.ReadDir(dir) - if err != nil { - return nil, err - } - - dirs := make([]os.DirEntry, 0) - - for _, f := range allFiles { - // only accept the directories and not the template - if f.IsDir() && f.Name() != "_template" { - dirs = append(dirs, f) - } - } - - return dirs, nil -} - -func getModulesOrExamplesAsString(t bool) (string, error) { - dirs, err := getModulesOrExamples(t) - if err != nil { - return "", err - } - - // sort the dir names by name - names := make([]string, len(dirs)) - for i, f := range dirs { - names[i] = f.Name() - } - - sort.Strings(names) - - return strings.Join(names, ", "), nil -} - -func runGoCommand(cmdDir string, args ...string) error { - cmd := exec.Command("go", args...) - cmd.Dir = cmdDir - return cmd.Run() + return NewContext(filepath.Dir(current)), nil } diff --git a/modulegen/main_test.go b/modulegen/main_test.go index 617998fdb7..e130345535 100644 --- a/modulegen/main_test.go +++ b/modulegen/main_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/testcontainers/testcontainers-go/modulegen/internal/dependabot" + "github.com/testcontainers/testcontainers-go/modulegen/internal/mkdocs" ) func TestExample(t *testing.T) { @@ -151,10 +152,10 @@ func TestExample_Validate(outer *testing.T) { } func TestGenerateWrongExampleName(t *testing.T) { - rootTmp := t.TempDir() - examplesTmp := filepath.Join(rootTmp, "examples") - examplesDocTmp := filepath.Join(rootTmp, "docs", "examples") - githubWorkflowsTmp := filepath.Join(rootTmp, ".github", "workflows") + tmpCtx := NewContext(t.TempDir()) + examplesTmp := filepath.Join(tmpCtx.RootDir, "examples") + examplesDocTmp := filepath.Join(tmpCtx.DocsDir(), "examples") + githubWorkflowsTmp := tmpCtx.GithubWorkflowsDir() err := os.MkdirAll(examplesTmp, 0o777) assert.Nil(t, err) @@ -163,7 +164,7 @@ func TestGenerateWrongExampleName(t *testing.T) { err = os.MkdirAll(githubWorkflowsTmp, 0o777) assert.Nil(t, err) - err = copyInitialMkdocsConfig(t, rootTmp) + err = copyInitialMkdocsConfig(t, tmpCtx) assert.Nil(t, err) tests := []struct { @@ -183,21 +184,20 @@ func TestGenerateWrongExampleName(t *testing.T) { for _, test := range tests { example := Example{ - Name: test.name, - Image: "docker.io/example/" + test.name + ":latest", - TCVersion: "v0.0.0-test", + Name: test.name, + Image: "docker.io/example/" + test.name + ":latest", } - err = generate(example, rootTmp) + err = generate(example, tmpCtx) assert.Error(t, err) } } func TestGenerateWrongExampleTitle(t *testing.T) { - rootTmp := t.TempDir() - examplesTmp := filepath.Join(rootTmp, "examples") - examplesDocTmp := filepath.Join(rootTmp, "docs", "examples") - githubWorkflowsTmp := filepath.Join(rootTmp, ".github", "workflows") + tmpCtx := NewContext(t.TempDir()) + examplesTmp := filepath.Join(tmpCtx.RootDir, "examples") + examplesDocTmp := filepath.Join(tmpCtx.DocsDir(), "examples") + githubWorkflowsTmp := tmpCtx.GithubWorkflowsDir() err := os.MkdirAll(examplesTmp, 0o777) assert.Nil(t, err) @@ -206,7 +206,7 @@ func TestGenerateWrongExampleTitle(t *testing.T) { err = os.MkdirAll(githubWorkflowsTmp, 0o777) assert.Nil(t, err) - err = copyInitialMkdocsConfig(t, rootTmp) + err = copyInitialMkdocsConfig(t, tmpCtx) assert.Nil(t, err) tests := []struct { @@ -229,19 +229,17 @@ func TestGenerateWrongExampleTitle(t *testing.T) { Name: "foo", TitleName: test.title, Image: "docker.io/example/foo:latest", - TCVersion: "v0.0.0-test", } - err = generate(example, rootTmp) + err = generate(example, tmpCtx) assert.Error(t, err) } } func TestGenerate(t *testing.T) { - rootTmp := t.TempDir() - tmpCtx := &Context{RootDir: rootTmp} - examplesTmp := filepath.Join(rootTmp, "examples") - examplesDocTmp := filepath.Join(rootTmp, "docs", "examples") + tmpCtx := NewContext(t.TempDir()) + examplesTmp := filepath.Join(tmpCtx.RootDir, "examples") + examplesDocTmp := filepath.Join(tmpCtx.DocsDir(), "examples") githubWorkflowsTmp := tmpCtx.GithubWorkflowsDir() err := os.MkdirAll(examplesTmp, 0o777) @@ -251,13 +249,13 @@ func TestGenerate(t *testing.T) { err = os.MkdirAll(githubWorkflowsTmp, 0o777) assert.Nil(t, err) - err = copyInitialMkdocsConfig(t, rootTmp) + err = copyInitialMkdocsConfig(t, tmpCtx) assert.Nil(t, err) - originalConfig, err := readMkdocsConfig(rootTmp) + originalConfig, err := mkdocs.ReadConfig(tmpCtx.MkdocsConfigFile()) assert.Nil(t, err) - err = copyInitialDependabotConfig(t, tmpCtx.DependabotConfigFile()) + err = copyInitialDependabotConfig(t, tmpCtx) assert.Nil(t, err) originalDependabotConfigUpdates, err := dependabot.GetUpdates(tmpCtx.DependabotConfigFile()) @@ -268,19 +266,13 @@ func TestGenerate(t *testing.T) { TitleName: "FooDB4TheWin", IsModule: false, Image: "docker.io/example/foodb:latest", - TCVersion: "v0.0.0-test", } exampleNameLower := example.Lower() - err = generate(example, rootTmp) - assert.Nil(t, err) - - templatesDir, err := os.ReadDir(filepath.Join(".", "_template")) + err = generate(example, tmpCtx) assert.Nil(t, err) exampleDirPath := filepath.Join(examplesTmp, exampleNameLower) - newExampleDir, err := os.ReadDir(exampleDirPath) - assert.Nil(t, err) exampleDirFileInfo, err := os.Stat(exampleDirPath) assert.Nil(t, err) // error nil implies the file exist @@ -294,26 +286,22 @@ func TestGenerate(t *testing.T) { _, err = os.Stat(mainWorkflowFile) assert.Nil(t, err) // error nil implies the file exist - // check the number of template files is equal to examples + 2 (the doc and the github workflow) - assert.Equal(t, len(newExampleDir)+2, len(templatesDir)) - assertExampleDocContent(t, example, exampleDocFile) assertExampleGithubWorkflowContent(t, example, mainWorkflowFile) generatedTemplatesDir := filepath.Join(examplesTmp, exampleNameLower) assertExampleTestContent(t, example, filepath.Join(generatedTemplatesDir, exampleNameLower+"_test.go")) assertExampleContent(t, example, filepath.Join(generatedTemplatesDir, exampleNameLower+".go")) - assertGoModContent(t, example, filepath.Join(generatedTemplatesDir, "go.mod")) + assertGoModContent(t, example, originalConfig.Extra.LatestVersion, filepath.Join(generatedTemplatesDir, "go.mod")) assertMakefileContent(t, example, filepath.Join(generatedTemplatesDir, "Makefile")) - assertMkdocsExamplesNav(t, example, originalConfig, rootTmp) - assertDependabotExamplesUpdates(t, example, originalDependabotConfigUpdates, tmpCtx.DependabotConfigFile()) + assertMkdocsExamplesNav(t, example, originalConfig, tmpCtx) + assertDependabotExamplesUpdates(t, example, originalDependabotConfigUpdates, tmpCtx) } func TestGenerateModule(t *testing.T) { - rootTmp := t.TempDir() - tmpCtx := &Context{RootDir: rootTmp} - modulesTmp := filepath.Join(rootTmp, "modules") - modulesDocTmp := filepath.Join(rootTmp, "docs", "modules") + tmpCtx := NewContext(t.TempDir()) + modulesTmp := filepath.Join(tmpCtx.RootDir, "modules") + modulesDocTmp := filepath.Join(tmpCtx.DocsDir(), "modules") githubWorkflowsTmp := tmpCtx.GithubWorkflowsDir() err := os.MkdirAll(modulesTmp, 0o777) @@ -323,13 +311,13 @@ func TestGenerateModule(t *testing.T) { err = os.MkdirAll(githubWorkflowsTmp, 0o777) assert.Nil(t, err) - err = copyInitialMkdocsConfig(t, rootTmp) + err = copyInitialMkdocsConfig(t, tmpCtx) assert.Nil(t, err) - originalConfig, err := readMkdocsConfig(rootTmp) + originalConfig, err := mkdocs.ReadConfig(tmpCtx.MkdocsConfigFile()) assert.Nil(t, err) - err = copyInitialDependabotConfig(t, tmpCtx.DependabotConfigFile()) + err = copyInitialDependabotConfig(t, tmpCtx) assert.Nil(t, err) originalDependabotConfigUpdates, err := dependabot.GetUpdates(tmpCtx.DependabotConfigFile()) @@ -340,19 +328,13 @@ func TestGenerateModule(t *testing.T) { TitleName: "FooDB", IsModule: true, Image: "docker.io/example/foodb:latest", - TCVersion: "v0.0.0-test", } exampleNameLower := example.Lower() - err = generate(example, rootTmp) - assert.Nil(t, err) - - templatesDir, err := os.ReadDir(filepath.Join(".", "_template")) + err = generate(example, tmpCtx) assert.Nil(t, err) exampleDirPath := filepath.Join(modulesTmp, exampleNameLower) - newExampleDir, err := os.ReadDir(exampleDirPath) - assert.Nil(t, err) exampleDirFileInfo, err := os.Stat(exampleDirPath) assert.Nil(t, err) // error nil implies the file exist @@ -366,24 +348,21 @@ func TestGenerateModule(t *testing.T) { _, err = os.Stat(mainWorkflowFile) assert.Nil(t, err) // error nil implies the file exist - // check the number of template files is equal to examples + 2 (the doc and the github workflow) - assert.Equal(t, len(newExampleDir)+2, len(templatesDir)) - assertExampleDocContent(t, example, exampleDocFile) assertExampleGithubWorkflowContent(t, example, mainWorkflowFile) generatedTemplatesDir := filepath.Join(modulesTmp, exampleNameLower) assertExampleTestContent(t, example, filepath.Join(generatedTemplatesDir, exampleNameLower+"_test.go")) assertExampleContent(t, example, filepath.Join(generatedTemplatesDir, exampleNameLower+".go")) - assertGoModContent(t, example, filepath.Join(generatedTemplatesDir, "go.mod")) + assertGoModContent(t, example, originalConfig.Extra.LatestVersion, filepath.Join(generatedTemplatesDir, "go.mod")) assertMakefileContent(t, example, filepath.Join(generatedTemplatesDir, "Makefile")) - assertMkdocsExamplesNav(t, example, originalConfig, rootTmp) - assertDependabotExamplesUpdates(t, example, originalDependabotConfigUpdates, tmpCtx.DependabotConfigFile()) + assertMkdocsExamplesNav(t, example, originalConfig, tmpCtx) + assertDependabotExamplesUpdates(t, example, originalDependabotConfigUpdates, tmpCtx) } // assert content in the Examples nav from mkdocs.yml -func assertDependabotExamplesUpdates(t *testing.T, example Example, originalConfigUpdates dependabot.Updates, tmpFile string) { - examples, err := dependabot.GetUpdates(tmpFile) +func assertDependabotExamplesUpdates(t *testing.T, example Example, originalConfigUpdates dependabot.Updates, tmpCtx *Context) { + examples, err := dependabot.GetUpdates(tmpCtx.DependabotConfigFile()) assert.Nil(t, err) assert.Equal(t, len(originalConfigUpdates)+1, len(examples)) @@ -447,7 +426,7 @@ func assertExampleTestContent(t *testing.T, example Example, exampleTestFile str data := sanitiseContent(content) assert.Equal(t, data[0], "package "+example.Lower()) assert.Equal(t, data[7], "func Test"+example.Title()+"(t *testing.T) {") - assert.Equal(t, data[10], "\tcontainer, err := RunContainer(ctx)") + assert.Equal(t, data[10], "\tcontainer, err := "+example.Entrypoint()+"(ctx)") } // assert content example @@ -476,24 +455,26 @@ func assertExampleGithubWorkflowContent(t *testing.T, example Example, exampleWo assert.Nil(t, err) data := sanitiseContent(content) + ctx := getTestRootContext(t) - modulesList, err := getModulesOrExamplesAsString(true) + modulesList, err := ctx.GetModules() assert.Nil(t, err) - assert.Equal(t, " module: ["+modulesList+"]", data[88]) + assert.Equal(t, " module: ["+strings.Join(modulesList, ", ")+"]", data[94]) - examplesList, err := getModulesOrExamplesAsString(false) + examplesList, err := ctx.GetExamples() assert.Nil(t, err) - assert.Equal(t, " module: ["+examplesList+"]", data[104]) + assert.Equal(t, " module: ["+strings.Join(examplesList, ", ")+"]", data[110]) } // assert content go.mod -func assertGoModContent(t *testing.T, example Example, goModFile string) { +func assertGoModContent(t *testing.T, example Example, tcVersion string, goModFile string) { content, err := os.ReadFile(goModFile) assert.Nil(t, err) data := sanitiseContent(content) assert.Equal(t, "module github.com/testcontainers/testcontainers-go/"+example.ParentDir()+"/"+example.Lower(), data[0]) - assert.Equal(t, "\tgithub.com/testcontainers/testcontainers-go "+example.TCVersion, data[5]) + assert.Equal(t, "require github.com/testcontainers/testcontainers-go "+tcVersion, data[4]) + assert.Equal(t, "replace github.com/testcontainers/testcontainers-go => ../..", data[6]) } // assert content Makefile @@ -506,8 +487,8 @@ func assertMakefileContent(t *testing.T, example Example, makefile string) { } // assert content in the Examples nav from mkdocs.yml -func assertMkdocsExamplesNav(t *testing.T, example Example, originalConfig *MkDocsConfig, rootDir string) { - config, err := readMkdocsConfig(rootDir) +func assertMkdocsExamplesNav(t *testing.T, example Example, originalConfig *mkdocs.Config, tmpCtx *Context) { + config, err := mkdocs.ReadConfig(tmpCtx.MkdocsConfigFile()) assert.Nil(t, err) parentDir := example.ParentDir() @@ -547,11 +528,7 @@ func sanitiseContent(bytes []byte) []string { return data } -func copyInitialDependabotConfig(t *testing.T, tmpFile string) error { - projectDir, err := getRootDir() - assert.Nil(t, err) - - ctx := &Context{RootDir: projectDir} - - return dependabot.CopyConfig(ctx.DependabotConfigFile(), tmpFile) +func copyInitialDependabotConfig(t *testing.T, tmpCtx *Context) error { + ctx := getTestRootContext(t) + return dependabot.CopyConfig(ctx.DependabotConfigFile(), tmpCtx.DependabotConfigFile()) } diff --git a/modulegen/make.go b/modulegen/make.go new file mode 100644 index 0000000000..49bf4d8533 --- /dev/null +++ b/modulegen/make.go @@ -0,0 +1,14 @@ +package main + +import ( + "path/filepath" + + "github.com/testcontainers/testcontainers-go/modulegen/internal/make" +) + +// creates Makefile for example +func generateMakefile(ctx *Context, example Example) error { + exampleDir := filepath.Join(ctx.RootDir, example.ParentDir(), example.Lower()) + exampleName := example.Lower() + return make.Generate(exampleDir, exampleName) +} diff --git a/modulegen/mkdocs.go b/modulegen/mkdocs.go index ed41f3dfa8..cc94a8b626 100644 --- a/modulegen/mkdocs.go +++ b/modulegen/mkdocs.go @@ -1,102 +1,27 @@ package main import ( - "os" "path/filepath" + "text/template" - "gopkg.in/yaml.v3" + "github.com/testcontainers/testcontainers-go/modulegen/internal/mkdocs" ) -type MkDocsConfig struct { - SiteName string `yaml:"site_name"` - SiteURL string `yaml:"site_url"` - Plugins []string `yaml:"plugins"` - Theme struct { - Name string `yaml:"name"` - CustomDir string `yaml:"custom_dir"` - Palette struct { - Scheme string `yaml:"scheme"` - } `yaml:"palette"` - Font struct { - Text string `yaml:"text"` - Code string `yaml:"code"` - } `yaml:"font"` - Logo string `yaml:"logo"` - Favicon string `yaml:"favicon"` - } `yaml:"theme"` - ExtraCSS []string `yaml:"extra_css"` - RepoName string `yaml:"repo_name"` - RepoURL string `yaml:"repo_url"` - MarkdownExtensions []interface{} `yaml:"markdown_extensions"` - Nav []struct { - Home string `yaml:"Home,omitempty"` - Quickstart string `yaml:"Quickstart,omitempty"` - Features []interface{} `yaml:"Features,omitempty"` - Examples []string `yaml:"Examples,omitempty"` - Modules []string `yaml:"Modules,omitempty"` - SystemRequirements []interface{} `yaml:"System Requirements,omitempty"` - Contributing []string `yaml:"Contributing,omitempty"` - GettingHelp string `yaml:"Getting help,omitempty"` - } `yaml:"nav"` - EditURI string `yaml:"edit_uri"` - Extra struct { - LatestVersion string `yaml:"latest_version"` - } `yaml:"extra"` -} - -func getMkdocsConfigFile(rootDir string) string { - return filepath.Join(rootDir, "mkdocs.yml") -} - -func getExamples() ([]os.DirEntry, error) { - return getModulesOrExamples(false) -} - -func getExamplesDocs() ([]os.DirEntry, error) { - parent, err := getRootDir() - if err != nil { - return nil, err - } - - dir := filepath.Join(parent, "docs", "examples") - - return os.ReadDir(dir) -} - -func getRootDir() (string, error) { - current, err := os.Getwd() - if err != nil { - return "", err - } - - return filepath.Dir(current), nil -} - -func readMkdocsConfig(rootDir string) (*MkDocsConfig, error) { - configFile := getMkdocsConfigFile(rootDir) - - file, err := os.ReadFile(configFile) - if err != nil { - return nil, err - } - - config := &MkDocsConfig{} - - err = yaml.Unmarshal(file, config) - if err != nil { - return nil, err +// update examples in mkdocs +func generateMkdocs(ctx *Context, example Example) error { + exampleMdFile := filepath.Join(ctx.DocsDir(), example.ParentDir(), example.Lower()+".md") + funcMap := template.FuncMap{ + "Entrypoint": func() string { return example.Entrypoint() }, + "ContainerName": func() string { return example.ContainerName() }, + "ParentDir": func() string { return example.ParentDir() }, + "ToLower": func() string { return example.Lower() }, + "Title": func() string { return example.Title() }, } - - return config, nil -} - -func writeMkdocsConfig(rootDir string, config *MkDocsConfig) error { - data, err := yaml.Marshal(config) + err := mkdocs.GenerateMdFile(exampleMdFile, funcMap, example) if err != nil { return err } - - file := getMkdocsConfigFile(rootDir) - - return os.WriteFile(file, data, 0o777) + exampleMd := example.ParentDir() + "/" + example.Lower() + ".md" + indexMd := example.ParentDir() + "/index.md" + return mkdocs.UpdateConfig(ctx.MkdocsConfigFile(), example.IsModule, exampleMd, indexMd) } diff --git a/modulegen/mkdocs_test.go b/modulegen/mkdocs_test.go index d996ecac7c..badce9e442 100644 --- a/modulegen/mkdocs_test.go +++ b/modulegen/mkdocs_test.go @@ -8,36 +8,34 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/testcontainers/testcontainers-go/modulegen/internal/mkdocs" ) func TestGetMkDocsConfigFile(t *testing.T) { - tmp := t.TempDir() - - rootDir := filepath.Join(tmp, "testcontainers-go") - cfgFile := filepath.Join(rootDir, "mkdocs.yml") - err := os.MkdirAll(rootDir, 0o777) + tmpCtx := NewContext(filepath.Join(t.TempDir(), "testcontainers-go")) + cfgFile := tmpCtx.MkdocsConfigFile() + err := os.MkdirAll(tmpCtx.RootDir, 0o777) require.NoError(t, err) err = os.WriteFile(cfgFile, []byte{}, 0o777) require.NoError(t, err) - file := getMkdocsConfigFile(rootDir) + file := tmpCtx.MkdocsConfigFile() require.NotNil(t, file) assert.True(t, strings.HasSuffix(file, filepath.Join("testcontainers-go", "mkdocs.yml"))) } func TestReadMkDocsConfig(t *testing.T) { - tmp := t.TempDir() - - rootDir := filepath.Join(tmp, "testcontainers-go") - err := os.MkdirAll(rootDir, 0o777) + tmpCtx := NewContext(filepath.Join(t.TempDir(), "testcontainers-go")) + err := os.MkdirAll(tmpCtx.RootDir, 0o777) require.NoError(t, err) - err = copyInitialMkdocsConfig(t, rootDir) + err = copyInitialMkdocsConfig(t, tmpCtx) require.NoError(t, err) - config, err := readMkdocsConfig(rootDir) + config, err := mkdocs.ReadConfig(tmpCtx.MkdocsConfigFile()) require.NoError(t, err) require.NotNil(t, config) @@ -58,9 +56,10 @@ func TestReadMkDocsConfig(t *testing.T) { } func TestExamples(t *testing.T) { - examples, err := getExamples() + ctx := getTestRootContext(t) + examples, err := ctx.GetExamples() require.NoError(t, err) - examplesDocs, err := getExamplesDocs() + examplesDocs, err := ctx.GetExamplesDocs() require.NoError(t, err) // we have to remove the index.md file from the examples docs @@ -70,23 +69,18 @@ func TestExamples(t *testing.T) { for _, example := range examples { found := false for _, exampleDoc := range examplesDocs { - markdownName := example.Name() + ".md" + markdownName := example + ".md" - if markdownName == exampleDoc.Name() { + if markdownName == exampleDoc { found = true continue } } - assert.True(t, found, "example %s is not present in the docs", example.Name()) + assert.True(t, found, "example %s is not present in the docs", example) } } -func copyInitialMkdocsConfig(t *testing.T, tmpDir string) error { - projectDir, err := getRootDir() - require.NoError(t, err) - - initialConfig, err := readMkdocsConfig(projectDir) - require.NoError(t, err) - - return writeMkdocsConfig(tmpDir, initialConfig) +func copyInitialMkdocsConfig(t *testing.T, tmpCtx *Context) error { + ctx := getTestRootContext(t) + return mkdocs.CopyConfig(ctx.MkdocsConfigFile(), tmpCtx.MkdocsConfigFile()) } diff --git a/modulegen/module.go b/modulegen/module.go new file mode 100644 index 0000000000..1c73380be6 --- /dev/null +++ b/modulegen/module.go @@ -0,0 +1,47 @@ +package main + +import ( + "fmt" + "path/filepath" + "text/template" + + "github.com/testcontainers/testcontainers-go/modulegen/internal/mkdocs" + "github.com/testcontainers/testcontainers-go/modulegen/internal/modfile" + "github.com/testcontainers/testcontainers-go/modulegen/internal/module" +) + +func generateGoModule(ctx *Context, example Example) error { + exampleDir := filepath.Join(ctx.RootDir, example.ParentDir(), example.Lower()) + err := generateGoFiles(exampleDir, example) + if err != nil { + return err + } + return generateGoModFile(exampleDir, example) +} + +func generateGoFiles(exampleDir string, example Example) error { + funcMap := template.FuncMap{ + "Entrypoint": func() string { return example.Entrypoint() }, + "ContainerName": func() string { return example.ContainerName() }, + "ParentDir": func() string { return example.ParentDir() }, + "ToLower": func() string { return example.Lower() }, + "Title": func() string { return example.Title() }, + } + return module.GenerateFiles(exampleDir, example.Lower(), funcMap, example) +} + +func generateGoModFile(exampleDir string, example Example) error { + rootCtx, err := getRootContext() + if err != nil { + return err + } + mkdocsConfig, err := mkdocs.ReadConfig(rootCtx.MkdocsConfigFile()) + if err != nil { + fmt.Printf(">> could not read MkDocs config: %v\n", err) + return err + } + rootGoModFile := rootCtx.GoModFile() + directory := "/" + example.ParentDir() + "/" + example.Lower() + tcVersion := mkdocsConfig.Extra.LatestVersion + return modfile.GenerateModFile(exampleDir, rootGoModFile, directory, tcVersion) +} diff --git a/modulegen/types.go b/modulegen/types.go new file mode 100644 index 0000000000..d2665c7b5f --- /dev/null +++ b/modulegen/types.go @@ -0,0 +1,86 @@ +package main + +import ( + "fmt" + "regexp" + "strings" + "unicode" + "unicode/utf8" + + "golang.org/x/text/cases" + "golang.org/x/text/language" +) + +type Example struct { + Image string // fully qualified name of the Docker image + IsModule bool // if true, the example will be generated as a Go module + Name string + TitleName string // title of the name: e.g. "mongodb" -> "MongoDB" + TCVersion string // Testcontainers for Go version +} + +// 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 (e *Example) ContainerName() string { + name := e.Lower() + + if e.IsModule { + name = e.Title() + } else { + if e.TitleName != "" { + r, n := utf8.DecodeRuneInString(e.TitleName) + name = string(unicode.ToLower(r)) + e.TitleName[n:] + } + } + + return name + "Container" +} + +// Entrypoint returns the name of the entrypoint function, which is the lower-cased title of the example +// If the example is a module, the entrypoint will be "RunContainer" +func (e *Example) Entrypoint() string { + if e.IsModule { + return "RunContainer" + } + + return "runContainer" +} + +func (e *Example) Lower() string { + return strings.ToLower(e.Name) +} + +func (e *Example) ParentDir() string { + if e.IsModule { + return "modules" + } + + return "examples" +} + +func (e *Example) Title() string { + if e.TitleName != "" { + return e.TitleName + } + + return cases.Title(language.Und, cases.NoLower).String(e.Lower()) +} + +func (e *Example) Type() string { + if e.IsModule { + return "module" + } + return "example" +} + +func (e *Example) Validate() error { + if !regexp.MustCompile(`^[A-Za-z][A-Za-z0-9]*$`).MatchString(e.Name) { + return fmt.Errorf("invalid name: %s. Only alphanumerical characters are allowed (leading character must be a letter)", e.Name) + } + + if !regexp.MustCompile(`^[A-Za-z][A-Za-z0-9]*$`).MatchString(e.TitleName) { + return fmt.Errorf("invalid title: %s. Only alphanumerical characters are allowed (leading character must be a letter)", e.TitleName) + } + + return nil +} diff --git a/modulegen/vscode.go b/modulegen/vscode.go new file mode 100644 index 0000000000..2a1bb3d2ce --- /dev/null +++ b/modulegen/vscode.go @@ -0,0 +1,23 @@ +package main + +import ( + "github.com/testcontainers/testcontainers-go/modulegen/internal/vscode" +) + +// print out the workspace for vscode +func generateVSCodeWorkspace(ctx *Context) error { + rootCtx, err := getRootContext() + if err != nil { + return err + } + examples, err := rootCtx.GetExamples() + if err != nil { + return err + } + modules, err := rootCtx.GetModules() + if err != nil { + return err + } + + return vscode.Generate(rootCtx.RootDir, examples, modules) +} diff --git a/modulegen/workflow.go b/modulegen/workflow.go new file mode 100644 index 0000000000..a0d4f0264e --- /dev/null +++ b/modulegen/workflow.go @@ -0,0 +1,22 @@ +package main + +import ( + "github.com/testcontainers/testcontainers-go/modulegen/internal/workflow" +) + +// update github ci workflow +func generateWorkFlow(ctx *Context) error { + rootCtx, err := getRootContext() + if err != nil { + return err + } + examples, err := rootCtx.GetExamples() + if err != nil { + return err + } + modules, err := rootCtx.GetModules() + if err != nil { + return err + } + return workflow.Generate(ctx.GithubWorkflowsDir(), examples, modules) +} diff --git a/modules/clickhouse/go.mod b/modules/clickhouse/go.mod index a3bd27e6bc..1673a256b0 100644 --- a/modules/clickhouse/go.mod +++ b/modules/clickhouse/go.mod @@ -3,7 +3,7 @@ module github.com/testcontainers/testcontainers-go/modules/clickhouse go 1.20 require ( - github.com/ClickHouse/clickhouse-go/v2 v2.13.0 + github.com/ClickHouse/clickhouse-go/v2 v2.13.3 github.com/docker/go-connections v0.4.0 github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.23.0 @@ -12,7 +12,7 @@ require ( require ( dario.cat/mergo v1.0.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/ClickHouse/ch-go v0.52.1 // indirect + github.com/ClickHouse/ch-go v0.58.2 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/andybalholm/brotli v1.0.5 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect @@ -26,8 +26,8 @@ require ( github.com/go-faster/errors v0.6.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/klauspost/compress v1.16.0 // indirect + github.com/google/uuid v1.3.1 // indirect + github.com/klauspost/compress v1.16.7 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect @@ -37,7 +37,7 @@ require ( github.com/opencontainers/image-spec v1.1.0-rc4 // indirect github.com/opencontainers/runc v1.1.5 // indirect github.com/paulmach/orb v0.10.0 // indirect - github.com/pierrec/lz4/v4 v4.1.17 // 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/segmentio/asm v1.2.0 // indirect diff --git a/modules/clickhouse/go.sum b/modules/clickhouse/go.sum index dd271513e1..054fd9f7de 100644 --- a/modules/clickhouse/go.sum +++ b/modules/clickhouse/go.sum @@ -4,10 +4,10 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1 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 v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/ClickHouse/ch-go v0.52.1 h1:nucdgfD1BDSHjbNaG3VNebonxJzD8fX8jbuBpfo5VY0= -github.com/ClickHouse/ch-go v0.52.1/go.mod h1:B9htMJ0hii/zrC2hljUKdnagRBuLqtRG/GrU3jqCwRk= -github.com/ClickHouse/clickhouse-go/v2 v2.13.0 h1:oP1OlTQIbQKKLnqLzyDhiyNFvN3pbOtM+e/3qdexG9k= -github.com/ClickHouse/clickhouse-go/v2 v2.13.0/go.mod h1:xyL0De2K54/n+HGsdtPuyYJq76wefafaHfGUXTDEq/0= +github.com/ClickHouse/ch-go v0.58.2 h1:jSm2szHbT9MCAB1rJ3WuCJqmGLi5UTjlNu+f530UTS0= +github.com/ClickHouse/ch-go v0.58.2/go.mod h1:Ap/0bEmiLa14gYjCiRkYGbXvbe8vwdrfTYWhsuQ99aw= +github.com/ClickHouse/clickhouse-go/v2 v2.13.3 h1:/esk41SjVLIDQs2rkOmRKXJ1FIFArIJiX6sYG0DUavE= +github.com/ClickHouse/clickhouse-go/v2 v2.13.3/go.mod h1:yoCB//XLqbyqaYvXzdbIdmMafOSomU3erh3r06NLCZU= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= @@ -56,16 +56,16 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= -github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 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= @@ -93,13 +93,13 @@ github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuh github.com/paulmach/orb v0.10.0 h1:guVYVqzxHE/CQ1KpfGO077TR0ATHSNjp4s6XGLn3W9s= github.com/paulmach/orb v0.10.0/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= -github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= -github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 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/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= @@ -154,7 +154,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= 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-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/modules/compose/go.mod b/modules/compose/go.mod index 1f0b39b53f..7b7c24ec4a 100644 --- a/modules/compose/go.mod +++ b/modules/compose/go.mod @@ -8,11 +8,11 @@ replace ( ) require ( - github.com/compose-spec/compose-go v1.18.1 + github.com/compose-spec/compose-go v1.18.3 github.com/docker/cli v24.0.5+incompatible github.com/docker/compose/v2 v2.20.3 github.com/docker/docker v24.0.5+incompatible - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.3.1 github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.23.0 golang.org/x/sync v0.3.0 diff --git a/modules/compose/go.sum b/modules/compose/go.sum index c1462b08b5..f4f04ae6c3 100644 --- a/modules/compose/go.sum +++ b/modules/compose/go.sum @@ -121,8 +121,8 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= -github.com/compose-spec/compose-go v1.18.1 h1:YVYYkV8fAHW/eCOgtqSe1tHrlaDVvwS8zgs6F5ukm/Y= -github.com/compose-spec/compose-go v1.18.1/go.mod h1:zR2tP1+kZHi5vJz7PjpW6oMoDji/Js3GHjP+hfjf70Q= +github.com/compose-spec/compose-go v1.18.3 h1:hiwTZ8ED1l+CB2G2G4LFv/bIaoUfG2ZBalz4S7MOy5w= +github.com/compose-spec/compose-go v1.18.3/go.mod h1:zR2tP1+kZHi5vJz7PjpW6oMoDji/Js3GHjP+hfjf70Q= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= @@ -304,8 +304,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= diff --git a/modules/k3s/go.mod b/modules/k3s/go.mod index bc5ecfbacf..f08bf13d6b 100644 --- a/modules/k3s/go.mod +++ b/modules/k3s/go.mod @@ -8,8 +8,8 @@ require ( github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.23.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/apimachinery v0.27.4 - k8s.io/client-go v0.27.4 + k8s.io/apimachinery v0.28.1 + k8s.io/client-go v0.28.1 ) require ( @@ -23,13 +23,14 @@ require ( github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/emicklei/go-restful/v3 v3.10.1 // indirect - github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect - github.com/go-openapi/jsonreference v0.20.1 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.3.0 // indirect @@ -37,6 +38,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.16.0 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/moby/patternmatcher v0.5.0 // indirect @@ -51,27 +53,33 @@ require ( github.com/opencontainers/runc v1.1.5 // 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.7 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/tklauser/go-sysconf v0.3.11 // indirect + github.com/tklauser/numcpus v0.6.0 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea // indirect - golang.org/x/mod v0.9.0 // indirect - golang.org/x/net v0.9.0 // indirect - golang.org/x/oauth2 v0.7.0 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/net v0.13.0 // indirect + golang.org/x/oauth2 v0.8.0 // indirect golang.org/x/sys v0.11.0 // indirect - golang.org/x/term v0.7.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/term v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.7.0 // indirect + golang.org/x/tools v0.8.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect google.golang.org/grpc v1.57.0 // indirect google.golang.org/protobuf v1.30.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/api v0.27.4 // indirect - k8s.io/klog/v2 v2.90.1 // indirect - k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect - k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect + k8s.io/api v0.28.1 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect + k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect diff --git a/modules/k3s/go.sum b/modules/k3s/go.sum index 56f83d053b..8fbc283060 100644 --- a/modules/k3s/go.sum +++ b/modules/k3s/go.sum @@ -1,4 +1,3 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 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-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic= @@ -10,10 +9,8 @@ github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5 github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= 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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/containerd v1.7.3 h1:cKwYKkP1eTj54bP3wCdXXBymmKRQMrWjkLSWZZJDa8o= github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+HMvaKUNiqCZB8= @@ -37,49 +34,34 @@ github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5Xh github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +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/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= -github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -98,13 +80,14 @@ 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.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 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= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -126,8 +109,8 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= 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/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk= -github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= +github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE= +github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= 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-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= @@ -140,23 +123,28 @@ 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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +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.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/shirou/gopsutil/v3 v3.23.7 h1:C+fHO8hfIppoJ1WdsVm1RoI0RwXoNdfTK7yWXV0wVj4= +github.com/shirou/gopsutil/v3 v3.23.7/go.mod h1:c4gnmoRC0hQuaLqvxnx1//VXQ0Ms/X9UnJF8pddY5z4= +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/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= 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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 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= @@ -164,115 +152,91 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= +github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= +github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= +github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= 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= 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/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea h1:vLCWI/yYrdEHyN2JzIzPO3aaQJHQdp89IZBA/+azVC4= golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 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.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= +golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= 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.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -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= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/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-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= 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.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 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= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 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/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= 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/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= @@ -282,25 +246,22 @@ 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-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0/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.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.27.4 h1:0pCo/AN9hONazBKlNUdhQymmnfLRbSZjd5H5H3f0bSs= -k8s.io/api v0.27.4/go.mod h1:O3smaaX15NfxjzILfiln1D8Z3+gEYpjEpiNA/1EVK1Y= -k8s.io/apimachinery v0.27.4 h1:CdxflD4AF61yewuid0fLl6bM4a3q04jWel0IlP+aYjs= -k8s.io/apimachinery v0.27.4/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= -k8s.io/client-go v0.27.4 h1:vj2YTtSJ6J4KxaC88P4pMPEQECWMY8gqPqsTgUKzvjk= -k8s.io/client-go v0.27.4/go.mod h1:ragcly7lUlN0SRPk5/ZkGnDjPknzb37TICq07WhI6Xc= -k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= -k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= -k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/api v0.28.1 h1:i+0O8k2NPBCPYaMB+uCkseEbawEt/eFaiRqUx8aB108= +k8s.io/api v0.28.1/go.mod h1:uBYwID+66wiL28Kn2tBjBYQdEU0Xk0z5qF8bIBqk/Dg= +k8s.io/apimachinery v0.28.1 h1:EJD40og3GizBSV3mkIoXQBsws32okPOy+MkRyzh6nPY= +k8s.io/apimachinery v0.28.1/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= +k8s.io/client-go v0.28.1 h1:pRhMzB8HyLfVwpngWKE8hDcXRqifh1ga2Z/PU9SXVK8= +k8s.io/client-go v0.28.1/go.mod h1:pEZA3FqOsVkCc07pFVzK076R+P/eXqsgx5zuuRWukNE= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= +k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= diff --git a/modules/localstack/go.mod b/modules/localstack/go.mod index e8029bbc17..609288eef7 100644 --- a/modules/localstack/go.mod +++ b/modules/localstack/go.mod @@ -3,11 +3,11 @@ module github.com/testcontainers/testcontainers-go/modules/localstack go 1.20 require ( - github.com/aws/aws-sdk-go v1.44.322 - github.com/aws/aws-sdk-go-v2 v1.20.1 - github.com/aws/aws-sdk-go-v2/config v1.18.33 - github.com/aws/aws-sdk-go-v2/credentials v1.13.32 - github.com/aws/aws-sdk-go-v2/service/s3 v1.38.2 + github.com/aws/aws-sdk-go v1.44.334 + github.com/aws/aws-sdk-go-v2 v1.21.0 + github.com/aws/aws-sdk-go-v2/config v1.18.37 + github.com/aws/aws-sdk-go-v2/credentials v1.13.35 + github.com/aws/aws-sdk-go-v2/service/s3 v1.38.5 github.com/docker/go-connections v0.4.0 github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.23.0 @@ -18,20 +18,20 @@ 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.1 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.12 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.8 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.32 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.39 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.13 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.33 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.32 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.13.2 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.21.2 // indirect - github.com/aws/smithy-go v1.14.1 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.13 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.11 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.41 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.35 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.42 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.14 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.36 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.35 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.4 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.13.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.21.5 // indirect + github.com/aws/smithy-go v1.14.2 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/containerd/containerd v1.7.3 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect diff --git a/modules/localstack/go.sum b/modules/localstack/go.sum index 8acef922fb..9bb46061de 100644 --- a/modules/localstack/go.sum +++ b/modules/localstack/go.sum @@ -7,44 +7,44 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= -github.com/aws/aws-sdk-go v1.44.322 h1:7JfwifGRGQMHd99PvfXqxBaZsjuRaOF6e3X9zRx2uYo= -github.com/aws/aws-sdk-go v1.44.322/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aws/aws-sdk-go-v2 v1.20.1 h1:rZBf5DWr7YGrnlTK4kgDQGn1ltqOg5orCYb/UhOFZkg= -github.com/aws/aws-sdk-go-v2 v1.20.1/go.mod h1:NU06lETsFm8fUC6ZjhgDpVBcGZTFQ6XM+LZWZxMI4ac= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.12 h1:lN6L3LrYHeZ6xCxaIYtoWCx4GMLk4nRknsh29OMSqHY= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.12/go.mod h1:TDCkEAkMTXxTs0oLBGBKpBZbk3NLh8EvAfF0Q3x8/0c= -github.com/aws/aws-sdk-go-v2/config v1.18.33 h1:JKcw5SFxFW/rpM4mOPjv0VQ11E2kxW13F3exWOy7VZU= -github.com/aws/aws-sdk-go-v2/config v1.18.33/go.mod h1:hXO/l9pgY3K5oZJldamP0pbZHdPqqk+4/maa7DSD3cA= -github.com/aws/aws-sdk-go-v2/credentials v1.13.32 h1:lIH1eKPcCY1ylR4B6PkBGRWMHO3aVenOKJHWiS4/G2w= -github.com/aws/aws-sdk-go-v2/credentials v1.13.32/go.mod h1:lL8U3v/Y79YRG69WlAho0OHIKUXCyFvSXaIvfo81sls= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.8 h1:DK/9C+UN/X+1+Wm8pqaDksQr2tSLzq+8X1/rI/ZxKEQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.8/go.mod h1:ce7BgLQfYr5hQFdy67oX2svto3ufGtm6oBvmsHScI1Q= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38 h1:c8ed/T9T2K5I+h/JzmF5tpI46+OODQ74dzmdo+QnaMg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.38/go.mod h1:qggunOChCMu9ZF/UkAfhTz25+U2rLVb3ya0Ua6TTfCA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.32 h1:hNeAAymUY5gu11WrrmFb3CVIp9Dar9hbo44yzzcQpzA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.32/go.mod h1:0ZXSqrty4FtQ7p8TEuRde/SZm9X05KT18LAUlR40Ln0= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.39 h1:fc0ukRAiP1syoSGZYu+DaE+FulSYhTiJ8WpVu5jElU4= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.39/go.mod h1:WLAW8PT7+JhjZfLSWe7WEJaJu0GNo0cKc2Zyo003RBs= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.1 h1:vUh7dBFNS3oFCtVv6CiYKh5hP9ls8+kIpKLeFruIBLk= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.1/go.mod h1:sFMeinkhj/SZKQM8BxtvNtSPjJEo0Xrz+w3g2e4FSKI= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.13 h1:iV/W5OMBys+66OeXJi/7xIRrKZNsu0ylsLGu+6nbmQE= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.13/go.mod h1:ReJb6xYmtGyu9KoFtRreWegbN9dZqvZIIv4vWnhcsyI= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.33 h1:QviNkc+vGSuEHx8P+pVNKOdWLXBPIwMFv7p0fphgE4U= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.33/go.mod h1:fABTUmOrAgAalG2i9WJpjBvlnk7UK8YmnYaxN+Q2CwE= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.32 h1:dGAseBFEYxth10V23b5e2mAS+tX7oVbfYHD6dnDdAsg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.32/go.mod h1:4jwAWKEkCR0anWk5+1RbfSg1R5Gzld7NLiuaq5bTR/Y= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.1 h1:PT6PBCycRwhpEW5hJnRiceCeoWJ+r3bdgXtV+VKG7Pk= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.1/go.mod h1:TqoxCLwT2nrxrBGA+z7t6OWM7LBkgRckK3gOjYE+7JA= -github.com/aws/aws-sdk-go-v2/service/s3 v1.38.2 h1:v346f1h8sUBKXnEbrv43L37MTBlFHyKXQPIZHNAaghA= -github.com/aws/aws-sdk-go-v2/service/s3 v1.38.2/go.mod h1:cwCATiyNrXK9P2FsWdZ89g9mpsYv2rhk0UA/KByl5fY= -github.com/aws/aws-sdk-go-v2/service/sso v1.13.2 h1:A2RlEMo4SJSwbNoUUgkxTAEMduAy/8wG3eB2b2lP4gY= -github.com/aws/aws-sdk-go-v2/service/sso v1.13.2/go.mod h1:ju+nNXUunfIFamXUIZQiICjnO/TPlOmWcYhZcSy7xaE= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.2 h1:OJELEgyaT2kmaBGZ+myyZbTTLobfe3ox3FSh5eYK9Qs= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.2/go.mod h1:ubDBBaDFs1GHijSOTi8ljppML15GLG0HxhILtbjNNYQ= -github.com/aws/aws-sdk-go-v2/service/sts v1.21.2 h1:ympg1+Lnq33XLhcK/xTG4yZHPs1Oyxu+6DEWbl7qOzA= -github.com/aws/aws-sdk-go-v2/service/sts v1.21.2/go.mod h1:FQ/DQcOfESELfJi5ED+IPPAjI5xC6nxtSolVVB773jM= -github.com/aws/smithy-go v1.14.1 h1:EFKMUmH/iHMqLiwoEDx2rRjRQpI1YCn5jTysoaDujFs= -github.com/aws/smithy-go v1.14.1/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/aws-sdk-go v1.44.334 h1:h2bdbGb//fez6Sv6PaYv868s9liDeoYM6hYsAqTB4MU= +github.com/aws/aws-sdk-go v1.44.334/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go-v2 v1.21.0 h1:gMT0IW+03wtYJhRqTVYn0wLzwdnK9sRMcxmtfGzRdJc= +github.com/aws/aws-sdk-go-v2 v1.21.0/go.mod h1:/RfNgGmRxI+iFOB1OeJUyxiU+9s88k3pfHvDagGEp0M= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.13 h1:OPLEkmhXf6xFPiz0bLeDArZIDx1NNS4oJyG4nv3Gct0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.13/go.mod h1:gpAbvyDGQFozTEmlTFO8XcQKHzubdq0LzRyJpG6MiXM= +github.com/aws/aws-sdk-go-v2/config v1.18.37 h1:RNAfbPqw1CstCooHaTPhScz7z1PyocQj0UL+l95CgzI= +github.com/aws/aws-sdk-go-v2/config v1.18.37/go.mod h1:8AnEFxW9/XGKCbjYDCJy7iltVNyEI9Iu9qC21UzhhgQ= +github.com/aws/aws-sdk-go-v2/credentials v1.13.35 h1:QpsNitYJu0GgvMBLUIYu9H4yryA5kMksjeIVQfgXrt8= +github.com/aws/aws-sdk-go-v2/credentials v1.13.35/go.mod h1:o7rCaLtvK0hUggAGclf76mNGGkaG5a9KWlp+d9IpcV8= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.11 h1:uDZJF1hu0EVT/4bogChk8DyjSF6fof6uL/0Y26Ma7Fg= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.11/go.mod h1:TEPP4tENqBGO99KwVpV9MlOX4NSrSLP8u3KRy2CDwA8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.41 h1:22dGT7PneFMx4+b3pz7lMTRyN8ZKH7M2cW4GP9yUS2g= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.41/go.mod h1:CrObHAuPneJBlfEJ5T3szXOUkLEThaGfvnhTf33buas= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.35 h1:SijA0mgjV8E+8G45ltVHs0fvKpTj8xmZJ3VwhGKtUSI= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.35/go.mod h1:SJC1nEVVva1g3pHAIdCp7QsRIkMmLAgoDquQ9Rr8kYw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.42 h1:GPUcE/Yq7Ur8YSUk6lVkoIMWnJNO0HT18GUzCWCgCI0= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.42/go.mod h1:rzfdUlfA+jdgLDmPKjd3Chq9V7LVLYo1Nz++Wb91aRo= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.4 h1:6lJvvkQ9HmbHZ4h/IEwclwv2mrTW8Uq1SOB/kXy0mfw= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.4/go.mod h1:1PrKYwxTM+zjpw9Y41KFtoJCQrJ34Z47Y4VgVbfndjo= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.14 h1:m0QTSI6pZYJTk5WSKx3fm5cNW/DCicVzULBgU/6IyD0= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.14/go.mod h1:dDilntgHy9WnHXsh7dDtUPgHKEfTJIBUTHM8OWm0f/0= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.36 h1:eev2yZX7esGRjqRbnVk1UxMLw4CyVZDpZXRCcy75oQk= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.36/go.mod h1:lGnOkH9NJATw0XEPcAknFBj3zzNTEGRHtSw+CwC1YTg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.35 h1:CdzPW9kKitgIiLV1+MHobfR5Xg25iYnyzWZhyQuSlDI= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.35/go.mod h1:QGF2Rs33W5MaN9gYdEQOBBFPLwTZkEhRwI33f7KIG0o= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.4 h1:v0jkRigbSD6uOdwcaUQmgEwG1BkPfAPDqaeNt/29ghg= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.4/go.mod h1:LhTyt8J04LL+9cIt7pYJ5lbS/U98ZmXovLOR/4LUsk8= +github.com/aws/aws-sdk-go-v2/service/s3 v1.38.5 h1:A42xdtStObqy7NGvzZKpnyNXvoOmm+FENobZ0/ssHWk= +github.com/aws/aws-sdk-go-v2/service/s3 v1.38.5/go.mod h1:rDGMZA7f4pbmTtPOk5v5UM2lmX6UAbRnMDJeDvnH7AM= +github.com/aws/aws-sdk-go-v2/service/sso v1.13.5 h1:oCvTFSDi67AX0pOX3PuPdGFewvLRU2zzFSrTsgURNo0= +github.com/aws/aws-sdk-go-v2/service/sso v1.13.5/go.mod h1:fIAwKQKBFu90pBxx07BFOMJLpRUGu8VOzLJakeY+0K4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.5 h1:dnInJb4S0oy8aQuri1mV6ipLlnZPfnsDNB9BGO9PDNY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.5/go.mod h1:yygr8ACQRY2PrEcy3xsUI357stq2AxnFM6DIsR9lij4= +github.com/aws/aws-sdk-go-v2/service/sts v1.21.5 h1:CQBFElb0LS8RojMJlxRSo/HXipvTZW2S44Lt9Mk2aYQ= +github.com/aws/aws-sdk-go-v2/service/sts v1.21.5/go.mod h1:VC7JDqsqiwXukYEDjoHh9U0fOJtNWh04FPQz4ct4GGU= +github.com/aws/smithy-go v1.14.2 h1:MJU9hqBGbvWZdApzpvoF2WAIJDbtjK2NDJSiJP7HblQ= +github.com/aws/smithy-go v1.14.2/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= 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/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= diff --git a/modules/mariadb/Makefile b/modules/mariadb/Makefile new file mode 100644 index 0000000000..59246b22dd --- /dev/null +++ b/modules/mariadb/Makefile @@ -0,0 +1,5 @@ +include ../../commons-test.mk + +.PHONY: test +test: + $(MAKE) test-mariadb diff --git a/modules/mariadb/go.mod b/modules/mariadb/go.mod new file mode 100644 index 0000000000..53546a1cc3 --- /dev/null +++ b/modules/mariadb/go.mod @@ -0,0 +1,45 @@ +module github.com/testcontainers/testcontainers-go/modules/mariadb + +go 1.20 + +require ( + github.com/go-sql-driver/mysql v1.7.1 + github.com/testcontainers/testcontainers-go v0.23.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.1 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/containerd/containerd v1.7.5 // indirect + github.com/cpuguy83/dockercfg v0.3.1 // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/docker v24.0.5+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/uuid v1.3.1 // indirect + github.com/klauspost/compress v1.16.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/moby/patternmatcher v0.5.0 // indirect + github.com/moby/sys/sequential v0.5.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-rc4 // indirect + github.com/opencontainers/runc v1.1.5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect + golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea // indirect + golang.org/x/mod v0.9.0 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/sys v0.11.0 // indirect + golang.org/x/tools v0.7.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect + google.golang.org/grpc v1.57.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect +) + +replace github.com/testcontainers/testcontainers-go => ../.. diff --git a/modules/mariadb/go.sum b/modules/mariadb/go.sum new file mode 100644 index 0000000000..7c959d3151 --- /dev/null +++ b/modules/mariadb/go.sum @@ -0,0 +1,161 @@ +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/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 v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= +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/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= +github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/containerd v1.7.5 h1:i9T9XpAWMe11BHMN7pu1BZqOGjXaKTPyz2v+KYOZgkY= +github.com/containerd/containerd v1.7.5/go.mod h1:ieJNCSzASw2shSGYLHx8NAE7WsZ/gEigo5fQ78W5Zvw= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +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/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +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/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= +github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= +github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +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/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= +github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +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/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/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +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-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= +github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +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/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +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/exp v0.0.0-20230510235704-dd950f8aeaea h1:vLCWI/yYrdEHyN2JzIzPO3aaQJHQdp89IZBA/+azVC4= +golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +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.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +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.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +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.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +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-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/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-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +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.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +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/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +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/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= diff --git a/modules/mariadb/mariadb.go b/modules/mariadb/mariadb.go new file mode 100644 index 0000000000..b84d82c2ec --- /dev/null +++ b/modules/mariadb/mariadb.go @@ -0,0 +1,183 @@ +package mariadb + +import ( + "context" + "fmt" + "path/filepath" + "strings" + + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +const ( + rootUser = "root" + defaultUser = "test" + defaultPassword = "test" + defaultDatabaseName = "test" +) + +// defaultImage { +const defaultImage = "mariadb:11.0.3" + +// } + +// MariaDBContainer represents the MariaDB container type used in the module +type MariaDBContainer struct { + testcontainers.Container + username string + password string + database string +} + +// WithDefaultCredentials applies the default credentials to the container request. +// It will look up for MARIADB environment variables. +func WithDefaultCredentials() testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) { + username := req.Env["MARIADB_USER"] + password := req.Env["MARIADB_PASSWORD"] + if strings.EqualFold(rootUser, username) { + delete(req.Env, "MARIADB_USER") + } + + if len(password) != 0 && password != "" { + req.Env["MARIADB_ROOT_PASSWORD"] = password + } else if strings.EqualFold(rootUser, username) { + req.Env["MARIADB_ALLOW_EMPTY_ROOT_PASSWORD"] = "yes" + delete(req.Env, "MARIADB_PASSWORD") + } + } +} + +// https://github.com/docker-library/docs/tree/master/mariadb#environment-variables +// From tag 10.2.38, 10.3.29, 10.4.19, 10.5.10 onwards, and all 10.6 and later tags, +// the MARIADB_* equivalent variables are provided. MARIADB_* variants will always be +// used in preference to MYSQL_* variants. +func withMySQLEnvVars() testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) { + // look up for MARIADB environment variables and apply the same to MYSQL + for k, v := range req.Env { + if strings.HasPrefix(k, "MARIADB_") { + // apply the same value to the MYSQL environment variables + mysqlEnvVar := strings.ReplaceAll(k, "MARIADB_", "MYSQL_") + req.Env[mysqlEnvVar] = v + } + } + } +} + +func WithUsername(username string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) { + req.Env["MARIADB_USER"] = username + } +} + +func WithPassword(password string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) { + req.Env["MARIADB_PASSWORD"] = password + } +} + +func WithDatabase(database string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) { + req.Env["MARIADB_DATABASE"] = database + } +} + +func WithConfigFile(configFile string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) { + cf := testcontainers.ContainerFile{ + HostFilePath: configFile, + ContainerFilePath: "/etc/mysql/conf.d/my.cnf", + FileMode: 0o755, + } + req.Files = append(req.Files, cf) + } +} + +func WithScripts(scripts ...string) testcontainers.CustomizeRequestOption { + return func(req *testcontainers.GenericContainerRequest) { + var initScripts []testcontainers.ContainerFile + for _, script := range scripts { + cf := testcontainers.ContainerFile{ + HostFilePath: script, + ContainerFilePath: "/docker-entrypoint-initdb.d/" + filepath.Base(script), + FileMode: 0o755, + } + initScripts = append(initScripts, cf) + } + req.Files = append(req.Files, initScripts...) + } +} + +// RunContainer creates an instance of the MariaDB container type +func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*MariaDBContainer, error) { + req := testcontainers.ContainerRequest{ + Image: defaultImage, + ExposedPorts: []string{"3306/tcp", "33060/tcp"}, + Env: map[string]string{ + "MARIADB_USER": defaultUser, + "MARIADB_PASSWORD": defaultPassword, + "MARIADB_DATABASE": defaultDatabaseName, + }, + WaitingFor: wait.ForLog("port: 3306 mariadb.org binary distribution"), + } + + genericContainerReq := testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + } + + opts = append(opts, WithDefaultCredentials()) + + for _, opt := range opts { + opt.Customize(&genericContainerReq) + } + + // Apply MySQL environment variables after user customization + // In future releases of MariaDB, they could remove the MYSQL_* environment variables + // at all. Then we can remove this customization. + withMySQLEnvVars().Customize(&genericContainerReq) + + username, ok := req.Env["MARIADB_USER"] + if !ok { + username = rootUser + } + 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") + } + + container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + if err != nil { + return nil, err + } + + database := req.Env["MARIADB_DATABASE"] + + return &MariaDBContainer{container, username, password, database}, nil +} + +func (c *MariaDBContainer) ConnectionString(ctx context.Context, args ...string) (string, error) { + containerPort, err := c.MappedPort(ctx, "3306/tcp") + if err != nil { + return "", err + } + + host, err := c.Host(ctx) + if err != nil { + return "", err + } + + extraArgs := "" + if len(args) > 0 { + extraArgs = strings.Join(args, "&") + } + if extraArgs != "" { + extraArgs = "?" + extraArgs + } + + connectionString := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s%s", c.username, c.password, host, containerPort.Port(), c.database, extraArgs) + return connectionString, nil +} diff --git a/modules/mariadb/mariadb_test.go b/modules/mariadb/mariadb_test.go new file mode 100644 index 0000000000..f3323fd5d4 --- /dev/null +++ b/modules/mariadb/mariadb_test.go @@ -0,0 +1,239 @@ +package mariadb + +import ( + "context" + "database/sql" + "path/filepath" + "testing" + + // Import mysql into the scope of this package (required) + _ "github.com/go-sql-driver/mysql" + + "github.com/testcontainers/testcontainers-go" +) + +func TestMariaDB(t *testing.T) { + ctx := context.Background() + + // createMariaDBContainer { + container, err := RunContainer(ctx) + 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) + } + }) + + // connectionString { + // By default, MariaDB transmits data between the server and clients without encrypting it. + connectionString, err := container.ConnectionString(ctx, "tls=false") + if err != nil { + t.Fatal(err) + } + // } + + db, err := sql.Open("mysql", connectionString) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + if err = db.Ping(); err != nil { + t.Errorf("error pinging db: %+v\n", 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) + } +} + +func TestMariaDBWithNonRootUserAndEmptyPassword(t *testing.T) { + ctx := context.Background() + + _, err := RunContainer(ctx, + WithDatabase("foo"), + WithUsername("test"), + WithPassword("")) + if err.Error() != "empty password can be used only with the root user" { + t.Fatal(err) + } +} + +func TestMariaDBWithRootUserAndEmptyPassword(t *testing.T) { + ctx := context.Background() + + // customInitialization { + container, err := RunContainer(ctx, + WithDatabase("foo"), + WithUsername("root"), + 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) + } + }) + + connectionString, err := container.ConnectionString(ctx) + if err != nil { + t.Fatal(err) + } + + db, err := sql.Open("mysql", connectionString) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + if err = db.Ping(); err != nil { + t.Errorf("error pinging db: %+v\n", 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) + } +} + +func TestMariaDBWithMySQLEnvVars(t *testing.T) { + ctx := context.Background() + + // withMySQLVars { + container, err := RunContainer(ctx, testcontainers.WithImage("mariadb:10.3.29"), + WithScripts(filepath.Join("testdata", "schema.sql"))) + if err != nil { + t.Fatal(err) + } + // } + + t.Cleanup(func() { + if err := container.Terminate(ctx); err != nil { + t.Fatalf("failed to terminate container: %s", err) + } + }) + + assertDataCanBeFetched(t, ctx, container) +} + +func TestMariaDBWithConfigFile(t *testing.T) { + ctx := context.Background() + + // withConfigFile { + container, err := RunContainer(ctx, testcontainers.WithImage("mariadb:11.0.3"), + WithConfigFile(filepath.Join("testdata", "my.cnf"))) + 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) + } + }) + + connectionString, err := container.ConnectionString(ctx) + if err != nil { + t.Fatal(err) + } + + db, err := sql.Open("mysql", connectionString) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + if err = db.Ping(); err != nil { + t.Errorf("error pinging db: %+v\n", 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) + } + 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") + } +} + +func TestMariaDBWithScripts(t *testing.T) { + ctx := context.Background() + + // withScripts { + container, err := RunContainer(ctx, + 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) + } + }) + + assertDataCanBeFetched(t, ctx, container) +} + +func assertDataCanBeFetched(t *testing.T, ctx context.Context, container *MariaDBContainer) { + connectionString, err := container.ConnectionString(ctx) + if err != nil { + t.Fatal(err) + } + + db, err := sql.Open("mysql", connectionString) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + if err = db.Ping(); err != nil { + t.Errorf("error pinging db: %+v\n", err) + } + + stmt, err := db.Prepare("SELECT name from profile") + if err != nil { + t.Fatal(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.") + } +} diff --git a/modules/mariadb/testdata/my.cnf b/modules/mariadb/testdata/my.cnf new file mode 100644 index 0000000000..c5e11ebb49 --- /dev/null +++ b/modules/mariadb/testdata/my.cnf @@ -0,0 +1,48 @@ +[mysqld] +port = 3306 +#socket = /tmp/mysql.sock +skip-external-locking +key_buffer_size = 16K +max_allowed_packet = 1M +table_open_cache = 4 +sort_buffer_size = 64K +read_buffer_size = 256K +read_rnd_buffer_size = 256K +net_buffer_length = 2K +thread_stack = 512K +skip-host-cache +skip-name-resolve + +# Don't listen on a TCP/IP port at all. This can be a security enhancement, +# if all processes that need to connect to mysqld run on the same host. +# All interaction with mysqld must be made via Unix sockets or named pipes. +# Note that using this option without enabling named pipes on Windows +# (using the "enable-named-pipe" option) will render mysqld useless! +# +#skip-networking +#server-id = 1 + +# Uncomment the following if you want to log updates +#log-bin=mysql-bin + +# binary logging format - mixed recommended +#binlog_format=mixed + +# Causes updates to non-transactional engines using statement format to be +# written directly to binary log. Before using this option make sure that +# there are no dependencies between transactional and non-transactional +# tables such as in the statement INSERT INTO t_myisam SELECT * FROM +# t_innodb; otherwise, slaves may diverge from the master. +#binlog_direct_non_transactional_updates=TRUE + +# Uncomment the following if you are using InnoDB tables +innodb_data_file_path = ibdata1:10M:autoextend +# You can set .._buffer_pool_size up to 50 - 80 % +# of RAM but beware of setting memory usage too high +innodb_buffer_pool_size = 16M +#innodb_additional_mem_pool_size = 2M +# Set .._log_file_size to 25 % of buffer pool size +innodb_log_file_size = 5M +innodb_log_buffer_size = 8M +innodb_flush_log_at_trx_commit = 1 +innodb_lock_wait_timeout = 50 \ No newline at end of file diff --git a/modules/mariadb/testdata/schema.sql b/modules/mariadb/testdata/schema.sql new file mode 100644 index 0000000000..590774b81c --- /dev/null +++ b/modules/mariadb/testdata/schema.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS profile ( + id MEDIUMINT NOT NULL AUTO_INCREMENT, + name VARCHAR(30) NOT NULL, + PRIMARY KEY (id) +); + +INSERT INTO profile (name) values ('profile 1'); diff --git a/modules/mysql/mysql_test.go b/modules/mysql/mysql_test.go index 41ac2f828b..fcc228bebc 100644 --- a/modules/mysql/mysql_test.go +++ b/modules/mysql/mysql_test.go @@ -115,7 +115,7 @@ func TestMySQLWithConfigFile(t *testing.T) { // withConfigFile { container, err := RunContainer(ctx, testcontainers.WithImage("mysql:5.6"), - WithConfigFile("./testdata/my.cnf")) + WithConfigFile(filepath.Join("testdata", "my.cnf"))) if err != nil { t.Fatal(err) } @@ -140,7 +140,7 @@ func TestMySQLWithConfigFile(t *testing.T) { if err = db.Ping(); err != nil { t.Errorf("error pinging db: %+v\n", err) } - stmt, _ := db.Prepare("SELECT @@GLOBAL.innodb_file_format") + stmt, err := db.Prepare("SELECT @@GLOBAL.innodb_file_format") if err != nil { t.Fatal(err) } diff --git a/modules/redis/go.mod b/modules/redis/go.mod index a4a824180d..bd161d6b5e 100644 --- a/modules/redis/go.mod +++ b/modules/redis/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/go-redis/redis/v8 v8.11.5 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.3.1 github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.23.0 diff --git a/modules/redis/go.sum b/modules/redis/go.sum index 6a45cc2e40..132b3c7a4a 100644 --- a/modules/redis/go.sum +++ b/modules/redis/go.sum @@ -51,8 +51,8 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= diff --git a/modules/redpanda/go.mod b/modules/redpanda/go.mod index 4facdfdae7..be166f0364 100644 --- a/modules/redpanda/go.mod +++ b/modules/redpanda/go.mod @@ -6,7 +6,7 @@ require ( github.com/docker/go-connections v0.4.0 github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.23.0 - github.com/twmb/franz-go v1.14.3 + github.com/twmb/franz-go v1.14.4 github.com/twmb/franz-go/pkg/kadm v1.9.0 ) diff --git a/modules/redpanda/go.sum b/modules/redpanda/go.sum index 40a65ff6c4..63ee4a4fc2 100644 --- a/modules/redpanda/go.sum +++ b/modules/redpanda/go.sum @@ -94,8 +94,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/twmb/franz-go v1.14.3 h1:cq8rxAnVYU1uF3SRVn8eEaUf+AaXKWlB0Cl3Ca7JSa4= -github.com/twmb/franz-go v1.14.3/go.mod h1:nMAvTC2kHtK+ceaSHeHm4dlxC78389M/1DjpOswEgu4= +github.com/twmb/franz-go v1.14.4 h1:Bt8hyF8zOmZ/7sYD15Do1gdi3uKT9XQreBbFkMS+skA= +github.com/twmb/franz-go v1.14.4/go.mod h1:nMAvTC2kHtK+ceaSHeHm4dlxC78389M/1DjpOswEgu4= github.com/twmb/franz-go/pkg/kadm v1.9.0 h1:UgwBu0YCd6P8HLdg6ZRA4v9W6/zoI1042fOd2CvvLBE= github.com/twmb/franz-go/pkg/kadm v1.9.0/go.mod h1:eG3f+GHUndq1CUSVvjp+WdNq5zePeJi3tEHzyTkao6g= github.com/twmb/franz-go/pkg/kmsg v1.6.1 h1:tm6hXPv5antMHLasTfKv9R+X03AjHSkSkXhQo2c5ALM= diff --git a/modules/redpanda/mounts/redpanda.yaml.tpl b/modules/redpanda/mounts/redpanda.yaml.tpl index 9c7922d75d..a19d21ce19 100644 --- a/modules/redpanda/mounts/redpanda.yaml.tpl +++ b/modules/redpanda/mounts/redpanda.yaml.tpl @@ -27,6 +27,18 @@ redpanda: name: internal port: 9093 +{{ if .EnableTLS }} + admin_api_tls: + - enabled: true + cert_file: /etc/redpanda/cert.pem + key_file: /etc/redpanda/key.pem + kafka_api_tls: + - name: external + enabled: true + cert_file: /etc/redpanda/cert.pem + key_file: /etc/redpanda/key.pem +{{ end }} + schema_registry: schema_registry_api: - address: "0.0.0.0" @@ -34,6 +46,14 @@ schema_registry: port: 8081 authentication_method: {{ .SchemaRegistry.AuthenticationMethod }} +{{ if .EnableTLS }} + schema_registry_api_tls: + - name: main + enabled: true + cert_file: /etc/redpanda/cert.pem + key_file: /etc/redpanda/key.pem +{{ end }} + schema_registry_client: brokers: - address: localhost diff --git a/modules/redpanda/options.go b/modules/redpanda/options.go index 29a32bdb9b..379492b95d 100644 --- a/modules/redpanda/options.go +++ b/modules/redpanda/options.go @@ -26,6 +26,10 @@ type options struct { // AutoCreateTopics is a flag to allow topic auto creation. AutoCreateTopics bool + + // EnableTLS is a flag to enable TLS. + EnableTLS bool + cert, key []byte } func defaultOptions() options { @@ -36,6 +40,7 @@ func defaultOptions() options { SchemaRegistryAuthenticationMethod: "none", ServiceAccounts: make(map[string]string, 0), AutoCreateTopics: false, + EnableTLS: false, } } @@ -93,3 +98,11 @@ func WithAutoCreateTopics() Option { o.AutoCreateTopics = true } } + +func WithTLS(cert, key []byte) Option { + return func(o *options) { + o.EnableTLS = true + o.cert = cert + o.key = key + } +} diff --git a/modules/redpanda/redpanda.go b/modules/redpanda/redpanda.go index 944a6d112a..83252d5fa3 100644 --- a/modules/redpanda/redpanda.go +++ b/modules/redpanda/redpanda.go @@ -6,6 +6,7 @@ import ( _ "embed" "fmt" "os" + "path/filepath" "text/template" "time" @@ -24,19 +25,34 @@ var ( //go:embed mounts/entrypoint-tc.sh entrypoint []byte +) +const ( defaultKafkaAPIPort = "9092/tcp" defaultAdminAPIPort = "9644/tcp" defaultSchemaRegistryPort = "8081/tcp" + + redpandaDir = "/etc/redpanda" + entrypointFile = "/entrypoint-tc.sh" + bootstrapConfigFile = ".bootstrap.yaml" + certFile = "cert.pem" + keyFile = "key.pem" ) -// Container represents the Redpanda container type used in the module +// Container represents the Redpanda container type used in the module. type Container struct { testcontainers.Container + urlScheme string } -// RunContainer creates an instance of the Redpanda container type +// RunContainer creates an instance of the Redpanda container type. func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*Container, error) { + tmpDir, err := os.MkdirTemp("", "redpanda") + if err != nil { + return nil, fmt.Errorf("failed to create directory: %w", err) + } + defer os.RemoveAll(tmpDir) + // 1. Create container request. // Some (e.g. Image) may be overridden by providing an option argument to this function. req := testcontainers.GenericContainerRequest{ @@ -51,7 +67,7 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize }, Entrypoint: []string{}, Cmd: []string{ - "/entrypoint-tc.sh", + entrypointFile, "redpanda", "start", "--mode=dev-container", @@ -75,38 +91,66 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize // We have to do this kind of two-step process, because we need to know the mapped // port, so that we can use this in Redpanda's advertised listeners configuration for // the Kafka API. - entrypointFile, err := createEntrypointTmpFile() - if err != nil { + 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) } // Bootstrap config file contains cluster configurations which will only be considered // the very first time you start a cluster. - bootstrapConfigFile, err := createBootstrapConfigFile(settings) + bootstrapConfigPath := filepath.Join(tmpDir, bootstrapConfigFile) + bootstrapConfig, err := renderBootstrapConfig(settings) if err != nil { return nil, fmt.Errorf("failed to create bootstrap config file: %w", err) } + if err := os.WriteFile(bootstrapConfigPath, bootstrapConfig, 0o600); err != nil { + return nil, fmt.Errorf("failed to create bootstrap config file: %w", err) + } - toBeMountedFiles := []testcontainers.ContainerFile{ - { - HostFilePath: entrypointFile.Name(), - ContainerFilePath: "/entrypoint-tc.sh", + req.Files = append(req.Files, + testcontainers.ContainerFile{ + HostFilePath: entrypointPath, + ContainerFilePath: entrypointFile, FileMode: 700, }, - { - HostFilePath: bootstrapConfigFile.Name(), - ContainerFilePath: "/etc/redpanda/.bootstrap.yaml", - FileMode: 700, + testcontainers.ContainerFile{ + HostFilePath: bootstrapConfigPath, + ContainerFilePath: filepath.Join(redpandaDir, bootstrapConfigFile), + FileMode: 600, }, + ) + + // 4. Create certificate and key for TLS connections. + 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) + } + 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) + } + + req.Files = append(req.Files, + testcontainers.ContainerFile{ + HostFilePath: certPath, + ContainerFilePath: filepath.Join(redpandaDir, certFile), + FileMode: 600, + }, + testcontainers.ContainerFile{ + HostFilePath: keyPath, + ContainerFilePath: filepath.Join(redpandaDir, keyFile), + FileMode: 600, + }, + ) } - req.Files = append(req.Files, toBeMountedFiles...) container, err := testcontainers.GenericContainer(ctx, req) if err != nil { return nil, err } - // 4. Get mapped port for the Kafka API, so that we can render and then mount + // 5. 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) if err != nil { @@ -118,18 +162,13 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize return nil, fmt.Errorf("failed to get mapped Kafka port: %w", err) } - // 5. Render redpanda.yaml config and mount it. + // 6. 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) } - err = container.CopyToContainer( - ctx, - nodeConfig, - "/etc/redpanda/redpanda.yaml", - 700, - ) + err = container.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) } @@ -159,73 +198,37 @@ func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomize } } - return &Container{Container: container}, nil + scheme := "http" + if settings.EnableTLS { + scheme += "s" + } + + return &Container{Container: container, urlScheme: scheme}, nil } // 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". func (c *Container) KafkaSeedBroker(ctx context.Context) (string, error) { - return c.getMappedHostPort(ctx, nat.Port(defaultKafkaAPIPort)) + return c.PortEndpoint(ctx, nat.Port(defaultKafkaAPIPort), "") } // 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. func (c *Container) AdminAPIAddress(ctx context.Context) (string, error) { - hostPort, err := c.getMappedHostPort(ctx, nat.Port(defaultAdminAPIPort)) - if err != nil { - return "", err - } - return fmt.Sprintf("http://%v", hostPort), nil + return c.PortEndpoint(ctx, nat.Port(defaultAdminAPIPort), c.urlScheme) } // 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. func (c *Container) SchemaRegistryAddress(ctx context.Context) (string, error) { - hostPort, err := c.getMappedHostPort(ctx, nat.Port(defaultSchemaRegistryPort)) - if err != nil { - return "", err - } - return fmt.Sprintf("http://%v", hostPort), nil + return c.PortEndpoint(ctx, nat.Port(defaultSchemaRegistryPort), c.urlScheme) } -// getMappedHostPort returns the mapped host and port a given nat.Port following -// this format: "host:port". The mapped port is the port that is accessible from -// the host system and is remapped to the given container port. -func (c *Container) getMappedHostPort(ctx context.Context, port nat.Port) (string, error) { - hostIP, err := c.Host(ctx) - if err != nil { - return "", fmt.Errorf("failed to get hostIP: %w", err) - } - - mappedPort, err := c.MappedPort(ctx, port) - if err != nil { - return "", fmt.Errorf("failed to get mapped port: %w", err) - } - - return fmt.Sprintf("%v:%d", hostIP, mappedPort.Int()), nil -} - -// createEntrypointTmpFile returns a temporary file with the custom entrypoint -// that awaits the actual Redpanda config after the container has been started, -// before it's going to start the Redpanda process. -func createEntrypointTmpFile() (*os.File, error) { - entrypointTmpFile, err := os.CreateTemp("", "") - if err != nil { - return nil, err - } - - if err := os.WriteFile(entrypointTmpFile.Name(), entrypoint, 0o700); err != nil { - return nil, err - } - - return entrypointTmpFile, nil -} - -// createBootstrapConfigFile renders the config template for the .bootstrap.yaml config, +// renderBootstrapConfig renders the config template for the .bootstrap.yaml config, // which configures Redpanda's cluster properties. // Reference: https://docs.redpanda.com/docs/reference/cluster-properties/ -func createBootstrapConfigFile(settings options) (*os.File, error) { +func renderBootstrapConfig(settings options) ([]byte, error) { bootstrapTplParams := redpandaBootstrapConfigTplParams{ Superusers: settings.Superusers, KafkaAPIEnableAuthorization: settings.KafkaEnableAuthorization, @@ -242,16 +245,7 @@ func createBootstrapConfigFile(settings options) (*os.File, error) { return nil, fmt.Errorf("failed to render redpanda bootstrap config template: %w", err) } - bootstrapTmpFile, err := os.CreateTemp("", "") - if err != nil { - return nil, err - } - - if err := os.WriteFile(bootstrapTmpFile.Name(), bootstrapConfig.Bytes(), 0o700); err != nil { - return nil, err - } - - return bootstrapTmpFile, nil + return bootstrapConfig.Bytes(), nil } // renderNodeConfig renders the redpanda.yaml node config and returns it as @@ -268,6 +262,7 @@ func renderNodeConfig(settings options, hostIP string, advertisedKafkaPort int) SchemaRegistry: redpandaConfigTplParamsSchemaRegistry{ AuthenticationMethod: settings.SchemaRegistryAuthenticationMethod, }, + EnableTLS: settings.EnableTLS, } ncTpl, err := template.New("redpanda.yaml").Parse(nodeConfigTpl) @@ -293,6 +288,7 @@ type redpandaConfigTplParams struct { KafkaAPI redpandaConfigTplParamsKafkaAPI SchemaRegistry redpandaConfigTplParamsSchemaRegistry AutoCreateTopics bool + EnableTLS bool } type redpandaConfigTplParamsKafkaAPI struct { diff --git a/modules/redpanda/redpanda_test.go b/modules/redpanda/redpanda_test.go index af7a5244ef..95a601c6ab 100644 --- a/modules/redpanda/redpanda_test.go +++ b/modules/redpanda/redpanda_test.go @@ -2,8 +2,11 @@ package redpanda import ( "context" + "crypto/tls" + "crypto/x509" "fmt" "net/http" + "strings" "testing" "time" @@ -47,7 +50,7 @@ func TestRedpanda(t *testing.T) { httpCl := &http.Client{Timeout: 5 * time.Second} schemaRegistryURL, err := container.SchemaRegistryAddress(ctx) require.NoError(t, err) - req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/subjects", schemaRegistryURL), nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/subjects", schemaRegistryURL), nil) require.NoError(t, err) resp, err := httpCl.Do(req) require.NoError(t, err) @@ -59,7 +62,7 @@ func TestRedpanda(t *testing.T) { adminAPIURL, err := container.AdminAPIAddress(ctx) require.NoError(t, err) // } - req, err = http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/v1/cluster/health_overview", adminAPIURL), nil) + req, err = http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v1/cluster/health_overview", adminAPIURL), nil) require.NoError(t, err) resp, err = httpCl.Do(req) require.NoError(t, err) @@ -163,7 +166,7 @@ func TestRedpandaWithAuthentication(t *testing.T) { // } // Failed authentication - req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/subjects", schemaRegistryURL), nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/subjects", schemaRegistryURL), nil) require.NoError(t, err) resp, err := httpCl.Do(req) require.NoError(t, err) @@ -205,3 +208,128 @@ func TestRedpandaProduceWithAutoCreateTopics(t *testing.T) { results := kafkaCl.ProduceSync(ctx, &kgo.Record{Topic: "test", Value: []byte("test message")}) require.NoError(t, results.FirstErr()) } + +func TestRedpandaWithTLS(t *testing.T) { + cert, err := tls.X509KeyPair(localhostCert, localhostKey) + require.NoError(t, err, "failed to load key pair") + + ctx := context.Background() + + container, err := RunContainer(ctx, WithTLS(localhostCert, localhostKey)) + require.NoError(t, err) + + t.Cleanup(func() { + if err := container.Terminate(ctx); err != nil { + t.Fatalf("failed to terminate container: %s", err) + } + }) + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(localhostCert) + + tlsConfig := &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: caCertPool, + } + + httpCl := &http.Client{ + Timeout: 5 * time.Second, + Transport: &http.Transport{ + ForceAttemptHTTP2: true, + TLSHandshakeTimeout: 10 * time.Second, + TLSClientConfig: tlsConfig, + }, + } + + // Test Admin API + adminAPIURL, err := container.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) + require.NoError(t, err) + resp, err := httpCl.Do(req) + require.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + resp.Body.Close() + + // Test Schema Registry API + schemaRegistryURL, err := container.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) + require.NoError(t, err) + resp, err = httpCl.Do(req) + require.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + resp.Body.Close() + + brokers, err := container.KafkaSeedBroker(ctx) + require.NoError(t, err) + + kafkaCl, err := kgo.NewClient( + kgo.SeedBrokers(brokers), + kgo.DialTLSConfig(tlsConfig), + ) + require.NoError(t, err) + defer kafkaCl.Close() + + // Test produce to unknown topic + results := kafkaCl.ProduceSync(ctx, &kgo.Record{Topic: "test", Value: []byte("test message")}) + require.Error(t, results.FirstErr(), kerr.UnknownTopicOrPartition) +} + +// localhostCert is a PEM-encoded TLS cert with SAN IPs +// generated from src/crypto/tls: +// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,localhost --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h +var localhostCert = []byte(`-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIRAKMykg5qJSCb4L3WtcZznSQwDQYJKoZIhvcNAQELBQAw +EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2 +MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAPYcLIhqCsrmqvsY1gWqI1jx3Ytn5Qjfvlg3BPD/YeD4UVouBhgQ +NIIERFCmDUzu52pXYZeCouBIVDWqZKixQf3PyBzAqbFvX0pTsZrOnvjuoahzjEcl +x+CfkIp58mVaV/8v9TyBYCXNuHlI7Pndu/3U5d6npSg8+dTkwW3VZzZyHpsDW+a4 +ByW02NI58LoHzQPMRg9MFToL1qNQy4PFyADf2N/3/SYOkrbSrXA0jYqXE8yvQGYe +LWcoQ+4YkurSS1TgSNEKxrzGj8w4xRjEjRNsLVNWd8uxZkHwv6LXOn4s39ix3jN4 +7OJJHA8fJAWxAP4ThrpM1j5J+Rq1PD380u8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8E +BAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQU8gMBt2leRAnGgCQ6pgIYPHY35GAwLAYDVR0RBCUwI4IJbG9jYWxob3N0 +hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4IBAQA5F6aw +6JJMsnCjxRGYXb252zqjxOxweawZ2je4UAGSsF27Phm1Bx6/2mzPpgIB0I7xNBFL +ljtqBG/FpH6qWpkkegljL8Z5soXiye/4r1G+V6hadm32/OLQCS//dyq7W1a2uVlS +KdFjoNqRW2PacVQLjnTbP2SJV5CnrJgCsSMXVoNnKdj5gr5ltNNAt9TAJ85iFa5d +rJla/XghtqEOzYtigKPF7EVqRRl4RmPu30hxwDZMT60ptFolfCEeXpDra5uonJMv +ElEbzK8ZzXmvWCj94RjPkGKZs8+SDM2qfKPk5ZW2xJxwqS3tkEkZlj1L+b7zYOlt +aJ65OWCXHLecrgdl +-----END CERTIFICATE-----`) + +// localhostKey is the private key for localhostCert. +var localhostKey = []byte(testingKey(`-----BEGIN TESTING KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD2HCyIagrK5qr7 +GNYFqiNY8d2LZ+UI375YNwTw/2Hg+FFaLgYYEDSCBERQpg1M7udqV2GXgqLgSFQ1 +qmSosUH9z8gcwKmxb19KU7Gazp747qGoc4xHJcfgn5CKefJlWlf/L/U8gWAlzbh5 +SOz53bv91OXep6UoPPnU5MFt1Wc2ch6bA1vmuAcltNjSOfC6B80DzEYPTBU6C9aj +UMuDxcgA39jf9/0mDpK20q1wNI2KlxPMr0BmHi1nKEPuGJLq0ktU4EjRCsa8xo/M +OMUYxI0TbC1TVnfLsWZB8L+i1zp+LN/Ysd4zeOziSRwPHyQFsQD+E4a6TNY+Sfka +tTw9/NLvAgMBAAECggEBALKxAiSJ2gw4Lyzhe4PhZIjQE+uEI+etjKbAS/YvdwHB +SlAP2pzeJ0G/l1p3NnEFhUDQ8SrwzxHJclsEvNE+4otGsiUuPgd2tdlhqzKbkxFr +MjT8sH14EQgm0uu4Xyb30ayXRZgI16abF7X4HRfOxxAl5EElt+TfYQYSkd8Nc0Mz +bD7g0riSdOKVhNIkUTT1U7x8ClIgff6vbWztOVP4hGezqEKpO/8+JBkg2GLeH3lC +PyuHEb33Foxg7SX35M1a89EKC2p4ER6/nfg6wGYyIsn42gBk1JgQdg23x7c/0WOu +vcw1unNP2kCbnsCeZ6KPRRGXEjbpTqOTzAUOekOeOgECgYEA9/jwK2wrX2J3kJN7 +v6kmxazigXHCa7XmFMgTfdqiQfXfjdi/4u+4KAX04jWra3ZH4KT98ztPOGjb6KhM +hfMldsxON8S9IQPcbDyj+5R77KU4BG/JQBEOX1uzS9KjMVG5e9ZUpG5UnSoSOgyM +oN3DZto7C5ULO2U2MT8JaoGb53cCgYEA/hPNMsCXFairxKy0BCsvJFan93+GIdwM +YoAGLc4Oj67ES8TYC4h9Im5i81JYOjpY4aZeKdj8S+ozmbqqa/iJiAfOr37xOMuX +AQA2T8uhPXXNXA5s6T3LaIXtzL0NmRRZCtuyEGdCidIXub7Bz8LrfsMc+s/jv57f +4IPmW12PPkkCgYBpEdDqBT5nfzh8SRGhR1IHZlbfVE12CDACVDh2FkK0QjNETjgY +N0zHoKZ/hxAoS4jvNdnoyxOpKj0r2sv54enY6X6nALTGnXUzY4p0GhlcTzFqJ9eV +TuTRIPDaytidGCzIvStGNP2jTmVEtXaM3wphtUxZfwCwXRVWToh12Y8uxwKBgA1a +FQp5vHbS6lPnj344lr2eIC2NcgsNeUkj2S9HCNTcJkylB4Vzor/QdTq8NQ66Sjlx +eLlSQc/retK1UIdkBDY10tK+JQcLC+Btlm0TEmIccrJHv8lyCeJwR1LfDHvi6dr8 +OJtMEd8UP1Lvh1fXsnBy6G71xc4oFzPBOrXKcOChAoGACOgyYe47ZizScsUGjCC7 +xARTEolZhtqHKVd5s9oi95P0r7A1gcNx/9YW0rCT2ZD8BD9H++HTE2L+mh3R9zDn +jwDeW7wVZec+oyGdc9L+B1xU25O+88zNLxlRAX8nXJbHdgL83UclmC51GbXejloP +D4ZNvyXf/6E27Ibu6v2p/vs= +-----END TESTING KEY-----`)) + +func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } diff --git a/scripts/bump-go.sh b/scripts/bump-go.sh index c2684b8752..02a20da35c 100755 --- a/scripts/bump-go.sh +++ b/scripts/bump-go.sh @@ -38,7 +38,6 @@ function main() { for modFile in $(find "${ROOT_DIR}" -name "go.mod" -not -path "${ROOT_DIR}/vendor/*" -not -path "${ROOT_DIR}/.git/*"); do bumpModFile "${modFile}" "${escapedCurrentGoVersion}" "${escapedGoVersion}" done - bumpModFile "${ROOT_DIR}/modulegen/_template/go.mod.tmpl" "${escapedCurrentGoVersion}" "${escapedGoVersion}" # bump markdown files for f in $(find "${ROOT_DIR}" -name "*.md"); do