forked from testcontainers/testcontainers-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
docker_client.go
129 lines (106 loc) · 3.51 KB
/
docker_client.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
package testcontainers
import (
"context"
"fmt"
"sync"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/api/types/system"
"github.com/docker/docker/client"
"github.com/testcontainers/testcontainers-go/internal/core"
)
// DockerClient is a wrapper around the docker client that is used by testcontainers-go.
// It implements the SystemAPIClient interface in order to cache the docker info and reuse it.
type DockerClient struct {
*client.Client // client is embedded into our own client
}
var (
// dockerInfo stores the docker info to be reused in the Info method
dockerInfo system.Info
dockerInfoSet bool
dockerInfoLock sync.Mutex
)
// implements SystemAPIClient interface
var _ client.SystemAPIClient = &DockerClient{}
// Events returns a channel to listen to events that happen to the docker daemon.
func (c *DockerClient) Events(ctx context.Context, options types.EventsOptions) (<-chan events.Message, <-chan error) {
return c.Client.Events(ctx, options)
}
// Info returns information about the docker server. The result of Info is cached
// and reused every time Info is called.
// It will also print out the docker server info, and the resolved Docker paths, to the default logger.
func (c *DockerClient) Info(ctx context.Context) (system.Info, error) {
dockerInfoLock.Lock()
defer dockerInfoLock.Unlock()
if dockerInfoSet {
return dockerInfo, nil
}
info, err := c.Client.Info(ctx)
if err != nil {
return info, fmt.Errorf("failed to retrieve docker info: %w", err)
}
dockerInfo = info
dockerInfoSet = true
infoMessage := `%v - Connected to docker:
Server Version: %v
API Version: %v
Operating System: %v
Total Memory: %v MB
Resolved Docker Host: %s
Resolved Docker Socket Path: %s
Test SessionID: %s
Test ProcessID: %s
`
Logger.Printf(infoMessage, packagePath,
dockerInfo.ServerVersion, c.Client.ClientVersion(),
dockerInfo.OperatingSystem, dockerInfo.MemTotal/1024/1024,
core.ExtractDockerHost(ctx),
core.ExtractDockerSocket(ctx),
core.SessionID(),
core.ProcessID(),
)
return dockerInfo, nil
}
// RegistryLogin logs into a Docker registry.
func (c *DockerClient) RegistryLogin(ctx context.Context, auth registry.AuthConfig) (registry.AuthenticateOKBody, error) {
return c.Client.RegistryLogin(ctx, auth)
}
// DiskUsage returns the disk usage of all images.
func (c *DockerClient) DiskUsage(ctx context.Context, options types.DiskUsageOptions) (types.DiskUsage, error) {
return c.Client.DiskUsage(ctx, options)
}
// Ping pings the docker server.
func (c *DockerClient) Ping(ctx context.Context) (types.Ping, error) {
return c.Client.Ping(ctx)
}
// Deprecated: Use NewDockerClientWithOpts instead.
func NewDockerClient() (*client.Client, error) {
cli, err := NewDockerClientWithOpts(context.Background())
if err != nil {
return nil, err
}
return cli.Client, nil
}
func NewDockerClientWithOpts(ctx context.Context, opt ...client.Opt) (*DockerClient, error) {
dockerClient, err := core.NewClient(ctx, opt...)
if err != nil {
return nil, err
}
tcClient := DockerClient{
Client: dockerClient,
}
if _, err = tcClient.Info(ctx); err != nil {
// Fallback to environment, including the original options
if len(opt) == 0 {
opt = []client.Opt{client.FromEnv, client.WithAPIVersionNegotiation()}
}
dockerClient, err := client.NewClientWithOpts(opt...)
if err != nil {
return nil, err
}
tcClient.Client = dockerClient
}
defer tcClient.Close()
return &tcClient, nil
}