Documentation
¶
Index ¶
- Constants
- Variables
- func GetAPIEndpoints(container *dockertest.Resource) (endpointByPrivatePort map[PrivatePort]APIEndpoint)
- type APIEndpoint
- type BuildOption
- type BuildOptions
- type ContainerConfigCheck
- type Pool
- func (p Pool) Build(ctx context.Context, buildOptions ...BuildOption) (err error)
- func (p Pool) BuildAndGet(ctx context.Context, buildOptions ...BuildOption) (image *docker.Image, err error)
- func (p Pool) Prune(ctx context.Context, customOptions ...PruneOption) (err error)
- func (p Pool) Run(ctx context.Context, repository string, customOpts ...RunOption) (container *dockertest.Resource, err error)
- type PrivatePort
- type PruneContainersOption
- type PruneImagesOption
- type PruneOption
- type PruneOptions
- type RetryOperation
- type RetryOptions
- type ReuseContainerOptions
- type RunOption
- type RunOptions
Examples ¶
Constants ¶
const (
DefaultLabelKeyValue = "tcontainer"
)
const (
ImageLabelUUID = DefaultLabelKeyValue + ".uuid"
)
Variables ¶
var ( // ErrInvalidOptions - occurs when invalid value was passed to TestContainerOption. ErrInvalidOptions = errors.New("invalid option") // ErrOptionConflict - occurs when incompatible TestContainerOption have been passed. ErrOptionConflict = errors.New("conflicted options") )
var ( // ErrContainerAlreadyExists - occurs when the container already exists. ErrContainerAlreadyExists = docker.ErrContainerAlreadyExists // ErrUnreusableState - occurs when it's impossible to reuse container (see WithReuseContainer()). ErrUnreusableState = errors.New("imposible to reuse container with it's current state") // ErrReuseContainerConflict - occurs when existed container have different options (e.q. image tag). ErrReuseContainerConflict = errors.New("imposible to reuse container, it has differnent options") )
Functions ¶
func GetAPIEndpoints ¶ added in v0.0.4
func GetAPIEndpoints(container *dockertest.Resource) (endpointByPrivatePort map[PrivatePort]APIEndpoint)
GetAPIEndpoints - provides you APIEndpoint by each privatePort (port inside the container).
Types ¶
type APIEndpoint ¶ added in v0.0.3
type APIEndpoint struct {
IP string // localhost/dockerGateway or container IP
Port string // publicPort or private port
}
Endpoint that you can use to connect to the container.
Note: macOS users may encounter issues accessing the container through APIEndpoint from inside the container. This is because macOS users cannot use the container's IP directly, potentially leading to connectivity problems.
func (APIEndpoint) NetJoinHostPort ¶ added in v0.0.3
func (e APIEndpoint) NetJoinHostPort() string
NetJoinHostPort - combines ip and port into a network address of the form "host:port".
type BuildOption ¶ added in v0.0.5
type BuildOption func(options *BuildOptions) (err error)
BuildOption - option for (Pool).Build / (Pool).BuildAndGet functions. See ApplyBuildOptions.
func WithImageName ¶ added in v0.0.5
func WithImageName(nameParts ...string) BuildOption
WithImageName - use custom image name instead of random (generated by docker).
- All invalid characters will be repaced to "/".
- Not empty nameParts will be joined with "/" separator, empty parts will be removed.
- Snake case will be applied.
Example:
WithImageName(t.Name(), "redis") // "Test/withInvalid|chars", "redis" -> "Test/with_invalid/chars/redis"
type BuildOptions ¶ added in v0.0.5
type BuildOptions struct {
ImageName string
Dockerfile string
ContextDir string
BuildArgs []docker.BuildArg
Platform string
NoCache bool
CacheFrom []string
SuppressOutput bool
Pull bool
RmTmpContainer bool
ForceRmTmpContainer bool
RawJSONStream bool
Memory int64
Memswap int64
ShmSize int64
CPUQuota int64
CPUPeriod int64
CPUSetCPUs string
Labels map[string]string
InputStream io.Reader
OutputStream io.Writer
ErrorStream io.Writer
Remote string
Auth docker.AuthConfiguration
AuthConfigs docker.AuthConfigurations
Ulimits []docker.ULimit
NetworkMode string
InactivityTimeout time.Duration
CgroupParent string
SecurityOpt []string
Target string
Version string
Outputs string
ExtraHosts string
}
BuildOptions for (Pool).Build / (Pool).BuildAndGet functions.
func ApplyBuildOptions ¶ added in v0.0.5
func ApplyBuildOptions(uuid string, customOpts ...BuildOption) ( options BuildOptions, err error, )
ApplyBuildOptions sets defaults and apply custom options. Options aplies in order they passed.
Each option rewrites previous value
ApplyBuildOptions(WithImageName("first"), WithImageName("second")) // "second"
type ContainerConfigCheck ¶ added in v0.0.5
type ContainerConfigCheck func(container *docker.Container, expectedOptions RunOptions) (err error)
Function for check that container suits for reuse.
type Pool ¶ added in v0.0.5
type Pool struct {
Pool *dockertest.Pool
}
Pool with docker client.
func MustNewPool ¶ added in v0.0.5
func (Pool) Build ¶ added in v0.0.5
func (p Pool) Build(ctx context.Context, buildOptions ...BuildOption) (err error)
Build a new image.
- Rewrites old image with new one if they have the same name.
- Old image with the same name won't be removed, but it will lose it's name.
func (Pool) BuildAndGet ¶ added in v0.0.5
func (p Pool) BuildAndGet(ctx context.Context, buildOptions ...BuildOption) (image *docker.Image, err error)
BuildAndGet a new image.
- Rewrites old image with new one if they have the same name.
- Old image with the same name won't be removed, but it will lose it's name.
- Returns information about the created image.
func (Pool) Prune ¶ added in v0.0.5
func (p Pool) Prune(ctx context.Context, customOptions ...PruneOption) (err error)
Prune - remove containers and images created by this package.
func (Pool) Run ¶ added in v0.0.5
func (p Pool) Run( ctx context.Context, repository string, customOpts ...RunOption, ) (container *dockertest.Resource, err error)
Run - creates and runs new test container.
Example ¶
const containerAPIPort = "80"
const serverHelloMesage = "Hello, World!"
startServerCMD := fmt.Sprintf(`echo '%s' > /index.html && httpd -p %s -h / && tail -f /dev/null`, serverHelloMesage, containerAPIPort)
// define function to check the server is ready
url := ""
pingServerRetry := func(_ context.Context, container *dockertest.Resource) (err error) {
url = "http://" + tcontainer.GetAPIEndpoints(container)[containerAPIPort].NetJoinHostPort()
resp, err := http.Get(url)
if err != nil {
return fmt.Errorf("failed to http.Get: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected response status `%s`", resp.Status)
}
return nil
}
pool := tcontainer.MustNewPool("")
// you can remove all containers and images created by this package (from previous tests run)
// in order to avoid errors like ErrContainerAlreadyExists
err := pool.Prune(context.Background())
if err != nil {
panic(err)
}
// run container with the server
container, err := pool.Run(
context.Background(),
"busybox",
tcontainer.WithContainerName("my-test-server"),
func(options *tcontainer.RunOptions) (err error) {
// set by one field instead of *options = tcontainer.RunOptions{...}
// in order to not owerride default values (like options.Retry.Timeout)
options.Tag = "latest"
options.Env = []string{"SOME_ENV=value"}
options.Cmd = []string{"sh", "-c", startServerCMD}
options.ExposedPorts = []string{containerAPIPort}
options.HostConfig.AutoRemove = false
options.HostConfig.RestartPolicy = docker.RestartPolicy{Name: "no", MaximumRetryCount: 0}
options.Retry.Operation = pingServerRetry
options.Reuse.Reuse = true
options.Reuse.RecreateOnErr = true
options.ContainerExpiry = time.Minute * 10
options.HostConfig.PortBindings = map[docker.Port][]docker.PortBinding{
"80": {{HostIP: "", HostPort: "8080"}},
}
options.RemoveOnExists = false // not compatible with Reuse option
return nil
},
)
if err != nil {
panic(err)
}
defer container.Close() // not necessary if you want to WithReuseContainer
// make request to the server
resp, err := http.Get(url)
if err != nil {
panic(err)
}
defer resp.Body.Close()
responseBody, _ := io.ReadAll(resp.Body)
fmt.Println(string(responseBody))
Output: Hello, World!
type PrivatePort ¶ added in v0.0.5
type PrivatePort = string
PrivatePort - port inside the container.
type PruneContainersOption ¶ added in v0.0.5
PruneContainersOption for (Pool).Prune function.
type PruneImagesOption ¶ added in v0.0.5
PruneImagesOption for (Pool).Prune function.
type PruneOption ¶ added in v0.0.5
type PruneOption func(options *PruneOptions) (err error)
PruneOption - option for (Pool).Prune function. See ApplyPruneOptions.
type PruneOptions ¶ added in v0.0.5
type PruneOptions struct {
PruneContainersOption PruneContainersOption
PruneImagesOption PruneImagesOption
}
PruneOptions for (Pool).Prune function.
func ApplyPruneOptions ¶ added in v0.0.5
func ApplyPruneOptions(customOpts ...PruneOption) ( options PruneOptions, err error, )
ApplyPruneOptions sets defaults and apply custom options. Options aplies in order they passed.
Each option rewrites previous value.
type RetryOperation ¶
type RetryOperation func(ctx context.Context, container *dockertest.Resource) (err error)
RetryOperation is an exponential backoff retry operation. You can use it to wait for e.g. mysql to boot up.
type RetryOptions ¶ added in v0.0.5
type RetryOptions struct {
Operation RetryOperation
Backoff backoff.BackOff
}
Allows you to specify a command that checks that the container is successfully started and ready to work.
- `Run` function will periodically run and wait for the successful completion of `Retry.Operation` or issue an error upon reaching `backoff.Stop` / `backoff.Permanent`.
- Use `GetAPIEndpoints(container)` to get the externally accessible ip and port to connect to a specific internal port of the container.
Default: ¶
- if `Retry.Operation` is not performed, `Run` function complete immediately after container creation
Example: ¶
func(options *RunOptions) (err error) {
options.Retry.Operation = func(ctx context.Context, container *dockertest.Resource) (err error) {
fmt.Println("ping")
return nil
}
retryBackoff := backoff.NewExponentialBackOff()
retryBackoff.MaxInterval = time.Second
retryBackoff.Reset()
options.Retry.Backoff = retryBackoff
return nil
}
type ReuseContainerOptions ¶ added in v0.0.5
type ReuseContainerOptions struct {
Reuse bool
Backoff backoff.BackOff
RecreateOnErr bool
ConfigChecks []ContainerConfigCheck
}
Allows you to reuse a container instead of getting an error that the container already exists.
- Should not be used together with `RemoveOnExists` - will return `ErrOptionsConflict` error.
- You may get an error if the existing container has different settings (different port mapping or image name). This error can be ignored with `RecreateOnErr`
- You can specify `Backoff` to change the timeout waiting for the old container to be unpaused or started.
- You can specify `RecreateOnErr` to recreate the container instead of getting an error when trying to reuse it. (When the old container has different settings or could not be revived)
- Use `ConfigChecks` to check that old container suits for reuse
Default: ¶
- `Reuse` - `false`
- `RecreateOnErr` - `false`
- `ConfigChecks` - checks that old container have the same image, exposed ports and port bindings
Example ¶
func(options *RunOptions) (err error) {
options.Reuse.Reuse = true
reuseBackoff := backoff.NewExponentialBackOff()
reuseBackoff.MaxInterval = time.Second
reuseBackoff.Reset()
options.Reuse.Backoff = reuseBackoff
options.Reuse.ConfigChecks = append(options.Reuse.ConfigChecks,
func(container *docker.Container, expectedOptions RunOptions) (err error) {
if container.Config.Image != expectedOptions.Repository + ":" + expectedOptions.Tag {
return errors.New("old container have other image")
}
return nil
},
)
return nil
}
type RunOption ¶ added in v0.0.5
type RunOption func(options *RunOptions) (err error)
RunOption - option for (Pool).Run function. See ApplyRunOptions.
func WithContainerName ¶
WithContainerName - use custom container name instead of random (generated by docker). All invalid characters will be repaced to "-". Not empty containerNameParts will be joined with "-" separator, empty parts will be removed.
Example usage:
WithContainerName(t.Name(), "redis") // "Test/with/invalid/chars", "redis" -> "Test-with-invalid-chars-redis"
type RunOptions ¶ added in v0.0.5
type RunOptions struct {
Hostname string
Name string
Repository string
Tag string
Env []string
Entrypoint []string
Cmd []string
ExposedPorts []string
WorkingDir string
Networks []*dockertest.Network // optional networks to join
Labels map[string]string
Auth docker.AuthConfiguration
User string
Tty bool
Platform string
HostConfig docker.HostConfig
// Allows you to reuse a container instead of getting an error that the container already exists.
// See [RetryOptions] struct description
Retry RetryOptions
ContainerExpiry time.Duration
// Try to reuse container if it already exists.
// See [ReuseContainerOptions] struct description.
Reuse ReuseContainerOptions
// Allows you to remove an existing container instead of getting an error that the container already exists.
// - Should not be used together with `Reuse` - will return `ErrOptionsConflict` error.
//
// Default: `false`
RemoveOnExists bool
}
RunOptions for (Pool).Run function.
func ApplyRunOptions ¶ added in v0.0.5
func ApplyRunOptions(repository string, customOpts ...RunOption) ( options RunOptions, err error, )
ApplyRunOptions sets defaults and apply custom options. Options aplies in order they passed.
Each option rewrites previous value
ApplyRunOptions(WithContainerName("first"), WithContainerName("second")) // "second"