mirror of https://github.com/docker/cli.git
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:
parent
8ec21567a7
commit
2d344b2f61
|
@ -19,8 +19,8 @@ import (
|
||||||
manifeststore "github.com/docker/cli/cli/manifest/store"
|
manifeststore "github.com/docker/cli/cli/manifest/store"
|
||||||
registryclient "github.com/docker/cli/cli/registry/client"
|
registryclient "github.com/docker/cli/cli/registry/client"
|
||||||
"github.com/docker/cli/cli/trust"
|
"github.com/docker/cli/cli/trust"
|
||||||
"github.com/docker/cli/internal/containerizedengine"
|
|
||||||
dopts "github.com/docker/cli/opts"
|
dopts "github.com/docker/cli/opts"
|
||||||
|
clitypes "github.com/docker/cli/types"
|
||||||
"github.com/docker/docker/api"
|
"github.com/docker/docker/api"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
registrytypes "github.com/docker/docker/api/types/registry"
|
registrytypes "github.com/docker/docker/api/types/registry"
|
||||||
|
@ -55,20 +55,21 @@ type Cli interface {
|
||||||
ManifestStore() manifeststore.Store
|
ManifestStore() manifeststore.Store
|
||||||
RegistryClient(bool) registryclient.RegistryClient
|
RegistryClient(bool) registryclient.RegistryClient
|
||||||
ContentTrustEnabled() bool
|
ContentTrustEnabled() bool
|
||||||
NewContainerizedEngineClient(sockPath string) (containerizedengine.Client, error)
|
NewContainerizedEngineClient(sockPath string) (clitypes.ContainerizedClient, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DockerCli is an instance the docker command line client.
|
// DockerCli is an instance the docker command line client.
|
||||||
// Instances of the client can be returned from NewDockerCli.
|
// Instances of the client can be returned from NewDockerCli.
|
||||||
type DockerCli struct {
|
type DockerCli struct {
|
||||||
configFile *configfile.ConfigFile
|
configFile *configfile.ConfigFile
|
||||||
in *InStream
|
in *InStream
|
||||||
out *OutStream
|
out *OutStream
|
||||||
err io.Writer
|
err io.Writer
|
||||||
client client.APIClient
|
client client.APIClient
|
||||||
serverInfo ServerInfo
|
serverInfo ServerInfo
|
||||||
clientInfo ClientInfo
|
clientInfo ClientInfo
|
||||||
contentTrust bool
|
contentTrust bool
|
||||||
|
newContainerizeClient func(string) (clitypes.ContainerizedClient, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultVersion returns api.defaultVersion or DOCKER_API_VERSION if specified.
|
// 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
|
// NewContainerizedEngineClient returns a containerized engine client
|
||||||
func (cli *DockerCli) NewContainerizedEngineClient(sockPath string) (containerizedengine.Client, error) {
|
func (cli *DockerCli) NewContainerizedEngineClient(sockPath string) (clitypes.ContainerizedClient, error) {
|
||||||
return containerizedengine.NewClient(sockPath)
|
return cli.newContainerizeClient(sockPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerInfo stores details about the supported features and platform of the
|
// 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.
|
// 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 {
|
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}
|
return &DockerCli{in: NewInStream(in), out: NewOutStream(out), err: err, contentTrust: isTrusted, newContainerizeClient: containerizedFn}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAPIClientFromFlags creates a new APIClient from command line flags
|
// NewAPIClientFromFlags creates a new APIClient from command line flags
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
|
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/cli/cli/command/formatter"
|
"github.com/docker/cli/cli/command/formatter"
|
||||||
"github.com/docker/cli/internal/containerizedengine"
|
|
||||||
"github.com/docker/cli/internal/licenseutils"
|
"github.com/docker/cli/internal/licenseutils"
|
||||||
|
clitypes "github.com/docker/cli/types"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/licensing/model"
|
"github.com/docker/licensing/model"
|
||||||
"github.com/pkg/errors"
|
"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.licenseFile, "license", "", "License File")
|
||||||
flags.StringVar(&options.version, "version", "", "Specify engine version (default is to use currently running version)")
|
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.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.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.displayOnly, "display-only", false, "only display the available licenses and exit")
|
||||||
flags.BoolVar(&options.quiet, "quiet", false, "Only display available licenses by ID")
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := containerizedengine.EngineInitOptions{
|
opts := clitypes.EngineInitOptions{
|
||||||
RegistryPrefix: options.registryPrefix,
|
RegistryPrefix: options.registryPrefix,
|
||||||
EngineImage: options.image,
|
EngineImage: options.image,
|
||||||
EngineVersion: options.version,
|
EngineVersion: options.version,
|
||||||
|
|
|
@ -4,13 +4,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/internal/containerizedengine"
|
"github.com/docker/cli/types"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestActivateNoContainerd(t *testing.T) {
|
func TestActivateNoContainerd(t *testing.T) {
|
||||||
testCli.SetContainerizedEngineClient(
|
testCli.SetContainerizedEngineClient(
|
||||||
func(string) (containerizedengine.Client, error) {
|
func(string) (types.ContainerizedClient, error) {
|
||||||
return nil, fmt.Errorf("some error")
|
return nil, fmt.Errorf("some error")
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -24,7 +24,7 @@ func TestActivateNoContainerd(t *testing.T) {
|
||||||
|
|
||||||
func TestActivateBadLicense(t *testing.T) {
|
func TestActivateBadLicense(t *testing.T) {
|
||||||
testCli.SetContainerizedEngineClient(
|
testCli.SetContainerizedEngineClient(
|
||||||
func(string) (containerizedengine.Client, error) {
|
func(string) (types.ContainerizedClient, error) {
|
||||||
return &fakeContainerizedEngineClient{}, nil
|
return &fakeContainerizedEngineClient{}, nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/cli/cli/command/formatter"
|
"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/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -72,7 +72,7 @@ func runCheck(dockerCli command.Cli, options checkOptions) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
availUpdates := []containerizedengine.Update{
|
availUpdates := []clitypes.Update{
|
||||||
{Type: "current", Version: currentVersion},
|
{Type: "current", Version: currentVersion},
|
||||||
}
|
}
|
||||||
if len(versions.Patches) > 0 {
|
if len(versions.Patches) > 0 {
|
||||||
|
@ -115,14 +115,14 @@ func runCheck(dockerCli command.Cli, options checkOptions) error {
|
||||||
|
|
||||||
func processVersions(currentVersion, verType string,
|
func processVersions(currentVersion, verType string,
|
||||||
includePrerelease bool,
|
includePrerelease bool,
|
||||||
versions []containerizedengine.DockerVersion) []containerizedengine.Update {
|
versions []clitypes.DockerVersion) []clitypes.Update {
|
||||||
availUpdates := []containerizedengine.Update{}
|
availUpdates := []clitypes.Update{}
|
||||||
for _, ver := range versions {
|
for _, ver := range versions {
|
||||||
if !includePrerelease && ver.Prerelease() != "" {
|
if !includePrerelease && ver.Prerelease() != "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ver.Tag != currentVersion {
|
if ver.Tag != currentVersion {
|
||||||
availUpdates = append(availUpdates, containerizedengine.Update{
|
availUpdates = append(availUpdates, clitypes.Update{
|
||||||
Type: verType,
|
Type: verType,
|
||||||
Version: ver.Tag,
|
Version: ver.Tag,
|
||||||
Notes: fmt.Sprintf("%s/%s", releaseNotePrefix, ver.Tag),
|
Notes: fmt.Sprintf("%s/%s", releaseNotePrefix, ver.Tag),
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
registryclient "github.com/docker/cli/cli/registry/client"
|
registryclient "github.com/docker/cli/cli/registry/client"
|
||||||
"github.com/docker/cli/internal/containerizedengine"
|
|
||||||
"github.com/docker/cli/internal/test"
|
"github.com/docker/cli/internal/test"
|
||||||
|
clitypes "github.com/docker/cli/types"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
ver "github.com/hashicorp/go-version"
|
ver "github.com/hashicorp/go-version"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
|
@ -20,7 +20,7 @@ var (
|
||||||
|
|
||||||
func TestCheckForUpdatesNoContainerd(t *testing.T) {
|
func TestCheckForUpdatesNoContainerd(t *testing.T) {
|
||||||
testCli.SetContainerizedEngineClient(
|
testCli.SetContainerizedEngineClient(
|
||||||
func(string) (containerizedengine.Client, error) {
|
func(string) (clitypes.ContainerizedClient, error) {
|
||||||
return nil, fmt.Errorf("some error")
|
return nil, fmt.Errorf("some error")
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -33,11 +33,11 @@ func TestCheckForUpdatesNoContainerd(t *testing.T) {
|
||||||
|
|
||||||
func TestCheckForUpdatesNoCurrentVersion(t *testing.T) {
|
func TestCheckForUpdatesNoCurrentVersion(t *testing.T) {
|
||||||
retErr := fmt.Errorf("some failure")
|
retErr := fmt.Errorf("some failure")
|
||||||
getCurrentEngineVersionFunc := func(ctx context.Context) (containerizedengine.EngineInitOptions, error) {
|
getCurrentEngineVersionFunc := func(ctx context.Context) (clitypes.EngineInitOptions, error) {
|
||||||
return containerizedengine.EngineInitOptions{}, retErr
|
return clitypes.EngineInitOptions{}, retErr
|
||||||
}
|
}
|
||||||
testCli.SetContainerizedEngineClient(
|
testCli.SetContainerizedEngineClient(
|
||||||
func(string) (containerizedengine.Client, error) {
|
func(string) (clitypes.ContainerizedClient, error) {
|
||||||
return &fakeContainerizedEngineClient{
|
return &fakeContainerizedEngineClient{
|
||||||
getCurrentEngineVersionFunc: getCurrentEngineVersionFunc,
|
getCurrentEngineVersionFunc: getCurrentEngineVersionFunc,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -54,11 +54,11 @@ func TestCheckForUpdatesGetEngineVersionsFail(t *testing.T) {
|
||||||
retErr := fmt.Errorf("some failure")
|
retErr := fmt.Errorf("some failure")
|
||||||
getEngineVersionsFunc := func(ctx context.Context,
|
getEngineVersionsFunc := func(ctx context.Context,
|
||||||
registryClient registryclient.RegistryClient,
|
registryClient registryclient.RegistryClient,
|
||||||
currentVersion, imageName string) (containerizedengine.AvailableVersions, error) {
|
currentVersion, imageName string) (clitypes.AvailableVersions, error) {
|
||||||
return containerizedengine.AvailableVersions{}, retErr
|
return clitypes.AvailableVersions{}, retErr
|
||||||
}
|
}
|
||||||
testCli.SetContainerizedEngineClient(
|
testCli.SetContainerizedEngineClient(
|
||||||
func(string) (containerizedengine.Client, error) {
|
func(string) (clitypes.ContainerizedClient, error) {
|
||||||
return &fakeContainerizedEngineClient{
|
return &fakeContainerizedEngineClient{
|
||||||
getEngineVersionsFunc: getEngineVersionsFunc,
|
getEngineVersionsFunc: getEngineVersionsFunc,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -72,23 +72,23 @@ func TestCheckForUpdatesGetEngineVersionsFail(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckForUpdatesGetEngineVersionsHappy(t *testing.T) {
|
func TestCheckForUpdatesGetEngineVersionsHappy(t *testing.T) {
|
||||||
getCurrentEngineVersionFunc := func(ctx context.Context) (containerizedengine.EngineInitOptions, error) {
|
getCurrentEngineVersionFunc := func(ctx context.Context) (clitypes.EngineInitOptions, error) {
|
||||||
return containerizedengine.EngineInitOptions{
|
return clitypes.EngineInitOptions{
|
||||||
EngineImage: "current engine",
|
EngineImage: "current engine",
|
||||||
EngineVersion: "1.1.0",
|
EngineVersion: "1.1.0",
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
getEngineVersionsFunc := func(ctx context.Context,
|
getEngineVersionsFunc := func(ctx context.Context,
|
||||||
registryClient registryclient.RegistryClient,
|
registryClient registryclient.RegistryClient,
|
||||||
currentVersion, imageName string) (containerizedengine.AvailableVersions, error) {
|
currentVersion, imageName string) (clitypes.AvailableVersions, error) {
|
||||||
return containerizedengine.AvailableVersions{
|
return clitypes.AvailableVersions{
|
||||||
Downgrades: parseVersions(t, "1.0.1", "1.0.2", "1.0.3-beta1"),
|
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"),
|
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"),
|
Upgrades: parseVersions(t, "1.2.0", "2.0.0", "2.1.0-beta1"),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
testCli.SetContainerizedEngineClient(
|
testCli.SetContainerizedEngineClient(
|
||||||
func(string) (containerizedengine.Client, error) {
|
func(string) (clitypes.ContainerizedClient, error) {
|
||||||
return &fakeContainerizedEngineClient{
|
return &fakeContainerizedEngineClient{
|
||||||
getEngineVersionsFunc: getEngineVersionsFunc,
|
getEngineVersionsFunc: getEngineVersionsFunc,
|
||||||
getCurrentEngineVersionFunc: getCurrentEngineVersionFunc,
|
getCurrentEngineVersionFunc: getCurrentEngineVersionFunc,
|
||||||
|
@ -128,14 +128,14 @@ func TestCheckForUpdatesGetEngineVersionsHappy(t *testing.T) {
|
||||||
golden.Assert(t, testCli.OutBuffer().String(), "check-patches-only.golden")
|
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)
|
v, err := ver.NewVersion(tag)
|
||||||
assert.NilError(t, err)
|
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 {
|
func parseVersions(t *testing.T, tags ...string) []clitypes.DockerVersion {
|
||||||
ret := make([]containerizedengine.DockerVersion, len(tags))
|
ret := make([]clitypes.DockerVersion, len(tags))
|
||||||
for i, tag := range tags {
|
for i, tag := range tags {
|
||||||
ret[i] = makeVersion(t, tag)
|
ret[i] = makeVersion(t, tag)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
registryclient "github.com/docker/cli/cli/registry/client"
|
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"
|
"github.com/docker/docker/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,28 +13,28 @@ type (
|
||||||
fakeContainerizedEngineClient struct {
|
fakeContainerizedEngineClient struct {
|
||||||
closeFunc func() error
|
closeFunc func() error
|
||||||
activateEngineFunc func(ctx context.Context,
|
activateEngineFunc func(ctx context.Context,
|
||||||
opts containerizedengine.EngineInitOptions,
|
opts clitypes.EngineInitOptions,
|
||||||
out containerizedengine.OutStream,
|
out clitypes.OutStream,
|
||||||
authConfig *types.AuthConfig,
|
authConfig *types.AuthConfig,
|
||||||
healthfn func(context.Context) error) error
|
healthfn func(context.Context) error) error
|
||||||
initEngineFunc func(ctx context.Context,
|
initEngineFunc func(ctx context.Context,
|
||||||
opts containerizedengine.EngineInitOptions,
|
opts clitypes.EngineInitOptions,
|
||||||
out containerizedengine.OutStream,
|
out clitypes.OutStream,
|
||||||
authConfig *types.AuthConfig,
|
authConfig *types.AuthConfig,
|
||||||
healthfn func(context.Context) error) error
|
healthfn func(context.Context) error) error
|
||||||
doUpdateFunc func(ctx context.Context,
|
doUpdateFunc func(ctx context.Context,
|
||||||
opts containerizedengine.EngineInitOptions,
|
opts clitypes.EngineInitOptions,
|
||||||
out containerizedengine.OutStream,
|
out clitypes.OutStream,
|
||||||
authConfig *types.AuthConfig,
|
authConfig *types.AuthConfig,
|
||||||
healthfn func(context.Context) error) error
|
healthfn func(context.Context) error) error
|
||||||
getEngineVersionsFunc func(ctx context.Context,
|
getEngineVersionsFunc func(ctx context.Context,
|
||||||
registryClient registryclient.RegistryClient,
|
registryClient registryclient.RegistryClient,
|
||||||
currentVersion,
|
currentVersion,
|
||||||
imageName string) (containerizedengine.AvailableVersions, error)
|
imageName string) (clitypes.AvailableVersions, error)
|
||||||
|
|
||||||
getEngineFunc func(ctx context.Context) (containerd.Container, error)
|
getEngineFunc func(ctx context.Context) (containerd.Container, error)
|
||||||
removeEngineFunc func(ctx context.Context, engine containerd.Container) error
|
removeEngineFunc func(ctx context.Context) error
|
||||||
getCurrentEngineVersionFunc func(ctx context.Context) (containerizedengine.EngineInitOptions, 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,
|
func (w *fakeContainerizedEngineClient) ActivateEngine(ctx context.Context,
|
||||||
opts containerizedengine.EngineInitOptions,
|
opts clitypes.EngineInitOptions,
|
||||||
out containerizedengine.OutStream,
|
out clitypes.OutStream,
|
||||||
authConfig *types.AuthConfig,
|
authConfig *types.AuthConfig,
|
||||||
healthfn func(context.Context) error) error {
|
healthfn func(context.Context) error) error {
|
||||||
if w.activateEngineFunc != nil {
|
if w.activateEngineFunc != nil {
|
||||||
|
@ -56,8 +56,8 @@ func (w *fakeContainerizedEngineClient) ActivateEngine(ctx context.Context,
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (w *fakeContainerizedEngineClient) InitEngine(ctx context.Context,
|
func (w *fakeContainerizedEngineClient) InitEngine(ctx context.Context,
|
||||||
opts containerizedengine.EngineInitOptions,
|
opts clitypes.EngineInitOptions,
|
||||||
out containerizedengine.OutStream,
|
out clitypes.OutStream,
|
||||||
authConfig *types.AuthConfig,
|
authConfig *types.AuthConfig,
|
||||||
healthfn func(context.Context) error) error {
|
healthfn func(context.Context) error) error {
|
||||||
if w.initEngineFunc != nil {
|
if w.initEngineFunc != nil {
|
||||||
|
@ -66,8 +66,8 @@ func (w *fakeContainerizedEngineClient) InitEngine(ctx context.Context,
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (w *fakeContainerizedEngineClient) DoUpdate(ctx context.Context,
|
func (w *fakeContainerizedEngineClient) DoUpdate(ctx context.Context,
|
||||||
opts containerizedengine.EngineInitOptions,
|
opts clitypes.EngineInitOptions,
|
||||||
out containerizedengine.OutStream,
|
out clitypes.OutStream,
|
||||||
authConfig *types.AuthConfig,
|
authConfig *types.AuthConfig,
|
||||||
healthfn func(context.Context) error) error {
|
healthfn func(context.Context) error) error {
|
||||||
if w.doUpdateFunc != nil {
|
if w.doUpdateFunc != nil {
|
||||||
|
@ -77,12 +77,12 @@ func (w *fakeContainerizedEngineClient) DoUpdate(ctx context.Context,
|
||||||
}
|
}
|
||||||
func (w *fakeContainerizedEngineClient) GetEngineVersions(ctx context.Context,
|
func (w *fakeContainerizedEngineClient) GetEngineVersions(ctx context.Context,
|
||||||
registryClient registryclient.RegistryClient,
|
registryClient registryclient.RegistryClient,
|
||||||
currentVersion, imageName string) (containerizedengine.AvailableVersions, error) {
|
currentVersion, imageName string) (clitypes.AvailableVersions, error) {
|
||||||
|
|
||||||
if w.getEngineVersionsFunc != nil {
|
if w.getEngineVersionsFunc != nil {
|
||||||
return w.getEngineVersionsFunc(ctx, registryClient, currentVersion, imageName)
|
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) {
|
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
|
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 {
|
if w.removeEngineFunc != nil {
|
||||||
return w.removeEngineFunc(ctx, engine)
|
return w.removeEngineFunc(ctx)
|
||||||
}
|
}
|
||||||
return nil
|
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 {
|
if w.getCurrentEngineVersionFunc != nil {
|
||||||
return w.getCurrentEngineVersionFunc(ctx)
|
return w.getCurrentEngineVersionFunc(ctx)
|
||||||
}
|
}
|
||||||
return containerizedengine.EngineInitOptions{}, nil
|
return clitypes.EngineInitOptions{}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,13 @@ import (
|
||||||
|
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/cli/internal/containerizedengine"
|
clitypes "github.com/docker/cli/types"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
type extendedEngineInitOptions struct {
|
type extendedEngineInitOptions struct {
|
||||||
containerizedengine.EngineInitOptions
|
clitypes.EngineInitOptions
|
||||||
sockPath string
|
sockPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ file on the host and may be pre-created before running the 'init' command.
|
||||||
}
|
}
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
flags.StringVar(&options.EngineVersion, "version", cli.Version, "Specify engine version")
|
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.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.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")
|
flags.StringVar(&options.sockPath, "containerd", "", "override default location of containerd endpoint")
|
||||||
|
|
|
@ -4,13 +4,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/internal/containerizedengine"
|
clitypes "github.com/docker/cli/types"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInitNoContainerd(t *testing.T) {
|
func TestInitNoContainerd(t *testing.T) {
|
||||||
testCli.SetContainerizedEngineClient(
|
testCli.SetContainerizedEngineClient(
|
||||||
func(string) (containerizedengine.Client, error) {
|
func(string) (clitypes.ContainerizedClient, error) {
|
||||||
return nil, fmt.Errorf("some error")
|
return nil, fmt.Errorf("some error")
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -23,7 +23,7 @@ func TestInitNoContainerd(t *testing.T) {
|
||||||
|
|
||||||
func TestInitHappy(t *testing.T) {
|
func TestInitHappy(t *testing.T) {
|
||||||
testCli.SetContainerizedEngineClient(
|
testCli.SetContainerizedEngineClient(
|
||||||
func(string) (containerizedengine.Client, error) {
|
func(string) (clitypes.ContainerizedClient, error) {
|
||||||
return &fakeContainerizedEngineClient{}, nil
|
return &fakeContainerizedEngineClient{}, nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -45,10 +45,5 @@ func runRm(dockerCli command.Cli, options rmOptions) error {
|
||||||
}
|
}
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
engine, err := client.GetEngine(ctx)
|
return client.RemoveEngine(ctx)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return client.RemoveEngine(ctx, engine)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/internal/containerizedengine"
|
clitypes "github.com/docker/cli/types"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRmNoContainerd(t *testing.T) {
|
func TestRmNoContainerd(t *testing.T) {
|
||||||
testCli.SetContainerizedEngineClient(
|
testCli.SetContainerizedEngineClient(
|
||||||
func(string) (containerizedengine.Client, error) {
|
func(string) (clitypes.ContainerizedClient, error) {
|
||||||
return nil, fmt.Errorf("some error")
|
return nil, fmt.Errorf("some error")
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -23,7 +23,7 @@ func TestRmNoContainerd(t *testing.T) {
|
||||||
|
|
||||||
func TestRmHappy(t *testing.T) {
|
func TestRmHappy(t *testing.T) {
|
||||||
testCli.SetContainerizedEngineClient(
|
testCli.SetContainerizedEngineClient(
|
||||||
func(string) (containerizedengine.Client, error) {
|
func(string) (clitypes.ContainerizedClient, error) {
|
||||||
return &fakeContainerizedEngineClient{}, nil
|
return &fakeContainerizedEngineClient{}, nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,13 +4,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/internal/containerizedengine"
|
clitypes "github.com/docker/cli/types"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUpdateNoContainerd(t *testing.T) {
|
func TestUpdateNoContainerd(t *testing.T) {
|
||||||
testCli.SetContainerizedEngineClient(
|
testCli.SetContainerizedEngineClient(
|
||||||
func(string) (containerizedengine.Client, error) {
|
func(string) (clitypes.ContainerizedClient, error) {
|
||||||
return nil, fmt.Errorf("some error")
|
return nil, fmt.Errorf("some error")
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -23,7 +23,7 @@ func TestUpdateNoContainerd(t *testing.T) {
|
||||||
|
|
||||||
func TestUpdateHappy(t *testing.T) {
|
func TestUpdateHappy(t *testing.T) {
|
||||||
testCli.SetContainerizedEngineClient(
|
testCli.SetContainerizedEngineClient(
|
||||||
func(string) (containerizedengine.Client, error) {
|
func(string) (clitypes.ContainerizedClient, error) {
|
||||||
return &fakeContainerizedEngineClient{}, nil
|
return &fakeContainerizedEngineClient{}, nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package formatter
|
package formatter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/docker/cli/internal/containerizedengine"
|
clitypes "github.com/docker/cli/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -31,7 +31,7 @@ func NewUpdatesFormat(source string, quiet bool) Format {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdatesWrite writes the context
|
// 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 {
|
render := func(format func(subContext subContext) error) error {
|
||||||
for _, update := range availableUpdates {
|
for _, update := range availableUpdates {
|
||||||
updatesCtx := &updateContext{trunc: ctx.Trunc, u: update}
|
updatesCtx := &updateContext{trunc: ctx.Trunc, u: update}
|
||||||
|
@ -53,7 +53,7 @@ func UpdatesWrite(ctx Context, availableUpdates []containerizedengine.Update) er
|
||||||
type updateContext struct {
|
type updateContext struct {
|
||||||
HeaderContext
|
HeaderContext
|
||||||
trunc bool
|
trunc bool
|
||||||
u containerizedengine.Update
|
u clitypes.Update
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *updateContext) MarshalJSON() ([]byte, error) {
|
func (c *updateContext) MarshalJSON() ([]byte, error) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/internal/containerizedengine"
|
clitypes "github.com/docker/cli/types"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
is "gotest.tools/assert/cmp"
|
is "gotest.tools/assert/cmp"
|
||||||
)
|
)
|
||||||
|
@ -84,7 +84,7 @@ version2
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testcase := range cases {
|
for _, testcase := range cases {
|
||||||
updates := []containerizedengine.Update{
|
updates := []clitypes.Update{
|
||||||
{Type: "updateType1", Version: "version1", Notes: "description 1"},
|
{Type: "updateType1", Version: "version1", Notes: "description 1"},
|
||||||
{Type: "updateType2", Version: "version2", Notes: "description 2"},
|
{Type: "updateType2", Version: "version2", Notes: "description 2"},
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ version2
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateContextWriteJSON(t *testing.T) {
|
func TestUpdateContextWriteJSON(t *testing.T) {
|
||||||
updates := []containerizedengine.Update{
|
updates := []clitypes.Update{
|
||||||
{Type: "updateType1", Version: "version1", Notes: "note1"},
|
{Type: "updateType1", Version: "version1", Notes: "note1"},
|
||||||
{Type: "updateType2", Version: "version2", Notes: "note2"},
|
{Type: "updateType2", Version: "version2", Notes: "note2"},
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ func TestUpdateContextWriteJSON(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateContextWriteJSONField(t *testing.T) {
|
func TestUpdateContextWriteJSONField(t *testing.T) {
|
||||||
updates := []containerizedengine.Update{
|
updates := []clitypes.Update{
|
||||||
{Type: "updateType1", Version: "version1"},
|
{Type: "updateType1", Version: "version1"},
|
||||||
{Type: "updateType2", Version: "version2"},
|
{Type: "updateType2", Version: "version2"},
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
cliconfig "github.com/docker/cli/cli/config"
|
cliconfig "github.com/docker/cli/cli/config"
|
||||||
"github.com/docker/cli/cli/debug"
|
"github.com/docker/cli/cli/debug"
|
||||||
cliflags "github.com/docker/cli/cli/flags"
|
cliflags "github.com/docker/cli/cli/flags"
|
||||||
|
"github.com/docker/cli/internal/containerizedengine"
|
||||||
"github.com/docker/docker/api/types/versions"
|
"github.com/docker/docker/api/types/versions"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/docker/docker/pkg/term"
|
"github.com/docker/docker/pkg/term"
|
||||||
|
@ -168,7 +169,7 @@ func main() {
|
||||||
stdin, stdout, stderr := term.StdStreams()
|
stdin, stdout, stderr := term.StdStreams()
|
||||||
logrus.SetOutput(stderr)
|
logrus.SetOutput(stderr)
|
||||||
|
|
||||||
dockerCli := command.NewDockerCli(stdin, stdout, stderr, contentTrustEnabled())
|
dockerCli := command.NewDockerCli(stdin, stdout, stderr, contentTrustEnabled(), containerizedengine.NewClient)
|
||||||
cmd := newDockerCommand(dockerCli)
|
cmd := newDockerCommand(dockerCli)
|
||||||
|
|
||||||
if err := cmd.Execute(); err != nil {
|
if err := cmd.Execute(); err != nil {
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestClientDebugEnabled(t *testing.T) {
|
||||||
|
|
||||||
func TestExitStatusForInvalidSubcommandWithHelpFlag(t *testing.T) {
|
func TestExitStatusForInvalidSubcommandWithHelpFlag(t *testing.T) {
|
||||||
discard := ioutil.Discard
|
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"})
|
cmd.SetArgs([]string{"help", "invalid"})
|
||||||
err := cmd.Execute()
|
err := cmd.Execute()
|
||||||
assert.Error(t, err, "unknown help topic: invalid")
|
assert.Error(t, err, "unknown help topic: invalid")
|
||||||
|
|
|
@ -19,7 +19,7 @@ const descriptionSourcePath = "docs/reference/commandline/"
|
||||||
|
|
||||||
func generateCliYaml(opts *options) error {
|
func generateCliYaml(opts *options) error {
|
||||||
stdin, stdout, stderr := term.StdStreams()
|
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"}
|
cmd := &cobra.Command{Use: "docker"}
|
||||||
commands.AddCommands(cmd, dockerCli)
|
commands.AddCommands(cmd, dockerCli)
|
||||||
source := filepath.Join(opts.source, descriptionSourcePath)
|
source := filepath.Join(opts.source, descriptionSourcePath)
|
||||||
|
|
|
@ -5,9 +5,16 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd"
|
||||||
"github.com/docker/cli/internal/containerizedengine"
|
"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
|
// CleanupEngine ensures the local engine has been removed between testcases
|
||||||
func CleanupEngine(t *testing.T) error {
|
func CleanupEngine(t *testing.T) error {
|
||||||
t.Log("doing engine cleanup")
|
t.Log("doing engine cleanup")
|
||||||
|
@ -19,7 +26,7 @@ func CleanupEngine(t *testing.T) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if the engine exists first
|
// See if the engine exists first
|
||||||
engine, err := client.GetEngine(ctx)
|
_, err = client.(containerizedclient).GetEngine(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "not present") {
|
if strings.Contains(err.Error(), "not present") {
|
||||||
t.Log("engine was not detected, no cleanup to perform")
|
t.Log("engine was not detected, no cleanup to perform")
|
||||||
|
@ -31,7 +38,7 @@ func CleanupEngine(t *testing.T) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// TODO Consider nuking the docker dir too so there's no cached content between test cases
|
// 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 {
|
if err != nil {
|
||||||
t.Logf("Failed to remove engine: %s", err)
|
t.Logf("Failed to remove engine: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package containerizedengine
|
package containerizedengine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
@ -69,10 +68,6 @@ type (
|
||||||
loadProcessFunc func(context.Context, string, cio.Attach) (containerd.Process, error)
|
loadProcessFunc func(context.Context, string, cio.Attach) (containerd.Process, error)
|
||||||
metricsFunc func(context.Context) (*containerdtypes.Metric, error)
|
metricsFunc func(context.Context) (*containerdtypes.Metric, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
testOutStream struct {
|
|
||||||
bytes.Buffer
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w *fakeContainerdClient) Containers(ctx context.Context, filters ...string) ([]containerd.Container, error) {
|
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
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *testOutStream) FD() uintptr {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
func (o *testOutStream) IsTerminal() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/remotes/docker"
|
"github.com/containerd/containerd/remotes/docker"
|
||||||
|
clitypes "github.com/docker/cli/types"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/pkg/jsonmessage"
|
"github.com/docker/docker/pkg/jsonmessage"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
@ -15,7 +16,7 @@ import (
|
||||||
// NewClient returns a new containerizedengine client
|
// NewClient returns a new containerizedengine client
|
||||||
// This client can be used to manage the lifecycle of
|
// This client can be used to manage the lifecycle of
|
||||||
// dockerd running as a container on containerd.
|
// dockerd running as a container on containerd.
|
||||||
func NewClient(sockPath string) (Client, error) {
|
func NewClient(sockPath string) (clitypes.ContainerizedClient, error) {
|
||||||
if sockPath == "" {
|
if sockPath == "" {
|
||||||
sockPath = containerdSockPath
|
sockPath = containerdSockPath
|
||||||
}
|
}
|
||||||
|
@ -23,17 +24,17 @@ func NewClient(sockPath string) (Client, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return baseClient{
|
return &baseClient{
|
||||||
cclient: cclient,
|
cclient: cclient,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close will close the underlying clients
|
// Close will close the underlying clients
|
||||||
func (c baseClient) Close() error {
|
func (c *baseClient) Close() error {
|
||||||
return c.cclient.Close()
|
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) {
|
authConfig *types.AuthConfig) (containerd.Image, error) {
|
||||||
|
|
||||||
resolver := docker.NewResolver(docker.ResolverOptions{
|
resolver := docker.NewResolver(docker.ResolverOptions{
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package containerizedengine
|
package containerizedengine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
@ -22,7 +24,7 @@ func TestPullWithAuthPullFail(t *testing.T) {
|
||||||
}
|
}
|
||||||
imageName := "testnamegoeshere"
|
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")
|
assert.ErrorContains(t, err, "pull failure")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +40,6 @@ func TestPullWithAuthPullPass(t *testing.T) {
|
||||||
}
|
}
|
||||||
imageName := "testnamegoeshere"
|
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)
|
assert.NilError(t, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,15 @@ import (
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
"github.com/containerd/containerd/runtime/restart"
|
"github.com/containerd/containerd/runtime/restart"
|
||||||
"github.com/docker/cli/internal/pkg/containerized"
|
"github.com/docker/cli/internal/pkg/containerized"
|
||||||
|
clitypes "github.com/docker/cli/types"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _ clitypes.ContainerizedClient = &baseClient{}
|
||||||
|
|
||||||
// InitEngine is the main entrypoint for `docker engine init`
|
// 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 {
|
authConfig *types.AuthConfig, healthfn func(context.Context) error) error {
|
||||||
|
|
||||||
ctx = namespaces.WithNamespace(ctx, engineNamespace)
|
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)
|
// 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)
|
ctx = namespaces.WithNamespace(ctx, engineNamespace)
|
||||||
containers, err := c.cclient.Containers(ctx, "id=="+engineContainerName)
|
containers, err := c.cclient.Containers(ctx, "id=="+engineContainerName)
|
||||||
if err != nil {
|
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
|
// 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)
|
ctx := namespaces.WithNamespace(context.Background(), engineNamespace)
|
||||||
image, err := engine.Image(ctx)
|
image, err := engine.Image(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -94,7 +97,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// waitForEngine will wait for the engine to start
|
// 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)
|
ticker := time.NewTicker(engineWaitInterval)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
defer func() {
|
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
|
var ret error
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -137,7 +140,15 @@ func (c baseClient) waitForEngineContainer(ctx context.Context, ticker *time.Tic
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveEngine gracefully unwinds the current engine
|
// 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)
|
ctx = namespaces.WithNamespace(ctx, engineNamespace)
|
||||||
|
|
||||||
// Make sure the container isn't being restarted while we unwind it
|
// 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
|
// 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)
|
ctx = namespaces.WithNamespace(ctx, engineNamespace)
|
||||||
image, err := c.cclient.GetImage(ctx, imageName)
|
image, err := c.cclient.GetImage(ctx, imageName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package containerizedengine
|
package containerizedengine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -12,6 +13,8 @@ import (
|
||||||
"github.com/containerd/containerd/cio"
|
"github.com/containerd/containerd/cio"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/oci"
|
"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/docker/docker/api/types"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
|
@ -26,11 +29,11 @@ func healthfnError(ctx context.Context) error {
|
||||||
|
|
||||||
func TestInitGetEngineFail(t *testing.T) {
|
func TestInitGetEngineFail(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
opts := EngineInitOptions{
|
opts := clitypes.EngineInitOptions{
|
||||||
EngineVersion: "engineversiongoeshere",
|
EngineVersion: "engineversiongoeshere",
|
||||||
RegistryPrefix: "registryprefixgoeshere",
|
RegistryPrefix: "registryprefixgoeshere",
|
||||||
ConfigFile: "/tmp/configfilegoeshere",
|
ConfigFile: "/tmp/configfilegoeshere",
|
||||||
EngineImage: CommunityEngineImage,
|
EngineImage: clitypes.CommunityEngineImage,
|
||||||
}
|
}
|
||||||
container := &fakeContainer{}
|
container := &fakeContainer{}
|
||||||
client := baseClient{
|
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)
|
assert.Assert(t, err == ErrEngineAlreadyPresent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInitCheckImageFail(t *testing.T) {
|
func TestInitCheckImageFail(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
opts := EngineInitOptions{
|
opts := clitypes.EngineInitOptions{
|
||||||
EngineVersion: "engineversiongoeshere",
|
EngineVersion: "engineversiongoeshere",
|
||||||
RegistryPrefix: "registryprefixgoeshere",
|
RegistryPrefix: "registryprefixgoeshere",
|
||||||
ConfigFile: "/tmp/configfilegoeshere",
|
ConfigFile: "/tmp/configfilegoeshere",
|
||||||
EngineImage: CommunityEngineImage,
|
EngineImage: clitypes.CommunityEngineImage,
|
||||||
}
|
}
|
||||||
client := baseClient{
|
client := baseClient{
|
||||||
cclient: &fakeContainerdClient{
|
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, "unable to check for image")
|
||||||
assert.ErrorContains(t, err, "something went wrong")
|
assert.ErrorContains(t, err, "something went wrong")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInitPullFail(t *testing.T) {
|
func TestInitPullFail(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
opts := EngineInitOptions{
|
opts := clitypes.EngineInitOptions{
|
||||||
EngineVersion: "engineversiongoeshere",
|
EngineVersion: "engineversiongoeshere",
|
||||||
RegistryPrefix: "registryprefixgoeshere",
|
RegistryPrefix: "registryprefixgoeshere",
|
||||||
ConfigFile: "/tmp/configfilegoeshere",
|
ConfigFile: "/tmp/configfilegoeshere",
|
||||||
EngineImage: CommunityEngineImage,
|
EngineImage: clitypes.CommunityEngineImage,
|
||||||
}
|
}
|
||||||
client := baseClient{
|
client := baseClient{
|
||||||
cclient: &fakeContainerdClient{
|
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, "unable to pull image")
|
||||||
assert.ErrorContains(t, err, "pull failure")
|
assert.ErrorContains(t, err, "pull failure")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInitStartFail(t *testing.T) {
|
func TestInitStartFail(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
opts := EngineInitOptions{
|
opts := clitypes.EngineInitOptions{
|
||||||
EngineVersion: "engineversiongoeshere",
|
EngineVersion: "engineversiongoeshere",
|
||||||
RegistryPrefix: "registryprefixgoeshere",
|
RegistryPrefix: "registryprefixgoeshere",
|
||||||
ConfigFile: "/tmp/configfilegoeshere",
|
ConfigFile: "/tmp/configfilegoeshere",
|
||||||
EngineImage: CommunityEngineImage,
|
EngineImage: clitypes.CommunityEngineImage,
|
||||||
}
|
}
|
||||||
client := baseClient{
|
client := baseClient{
|
||||||
cclient: &fakeContainerdClient{
|
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")
|
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")
|
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")
|
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)
|
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, "failed to remove existing engine")
|
||||||
assert.ErrorContains(t, err, "delete failure")
|
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")
|
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")
|
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")
|
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")
|
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)
|
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)
|
assert.Assert(t, err == ErrEngineShutdownTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,24 +3,14 @@ package containerizedengine
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/content"
|
"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"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
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"
|
containerdSockPath = "/run/containerd/containerd.sock"
|
||||||
engineContainerName = "dockerd"
|
engineContainerName = "dockerd"
|
||||||
engineNamespace = "docker"
|
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 {
|
type baseClient struct {
|
||||||
cclient containerdClient
|
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
|
// containerdClient abstracts the containerd client to aid in testability
|
||||||
type containerdClient interface {
|
type containerdClient interface {
|
||||||
Containers(ctx context.Context, filters ...string) ([]containerd.Container, error)
|
Containers(ctx context.Context, filters ...string) ([]containerd.Container, error)
|
||||||
|
@ -128,32 +83,3 @@ type containerdClient interface {
|
||||||
ContentStore() content.Store
|
ContentStore() content.Store
|
||||||
ContainerService() containers.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
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,16 +9,17 @@ import (
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
"github.com/docker/cli/internal/pkg/containerized"
|
"github.com/docker/cli/internal/pkg/containerized"
|
||||||
|
clitypes "github.com/docker/cli/types"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetCurrentEngineVersion determines the current type of engine (image) and version
|
// 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)
|
ctx = namespaces.WithNamespace(ctx, engineNamespace)
|
||||||
ret := EngineInitOptions{}
|
ret := clitypes.EngineInitOptions{}
|
||||||
currentEngine := CommunityEngineImage
|
currentEngine := clitypes.CommunityEngineImage
|
||||||
engine, err := c.GetEngine(ctx)
|
engine, err := c.GetEngine(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == ErrEngineNotPresent {
|
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)
|
return ret, errors.Wrapf(err, "failed to parse image name: %s", imageName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(distributionRef.Name(), EnterpriseEngineImage) {
|
if strings.Contains(distributionRef.Name(), clitypes.EnterpriseEngineImage) {
|
||||||
currentEngine = EnterpriseEngineImage
|
currentEngine = clitypes.EnterpriseEngineImage
|
||||||
}
|
}
|
||||||
taggedRef, ok := distributionRef.(reference.NamedTagged)
|
taggedRef, ok := distributionRef.(reference.NamedTagged)
|
||||||
if !ok {
|
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
|
// 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 {
|
authConfig *types.AuthConfig, healthfn func(context.Context) error) error {
|
||||||
|
|
||||||
// set the proxy scope to "ee" for activate flows
|
// set the proxy scope to "ee" for activate flows
|
||||||
opts.scope = "ee"
|
opts.Scope = "ee"
|
||||||
|
|
||||||
ctx = namespaces.WithNamespace(ctx, engineNamespace)
|
ctx = namespaces.WithNamespace(ctx, engineNamespace)
|
||||||
|
|
||||||
|
@ -64,7 +65,7 @@ func (c baseClient) ActivateEngine(ctx context.Context, opts EngineInitOptions,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
opts.EngineVersion = currentOpts.EngineVersion
|
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
|
// This is a "no-op" activation so the only change would be the license - don't update the engine itself
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -73,7 +74,7 @@ func (c baseClient) ActivateEngine(ctx context.Context, opts EngineInitOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoUpdate performs the underlying engine update
|
// 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 {
|
authConfig *types.AuthConfig, healthfn func(context.Context) error) error {
|
||||||
|
|
||||||
ctx = namespaces.WithNamespace(ctx, engineNamespace)
|
ctx = namespaces.WithNamespace(ctx, engineNamespace)
|
||||||
|
@ -117,13 +118,13 @@ func (c baseClient) DoUpdate(ctx context.Context, opts EngineInitOptions, out Ou
|
||||||
defer cancel()
|
defer cancel()
|
||||||
return c.waitForEngine(ctx, out, healthfn)
|
return c.waitForEngine(ctx, out, healthfn)
|
||||||
})
|
})
|
||||||
if err == nil && opts.scope != "" {
|
if err == nil && opts.Scope != "" {
|
||||||
var labels map[string]string
|
var labels map[string]string
|
||||||
labels, err = engine.Labels(ctx)
|
labels, err = engine.Labels(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
labels[proxyLabel] = opts.scope
|
labels[proxyLabel] = opts.Scope
|
||||||
_, err = engine.SetLabels(ctx, labels)
|
_, err = engine.SetLabels(ctx, labels)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package containerizedengine
|
package containerizedengine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -8,6 +9,8 @@ import (
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/cio"
|
"github.com/containerd/containerd/cio"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/docker/cli/cli/command"
|
||||||
|
clitypes "github.com/docker/cli/types"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
@ -16,7 +19,7 @@ func TestGetCurrentEngineVersionHappy(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
image := &fakeImage{
|
image := &fakeImage{
|
||||||
nameFunc: func() string {
|
nameFunc: func() string {
|
||||||
return "acme.com/dockermirror/" + CommunityEngineImage + ":engineversion"
|
return "acme.com/dockermirror/" + clitypes.CommunityEngineImage + ":engineversion"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
container := &fakeContainer{
|
container := &fakeContainer{
|
||||||
|
@ -34,7 +37,7 @@ func TestGetCurrentEngineVersionHappy(t *testing.T) {
|
||||||
|
|
||||||
opts, err := client.GetCurrentEngineVersion(ctx)
|
opts, err := client.GetCurrentEngineVersion(ctx)
|
||||||
assert.NilError(t, err)
|
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.RegistryPrefix, "acme.com/dockermirror")
|
||||||
assert.Equal(t, opts.EngineVersion, "engineversion")
|
assert.Equal(t, opts.EngineVersion, "engineversion")
|
||||||
}
|
}
|
||||||
|
@ -43,7 +46,7 @@ func TestGetCurrentEngineVersionEnterpriseHappy(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
image := &fakeImage{
|
image := &fakeImage{
|
||||||
nameFunc: func() string {
|
nameFunc: func() string {
|
||||||
return "docker.io/docker/" + EnterpriseEngineImage + ":engineversion"
|
return "docker.io/docker/" + clitypes.EnterpriseEngineImage + ":engineversion"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
container := &fakeContainer{
|
container := &fakeContainer{
|
||||||
|
@ -61,7 +64,7 @@ func TestGetCurrentEngineVersionEnterpriseHappy(t *testing.T) {
|
||||||
|
|
||||||
opts, err := client.GetCurrentEngineVersion(ctx)
|
opts, err := client.GetCurrentEngineVersion(ctx)
|
||||||
assert.NilError(t, err)
|
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.EngineVersion, "engineversion")
|
||||||
assert.Equal(t, opts.RegistryPrefix, "docker.io/docker")
|
assert.Equal(t, opts.RegistryPrefix, "docker.io/docker")
|
||||||
}
|
}
|
||||||
|
@ -147,14 +150,14 @@ func TestActivateNoEngine(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
opts := EngineInitOptions{
|
opts := clitypes.EngineInitOptions{
|
||||||
EngineVersion: "engineversiongoeshere",
|
EngineVersion: "engineversiongoeshere",
|
||||||
RegistryPrefix: "registryprefixgoeshere",
|
RegistryPrefix: "registryprefixgoeshere",
|
||||||
ConfigFile: "/tmp/configfilegoeshere",
|
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")
|
assert.ErrorContains(t, err, "unable to find")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +166,7 @@ func TestActivateNoChange(t *testing.T) {
|
||||||
registryPrefix := "registryprefixgoeshere"
|
registryPrefix := "registryprefixgoeshere"
|
||||||
image := &fakeImage{
|
image := &fakeImage{
|
||||||
nameFunc: func() string {
|
nameFunc: func() string {
|
||||||
return registryPrefix + "/" + EnterpriseEngineImage + ":engineversion"
|
return registryPrefix + "/" + clitypes.EnterpriseEngineImage + ":engineversion"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
container := &fakeContainer{
|
container := &fakeContainer{
|
||||||
|
@ -184,14 +187,14 @@ func TestActivateNoChange(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
opts := EngineInitOptions{
|
opts := clitypes.EngineInitOptions{
|
||||||
EngineVersion: "engineversiongoeshere",
|
EngineVersion: "engineversiongoeshere",
|
||||||
RegistryPrefix: "registryprefixgoeshere",
|
RegistryPrefix: "registryprefixgoeshere",
|
||||||
ConfigFile: "/tmp/configfilegoeshere",
|
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)
|
assert.NilError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,34 +222,34 @@ func TestActivateDoUpdateFail(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
opts := EngineInitOptions{
|
opts := clitypes.EngineInitOptions{
|
||||||
EngineVersion: "engineversiongoeshere",
|
EngineVersion: "engineversiongoeshere",
|
||||||
RegistryPrefix: "registryprefixgoeshere",
|
RegistryPrefix: "registryprefixgoeshere",
|
||||||
ConfigFile: "/tmp/configfilegoeshere",
|
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, "check for image")
|
||||||
assert.ErrorContains(t, err, "something went wrong")
|
assert.ErrorContains(t, err, "something went wrong")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDoUpdateNoVersion(t *testing.T) {
|
func TestDoUpdateNoVersion(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
opts := EngineInitOptions{
|
opts := clitypes.EngineInitOptions{
|
||||||
EngineVersion: "",
|
EngineVersion: "",
|
||||||
RegistryPrefix: "registryprefixgoeshere",
|
RegistryPrefix: "registryprefixgoeshere",
|
||||||
ConfigFile: "/tmp/configfilegoeshere",
|
ConfigFile: "/tmp/configfilegoeshere",
|
||||||
EngineImage: EnterpriseEngineImage,
|
EngineImage: clitypes.EnterpriseEngineImage,
|
||||||
}
|
}
|
||||||
client := baseClient{}
|
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")
|
assert.ErrorContains(t, err, "please pick the version you")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDoUpdateImageMiscError(t *testing.T) {
|
func TestDoUpdateImageMiscError(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
opts := EngineInitOptions{
|
opts := clitypes.EngineInitOptions{
|
||||||
EngineVersion: "engineversiongoeshere",
|
EngineVersion: "engineversiongoeshere",
|
||||||
RegistryPrefix: "registryprefixgoeshere",
|
RegistryPrefix: "registryprefixgoeshere",
|
||||||
ConfigFile: "/tmp/configfilegoeshere",
|
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, "check for image")
|
||||||
assert.ErrorContains(t, err, "something went wrong")
|
assert.ErrorContains(t, err, "something went wrong")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDoUpdatePullFail(t *testing.T) {
|
func TestDoUpdatePullFail(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
opts := EngineInitOptions{
|
opts := clitypes.EngineInitOptions{
|
||||||
EngineVersion: "engineversiongoeshere",
|
EngineVersion: "engineversiongoeshere",
|
||||||
RegistryPrefix: "registryprefixgoeshere",
|
RegistryPrefix: "registryprefixgoeshere",
|
||||||
ConfigFile: "/tmp/configfilegoeshere",
|
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, "unable to pull")
|
||||||
assert.ErrorContains(t, err, "pull failure")
|
assert.ErrorContains(t, err, "pull failure")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDoUpdateEngineMissing(t *testing.T) {
|
func TestDoUpdateEngineMissing(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
opts := EngineInitOptions{
|
opts := clitypes.EngineInitOptions{
|
||||||
EngineVersion: "engineversiongoeshere",
|
EngineVersion: "engineversiongoeshere",
|
||||||
RegistryPrefix: "registryprefixgoeshere",
|
RegistryPrefix: "registryprefixgoeshere",
|
||||||
ConfigFile: "/tmp/configfilegoeshere",
|
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")
|
assert.ErrorContains(t, err, "unable to find existing engine")
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
registryclient "github.com/docker/cli/cli/registry/client"
|
registryclient "github.com/docker/cli/cli/registry/client"
|
||||||
|
clitypes "github.com/docker/cli/types"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
ver "github.com/hashicorp/go-version"
|
ver "github.com/hashicorp/go-version"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -12,29 +13,29 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetEngineVersions reports the versions of the engine that are available
|
// 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)
|
imageRef, err := reference.ParseNormalizedNamed(imageName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return AvailableVersions{}, err
|
return clitypes.AvailableVersions{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tags, err := registryClient.GetTags(ctx, imageRef)
|
tags, err := registryClient.GetTags(ctx, imageRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return AvailableVersions{}, err
|
return clitypes.AvailableVersions{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseTags(tags, currentVersion)
|
return parseTags(tags, currentVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTags(tags []string, currentVersion string) (AvailableVersions, error) {
|
func parseTags(tags []string, currentVersion string) (clitypes.AvailableVersions, error) {
|
||||||
var ret AvailableVersions
|
var ret clitypes.AvailableVersions
|
||||||
currentVer, err := ver.NewVersion(currentVersion)
|
currentVer, err := ver.NewVersion(currentVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, errors.Wrapf(err, "failed to parse existing version %s", currentVersion)
|
return ret, errors.Wrapf(err, "failed to parse existing version %s", currentVersion)
|
||||||
}
|
}
|
||||||
downgrades := []DockerVersion{}
|
downgrades := []clitypes.DockerVersion{}
|
||||||
patches := []DockerVersion{}
|
patches := []clitypes.DockerVersion{}
|
||||||
upgrades := []DockerVersion{}
|
upgrades := []clitypes.DockerVersion{}
|
||||||
currentSegments := currentVer.Segments()
|
currentSegments := currentVer.Segments()
|
||||||
for _, tag := range tags {
|
for _, tag := range tags {
|
||||||
tmp, err := ver.NewVersion(tag)
|
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)
|
logrus.Debugf("Unable to parse %s: %s", tag, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
testVersion := DockerVersion{Version: *tmp, Tag: tag}
|
testVersion := clitypes.DockerVersion{Version: *tmp, Tag: tag}
|
||||||
if testVersion.LessThan(currentVer) {
|
if testVersion.LessThan(currentVer) {
|
||||||
downgrades = append(downgrades, testVersion)
|
downgrades = append(downgrades, testVersion)
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
manifeststore "github.com/docker/cli/cli/manifest/store"
|
manifeststore "github.com/docker/cli/cli/manifest/store"
|
||||||
registryclient "github.com/docker/cli/cli/registry/client"
|
registryclient "github.com/docker/cli/cli/registry/client"
|
||||||
"github.com/docker/cli/cli/trust"
|
"github.com/docker/cli/cli/trust"
|
||||||
"github.com/docker/cli/internal/containerizedengine"
|
clitypes "github.com/docker/cli/types"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
notaryclient "github.com/theupdateframework/notary/client"
|
notaryclient "github.com/theupdateframework/notary/client"
|
||||||
)
|
)
|
||||||
|
@ -20,7 +20,7 @@ import (
|
||||||
// NotaryClientFuncType defines a function that returns a fake notary client
|
// NotaryClientFuncType defines a function that returns a fake notary client
|
||||||
type NotaryClientFuncType func(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error)
|
type NotaryClientFuncType func(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error)
|
||||||
type clientInfoFuncType func() command.ClientInfo
|
type clientInfoFuncType func() command.ClientInfo
|
||||||
type containerizedEngineFuncType func(string) (containerizedengine.Client, error)
|
type containerizedEngineFuncType func(string) (clitypes.ContainerizedClient, error)
|
||||||
|
|
||||||
// FakeCli emulates the default DockerCli
|
// FakeCli emulates the default DockerCli
|
||||||
type FakeCli struct {
|
type FakeCli struct {
|
||||||
|
@ -172,7 +172,7 @@ func EnableContentTrust(c *FakeCli) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContainerizedEngineClient returns a containerized engine client
|
// 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 {
|
if c.containerizedEngineClientFunc != nil {
|
||||||
return c.containerizedEngineClientFunc(sockPath)
|
return c.containerizedEngineClientFunc(sockPath)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ func generateManPages(opts *options) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
stdin, stdout, stderr := term.StdStreams()
|
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"}
|
cmd := &cobra.Command{Use: "docker"}
|
||||||
commands.AddCommands(cmd, dockerCli)
|
commands.AddCommands(cmd, dockerCli)
|
||||||
source := filepath.Join(opts.source, descriptionSourcePath)
|
source := filepath.Join(opts.source, descriptionSourcePath)
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue