Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/modules/postgres.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ An example of a `*.sh` script that creates a user and database is shown below:
[Init script content](../../modules/postgres/testdata/init-user-db.sh)
<!--/codeinclude-->

#### Ordered Init Scripts

If you would like to run the init scripts in a specific order, you can use the `WithOrderedInitScripts` function, which copies the given scripts in the order they are provided to the container, prefixed with the order number so that Postgres executes them in the correct order.

<!--codeinclude-->
[Ordered init scripts](../../modules/postgres/postgres_test.go) inside_block:orderedInitScripts
<!--/codeinclude-->

#### Database configuration

In the case you have a custom config file for Postgres, it's possible to copy that file into the container before it's started, using the `WithConfigFile(cfgPath string)` function.
Expand Down
39 changes: 27 additions & 12 deletions modules/postgres/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,22 +94,37 @@ func WithDatabase(dbName string) testcontainers.CustomizeRequestOption {
}
}

// WithInitScripts sets the init scripts to be run when the container starts
// WithInitScripts sets the init scripts to be run when the container starts.
// These init scripts will be executed in sorted name order as defined by the container's current locale, which defaults to en_US.utf8.
// If you need to run your scripts in a specific order, consider using `WithOrderedInitScripts` instead.
func WithInitScripts(scripts ...string) testcontainers.CustomizeRequestOption {
return func(req *testcontainers.GenericContainerRequest) error {
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)
containerFiles := []testcontainers.ContainerFile{}
for _, script := range scripts {
initScript := testcontainers.ContainerFile{
HostFilePath: script,
ContainerFilePath: "/docker-entrypoint-initdb.d/" + filepath.Base(script),
FileMode: 0o755,
}
req.Files = append(req.Files, initScripts...)
containerFiles = append(containerFiles, initScript)
}

return nil
return testcontainers.WithFiles(containerFiles...)
}

// WithOrderedInitScripts sets the init scripts to be run when the container starts.
// The scripts will be run in the order that they are provided in this function.
func WithOrderedInitScripts(scripts ...string) testcontainers.CustomizeRequestOption {
containerFiles := []testcontainers.ContainerFile{}
for idx, script := range scripts {
initScript := testcontainers.ContainerFile{
HostFilePath: script,
ContainerFilePath: "/docker-entrypoint-initdb.d/" + fmt.Sprintf("%03d-%s", idx, filepath.Base(script)),
FileMode: 0o755,
}
containerFiles = append(containerFiles, initScript)
}

return testcontainers.WithFiles(containerFiles...)
}

// WithPassword sets the initial password of the user to be created when the container starts
Expand Down
59 changes: 59 additions & 0 deletions modules/postgres/postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import (
"database/sql"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"testing"
"time"

Expand All @@ -19,6 +21,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/testcontainers/testcontainers-go"
tcexec "github.com/testcontainers/testcontainers-go/exec"
"github.com/testcontainers/testcontainers-go/modules/postgres"
"github.com/testcontainers/testcontainers-go/wait"
)
Expand Down Expand Up @@ -288,6 +291,62 @@ func TestWithInitScript(t *testing.T) {
require.NotNil(t, result)
}

func TestWithOrderedInitScript(t *testing.T) {
ctx := context.Background()

ctr, err := postgres.Run(ctx,
"postgres:15.2-alpine",
// orderedInitScripts {
// Executes first the init-user-db shell-script, then the do-insert-user SQL script
// Using WithInitScripts, this would not work.
// This is because aaaa-insert-user would get executed first, but requires init-user-db to be executed before.
postgres.WithOrderedInitScripts(
filepath.Join("testdata", "init-user-db.sh"),
filepath.Join("testdata", "aaaa-insert-user.sql"),
),
// }
postgres.WithDatabase(dbname),
postgres.WithUsername(user),
postgres.WithPassword(password),
postgres.BasicWaitStrategies(),
)
testcontainers.CleanupContainer(t, ctr)
require.NoError(t, err)

// Test that init scripts have been correctly renamed
c, reader, err := ctr.Exec(ctx, []string{"ls", "-l", "/docker-entrypoint-initdb.d"}, tcexec.Multiplexed())
require.NoError(t, err)
require.Equal(t, 0, c, "Expected to read init scripts from the container")

buf := new(strings.Builder)
_, err = io.Copy(buf, reader)
require.NoError(t, err)

initScripts := buf.String()
strings.Contains(initScripts, "000-init-user-db.sh")
strings.Contains(initScripts, "001-aaaa-insert-user.sql")

// explicitly set sslmode=disable because the container is not configured to use TLS
connStr, err := ctr.ConnectionString(ctx, "sslmode=disable")
require.NoError(t, err)

db, err := sql.Open("postgres", connStr)
require.NoError(t, err)
require.NotNil(t, db)
defer db.Close()

// database created in init script. See testdata/init-user-db.sh
rows, err := db.Query("SELECT COUNT(*) FROM testdb;")
require.NoError(t, err)
require.NotNil(t, rows)
for rows.Next() {
var count int
err := rows.Scan(&count)
require.NoError(t, err)
require.Equal(t, 2, count)
}
}

func TestSnapshot(t *testing.T) {
tests := []struct {
name string
Expand Down
5 changes: 5 additions & 0 deletions modules/postgres/testdata/aaaa-insert-user.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- Do not rename this file, it is named like this
-- to test correct ordering behavior.
--
-- See TestWithOrderedInitScripts.
INSERT INTO testdb (id, name) VALUES (2, 'second user')
Loading