Remove containerizedengine package dependency from docker/cli/command…

… this removes a whole lot of dependencies from people depending on docker/cli…

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
Vincent Demeester 2018-09-11 14:46:30 +02:00
parent 8ec21567a7
commit 2d344b2f61
No known key found for this signature in database
GPG Key ID: 083CC6FD6EB699A3
29 changed files with 283 additions and 262 deletions

View File

@ -19,8 +19,8 @@ import (
manifeststore "github.com/docker/cli/cli/manifest/store"
registryclient "github.com/docker/cli/cli/registry/client"
"github.com/docker/cli/cli/trust"
"github.com/docker/cli/internal/containerizedengine"
dopts "github.com/docker/cli/opts"
clitypes "github.com/docker/cli/types"
"github.com/docker/docker/api"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
@ -55,20 +55,21 @@ type Cli interface {
ManifestStore() manifeststore.Store
RegistryClient(bool) registryclient.RegistryClient
ContentTrustEnabled() bool
NewContainerizedEngineClient(sockPath string) (containerizedengine.Client, error)
NewContainerizedEngineClient(sockPath string) (clitypes.ContainerizedClient, error)
}
// DockerCli is an instance the docker command line client.
// Instances of the client can be returned from NewDockerCli.
type DockerCli struct {
configFile *configfile.ConfigFile
in *InStream
out *OutStream
err io.Writer
client client.APIClient
serverInfo ServerInfo
clientInfo ClientInfo
contentTrust bool
configFile *configfile.ConfigFile
in *InStream
out *OutStream
err io.Writer
client client.APIClient
serverInfo ServerInfo
clientInfo ClientInfo
contentTrust bool
newContainerizeClient func(string) (clitypes.ContainerizedClient, error)
}
// DefaultVersion returns api.defaultVersion or DOCKER_API_VERSION if specified.
@ -233,8 +234,8 @@ func (cli *DockerCli) NotaryClient(imgRefAndAuth trust.ImageRefAndAuth, actions
}
// NewContainerizedEngineClient returns a containerized engine client
func (cli *DockerCli) NewContainerizedEngineClient(sockPath string) (containerizedengine.Client, error) {
return containerizedengine.NewClient(sockPath)
func (cli *DockerCli) NewContainerizedEngineClient(sockPath string) (clitypes.ContainerizedClient, error) {
return cli.newContainerizeClient(sockPath)
}
// ServerInfo stores details about the supported features and platform of the
@ -252,8 +253,8 @@ type ClientInfo struct {
}
// NewDockerCli returns a DockerCli instance with IO output and error streams set by in, out and err.
func NewDockerCli(in io.ReadCloser, out, err io.Writer, isTrusted bool) *DockerCli {
return &DockerCli{in: NewInStream(in), out: NewOutStream(out), err: err, contentTrust: isTrusted}
func NewDockerCli(in io.ReadCloser, out, err io.Writer, isTrusted bool, containerizedFn func(string) (clitypes.ContainerizedClient, error)) *DockerCli {
return &DockerCli{in: NewInStream(in), out: NewOutStream(out), err: err, contentTrust: isTrusted, newContainerizeClient: containerizedFn}
}
// NewAPIClientFromFlags creates a new APIClient from command line flags

View File

@ -6,8 +6,8 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/cli/internal/containerizedengine"
"github.com/docker/cli/internal/licenseutils"
clitypes "github.com/docker/cli/types"
"github.com/docker/docker/api/types"
"github.com/docker/licensing/model"
"github.com/pkg/errors"
@ -57,7 +57,7 @@ https://hub.docker.com/ then specify the file with the '--license' flag.
flags.StringVar(&options.licenseFile, "license", "", "License File")
flags.StringVar(&options.version, "version", "", "Specify engine version (default is to use currently running version)")
flags.StringVar(&options.registryPrefix, "registry-prefix", "docker.io/docker", "Override the default location where engine images are pulled")
flags.StringVar(&options.image, "engine-image", containerizedengine.EnterpriseEngineImage, "Specify engine image")
flags.StringVar(&options.image, "engine-image", clitypes.EnterpriseEngineImage, "Specify engine image")
flags.StringVar(&options.format, "format", "", "Pretty-print licenses using a Go template")
flags.BoolVar(&options.displayOnly, "display-only", false, "only display the available licenses and exit")
flags.BoolVar(&options.quiet, "quiet", false, "Only display available licenses by ID")
@ -98,7 +98,7 @@ func runActivate(cli command.Cli, options activateOptions) error {
return err
}
opts := containerizedengine.EngineInitOptions{
opts := clitypes.EngineInitOptions{
RegistryPrefix: options.registryPrefix,
EngineImage: options.image,
EngineVersion: options.version,

View File

@ -4,13 +4,13 @@ import (
"fmt"
"testing"
"github.com/docker/cli/internal/containerizedengine"
"github.com/docker/cli/types"
"gotest.tools/assert"
)
func TestActivateNoContainerd(t *testing.T) {
testCli.SetContainerizedEngineClient(
func(string) (containerizedengine.Client, error) {
func(string) (types.ContainerizedClient, error) {
return nil, fmt.Errorf("some error")
},
)
@ -24,7 +24,7 @@ func TestActivateNoContainerd(t *testing.T) {
func TestActivateBadLicense(t *testing.T) {
testCli.SetContainerizedEngineClient(
func(string) (containerizedengine.Client, error) {
func(string) (types.ContainerizedClient, error) {
return &fakeContainerizedEngineClient{}, nil
},
)

View File

@ -7,7 +7,7 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/cli/internal/containerizedengine"
clitypes "github.com/docker/cli/types"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -72,7 +72,7 @@ func runCheck(dockerCli command.Cli, options checkOptions) error {
return err
}
availUpdates := []containerizedengine.Update{
availUpdates := []clitypes.Update{
{Type: "current", Version: currentVersion},
}
if len(versions.Patches) > 0 {
@ -115,14 +115,14 @@ func runCheck(dockerCli command.Cli, options checkOptions) error {
func processVersions(currentVersion, verType string,
includePrerelease bool,
versions []containerizedengine.DockerVersion) []containerizedengine.Update {
availUpdates := []containerizedengine.Update{}
versions []clitypes.DockerVersion) []clitypes.Update {
availUpdates := []clitypes.Update{}
for _, ver := range versions {
if !includePrerelease && ver.Prerelease() != "" {
continue
}
if ver.Tag != currentVersion {
availUpdates = append(availUpdates, containerizedengine.Update{
availUpdates = append(availUpdates, clitypes.Update{
Type: verType,
Version: ver.Tag,
Notes: fmt.Sprintf("%s/%s", releaseNotePrefix, ver.Tag),

View File

@ -6,8 +6,8 @@ import (
"testing"
registryclient "github.com/docker/cli/cli/registry/client"
"github.com/docker/cli/internal/containerizedengine"
"github.com/docker/cli/internal/test"
clitypes "github.com/docker/cli/types"
"github.com/docker/docker/client"
ver "github.com/hashicorp/go-version"
"gotest.tools/assert"
@ -20,7 +20,7 @@ var (
func TestCheckForUpdatesNoContainerd(t *testing.T) {
testCli.SetContainerizedEngineClient(
func(string) (containerizedengine.Client, error) {
func(string) (clitypes.ContainerizedClient, error) {
return nil, fmt.Errorf("some error")
},
)
@ -33,11 +33,11 @@ func TestCheckForUpdatesNoContainerd(t *testing.T) {
func TestCheckForUpdatesNoCurrentVersion(t *testing.T) {
retErr := fmt.Errorf("some failure")
getCurrentEngineVersionFunc := func(ctx context.Context) (containerizedengine.EngineInitOptions, error) {
return containerizedengine.EngineInitOptions{}, retErr
getCurrentEngineVersionFunc := func(ctx context.Context) (clitypes.EngineInitOptions, error) {
return clitypes.EngineInitOptions{}, retErr
}
testCli.SetContainerizedEngineClient(
func(string) (containerizedengine.Client, error) {
func(string) (clitypes.ContainerizedClient, error) {
return &fakeContainerizedEngineClient{
getCurrentEngineVersionFunc: getCurrentEngineVersionFunc,
}, nil
@ -54,11 +54,11 @@ func TestCheckForUpdatesGetEngineVersionsFail(t *testing.T) {
retErr := fmt.Errorf("some failure")
getEngineVersionsFunc := func(ctx context.Context,
registryClient registryclient.RegistryClient,
currentVersion, imageName string) (containerizedengine.AvailableVersions, error) {
return containerizedengine.AvailableVersions{}, retErr
currentVersion, imageName string) (clitypes.AvailableVersions, error) {
return clitypes.AvailableVersions{}, retErr
}
testCli.SetContainerizedEngineClient(
func(string) (containerizedengine.Client, error) {
func(string) (clitypes.ContainerizedClient, error) {
return &fakeContainerizedEngineClient{
getEngineVersionsFunc: getEngineVersionsFunc,
}, nil
@ -72,23 +72,23 @@ func TestCheckForUpdatesGetEngineVersionsFail(t *testing.T) {
}
func TestCheckForUpdatesGetEngineVersionsHappy(t *testing.T) {
getCurrentEngineVersionFunc := func(ctx context.Context) (containerizedengine.EngineInitOptions, error) {
return containerizedengine.EngineInitOptions{
getCurrentEngineVersionFunc := func(ctx context.Context) (clitypes.EngineInitOptions, error) {
return clitypes.EngineInitOptions{
EngineImage: "current engine",
EngineVersion: "1.1.0",
}, nil
}
getEngineVersionsFunc := func(ctx context.Context,
registryClient registryclient.RegistryClient,
currentVersion, imageName string) (containerizedengine.AvailableVersions, error) {
return containerizedengine.AvailableVersions{
currentVersion, imageName string) (clitypes.AvailableVersions, error) {
return clitypes.AvailableVersions{
Downgrades: parseVersions(t, "1.0.1", "1.0.2", "1.0.3-beta1"),
Patches: parseVersions(t, "1.1.1", "1.1.2", "1.1.3-beta1"),
Upgrades: parseVersions(t, "1.2.0", "2.0.0", "2.1.0-beta1"),
}, nil
}
testCli.SetContainerizedEngineClient(
func(string) (containerizedengine.Client, error) {
func(string) (clitypes.ContainerizedClient, error) {
return &fakeContainerizedEngineClient{
getEngineVersionsFunc: getEngineVersionsFunc,
getCurrentEngineVersionFunc: getCurrentEngineVersionFunc,
@ -128,14 +128,14 @@ func TestCheckForUpdatesGetEngineVersionsHappy(t *testing.T) {
golden.Assert(t, testCli.OutBuffer().String(), "check-patches-only.golden")
}
func makeVersion(t *testing.T, tag string) containerizedengine.DockerVersion {
func makeVersion(t *testing.T, tag string) clitypes.DockerVersion {
v, err := ver.NewVersion(tag)
assert.NilError(t, err)
return containerizedengine.DockerVersion{Version: *v, Tag: tag}
return clitypes.DockerVersion{Version: *v, Tag: tag}
}
func parseVersions(t *testing.T, tags ...string) []containerizedengine.DockerVersion {
ret := make([]containerizedengine.DockerVersion, len(tags))
func parseVersions(t *testing.T, tags ...string) []clitypes.DockerVersion {
ret := make([]clitypes.DockerVersion, len(tags))
for i, tag := range tags {
ret[i] = makeVersion(t, tag)
}

View File

@ -5,7 +5,7 @@ import (
"github.com/containerd/containerd"
registryclient "github.com/docker/cli/cli/registry/client"
"github.com/docker/cli/internal/containerizedengine"
clitypes "github.com/docker/cli/types"
"github.com/docker/docker/api/types"
)
@ -13,28 +13,28 @@ type (
fakeContainerizedEngineClient struct {
closeFunc func() error
activateEngineFunc func(ctx context.Context,
opts containerizedengine.EngineInitOptions,
out containerizedengine.OutStream,
opts clitypes.EngineInitOptions,
out clitypes.OutStream,
authConfig *types.AuthConfig,
healthfn func(context.Context) error) error
initEngineFunc func(ctx context.Context,
opts containerizedengine.EngineInitOptions,
out containerizedengine.OutStream,
opts clitypes.EngineInitOptions,
out clitypes.OutStream,
authConfig *types.AuthConfig,
healthfn func(context.Context) error) error
doUpdateFunc func(ctx context.Context,
opts containerizedengine.EngineInitOptions,
out containerizedengine.OutStream,
opts clitypes.EngineInitOptions,
out clitypes.OutStream,
authConfig *types.AuthConfig,
healthfn func(context.Context) error) error
getEngineVersionsFunc func(ctx context.Context,
registryClient registryclient.RegistryClient,
currentVersion,
imageName string) (containerizedengine.AvailableVersions, error)
imageName string) (clitypes.AvailableVersions, error)
getEngineFunc func(ctx context.Context) (containerd.Container, error)
removeEngineFunc func(ctx context.Context, engine containerd.Container) error
getCurrentEngineVersionFunc func(ctx context.Context) (containerizedengine.EngineInitOptions, error)
removeEngineFunc func(ctx context.Context) error
getCurrentEngineVersionFunc func(ctx context.Context) (clitypes.EngineInitOptions, error)
}
)
@ -46,8 +46,8 @@ func (w *fakeContainerizedEngineClient) Close() error {
}
func (w *fakeContainerizedEngineClient) ActivateEngine(ctx context.Context,
opts containerizedengine.EngineInitOptions,
out containerizedengine.OutStream,
opts clitypes.EngineInitOptions,
out clitypes.OutStream,
authConfig *types.AuthConfig,
healthfn func(context.Context) error) error {
if w.activateEngineFunc != nil {
@ -56,8 +56,8 @@ func (w *fakeContainerizedEngineClient) ActivateEngine(ctx context.Context,
return nil
}
func (w *fakeContainerizedEngineClient) InitEngine(ctx context.Context,
opts containerizedengine.EngineInitOptions,
out containerizedengine.OutStream,
opts clitypes.EngineInitOptions,
out clitypes.OutStream,
authConfig *types.AuthConfig,
healthfn func(context.Context) error) error {
if w.initEngineFunc != nil {
@ -66,8 +66,8 @@ func (w *fakeContainerizedEngineClient) InitEngine(ctx context.Context,
return nil
}
func (w *fakeContainerizedEngineClient) DoUpdate(ctx context.Context,
opts containerizedengine.EngineInitOptions,
out containerizedengine.OutStream,
opts clitypes.EngineInitOptions,
out clitypes.OutStream,
authConfig *types.AuthConfig,
healthfn func(context.Context) error) error {
if w.doUpdateFunc != nil {
@ -77,12 +77,12 @@ func (w *fakeContainerizedEngineClient) DoUpdate(ctx context.Context,
}
func (w *fakeContainerizedEngineClient) GetEngineVersions(ctx context.Context,
registryClient registryclient.RegistryClient,
currentVersion, imageName string) (containerizedengine.AvailableVersions, error) {
currentVersion, imageName string) (clitypes.AvailableVersions, error) {
if w.getEngineVersionsFunc != nil {
return w.getEngineVersionsFunc(ctx, registryClient, currentVersion, imageName)
}
return containerizedengine.AvailableVersions{}, nil
return clitypes.AvailableVersions{}, nil
}
func (w *fakeContainerizedEngineClient) GetEngine(ctx context.Context) (containerd.Container, error) {
@ -91,15 +91,15 @@ func (w *fakeContainerizedEngineClient) GetEngine(ctx context.Context) (containe
}
return nil, nil
}
func (w *fakeContainerizedEngineClient) RemoveEngine(ctx context.Context, engine containerd.Container) error {
func (w *fakeContainerizedEngineClient) RemoveEngine(ctx context.Context) error {
if w.removeEngineFunc != nil {
return w.removeEngineFunc(ctx, engine)
return w.removeEngineFunc(ctx)
}
return nil
}
func (w *fakeContainerizedEngineClient) GetCurrentEngineVersion(ctx context.Context) (containerizedengine.EngineInitOptions, error) {
func (w *fakeContainerizedEngineClient) GetCurrentEngineVersion(ctx context.Context) (clitypes.EngineInitOptions, error) {
if w.getCurrentEngineVersionFunc != nil {
return w.getCurrentEngineVersionFunc(ctx)
}
return containerizedengine.EngineInitOptions{}, nil
return clitypes.EngineInitOptions{}, nil
}

View File

@ -5,13 +5,13 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/internal/containerizedengine"
clitypes "github.com/docker/cli/types"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
type extendedEngineInitOptions struct {
containerizedengine.EngineInitOptions
clitypes.EngineInitOptions
sockPath string
}
@ -34,7 +34,7 @@ file on the host and may be pre-created before running the 'init' command.
}
flags := cmd.Flags()
flags.StringVar(&options.EngineVersion, "version", cli.Version, "Specify engine version")
flags.StringVar(&options.EngineImage, "engine-image", containerizedengine.CommunityEngineImage, "Specify engine image")
flags.StringVar(&options.EngineImage, "engine-image", clitypes.CommunityEngineImage, "Specify engine image")
flags.StringVar(&options.RegistryPrefix, "registry-prefix", "docker.io/docker", "Override the default location where engine images are pulled")
flags.StringVar(&options.ConfigFile, "config-file", "/etc/docker/daemon.json", "Specify the location of the daemon configuration file on the host")
flags.StringVar(&options.sockPath, "containerd", "", "override default location of containerd endpoint")

View File

@ -4,13 +4,13 @@ import (
"fmt"
"testing"
"github.com/docker/cli/internal/containerizedengine"
clitypes "github.com/docker/cli/types"
"gotest.tools/assert"
)
func TestInitNoContainerd(t *testing.T) {
testCli.SetContainerizedEngineClient(
func(string) (containerizedengine.Client, error) {
func(string) (clitypes.ContainerizedClient, error) {
return nil, fmt.Errorf("some error")
},
)
@ -23,7 +23,7 @@ func TestInitNoContainerd(t *testing.T) {
func TestInitHappy(t *testing.T) {
testCli.SetContainerizedEngineClient(
func(string) (containerizedengine.Client, error) {
func(string) (clitypes.ContainerizedClient, error) {
return &fakeContainerizedEngineClient{}, nil
},
)

View File

@ -45,10 +45,5 @@ func runRm(dockerCli command.Cli, options rmOptions) error {
}
defer client.Close()
engine, err := client.GetEngine(ctx)
if err != nil {
return err
}
return client.RemoveEngine(ctx, engine)
return client.RemoveEngine(ctx)
}

View File

@ -4,13 +4,13 @@ import (
"fmt"
"testing"
"github.com/docker/cli/internal/containerizedengine"
clitypes "github.com/docker/cli/types"
"gotest.tools/assert"
)
func TestRmNoContainerd(t *testing.T) {
testCli.SetContainerizedEngineClient(
func(string) (containerizedengine.Client, error) {
func(string) (clitypes.ContainerizedClient, error) {
return nil, fmt.Errorf("some error")
},
)
@ -23,7 +23,7 @@ func TestRmNoContainerd(t *testing.T) {
func TestRmHappy(t *testing.T) {
testCli.SetContainerizedEngineClient(
func(string) (containerizedengine.Client, error) {
func(string) (clitypes.ContainerizedClient, error) {
return &fakeContainerizedEngineClient{}, nil
},
)

View File

@ -4,13 +4,13 @@ import (
"fmt"
"testing"
"github.com/docker/cli/internal/containerizedengine"
clitypes "github.com/docker/cli/types"
"gotest.tools/assert"
)
func TestUpdateNoContainerd(t *testing.T) {
testCli.SetContainerizedEngineClient(
func(string) (containerizedengine.Client, error) {
func(string) (clitypes.ContainerizedClient, error) {
return nil, fmt.Errorf("some error")
},
)
@ -23,7 +23,7 @@ func TestUpdateNoContainerd(t *testing.T) {
func TestUpdateHappy(t *testing.T) {
testCli.SetContainerizedEngineClient(
func(string) (containerizedengine.Client, error) {
func(string) (clitypes.ContainerizedClient, error) {
return &fakeContainerizedEngineClient{}, nil
},
)

View File

@ -1,7 +1,7 @@
package formatter
import (
"github.com/docker/cli/internal/containerizedengine"
clitypes "github.com/docker/cli/types"
)
const (
@ -31,7 +31,7 @@ func NewUpdatesFormat(source string, quiet bool) Format {
}
// UpdatesWrite writes the context
func UpdatesWrite(ctx Context, availableUpdates []containerizedengine.Update) error {
func UpdatesWrite(ctx Context, availableUpdates []clitypes.Update) error {
render := func(format func(subContext subContext) error) error {
for _, update := range availableUpdates {
updatesCtx := &updateContext{trunc: ctx.Trunc, u: update}
@ -53,7 +53,7 @@ func UpdatesWrite(ctx Context, availableUpdates []containerizedengine.Update) er
type updateContext struct {
HeaderContext
trunc bool
u containerizedengine.Update
u clitypes.Update
}
func (c *updateContext) MarshalJSON() ([]byte, error) {

View File

@ -6,7 +6,7 @@ import (
"strings"
"testing"
"github.com/docker/cli/internal/containerizedengine"
clitypes "github.com/docker/cli/types"
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
)
@ -84,7 +84,7 @@ version2
}
for _, testcase := range cases {
updates := []containerizedengine.Update{
updates := []clitypes.Update{
{Type: "updateType1", Version: "version1", Notes: "description 1"},
{Type: "updateType2", Version: "version2", Notes: "description 2"},
}
@ -100,7 +100,7 @@ version2
}
func TestUpdateContextWriteJSON(t *testing.T) {
updates := []containerizedengine.Update{
updates := []clitypes.Update{
{Type: "updateType1", Version: "version1", Notes: "note1"},
{Type: "updateType2", Version: "version2", Notes: "note2"},
}
@ -124,7 +124,7 @@ func TestUpdateContextWriteJSON(t *testing.T) {
}
func TestUpdateContextWriteJSONField(t *testing.T) {
updates := []containerizedengine.Update{
updates := []clitypes.Update{
{Type: "updateType1", Version: "version1"},
{Type: "updateType2", Version: "version2"},
}

View File

@ -13,6 +13,7 @@ import (
cliconfig "github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/debug"
cliflags "github.com/docker/cli/cli/flags"
"github.com/docker/cli/internal/containerizedengine"
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/term"
@ -168,7 +169,7 @@ func main() {
stdin, stdout, stderr := term.StdStreams()
logrus.SetOutput(stderr)
dockerCli := command.NewDockerCli(stdin, stdout, stderr, contentTrustEnabled())
dockerCli := command.NewDockerCli(stdin, stdout, stderr, contentTrustEnabled(), containerizedengine.NewClient)
cmd := newDockerCommand(dockerCli)
if err := cmd.Execute(); err != nil {

View File

@ -26,7 +26,7 @@ func TestClientDebugEnabled(t *testing.T) {
func TestExitStatusForInvalidSubcommandWithHelpFlag(t *testing.T) {
discard := ioutil.Discard
cmd := newDockerCommand(command.NewDockerCli(os.Stdin, discard, discard, false))
cmd := newDockerCommand(command.NewDockerCli(os.Stdin, discard, discard, false, nil))
cmd.SetArgs([]string{"help", "invalid"})
err := cmd.Execute()
assert.Error(t, err, "unknown help topic: invalid")

View File

@ -19,7 +19,7 @@ const descriptionSourcePath = "docs/reference/commandline/"
func generateCliYaml(opts *options) error {
stdin, stdout, stderr := term.StdStreams()
dockerCli := command.NewDockerCli(stdin, stdout, stderr, false)
dockerCli := command.NewDockerCli(stdin, stdout, stderr, false, nil)
cmd := &cobra.Command{Use: "docker"}
commands.AddCommands(cmd, dockerCli)
source := filepath.Join(opts.source, descriptionSourcePath)

View File

@ -5,9 +5,16 @@ import (
"strings"
"testing"
"github.com/containerd/containerd"
"github.com/docker/cli/internal/containerizedengine"
"github.com/docker/cli/types"
)
type containerizedclient interface {
types.ContainerizedClient
GetEngine(context.Context) (containerd.Container, error)
}
// CleanupEngine ensures the local engine has been removed between testcases
func CleanupEngine(t *testing.T) error {
t.Log("doing engine cleanup")
@ -19,7 +26,7 @@ func CleanupEngine(t *testing.T) error {
}
// See if the engine exists first
engine, err := client.GetEngine(ctx)
_, err = client.(containerizedclient).GetEngine(ctx)
if err != nil {
if strings.Contains(err.Error(), "not present") {
t.Log("engine was not detected, no cleanup to perform")
@ -31,7 +38,7 @@ func CleanupEngine(t *testing.T) error {
return err
}
// TODO Consider nuking the docker dir too so there's no cached content between test cases
err = client.RemoveEngine(ctx, engine)
err = client.RemoveEngine(ctx)
if err != nil {
t.Logf("Failed to remove engine: %s", err)
}

View File

@ -1,7 +1,6 @@
package containerizedengine
import (
"bytes"
"context"
"syscall"
@ -69,10 +68,6 @@ type (
loadProcessFunc func(context.Context, string, cio.Attach) (containerd.Process, error)
metricsFunc func(context.Context) (*containerdtypes.Metric, error)
}
testOutStream struct {
bytes.Buffer
}
)
func (w *fakeContainerdClient) Containers(ctx context.Context, filters ...string) ([]containerd.Container, error) {
@ -339,10 +334,3 @@ func (t *fakeTask) Metrics(ctx context.Context) (*containerdtypes.Metric, error)
}
return nil, nil
}
func (o *testOutStream) FD() uintptr {
return 0
}
func (o *testOutStream) IsTerminal() bool {
return false
}

View File

@ -7,6 +7,7 @@ import (
"github.com/containerd/containerd"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/remotes/docker"
clitypes "github.com/docker/cli/types"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/jsonmessage"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@ -15,7 +16,7 @@ import (
// NewClient returns a new containerizedengine client
// This client can be used to manage the lifecycle of
// dockerd running as a container on containerd.
func NewClient(sockPath string) (Client, error) {
func NewClient(sockPath string) (clitypes.ContainerizedClient, error) {
if sockPath == "" {
sockPath = containerdSockPath
}
@ -23,17 +24,17 @@ func NewClient(sockPath string) (Client, error) {
if err != nil {
return nil, err
}
return baseClient{
return &baseClient{
cclient: cclient,
}, nil
}
// Close will close the underlying clients
func (c baseClient) Close() error {
func (c *baseClient) Close() error {
return c.cclient.Close()
}
func (c baseClient) pullWithAuth(ctx context.Context, imageName string, out OutStream,
func (c *baseClient) pullWithAuth(ctx context.Context, imageName string, out clitypes.OutStream,
authConfig *types.AuthConfig) (containerd.Image, error) {
resolver := docker.NewResolver(docker.ResolverOptions{

View File

@ -1,11 +1,13 @@
package containerizedengine
import (
"bytes"
"context"
"fmt"
"testing"
"github.com/containerd/containerd"
"github.com/docker/cli/cli/command"
"github.com/docker/docker/api/types"
"gotest.tools/assert"
)
@ -22,7 +24,7 @@ func TestPullWithAuthPullFail(t *testing.T) {
}
imageName := "testnamegoeshere"
_, err := client.pullWithAuth(ctx, imageName, &testOutStream{}, &types.AuthConfig{})
_, err := client.pullWithAuth(ctx, imageName, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{})
assert.ErrorContains(t, err, "pull failure")
}
@ -38,6 +40,6 @@ func TestPullWithAuthPullPass(t *testing.T) {
}
imageName := "testnamegoeshere"
_, err := client.pullWithAuth(ctx, imageName, &testOutStream{}, &types.AuthConfig{})
_, err := client.pullWithAuth(ctx, imageName, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{})
assert.NilError(t, err)
}

View File

@ -12,12 +12,15 @@ import (
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/runtime/restart"
"github.com/docker/cli/internal/pkg/containerized"
clitypes "github.com/docker/cli/types"
"github.com/docker/docker/api/types"
"github.com/pkg/errors"
)
var _ clitypes.ContainerizedClient = &baseClient{}
// InitEngine is the main entrypoint for `docker engine init`
func (c baseClient) InitEngine(ctx context.Context, opts EngineInitOptions, out OutStream,
func (c *baseClient) InitEngine(ctx context.Context, opts clitypes.EngineInitOptions, out clitypes.OutStream,
authConfig *types.AuthConfig, healthfn func(context.Context) error) error {
ctx = namespaces.WithNamespace(ctx, engineNamespace)
@ -66,7 +69,7 @@ func (c baseClient) InitEngine(ctx context.Context, opts EngineInitOptions, out
}
// GetEngine will return the containerd container running the engine (or error)
func (c baseClient) GetEngine(ctx context.Context) (containerd.Container, error) {
func (c *baseClient) GetEngine(ctx context.Context) (containerd.Container, error) {
ctx = namespaces.WithNamespace(ctx, engineNamespace)
containers, err := c.cclient.Containers(ctx, "id=="+engineContainerName)
if err != nil {
@ -79,7 +82,7 @@ func (c baseClient) GetEngine(ctx context.Context) (containerd.Container, error)
}
// getEngineImage will return the current image used by the engine
func (c baseClient) getEngineImage(engine containerd.Container) (string, error) {
func (c *baseClient) getEngineImage(engine containerd.Container) (string, error) {
ctx := namespaces.WithNamespace(context.Background(), engineNamespace)
image, err := engine.Image(ctx)
if err != nil {
@ -94,7 +97,7 @@ var (
)
// waitForEngine will wait for the engine to start
func (c baseClient) waitForEngine(ctx context.Context, out io.Writer, healthfn func(context.Context) error) error {
func (c *baseClient) waitForEngine(ctx context.Context, out io.Writer, healthfn func(context.Context) error) error {
ticker := time.NewTicker(engineWaitInterval)
defer ticker.Stop()
defer func() {
@ -120,7 +123,7 @@ func (c baseClient) waitForEngine(ctx context.Context, out io.Writer, healthfn f
}
}
func (c baseClient) waitForEngineContainer(ctx context.Context, ticker *time.Ticker) error {
func (c *baseClient) waitForEngineContainer(ctx context.Context, ticker *time.Ticker) error {
var ret error
for {
select {
@ -137,7 +140,15 @@ func (c baseClient) waitForEngineContainer(ctx context.Context, ticker *time.Tic
}
// RemoveEngine gracefully unwinds the current engine
func (c baseClient) RemoveEngine(ctx context.Context, engine containerd.Container) error {
func (c *baseClient) RemoveEngine(ctx context.Context) error {
engine, err := c.GetEngine(ctx)
if err != nil {
return err
}
return c.removeEngine(ctx, engine)
}
func (c *baseClient) removeEngine(ctx context.Context, engine containerd.Container) error {
ctx = namespaces.WithNamespace(ctx, engineNamespace)
// Make sure the container isn't being restarted while we unwind it
@ -190,7 +201,7 @@ func (c baseClient) RemoveEngine(ctx context.Context, engine containerd.Containe
}
// startEngineOnContainerd creates a new docker engine running on containerd
func (c baseClient) startEngineOnContainerd(ctx context.Context, imageName, configFile string) error {
func (c *baseClient) startEngineOnContainerd(ctx context.Context, imageName, configFile string) error {
ctx = namespaces.WithNamespace(ctx, engineNamespace)
image, err := c.cclient.GetImage(ctx, imageName)
if err != nil {

View File

@ -1,6 +1,7 @@
package containerizedengine
import (
"bytes"
"context"
"fmt"
"strings"
@ -12,6 +13,8 @@ import (
"github.com/containerd/containerd/cio"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/oci"
"github.com/docker/cli/cli/command"
clitypes "github.com/docker/cli/types"
"github.com/docker/docker/api/types"
"github.com/opencontainers/runtime-spec/specs-go"
"gotest.tools/assert"
@ -26,11 +29,11 @@ func healthfnError(ctx context.Context) error {
func TestInitGetEngineFail(t *testing.T) {
ctx := context.Background()
opts := EngineInitOptions{
opts := clitypes.EngineInitOptions{
EngineVersion: "engineversiongoeshere",
RegistryPrefix: "registryprefixgoeshere",
ConfigFile: "/tmp/configfilegoeshere",
EngineImage: CommunityEngineImage,
EngineImage: clitypes.CommunityEngineImage,
}
container := &fakeContainer{}
client := baseClient{
@ -41,17 +44,17 @@ func TestInitGetEngineFail(t *testing.T) {
},
}
err := client.InitEngine(ctx, opts, &testOutStream{}, &types.AuthConfig{}, healthfnHappy)
err := client.InitEngine(ctx, opts, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{}, healthfnHappy)
assert.Assert(t, err == ErrEngineAlreadyPresent)
}
func TestInitCheckImageFail(t *testing.T) {
ctx := context.Background()
opts := EngineInitOptions{
opts := clitypes.EngineInitOptions{
EngineVersion: "engineversiongoeshere",
RegistryPrefix: "registryprefixgoeshere",
ConfigFile: "/tmp/configfilegoeshere",
EngineImage: CommunityEngineImage,
EngineImage: clitypes.CommunityEngineImage,
}
client := baseClient{
cclient: &fakeContainerdClient{
@ -65,18 +68,18 @@ func TestInitCheckImageFail(t *testing.T) {
},
}
err := client.InitEngine(ctx, opts, &testOutStream{}, &types.AuthConfig{}, healthfnHappy)
err := client.InitEngine(ctx, opts, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{}, healthfnHappy)
assert.ErrorContains(t, err, "unable to check for image")
assert.ErrorContains(t, err, "something went wrong")
}
func TestInitPullFail(t *testing.T) {
ctx := context.Background()
opts := EngineInitOptions{
opts := clitypes.EngineInitOptions{
EngineVersion: "engineversiongoeshere",
RegistryPrefix: "registryprefixgoeshere",
ConfigFile: "/tmp/configfilegoeshere",
EngineImage: CommunityEngineImage,
EngineImage: clitypes.CommunityEngineImage,
}
client := baseClient{
cclient: &fakeContainerdClient{
@ -93,18 +96,18 @@ func TestInitPullFail(t *testing.T) {
},
}
err := client.InitEngine(ctx, opts, &testOutStream{}, &types.AuthConfig{}, healthfnHappy)
err := client.InitEngine(ctx, opts, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{}, healthfnHappy)
assert.ErrorContains(t, err, "unable to pull image")
assert.ErrorContains(t, err, "pull failure")
}
func TestInitStartFail(t *testing.T) {
ctx := context.Background()
opts := EngineInitOptions{
opts := clitypes.EngineInitOptions{
EngineVersion: "engineversiongoeshere",
RegistryPrefix: "registryprefixgoeshere",
ConfigFile: "/tmp/configfilegoeshere",
EngineImage: CommunityEngineImage,
EngineImage: clitypes.CommunityEngineImage,
}
client := baseClient{
cclient: &fakeContainerdClient{
@ -121,7 +124,7 @@ func TestInitStartFail(t *testing.T) {
},
}
err := client.InitEngine(ctx, opts, &testOutStream{}, &types.AuthConfig{}, healthfnHappy)
err := client.InitEngine(ctx, opts, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{}, healthfnHappy)
assert.ErrorContains(t, err, "failed to create docker daemon")
}
@ -211,7 +214,7 @@ func TestWaitForEngineNeverShowsUp(t *testing.T) {
},
}
err := client.waitForEngine(ctx, &testOutStream{}, healthfnError)
err := client.waitForEngine(ctx, command.NewOutStream(&bytes.Buffer{}), healthfnError)
assert.ErrorContains(t, err, "timeout waiting")
}
@ -228,7 +231,7 @@ func TestWaitForEnginePingFail(t *testing.T) {
},
}
err := client.waitForEngine(ctx, &testOutStream{}, healthfnError)
err := client.waitForEngine(ctx, command.NewOutStream(&bytes.Buffer{}), healthfnError)
assert.ErrorContains(t, err, "ping fail")
}
@ -245,7 +248,7 @@ func TestWaitForEngineHealthy(t *testing.T) {
},
}
err := client.waitForEngine(ctx, &testOutStream{}, healthfnHappy)
err := client.waitForEngine(ctx, command.NewOutStream(&bytes.Buffer{}), healthfnHappy)
assert.NilError(t, err)
}
@ -261,7 +264,7 @@ func TestRemoveEngineBadTaskBadDelete(t *testing.T) {
},
}
err := client.RemoveEngine(ctx, container)
err := client.removeEngine(ctx, container)
assert.ErrorContains(t, err, "failed to remove existing engine")
assert.ErrorContains(t, err, "delete failure")
}
@ -280,7 +283,7 @@ func TestRemoveEngineTaskNoStatus(t *testing.T) {
},
}
err := client.RemoveEngine(ctx, container)
err := client.removeEngine(ctx, container)
assert.ErrorContains(t, err, "task status failure")
}
@ -301,7 +304,7 @@ func TestRemoveEngineTaskNotRunningDeleteFail(t *testing.T) {
},
}
err := client.RemoveEngine(ctx, container)
err := client.removeEngine(ctx, container)
assert.ErrorContains(t, err, "task delete failure")
}
@ -322,7 +325,7 @@ func TestRemoveEngineTaskRunningKillFail(t *testing.T) {
},
}
err := client.RemoveEngine(ctx, container)
err := client.removeEngine(ctx, container)
assert.ErrorContains(t, err, "task kill failure")
}
@ -343,7 +346,7 @@ func TestRemoveEngineTaskRunningWaitFail(t *testing.T) {
},
}
err := client.RemoveEngine(ctx, container)
err := client.removeEngine(ctx, container)
assert.ErrorContains(t, err, "task wait failure")
}
@ -366,7 +369,7 @@ func TestRemoveEngineTaskRunningHappyPath(t *testing.T) {
},
}
err := client.RemoveEngine(ctx, container)
err := client.removeEngine(ctx, container)
assert.NilError(t, err)
}
@ -390,7 +393,7 @@ func TestRemoveEngineTaskKillTimeout(t *testing.T) {
},
}
err := client.RemoveEngine(ctx, container)
err := client.removeEngine(ctx, container)
assert.Assert(t, err == ErrEngineShutdownTimeout)
}

View File

@ -3,24 +3,14 @@ package containerizedengine
import (
"context"
"errors"
"io"
"github.com/containerd/containerd"
"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/content"
registryclient "github.com/docker/cli/cli/registry/client"
"github.com/docker/docker/api/types"
ver "github.com/hashicorp/go-version"
specs "github.com/opencontainers/runtime-spec/specs-go"
)
const (
// CommunityEngineImage is the repo name for the community engine
CommunityEngineImage = "engine-community"
// EnterpriseEngineImage is the repo name for the enterprise engine
EnterpriseEngineImage = "engine-enterprise"
containerdSockPath = "/run/containerd/containerd.sock"
engineContainerName = "dockerd"
engineNamespace = "docker"
@ -79,45 +69,10 @@ var (
}
)
// Client can be used to manage the lifecycle of
// dockerd running as a container on containerd.
type Client interface {
Close() error
ActivateEngine(ctx context.Context,
opts EngineInitOptions,
out OutStream,
authConfig *types.AuthConfig,
healthfn func(context.Context) error) error
InitEngine(ctx context.Context,
opts EngineInitOptions,
out OutStream,
authConfig *types.AuthConfig,
healthfn func(context.Context) error) error
DoUpdate(ctx context.Context,
opts EngineInitOptions,
out OutStream,
authConfig *types.AuthConfig,
healthfn func(context.Context) error) error
GetEngineVersions(ctx context.Context, registryClient registryclient.RegistryClient, currentVersion, imageName string) (AvailableVersions, error)
GetEngine(ctx context.Context) (containerd.Container, error)
RemoveEngine(ctx context.Context, engine containerd.Container) error
GetCurrentEngineVersion(ctx context.Context) (EngineInitOptions, error)
}
type baseClient struct {
cclient containerdClient
}
// EngineInitOptions contains the configuration settings
// use during initialization of a containerized docker engine
type EngineInitOptions struct {
RegistryPrefix string
EngineImage string
EngineVersion string
ConfigFile string
scope string
}
// containerdClient abstracts the containerd client to aid in testability
type containerdClient interface {
Containers(ctx context.Context, filters ...string) ([]containerd.Container, error)
@ -128,32 +83,3 @@ type containerdClient interface {
ContentStore() content.Store
ContainerService() containers.Store
}
// AvailableVersions groups the available versions which were discovered
type AvailableVersions struct {
Downgrades []DockerVersion
Patches []DockerVersion
Upgrades []DockerVersion
}
// DockerVersion wraps a semantic version to retain the original tag
// since the docker date based versions don't strictly follow semantic
// versioning (leading zeros, etc.)
type DockerVersion struct {
ver.Version
Tag string
}
// Update stores available updates for rendering in a table
type Update struct {
Type string
Version string
Notes string
}
// OutStream is an output stream used to write normal program output.
type OutStream interface {
io.Writer
FD() uintptr
IsTerminal() bool
}

View File

@ -9,16 +9,17 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/namespaces"
"github.com/docker/cli/internal/pkg/containerized"
clitypes "github.com/docker/cli/types"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/pkg/errors"
)
// GetCurrentEngineVersion determines the current type of engine (image) and version
func (c baseClient) GetCurrentEngineVersion(ctx context.Context) (EngineInitOptions, error) {
func (c *baseClient) GetCurrentEngineVersion(ctx context.Context) (clitypes.EngineInitOptions, error) {
ctx = namespaces.WithNamespace(ctx, engineNamespace)
ret := EngineInitOptions{}
currentEngine := CommunityEngineImage
ret := clitypes.EngineInitOptions{}
currentEngine := clitypes.CommunityEngineImage
engine, err := c.GetEngine(ctx)
if err != nil {
if err == ErrEngineNotPresent {
@ -35,8 +36,8 @@ func (c baseClient) GetCurrentEngineVersion(ctx context.Context) (EngineInitOpti
return ret, errors.Wrapf(err, "failed to parse image name: %s", imageName)
}
if strings.Contains(distributionRef.Name(), EnterpriseEngineImage) {
currentEngine = EnterpriseEngineImage
if strings.Contains(distributionRef.Name(), clitypes.EnterpriseEngineImage) {
currentEngine = clitypes.EnterpriseEngineImage
}
taggedRef, ok := distributionRef.(reference.NamedTagged)
if !ok {
@ -49,11 +50,11 @@ func (c baseClient) GetCurrentEngineVersion(ctx context.Context) (EngineInitOpti
}
// ActivateEngine will switch the image from the CE to EE image
func (c baseClient) ActivateEngine(ctx context.Context, opts EngineInitOptions, out OutStream,
func (c *baseClient) ActivateEngine(ctx context.Context, opts clitypes.EngineInitOptions, out clitypes.OutStream,
authConfig *types.AuthConfig, healthfn func(context.Context) error) error {
// set the proxy scope to "ee" for activate flows
opts.scope = "ee"
opts.Scope = "ee"
ctx = namespaces.WithNamespace(ctx, engineNamespace)
@ -64,7 +65,7 @@ func (c baseClient) ActivateEngine(ctx context.Context, opts EngineInitOptions,
return err
}
opts.EngineVersion = currentOpts.EngineVersion
if currentOpts.EngineImage == EnterpriseEngineImage {
if currentOpts.EngineImage == clitypes.EnterpriseEngineImage {
// This is a "no-op" activation so the only change would be the license - don't update the engine itself
return nil
}
@ -73,7 +74,7 @@ func (c baseClient) ActivateEngine(ctx context.Context, opts EngineInitOptions,
}
// DoUpdate performs the underlying engine update
func (c baseClient) DoUpdate(ctx context.Context, opts EngineInitOptions, out OutStream,
func (c *baseClient) DoUpdate(ctx context.Context, opts clitypes.EngineInitOptions, out clitypes.OutStream,
authConfig *types.AuthConfig, healthfn func(context.Context) error) error {
ctx = namespaces.WithNamespace(ctx, engineNamespace)
@ -117,13 +118,13 @@ func (c baseClient) DoUpdate(ctx context.Context, opts EngineInitOptions, out Ou
defer cancel()
return c.waitForEngine(ctx, out, healthfn)
})
if err == nil && opts.scope != "" {
if err == nil && opts.Scope != "" {
var labels map[string]string
labels, err = engine.Labels(ctx)
if err != nil {
return err
}
labels[proxyLabel] = opts.scope
labels[proxyLabel] = opts.Scope
_, err = engine.SetLabels(ctx, labels)
}
return err

View File

@ -1,6 +1,7 @@
package containerizedengine
import (
"bytes"
"context"
"fmt"
"testing"
@ -8,6 +9,8 @@ import (
"github.com/containerd/containerd"
"github.com/containerd/containerd/cio"
"github.com/containerd/containerd/errdefs"
"github.com/docker/cli/cli/command"
clitypes "github.com/docker/cli/types"
"github.com/docker/docker/api/types"
"gotest.tools/assert"
)
@ -16,7 +19,7 @@ func TestGetCurrentEngineVersionHappy(t *testing.T) {
ctx := context.Background()
image := &fakeImage{
nameFunc: func() string {
return "acme.com/dockermirror/" + CommunityEngineImage + ":engineversion"
return "acme.com/dockermirror/" + clitypes.CommunityEngineImage + ":engineversion"
},
}
container := &fakeContainer{
@ -34,7 +37,7 @@ func TestGetCurrentEngineVersionHappy(t *testing.T) {
opts, err := client.GetCurrentEngineVersion(ctx)
assert.NilError(t, err)
assert.Equal(t, opts.EngineImage, CommunityEngineImage)
assert.Equal(t, opts.EngineImage, clitypes.CommunityEngineImage)
assert.Equal(t, opts.RegistryPrefix, "acme.com/dockermirror")
assert.Equal(t, opts.EngineVersion, "engineversion")
}
@ -43,7 +46,7 @@ func TestGetCurrentEngineVersionEnterpriseHappy(t *testing.T) {
ctx := context.Background()
image := &fakeImage{
nameFunc: func() string {
return "docker.io/docker/" + EnterpriseEngineImage + ":engineversion"
return "docker.io/docker/" + clitypes.EnterpriseEngineImage + ":engineversion"
},
}
container := &fakeContainer{
@ -61,7 +64,7 @@ func TestGetCurrentEngineVersionEnterpriseHappy(t *testing.T) {
opts, err := client.GetCurrentEngineVersion(ctx)
assert.NilError(t, err)
assert.Equal(t, opts.EngineImage, EnterpriseEngineImage)
assert.Equal(t, opts.EngineImage, clitypes.EnterpriseEngineImage)
assert.Equal(t, opts.EngineVersion, "engineversion")
assert.Equal(t, opts.RegistryPrefix, "docker.io/docker")
}
@ -147,14 +150,14 @@ func TestActivateNoEngine(t *testing.T) {
},
},
}
opts := EngineInitOptions{
opts := clitypes.EngineInitOptions{
EngineVersion: "engineversiongoeshere",
RegistryPrefix: "registryprefixgoeshere",
ConfigFile: "/tmp/configfilegoeshere",
EngineImage: EnterpriseEngineImage,
EngineImage: clitypes.EnterpriseEngineImage,
}
err := client.ActivateEngine(ctx, opts, &testOutStream{}, &types.AuthConfig{}, healthfnHappy)
err := client.ActivateEngine(ctx, opts, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{}, healthfnHappy)
assert.ErrorContains(t, err, "unable to find")
}
@ -163,7 +166,7 @@ func TestActivateNoChange(t *testing.T) {
registryPrefix := "registryprefixgoeshere"
image := &fakeImage{
nameFunc: func() string {
return registryPrefix + "/" + EnterpriseEngineImage + ":engineversion"
return registryPrefix + "/" + clitypes.EnterpriseEngineImage + ":engineversion"
},
}
container := &fakeContainer{
@ -184,14 +187,14 @@ func TestActivateNoChange(t *testing.T) {
},
},
}
opts := EngineInitOptions{
opts := clitypes.EngineInitOptions{
EngineVersion: "engineversiongoeshere",
RegistryPrefix: "registryprefixgoeshere",
ConfigFile: "/tmp/configfilegoeshere",
EngineImage: EnterpriseEngineImage,
EngineImage: clitypes.EnterpriseEngineImage,
}
err := client.ActivateEngine(ctx, opts, &testOutStream{}, &types.AuthConfig{}, healthfnHappy)
err := client.ActivateEngine(ctx, opts, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{}, healthfnHappy)
assert.NilError(t, err)
}
@ -219,34 +222,34 @@ func TestActivateDoUpdateFail(t *testing.T) {
},
},
}
opts := EngineInitOptions{
opts := clitypes.EngineInitOptions{
EngineVersion: "engineversiongoeshere",
RegistryPrefix: "registryprefixgoeshere",
ConfigFile: "/tmp/configfilegoeshere",
EngineImage: EnterpriseEngineImage,
EngineImage: clitypes.EnterpriseEngineImage,
}
err := client.ActivateEngine(ctx, opts, &testOutStream{}, &types.AuthConfig{}, healthfnHappy)
err := client.ActivateEngine(ctx, opts, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{}, healthfnHappy)
assert.ErrorContains(t, err, "check for image")
assert.ErrorContains(t, err, "something went wrong")
}
func TestDoUpdateNoVersion(t *testing.T) {
ctx := context.Background()
opts := EngineInitOptions{
opts := clitypes.EngineInitOptions{
EngineVersion: "",
RegistryPrefix: "registryprefixgoeshere",
ConfigFile: "/tmp/configfilegoeshere",
EngineImage: EnterpriseEngineImage,
EngineImage: clitypes.EnterpriseEngineImage,
}
client := baseClient{}
err := client.DoUpdate(ctx, opts, &testOutStream{}, &types.AuthConfig{}, healthfnHappy)
err := client.DoUpdate(ctx, opts, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{}, healthfnHappy)
assert.ErrorContains(t, err, "please pick the version you")
}
func TestDoUpdateImageMiscError(t *testing.T) {
ctx := context.Background()
opts := EngineInitOptions{
opts := clitypes.EngineInitOptions{
EngineVersion: "engineversiongoeshere",
RegistryPrefix: "registryprefixgoeshere",
ConfigFile: "/tmp/configfilegoeshere",
@ -260,14 +263,14 @@ func TestDoUpdateImageMiscError(t *testing.T) {
},
},
}
err := client.DoUpdate(ctx, opts, &testOutStream{}, &types.AuthConfig{}, healthfnHappy)
err := client.DoUpdate(ctx, opts, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{}, healthfnHappy)
assert.ErrorContains(t, err, "check for image")
assert.ErrorContains(t, err, "something went wrong")
}
func TestDoUpdatePullFail(t *testing.T) {
ctx := context.Background()
opts := EngineInitOptions{
opts := clitypes.EngineInitOptions{
EngineVersion: "engineversiongoeshere",
RegistryPrefix: "registryprefixgoeshere",
ConfigFile: "/tmp/configfilegoeshere",
@ -284,14 +287,14 @@ func TestDoUpdatePullFail(t *testing.T) {
},
},
}
err := client.DoUpdate(ctx, opts, &testOutStream{}, &types.AuthConfig{}, healthfnHappy)
err := client.DoUpdate(ctx, opts, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{}, healthfnHappy)
assert.ErrorContains(t, err, "unable to pull")
assert.ErrorContains(t, err, "pull failure")
}
func TestDoUpdateEngineMissing(t *testing.T) {
ctx := context.Background()
opts := EngineInitOptions{
opts := clitypes.EngineInitOptions{
EngineVersion: "engineversiongoeshere",
RegistryPrefix: "registryprefixgoeshere",
ConfigFile: "/tmp/configfilegoeshere",
@ -313,6 +316,6 @@ func TestDoUpdateEngineMissing(t *testing.T) {
},
},
}
err := client.DoUpdate(ctx, opts, &testOutStream{}, &types.AuthConfig{}, healthfnHappy)
err := client.DoUpdate(ctx, opts, command.NewOutStream(&bytes.Buffer{}), &types.AuthConfig{}, healthfnHappy)
assert.ErrorContains(t, err, "unable to find existing engine")
}

View File

@ -5,6 +5,7 @@ import (
"sort"
registryclient "github.com/docker/cli/cli/registry/client"
clitypes "github.com/docker/cli/types"
"github.com/docker/distribution/reference"
ver "github.com/hashicorp/go-version"
"github.com/pkg/errors"
@ -12,29 +13,29 @@ import (
)
// GetEngineVersions reports the versions of the engine that are available
func (c baseClient) GetEngineVersions(ctx context.Context, registryClient registryclient.RegistryClient, currentVersion, imageName string) (AvailableVersions, error) {
func (c *baseClient) GetEngineVersions(ctx context.Context, registryClient registryclient.RegistryClient, currentVersion, imageName string) (clitypes.AvailableVersions, error) {
imageRef, err := reference.ParseNormalizedNamed(imageName)
if err != nil {
return AvailableVersions{}, err
return clitypes.AvailableVersions{}, err
}
tags, err := registryClient.GetTags(ctx, imageRef)
if err != nil {
return AvailableVersions{}, err
return clitypes.AvailableVersions{}, err
}
return parseTags(tags, currentVersion)
}
func parseTags(tags []string, currentVersion string) (AvailableVersions, error) {
var ret AvailableVersions
func parseTags(tags []string, currentVersion string) (clitypes.AvailableVersions, error) {
var ret clitypes.AvailableVersions
currentVer, err := ver.NewVersion(currentVersion)
if err != nil {
return ret, errors.Wrapf(err, "failed to parse existing version %s", currentVersion)
}
downgrades := []DockerVersion{}
patches := []DockerVersion{}
upgrades := []DockerVersion{}
downgrades := []clitypes.DockerVersion{}
patches := []clitypes.DockerVersion{}
upgrades := []clitypes.DockerVersion{}
currentSegments := currentVer.Segments()
for _, tag := range tags {
tmp, err := ver.NewVersion(tag)
@ -42,7 +43,7 @@ func parseTags(tags []string, currentVersion string) (AvailableVersions, error)
logrus.Debugf("Unable to parse %s: %s", tag, err)
continue
}
testVersion := DockerVersion{Version: *tmp, Tag: tag}
testVersion := clitypes.DockerVersion{Version: *tmp, Tag: tag}
if testVersion.LessThan(currentVer) {
downgrades = append(downgrades, testVersion)
continue

View File

@ -12,7 +12,7 @@ import (
manifeststore "github.com/docker/cli/cli/manifest/store"
registryclient "github.com/docker/cli/cli/registry/client"
"github.com/docker/cli/cli/trust"
"github.com/docker/cli/internal/containerizedengine"
clitypes "github.com/docker/cli/types"
"github.com/docker/docker/client"
notaryclient "github.com/theupdateframework/notary/client"
)
@ -20,7 +20,7 @@ import (
// NotaryClientFuncType defines a function that returns a fake notary client
type NotaryClientFuncType func(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error)
type clientInfoFuncType func() command.ClientInfo
type containerizedEngineFuncType func(string) (containerizedengine.Client, error)
type containerizedEngineFuncType func(string) (clitypes.ContainerizedClient, error)
// FakeCli emulates the default DockerCli
type FakeCli struct {
@ -172,7 +172,7 @@ func EnableContentTrust(c *FakeCli) {
}
// NewContainerizedEngineClient returns a containerized engine client
func (c *FakeCli) NewContainerizedEngineClient(sockPath string) (containerizedengine.Client, error) {
func (c *FakeCli) NewContainerizedEngineClient(sockPath string) (clitypes.ContainerizedClient, error) {
if c.containerizedEngineClientFunc != nil {
return c.containerizedEngineClientFunc(sockPath)
}

View File

@ -25,7 +25,7 @@ func generateManPages(opts *options) error {
}
stdin, stdout, stderr := term.StdStreams()
dockerCli := command.NewDockerCli(stdin, stdout, stderr, false)
dockerCli := command.NewDockerCli(stdin, stdout, stderr, false, nil)
cmd := &cobra.Command{Use: "docker"}
commands.AddCommands(cmd, dockerCli)
source := filepath.Join(opts.source, descriptionSourcePath)

81
types/types.go Normal file
View File

@ -0,0 +1,81 @@
package types
import (
"context"
"io"
registryclient "github.com/docker/cli/cli/registry/client"
"github.com/docker/docker/api/types"
ver "github.com/hashicorp/go-version"
)
const (
// CommunityEngineImage is the repo name for the community engine
CommunityEngineImage = "engine-community"
// EnterpriseEngineImage is the repo name for the enterprise engine
EnterpriseEngineImage = "engine-enterprise"
)
// ContainerizedClient can be used to manage the lifecycle of
// dockerd running as a container on containerd.
type ContainerizedClient interface {
Close() error
ActivateEngine(ctx context.Context,
opts EngineInitOptions,
out OutStream,
authConfig *types.AuthConfig,
healthfn func(context.Context) error) error
InitEngine(ctx context.Context,
opts EngineInitOptions,
out OutStream,
authConfig *types.AuthConfig,
healthfn func(context.Context) error) error
DoUpdate(ctx context.Context,
opts EngineInitOptions,
out OutStream,
authConfig *types.AuthConfig,
healthfn func(context.Context) error) error
GetEngineVersions(ctx context.Context, registryClient registryclient.RegistryClient, currentVersion, imageName string) (AvailableVersions, error)
GetCurrentEngineVersion(ctx context.Context) (EngineInitOptions, error)
RemoveEngine(ctx context.Context) error
}
// EngineInitOptions contains the configuration settings
// use during initialization of a containerized docker engine
type EngineInitOptions struct {
RegistryPrefix string
EngineImage string
EngineVersion string
ConfigFile string
Scope string
}
// AvailableVersions groups the available versions which were discovered
type AvailableVersions struct {
Downgrades []DockerVersion
Patches []DockerVersion
Upgrades []DockerVersion
}
// DockerVersion wraps a semantic version to retain the original tag
// since the docker date based versions don't strictly follow semantic
// versioning (leading zeros, etc.)
type DockerVersion struct {
ver.Version
Tag string
}
// Update stores available updates for rendering in a table
type Update struct {
Type string
Version string
Notes string
}
// OutStream is an output stream used to write normal program output.
type OutStream interface {
io.Writer
FD() uintptr
IsTerminal() bool
}