forked from testcontainers/testcontainers-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
provider.go
163 lines (135 loc) · 4.86 KB
/
provider.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
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
}