From 27fe39f23646ee6c8e841cfc8261a0f33c582d31 Mon Sep 17 00:00:00 2001 From: Jordan Date: Thu, 28 Oct 2021 10:15:05 -0500 Subject: [PATCH] feat(mock): add logic from go-vela/mock --- go.mod | 1 + mock/doc.go | 11 + mock/docker/config.go | 59 ++++ mock/docker/container.go | 532 ++++++++++++++++++++++++++++++++++++ mock/docker/distribution.go | 30 ++ mock/docker/doc.go | 12 + mock/docker/docker.go | 43 +++ mock/docker/image.go | 256 +++++++++++++++++ mock/docker/mock.go | 112 ++++++++ mock/docker/network.go | 188 +++++++++++++ mock/docker/node.go | 62 +++++ mock/docker/plugin.go | 109 ++++++++ mock/docker/secret.go | 71 +++++ mock/docker/service.go | 106 +++++++ mock/docker/swarm.go | 89 ++++++ mock/docker/system.go | 72 +++++ mock/docker/volume.go | 184 +++++++++++++ mock/mock.go | 5 + runtime/docker/docker.go | 4 +- 19 files changed, 1944 insertions(+), 2 deletions(-) create mode 100644 mock/doc.go create mode 100644 mock/docker/config.go create mode 100644 mock/docker/container.go create mode 100644 mock/docker/distribution.go create mode 100644 mock/docker/doc.go create mode 100644 mock/docker/docker.go create mode 100644 mock/docker/image.go create mode 100644 mock/docker/mock.go create mode 100644 mock/docker/network.go create mode 100644 mock/docker/node.go create mode 100644 mock/docker/plugin.go create mode 100644 mock/docker/secret.go create mode 100644 mock/docker/service.go create mode 100644 mock/docker/swarm.go create mode 100644 mock/docker/system.go create mode 100644 mock/docker/volume.go create mode 100644 mock/mock.go diff --git a/go.mod b/go.mod index c82769c4..a6b1e620 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/go-vela/types v0.10.0 github.com/google/go-cmp v0.5.6 github.com/joho/godotenv v1.4.0 + github.com/opencontainers/image-spec v1.0.1 github.com/prometheus/client_golang v1.11.0 github.com/sirupsen/logrus v1.8.1 github.com/urfave/cli/v2 v2.3.0 diff --git a/mock/doc.go b/mock/doc.go new file mode 100644 index 00000000..b301891e --- /dev/null +++ b/mock/doc.go @@ -0,0 +1,11 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Package mock provides a collection of mock +// packages used for a Vela worker. +// +// Usage: +// +// import "github.com/go-vela/worker/mock" +package mock diff --git a/mock/docker/config.go b/mock/docker/config.go new file mode 100644 index 00000000..6ccbc2bf --- /dev/null +++ b/mock/docker/config.go @@ -0,0 +1,59 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "context" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" + "github.com/docker/docker/client" +) + +// ConfigService implements all the config +// related functions for the Docker mock. +type ConfigService struct{} + +// ConfigCreate is a helper function to simulate +// a mocked call to create a config for a +// Docker swarm cluster. +func (c *ConfigService) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error) { + return types.ConfigCreateResponse{}, nil +} + +// ConfigInspectWithRaw is a helper function to simulate +// a mocked call to inspect a config for a Docker swarm +// cluster and return the raw body received from the API. +func (c *ConfigService) ConfigInspectWithRaw(ctx context.Context, name string) (swarm.Config, []byte, error) { + return swarm.Config{}, nil, nil +} + +// ConfigList is a helper function to simulate +// a mocked call to list the configs for a +// Docker swarm cluster. +func (c *ConfigService) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) { + return nil, nil +} + +// ConfigRemove is a helper function to simulate +// a mocked call to remove a config for a +// Docker swarm cluster. +func (c *ConfigService) ConfigRemove(ctx context.Context, id string) error { return nil } + +// ConfigUpdate is a helper function to simulate +// a mocked call to update a config for a +// Docker swarm cluster. +func (c *ConfigService) ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error { + return nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure that our +// ImageService satisfies the ImageAPIClient interface that +// the Docker client expects. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#ConfigAPIClient +var _ client.ConfigAPIClient = (*ConfigService)(nil) diff --git a/mock/docker/container.go b/mock/docker/container.go new file mode 100644 index 00000000..773b7259 --- /dev/null +++ b/mock/docker/container.go @@ -0,0 +1,532 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "strings" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/client" + "github.com/docker/docker/errdefs" + "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/pkg/stringid" + v1 "github.com/opencontainers/image-spec/specs-go/v1" +) + +// ContainerService implements all the container +// related functions for the Docker mock. +type ContainerService struct{} + +// ContainerAttach is a helper function to simulate +// a mocked call to attach a connection to a +// Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerAttach +func (c *ContainerService) ContainerAttach(ctx context.Context, ctn string, options types.ContainerAttachOptions) (types.HijackedResponse, error) { + return types.HijackedResponse{}, nil +} + +// ContainerCommit is a helper function to simulate +// a mocked call to apply changes to a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerCommit +func (c *ContainerService) ContainerCommit(ctx context.Context, ctn string, options types.ContainerCommitOptions) (types.IDResponse, error) { + return types.IDResponse{}, nil +} + +// ContainerCreate is a helper function to simulate +// a mocked call to create a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerCreate +func (c *ContainerService) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, p *v1.Platform, ctn string) (container.ContainerCreateCreatedBody, error) { + // verify a container was provided + if len(ctn) == 0 { + return container.ContainerCreateCreatedBody{}, + errors.New("no container provided") + } + + // check if the container is notfound and + // check if the notfound should be ignored + if strings.Contains(ctn, "notfound") && + !strings.Contains(ctn, "ignorenotfound") { + return container.ContainerCreateCreatedBody{}, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such container: %s", ctn)) + } + + // check if the container is not-found and + // check if the not-found should be ignored + if strings.Contains(ctn, "not-found") && + !strings.Contains(ctn, "ignore-not-found") { + return container.ContainerCreateCreatedBody{}, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such container: %s", ctn)) + } + + // check if the image is not found + if strings.Contains(config.Image, "notfound") || + strings.Contains(config.Image, "not-found") { + return container.ContainerCreateCreatedBody{}, + errdefs.NotFound( + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + fmt.Errorf("Error response from daemon: manifest for %s not found: manifest unknown", config.Image), + ) + } + + // create response object to return + response := container.ContainerCreateCreatedBody{ + ID: stringid.GenerateRandomID(), + } + + return response, nil +} + +// ContainerDiff is a helper function to simulate +// a mocked call to show the differences in the +// filesystem between two Docker containers. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerDiff +func (c *ContainerService) ContainerDiff(ctx context.Context, ctn string) ([]container.ContainerChangeResponseItem, error) { + return nil, nil +} + +// ContainerExecAttach is a helper function to simulate +// a mocked call to attach a connection to a process +// running inside a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerExecAttach +func (c *ContainerService) ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error) { + return types.HijackedResponse{}, nil +} + +// ContainerExecCreate is a helper function to simulate +// a mocked call to create a process to run inside a +// Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerExecCreate +func (c *ContainerService) ContainerExecCreate(ctx context.Context, ctn string, config types.ExecConfig) (types.IDResponse, error) { + return types.IDResponse{}, nil +} + +// ContainerExecInspect is a helper function to simulate +// a mocked call to inspect a process running inside a +// Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerExecInspect +func (c *ContainerService) ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) { + return types.ContainerExecInspect{}, nil +} + +// ContainerExecResize is a helper function to simulate +// a mocked call to resize the tty for a process running +// inside a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerExecResize +func (c *ContainerService) ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error { + return nil +} + +// ContainerExecStart is a helper function to simulate +// a mocked call to start a process inside a Docker +// container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerExecStart +func (c *ContainerService) ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error { + return nil +} + +// ContainerExport is a helper function to simulate +// a mocked call to expore the contents of a Docker +// container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerExport +func (c *ContainerService) ContainerExport(ctx context.Context, ctn string) (io.ReadCloser, error) { + return nil, nil +} + +// ContainerInspect is a helper function to simulate +// a mocked call to inspect a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerInspect +func (c *ContainerService) ContainerInspect(ctx context.Context, ctn string) (types.ContainerJSON, error) { + // verify a container was provided + if len(ctn) == 0 { + return types.ContainerJSON{}, errors.New("no container provided") + } + + // check if the container is notfound and + // check if the notfound should be ignored + if strings.Contains(ctn, "notfound") && + !strings.Contains(ctn, "ignorenotfound") { + return types.ContainerJSON{}, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such container: %s", ctn)) + } + + // check if the container is not-found and + // check if the not-found should be ignored + if strings.Contains(ctn, "not-found") && + !strings.Contains(ctn, "ignore-not-found") { + return types.ContainerJSON{}, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such container: %s", ctn)) + } + + // create response object to return + response := types.ContainerJSON{ + ContainerJSONBase: &types.ContainerJSONBase{ + ID: stringid.GenerateRandomID(), + Image: "alpine:latest", + Name: ctn, + State: &types.ContainerState{Running: true}, + }, + Config: &container.Config{ + Image: "alpine:latest", + }, + } + + return response, nil +} + +// ContainerInspectWithRaw is a helper function to simulate +// a mocked call to inspect a Docker container and return +// the raw body received from the API. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerInspectWithRaw +func (c *ContainerService) ContainerInspectWithRaw(ctx context.Context, ctn string, getSize bool) (types.ContainerJSON, []byte, error) { + // verify a container was provided + if len(ctn) == 0 { + return types.ContainerJSON{}, nil, errors.New("no container provided") + } + + // check if the container is not found + if strings.Contains(ctn, "notfound") || + strings.Contains(ctn, "not-found") { + return types.ContainerJSON{}, + nil, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such container: %s", ctn)) + } + + // create response object to return + response := types.ContainerJSON{ + ContainerJSONBase: &types.ContainerJSONBase{ + ID: stringid.GenerateRandomID(), + Image: "alpine:latest", + Name: ctn, + State: &types.ContainerState{Running: true}, + }, + Config: &container.Config{ + Image: "alpine:latest", + }, + } + + // marshal response into raw bytes + b, err := json.Marshal(response) + if err != nil { + return types.ContainerJSON{}, nil, err + } + + return response, b, nil +} + +// ContainerKill is a helper function to simulate +// a mocked call to kill a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerKill +func (c *ContainerService) ContainerKill(ctx context.Context, ctn, signal string) error { + // verify a container was provided + if len(ctn) == 0 { + return errors.New("no container provided") + } + + // check if the container is not found + if strings.Contains(ctn, "notfound") || + strings.Contains(ctn, "not-found") { + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + return errdefs.NotFound(fmt.Errorf("Error: No such container: %s", ctn)) + } + + return nil +} + +// ContainerList is a helper function to simulate +// a mocked call to list Docker containers. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerList +func (c *ContainerService) ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error) { + return nil, nil +} + +// ContainerLogs is a helper function to simulate +// a mocked call to capture the logs from a +// Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerLogs +func (c *ContainerService) ContainerLogs(ctx context.Context, ctn string, options types.ContainerLogsOptions) (io.ReadCloser, error) { + // verify a container was provided + if len(ctn) == 0 { + return nil, errors.New("no container provided") + } + + // check if the container is not found + if strings.Contains(ctn, "notfound") || + strings.Contains(ctn, "not-found") { + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + return nil, errdefs.NotFound(fmt.Errorf("Error: No such container: %s", ctn)) + } + + // create response object to return + response := new(bytes.Buffer) + + // write stdout logs to response buffer + _, err := stdcopy. + NewStdWriter(response, stdcopy.Stdout). + Write([]byte("hello to stdout from github.com/go-vela/worker/mock/docker")) + if err != nil { + return nil, err + } + + // write stderr logs to response buffer + _, err = stdcopy. + NewStdWriter(response, stdcopy.Stderr). + Write([]byte("hello to stderr from github.com/go-vela/worker/mock/docker")) + if err != nil { + return nil, err + } + + return ioutil.NopCloser(response), nil +} + +// ContainerPause is a helper function to simulate +// a mocked call to pause a running Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerPause +func (c *ContainerService) ContainerPause(ctx context.Context, ctn string) error { + return nil +} + +// ContainerRemove is a helper function to simulate +// a mocked call to remove a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerRemove +func (c *ContainerService) ContainerRemove(ctx context.Context, ctn string, options types.ContainerRemoveOptions) error { + // verify a container was provided + if len(ctn) == 0 { + return errors.New("no container provided") + } + + // check if the container is not found + if strings.Contains(ctn, "notfound") || strings.Contains(ctn, "not-found") { + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + return errdefs.NotFound(fmt.Errorf("Error: No such container: %s", ctn)) + } + + return nil +} + +// ContainerRename is a helper function to simulate +// a mocked call to rename a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerRename +func (c *ContainerService) ContainerRename(ctx context.Context, container, newContainerName string) error { + return nil +} + +// ContainerResize is a helper function to simulate +// a mocked call to resize a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerResize +func (c *ContainerService) ContainerResize(ctx context.Context, ctn string, options types.ResizeOptions) error { + return nil +} + +// ContainerRestart is a helper function to simulate +// a mocked call to restart a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerRestart +func (c *ContainerService) ContainerRestart(ctx context.Context, ctn string, timeout *time.Duration) error { + return nil +} + +// ContainerStart is a helper function to simulate +// a mocked call to start a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerStart +func (c *ContainerService) ContainerStart(ctx context.Context, ctn string, options types.ContainerStartOptions) error { + // verify a container was provided + if len(ctn) == 0 { + return errors.New("no container provided") + } + + // check if the container is not found + if strings.Contains(ctn, "notfound") || + strings.Contains(ctn, "not-found") { + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + return errdefs.NotFound(fmt.Errorf("Error: No such container: %s", ctn)) + } + + return nil +} + +// ContainerStatPath is a helper function to simulate +// a mocked call to capture information about a path +// inside a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerStatPath +func (c *ContainerService) ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error) { + return types.ContainerPathStat{}, nil +} + +// ContainerStats is a helper function to simulate +// a mocked call to capture information about a +// Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerStats +func (c *ContainerService) ContainerStats(ctx context.Context, ctn string, stream bool) (types.ContainerStats, error) { + return types.ContainerStats{}, nil +} + +// ContainerStop is a helper function to simulate +// a mocked call to stop a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerStop +func (c *ContainerService) ContainerStop(ctx context.Context, ctn string, timeout *time.Duration) error { + // verify a container was provided + if len(ctn) == 0 { + return errors.New("no container provided") + } + + // check if the container is not found + if strings.Contains(ctn, "notfound") || strings.Contains(ctn, "not-found") { + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + return errdefs.NotFound(fmt.Errorf("Error: No such container: %s", ctn)) + } + + return nil +} + +// ContainerTop is a helper function to simulate +// a mocked call to show running processes inside +// a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerTop +func (c *ContainerService) ContainerTop(ctx context.Context, ctn string, arguments []string) (container.ContainerTopOKBody, error) { + return container.ContainerTopOKBody{}, nil +} + +// ContainerUnpause is a helper function to simulate +// a mocked call to unpause a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerUnpause +func (c *ContainerService) ContainerUnpause(ctx context.Context, ctn string) error { + return nil +} + +// ContainerUpdate is a helper function to simulate +// a mocked call to update a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerUpdate +func (c *ContainerService) ContainerUpdate(ctx context.Context, ctn string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error) { + return container.ContainerUpdateOKBody{}, nil +} + +// ContainerWait is a helper function to simulate +// a mocked call to wait for a running Docker +// container to finish. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainerWait +func (c *ContainerService) ContainerWait(ctx context.Context, ctn string, condition container.WaitCondition) (<-chan container.ContainerWaitOKBody, <-chan error) { + ctnCh := make(chan container.ContainerWaitOKBody, 1) + errCh := make(chan error, 1) + + // verify a container was provided + if len(ctn) == 0 { + // propagate the error to the error channel + errCh <- errors.New("no container provided") + + return ctnCh, errCh + } + + // check if the container is not found + if strings.Contains(ctn, "notfound") || strings.Contains(ctn, "not-found") { + // propagate the error to the error channel + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errCh <- errdefs.NotFound(fmt.Errorf("Error: No such container: %s", ctn)) + + return ctnCh, errCh + } + + // create goroutine for responding to call + go func() { + // create response object to return + response := container.ContainerWaitOKBody{ + StatusCode: 15, + } + + // sleep for 1 second to simulate waiting for the container + time.Sleep(1 * time.Second) + + // propagate the response to the container channel + ctnCh <- response + + // propagate nil to the error channel + errCh <- nil + }() + + return ctnCh, errCh +} + +// ContainersPrune is a helper function to simulate +// a mocked call to prune Docker containers. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ContainersPrune +func (c *ContainerService) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) { + return types.ContainersPruneReport{}, nil +} + +// ContainerStatsOneShot is a helper function to simulate +// a mocked call to return near realtime stats for a given container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.CopyFromContainer +func (c *ContainerService) ContainerStatsOneShot(ctx context.Context, containerID string) (types.ContainerStats, error) { + return types.ContainerStats{}, nil +} + +// CopyFromContainer is a helper function to simulate +// a mocked call to copy content from a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.CopyFromContainer +func (c *ContainerService) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) { + return nil, types.ContainerPathStat{}, nil +} + +// CopyToContainer is a helper function to simulate +// a mocked call to copy content to a Docker container. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.CopyToContainer +func (c *ContainerService) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error { + return nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure that our +// ContainerService satisfies the ContainerAPIClient interface that +// the Docker client expects. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#ContainerAPIClient +var _ client.ContainerAPIClient = (*ContainerService)(nil) diff --git a/mock/docker/distribution.go b/mock/docker/distribution.go new file mode 100644 index 00000000..eb78ce76 --- /dev/null +++ b/mock/docker/distribution.go @@ -0,0 +1,30 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "context" + + "github.com/docker/docker/api/types/registry" + "github.com/docker/docker/client" +) + +// DistributionService implements all the distribution +// related functions for the Docker mock. +type DistributionService struct{} + +// DistributionInspect is a helper function to simulate +// a mocked call to inspect a Docker image and return +// the digest and manifest. +func (d *DistributionService) DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registry.DistributionInspect, error) { + return registry.DistributionInspect{}, nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure that our +// DistributionService satisfies the DistributionAPIClient interface that +// the Docker client expects. +var _ client.DistributionAPIClient = (*DistributionService)(nil) diff --git a/mock/docker/doc.go b/mock/docker/doc.go new file mode 100644 index 00000000..04e8f801 --- /dev/null +++ b/mock/docker/doc.go @@ -0,0 +1,12 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +// Package docker provides a mock for using the Docker API. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc +// +// Usage: +// +// import "github.com/go-vela/worker/mock/docker" +package docker diff --git a/mock/docker/docker.go b/mock/docker/docker.go new file mode 100644 index 00000000..96b60895 --- /dev/null +++ b/mock/docker/docker.go @@ -0,0 +1,43 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +// nolint: godot // ignore comment ending in a list +// +// Version represents the supported Docker API version for the mock. +// +// The Docker API version is pinned to ensure compatibility between the +// Docker API and client. The goal is to maintain n-1 compatibility. +// +// The maximum supported Docker API version for the client is here: +// +// https://docs.docker.com/engine/api/#api-version-matrix +// +// For example (use the compatibility matrix above for reference): +// +// * the Docker version of v20.10 has a maximum API version of v1.41 +// * to maintain n-1, the API version is pinned to v1.40 +const Version = "v1.40" + +// New returns a client that is capable of handling +// Docker client calls and returning stub responses. +// nolint:golint // returning unexported type intentionally +func New() (*mock, error) { + return &mock{ + ConfigService: ConfigService{}, + ContainerService: ContainerService{}, + DistributionService: DistributionService{}, + ImageService: ImageService{}, + NetworkService: NetworkService{}, + NodeService: NodeService{}, + PluginService: PluginService{}, + SecretService: SecretService{}, + ServiceService: ServiceService{}, + SystemService: SystemService{}, + SwarmService: SwarmService{}, + VolumeService: VolumeService{}, + Version: Version, + }, nil +} diff --git a/mock/docker/image.go b/mock/docker/image.go new file mode 100644 index 00000000..23dac612 --- /dev/null +++ b/mock/docker/image.go @@ -0,0 +1,256 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "strings" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/image" + "github.com/docker/docker/api/types/registry" + "github.com/docker/docker/client" + "github.com/docker/docker/errdefs" + "github.com/docker/docker/pkg/stringid" +) + +// ImageService implements all the image +// related functions for the Docker mock. +type ImageService struct{} + +// BuildCachePrune is a helper function to simulate +// a mocked call to prune the build cache for the +// Docker daemon. +func (i *ImageService) BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) { + return nil, nil +} + +// BuildCancel is a helper function to simulate +// a mocked call to cancel building a Docker image. +func (i *ImageService) BuildCancel(ctx context.Context, id string) error { + return nil +} + +// ImageBuild is a helper function to simulate +// a mocked call to build a Docker image. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImageBuild +func (i *ImageService) ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) { + return types.ImageBuildResponse{}, nil +} + +// ImageCreate is a helper function to simulate +// a mocked call to create a Docker image. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImageCreate +func (i *ImageService) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) { + return nil, nil +} + +// ImageHistory is a helper function to simulate +// a mocked call to inspect the history for a +// Docker image. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImageHistory +func (i *ImageService) ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error) { + return nil, nil +} + +// ImageImport is a helper function to simulate +// a mocked call to import a Docker image. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImageImport +func (i *ImageService) ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) { + return nil, nil +} + +// ImageInspectWithRaw is a helper function to simulate +// a mocked call to inspect a Docker image and return +// the raw body received from the API. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImageInspectWithRaw +func (i *ImageService) ImageInspectWithRaw(ctx context.Context, image string) (types.ImageInspect, []byte, error) { + // verify an image was provided + if len(image) == 0 { + return types.ImageInspect{}, nil, errors.New("no image provided") + } + + // check if the image is not found + if strings.Contains(image, "notfound") || strings.Contains(image, "not-found") { + return types.ImageInspect{}, + nil, + errdefs.NotFound( + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + fmt.Errorf("Error response from daemon: manifest for %s not found: manifest unknown", image), + ) + } + + path := fmt.Sprintf("/var/lib/docker/overlay2/%s", stringid.GenerateRandomID()) + + // create response object to return + response := types.ImageInspect{ + ID: fmt.Sprintf("sha256:%s", stringid.GenerateRandomID()), + RepoTags: []string{"alpine:latest"}, + RepoDigests: []string{fmt.Sprintf("alpine@sha256:%s", stringid.GenerateRandomID())}, + Created: time.Now().String(), + Container: fmt.Sprintf("sha256:%s", stringid.GenerateRandomID()), + DockerVersion: "19.03.1-ce", + Architecture: "amd64", + Os: "linux", + Size: 5552690, + VirtualSize: 5552690, + GraphDriver: types.GraphDriverData{ + Data: map[string]string{ + "MergedDir": fmt.Sprintf("%s/merged", path), + "UpperDir": fmt.Sprintf("%s/diff", path), + "WorkDir": fmt.Sprintf("%s/work", path), + }, + Name: "overlay2", + }, + RootFS: types.RootFS{ + Type: "layers", + Layers: []string{fmt.Sprintf("sha256:%s", stringid.GenerateRandomID())}, + }, + Metadata: types.ImageMetadata{LastTagTime: time.Now()}, + } + + // marshal response into raw bytes + b, err := json.Marshal(response) + if err != nil { + return types.ImageInspect{}, nil, err + } + + return response, b, nil +} + +// ImageList is a helper function to simulate +// a mocked call to list Docker images. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImageList +func (i *ImageService) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) { + return nil, nil +} + +// ImageLoad is a helper function to simulate +// a mocked call to load a Docker image. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImageLoad +func (i *ImageService) ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error) { + return types.ImageLoadResponse{}, nil +} + +// ImagePull is a helper function to simulate +// a mocked call to pull a Docker image. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImagePull +func (i *ImageService) ImagePull(ctx context.Context, image string, options types.ImagePullOptions) (io.ReadCloser, error) { + // verify an image was provided + if len(image) == 0 { + return nil, errors.New("no container provided") + } + + // check if the image is notfound and + // check if the notfound should be ignored + if strings.Contains(image, "notfound") && + !strings.Contains(image, "ignorenotfound") { + return nil, + errdefs.NotFound( + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + fmt.Errorf("Error response from daemon: manifest for %s not found: manifest unknown", image), + ) + } + + // check if the image is not-found and + // check if the not-found should be ignored + if strings.Contains(image, "not-found") && + !strings.Contains(image, "ignore-not-found") { + return nil, + errdefs.NotFound( + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + fmt.Errorf("Error response from daemon: manifest for %s not found: manifest unknown", image), + ) + } + + // create response object to return + response := ioutil.NopCloser( + bytes.NewReader( + []byte( + fmt.Sprintf("%s\n%s\n%s\n%s\n", + fmt.Sprintf("latest: Pulling from %s", image), + fmt.Sprintf("Digest: sha256:%s", stringid.GenerateRandomID()), + fmt.Sprintf("Status: Image is up to date for %s", image), + image, + ), + ), + ), + ) + + return response, nil +} + +// ImagePush is a helper function to simulate +// a mocked call to push a Docker image. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImagePush +func (i *ImageService) ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) { + return nil, nil +} + +// ImageRemove is a helper function to simulate +// a mocked call to remove a Docker image. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImageRemove +func (i *ImageService) ImageRemove(ctx context.Context, image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) { + return nil, nil +} + +// ImageSave is a helper function to simulate +// a mocked call to save a Docker image. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImageSave +func (i *ImageService) ImageSave(ctx context.Context, images []string) (io.ReadCloser, error) { + return nil, nil +} + +// ImageSearch is a helper function to simulate +// a mocked call to search for a Docker image. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImageSearch +func (i *ImageService) ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error) { + return nil, nil +} + +// ImageTag is a helper function to simulate +// a mocked call to tag a Docker image. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImageTag +func (i *ImageService) ImageTag(ctx context.Context, image, ref string) error { + return nil +} + +// ImagesPrune is a helper function to simulate +// a mocked call to prune Docker images. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ImagesPrune +func (i *ImageService) ImagesPrune(ctx context.Context, pruneFilter filters.Args) (types.ImagesPruneReport, error) { + return types.ImagesPruneReport{}, nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure that our +// ImageService satisfies the ImageAPIClient interface that +// the Docker client expects. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#ImageAPIClient +var _ client.ImageAPIClient = (*ImageService)(nil) diff --git a/mock/docker/mock.go b/mock/docker/mock.go new file mode 100644 index 00000000..08a139d7 --- /dev/null +++ b/mock/docker/mock.go @@ -0,0 +1,112 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "context" + "net" + "net/http" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" +) + +type mock struct { + // Services + ConfigService + ContainerService + DistributionService + ImageService + NetworkService + NodeService + PluginService + SecretService + ServiceService + SwarmService + SystemService + VolumeService + + // Docker API version for the mock + Version string +} + +// ClientVersion is a helper function to return +// the version string associated with the mock. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ClientVersion +func (m *mock) ClientVersion() string { + return m.Version +} + +// Close is a helper function to simulate +// closing the transport client for the mock. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.Close +func (m *mock) Close() error { + return nil +} + +// DaemonHost is a helper function to simulate +// returning the host address used by the client. +func (m *mock) DaemonHost() string { + return "" +} + +// DialSession is a helper function to simulate +// returning a connection that can be used +// for communication with daemon. +func (m *mock) DialSession(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) { + return nil, nil +} + +// DialHijack is a helper function to simulate +// returning a hijacked connection with +// negotiated protocol proto. +func (m *mock) DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) { + return nil, nil +} + +// Dialer is a helper function to simulate +// returning a dialer for the raw stream +// connection, with HTTP/1.1 header, that can +// be used for proxying the daemon connection. +func (m *mock) Dialer() func(context.Context) (net.Conn, error) { + return func(context.Context) (net.Conn, error) { return nil, nil } +} + +// HTTPClient is a helper function to simulate +// returning a copy of the HTTP client bound +// to the server. +func (m *mock) HTTPClient() *http.Client { + return http.DefaultClient +} + +// NegotiateAPIVersion is a helper function to simulate +// a mocked call to query the API and update the client +// version to match the API version. +func (m *mock) NegotiateAPIVersion(ctx context.Context) {} + +// NegotiateAPIVersionPing is a helper function to simulate +// a mocked call to update the client version to match +// the ping version if it's less than the default version. +func (m *mock) NegotiateAPIVersionPing(types.Ping) {} + +// ServerVersion is a helper function to simulate +// a mocked call to return information on the +// Docker client and server host. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ServerVersion +func (m *mock) ServerVersion(ctx context.Context) (types.Version, error) { + return types.Version{}, nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure +// that our mock satisfies the Go interface that the +// Docker client expects. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#CommonAPIClient +var _ client.CommonAPIClient = (*mock)(nil) diff --git a/mock/docker/network.go b/mock/docker/network.go new file mode 100644 index 00000000..56df60d5 --- /dev/null +++ b/mock/docker/network.go @@ -0,0 +1,188 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/client" + "github.com/docker/docker/errdefs" + "github.com/docker/docker/pkg/stringid" +) + +// NetworkService implements all the network +// related functions for the Docker mock. +type NetworkService struct{} + +// NetworkConnect is a helper function to simulate +// a mocked call to connect to a Docker network. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.NetworkConnect +func (n *NetworkService) NetworkConnect(ctx context.Context, network, container string, config *network.EndpointSettings) error { + return nil +} + +// NetworkCreate is a helper function to simulate +// a mocked call to create a Docker network. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.NetworkCreate +func (n *NetworkService) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) { + // verify a network was provided + if len(name) == 0 { + return types.NetworkCreateResponse{}, errors.New("no network provided") + } + + // check if the network is notfound and + // check if the notfound should be ignored + if strings.Contains(name, "notfound") && + !strings.Contains(name, "ignorenotfound") { + return types.NetworkCreateResponse{}, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such network: %s", name)) + } + + // check if the network is not-found and + // check if the not-found should be ignored + if strings.Contains(name, "not-found") && + !strings.Contains(name, "ignore-not-found") { + return types.NetworkCreateResponse{}, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such network: %s", name)) + } + + // create response object to return + response := types.NetworkCreateResponse{ + ID: stringid.GenerateRandomID(), + } + + return response, nil +} + +// NetworkDisconnect is a helper function to simulate +// a mocked call to disconnect from a Docker network. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.NetworkDisconnect +func (n *NetworkService) NetworkDisconnect(ctx context.Context, network, container string, force bool) error { + return nil +} + +// NetworkInspect is a helper function to simulate +// a mocked call to inspect a Docker network. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.NetworkInspect +func (n *NetworkService) NetworkInspect(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, error) { + // verify a network was provided + if len(network) == 0 { + return types.NetworkResource{}, errors.New("no network provided") + } + + // check if the network is notfound + if strings.Contains(network, "notfound") { + return types.NetworkResource{}, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such network: %s", network)) + } + + // check if the network is not-found + if strings.Contains(network, "not-found") { + return types.NetworkResource{}, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such network: %s", network)) + } + + // create response object to return + response := types.NetworkResource{ + Attachable: false, + ConfigOnly: false, + Created: time.Now(), + Driver: "host", + ID: stringid.GenerateRandomID(), + Ingress: false, + Internal: false, + Name: network, + Scope: "local", + } + + return response, nil +} + +// NetworkInspectWithRaw is a helper function to simulate +// a mocked call to inspect a Docker network and return +// the raw body received from the API. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.NetworkInspectWithRaw +func (n *NetworkService) NetworkInspectWithRaw(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, []byte, error) { + // verify a network was provided + if len(network) == 0 { + return types.NetworkResource{}, nil, errors.New("no network provided") + } + + // create response object to return + response := types.NetworkResource{ + Attachable: false, + ConfigOnly: false, + Created: time.Now(), + Driver: "host", + ID: stringid.GenerateRandomID(), + Ingress: false, + Internal: false, + Name: network, + Scope: "local", + } + + // marshal response into raw bytes + b, err := json.Marshal(response) + if err != nil { + return types.NetworkResource{}, nil, err + } + + return response, b, nil +} + +// NetworkList is a helper function to simulate +// a mocked call to list Docker networks. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.NetworkList +func (n *NetworkService) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) { + return nil, nil +} + +// NetworkRemove is a helper function to simulate +// a mocked call to remove Docker a network. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.NetworkRemove +func (n *NetworkService) NetworkRemove(ctx context.Context, network string) error { + // verify a network was provided + if len(network) == 0 { + return errors.New("no network provided") + } + + return nil +} + +// NetworksPrune is a helper function to simulate +// a mocked call to prune Docker networks. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.NetworksPrune +func (n *NetworkService) NetworksPrune(ctx context.Context, pruneFilter filters.Args) (types.NetworksPruneReport, error) { + return types.NetworksPruneReport{}, nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure that our +// NetworkService satisfies the NetworkAPIClient interface that +// the Docker client expects. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#NetworkAPIClient +var _ client.NetworkAPIClient = (*NetworkService)(nil) diff --git a/mock/docker/node.go b/mock/docker/node.go new file mode 100644 index 00000000..168f0f01 --- /dev/null +++ b/mock/docker/node.go @@ -0,0 +1,62 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "context" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" + "github.com/docker/docker/client" +) + +// NodeService implements all the node +// related functions for the Docker mock. +type NodeService struct{} + +// NodeInspectWithRaw is a helper function to simulate +// a mocked call to inspect a node for a Docker swarm +// cluster and return the raw body received from the API. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.NodeInspectWithRaw +func (n *NodeService) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error) { + return swarm.Node{}, nil, nil +} + +// NodeList is a helper function to simulate +// a mocked call to list the nodes for a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.NodeList +func (n *NodeService) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) { + return nil, nil +} + +// NodeRemove is a helper function to simulate +// a mocked call to remove a node from a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.NodeRemove +func (n *NodeService) NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error { + return nil +} + +// NodeUpdate is a helper function to simulate +// a mocked call to update a node for a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.NodeUpdate +func (n *NodeService) NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error { + return nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure that our +// NodeService satisfies the NodeAPIClient interface that +// the Docker client expects. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#NodeAPIClient +var _ client.NodeAPIClient = (*NodeService)(nil) diff --git a/mock/docker/plugin.go b/mock/docker/plugin.go new file mode 100644 index 00000000..396250a0 --- /dev/null +++ b/mock/docker/plugin.go @@ -0,0 +1,109 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "context" + "io" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/client" +) + +// PluginService implements all the plugin +// related functions for the Docker mock. +type PluginService struct{} + +// PluginCreate is a helper function to simulate +// a mocked call to create a Docker plugin. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.PluginCreate +func (p *PluginService) PluginCreate(ctx context.Context, createContext io.Reader, options types.PluginCreateOptions) error { + return nil +} + +// PluginDisable is a helper function to simulate +// a mocked call to disable a Docker plugin. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.PluginDisable +func (p *PluginService) PluginDisable(ctx context.Context, name string, options types.PluginDisableOptions) error { + return nil +} + +// PluginEnable is a helper function to simulate +// a mocked call to enable a Docker plugin. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.PluginEnable +func (p *PluginService) PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error { + return nil +} + +// PluginInspectWithRaw is a helper function to simulate +// a mocked call to inspect a Docker plugin and return +// the raw body received from the API. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.PluginInspectWithRaw +func (p *PluginService) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) { + return nil, nil, nil +} + +// PluginInstall is a helper function to simulate +// a mocked call to install a Docker plugin. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.PluginInstall +func (p *PluginService) PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error) { + return nil, nil +} + +// PluginList is a helper function to simulate +// a mocked call to list Docker plugins. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.PluginList +func (p *PluginService) PluginList(ctx context.Context, filter filters.Args) (types.PluginsListResponse, error) { + return types.PluginsListResponse{}, nil +} + +// PluginPush is a helper function to simulate +// a mocked call to push a Docker plugin. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.PluginPush +func (p *PluginService) PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) { + return nil, nil +} + +// PluginRemove is a helper function to simulate +// a mocked call to remove a Docker plugin. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.PluginRemove +func (p *PluginService) PluginRemove(ctx context.Context, name string, options types.PluginRemoveOptions) error { + return nil +} + +// PluginSet is a helper function to simulate +// a mocked call to update settings for a +// Docker plugin. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.PluginSet +func (p *PluginService) PluginSet(ctx context.Context, name string, args []string) error { + return nil +} + +// PluginUpgrade is a helper function to simulate +// a mocked call to upgrade a Docker plugin. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.PluginUpgrade +func (p *PluginService) PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error) { + return nil, nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure that our +// PluginService satisfies the PluginAPIClient interface that +// the Docker client expects. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#PluginAPIClient +var _ client.PluginAPIClient = (*PluginService)(nil) diff --git a/mock/docker/secret.go b/mock/docker/secret.go new file mode 100644 index 00000000..04f4495a --- /dev/null +++ b/mock/docker/secret.go @@ -0,0 +1,71 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "context" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" + "github.com/docker/docker/client" +) + +// SecretService implements all the secret +// related functions for the Docker mock. +type SecretService struct{} + +// SecretCreate is a helper function to simulate +// a mocked call to create a secret for a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.SecretCreate +func (s *SecretService) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error) { + return types.SecretCreateResponse{}, nil +} + +// SecretInspectWithRaw is a helper function to simulate +// a mocked call to inspect a Docker secret and return +// the raw body received from the API. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.SecretInspectWithRaw +func (s *SecretService) SecretInspectWithRaw(ctx context.Context, name string) (swarm.Secret, []byte, error) { + return swarm.Secret{}, nil, nil +} + +// SecretList is a helper function to simulate +// a mocked call to list secrets for a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.SecretList +func (s *SecretService) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) { + return nil, nil +} + +// SecretRemove is a helper function to simulate +// a mocked call to remove a secret for a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.SecretRemove +func (s *SecretService) SecretRemove(ctx context.Context, id string) error { + return nil +} + +// SecretUpdate is a helper function to simulate +// a mocked call to update a secret for a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.SecretUpdate +func (s *SecretService) SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error { + return nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure that our +// SecretService satisfies the SecretAPIClient interface that +// the Docker client expects. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#SecretAPIClient +var _ client.SecretAPIClient = (*SecretService)(nil) diff --git a/mock/docker/service.go b/mock/docker/service.go new file mode 100644 index 00000000..750a1522 --- /dev/null +++ b/mock/docker/service.go @@ -0,0 +1,106 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "context" + "io" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" + "github.com/docker/docker/client" +) + +// ServiceService implements all the service +// related functions for the Docker mock. +type ServiceService struct{} + +// ServiceCreate is a helper function to simulate +// a mocked call to create a service for a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ServiceCreate +func (s *ServiceService) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) { + return types.ServiceCreateResponse{}, nil +} + +// ServiceInspectWithRaw is a helper function to simulate +// a mocked call to inspect a Docker service and return +// the raw body received from the API. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ServiceInspectWithRaw +func (s *ServiceService) ServiceInspectWithRaw(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) { + return swarm.Service{}, nil, nil +} + +// ServiceList is a helper function to simulate +// a mocked call to list services for a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ServiceList +func (s *ServiceService) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) { + return nil, nil +} + +// ServiceLogs is a helper function to simulate +// a mocked call to capture the logs from a +// service for a Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ServiceLogs +func (s *ServiceService) ServiceLogs(ctx context.Context, serviceID string, options types.ContainerLogsOptions) (io.ReadCloser, error) { + return nil, nil +} + +// ServiceRemove is a helper function to simulate +// a mocked call to remove a service for a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ServiceRemove +func (s *ServiceService) ServiceRemove(ctx context.Context, serviceID string) error { + return nil +} + +// ServiceUpdate is a helper function to simulate +// a mocked call to update a service for a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.ServiceUpdate +func (s *ServiceService) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) { + return types.ServiceUpdateResponse{}, nil +} + +// TaskInspectWithRaw is a helper function to simulate +// a mocked call to inspect a task for a Docker swarm +// cluster and return the raw body received from the API. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.TaskInspectWithRaw +func (s *ServiceService) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) { + return swarm.Task{}, nil, nil +} + +// TaskList is a helper function to simulate +// a mocked call to list tasks for a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.TaskList +func (s *ServiceService) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) { + return nil, nil +} + +// TaskLogs is a helper function to simulate +// a mocked call to capture the logs from a +// task for a Docker swarm cluster. +func (s *ServiceService) TaskLogs(ctx context.Context, taskID string, options types.ContainerLogsOptions) (io.ReadCloser, error) { + return nil, nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure that our +// ServiceService satisfies the ServiceAPIClient interface that +// the Docker client expects. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#ServiceAPIClient +var _ client.ServiceAPIClient = (*ServiceService)(nil) diff --git a/mock/docker/swarm.go b/mock/docker/swarm.go new file mode 100644 index 00000000..bf45b893 --- /dev/null +++ b/mock/docker/swarm.go @@ -0,0 +1,89 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "context" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" + "github.com/docker/docker/client" +) + +// SwarmService implements all the swarm +// related functions for the Docker mock. +type SwarmService struct{} + +// SwarmGetUnlockKey is a helper function to simulate +// a mocked call to capture the unlock key for a +// Docker swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.SwarmGetUnlockKey +func (s *SwarmService) SwarmGetUnlockKey(ctx context.Context) (types.SwarmUnlockKeyResponse, error) { + return types.SwarmUnlockKeyResponse{}, nil +} + +// SwarmInit is a helper function to simulate +// a mocked call to initialize the Docker +// swarm cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.SwarmInit +func (s *SwarmService) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) { + return "", nil +} + +// SwarmInspect is a helper function to simulate +// a mocked call to inspect the Docker swarm +// cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.SwarmInspect +func (s *SwarmService) SwarmInspect(ctx context.Context) (swarm.Swarm, error) { + return swarm.Swarm{}, nil +} + +// SwarmJoin is a helper function to simulate +// a mocked call to join the Docker swarm +// cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.SwarmJoin +func (s *SwarmService) SwarmJoin(ctx context.Context, req swarm.JoinRequest) error { + return nil +} + +// SwarmLeave is a helper function to simulate +// a mocked call to leave the Docker swarm +// cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.SwarmLeave +func (s *SwarmService) SwarmLeave(ctx context.Context, force bool) error { + return nil +} + +// SwarmUnlock is a helper function to simulate +// a mocked call to unlock the Docker swarm +// cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.SwarmUnlock +func (s *SwarmService) SwarmUnlock(ctx context.Context, req swarm.UnlockRequest) error { + return nil +} + +// SwarmUpdate is a helper function to simulate +// a mocked call to update the Docker swarm +// cluster. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.SwarmUpdate +func (s *SwarmService) SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error { + return nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure that our +// SwarmService satisfies the SwarmAPIClient interface that +// the Docker client expects. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#SwarmAPIClient +var _ client.SwarmAPIClient = (*SwarmService)(nil) diff --git a/mock/docker/system.go b/mock/docker/system.go new file mode 100644 index 00000000..bac9f756 --- /dev/null +++ b/mock/docker/system.go @@ -0,0 +1,72 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "context" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/events" + "github.com/docker/docker/api/types/registry" + "github.com/docker/docker/client" +) + +// SystemService implements all the system +// related functions for the Docker mock. +type SystemService struct{} + +// DiskUsage is a helper function to simulate +// a mocked call to capture the data usage +// from the Docker daemon. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.DiskUsage +func (s *SystemService) DiskUsage(ctx context.Context) (types.DiskUsage, error) { + return types.DiskUsage{}, nil +} + +// Events is a helper function to simulate +// a mocked call to capture the events +// from the Docker daemon. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.Events +func (s *SystemService) Events(ctx context.Context, options types.EventsOptions) (<-chan events.Message, <-chan error) { + return nil, nil +} + +// Info is a helper function to simulate +// a mocked call to capture the system +// information from the Docker daemon. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.Info +func (s *SystemService) Info(ctx context.Context) (types.Info, error) { + return types.Info{}, nil +} + +// Ping is a helper function to simulate +// a mocked call to ping the Docker +// daemon and return version information. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.Ping +func (s *SystemService) Ping(ctx context.Context) (types.Ping, error) { + return types.Ping{}, nil +} + +// RegistryLogin is a helper function to simulate +// a mocked call to authenticate the Docker +// daemon against a Docker registry. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.RegistryLogin +func (s *SystemService) RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error) { + return registry.AuthenticateOKBody{}, nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure that our +// SystemService satisfies the SystemAPIClient interface that +// the Docker client expects. +// +// hhttps://pkg.go.dev/github.com/docker/docker/client?tab=doc#SystemAPIClient +var _ client.NetworkAPIClient = (*NetworkService)(nil) diff --git a/mock/docker/volume.go b/mock/docker/volume.go new file mode 100644 index 00000000..36009818 --- /dev/null +++ b/mock/docker/volume.go @@ -0,0 +1,184 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package docker + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/volume" + "github.com/docker/docker/client" + "github.com/docker/docker/errdefs" + "github.com/docker/docker/pkg/stringid" +) + +// VolumeService implements all the volume +// related functions for the Docker mock. +type VolumeService struct{} + +// VolumeCreate is a helper function to simulate +// a mocked call to create a Docker volume. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.VolumeCreate +func (v *VolumeService) VolumeCreate(ctx context.Context, options volume.VolumeCreateBody) (types.Volume, error) { + // verify a volume was provided + if len(options.Name) == 0 { + return types.Volume{}, errors.New("no volume provided") + } + + // check if the volume is notfound and + // check if the notfound should be ignored + if strings.Contains(options.Name, "notfound") && + !strings.Contains(options.Name, "ignorenotfound") { + return types.Volume{}, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such volume: %s", options.Name)) + } + + // check if the volume is not-found and + // check if the not-found should be ignored + if strings.Contains(options.Name, "not-found") && + !strings.Contains(options.Name, "ignore-not-found") { + return types.Volume{}, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such volume: %s", options.Name)) + } + + // create response object to return + response := types.Volume{ + CreatedAt: time.Now().String(), + Driver: options.Driver, + Labels: options.Labels, + Mountpoint: fmt.Sprintf("/var/lib/docker/volumes/%s/_data", stringid.GenerateRandomID()), + Name: options.Name, + Options: options.DriverOpts, + Scope: "local", + } + + return response, nil +} + +// VolumeInspect is a helper function to simulate +// a mocked call to inspect a Docker volume. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.VolumeInspect +func (v *VolumeService) VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error) { + // verify a volume was provided + if len(volumeID) == 0 { + return types.Volume{}, errors.New("no volume provided") + } + + // check if the volume is notfound + if strings.Contains(volumeID, "notfound") { + return types.Volume{}, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such volume: %s", volumeID)) + } + + // check if the volume is not-found + if strings.Contains(volumeID, "not-found") { + return types.Volume{}, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such volume: %s", volumeID)) + } + + // create response object to return + response := types.Volume{ + CreatedAt: time.Now().String(), + Driver: "local", + Mountpoint: fmt.Sprintf("/var/lib/docker/volumes/%s/_data", stringid.GenerateRandomID()), + Name: volumeID, + Scope: "local", + } + + return response, nil +} + +// VolumeInspectWithRaw is a helper function to simulate +// a mocked call to inspect a Docker volume and return +// the raw body received from the API. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.VolumeInspectWithRaw +func (v *VolumeService) VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error) { + // verify a volume was provided + if len(volumeID) == 0 { + return types.Volume{}, nil, errors.New("no volume provided") + } + + // check if the volume is notfound + if strings.Contains(volumeID, "notfound") { + return types.Volume{}, nil, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such volume: %s", volumeID)) + } + + // check if the volume is not-found + if strings.Contains(volumeID, "not-found") { + return types.Volume{}, nil, + // nolint:golint,stylecheck // messsage is capitalized to match Docker messages + errdefs.NotFound(fmt.Errorf("Error: No such volume: %s", volumeID)) + } + + // create response object to return + response := types.Volume{ + CreatedAt: time.Now().String(), + Driver: "local", + Mountpoint: fmt.Sprintf("/var/lib/docker/volumes/%s/_data", stringid.GenerateRandomID()), + Name: volumeID, + Scope: "local", + } + + // marshal response into raw bytes + b, err := json.Marshal(response) + if err != nil { + return types.Volume{}, nil, err + } + + return response, b, nil +} + +// VolumeList is a helper function to simulate +// a mocked call to list Docker volumes. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.VolumeList +func (v *VolumeService) VolumeList(ctx context.Context, filter filters.Args) (volume.VolumeListOKBody, error) { + return volume.VolumeListOKBody{}, nil +} + +// VolumeRemove is a helper function to simulate +// a mocked call to remove Docker a volume. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.VolumeRemove +func (v *VolumeService) VolumeRemove(ctx context.Context, volumeID string, force bool) error { + // verify a volume was provided + if len(volumeID) == 0 { + return errors.New("no volume provided") + } + + return nil +} + +// VolumesPrune is a helper function to simulate +// a mocked call to prune Docker volumes. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#Client.VolumesPrune +func (v *VolumeService) VolumesPrune(ctx context.Context, pruneFilter filters.Args) (types.VolumesPruneReport, error) { + return types.VolumesPruneReport{}, nil +} + +// WARNING: DO NOT REMOVE THIS UNDER ANY CIRCUMSTANCES +// +// This line serves as a quick and efficient way to ensure that our +// VolumeService satisfies the VolumeAPIClient interface that +// the Docker client expects. +// +// https://pkg.go.dev/github.com/docker/docker/client?tab=doc#VolumeAPIClient +var _ client.VolumeAPIClient = (*VolumeService)(nil) diff --git a/mock/mock.go b/mock/mock.go new file mode 100644 index 00000000..7ff45c76 --- /dev/null +++ b/mock/mock.go @@ -0,0 +1,5 @@ +// Copyright (c) 2021 Target Brands, Inc. All rights reserved. +// +// Use of this source code is governed by the LICENSE file in this repository. + +package mock diff --git a/runtime/docker/docker.go b/runtime/docker/docker.go index 8f18dc42..e293904d 100644 --- a/runtime/docker/docker.go +++ b/runtime/docker/docker.go @@ -7,7 +7,7 @@ package docker import ( docker "github.com/docker/docker/client" - mock "github.com/go-vela/mock/docker" + mock "github.com/go-vela/worker/mock/docker" ) // nolint: godot // ignore comment ending in a list @@ -96,7 +96,7 @@ func NewMock(opts ...ClientOpt) (*client, error) { // create Docker client from the mock client // - // https://pkg.go.dev/github.com/go-vela/mock/docker#New + // https://pkg.go.dev/github.com/go-vela/worker/mock/docker#New _docker, err := mock.New() if err != nil { return nil, err