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 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 }
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(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(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
- `Retry.Backoff.MaxElapsedTime` - `time.Second * 20`
Example: ¶
func(options *RunOptions) (err error) { options.Retry.Operation = func(container *dockertest.Resource) (err error) { fmt.Println("ping") return nil } retryBackoff := backoff.NewExponentialBackOff() retryBackoff.MaxInterval = time.Second retryBackoff.MaxElapsedTime = time.Second * 20 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`
- `Backoff.MaxElapsedTime` - `time.Second * 20`
- `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.MaxElapsedTime = time.Second * 20 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"