1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
10 dockertypes "github.com/docker/docker/api/types"
11 dockercontainer "github.com/docker/docker/api/types/container"
12 dockernetwork "github.com/docker/docker/api/types/network"
13 "golang.org/x/net/context"
16 type DockerAdapter struct {
17 docker ThinDockerClient
18 containerConfig ContainerConfig
19 hostConfig dockercontainer.HostConfig
22 func (a *DockerAdapter) ContainerAttach(ctx context.Context, container string, options ContainerAttachOptions) (HijackedResponse, error) {
23 dockerOptions := dockertypes.ContainerAttachOptions{
24 Stream: options.Stream,
26 Stdout: options.Stdout,
27 Stderr: options.Stderr}
28 dockerResponse, docker_err := a.docker.ContainerAttach(ctx, container, dockerOptions)
30 adapterResponse := HijackedResponse{
31 Conn: dockerResponse.Conn,
32 Reader: dockerResponse.Reader,
35 return adapterResponse, docker_err
38 func (a *DockerAdapter) ContainerCreate(ctx context.Context, config ContainerConfig, hostConfig HostConfig, networkingConfig *NetworkingConfig, containerName string) (ContainerCreateResponse, error) {
39 var dockerEndpointsConfig map[string]*dockernetwork.EndpointSettings
41 var dockerNetworkConfig *dockernetwork.NetworkingConfig
42 if networkingConfig != nil {
43 for k, v := range networkingConfig.EndpointsConfig {
45 dockerIpamConfig := &dockernetwork.EndpointIPAMConfig{
46 IPv4Address: v.IPAMConfig.IPv4Address,
47 IPv6Address: v.IPAMConfig.IPv6Address,
48 LinkLocalIPs: v.IPAMConfig.LinkLocalIPs,
50 dockerEndpointsConfig[k] = &dockernetwork.EndpointSettings{
51 IPAMConfig: dockerIpamConfig,
54 NetworkID: v.NetworkID,
55 EndpointID: v.EndpointID,
57 IPAddress: v.IPAddress,
58 IPPrefixLen: v.IPPrefixLen,
59 IPv6Gateway: v.IPv6Gateway,
60 GlobalIPv6Address: v.GlobalIPv6Address,
61 GlobalIPv6PrefixLen: v.GlobalIPv6PrefixLen,
62 MacAddress: v.MacAddress,
63 DriverOpts: v.DriverOpts,
68 dockerNetworkConfig = &dockernetwork.NetworkingConfig{
69 EndpointsConfig: dockerEndpointsConfig,
72 dockerConfig := dockercontainer.Config{
73 OpenStdin: config.OpenStdin,
74 StdinOnce: config.StdinOnce,
75 AttachStdin: config.AttachStdin,
76 AttachStdout: config.AttachStdout,
77 AttachStderr: config.AttachStderr,
79 WorkingDir: config.WorkingDir,
81 Volumes: config.Volumes,
83 dockerHostConfig := dockercontainer.HostConfig{}
85 dockerResponse, dockerErr := a.docker.ContainerCreate(ctx,
87 &dockerHostConfig, dockerNetworkConfig, containerName)
88 adapterResponse := ContainerCreateResponse{
89 ID: dockerResponse.ID,
90 Warnings: dockerResponse.Warnings,
92 return adapterResponse, dockerErr
95 func (a *DockerAdapter) ContainerStart(ctx context.Context, container string, options ContainerStartOptions) error {
96 dockerContainerStartOptions := dockertypes.ContainerStartOptions{
97 CheckpointID: options.CheckpointID,
98 CheckpointDir: options.CheckpointDir,
101 dockerErr := a.docker.ContainerStart(ctx, container, dockerContainerStartOptions)
106 func (a *DockerAdapter) ContainerRemove(ctx context.Context, container string, options ContainerRemoveOptions) error {
107 dockerContainerRemoveOptions := dockertypes.ContainerRemoveOptions{Force: options.Force}
109 dockerErr := a.docker.ContainerRemove(ctx, container, dockerContainerRemoveOptions)
114 func (a *DockerAdapter) ContainerInspect(ctx context.Context, id string) (ContainerInspectResponse, error) {
116 dockerContainerInspectResponse, dockerErr := a.docker.ContainerInspect(ctx, id)
118 containerState := &ContainerState{
119 Running: dockerContainerInspectResponse.State.Running,
120 Paused: dockerContainerInspectResponse.State.Paused,
121 Restarting: dockerContainerInspectResponse.State.Restarting,
122 OOMKilled: dockerContainerInspectResponse.State.OOMKilled,
123 Dead: dockerContainerInspectResponse.State.Dead,
124 Pid: dockerContainerInspectResponse.State.Pid,
125 ExitCode: dockerContainerInspectResponse.State.ExitCode,
126 Error: dockerContainerInspectResponse.State.Error,
127 StartedAt: dockerContainerInspectResponse.State.StartedAt,
128 FinishedAt: dockerContainerInspectResponse.State.FinishedAt,
131 adapterResponse := &ContainerInspectResponse{State: containerState}
133 return *adapterResponse, dockerErr
136 func (a *DockerAdapter) ContainerWait(ctx context.Context, container string, condition WaitCondition) (<-chan ContainerWaitOKBody, <-chan error) {
138 //var dockercontainerCondition dockercontainer.WaitCondition =
139 dockercontainerCondition := dockercontainer.WaitCondition(condition)
141 dockerContainerWaitOKBody, dockerErr := a.docker.ContainerWait(ctx, container, dockercontainerCondition)
143 // translate from <-chan dockercontainer.ContainerWaitOKBody to <-chan ContainerWaitOKBody,
144 adapterContainerWaitOKBody := make(chan ContainerWaitOKBody)
146 for dockerMsg := range dockerContainerWaitOKBody {
147 var adapterBodyMsg *ContainerWaitOKBody
148 var adapterError *ContainerWaitOKBodyError
150 if dockerMsg.Error != nil {
151 adapterError = &ContainerWaitOKBodyError{
152 Message: dockerMsg.Error.Message,
156 adapterBodyMsg = &ContainerWaitOKBody{
158 StatusCode: dockerMsg.StatusCode,
161 adapterContainerWaitOKBody <- *adapterBodyMsg
165 return adapterContainerWaitOKBody, dockerErr
168 func (a *DockerAdapter) ImageInspectWithRaw(ctx context.Context, image string) (ImageInspectResponse, []byte, error) {
169 dockerImageInspectResponse, rawBytes, dockerErr := a.docker.ImageInspectWithRaw(ctx, image)
171 adapterImageInspectResponse := &ImageInspectResponse{
172 ID: dockerImageInspectResponse.ID,
174 return *adapterImageInspectResponse, rawBytes, dockerErr
177 func (a *DockerAdapter) ImageLoad(ctx context.Context, input io.Reader, quiet bool) (ImageLoadResponse, error) {
178 dockerImageLoadResponse, dockerErr := a.docker.ImageLoad(ctx, input, quiet)
180 adapterImageLoadResponse := &ImageLoadResponse{
181 Body: dockerImageLoadResponse.Body,
182 JSON: dockerImageLoadResponse.JSON,
185 return *adapterImageLoadResponse, dockerErr
188 func (a *DockerAdapter) ImageRemove(ctx context.Context, image string, options ImageRemoveOptions) ([]ImageDeleteResponseItem, error) {
190 dockerOptions := &dockertypes.ImageRemoveOptions{
191 Force: options.Force,
192 PruneChildren: options.PruneChildren,
194 dockerImageDeleteResponseItems, dockerErr := a.docker.ImageRemove(ctx, image, *dockerOptions)
196 var adapterResponses []ImageDeleteResponseItem
197 for _, dockerResponse := range dockerImageDeleteResponseItems {
198 adapterResponse := &ImageDeleteResponseItem{
199 Deleted: dockerResponse.Deleted,
200 Untagged: dockerResponse.Untagged,
202 adapterResponses = append(adapterResponses, *adapterResponse)
204 return adapterResponses, dockerErr
207 func (a *DockerAdapter) GetContainerConfig() (ContainerConfig, error) {
208 return a.containerConfig, nil
211 func (a *DockerAdapter) GetHostConfig() (HostConfig, error) {
212 adapterHostConfig := HostConfig{
213 Binds: a.hostConfig.Binds,
214 LogConfig: LogConfig{
215 Type: a.hostConfig.LogConfig.Type,
217 Resources: Resources{
218 CgroupParent: a.hostConfig.CgroupParent,
219 NanoCPUs: a.hostConfig.NanoCPUs,
220 Memory: a.hostConfig.Memory,
221 MemorySwap: a.hostConfig.MemorySwap,
222 KernelMemory: a.hostConfig.KernelMemory,
225 return adapterHostConfig, nil
228 func (a *DockerAdapter) SetHostConfig(adapterHostConfig HostConfig) error {
229 dockerHostConfig := dockercontainer.HostConfig{
230 Binds: adapterHostConfig.Binds,
231 LogConfig: dockercontainer.LogConfig{
232 Type: adapterHostConfig.LogConfig.Type,
234 Resources: dockercontainer.Resources{
235 CgroupParent: adapterHostConfig.CgroupParent,
236 NanoCPUs: adapterHostConfig.NanoCPUs,
237 Memory: adapterHostConfig.Memory,
238 MemorySwap: adapterHostConfig.MemorySwap,
239 KernelMemory: adapterHostConfig.KernelMemory,
242 a.hostConfig = dockerHostConfig
246 func (a *DockerAdapter) GetImage() (imageID string) {
247 return a.containerConfig.Image
250 func (a *DockerAdapter) SetImage(imageID string) {
251 a.containerConfig.Image = imageID
253 func (a *DockerAdapter) GetNetworkMode() (networkMode NetworkMode) {
254 return NetworkMode(a.hostConfig.NetworkMode)
257 func (a *DockerAdapter) SetNetworkMode(networkMode NetworkMode) {
258 a.hostConfig.NetworkMode = dockercontainer.NetworkMode(networkMode)
261 func adapter(docker ThinDockerClient) ThinContainerExecRunner {
262 return_object := &DockerAdapter{docker: docker}