Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: add a basic layout for wait strategies in docs (#536)
* docs: add a basic layout for wait strategies in docs * fix: bump docs version * docs: remove exposed ports * docs: rename intro file * chor: use simpler image * chore: simplify waitFor http examples * docs: add wait.ForExec * docs: simplify wording * docs: link to exec * docs: add exit wait strategy * chore: wording * fix: relative links * feat: support setting poll interval in host port * chore: include startup timeout * docs: add health strategy * fix: add dots * docs: add wait for log * docs: add wait for multiple * chore: consistency with startup timeout method in SQL wait * docs: add wait for SQL * chore: apply suggestions from code review Co-authored-by: Kevin Wittek <kiview@users.noreply.github.com> * fix: wrong copy & paste * chore: wording * chore: explain wait.FromExposedPort and container config * docs: clarify * chore: apply suggestions from code review Co-authored-by: Kevin Wittek <kiview@users.noreply.github.com> * fix: replace one shot with exit * fix: refine introduction to wait strategies * docs: create section for startup timeouts * docs: rephrase startup timeout * docs: explain poll interval Co-authored-by: Kevin Wittek <kiview@users.noreply.github.com>
- Loading branch information
1 parent
6ee7f6a
commit db5eeb8
Showing
12 changed files
with
264 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Exec Wait Strategy | ||
|
||
The exec wait strategy will check the exit code of a process to be executed in the container, and allows to set the following conditions: | ||
|
||
- the command and arguments to be executed, as an array of strings. | ||
- a function to match a specific exit code, with the default matching `0`. | ||
- the startup timeout to be used in seconds, default is 60 seconds. | ||
- the poll interval to be used in milliseconds, default is 100 milliseconds. | ||
|
||
## Match an exit code | ||
|
||
```golang | ||
req := ContainerRequest{ | ||
Image: "docker.io/nginx:alpine", | ||
WaitingFor: wait.NewExecStrategy([]string{"git", "version"}).WithExitCodeMatcher(func(exitCode int) bool { | ||
return exitCode == 10 | ||
}), | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Exit Wait strategy | ||
|
||
The exit wait strategy will check that the container is not in the running state, and allows to set the following conditions: | ||
|
||
- the exit timeout in seconds, default is `0`. | ||
- the poll interval to be used in milliseconds, default is 100 milliseconds. | ||
|
||
## Match an exit code | ||
|
||
```golang | ||
req := ContainerRequest{ | ||
Image: "docker.io/alpine:latest", | ||
WaitingFor: wait.ForExit(), | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Health Wait strategy | ||
|
||
The health wait strategy will check that the container is in the healthy state and allows to set the following conditions: | ||
|
||
- the startup timeout to be used in seconds, default is 60 seconds. | ||
- the poll interval to be used in milliseconds, default is 100 milliseconds. | ||
|
||
```golang | ||
req := ContainerRequest{ | ||
Image: "docker.io/alpine:latest", | ||
WaitingFor: wait.ForHealthCheck(), | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# HostPort Wait strategy | ||
|
||
The host-port wait strategy will check if the container is listening to a specific port and allows to set the following conditions: | ||
|
||
- a port exposed by the container. The port and protocol to be used, which is represented by a string containing the port number and protocol in the format "80/tcp". | ||
- alternatively, wait for the first exposed port in the container. | ||
- the startup timeout to be used, default is 60 seconds. | ||
- the poll interval to be used, default is 100 milliseconds. | ||
|
||
Variations on the HostPort wait strategy are supported, including: | ||
|
||
## Listening port in the container | ||
|
||
```golang | ||
req := ContainerRequest{ | ||
Image: "docker.io/nginx:alpine", | ||
ExposedPorts: []string{"80/tcp"}, | ||
WaitingFor: wait.ForListeningPort("80/tcp"), | ||
} | ||
``` | ||
|
||
## First exposed port in the container | ||
|
||
The wait strategy will use the first exposed port from the container configuration. | ||
|
||
```golang | ||
req := ContainerRequest{ | ||
Image: "docker.io/nginx:alpine", | ||
WaitingFor: wait.ForExposedPort(), | ||
} | ||
``` | ||
|
||
Said that, it could be the case that the container request included ports to be exposed. Therefore using `wait.ForExposedPort` will wait for the first exposed port in the request, because the container configuration retrieved from Docker will already include them. | ||
|
||
```golang | ||
req := ContainerRequest{ | ||
Image: "docker.io/nginx:alpine", | ||
ExposedPorts: []string{"80/tcp", "9080/tcp"}, | ||
WaitingFor: wait.ForExposedPort(), | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# HTTP(S) Wait strategy | ||
|
||
The HTTP wait strategy will check the result of an HTTP(S) request against the container and allows to set the following conditions: | ||
|
||
- the port to be used. | ||
- the path to be used. | ||
- the HTTP method to be used. | ||
- the HTTP request body to be sent. | ||
- the HTTP status code matcher as a function. | ||
- the HTTP response matcher as a function. | ||
- the TLS config to be used for HTTPS. | ||
- the startup timeout to be used in seconds, default is 60 seconds. | ||
- the poll interval to be used in milliseconds, default is 100 milliseconds. | ||
|
||
Variations on the HTTP wait strategy are supported, including: | ||
|
||
## Match an HTTP method | ||
|
||
```golang | ||
req := ContainerRequest{ | ||
Image: "docker.io/nginx:alpine", | ||
ExposedPorts: []string{"8086/tcp"}, | ||
WaitingFor: wait.ForHTTP("/ping").WithMethod(http.MethodPost).WithBody(bytes.NewReader([]byte("ping"))), | ||
} | ||
``` | ||
|
||
## Match an HTTP status code | ||
|
||
```golang | ||
req := ContainerRequest{ | ||
Image: "docker.io/nginx:alpine", | ||
ExposedPorts: []string{"8086/tcp"}, | ||
WaitingFor: wait.ForHTTP("/ping").WithPort("8086/tcp").WithStatusCodeMatcher( | ||
func(status int) bool { | ||
return status == http.StatusNoContent | ||
}, | ||
), | ||
} | ||
``` | ||
|
||
## Match an HTTPS status code and a response matcher | ||
|
||
```golang | ||
req := testcontainers.ContainerRequest{ | ||
FromDockerfile: testcontainers.FromDockerfile{ | ||
Context: workdir + "/testdata", | ||
}, | ||
ExposedPorts: []string{"80/tcp"}, | ||
WaitingFor: wait.NewHTTPStrategy("/ping"). | ||
WithStartupTimeout(time.Second * 10).WithPort("80/tcp"). | ||
WithResponseMatcher(func(body io.Reader) bool { | ||
data, _ := ioutil.ReadAll(body) | ||
return bytes.Equal(data, []byte("pong")) | ||
}). | ||
WithStatusCodeMatcher(func(status int) bool { | ||
i++ // always fail the first try in order to force the polling loop to be re-run | ||
return i > 1 && status == 200 | ||
}). | ||
WithMethod(http.MethodPost).WithBody(bytes.NewReader([]byte("ping"))), | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Wait Strategies | ||
|
||
There are scenarios where your tests need the external services they rely on to reach a specific state that is particularly useful for testing. This is generally approximated as 'Can we talk to this container over the network?' or 'Let's wait until the container is running an reaches certain state'. | ||
|
||
Testcontainers-go comes with the concept of `wait strategy`, which allows your tests to actually wait for the most useful conditions to be met, before continuing with their execution. These wait strategies are implemented in the `wait` package. | ||
|
||
Below you can find a list of the available wait strategies that you can use: | ||
|
||
- [Exec](./exec.md) | ||
- [Exit](./exit.md) | ||
- [Health](./health.md) | ||
- [HostPort](./host_port.md) | ||
- [HTTP](./http.md) | ||
- [Log](./log.md) | ||
- [Multi](./multi.md) | ||
- [SQL](./sql.md) | ||
|
||
## Startup timeout and Poll interval | ||
|
||
When defining a wait strategy, it should define a way to set the startup timeout to avoid waiting infinitely. For that, Testcontainers-go creates a cancel context with 60 seconds defined as timeout. | ||
|
||
If the default 60s timeout is not sufficient, it can be updated with the `WithStartupTimeout(startupTimeout time.Duration)` function. | ||
|
||
Besides that, it's possible to define a poll interval, which will actually stop 100 milliseconds the test execution. | ||
|
||
If the default 100 milliseconds poll interval is not sufficient, it can be updated with the `WithPollInterval(pollInterval time.Duration)` function. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Log Wait strategy | ||
|
||
The Log wait strategy will check if a string occurs in the container logs for a desired number of times, and allows to set the following conditions: | ||
|
||
- the string to be waited for in the container log. | ||
- the number of occurrences of the string to wait for, default is `1`. | ||
- the startup timeout to be used in seconds, default is 60 seconds. | ||
- the poll interval to be used in milliseconds, default is 100 milliseconds. | ||
|
||
```golang | ||
req := ContainerRequest{ | ||
Image: "docker.io/mysql:latest", | ||
ExposedPorts: []string{"3306/tcp", "33060/tcp"}, | ||
Env: map[string]string{ | ||
"MYSQL_ROOT_PASSWORD": "password", | ||
"MYSQL_DATABASE": "database", | ||
}, | ||
WaitingFor: wait.ForLog("port: 3306 MySQL Community Server - GPL"), | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Multi Wait strategy | ||
|
||
The Multi wait strategy will hold a list of wait strategies, in order to wait for all of them. It's possible to set the following conditions: | ||
|
||
- the startup timeout to be used in seconds, default is 60 seconds. | ||
|
||
```golang | ||
req := ContainerRequest{ | ||
Image: "docker.io/mysql:latest", | ||
ExposedPorts: []string{"3306/tcp", "33060/tcp"}, | ||
Env: map[string]string{ | ||
"MYSQL_ROOT_PASSWORD": "password", | ||
"MYSQL_DATABASE": "database", | ||
}, | ||
WaitingFor: wait.ForAll( | ||
wait.ForLog("port: 3306 MySQL Community Server - GPL"), | ||
wait.ForListeningPort("3306/tcp"), | ||
).WithStartupTimeout(10*time.Second), | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# SQL Wait strategy | ||
|
||
The SQL wait strategy will check the result of a SQL query executed in a container representing a SQL database, and allows to set the following conditions: | ||
|
||
- the SQL query to be used, default is `SELECT 1`. | ||
- the port to be used. | ||
- the database driver to be used, as a string. | ||
- the URL of the database to be used, as a function returning the URL string. | ||
- the startup timeout to be used in seconds, default is 60 seconds. | ||
- the poll interval to be used in milliseconds, default is 100 milliseconds. | ||
|
||
```golang | ||
req := ContainerRequest{ | ||
Image: "postgres:14.1-alpine", | ||
ExposedPorts: []string{port}, | ||
Cmd: []string{"postgres", "-c", "fsync=off"}, | ||
Env: env, | ||
WaitingFor: wait.ForSQL(nat.Port(port), "postgres", dbURL). | ||
WithStartupTimeout(time.Second * 5). | ||
WithQuery("SELECT 10"), | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters