robocar-base/vendor/github.com/testcontainers/testcontainers-go/provider.go

164 lines
4.9 KiB
Go

package testcontainers
import (
"context"
"errors"
"fmt"
"os"
"strings"
"github.com/testcontainers/testcontainers-go/internal/testcontainersdocker"
)
// possible provider types
const (
ProviderDefault ProviderType = iota // default will auto-detect provider from DOCKER_HOST environment variable
ProviderDocker
ProviderPodman
)
type (
// ProviderType is an enum for the possible providers
ProviderType int
// GenericProviderOptions defines options applicable to all providers
GenericProviderOptions struct {
Logger Logging
DefaultNetwork string
}
// GenericProviderOption defines a common interface to modify GenericProviderOptions
// These options can be passed to GetProvider in a variadic way to customize the returned GenericProvider instance
GenericProviderOption interface {
ApplyGenericTo(opts *GenericProviderOptions)
}
// GenericProviderOptionFunc is a shorthand to implement the GenericProviderOption interface
GenericProviderOptionFunc func(opts *GenericProviderOptions)
// DockerProviderOptions defines options applicable to DockerProvider
DockerProviderOptions struct {
defaultBridgeNetworkName string
*GenericProviderOptions
}
// DockerProviderOption defines a common interface to modify DockerProviderOptions
// These can be passed to NewDockerProvider in a variadic way to customize the returned DockerProvider instance
DockerProviderOption interface {
ApplyDockerTo(opts *DockerProviderOptions)
}
// DockerProviderOptionFunc is a shorthand to implement the DockerProviderOption interface
DockerProviderOptionFunc func(opts *DockerProviderOptions)
)
func (f DockerProviderOptionFunc) ApplyDockerTo(opts *DockerProviderOptions) {
f(opts)
}
func Generic2DockerOptions(opts ...GenericProviderOption) []DockerProviderOption {
converted := make([]DockerProviderOption, 0, len(opts))
for _, o := range opts {
switch c := o.(type) {
case DockerProviderOption:
converted = append(converted, c)
default:
converted = append(converted, DockerProviderOptionFunc(func(opts *DockerProviderOptions) {
o.ApplyGenericTo(opts.GenericProviderOptions)
}))
}
}
return converted
}
func WithDefaultBridgeNetwork(bridgeNetworkName string) DockerProviderOption {
return DockerProviderOptionFunc(func(opts *DockerProviderOptions) {
opts.defaultBridgeNetworkName = bridgeNetworkName
})
}
func (f GenericProviderOptionFunc) ApplyGenericTo(opts *GenericProviderOptions) {
f(opts)
}
// ContainerProvider allows the creation of containers on an arbitrary system
type ContainerProvider interface {
Close() error // close the provider
CreateContainer(context.Context, ContainerRequest) (Container, error) // create a container without starting it
ReuseOrCreateContainer(context.Context, ContainerRequest) (Container, error) // reuses a container if it exists or creates a container without starting
RunContainer(context.Context, ContainerRequest) (Container, error) // create a container and start it
Health(context.Context) error
Config() TestcontainersConfig
}
// GetProvider provides the provider implementation for a certain type
func (t ProviderType) GetProvider(opts ...GenericProviderOption) (GenericProvider, error) {
opt := &GenericProviderOptions{
Logger: Logger,
}
for _, o := range opts {
o.ApplyGenericTo(opt)
}
pt := t
if pt == ProviderDefault && strings.Contains(os.Getenv("DOCKER_HOST"), "podman.sock") {
pt = ProviderPodman
}
switch pt {
case ProviderDefault, ProviderDocker:
providerOptions := append(Generic2DockerOptions(opts...), WithDefaultBridgeNetwork(Bridge))
provider, err := NewDockerProvider(providerOptions...)
if err != nil {
return nil, fmt.Errorf("%w, failed to create Docker provider", err)
}
return provider, nil
case ProviderPodman:
providerOptions := append(Generic2DockerOptions(opts...), WithDefaultBridgeNetwork(Podman))
provider, err := NewDockerProvider(providerOptions...)
if err != nil {
return nil, fmt.Errorf("%w, failed to create Docker provider", err)
}
return provider, nil
}
return nil, errors.New("unknown provider")
}
// NewDockerProvider creates a Docker provider with the EnvClient
func NewDockerProvider(provOpts ...DockerProviderOption) (*DockerProvider, error) {
o := &DockerProviderOptions{
GenericProviderOptions: &GenericProviderOptions{
Logger: Logger,
},
}
for idx := range provOpts {
provOpts[idx].ApplyDockerTo(o)
}
c, err := NewDockerClient()
if err != nil {
return nil, err
}
tcConfig := ReadConfig()
dockerHost := testcontainersdocker.ExtractDockerHost(context.Background())
p := &DockerProvider{
DockerProviderOptions: o,
host: dockerHost,
client: c,
config: tcConfig,
}
// log docker server info only once
logOnce.Do(func() {
LogDockerServerInfo(context.Background(), p.client, p.Logger)
})
return p, nil
}