diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4193748c61..8bf4be4ea8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,12 +41,11 @@ jobs: ryuk-disabled: false # The job below is a copy of the job above, but with ryuk disabled. - # It's executed in a secondary stage to avoid concurrency issues. + # It's executed in the first stage to avoid concurrency issues. test-reaper-off: # do not run this job if it's a PR from dependabot that is not approved yet if: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.state != 'approved' && github.triggering_actor == 'dependabot[bot]') }} name: "Test with reaper off" - needs: test strategy: matrix: go-version: [1.20.x, 1.x] @@ -61,12 +60,11 @@ jobs: ryuk-disabled: true # The job below is a copy of the job above, but with Docker rootless. - # It's executed in a secondary stage to avoid concurrency issues. + # It's executed in the first stage to avoid concurrency issues. test-rootless-docker: # do not run this job if it's a PR from dependabot that is not approved yet if: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.state != 'approved' && github.triggering_actor == 'dependabot[bot]') }} name: "Test with Rootless Docker" - needs: test strategy: matrix: go-version: [1.20.x, 1.x] diff --git a/docker_test.go b/docker_test.go index 27c447f294..66c7ae7167 100644 --- a/docker_test.go +++ b/docker_test.go @@ -27,7 +27,7 @@ import ( ) const ( - mysqlImage = "docker.io/mysql:8.0.30" + mysqlImage = "docker.io/mysql:8.0.36" nginxDelayedImage = "docker.io/menedev/delayed-nginx:1.15.2" nginxImage = "docker.io/nginx" nginxAlpineImage = "docker.io/nginx:alpine" @@ -508,7 +508,10 @@ func TestContainerCreation(t *testing.T) { fmt.Printf("%v", networkAliases) t.Errorf("Expected number of connected networks %d. Got %d.", 0, len(networkAliases)) } - if len(networkAliases["bridge"]) != 0 { + + if os.Getenv("XDG_RUNTIME_DIR") != "" { + t.Log("[Docker Rootless] do not assert that the container should have zero aliases in the bridge network") + } else if len(networkAliases["bridge"]) != 0 { t.Errorf("Expected number of aliases for 'bridge' network %d. Got %d.", 0, len(networkAliases["bridge"])) } } @@ -1271,7 +1274,7 @@ func TestContainerCustomPlatformImage(t *testing.T) { c, err := GenericContainer(ctx, GenericContainerRequest{ ProviderType: providerType, ContainerRequest: ContainerRequest{ - Image: "docker.io/mysql:5.7", + Image: "docker.io/mysql:8.0.36", ImagePlatform: "linux/amd64", }, Started: false, diff --git a/docs/features/image_name_substitution.md b/docs/features/image_name_substitution.md index 59693d3fcb..08e9e1d6a0 100644 --- a/docs/features/image_name_substitution.md +++ b/docs/features/image_name_substitution.md @@ -26,7 +26,7 @@ Consider this if: * Developers and CI machines need to use different image names. For example, developers are able to pull images from Docker Hub, but CI machines need to pull from a private registry. * Your private registry has copies of images from Docker Hub where the names are predictable, and just adding a prefix is enough. - For example, `registry.mycompany.com/mirror/mysql:8.0.24` can be derived from the original Docker Hub image name (`mysql:8.0.24`) with a consistent prefix string: `registry.mycompany.com/mirror` + For example, `registry.mycompany.com/mirror/mysql:8.0.36` can be derived from the original Docker Hub image name (`mysql:8.0.36`) with a consistent prefix string: `registry.mycompany.com/mirror` In this case, image name references in code are **unchanged**. i.e. you would leave as-is: diff --git a/docs/features/wait/log.md b/docs/features/wait/log.md index 6aaeb1988c..66c418b284 100644 --- a/docs/features/wait/log.md +++ b/docs/features/wait/log.md @@ -10,7 +10,7 @@ The Log wait strategy will check if a string occurs in the container logs for a ```golang req := ContainerRequest{ - Image: "docker.io/mysql:8.0.30", + Image: "docker.io/mysql:8.0.36", ExposedPorts: []string{"3306/tcp", "33060/tcp"}, Env: map[string]string{ "MYSQL_ROOT_PASSWORD": "password", @@ -24,7 +24,7 @@ Using a regular expression: ```golang req := ContainerRequest{ - Image: "docker.io/mysql:8.0.30", + Image: "docker.io/mysql:8.0.36", ExposedPorts: []string{"3306/tcp", "33060/tcp"}, Env: map[string]string{ "MYSQL_ROOT_PASSWORD": "password", diff --git a/docs/features/wait/multi.md b/docs/features/wait/multi.md index 62a2e26894..bfd053955b 100644 --- a/docs/features/wait/multi.md +++ b/docs/features/wait/multi.md @@ -9,7 +9,7 @@ Available Options: ```golang req := ContainerRequest{ - Image: "docker.io/mysql:8.0.30", + Image: "docker.io/mysql:8.0.36", ExposedPorts: []string{"3306/tcp", "33060/tcp"}, Env: map[string]string{ "MYSQL_ROOT_PASSWORD": "password", diff --git a/docs/modules/mysql.md b/docs/modules/mysql.md index fbbef2b7d9..5fbaa1bd49 100644 --- a/docs/modules/mysql.md +++ b/docs/modules/mysql.md @@ -42,7 +42,7 @@ When starting the MySQL container, you can pass options in a variadic way to con #### Image If you need to set a different MySQL Docker image, you can use `testcontainers.WithImage` with a valid Docker image -for MySQL. E.g. `testcontainers.WithImage("mysql:5.6")`. +for MySQL. E.g. `testcontainers.WithImage("mysql:8.0.36")`. By default, the container will use the following Docker image: diff --git a/from_dockerfile_test.go b/from_dockerfile_test.go index 093a95e1dc..0e3a4ff10d 100644 --- a/from_dockerfile_test.go +++ b/from_dockerfile_test.go @@ -213,6 +213,4 @@ func TestBuildImageFromDockerfile_TargetDoesNotExist(t *testing.T) { Started: true, }) require.Error(t, err) - - assert.Contains(t, err.Error(), "failed to reach build target target-foo in Dockerfile") } diff --git a/modulegen/_template/ci.yml.tmpl b/modulegen/_template/ci.yml.tmpl index 2d605d0d1b..9cbe9b0a6e 100644 --- a/modulegen/_template/ci.yml.tmpl +++ b/modulegen/_template/ci.yml.tmpl @@ -41,12 +41,11 @@ jobs: ryuk-disabled: false # The job below is a copy of the job above, but with ryuk disabled. - # It's executed in a secondary stage to avoid concurrency issues. + # It's executed in the first stage to avoid concurrency issues. test-reaper-off: # do not run this job if it's a PR from dependabot that is not approved yet if: {{ "${{ !(github.event_name == 'pull_request' && github.event.pull_request.state != 'approved' && github.triggering_actor == 'dependabot[bot]') }}" }} name: "Test with reaper off" - needs: test strategy: matrix: go-version: [1.20.x, 1.x] @@ -61,12 +60,11 @@ jobs: ryuk-disabled: true # The job below is a copy of the job above, but with Docker rootless. - # It's executed in a secondary stage to avoid concurrency issues. + # It's executed in the first stage to avoid concurrency issues. test-rootless-docker: # do not run this job if it's a PR from dependabot that is not approved yet if: {{ "${{ !(github.event_name == 'pull_request' && github.event.pull_request.state != 'approved' && github.triggering_actor == 'dependabot[bot]') }}" }} name: "Test with Rootless Docker" - needs: test strategy: matrix: go-version: [1.20.x, 1.x] diff --git a/modulegen/main_test.go b/modulegen/main_test.go index 4d28da665c..f861a8d3ac 100644 --- a/modulegen/main_test.go +++ b/modulegen/main_test.go @@ -482,11 +482,11 @@ func assertModuleGithubWorkflowContent(t *testing.T, module context.Testcontaine modulesList, err := ctx.GetModules() require.NoError(t, err) - assert.Equal(t, " module: ["+strings.Join(modulesList, ", ")+"]", data[108]) + assert.Equal(t, " module: ["+strings.Join(modulesList, ", ")+"]", data[106]) examplesList, err := ctx.GetExamples() require.NoError(t, err) - assert.Equal(t, " module: ["+strings.Join(examplesList, ", ")+"]", data[128]) + assert.Equal(t, " module: ["+strings.Join(examplesList, ", ")+"]", data[126]) } // assert content go.mod diff --git a/modules/compose/testdata/docker-compose-complex.yml b/modules/compose/testdata/docker-compose-complex.yml index 8185d87643..46a674ca04 100644 --- a/modules/compose/testdata/docker-compose-complex.yml +++ b/modules/compose/testdata/docker-compose-complex.yml @@ -5,7 +5,7 @@ services: ports: - "9080:80" mysql: - image: docker.io/mysql:8 + image: docker.io/mysql:8.0.36 environment: - MYSQL_DATABASE=db - MYSQL_ROOT_PASSWORD=my-secret-pw diff --git a/modules/compose/testdata/docker-compose-override.yml b/modules/compose/testdata/docker-compose-override.yml index 07b13609ed..3fcb135947 100644 --- a/modules/compose/testdata/docker-compose-override.yml +++ b/modules/compose/testdata/docker-compose-override.yml @@ -3,7 +3,7 @@ services: nginx: image: docker.io/nginx:stable-alpine mysql: - image: docker.io/mysql:8 + image: docker.io/mysql:8.0.36 environment: MYSQL_RANDOM_ROOT_PASSWORD: Y ports: diff --git a/modules/mariadb/testdata/my.cnf b/modules/mariadb/testdata/my.cnf index c5e11ebb49..3db92faa9c 100644 --- a/modules/mariadb/testdata/my.cnf +++ b/modules/mariadb/testdata/my.cnf @@ -10,7 +10,7 @@ read_buffer_size = 256K read_rnd_buffer_size = 256K net_buffer_length = 2K thread_stack = 512K -skip-host-cache +host_cache_size=0 skip-name-resolve # Don't listen on a TCP/IP port at all. This can be a security enhancement, diff --git a/modules/mysql/examples_test.go b/modules/mysql/examples_test.go index fa2c19ff6e..29668dc3c4 100644 --- a/modules/mysql/examples_test.go +++ b/modules/mysql/examples_test.go @@ -2,6 +2,7 @@ package mysql_test import ( "context" + "database/sql" "fmt" "path/filepath" @@ -14,7 +15,7 @@ func ExampleRunContainer() { ctx := context.Background() mysqlContainer, err := mysql.RunContainer(ctx, - testcontainers.WithImage("mysql:8"), + testcontainers.WithImage("mysql:8.0.36"), mysql.WithConfigFile(filepath.Join("testdata", "my_8.cnf")), mysql.WithDatabase("foo"), mysql.WithUsername("root"), @@ -43,3 +44,53 @@ func ExampleRunContainer() { // Output: // true } + +func ExampleRunContainer_connect() { + ctx := context.Background() + + mysqlContainer, err := mysql.RunContainer(ctx, + testcontainers.WithImage("mysql:8.0.36"), + mysql.WithConfigFile(filepath.Join("testdata", "my_8.cnf")), + mysql.WithDatabase("foo"), + mysql.WithUsername("root"), + mysql.WithPassword("password"), + mysql.WithScripts(filepath.Join("testdata", "schema.sql")), + ) + if err != nil { + panic(err) + } + + defer func() { + if err := mysqlContainer.Terminate(ctx); err != nil { + panic(err) + } + }() + + connectionString, _ := mysqlContainer.ConnectionString(ctx) + + db, err := sql.Open("mysql", connectionString) + if err != nil { + panic(err) + } + defer db.Close() + + if err = db.Ping(); err != nil { + panic(err) + } + stmt, err := db.Prepare("SELECT @@GLOBAL.tmpdir") + if err != nil { + panic(err) + } + defer stmt.Close() + row := stmt.QueryRow() + tmpDir := "" + err = row.Scan(&tmpDir) + if err != nil { + panic(err) + } + + fmt.Println(tmpDir) + + // Output: + // /tmp +} diff --git a/modules/mysql/mysql.go b/modules/mysql/mysql.go index ec98b481be..2ebfce1710 100644 --- a/modules/mysql/mysql.go +++ b/modules/mysql/mysql.go @@ -18,7 +18,7 @@ const ( ) // defaultImage { -const defaultImage = "mysql:8" +const defaultImage = "mysql:8.0.36" // } diff --git a/modules/mysql/mysql_test.go b/modules/mysql/mysql_test.go index 723b2930c9..daf5d879dc 100644 --- a/modules/mysql/mysql_test.go +++ b/modules/mysql/mysql_test.go @@ -1,4 +1,4 @@ -package mysql +package mysql_test import ( "context" @@ -9,13 +9,13 @@ import ( // Import mysql into the scope of this package (required) _ "github.com/go-sql-driver/mysql" - "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/modules/mysql" ) func TestMySQL(t *testing.T) { ctx := context.Background() - container, err := RunContainer(ctx) + container, err := mysql.RunContainer(ctx) if err != nil { t.Fatal(err) } @@ -57,10 +57,10 @@ func TestMySQL(t *testing.T) { func TestMySQLWithNonRootUserAndEmptyPassword(t *testing.T) { ctx := context.Background() - _, err := RunContainer(ctx, - WithDatabase("foo"), - WithUsername("test"), - WithPassword("")) + _, err := mysql.RunContainer(ctx, + mysql.WithDatabase("foo"), + mysql.WithUsername("test"), + mysql.WithPassword("")) if err.Error() != "empty password can be used only with the root user" { t.Fatal(err) } @@ -69,10 +69,10 @@ func TestMySQLWithNonRootUserAndEmptyPassword(t *testing.T) { func TestMySQLWithRootUserAndEmptyPassword(t *testing.T) { ctx := context.Background() - container, err := RunContainer(ctx, - WithDatabase("foo"), - WithUsername("root"), - WithPassword("")) + container, err := mysql.RunContainer(ctx, + mysql.WithDatabase("foo"), + mysql.WithUsername("root"), + mysql.WithPassword("")) if err != nil { t.Fatal(err) } @@ -106,55 +106,11 @@ func TestMySQLWithRootUserAndEmptyPassword(t *testing.T) { } } -func TestMySQLWithConfigFile(t *testing.T) { - ctx := context.Background() - - container, err := RunContainer(ctx, testcontainers.WithImage("mysql:5.6"), - WithConfigFile(filepath.Join("testdata", "my_5.6.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) - } - }) - - // perform assertions - connectionString, _ := container.ConnectionString(ctx) - - 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 @@GLOBAL.innodb_file_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_file_format value") - } - if innodbFileFormat != "Barracuda" { - t.Fatal("The InnoDB file format has been set by the ini file content") - } -} - func TestMySQLWithScripts(t *testing.T) { ctx := context.Background() - container, err := RunContainer(ctx, - WithScripts(filepath.Join("testdata", "schema.sql"))) + container, err := mysql.RunContainer(ctx, + mysql.WithScripts(filepath.Join("testdata", "schema.sql"))) if err != nil { t.Fatal(err) } diff --git a/modules/mysql/testdata/my_5.6.cnf b/modules/mysql/testdata/my_5.6.cnf deleted file mode 100644 index 78012cc4bf..0000000000 --- a/modules/mysql/testdata/my_5.6.cnf +++ /dev/null @@ -1,54 +0,0 @@ -[mysqld] -user = mysql -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 = 128K - - -innodb_file_format=Barracuda - - - - - -# 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/mysql/testdata/my_8.cnf b/modules/mysql/testdata/my_8.cnf index 7eb6b0faf7..c4c6039b8a 100644 --- a/modules/mysql/testdata/my_8.cnf +++ b/modules/mysql/testdata/my_8.cnf @@ -22,7 +22,7 @@ # this will increase compatibility with older clients. For background, see: # https://dev.mysql.com/doc/refman/8.1/en/server-system-variables.html#sysvar_default_authentication_plugin # default-authentication-plugin=mysql_native_password -skip-host-cache +host_cache_size=0 skip-name-resolve datadir=/var/lib/mysql socket=/var/run/mysqld/mysqld.sock diff --git a/modules/pulsar/go.mod b/modules/pulsar/go.mod index a335bfabfa..01d9bf5180 100644 --- a/modules/pulsar/go.mod +++ b/modules/pulsar/go.mod @@ -33,7 +33,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/dvsekhvalnov/jose2go v1.5.0 // indirect + github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/protobuf v1.3.2 // indirect diff --git a/modules/pulsar/go.sum b/modules/pulsar/go.sum index 4e655090e8..7de947d2b9 100644 --- a/modules/pulsar/go.sum +++ b/modules/pulsar/go.sum @@ -109,8 +109,8 @@ github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6 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/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= -github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= +github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=