mirror of
https://github.com/docker/cli.git
synced 2026-08-24 10:05:37 -05:00
Compare commits
@@ -61,9 +61,9 @@ jobs:
|
||||
path: ${{ env.GOPATH }}/src/github.com/docker/cli
|
||||
-
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.20.4
|
||||
go-version: 1.20.7
|
||||
-
|
||||
name: Test
|
||||
run: |
|
||||
|
||||
+4
-1
@@ -117,7 +117,10 @@ issues:
|
||||
- text: "package-comments: should have a package comment"
|
||||
linters:
|
||||
- revive
|
||||
|
||||
# FIXME temporarily suppress these (see https://github.com/gotestyourself/gotest.tools/issues/272)
|
||||
- text: "SA1019: (assert|cmp|is)\\.ErrorType is deprecated"
|
||||
linters:
|
||||
- staticcheck
|
||||
# Exclude some linters from running on tests files.
|
||||
- path: _test\.go
|
||||
linters:
|
||||
|
||||
+7
-7
@@ -1,12 +1,12 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG BASE_VARIANT=alpine
|
||||
ARG GO_VERSION=1.20.4
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG GO_VERSION=1.20.7
|
||||
ARG ALPINE_VERSION=3.17
|
||||
ARG XX_VERSION=1.1.1
|
||||
ARG GOVERSIONINFO_VERSION=v1.3.0
|
||||
ARG GOTESTSUM_VERSION=v1.8.2
|
||||
ARG BUILDX_VERSION=0.10.4
|
||||
ARG GOTESTSUM_VERSION=v1.10.0
|
||||
ARG BUILDX_VERSION=0.11.2
|
||||
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
||||
@@ -125,8 +125,8 @@ CMD ./scripts/test/e2e/entry
|
||||
FROM build-base-${BASE_VARIANT} AS dev
|
||||
COPY . .
|
||||
|
||||
FROM scratch AS plugins
|
||||
COPY --from=build-plugins /out .
|
||||
|
||||
FROM scratch AS binary
|
||||
COPY --from=build /out .
|
||||
|
||||
FROM scratch AS plugins
|
||||
COPY --from=build-plugins /out .
|
||||
|
||||
+1
-6
@@ -49,9 +49,9 @@
|
||||
|
||||
people = [
|
||||
"bsousaa",
|
||||
"neersighted",
|
||||
"programmerq",
|
||||
"sam-thibault",
|
||||
"thajeztah",
|
||||
"vvoland"
|
||||
]
|
||||
|
||||
@@ -103,11 +103,6 @@
|
||||
Email = "nicolas.deloof@gmail.com"
|
||||
GitHub = "ndeloof"
|
||||
|
||||
[people.neersighted]
|
||||
Name = "Bjorn Neergaard"
|
||||
Email = "bneergaard@mirantis.com"
|
||||
GitHub = "neersighted"
|
||||
|
||||
[people.programmerq]
|
||||
Name = "Jeff Anderson"
|
||||
Email = "jeff@docker.com"
|
||||
|
||||
+2
-2
@@ -426,7 +426,7 @@ func invalidPluginReason(cmd *cobra.Command) string {
|
||||
return cmd.Annotations[pluginmanager.CommandAnnotationPluginInvalid]
|
||||
}
|
||||
|
||||
const usageTemplate = `Usage:
|
||||
var usageTemplate = `Usage:
|
||||
|
||||
{{- if not .HasSubCommands}} {{.UseLine}}{{end}}
|
||||
{{- if .HasSubCommands}} {{ .CommandPath}}{{- if .HasAvailableFlags}} [OPTIONS]{{end}} COMMAND{{end}}
|
||||
@@ -525,5 +525,5 @@ Run '{{.CommandPath}} COMMAND --help' for more information on a command.
|
||||
{{- end}}
|
||||
`
|
||||
|
||||
const helpTemplate = `
|
||||
var helpTemplate = `
|
||||
{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
|
||||
|
||||
+4
-2
@@ -48,7 +48,9 @@ type Streams interface {
|
||||
// Cli represents the docker command line client.
|
||||
type Cli interface {
|
||||
Client() client.APIClient
|
||||
Streams
|
||||
Out() *streams.Out
|
||||
Err() io.Writer
|
||||
In() *streams.In
|
||||
SetIn(in *streams.In)
|
||||
Apply(ops ...DockerCliOption) error
|
||||
ConfigFile() *configfile.ConfigFile
|
||||
@@ -189,7 +191,7 @@ func (cli *DockerCli) ManifestStore() manifeststore.Store {
|
||||
// RegistryClient returns a client for communicating with a Docker distribution
|
||||
// registry
|
||||
func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient {
|
||||
resolver := func(ctx context.Context, index *registry.IndexInfo) registry.AuthConfig {
|
||||
resolver := func(ctx context.Context, index *registry.IndexInfo) types.AuthConfig {
|
||||
return ResolveAuthConfig(ctx, cli, index)
|
||||
}
|
||||
return registryclient.NewRegistryClient(resolver, UserAgent(), allowInsecure)
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -66,13 +66,13 @@ func ContainerNames(dockerCli command.Cli, all bool, filters ...func(types.Conta
|
||||
// VolumeNames offers completion for volumes
|
||||
func VolumeNames(dockerCli command.Cli) ValidArgsFn {
|
||||
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
list, err := dockerCli.Client().VolumeList(cmd.Context(), volume.ListOptions{})
|
||||
list, err := dockerCli.Client().VolumeList(cmd.Context(), filters.Args{})
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
var names []string
|
||||
for _, vol := range list.Volumes {
|
||||
names = append(names, vol.Name)
|
||||
for _, volume := range list.Volumes {
|
||||
names = append(names, volume.Name)
|
||||
}
|
||||
return names, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ func resolveLocalPath(localPath string) (absPath string, err error) {
|
||||
if absPath, err = filepath.Abs(localPath); err != nil {
|
||||
return
|
||||
}
|
||||
return archive.PreserveTrailingDotOrSeparator(absPath, localPath), nil
|
||||
return archive.PreserveTrailingDotOrSeparator(absPath, localPath, filepath.Separator), nil
|
||||
}
|
||||
|
||||
func copyFromContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpConfig) (err error) {
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
"github.com/docker/cli/cli/command/image"
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
@@ -20,6 +19,7 @@ import (
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
apiclient "github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/registry"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -95,16 +95,16 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, options *createOptio
|
||||
}
|
||||
}
|
||||
copts.env = *opts.NewListOptsRef(&newEnv, nil)
|
||||
containerCfg, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
|
||||
containerConfig, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
|
||||
if err != nil {
|
||||
reportError(dockerCli.Err(), "create", err.Error(), true)
|
||||
return cli.StatusError{StatusCode: 125}
|
||||
}
|
||||
if err = validateAPIVersion(containerCfg, dockerCli.Client().ClientVersion()); err != nil {
|
||||
if err = validateAPIVersion(containerConfig, dockerCli.Client().ClientVersion()); err != nil {
|
||||
reportError(dockerCli.Err(), "create", err.Error(), true)
|
||||
return cli.StatusError{StatusCode: 125}
|
||||
}
|
||||
response, err := createContainer(context.Background(), dockerCli, containerCfg, options)
|
||||
response, err := createContainer(context.Background(), dockerCli, containerConfig, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -112,27 +112,41 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, options *createOptio
|
||||
return nil
|
||||
}
|
||||
|
||||
// FIXME(thaJeztah): this is the only code-path that uses APIClient.ImageCreate. Rewrite this to use the regular "pull" code (or vice-versa).
|
||||
func pullImage(ctx context.Context, dockerCli command.Cli, image string, opts *createOptions) error {
|
||||
encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, image)
|
||||
func pullImage(ctx context.Context, dockerCli command.Cli, image string, platform string, out io.Writer) error {
|
||||
ref, err := reference.ParseNormalizedNamed(image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
responseBody, err := dockerCli.Client().ImageCreate(ctx, image, types.ImageCreateOptions{
|
||||
// Resolve the Repository name from fqn to RepositoryInfo
|
||||
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
options := types.ImageCreateOptions{
|
||||
RegistryAuth: encodedAuth,
|
||||
Platform: opts.platform,
|
||||
})
|
||||
Platform: platform,
|
||||
}
|
||||
|
||||
responseBody, err := dockerCli.Client().ImageCreate(ctx, image, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseBody.Close()
|
||||
|
||||
out := dockerCli.Err()
|
||||
if opts.quiet {
|
||||
out = io.Discard
|
||||
}
|
||||
return jsonmessage.DisplayJSONMessagesToStream(responseBody, streams.NewOut(out), nil)
|
||||
return jsonmessage.DisplayJSONMessagesStream(
|
||||
responseBody,
|
||||
out,
|
||||
dockerCli.Out().FD(),
|
||||
dockerCli.Out().IsTerminal(),
|
||||
nil)
|
||||
}
|
||||
|
||||
type cidFile struct {
|
||||
@@ -185,10 +199,10 @@ func newCIDFile(path string) (*cidFile, error) {
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *containerConfig, opts *createOptions) (*container.CreateResponse, error) {
|
||||
config := containerCfg.Config
|
||||
hostConfig := containerCfg.HostConfig
|
||||
networkingConfig := containerCfg.NetworkingConfig
|
||||
func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig *containerConfig, opts *createOptions) (*container.CreateResponse, error) {
|
||||
config := containerConfig.Config
|
||||
hostConfig := containerConfig.HostConfig
|
||||
networkingConfig := containerConfig.NetworkingConfig
|
||||
|
||||
warnOnOomKillDisable(*hostConfig, dockerCli.Err())
|
||||
warnOnLocalhostDNS(*hostConfig, dockerCli.Err())
|
||||
@@ -213,7 +227,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
|
||||
|
||||
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && !opts.untrusted {
|
||||
var err error
|
||||
trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef)
|
||||
trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -222,7 +236,11 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
|
||||
}
|
||||
|
||||
pullAndTagImage := func() error {
|
||||
if err := pullImage(ctx, dockerCli, config.Image, opts); err != nil {
|
||||
pullOut := dockerCli.Err()
|
||||
if opts.quiet {
|
||||
pullOut = io.Discard
|
||||
}
|
||||
if err := pullImage(ctx, dockerCli, config.Image, opts.platform, pullOut); err != nil {
|
||||
return err
|
||||
}
|
||||
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && trustedRef != nil {
|
||||
@@ -275,8 +293,8 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
|
||||
}
|
||||
}
|
||||
|
||||
for _, w := range response.Warnings {
|
||||
fmt.Fprintf(dockerCli.Err(), "WARNING: %s\n", w)
|
||||
for _, warning := range response.Warnings {
|
||||
fmt.Fprintf(dockerCli.Err(), "WARNING: %s\n", warning)
|
||||
}
|
||||
err = containerIDFile.Write(response.ID)
|
||||
return &response, err
|
||||
|
||||
@@ -3,6 +3,7 @@ package container
|
||||
import (
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -22,7 +23,7 @@ func NewDiffFormat(source string) formatter.Format {
|
||||
}
|
||||
|
||||
// DiffFormatWrite writes formatted diff using the Context
|
||||
func DiffFormatWrite(ctx formatter.Context, changes []container.FilesystemChange) error {
|
||||
func DiffFormatWrite(ctx formatter.Context, changes []container.ContainerChangeResponseItem) error {
|
||||
render := func(format func(subContext formatter.SubContext) error) error {
|
||||
for _, change := range changes {
|
||||
if err := format(&diffContext{c: change}); err != nil {
|
||||
@@ -36,7 +37,7 @@ func DiffFormatWrite(ctx formatter.Context, changes []container.FilesystemChange
|
||||
|
||||
type diffContext struct {
|
||||
formatter.HeaderContext
|
||||
c container.FilesystemChange
|
||||
c container.ContainerChangeResponseItem
|
||||
}
|
||||
|
||||
func newDiffContext() *diffContext {
|
||||
@@ -53,7 +54,16 @@ func (d *diffContext) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (d *diffContext) Type() string {
|
||||
return d.c.Kind.String()
|
||||
var kind string
|
||||
switch d.c.Kind {
|
||||
case archive.ChangeModify:
|
||||
kind = "C"
|
||||
case archive.ChangeAdd:
|
||||
kind = "A"
|
||||
case archive.ChangeDelete:
|
||||
kind = "D"
|
||||
}
|
||||
return kind
|
||||
}
|
||||
|
||||
func (d *diffContext) Path() string {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
@@ -40,10 +41,10 @@ D: /usr/app/old_app.js
|
||||
},
|
||||
}
|
||||
|
||||
diffs := []container.FilesystemChange{
|
||||
{Kind: container.ChangeModify, Path: "/var/log/app.log"},
|
||||
{Kind: container.ChangeAdd, Path: "/usr/app/app.js"},
|
||||
{Kind: container.ChangeDelete, Path: "/usr/app/old_app.js"},
|
||||
diffs := []container.ContainerChangeResponseItem{
|
||||
{Kind: archive.ChangeModify, Path: "/var/log/app.log"},
|
||||
{Kind: archive.ChangeAdd, Path: "/usr/app/app.js"},
|
||||
{Kind: archive.ChangeDelete, Path: "/usr/app/old_app.js"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
||||
@@ -120,8 +120,6 @@ func runPs(dockerCli command.Cli, options *psOptions) error {
|
||||
if len(options.format) == 0 {
|
||||
// load custom psFormat from CLI config (if any)
|
||||
options.format = dockerCli.ConfigFile().PsFormat
|
||||
} else if options.quiet {
|
||||
_, _ = dockerCli.Err().Write([]byte("WARNING: Ignoring custom format, because both --format and --quiet are set.\n"))
|
||||
}
|
||||
|
||||
listOptions, err := buildContainerListOptions(options)
|
||||
|
||||
@@ -309,22 +309,8 @@ func TestContainerListWithFormat(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
|
||||
t.Run("with format", func(t *testing.T) {
|
||||
cli.OutBuffer().Reset()
|
||||
cmd := newListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}"))
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-with-format.golden")
|
||||
})
|
||||
|
||||
t.Run("with format and quiet", func(t *testing.T) {
|
||||
cli.OutBuffer().Reset()
|
||||
cmd := newListCommand(cli)
|
||||
assert.Check(t, cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}"))
|
||||
assert.Check(t, cmd.Flags().Set("quiet", "true"))
|
||||
assert.NilError(t, cmd.Execute())
|
||||
assert.Equal(t, cli.ErrBuffer().String(), "WARNING: Ignoring custom format, because both --format and --quiet are set.\n")
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-quiet.golden")
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}")
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), "container-list-with-format.golden")
|
||||
}
|
||||
|
||||
@@ -123,7 +123,6 @@ type containerOptions struct {
|
||||
runtime string
|
||||
autoRemove bool
|
||||
init bool
|
||||
annotations *opts.MapOpts
|
||||
|
||||
Image string
|
||||
Args []string
|
||||
@@ -164,7 +163,6 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||
ulimits: opts.NewUlimitOpt(nil),
|
||||
volumes: opts.NewListOpts(nil),
|
||||
volumesFrom: opts.NewListOpts(nil),
|
||||
annotations: opts.NewMapOpts(nil, nil),
|
||||
}
|
||||
|
||||
// General purpose flags
|
||||
@@ -299,10 +297,6 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||
|
||||
flags.BoolVar(&copts.init, "init", false, "Run an init inside the container that forwards signals and reaps processes")
|
||||
flags.SetAnnotation("init", "version", []string{"1.25"})
|
||||
|
||||
flags.Var(copts.annotations, "annotation", "Add an annotation to the container (passed through to the OCI runtime)")
|
||||
flags.SetAnnotation("annotation", "version", []string{"1.43"})
|
||||
|
||||
return copts
|
||||
}
|
||||
|
||||
@@ -660,7 +654,6 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
|
||||
Mounts: mounts,
|
||||
MaskedPaths: maskedPaths,
|
||||
ReadonlyPaths: readonlyPaths,
|
||||
Annotations: copts.annotations.GetAll(),
|
||||
}
|
||||
|
||||
if copts.autoRemove && !hostConfig.RestartPolicy.IsNone() {
|
||||
|
||||
@@ -49,11 +49,11 @@ func parseRun(args []string) (*container.Config, *container.HostConfig, *network
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
// TODO: fix tests to accept ContainerConfig
|
||||
containerCfg, err := parse(flags, copts, runtime.GOOS)
|
||||
containerConfig, err := parse(flags, copts, runtime.GOOS)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
return containerCfg.Config, containerCfg.HostConfig, containerCfg.NetworkingConfig, err
|
||||
return containerConfig.Config, containerConfig.HostConfig, containerConfig.NetworkingConfig, err
|
||||
}
|
||||
|
||||
func setupRunFlags() (*pflag.FlagSet, *containerOptions) {
|
||||
|
||||
@@ -105,22 +105,22 @@ func runRun(dockerCli command.Cli, flags *pflag.FlagSet, ropts *runOptions, copt
|
||||
}
|
||||
}
|
||||
copts.env = *opts.NewListOptsRef(&newEnv, nil)
|
||||
containerCfg, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
|
||||
containerConfig, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
|
||||
// just in case the parse does not exit
|
||||
if err != nil {
|
||||
reportError(dockerCli.Err(), "run", err.Error(), true)
|
||||
return cli.StatusError{StatusCode: 125}
|
||||
}
|
||||
if err = validateAPIVersion(containerCfg, dockerCli.CurrentVersion()); err != nil {
|
||||
if err = validateAPIVersion(containerConfig, dockerCli.CurrentVersion()); err != nil {
|
||||
reportError(dockerCli.Err(), "run", err.Error(), true)
|
||||
return cli.StatusError{StatusCode: 125}
|
||||
}
|
||||
return runContainer(dockerCli, ropts, copts, containerCfg)
|
||||
return runContainer(dockerCli, ropts, copts, containerConfig)
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptions, containerCfg *containerConfig) error {
|
||||
config := containerCfg.Config
|
||||
func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptions, containerConfig *containerConfig) error {
|
||||
config := containerConfig.Config
|
||||
stdout, stderr := dockerCli.Out(), dockerCli.Err()
|
||||
client := dockerCli.Client()
|
||||
|
||||
@@ -144,7 +144,7 @@ func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptio
|
||||
ctx, cancelFun := context.WithCancel(context.Background())
|
||||
defer cancelFun()
|
||||
|
||||
createResponse, err := createContainer(ctx, dockerCli, containerCfg, &opts.createOptions)
|
||||
createResponse, err := createContainer(ctx, dockerCli, containerConfig, &opts.createOptions)
|
||||
if err != nil {
|
||||
reportError(stderr, "run", err.Error(), true)
|
||||
return runStartContainerErr(err)
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
container_id
|
||||
container_id
|
||||
@@ -55,9 +55,6 @@ ports: {{- pad .Ports 1 0}}
|
||||
}
|
||||
return Format(format)
|
||||
default: // custom format
|
||||
if quiet {
|
||||
return DefaultQuietFormat
|
||||
}
|
||||
return Format(source)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ containerID2 ubuntu "" 24 hours ago foobar_bar
|
||||
},
|
||||
{
|
||||
Context{Format: NewContainerFormat("table {{.Image}}", true, false)},
|
||||
"containerID1\ncontainerID2\n",
|
||||
"IMAGE\nubuntu\nubuntu\n",
|
||||
},
|
||||
{
|
||||
Context{Format: NewContainerFormat("table", true, false)},
|
||||
|
||||
@@ -84,3 +84,10 @@ func (c *clientContextContext) Error() string {
|
||||
// TODO(thaJeztah) add "--no-trunc" option to context ls and set default to 30 cols to match "docker service ps"
|
||||
return Ellipsis(c.c.Error, maxErrLength)
|
||||
}
|
||||
|
||||
// KubernetesEndpoint returns the kubernetes endpoint.
|
||||
//
|
||||
// Deprecated: support for kubernetes endpoints in contexts has been removed, and this formatting option will always be empty.
|
||||
func (c *clientContextContext) KubernetesEndpoint() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultDiskUsageImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}"
|
||||
defaultDiskUsageImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.VirtualSize}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}"
|
||||
defaultDiskUsageContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.LocalVolumes}}\t{{.Size}}\t{{.RunningFor}}\t{{.Status}}\t{{.Names}}"
|
||||
defaultDiskUsageVolumeTableFormat = "table {{.Name}}\t{{.Links}}\t{{.Size}}"
|
||||
defaultDiskUsageBuildCacheTableFormat = "table {{.ID}}\t{{.CacheType}}\t{{.Size}}\t{{.CreatedSince}}\t{{.LastUsedSince}}\t{{.UsageCount}}\t{{.Shared}}"
|
||||
@@ -296,10 +296,10 @@ func (c *diskUsageImagesContext) Reclaimable() string {
|
||||
|
||||
for _, i := range c.images {
|
||||
if i.Containers != 0 {
|
||||
if i.Size == -1 || i.SharedSize == -1 {
|
||||
if i.VirtualSize == -1 || i.SharedSize == -1 {
|
||||
continue
|
||||
}
|
||||
used += i.Size - i.SharedSize
|
||||
used += i.VirtualSize - i.SharedSize
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ func newImageContext() *imageContext {
|
||||
"CreatedAt": CreatedAtHeader,
|
||||
"Size": SizeHeader,
|
||||
"Containers": containersHeader,
|
||||
"VirtualSize": SizeHeader, // Deprecated: VirtualSize is deprecated, and equivalent to Size.
|
||||
"VirtualSize": SizeHeader,
|
||||
"SharedSize": sharedSizeHeader,
|
||||
"UniqueSize": uniqueSizeHeader,
|
||||
}
|
||||
@@ -260,13 +260,8 @@ func (c *imageContext) Containers() string {
|
||||
return fmt.Sprintf("%d", c.i.Containers)
|
||||
}
|
||||
|
||||
// VirtualSize shows the virtual size of the image and all of its parent
|
||||
// images. Starting with docker 1.10, images are self-contained, and
|
||||
// the VirtualSize is identical to Size.
|
||||
//
|
||||
// Deprecated: VirtualSize is deprecated, and equivalent to [imageContext.Size].
|
||||
func (c *imageContext) VirtualSize() string {
|
||||
return units.HumanSize(float64(c.i.Size))
|
||||
return units.HumanSize(float64(c.i.VirtualSize))
|
||||
}
|
||||
|
||||
func (c *imageContext) SharedSize() string {
|
||||
@@ -277,8 +272,8 @@ func (c *imageContext) SharedSize() string {
|
||||
}
|
||||
|
||||
func (c *imageContext) UniqueSize() string {
|
||||
if c.i.Size == -1 || c.i.SharedSize == -1 {
|
||||
if c.i.VirtualSize == -1 || c.i.SharedSize == -1 {
|
||||
return "N/A"
|
||||
}
|
||||
return units.HumanSize(float64(c.i.Size - c.i.SharedSize))
|
||||
return units.HumanSize(float64(c.i.VirtualSize - c.i.SharedSize))
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func TestImageContext(t *testing.T) {
|
||||
call: ctx.ID,
|
||||
},
|
||||
{
|
||||
imageCtx: imageContext{i: types.ImageSummary{Size: 10}, trunc: true},
|
||||
imageCtx: imageContext{i: types.ImageSummary{Size: 10, VirtualSize: 10}, trunc: true},
|
||||
expValue: "10B",
|
||||
call: ctx.Size,
|
||||
},
|
||||
@@ -70,9 +70,9 @@ func TestImageContext(t *testing.T) {
|
||||
call: ctx.Containers,
|
||||
},
|
||||
{
|
||||
imageCtx: imageContext{i: types.ImageSummary{Size: 10000}},
|
||||
imageCtx: imageContext{i: types.ImageSummary{VirtualSize: 10000}},
|
||||
expValue: "10kB",
|
||||
call: ctx.VirtualSize, //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.44.
|
||||
call: ctx.VirtualSize,
|
||||
},
|
||||
{
|
||||
imageCtx: imageContext{i: types.ImageSummary{SharedSize: 10000}},
|
||||
@@ -80,7 +80,7 @@ func TestImageContext(t *testing.T) {
|
||||
call: ctx.SharedSize,
|
||||
},
|
||||
{
|
||||
imageCtx: imageContext{i: types.ImageSummary{SharedSize: 5000, Size: 20000}},
|
||||
imageCtx: imageContext{i: types.ImageSummary{SharedSize: 5000, VirtualSize: 20000}},
|
||||
expValue: "15kB",
|
||||
call: ctx.UniqueSize,
|
||||
},
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/builder/remotecontext/urlutil"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
@@ -280,7 +279,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||
var resolvedTags []*resolvedTag
|
||||
if !options.untrusted {
|
||||
translator := func(ctx context.Context, ref reference.NamedTagged) (reference.Canonical, error) {
|
||||
return TrustedReference(ctx, dockerCli, ref)
|
||||
return TrustedReference(ctx, dockerCli, ref, nil)
|
||||
}
|
||||
// if there is a tar wrapper, the dockerfile needs to be replaced inside it
|
||||
if buildCtx != nil {
|
||||
@@ -323,9 +322,9 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||
|
||||
configFile := dockerCli.ConfigFile()
|
||||
creds, _ := configFile.GetAllCredentials()
|
||||
authConfigs := make(map[string]registrytypes.AuthConfig, len(creds))
|
||||
authConfigs := make(map[string]types.AuthConfig, len(creds))
|
||||
for k, auth := range creds {
|
||||
authConfigs[k] = registrytypes.AuthConfig(auth)
|
||||
authConfigs[k] = types.AuthConfig(auth)
|
||||
}
|
||||
buildOptions := imageBuildOptions(dockerCli, options)
|
||||
buildOptions.Version = types.BuilderV1
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) {
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild})
|
||||
dockerfile := bytes.NewBufferString(`
|
||||
FROM alpine:frozen
|
||||
FROM alpine:3.6
|
||||
COPY foo /
|
||||
`)
|
||||
cli.SetIn(streams.NewIn(io.NopCloser(dockerfile)))
|
||||
@@ -66,7 +66,7 @@ func TestRunBuildResetsUidAndGidInContext(t *testing.T) {
|
||||
dir := fs.NewDir(t, "test-build-context",
|
||||
fs.WithFile("foo", "some content", fs.AsUser(65534, 65534)),
|
||||
fs.WithFile("Dockerfile", `
|
||||
FROM alpine:frozen
|
||||
FROM alpine:3.6
|
||||
COPY foo bar /
|
||||
`),
|
||||
)
|
||||
@@ -155,7 +155,7 @@ func TestRunBuildFromLocalGitHubDir(t *testing.T) {
|
||||
func TestRunBuildWithSymlinkedContext(t *testing.T) {
|
||||
t.Setenv("DOCKER_BUILDKIT", "0")
|
||||
dockerfile := `
|
||||
FROM alpine:frozen
|
||||
FROM alpine:3.6
|
||||
RUN echo hello world
|
||||
`
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ func RunPull(cli command.Cli, opts PullOptions) error {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), distributionRef.String())
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, AuthResolver(cli), distributionRef.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/pkg/errors"
|
||||
@@ -77,7 +76,7 @@ func RunPush(dockerCli command.Cli, opts pushOptions) error {
|
||||
|
||||
// Resolve the Auth config relevant for this server
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"Architecture": "",
|
||||
"Os": "",
|
||||
"Size": 0,
|
||||
"VirtualSize": 0,
|
||||
"GraphDriver": {
|
||||
"Data": null,
|
||||
"Name": ""
|
||||
@@ -38,6 +39,7 @@
|
||||
"Architecture": "",
|
||||
"Os": "",
|
||||
"Size": 0,
|
||||
"VirtualSize": 0,
|
||||
"GraphDriver": {
|
||||
"Data": null,
|
||||
"Name": ""
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"Architecture": "",
|
||||
"Os": "",
|
||||
"Size": 0,
|
||||
"VirtualSize": 0,
|
||||
"GraphDriver": {
|
||||
"Data": null,
|
||||
"Name": ""
|
||||
|
||||
+13
-10
@@ -30,7 +30,7 @@ type target struct {
|
||||
}
|
||||
|
||||
// TrustedPush handles content trust pushing of an image
|
||||
func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig registrytypes.AuthConfig, options types.ImagePushOptions) error {
|
||||
func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, options types.ImagePushOptions) error {
|
||||
responseBody, err := cli.Client().ImagePush(ctx, reference.FamiliarString(ref), options)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -44,7 +44,7 @@ func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.Reposi
|
||||
// PushTrustedReference pushes a canonical reference to the trust server.
|
||||
//
|
||||
//nolint:gocyclo
|
||||
func PushTrustedReference(streams command.Streams, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig registrytypes.AuthConfig, in io.Reader) error {
|
||||
func PushTrustedReference(streams command.Streams, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, in io.Reader) error {
|
||||
// If it is a trusted push we would like to find the target entry which match the
|
||||
// tag provided in the function and then do an AddTarget later.
|
||||
target := &client.Target{}
|
||||
@@ -186,7 +186,7 @@ func trustedPull(ctx context.Context, cli command.Cli, imgRefAndAuth trust.Image
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), trustedRef.String())
|
||||
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, AuthResolver(cli), trustedRef.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -262,17 +262,20 @@ func getTrustedPullTargets(cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth)
|
||||
|
||||
// imagePullPrivileged pulls the image and displays it to the output
|
||||
func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth, opts PullOptions) error {
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(*imgRefAndAuth.AuthConfig())
|
||||
ref := reference.FamiliarString(imgRefAndAuth.Reference())
|
||||
|
||||
encodedAuth, err := command.EncodeAuthToBase64(*imgRefAndAuth.AuthConfig())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(cli, imgRefAndAuth.RepoInfo().Index, "pull")
|
||||
responseBody, err := cli.Client().ImagePull(ctx, reference.FamiliarString(imgRefAndAuth.Reference()), types.ImagePullOptions{
|
||||
options := types.ImagePullOptions{
|
||||
RegistryAuth: encodedAuth,
|
||||
PrivilegeFunc: requestPrivilege,
|
||||
All: opts.all,
|
||||
Platform: opts.platform,
|
||||
})
|
||||
}
|
||||
responseBody, err := cli.Client().ImagePull(ctx, ref, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -286,8 +289,8 @@ func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth tru
|
||||
}
|
||||
|
||||
// TrustedReference returns the canonical trusted reference for an image reference
|
||||
func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) {
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), ref.String())
|
||||
func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedTagged, rs registry.Service) (reference.Canonical, error) {
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, rs, AuthResolver(cli), ref.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -337,8 +340,8 @@ func TagTrusted(ctx context.Context, cli command.Cli, trustedRef reference.Canon
|
||||
}
|
||||
|
||||
// AuthResolver returns an auth resolver function from a command.Cli
|
||||
func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
|
||||
return func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
|
||||
func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
|
||||
return func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
|
||||
return command.ResolveAuthConfig(ctx, cli, index)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/docker/cli/cli/command/image"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/pkg/errors"
|
||||
@@ -55,6 +54,26 @@ func newInstallCommand(dockerCli command.Cli) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
type pluginRegistryService struct {
|
||||
registry.Service
|
||||
}
|
||||
|
||||
func (s pluginRegistryService) ResolveRepository(name reference.Named) (*registry.RepositoryInfo, error) {
|
||||
repoInfo, err := s.Service.ResolveRepository(name)
|
||||
if repoInfo != nil {
|
||||
repoInfo.Class = "plugin"
|
||||
}
|
||||
return repoInfo, err
|
||||
}
|
||||
|
||||
func newRegistryService() (registry.Service, error) {
|
||||
svc, err := registry.NewService(registry.ServiceOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pluginRegistryService{Service: svc}, nil
|
||||
}
|
||||
|
||||
func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOptions, cmdName string) (types.PluginInstallOptions, error) {
|
||||
// Names with both tag and digest will be treated by the daemon
|
||||
// as a pull by digest with a local name for the tag
|
||||
@@ -79,7 +98,12 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
|
||||
return types.PluginInstallOptions{}, errors.Errorf("invalid name: %s", ref.String())
|
||||
}
|
||||
|
||||
trusted, err := image.TrustedReference(context.Background(), dockerCli, nt)
|
||||
ctx := context.Background()
|
||||
svc, err := newRegistryService()
|
||||
if err != nil {
|
||||
return types.PluginInstallOptions{}, err
|
||||
}
|
||||
trusted, err := image.TrustedReference(ctx, dockerCli, nt, svc)
|
||||
if err != nil {
|
||||
return types.PluginInstallOptions{}, err
|
||||
}
|
||||
@@ -87,7 +111,8 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
|
||||
}
|
||||
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
if err != nil {
|
||||
return types.PluginInstallOptions{}, err
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/image"
|
||||
"github.com/docker/distribution/reference"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/pkg/errors"
|
||||
@@ -56,7 +55,8 @@ func runPush(dockerCli command.Cli, opts pushOptions) error {
|
||||
return err
|
||||
}
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -68,6 +68,7 @@ func runPush(dockerCli command.Cli, opts pushOptions) error {
|
||||
defer responseBody.Close()
|
||||
|
||||
if !opts.untrusted {
|
||||
repoInfo.Class = "plugin"
|
||||
return image.PushTrustedReference(dockerCli, repoInfo, named, authConfig, responseBody)
|
||||
}
|
||||
|
||||
|
||||
+41
-49
@@ -3,6 +3,8 @@ package command
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@@ -19,11 +21,20 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload.
|
||||
// ElectAuthServer returns the default registry to use.
|
||||
//
|
||||
// Deprecated: use [registrytypes.EncodeAuthConfig] instead.
|
||||
func EncodeAuthToBase64(authConfig registrytypes.AuthConfig) (string, error) {
|
||||
return registrytypes.EncodeAuthConfig(authConfig)
|
||||
// Deprecated: use [registry.IndexServer] instead.
|
||||
func ElectAuthServer(_ context.Context, _ Cli) string {
|
||||
return registry.IndexServer
|
||||
}
|
||||
|
||||
// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload
|
||||
func EncodeAuthToBase64(authConfig types.AuthConfig) (string, error) {
|
||||
buf, err := json.Marshal(authConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64.URLEncoding.EncodeToString(buf), nil
|
||||
}
|
||||
|
||||
// RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info
|
||||
@@ -41,7 +52,7 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return registrytypes.EncodeAuthConfig(authConfig)
|
||||
return EncodeAuthToBase64(authConfig)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,19 +62,19 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
|
||||
//
|
||||
// It is similar to [registry.ResolveAuthConfig], but uses the credentials-
|
||||
// store, instead of looking up credentials from a map.
|
||||
func ResolveAuthConfig(_ context.Context, cli Cli, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
|
||||
func ResolveAuthConfig(_ context.Context, cli Cli, index *registrytypes.IndexInfo) types.AuthConfig {
|
||||
configKey := index.Name
|
||||
if index.Official {
|
||||
configKey = registry.IndexServer
|
||||
}
|
||||
|
||||
a, _ := cli.ConfigFile().GetAuthConfig(configKey)
|
||||
return registrytypes.AuthConfig(a)
|
||||
return types.AuthConfig(a)
|
||||
}
|
||||
|
||||
// GetDefaultAuthConfig gets the default auth config given a serverAddress
|
||||
// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it
|
||||
func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) {
|
||||
func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (types.AuthConfig, error) {
|
||||
if !isDefaultRegistry {
|
||||
serverAddress = registry.ConvertToHostname(serverAddress)
|
||||
}
|
||||
@@ -72,27 +83,20 @@ func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, is
|
||||
if checkCredStore {
|
||||
authconfig, err = cli.ConfigFile().GetAuthConfig(serverAddress)
|
||||
if err != nil {
|
||||
return registrytypes.AuthConfig{
|
||||
return types.AuthConfig{
|
||||
ServerAddress: serverAddress,
|
||||
}, err
|
||||
}
|
||||
}
|
||||
authconfig.ServerAddress = serverAddress
|
||||
authconfig.IdentityToken = ""
|
||||
res := registrytypes.AuthConfig(authconfig)
|
||||
res := types.AuthConfig(authconfig)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// ConfigureAuth handles prompting of user's username and password if needed
|
||||
func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes.AuthConfig, isDefaultRegistry bool) error {
|
||||
// On Windows, force the use of the regular OS stdin stream.
|
||||
//
|
||||
// See:
|
||||
// - https://github.com/moby/moby/issues/14336
|
||||
// - https://github.com/moby/moby/issues/14210
|
||||
// - https://github.com/moby/moby/pull/17738
|
||||
//
|
||||
// TODO(thaJeztah): we need to confirm if this special handling is still needed, as we may not be doing this in other places.
|
||||
func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *types.AuthConfig, isDefaultRegistry bool) error {
|
||||
// On Windows, force the use of the regular OS stdin stream. Fixes #14336/#14210
|
||||
if runtime.GOOS == "windows" {
|
||||
cli.SetIn(streams.NewIn(os.Stdin))
|
||||
}
|
||||
@@ -116,11 +120,8 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes
|
||||
fmt.Fprintln(cli.Out(), "Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.")
|
||||
}
|
||||
promptWithDefault(cli.Out(), "Username", authconfig.Username)
|
||||
var err error
|
||||
flUser, err = readInput(cli.In())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
flUser = readInput(cli.In(), cli.Out())
|
||||
flUser = strings.TrimSpace(flUser)
|
||||
if flUser == "" {
|
||||
flUser = authconfig.Username
|
||||
}
|
||||
@@ -134,15 +135,12 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(cli.Out(), "Password: ")
|
||||
_ = term.DisableEcho(cli.In().FD(), oldState)
|
||||
defer func() {
|
||||
_ = term.RestoreTerminal(cli.In().FD(), oldState)
|
||||
}()
|
||||
flPassword, err = readInput(cli.In())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
term.DisableEcho(cli.In().FD(), oldState)
|
||||
|
||||
flPassword = readInput(cli.In(), cli.Out())
|
||||
fmt.Fprint(cli.Out(), "\n")
|
||||
|
||||
term.RestoreTerminal(cli.In().FD(), oldState)
|
||||
if flPassword == "" {
|
||||
return errors.Errorf("Error: Password Required")
|
||||
}
|
||||
@@ -154,15 +152,14 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes
|
||||
return nil
|
||||
}
|
||||
|
||||
// readInput reads, and returns user input from in. It tries to return a
|
||||
// single line, not including the end-of-line bytes, and trims leading
|
||||
// and trailing whitespace.
|
||||
func readInput(in io.Reader) (string, error) {
|
||||
line, _, err := bufio.NewReader(in).ReadLine()
|
||||
func readInput(in io.Reader, out io.Writer) string {
|
||||
reader := bufio.NewReader(in)
|
||||
line, _, err := reader.ReadLine()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error while reading input")
|
||||
fmt.Fprintln(out, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
return strings.TrimSpace(string(line)), nil
|
||||
return string(line)
|
||||
}
|
||||
|
||||
func promptWithDefault(out io.Writer, prompt string, configDefault string) {
|
||||
@@ -173,19 +170,14 @@ func promptWithDefault(out io.Writer, prompt string, configDefault string) {
|
||||
}
|
||||
}
|
||||
|
||||
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete
|
||||
// image. The auth configuration is serialized as a base64url encoded RFC4648,
|
||||
// section 5) JSON string for sending through the X-Registry-Auth header.
|
||||
//
|
||||
// For details on base64url encoding, see:
|
||||
// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5
|
||||
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete image
|
||||
func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (string, error) {
|
||||
// Retrieve encoded auth token from the image reference
|
||||
authConfig, err := resolveAuthConfigFromImage(ctx, cli, image)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
encodedAuth, err := EncodeAuthToBase64(authConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -193,14 +185,14 @@ func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (str
|
||||
}
|
||||
|
||||
// resolveAuthConfigFromImage retrieves that AuthConfig using the image string
|
||||
func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (registrytypes.AuthConfig, error) {
|
||||
func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (types.AuthConfig, error) {
|
||||
registryRef, err := reference.ParseNormalizedNamed(image)
|
||||
if err != nil {
|
||||
return registrytypes.AuthConfig{}, err
|
||||
return types.AuthConfig{}, err
|
||||
}
|
||||
repoInfo, err := registry.ParseRepositoryInfo(registryRef)
|
||||
if err != nil {
|
||||
return registrytypes.AuthConfig{}, err
|
||||
return types.AuthConfig{}, err
|
||||
}
|
||||
return ResolveAuthConfig(ctx, cli, repoInfo.Index), nil
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
configtypes "github.com/docker/cli/cli/config/types"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/errdefs"
|
||||
@@ -163,7 +164,7 @@ func runLogin(dockerCli command.Cli, opts loginOptions) error { //nolint:gocyclo
|
||||
return nil
|
||||
}
|
||||
|
||||
func loginWithCredStoreCreds(ctx context.Context, dockerCli command.Cli, authConfig *registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
func loginWithCredStoreCreds(ctx context.Context, dockerCli command.Cli, authConfig *types.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
fmt.Fprintf(dockerCli.Out(), "Authenticating with existing credentials...\n")
|
||||
cliClient := dockerCli.Client()
|
||||
response, err := cliClient.RegistryLogin(ctx, *authConfig)
|
||||
@@ -177,7 +178,7 @@ func loginWithCredStoreCreds(ctx context.Context, dockerCli command.Cli, authCon
|
||||
return response, err
|
||||
}
|
||||
|
||||
func loginClientSide(ctx context.Context, auth registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
func loginClientSide(ctx context.Context, auth types.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
svc, err := registry.NewService(registry.ServiceOptions{})
|
||||
if err != nil {
|
||||
return registrytypes.AuthenticateOKBody{}, err
|
||||
|
||||
@@ -38,7 +38,7 @@ func (c fakeClient) Info(context.Context) (types.Info, error) {
|
||||
return types.Info{}, nil
|
||||
}
|
||||
|
||||
func (c fakeClient) RegistryLogin(_ context.Context, auth registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
func (c fakeClient) RegistryLogin(_ context.Context, auth types.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
if auth.Password == expiredPassword {
|
||||
return registrytypes.AuthenticateOKBody{}, fmt.Errorf("Invalid Username or Password")
|
||||
}
|
||||
@@ -53,16 +53,16 @@ func (c fakeClient) RegistryLogin(_ context.Context, auth registrytypes.AuthConf
|
||||
|
||||
func TestLoginWithCredStoreCreds(t *testing.T) {
|
||||
testCases := []struct {
|
||||
inputAuthConfig registrytypes.AuthConfig
|
||||
inputAuthConfig types.AuthConfig
|
||||
expectedMsg string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
inputAuthConfig: registrytypes.AuthConfig{},
|
||||
inputAuthConfig: types.AuthConfig{},
|
||||
expectedMsg: "Authenticating with existing credentials...\n",
|
||||
},
|
||||
{
|
||||
inputAuthConfig: registrytypes.AuthConfig{
|
||||
inputAuthConfig: types.AuthConfig{
|
||||
Username: userErr,
|
||||
},
|
||||
expectedMsg: "Authenticating with existing credentials...\n",
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -55,19 +54,25 @@ func runSearch(dockerCli command.Cli, options searchOptions) error {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, indexInfo)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search")
|
||||
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search")
|
||||
results, err := dockerCli.Client().ImageSearch(ctx, options.term, types.ImageSearchOptions{
|
||||
searchOptions := types.ImageSearchOptions{
|
||||
RegistryAuth: encodedAuth,
|
||||
PrivilegeFunc: requestPrivilege,
|
||||
Filters: options.filter.Value(),
|
||||
Limit: options.limit,
|
||||
})
|
||||
}
|
||||
|
||||
clnt := dockerCli.Client()
|
||||
|
||||
results, err := clnt.ImageSearch(ctx, options.term, searchOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
configtypes "github.com/docker/cli/cli/config/types"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/client"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
@@ -21,7 +20,7 @@ type fakeClient struct {
|
||||
infoFunc func() (types.Info, error)
|
||||
}
|
||||
|
||||
var testAuthConfigs = []registry.AuthConfig{
|
||||
var testAuthConfigs = []types.AuthConfig{
|
||||
{
|
||||
ServerAddress: "https://index.docker.io/v1/",
|
||||
Username: "u0",
|
||||
@@ -46,13 +45,13 @@ func TestGetDefaultAuthConfig(t *testing.T) {
|
||||
checkCredStore bool
|
||||
inputServerAddress string
|
||||
expectedErr string
|
||||
expectedAuthConfig registry.AuthConfig
|
||||
expectedAuthConfig types.AuthConfig
|
||||
}{
|
||||
{
|
||||
checkCredStore: false,
|
||||
inputServerAddress: "",
|
||||
expectedErr: "",
|
||||
expectedAuthConfig: registry.AuthConfig{
|
||||
expectedAuthConfig: types.AuthConfig{
|
||||
ServerAddress: "",
|
||||
Username: "",
|
||||
Password: "",
|
||||
@@ -102,7 +101,7 @@ func TestGetDefaultAuthConfig_HelperError(t *testing.T) {
|
||||
cli.SetErr(errBuf)
|
||||
cli.ConfigFile().CredentialsStore = "fake-does-not-exist"
|
||||
serverAddress := "test-server-address"
|
||||
expectedAuthConfig := registry.AuthConfig{
|
||||
expectedAuthConfig := types.AuthConfig{
|
||||
ServerAddress: serverAddress,
|
||||
}
|
||||
authconfig, err := GetDefaultAuthConfig(cli, true, serverAddress, serverAddress == "https://index.docker.io/v1/")
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/docker/cli/cli/streams"
|
||||
)
|
||||
|
||||
// InStream is an input stream used by the DockerCli to read user input
|
||||
//
|
||||
// Deprecated: Use [streams.In] instead.
|
||||
type InStream = streams.In
|
||||
|
||||
// OutStream is an output stream used by the DockerCli to write normal program
|
||||
// output.
|
||||
//
|
||||
// Deprecated: Use [streams.Out] instead.
|
||||
type OutStream = streams.Out
|
||||
|
||||
// NewInStream returns a new [streams.In] from an [io.ReadCloser].
|
||||
//
|
||||
// Deprecated: Use [streams.NewIn] instead.
|
||||
func NewInStream(in io.ReadCloser) *streams.In {
|
||||
return streams.NewIn(in)
|
||||
}
|
||||
|
||||
// NewOutStream returns a new [streams.Out] from an [io.Writer].
|
||||
//
|
||||
// Deprecated: Use [streams.NewOut] instead.
|
||||
func NewOutStream(out io.Writer) *streams.Out {
|
||||
return streams.NewOut(out)
|
||||
}
|
||||
+151
-171
@@ -19,7 +19,6 @@ import (
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -29,8 +28,8 @@ type infoOptions struct {
|
||||
}
|
||||
|
||||
type clientInfo struct {
|
||||
Debug bool
|
||||
clientVersion
|
||||
Debug bool
|
||||
Context string
|
||||
Plugins []pluginmanager.Plugin
|
||||
Warnings []string
|
||||
}
|
||||
@@ -42,19 +41,11 @@ type info struct {
|
||||
// object.
|
||||
*types.Info `json:",omitempty"`
|
||||
ServerErrors []string `json:",omitempty"`
|
||||
UserName string `json:"-"`
|
||||
|
||||
ClientInfo *clientInfo `json:",omitempty"`
|
||||
ClientErrors []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
func (i *info) clientPlatform() string {
|
||||
if i.ClientInfo != nil && i.ClientInfo.Platform != nil {
|
||||
return i.ClientInfo.Platform.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NewInfoCommand creates a new cobra.Command for `docker info`
|
||||
func NewInfoCommand(dockerCli command.Cli) *cobra.Command {
|
||||
var opts infoOptions
|
||||
@@ -80,11 +71,8 @@ func NewInfoCommand(dockerCli command.Cli) *cobra.Command {
|
||||
func runInfo(cmd *cobra.Command, dockerCli command.Cli, opts *infoOptions) error {
|
||||
info := info{
|
||||
ClientInfo: &clientInfo{
|
||||
// Don't pass a dockerCLI to newClientVersion(), because we currently
|
||||
// don't include negotiated API version, and want to avoid making an
|
||||
// API connection when only printing the Client section.
|
||||
clientVersion: newClientVersion(dockerCli.CurrentContext(), nil),
|
||||
Debug: debug.IsEnabled(),
|
||||
Context: dockerCli.CurrentContext(),
|
||||
Debug: debug.IsEnabled(),
|
||||
},
|
||||
Info: &types.Info{},
|
||||
}
|
||||
@@ -108,17 +96,15 @@ func runInfo(cmd *cobra.Command, dockerCli command.Cli, opts *infoOptions) error
|
||||
} else {
|
||||
// if a format is provided, print the error, as it may be hidden
|
||||
// otherwise if the template doesn't include the ServerErrors field.
|
||||
fprintln(dockerCli.Err(), err)
|
||||
fmt.Fprintln(dockerCli.Err(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if opts.format == "" {
|
||||
info.UserName = dockerCli.ConfigFile().AuthConfigs[registry.IndexServer].Username
|
||||
info.ClientInfo.APIVersion = dockerCli.CurrentVersion()
|
||||
return prettyPrintInfo(dockerCli, info)
|
||||
}
|
||||
return formatInfo(dockerCli.Out(), info, opts.format)
|
||||
return formatInfo(dockerCli, info, opts.format)
|
||||
}
|
||||
|
||||
// placeHolders does a rudimentary match for possible placeholders in a
|
||||
@@ -160,29 +146,24 @@ func needsServerInfo(template string, info info) bool {
|
||||
return err != nil
|
||||
}
|
||||
|
||||
func prettyPrintInfo(streams command.Streams, info info) error {
|
||||
// Only append the platform info if it's not empty, to prevent printing a trailing space.
|
||||
if p := info.clientPlatform(); p != "" {
|
||||
fprintln(streams.Out(), "Client:", p)
|
||||
} else {
|
||||
fprintln(streams.Out(), "Client:")
|
||||
}
|
||||
func prettyPrintInfo(dockerCli command.Cli, info info) error {
|
||||
fmt.Fprintln(dockerCli.Out(), "Client:")
|
||||
if info.ClientInfo != nil {
|
||||
prettyPrintClientInfo(streams, *info.ClientInfo)
|
||||
prettyPrintClientInfo(dockerCli, *info.ClientInfo)
|
||||
}
|
||||
for _, err := range info.ClientErrors {
|
||||
fprintln(streams.Err(), "ERROR:", err)
|
||||
fmt.Fprintln(dockerCli.Err(), "ERROR:", err)
|
||||
}
|
||||
|
||||
fprintln(streams.Out())
|
||||
fprintln(streams.Out(), "Server:")
|
||||
fmt.Fprintln(dockerCli.Out())
|
||||
fmt.Fprintln(dockerCli.Out(), "Server:")
|
||||
if info.Info != nil {
|
||||
for _, err := range prettyPrintServerInfo(streams, &info) {
|
||||
for _, err := range prettyPrintServerInfo(dockerCli, *info.Info) {
|
||||
info.ServerErrors = append(info.ServerErrors, err.Error())
|
||||
}
|
||||
}
|
||||
for _, err := range info.ServerErrors {
|
||||
fprintln(streams.Err(), "ERROR:", err)
|
||||
fmt.Fprintln(dockerCli.Err(), "ERROR:", err)
|
||||
}
|
||||
|
||||
if len(info.ServerErrors) > 0 || len(info.ClientErrors) > 0 {
|
||||
@@ -191,18 +172,17 @@ func prettyPrintInfo(streams command.Streams, info info) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func prettyPrintClientInfo(streams command.Streams, info clientInfo) {
|
||||
fprintlnNonEmpty(streams.Out(), " Version: ", info.Version)
|
||||
fprintln(streams.Out(), " Context: ", info.Context)
|
||||
fprintln(streams.Out(), " Debug Mode:", info.Debug)
|
||||
func prettyPrintClientInfo(dockerCli command.Cli, info clientInfo) {
|
||||
fmt.Fprintln(dockerCli.Out(), " Context: ", info.Context)
|
||||
fmt.Fprintln(dockerCli.Out(), " Debug Mode:", info.Debug)
|
||||
|
||||
if len(info.Plugins) > 0 {
|
||||
fprintln(streams.Out(), " Plugins:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Plugins:")
|
||||
for _, p := range info.Plugins {
|
||||
if p.Err == nil {
|
||||
fprintf(streams.Out(), " %s: %s (%s)\n", p.Name, p.ShortDescription, p.Vendor)
|
||||
fprintlnNonEmpty(streams.Out(), " Version: ", p.Version)
|
||||
fprintlnNonEmpty(streams.Out(), " Path: ", p.Path)
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s (%s)\n", p.Name, p.ShortDescription, p.Vendor)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Version: ", p.Version)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Path: ", p.Path)
|
||||
} else {
|
||||
info.Warnings = append(info.Warnings, fmt.Sprintf("WARNING: Plugin %q is not valid: %s", p.Path, p.Err))
|
||||
}
|
||||
@@ -210,60 +190,59 @@ func prettyPrintClientInfo(streams command.Streams, info clientInfo) {
|
||||
}
|
||||
|
||||
if len(info.Warnings) > 0 {
|
||||
fprintln(streams.Err(), strings.Join(info.Warnings, "\n"))
|
||||
fmt.Fprintln(dockerCli.Err(), strings.Join(info.Warnings, "\n"))
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func prettyPrintServerInfo(streams command.Streams, info *info) []error {
|
||||
func prettyPrintServerInfo(dockerCli command.Cli, info types.Info) []error {
|
||||
var errs []error
|
||||
output := streams.Out()
|
||||
|
||||
fprintln(output, " Containers:", info.Containers)
|
||||
fprintln(output, " Running:", info.ContainersRunning)
|
||||
fprintln(output, " Paused:", info.ContainersPaused)
|
||||
fprintln(output, " Stopped:", info.ContainersStopped)
|
||||
fprintln(output, " Images:", info.Images)
|
||||
fprintlnNonEmpty(output, " Server Version:", info.ServerVersion)
|
||||
fprintlnNonEmpty(output, " Storage Driver:", info.Driver)
|
||||
fmt.Fprintln(dockerCli.Out(), " Containers:", info.Containers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Running:", info.ContainersRunning)
|
||||
fmt.Fprintln(dockerCli.Out(), " Paused:", info.ContainersPaused)
|
||||
fmt.Fprintln(dockerCli.Out(), " Stopped:", info.ContainersStopped)
|
||||
fmt.Fprintln(dockerCli.Out(), " Images:", info.Images)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Server Version:", info.ServerVersion)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Storage Driver:", info.Driver)
|
||||
if info.DriverStatus != nil {
|
||||
for _, pair := range info.DriverStatus {
|
||||
fprintf(output, " %s: %s\n", pair[0], pair[1])
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1])
|
||||
}
|
||||
}
|
||||
if info.SystemStatus != nil {
|
||||
for _, pair := range info.SystemStatus {
|
||||
fprintf(output, " %s: %s\n", pair[0], pair[1])
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1])
|
||||
}
|
||||
}
|
||||
fprintlnNonEmpty(output, " Logging Driver:", info.LoggingDriver)
|
||||
fprintlnNonEmpty(output, " Cgroup Driver:", info.CgroupDriver)
|
||||
fprintlnNonEmpty(output, " Cgroup Version:", info.CgroupVersion)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Logging Driver:", info.LoggingDriver)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Cgroup Driver:", info.CgroupDriver)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Cgroup Version:", info.CgroupVersion)
|
||||
|
||||
fprintln(output, " Plugins:")
|
||||
fprintln(output, " Volume:", strings.Join(info.Plugins.Volume, " "))
|
||||
fprintln(output, " Network:", strings.Join(info.Plugins.Network, " "))
|
||||
fmt.Fprintln(dockerCli.Out(), " Plugins:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Volume:", strings.Join(info.Plugins.Volume, " "))
|
||||
fmt.Fprintln(dockerCli.Out(), " Network:", strings.Join(info.Plugins.Network, " "))
|
||||
|
||||
if len(info.Plugins.Authorization) != 0 {
|
||||
fprintln(output, " Authorization:", strings.Join(info.Plugins.Authorization, " "))
|
||||
fmt.Fprintln(dockerCli.Out(), " Authorization:", strings.Join(info.Plugins.Authorization, " "))
|
||||
}
|
||||
|
||||
fprintln(output, " Log:", strings.Join(info.Plugins.Log, " "))
|
||||
fmt.Fprintln(dockerCli.Out(), " Log:", strings.Join(info.Plugins.Log, " "))
|
||||
|
||||
fprintln(output, " Swarm:", info.Swarm.LocalNodeState)
|
||||
printSwarmInfo(output, *info.Info)
|
||||
fmt.Fprintln(dockerCli.Out(), " Swarm:", info.Swarm.LocalNodeState)
|
||||
printSwarmInfo(dockerCli, info)
|
||||
|
||||
if len(info.Runtimes) > 0 {
|
||||
names := make([]string, 0, len(info.Runtimes))
|
||||
fmt.Fprint(dockerCli.Out(), " Runtimes:")
|
||||
for name := range info.Runtimes {
|
||||
names = append(names, name)
|
||||
fmt.Fprintf(dockerCli.Out(), " %s", name)
|
||||
}
|
||||
fprintln(output, " Runtimes:", strings.Join(names, " "))
|
||||
fprintln(output, " Default Runtime:", info.DefaultRuntime)
|
||||
fmt.Fprint(dockerCli.Out(), "\n")
|
||||
fmt.Fprintln(dockerCli.Out(), " Default Runtime:", info.DefaultRuntime)
|
||||
}
|
||||
|
||||
if info.OSType == "linux" {
|
||||
fprintln(output, " Init Binary:", info.InitBinary)
|
||||
fmt.Fprintln(dockerCli.Out(), " Init Binary:", info.InitBinary)
|
||||
|
||||
for _, ci := range []struct {
|
||||
Name string
|
||||
@@ -273,23 +252,23 @@ func prettyPrintServerInfo(streams command.Streams, info *info) []error {
|
||||
{"runc", info.RuncCommit},
|
||||
{"init", info.InitCommit},
|
||||
} {
|
||||
fprintf(output, " %s version: %s", ci.Name, ci.Commit.ID)
|
||||
fmt.Fprintf(dockerCli.Out(), " %s version: %s", ci.Name, ci.Commit.ID)
|
||||
if ci.Commit.ID != ci.Commit.Expected {
|
||||
fprintf(output, " (expected: %s)", ci.Commit.Expected)
|
||||
fmt.Fprintf(dockerCli.Out(), " (expected: %s)", ci.Commit.Expected)
|
||||
}
|
||||
fprintln(output)
|
||||
fmt.Fprint(dockerCli.Out(), "\n")
|
||||
}
|
||||
if len(info.SecurityOptions) != 0 {
|
||||
if kvs, err := types.DecodeSecurityOptions(info.SecurityOptions); err != nil {
|
||||
errs = append(errs, err)
|
||||
} else {
|
||||
fprintln(output, " Security Options:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Security Options:")
|
||||
for _, so := range kvs {
|
||||
fprintln(output, " "+so.Name)
|
||||
fmt.Fprintln(dockerCli.Out(), " "+so.Name)
|
||||
for _, o := range so.Options {
|
||||
switch o.Key {
|
||||
case "profile":
|
||||
fprintln(output, " Profile:", o.Value)
|
||||
fmt.Fprintln(dockerCli.Out(), " Profile:", o.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -299,158 +278,167 @@ func prettyPrintServerInfo(streams command.Streams, info *info) []error {
|
||||
|
||||
// Isolation only has meaning on a Windows daemon.
|
||||
if info.OSType == "windows" {
|
||||
fprintln(output, " Default Isolation:", info.Isolation)
|
||||
fmt.Fprintln(dockerCli.Out(), " Default Isolation:", info.Isolation)
|
||||
}
|
||||
|
||||
fprintlnNonEmpty(output, " Kernel Version:", info.KernelVersion)
|
||||
fprintlnNonEmpty(output, " Operating System:", info.OperatingSystem)
|
||||
fprintlnNonEmpty(output, " OSType:", info.OSType)
|
||||
fprintlnNonEmpty(output, " Architecture:", info.Architecture)
|
||||
fprintln(output, " CPUs:", info.NCPU)
|
||||
fprintln(output, " Total Memory:", units.BytesSize(float64(info.MemTotal)))
|
||||
fprintlnNonEmpty(output, " Name:", info.Name)
|
||||
fprintlnNonEmpty(output, " ID:", info.ID)
|
||||
fprintln(output, " Docker Root Dir:", info.DockerRootDir)
|
||||
fprintln(output, " Debug Mode:", info.Debug)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Kernel Version:", info.KernelVersion)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Operating System:", info.OperatingSystem)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " OSType:", info.OSType)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Architecture:", info.Architecture)
|
||||
fmt.Fprintln(dockerCli.Out(), " CPUs:", info.NCPU)
|
||||
fmt.Fprintln(dockerCli.Out(), " Total Memory:", units.BytesSize(float64(info.MemTotal)))
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Name:", info.Name)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " ID:", info.ID)
|
||||
fmt.Fprintln(dockerCli.Out(), " Docker Root Dir:", info.DockerRootDir)
|
||||
fmt.Fprintln(dockerCli.Out(), " Debug Mode:", info.Debug)
|
||||
|
||||
if info.Debug {
|
||||
fprintln(output, " File Descriptors:", info.NFd)
|
||||
fprintln(output, " Goroutines:", info.NGoroutines)
|
||||
fprintln(output, " System Time:", info.SystemTime)
|
||||
fprintln(output, " EventsListeners:", info.NEventsListener)
|
||||
fmt.Fprintln(dockerCli.Out(), " File Descriptors:", info.NFd)
|
||||
fmt.Fprintln(dockerCli.Out(), " Goroutines:", info.NGoroutines)
|
||||
fmt.Fprintln(dockerCli.Out(), " System Time:", info.SystemTime)
|
||||
fmt.Fprintln(dockerCli.Out(), " EventsListeners:", info.NEventsListener)
|
||||
}
|
||||
|
||||
fprintlnNonEmpty(dockerCli.Out(), " HTTP Proxy:", info.HTTPProxy)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " HTTPS Proxy:", info.HTTPSProxy)
|
||||
fprintlnNonEmpty(dockerCli.Out(), " No Proxy:", info.NoProxy)
|
||||
|
||||
if info.IndexServerAddress != "" {
|
||||
u := dockerCli.ConfigFile().AuthConfigs[info.IndexServerAddress].Username
|
||||
if len(u) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Username:", u)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Registry:", info.IndexServerAddress)
|
||||
}
|
||||
|
||||
fprintlnNonEmpty(output, " HTTP Proxy:", info.HTTPProxy)
|
||||
fprintlnNonEmpty(output, " HTTPS Proxy:", info.HTTPSProxy)
|
||||
fprintlnNonEmpty(output, " No Proxy:", info.NoProxy)
|
||||
fprintlnNonEmpty(output, " Username:", info.UserName)
|
||||
if len(info.Labels) > 0 {
|
||||
fprintln(output, " Labels:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Labels:")
|
||||
for _, lbl := range info.Labels {
|
||||
fprintln(output, " "+lbl)
|
||||
fmt.Fprintln(dockerCli.Out(), " "+lbl)
|
||||
}
|
||||
}
|
||||
|
||||
fprintln(output, " Experimental:", info.ExperimentalBuild)
|
||||
fmt.Fprintln(dockerCli.Out(), " Experimental:", info.ExperimentalBuild)
|
||||
|
||||
if info.RegistryConfig != nil && (len(info.RegistryConfig.InsecureRegistryCIDRs) > 0 || len(info.RegistryConfig.IndexConfigs) > 0) {
|
||||
fprintln(output, " Insecure Registries:")
|
||||
for _, registryConfig := range info.RegistryConfig.IndexConfigs {
|
||||
if !registryConfig.Secure {
|
||||
fprintln(output, " "+registryConfig.Name)
|
||||
fmt.Fprintln(dockerCli.Out(), " Insecure Registries:")
|
||||
for _, registry := range info.RegistryConfig.IndexConfigs {
|
||||
if !registry.Secure {
|
||||
fmt.Fprintln(dockerCli.Out(), " "+registry.Name)
|
||||
}
|
||||
}
|
||||
|
||||
for _, registryConfig := range info.RegistryConfig.InsecureRegistryCIDRs {
|
||||
mask, _ := registryConfig.Mask.Size()
|
||||
fprintf(output, " %s/%d\n", registryConfig.IP.String(), mask)
|
||||
for _, registry := range info.RegistryConfig.InsecureRegistryCIDRs {
|
||||
mask, _ := registry.Mask.Size()
|
||||
fmt.Fprintf(dockerCli.Out(), " %s/%d\n", registry.IP.String(), mask)
|
||||
}
|
||||
}
|
||||
|
||||
if info.RegistryConfig != nil && len(info.RegistryConfig.Mirrors) > 0 {
|
||||
fprintln(output, " Registry Mirrors:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Registry Mirrors:")
|
||||
for _, mirror := range info.RegistryConfig.Mirrors {
|
||||
fprintln(output, " "+mirror)
|
||||
fmt.Fprintln(dockerCli.Out(), " "+mirror)
|
||||
}
|
||||
}
|
||||
|
||||
fprintln(output, " Live Restore Enabled:", info.LiveRestoreEnabled)
|
||||
fmt.Fprintln(dockerCli.Out(), " Live Restore Enabled:", info.LiveRestoreEnabled)
|
||||
if info.ProductLicense != "" {
|
||||
fprintln(output, " Product License:", info.ProductLicense)
|
||||
fmt.Fprintln(dockerCli.Out(), " Product License:", info.ProductLicense)
|
||||
}
|
||||
|
||||
if info.DefaultAddressPools != nil && len(info.DefaultAddressPools) > 0 {
|
||||
fprintln(output, " Default Address Pools:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Default Address Pools:")
|
||||
for _, pool := range info.DefaultAddressPools {
|
||||
fprintf(output, " Base: %s, Size: %d\n", pool.Base, pool.Size)
|
||||
fmt.Fprintf(dockerCli.Out(), " Base: %s, Size: %d\n", pool.Base, pool.Size)
|
||||
}
|
||||
}
|
||||
|
||||
fprintln(output)
|
||||
printServerWarnings(streams.Err(), info)
|
||||
fmt.Fprint(dockerCli.Out(), "\n")
|
||||
|
||||
printServerWarnings(dockerCli, info)
|
||||
return errs
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func printSwarmInfo(output io.Writer, info types.Info) {
|
||||
func printSwarmInfo(dockerCli command.Cli, info types.Info) {
|
||||
if info.Swarm.LocalNodeState == swarm.LocalNodeStateInactive || info.Swarm.LocalNodeState == swarm.LocalNodeStateLocked {
|
||||
return
|
||||
}
|
||||
fprintln(output, " NodeID:", info.Swarm.NodeID)
|
||||
fmt.Fprintln(dockerCli.Out(), " NodeID:", info.Swarm.NodeID)
|
||||
if info.Swarm.Error != "" {
|
||||
fprintln(output, " Error:", info.Swarm.Error)
|
||||
fmt.Fprintln(dockerCli.Out(), " Error:", info.Swarm.Error)
|
||||
}
|
||||
fprintln(output, " Is Manager:", info.Swarm.ControlAvailable)
|
||||
fmt.Fprintln(dockerCli.Out(), " Is Manager:", info.Swarm.ControlAvailable)
|
||||
if info.Swarm.Cluster != nil && info.Swarm.ControlAvailable && info.Swarm.Error == "" && info.Swarm.LocalNodeState != swarm.LocalNodeStateError {
|
||||
fprintln(output, " ClusterID:", info.Swarm.Cluster.ID)
|
||||
fprintln(output, " Managers:", info.Swarm.Managers)
|
||||
fprintln(output, " Nodes:", info.Swarm.Nodes)
|
||||
fmt.Fprintln(dockerCli.Out(), " ClusterID:", info.Swarm.Cluster.ID)
|
||||
fmt.Fprintln(dockerCli.Out(), " Managers:", info.Swarm.Managers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Nodes:", info.Swarm.Nodes)
|
||||
var strAddrPool strings.Builder
|
||||
if info.Swarm.Cluster.DefaultAddrPool != nil {
|
||||
for _, p := range info.Swarm.Cluster.DefaultAddrPool {
|
||||
strAddrPool.WriteString(p + " ")
|
||||
}
|
||||
fprintln(output, " Default Address Pool:", strAddrPool.String())
|
||||
fprintln(output, " SubnetSize:", info.Swarm.Cluster.SubnetSize)
|
||||
fmt.Fprintln(dockerCli.Out(), " Default Address Pool:", strAddrPool.String())
|
||||
fmt.Fprintln(dockerCli.Out(), " SubnetSize:", info.Swarm.Cluster.SubnetSize)
|
||||
}
|
||||
if info.Swarm.Cluster.DataPathPort > 0 {
|
||||
fprintln(output, " Data Path Port:", info.Swarm.Cluster.DataPathPort)
|
||||
fmt.Fprintln(dockerCli.Out(), " Data Path Port:", info.Swarm.Cluster.DataPathPort)
|
||||
}
|
||||
fprintln(output, " Orchestration:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Orchestration:")
|
||||
|
||||
taskHistoryRetentionLimit := int64(0)
|
||||
if info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit != nil {
|
||||
taskHistoryRetentionLimit = *info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit
|
||||
}
|
||||
fprintln(output, " Task History Retention Limit:", taskHistoryRetentionLimit)
|
||||
fprintln(output, " Raft:")
|
||||
fprintln(output, " Snapshot Interval:", info.Swarm.Cluster.Spec.Raft.SnapshotInterval)
|
||||
fmt.Fprintln(dockerCli.Out(), " Task History Retention Limit:", taskHistoryRetentionLimit)
|
||||
fmt.Fprintln(dockerCli.Out(), " Raft:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Snapshot Interval:", info.Swarm.Cluster.Spec.Raft.SnapshotInterval)
|
||||
if info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots != nil {
|
||||
fprintf(output, " Number of Old Snapshots to Retain: %d\n", *info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots)
|
||||
fmt.Fprintf(dockerCli.Out(), " Number of Old Snapshots to Retain: %d\n", *info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots)
|
||||
}
|
||||
fprintln(output, " Heartbeat Tick:", info.Swarm.Cluster.Spec.Raft.HeartbeatTick)
|
||||
fprintln(output, " Election Tick:", info.Swarm.Cluster.Spec.Raft.ElectionTick)
|
||||
fprintln(output, " Dispatcher:")
|
||||
fprintln(output, " Heartbeat Period:", units.HumanDuration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod))
|
||||
fprintln(output, " CA Configuration:")
|
||||
fprintln(output, " Expiry Duration:", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry))
|
||||
fprintln(output, " Force Rotate:", info.Swarm.Cluster.Spec.CAConfig.ForceRotate)
|
||||
fmt.Fprintln(dockerCli.Out(), " Heartbeat Tick:", info.Swarm.Cluster.Spec.Raft.HeartbeatTick)
|
||||
fmt.Fprintln(dockerCli.Out(), " Election Tick:", info.Swarm.Cluster.Spec.Raft.ElectionTick)
|
||||
fmt.Fprintln(dockerCli.Out(), " Dispatcher:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Heartbeat Period:", units.HumanDuration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod))
|
||||
fmt.Fprintln(dockerCli.Out(), " CA Configuration:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Expiry Duration:", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry))
|
||||
fmt.Fprintln(dockerCli.Out(), " Force Rotate:", info.Swarm.Cluster.Spec.CAConfig.ForceRotate)
|
||||
if caCert := strings.TrimSpace(info.Swarm.Cluster.Spec.CAConfig.SigningCACert); caCert != "" {
|
||||
fprintf(output, " Signing CA Certificate: \n%s\n\n", caCert)
|
||||
fmt.Fprintf(dockerCli.Out(), " Signing CA Certificate: \n%s\n\n", caCert)
|
||||
}
|
||||
if len(info.Swarm.Cluster.Spec.CAConfig.ExternalCAs) > 0 {
|
||||
fprintln(output, " External CAs:")
|
||||
fmt.Fprintln(dockerCli.Out(), " External CAs:")
|
||||
for _, entry := range info.Swarm.Cluster.Spec.CAConfig.ExternalCAs {
|
||||
fprintf(output, " %s: %s\n", entry.Protocol, entry.URL)
|
||||
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", entry.Protocol, entry.URL)
|
||||
}
|
||||
}
|
||||
fprintln(output, " Autolock Managers:", info.Swarm.Cluster.Spec.EncryptionConfig.AutoLockManagers)
|
||||
fprintln(output, " Root Rotation In Progress:", info.Swarm.Cluster.RootRotationInProgress)
|
||||
fmt.Fprintln(dockerCli.Out(), " Autolock Managers:", info.Swarm.Cluster.Spec.EncryptionConfig.AutoLockManagers)
|
||||
fmt.Fprintln(dockerCli.Out(), " Root Rotation In Progress:", info.Swarm.Cluster.RootRotationInProgress)
|
||||
}
|
||||
fprintln(output, " Node Address:", info.Swarm.NodeAddr)
|
||||
fmt.Fprintln(dockerCli.Out(), " Node Address:", info.Swarm.NodeAddr)
|
||||
if len(info.Swarm.RemoteManagers) > 0 {
|
||||
managers := []string{}
|
||||
for _, entry := range info.Swarm.RemoteManagers {
|
||||
managers = append(managers, entry.Addr)
|
||||
}
|
||||
sort.Strings(managers)
|
||||
fprintln(output, " Manager Addresses:")
|
||||
fmt.Fprintln(dockerCli.Out(), " Manager Addresses:")
|
||||
for _, entry := range managers {
|
||||
fprintf(output, " %s\n", entry)
|
||||
fmt.Fprintf(dockerCli.Out(), " %s\n", entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printServerWarnings(stdErr io.Writer, info *info) {
|
||||
if versions.LessThan(info.ClientInfo.APIVersion, "1.42") {
|
||||
printSecurityOptionsWarnings(stdErr, *info.Info)
|
||||
func printServerWarnings(dockerCli command.Cli, info types.Info) {
|
||||
if versions.LessThan(dockerCli.Client().ClientVersion(), "1.42") {
|
||||
printSecurityOptionsWarnings(dockerCli, info)
|
||||
}
|
||||
if len(info.Warnings) > 0 {
|
||||
fprintln(stdErr, strings.Join(info.Warnings, "\n"))
|
||||
fmt.Fprintln(dockerCli.Err(), strings.Join(info.Warnings, "\n"))
|
||||
return
|
||||
}
|
||||
// daemon didn't return warnings. Fallback to old behavior
|
||||
printServerWarningsLegacy(stdErr, *info.Info)
|
||||
printServerWarningsLegacy(dockerCli, info)
|
||||
}
|
||||
|
||||
// printSecurityOptionsWarnings prints warnings based on the security options
|
||||
@@ -459,7 +447,7 @@ func printServerWarnings(stdErr io.Writer, info *info) {
|
||||
// info.Warnings. This function is used to provide backward compatibility with
|
||||
// daemons that do not provide these warnings. No new warnings should be added
|
||||
// here.
|
||||
func printSecurityOptionsWarnings(stdErr io.Writer, info types.Info) {
|
||||
func printSecurityOptionsWarnings(dockerCli command.Cli, info types.Info) {
|
||||
if info.OSType == "windows" {
|
||||
return
|
||||
}
|
||||
@@ -470,7 +458,7 @@ func printSecurityOptionsWarnings(stdErr io.Writer, info types.Info) {
|
||||
}
|
||||
for _, o := range so.Options {
|
||||
if o.Key == "profile" && o.Value != "default" && o.Value != "builtin" {
|
||||
_, _ = fmt.Fprintln(stdErr, "WARNING: You're not using the default seccomp profile")
|
||||
_, _ = fmt.Fprintln(dockerCli.Err(), "WARNING: You're not using the default seccomp profile")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -481,43 +469,43 @@ func printSecurityOptionsWarnings(stdErr io.Writer, info types.Info) {
|
||||
// info.Warnings. This function is used to provide backward compatibility with
|
||||
// daemons that do not provide these warnings. No new warnings should be added
|
||||
// here.
|
||||
func printServerWarningsLegacy(stdErr io.Writer, info types.Info) {
|
||||
func printServerWarningsLegacy(dockerCli command.Cli, info types.Info) {
|
||||
if info.OSType == "windows" {
|
||||
return
|
||||
}
|
||||
if !info.MemoryLimit {
|
||||
fprintln(stdErr, "WARNING: No memory limit support")
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support")
|
||||
}
|
||||
if !info.SwapLimit {
|
||||
fprintln(stdErr, "WARNING: No swap limit support")
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support")
|
||||
}
|
||||
if !info.OomKillDisable && info.CgroupVersion != "2" {
|
||||
fprintln(stdErr, "WARNING: No oom kill disable support")
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support")
|
||||
}
|
||||
if !info.CPUCfsQuota {
|
||||
fprintln(stdErr, "WARNING: No cpu cfs quota support")
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support")
|
||||
}
|
||||
if !info.CPUCfsPeriod {
|
||||
fprintln(stdErr, "WARNING: No cpu cfs period support")
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support")
|
||||
}
|
||||
if !info.CPUShares {
|
||||
fprintln(stdErr, "WARNING: No cpu shares support")
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support")
|
||||
}
|
||||
if !info.CPUSet {
|
||||
fprintln(stdErr, "WARNING: No cpuset support")
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support")
|
||||
}
|
||||
if !info.IPv4Forwarding {
|
||||
fprintln(stdErr, "WARNING: IPv4 forwarding is disabled")
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled")
|
||||
}
|
||||
if !info.BridgeNfIptables {
|
||||
fprintln(stdErr, "WARNING: bridge-nf-call-iptables is disabled")
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled")
|
||||
}
|
||||
if !info.BridgeNfIP6tables {
|
||||
fprintln(stdErr, "WARNING: bridge-nf-call-ip6tables is disabled")
|
||||
fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled")
|
||||
}
|
||||
}
|
||||
|
||||
func formatInfo(output io.Writer, info info, format string) error {
|
||||
func formatInfo(dockerCli command.Cli, info info, format string) error {
|
||||
if format == formatter.JSONFormatKey {
|
||||
format = formatter.JSONFormat
|
||||
}
|
||||
@@ -534,21 +522,13 @@ func formatInfo(output io.Writer, info info, format string) error {
|
||||
Status: "template parsing error: " + err.Error(),
|
||||
}
|
||||
}
|
||||
err = tmpl.Execute(output, info)
|
||||
fprintln(output)
|
||||
err = tmpl.Execute(dockerCli.Out(), info)
|
||||
dockerCli.Out().Write([]byte{'\n'})
|
||||
return err
|
||||
}
|
||||
|
||||
func fprintf(w io.Writer, format string, a ...any) {
|
||||
_, _ = fmt.Fprintf(w, format, a...)
|
||||
}
|
||||
|
||||
func fprintln(w io.Writer, a ...any) {
|
||||
_, _ = fmt.Fprintln(w, a...)
|
||||
}
|
||||
|
||||
func fprintlnNonEmpty(w io.Writer, label, value string) {
|
||||
if value != "" {
|
||||
_, _ = fmt.Fprintln(w, label, value)
|
||||
fmt.Fprintln(w, label, value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,12 +278,8 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoNoSwarm,
|
||||
ClientInfo: &clientInfo{
|
||||
clientVersion: clientVersion{
|
||||
Platform: &platformInfo{Name: "Docker Engine - Community"},
|
||||
Version: "24.0.0",
|
||||
Context: "default",
|
||||
},
|
||||
Debug: true,
|
||||
Context: "default",
|
||||
Debug: true,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-no-swarm",
|
||||
@@ -294,8 +290,8 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoNoSwarm,
|
||||
ClientInfo: &clientInfo{
|
||||
clientVersion: clientVersion{Context: "default"},
|
||||
Plugins: samplePluginsInfo,
|
||||
Context: "default",
|
||||
Plugins: samplePluginsInfo,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-plugins",
|
||||
@@ -306,7 +302,7 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
doc: "info with nil labels",
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoLabelsNil,
|
||||
ClientInfo: &clientInfo{clientVersion: clientVersion{Context: "default"}},
|
||||
ClientInfo: &clientInfo{Context: "default"},
|
||||
},
|
||||
prettyGolden: "docker-info-with-labels-nil",
|
||||
},
|
||||
@@ -314,7 +310,7 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
doc: "info with empty labels",
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoLabelsEmpty,
|
||||
ClientInfo: &clientInfo{clientVersion: clientVersion{Context: "default"}},
|
||||
ClientInfo: &clientInfo{Context: "default"},
|
||||
},
|
||||
prettyGolden: "docker-info-with-labels-empty",
|
||||
},
|
||||
@@ -323,8 +319,8 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &infoWithSwarm,
|
||||
ClientInfo: &clientInfo{
|
||||
clientVersion: clientVersion{Context: "default"},
|
||||
Debug: false,
|
||||
Context: "default",
|
||||
Debug: false,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-with-swarm",
|
||||
@@ -335,12 +331,8 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &infoWithWarningsLinux,
|
||||
ClientInfo: &clientInfo{
|
||||
clientVersion: clientVersion{
|
||||
Platform: &platformInfo{Name: "Docker Engine - Community"},
|
||||
Version: "24.0.0",
|
||||
Context: "default",
|
||||
},
|
||||
Debug: true,
|
||||
Context: "default",
|
||||
Debug: true,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-no-swarm",
|
||||
@@ -352,12 +344,8 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoDaemonWarnings,
|
||||
ClientInfo: &clientInfo{
|
||||
clientVersion: clientVersion{
|
||||
Platform: &platformInfo{Name: "Docker Engine - Community"},
|
||||
Version: "24.0.0",
|
||||
Context: "default",
|
||||
},
|
||||
Debug: true,
|
||||
Context: "default",
|
||||
Debug: true,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-no-swarm",
|
||||
@@ -388,7 +376,6 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
expectedError: "errors pretty printing info",
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
err := prettyPrintInfo(cli, tc.dockerInfo)
|
||||
@@ -406,12 +393,12 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
|
||||
if tc.jsonGolden != "" {
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
assert.NilError(t, formatInfo(cli.Out(), tc.dockerInfo, "{{json .}}"))
|
||||
assert.NilError(t, formatInfo(cli, tc.dockerInfo, "{{json .}}"))
|
||||
golden.Assert(t, cli.OutBuffer().String(), tc.jsonGolden+".json.golden")
|
||||
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
||||
|
||||
cli = test.NewFakeCli(&fakeClient{})
|
||||
assert.NilError(t, formatInfo(cli.Out(), tc.dockerInfo, "json"))
|
||||
assert.NilError(t, formatInfo(cli, tc.dockerInfo, "json"))
|
||||
golden.Assert(t, cli.OutBuffer().String(), tc.jsonGolden+".json.golden")
|
||||
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
||||
}
|
||||
@@ -419,30 +406,6 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPrettyPrintInfo(b *testing.B) {
|
||||
infoWithSwarm := sampleInfoNoSwarm
|
||||
infoWithSwarm.Swarm = sampleSwarmInfo
|
||||
|
||||
dockerInfo := info{
|
||||
Info: &infoWithSwarm,
|
||||
ClientInfo: &clientInfo{
|
||||
clientVersion: clientVersion{
|
||||
Platform: &platformInfo{Name: "Docker Engine - Community"},
|
||||
Version: "24.0.0",
|
||||
Context: "default",
|
||||
},
|
||||
Debug: true,
|
||||
},
|
||||
}
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = prettyPrintInfo(cli, dockerInfo)
|
||||
cli.ResetOutputBuffers()
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatInfo(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
doc string
|
||||
@@ -466,14 +429,13 @@ func TestFormatInfo(t *testing.T) {
|
||||
expectedError: `template: :1:2: executing "" at <.badString>: can't evaluate field badString in type system.info`,
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
info := info{
|
||||
Info: &sampleInfoNoSwarm,
|
||||
ClientInfo: &clientInfo{Debug: true},
|
||||
}
|
||||
err := formatInfo(cli.Out(), info, tc.template)
|
||||
err := formatInfo(cli, info, tc.template)
|
||||
if tc.expectedOut != "" {
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, cli.OutBuffer().String(), tc.expectedOut)
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"Client":{"Version":"18.99.5-ce","ApiVersion":"1.38","DefaultAPIVersion":"1.38","GitCommit":"deadbeef","GoVersion":"go1.10.2","Os":"linux","Arch":"amd64","BuildTime":"Wed May 30 22:21:05 2018","Context":"my-context"},"Server":{"Platform":{"Name":"Docker Enterprise Edition (EE) 2.0"},"Components":[{"Name":"Engine","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 9 23:38:38 2018","Experimental":"false","GitCommit":"64ddfa6","GoVersion":"go1.8.7","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"Universal Control Plane","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 2 21:24:07 UTC 2018","GitCommit":"4513922","GoVersion":"go1.9.4","MinApiVersion":"1.20","Os":"linux","Version":"3.0.3-tp2"}},{"Name":"Kubernetes","Version":"1.8+","Details":{"buildDate":"2018-04-26T16:51:21Z","compiler":"gc","gitCommit":"8d637aedf46b9c21dde723e29c645b9f27106fa5","gitTreeState":"clean","gitVersion":"v1.8.11-docker-8d637ae","goVersion":"go1.8.3","major":"1","minor":"8+","platform":"linux/amd64"}},{"Name":"Calico","Version":"v3.0.8","Details":{"cni":"v2.0.6","kube-controllers":"v2.0.5","node":"v3.0.8"}}],"Version":"","ApiVersion":"","GitCommit":"","GoVersion":"","Os":"","Arch":""}}
|
||||
{"Client":{"Platform":{"Name":""},"Version":"18.99.5-ce","ApiVersion":"1.38","DefaultAPIVersion":"1.38","GitCommit":"deadbeef","GoVersion":"go1.10.2","Os":"linux","Arch":"amd64","BuildTime":"Wed May 30 22:21:05 2018","Context":"my-context"},"Server":{"Platform":{"Name":"Docker Enterprise Edition (EE) 2.0"},"Components":[{"Name":"Engine","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 9 23:38:38 2018","Experimental":"false","GitCommit":"64ddfa6","GoVersion":"go1.8.7","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"Universal Control Plane","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 2 21:24:07 UTC 2018","GitCommit":"4513922","GoVersion":"go1.9.4","MinApiVersion":"1.20","Os":"linux","Version":"3.0.3-tp2"}},{"Name":"Kubernetes","Version":"1.8+","Details":{"buildDate":"2018-04-26T16:51:21Z","compiler":"gc","gitCommit":"8d637aedf46b9c21dde723e29c645b9f27106fa5","gitTreeState":"clean","gitVersion":"v1.8.11-docker-8d637ae","goVersion":"go1.8.3","major":"1","minor":"8+","platform":"linux/amd64"}},{"Name":"Calico","Version":"v3.0.8","Details":{"cni":"v2.0.6","kube-controllers":"v2.0.5","node":"v3.0.8"}}],"Version":"","ApiVersion":"","GitCommit":"","GoVersion":"","Os":"","Arch":""}}
|
||||
|
||||
@@ -41,6 +41,7 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Labels:
|
||||
provider=digitalocean
|
||||
Experimental: false
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":33,"OomKillDisable":true,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":["WARNING: No memory limit support","WARNING: No swap limit support","WARNING: No oom kill disable support","WARNING: No cpu cfs quota support","WARNING: No cpu cfs period support","WARNING: No cpu shares support","WARNING: No cpuset support","WARNING: IPv4 forwarding is disabled","WARNING: bridge-nf-call-iptables is disabled","WARNING: bridge-nf-call-ip6tables is disabled"],"ClientInfo":{"Debug":true,"Platform":{"Name":"Docker Engine - Community"},"Version":"24.0.0","Context":"default","Plugins":[],"Warnings":null}}
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":33,"OomKillDisable":true,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":["WARNING: No memory limit support","WARNING: No swap limit support","WARNING: No oom kill disable support","WARNING: No cpu cfs quota support","WARNING: No cpu cfs period support","WARNING: No cpu shares support","WARNING: No cpuset support","WARNING: IPv4 forwarding is disabled","WARNING: bridge-nf-call-iptables is disabled","WARNING: bridge-nf-call-ip6tables is disabled"],"ClientInfo":{"Debug":true,"Context":"default","Plugins":[],"Warnings":null}}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":false,"SwapLimit":false,"CpuCfsPeriod":false,"CpuCfsQuota":false,"CPUShares":false,"CPUSet":false,"PidsLimit":false,"IPv4Forwarding":false,"BridgeNfIptables":false,"BridgeNfIp6tables":false,"Debug":true,"NFd":33,"OomKillDisable":false,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":null,"ClientInfo":{"Debug":true,"Platform":{"Name":"Docker Engine - Community"},"Version":"24.0.0","Context":"default","Plugins":[],"Warnings":null}}
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":false,"SwapLimit":false,"CpuCfsPeriod":false,"CpuCfsQuota":false,"CPUShares":false,"CPUSet":false,"PidsLimit":false,"IPv4Forwarding":false,"BridgeNfIptables":false,"BridgeNfIp6tables":false,"Debug":true,"NFd":33,"OomKillDisable":false,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":null,"ClientInfo":{"Debug":true,"Context":"default","Plugins":[],"Warnings":null}}
|
||||
|
||||
+2
-2
@@ -1,5 +1,4 @@
|
||||
Client: Docker Engine - Community
|
||||
Version: 24.0.0
|
||||
Client:
|
||||
Context: default
|
||||
Debug Mode: true
|
||||
|
||||
@@ -46,6 +45,7 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Labels:
|
||||
provider=digitalocean
|
||||
Experimental: false
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":33,"OomKillDisable":true,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":null,"ClientInfo":{"Debug":true,"Platform":{"Name":"Docker Engine - Community"},"Version":"24.0.0","Context":"default","Plugins":[],"Warnings":null}}
|
||||
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":33,"OomKillDisable":true,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":null,"ClientInfo":{"Debug":true,"Context":"default","Plugins":[],"Warnings":null}}
|
||||
|
||||
@@ -51,6 +51,7 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Labels:
|
||||
provider=digitalocean
|
||||
Experimental: false
|
||||
|
||||
@@ -45,6 +45,7 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Experimental: false
|
||||
Insecure Registries:
|
||||
127.0.0.0/8
|
||||
|
||||
@@ -45,6 +45,7 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Experimental: false
|
||||
Insecure Registries:
|
||||
127.0.0.0/8
|
||||
|
||||
@@ -67,6 +67,7 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Labels:
|
||||
provider=digitalocean
|
||||
Experimental: false
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
const defaultVersionTemplate = `{{with .Client -}}
|
||||
Client:{{if ne .Platform nil}}{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}{{end}}
|
||||
Client:{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}
|
||||
Version: {{.Version}}
|
||||
API version: {{.APIVersion}}{{if ne .APIVersion .DefaultAPIVersion}} (downgraded from {{.DefaultAPIVersion}}){{end}}
|
||||
Go version: {{.GoVersion}}
|
||||
@@ -33,7 +33,7 @@ Client:{{if ne .Platform nil}}{{if ne .Platform.Name ""}} {{.Platform.Name}}{{en
|
||||
Context: {{.Context}}
|
||||
{{- end}}
|
||||
|
||||
{{- if ne .Server nil}}{{with .Server}}
|
||||
{{- if .ServerOK}}{{with .Server}}
|
||||
|
||||
Server:{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}
|
||||
{{- range $component := .Components}}
|
||||
@@ -66,45 +66,24 @@ type versionInfo struct {
|
||||
Server *types.Version
|
||||
}
|
||||
|
||||
type platformInfo struct {
|
||||
Name string `json:"Name,omitempty"`
|
||||
}
|
||||
|
||||
type clientVersion struct {
|
||||
Platform *platformInfo `json:"Platform,omitempty"`
|
||||
Version string `json:"Version,omitempty"`
|
||||
APIVersion string `json:"ApiVersion,omitempty"`
|
||||
DefaultAPIVersion string `json:"DefaultAPIVersion,omitempty"`
|
||||
GitCommit string `json:"GitCommit,omitempty"`
|
||||
GoVersion string `json:"GoVersion,omitempty"`
|
||||
Os string `json:"Os,omitempty"`
|
||||
Arch string `json:"Arch,omitempty"`
|
||||
BuildTime string `json:"BuildTime,omitempty"`
|
||||
Context string `json:"Context"`
|
||||
Platform struct{ Name string } `json:",omitempty"`
|
||||
|
||||
Version string
|
||||
APIVersion string `json:"ApiVersion"`
|
||||
DefaultAPIVersion string `json:"DefaultAPIVersion,omitempty"`
|
||||
GitCommit string
|
||||
GoVersion string
|
||||
Os string
|
||||
Arch string
|
||||
BuildTime string `json:",omitempty"`
|
||||
Context string
|
||||
}
|
||||
|
||||
// newClientVersion constructs a new clientVersion. If a dockerCLI is
|
||||
// passed as argument, additional information is included (API version),
|
||||
// which may invoke an API connection. Pass nil to omit the additional
|
||||
// information.
|
||||
func newClientVersion(contextName string, dockerCli command.Cli) clientVersion {
|
||||
v := clientVersion{
|
||||
Version: version.Version,
|
||||
GoVersion: runtime.Version(),
|
||||
GitCommit: version.GitCommit,
|
||||
BuildTime: reformatDate(version.BuildTime),
|
||||
Os: runtime.GOOS,
|
||||
Arch: arch(),
|
||||
Context: contextName,
|
||||
}
|
||||
if version.PlatformName != "" {
|
||||
v.Platform = &platformInfo{Name: version.PlatformName}
|
||||
}
|
||||
if dockerCli != nil {
|
||||
v.APIVersion = dockerCli.CurrentVersion()
|
||||
v.DefaultAPIVersion = dockerCli.DefaultVersion()
|
||||
}
|
||||
return v
|
||||
// ServerOK returns true when the client could connect to the docker server
|
||||
// and parse the information received. It returns false otherwise.
|
||||
func (v versionInfo) ServerOK() bool {
|
||||
return v.Server != nil
|
||||
}
|
||||
|
||||
// NewVersionCommand creates a new cobra.Command for `docker version`
|
||||
@@ -154,8 +133,20 @@ func runVersion(dockerCli command.Cli, opts *versionOptions) error {
|
||||
// TODO print error if kubernetes is used?
|
||||
|
||||
vd := versionInfo{
|
||||
Client: newClientVersion(dockerCli.CurrentContext(), dockerCli),
|
||||
Client: clientVersion{
|
||||
Platform: struct{ Name string }{version.PlatformName},
|
||||
Version: version.Version,
|
||||
APIVersion: dockerCli.CurrentVersion(),
|
||||
DefaultAPIVersion: dockerCli.DefaultVersion(),
|
||||
GoVersion: runtime.Version(),
|
||||
GitCommit: version.GitCommit,
|
||||
BuildTime: reformatDate(version.BuildTime),
|
||||
Os: runtime.GOOS,
|
||||
Arch: arch(),
|
||||
Context: dockerCli.CurrentContext(),
|
||||
},
|
||||
}
|
||||
|
||||
sv, err := dockerCli.Client().ServerVersion(context.Background())
|
||||
if err == nil {
|
||||
vd.Server = &sv
|
||||
|
||||
@@ -53,7 +53,7 @@ type trustKey struct {
|
||||
// This information is to be pretty printed or serialized into a machine-readable format.
|
||||
func lookupTrustInfo(cli command.Cli, remote string) ([]trustTagRow, []client.RoleWithSignatures, []data.Role, error) {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), remote)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), remote)
|
||||
if err != nil {
|
||||
return []trustTagRow{}, []client.RoleWithSignatures{}, []data.Role{}, err
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func newRevokeCommand(dockerCli command.Cli) *cobra.Command {
|
||||
|
||||
func revokeTrust(cli command.Cli, remote string, options revokeOptions) error {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), remote)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), remote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/docker/cli/cli/command/image"
|
||||
"github.com/docker/cli/cli/trust"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/theupdateframework/notary/client"
|
||||
@@ -44,7 +43,7 @@ func newSignCommand(dockerCli command.Cli) *cobra.Command {
|
||||
func runSignImage(cli command.Cli, options signOptions) error {
|
||||
imageName := options.imageName
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), imageName)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), imageName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -94,7 +93,7 @@ func runSignImage(cli command.Cli, options signOptions) error {
|
||||
fmt.Fprintf(cli.Err(), "Signing and pushing trust data for local image %s, may overwrite remote trust data\n", imageName)
|
||||
|
||||
authConfig := command.ResolveAuthConfig(ctx, cli, imgRefAndAuth.RepoInfo().Index)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ func addSigner(cli command.Cli, options signerAddOptions) error {
|
||||
|
||||
func addSignerToRepo(cli command.Cli, signerName string, repoName string, signerPubKeys []data.PublicKey) error {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), repoName)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), repoName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ func isLastSignerForReleases(roleWithSig data.Role, allRoles []client.RoleWithSi
|
||||
// The signer not being removed doesn't necessarily raise an error e.g. user choosing "No" when prompted for confirmation.
|
||||
func removeSingleSigner(cli command.Cli, repoName, signerName string, forceYes bool) (bool, error) {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), repoName)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), repoName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ func (c *fakeClient) VolumeInspect(_ context.Context, volumeID string) (volume.V
|
||||
return volume.Volume{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) VolumeList(_ context.Context, options volume.ListOptions) (volume.ListResponse, error) {
|
||||
func (c *fakeClient) VolumeList(_ context.Context, filter filters.Args) (volume.ListResponse, error) {
|
||||
if c.volumeListFunc != nil {
|
||||
return c.volumeListFunc(options.Filters)
|
||||
return c.volumeListFunc(filter)
|
||||
}
|
||||
return volume.ListResponse{}, nil
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
flagsHelper "github.com/docker/cli/cli/flags"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/fvbommel/sortorder"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -53,7 +52,7 @@ func newListCommand(dockerCli command.Cli) *cobra.Command {
|
||||
|
||||
func runList(dockerCli command.Cli, options listOptions) error {
|
||||
client := dockerCli.Client()
|
||||
volumes, err := client.VolumeList(context.Background(), volume.ListOptions{Filters: options.filter.Value()})
|
||||
volumes, err := client.VolumeList(context.Background(), options.filter.Value())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -71,9 +70,9 @@ func runList(dockerCli command.Cli, options listOptions) error {
|
||||
|
||||
// trick for filtering in place
|
||||
n := 0
|
||||
for _, vol := range volumes.Volumes {
|
||||
if vol.ClusterVolume != nil {
|
||||
volumes.Volumes[n] = vol
|
||||
for _, volume := range volumes.Volumes {
|
||||
if volume.ClusterVolume != nil {
|
||||
volumes.Volumes[n] = volume
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ func strPtr(val string) *string {
|
||||
}
|
||||
|
||||
var sampleConfig = types.Config{
|
||||
Version: "3.11",
|
||||
Version: "3.10",
|
||||
Services: []types.ServiceConfig{
|
||||
{
|
||||
Name: "foo",
|
||||
@@ -488,17 +488,6 @@ services:
|
||||
assert.Check(t, is.ErrorContains(err, "services.foo.image must be a string"))
|
||||
}
|
||||
|
||||
func TestIgnoreBuildProperties(t *testing.T) {
|
||||
_, err := loadYAML(`
|
||||
services:
|
||||
foo:
|
||||
image: busybox
|
||||
build:
|
||||
unsupported_prop: foo
|
||||
`)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestLoadWithEnvironment(t *testing.T) {
|
||||
config, err := loadYAMLWithEnv(`
|
||||
version: "3"
|
||||
|
||||
@@ -1,672 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"id": "config_schema_v3.11.json",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string",
|
||||
"default": "3.11"
|
||||
},
|
||||
|
||||
"services": {
|
||||
"id": "#/properties/services",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/service"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"networks": {
|
||||
"id": "#/properties/networks",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/network"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"volumes": {
|
||||
"id": "#/properties/volumes",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/volume"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secrets": {
|
||||
"id": "#/properties/secrets",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/secret"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"configs": {
|
||||
"id": "#/properties/configs",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"$ref": "#/definitions/config"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false,
|
||||
|
||||
"definitions": {
|
||||
|
||||
"service": {
|
||||
"id": "#/definitions/service",
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"deploy": {"$ref": "#/definitions/deployment"},
|
||||
"build": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"context": {"type": "string"},
|
||||
"dockerfile": {"type": "string"},
|
||||
"args": {"$ref": "#/definitions/list_or_dict"},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"cache_from": {"$ref": "#/definitions/list_of_strings"},
|
||||
"network": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"shm_size": {"type": ["integer", "string"]},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"cgroupns_mode": {"type": "string"},
|
||||
"cgroup_parent": {"type": "string"},
|
||||
"command": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"configs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"container_name": {"type": "string"},
|
||||
"credential_spec": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"config": {"type": "string"},
|
||||
"file": {"type": "string"},
|
||||
"registry": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"depends_on": {"$ref": "#/definitions/list_of_strings"},
|
||||
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||
"domainname": {"type": "string"},
|
||||
"entrypoint": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"env_file": {"$ref": "#/definitions/string_or_list"},
|
||||
"environment": {"$ref": "#/definitions/list_or_dict"},
|
||||
|
||||
"expose": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "number"],
|
||||
"format": "expose"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||
"hostname": {"type": "string"},
|
||||
"image": {"type": "string"},
|
||||
"init": {"type": "boolean"},
|
||||
"ipc": {"type": "string"},
|
||||
"isolation": {"type": "string"},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number", "null"]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"mac_address": {"type": "string"},
|
||||
"network_mode": {"type": "string"},
|
||||
|
||||
"networks": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/definitions/list_of_strings"},
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9._-]+$": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"aliases": {"$ref": "#/definitions/list_of_strings"},
|
||||
"ipv4_address": {"type": "string"},
|
||||
"ipv6_address": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "null"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"pid": {"type": ["string", "null"]},
|
||||
|
||||
"ports": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "number", "format": "ports"},
|
||||
{"type": "string", "format": "ports"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"target": {"type": "integer"},
|
||||
"published": {"type": "integer"},
|
||||
"protocol": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"privileged": {"type": "boolean"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"restart": {"type": "string"},
|
||||
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"shm_size": {"type": ["number", "string"]},
|
||||
"secrets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"uid": {"type": "string"},
|
||||
"gid": {"type": "string"},
|
||||
"mode": {"type": "number"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||
"stdin_open": {"type": "boolean"},
|
||||
"stop_grace_period": {"type": "string", "format": "duration"},
|
||||
"stop_signal": {"type": "string"},
|
||||
"tmpfs": {"$ref": "#/definitions/string_or_list"},
|
||||
"tty": {"type": "boolean"},
|
||||
"ulimits": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^[a-z]+$": {
|
||||
"oneOf": [
|
||||
{"type": "integer"},
|
||||
{
|
||||
"type":"object",
|
||||
"properties": {
|
||||
"hard": {"type": "integer"},
|
||||
"soft": {"type": "integer"}
|
||||
},
|
||||
"required": ["soft", "hard"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"user": {"type": "string"},
|
||||
"userns_mode": {"type": "string"},
|
||||
"volumes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["type"],
|
||||
"properties": {
|
||||
"type": {"type": "string"},
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"read_only": {"type": "boolean"},
|
||||
"consistency": {"type": "string"},
|
||||
"bind": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"propagation": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nocopy": {"type": "boolean"}
|
||||
}
|
||||
},
|
||||
"tmpfs": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"size": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
],
|
||||
"uniqueItems": true
|
||||
}
|
||||
},
|
||||
"working_dir": {"type": "string"}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"healthcheck": {
|
||||
"id": "#/definitions/healthcheck",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disable": {"type": "boolean"},
|
||||
"interval": {"type": "string", "format": "duration"},
|
||||
"retries": {"type": "number"},
|
||||
"test": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"type": "array", "items": {"type": "string"}}
|
||||
]
|
||||
},
|
||||
"timeout": {"type": "string", "format": "duration"},
|
||||
"start_period": {"type": "string", "format": "duration"}
|
||||
}
|
||||
},
|
||||
"deployment": {
|
||||
"id": "#/definitions/deployment",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"mode": {"type": "string"},
|
||||
"endpoint_mode": {"type": "string"},
|
||||
"replicas": {"type": "integer"},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"rollback_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parallelism": {"type": "integer"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"failure_action": {"type": "string"},
|
||||
"monitor": {"type": "string", "format": "duration"},
|
||||
"max_failure_ratio": {"type": "number"},
|
||||
"order": {"type": "string", "enum": [
|
||||
"start-first", "stop-first"
|
||||
]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"update_config": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parallelism": {"type": "integer"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"failure_action": {"type": "string"},
|
||||
"monitor": {"type": "string", "format": "duration"},
|
||||
"max_failure_ratio": {"type": "number"},
|
||||
"order": {"type": "string", "enum": [
|
||||
"start-first", "stop-first"
|
||||
]}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"resources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limits": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpus": {"type": "string"},
|
||||
"memory": {"type": "string"},
|
||||
"pids": {"type": "integer"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"reservations": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpus": {"type": "string"},
|
||||
"memory": {"type": "string"},
|
||||
"generic_resources": {"$ref": "#/definitions/generic_resources"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"restart_policy": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"condition": {"type": "string"},
|
||||
"delay": {"type": "string", "format": "duration"},
|
||||
"max_attempts": {"type": "integer"},
|
||||
"window": {"type": "string", "format": "duration"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"placement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"constraints": {"type": "array", "items": {"type": "string"}},
|
||||
"preferences": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"spread": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"max_replicas_per_node": {"type": "integer"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"generic_resources": {
|
||||
"id": "#/definitions/generic_resources",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"discrete_resource_spec": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kind": {"type": "string"},
|
||||
"value": {"type": "number"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
|
||||
"network": {
|
||||
"id": "#/definitions/network",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"ipam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"config": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subnet": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"internal": {"type": "boolean"},
|
||||
"attachable": {"type": "boolean"},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"volume": {
|
||||
"id": "#/definitions/volume",
|
||||
"type": ["object", "null"],
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"x-cluster-spec": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"group": {"type": "string"},
|
||||
"access_mode": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"scope": {"type": "string"},
|
||||
"sharing": {"type": "string"},
|
||||
"block_volume": {"type": "object"},
|
||||
"mount_volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fs_type": {"type": "string"},
|
||||
"mount_flags": {"type": "array", "items": {"type": "string"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"accessibility_requirements": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"requisite": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"segments": {"$ref": "#/definitions/list_or_dict"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferred": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"segments": {"$ref": "#/definitions/list_or_dict"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"capacity_range": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"required_bytes": {"type": "string"},
|
||||
"limit_bytes": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"availability": {"type": "string"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"secret": {
|
||||
"id": "#/definitions/secret",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"driver": {"type": "string"},
|
||||
"driver_opts": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number"]}
|
||||
}
|
||||
},
|
||||
"template_driver": {"type": "string"}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"config": {
|
||||
"id": "#/definitions/config",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"file": {"type": "string"},
|
||||
"external": {
|
||||
"type": ["boolean", "object"],
|
||||
"properties": {
|
||||
"name": {"type": "string"}
|
||||
}
|
||||
},
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"template_driver": {"type": "string"}
|
||||
},
|
||||
"patternProperties": {"^x-": {}},
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"string_or_list": {
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{"$ref": "#/definitions/list_of_strings"}
|
||||
]
|
||||
},
|
||||
|
||||
"list_of_strings": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
||||
"list_or_dict": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
".+": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
]
|
||||
},
|
||||
|
||||
"constraints": {
|
||||
"service": {
|
||||
"id": "#/definitions/constraints/service",
|
||||
"anyOf": [
|
||||
{"required": ["build"]},
|
||||
{"required": ["image"]}
|
||||
],
|
||||
"properties": {
|
||||
"build": {
|
||||
"required": ["context"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultVersion = "3.11"
|
||||
defaultVersion = "3.10"
|
||||
versionField = "version"
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ func init() {
|
||||
}
|
||||
|
||||
// Version returns the version of the config, defaulting to the latest "3.x"
|
||||
// version (3.11). If only the major version "3" is specified, it is used as
|
||||
// version (3.10). If only the major version "3" is specified, it is used as
|
||||
// version "3.x" and returns the default version (latest 3.x).
|
||||
func Version(config map[string]interface{}) string {
|
||||
version, ok := config[versionField]
|
||||
|
||||
@@ -99,7 +99,6 @@ func TestValidateCredentialSpecs(t *testing.T) {
|
||||
{version: "3.8"},
|
||||
{version: "3.9"},
|
||||
{version: "3.10"},
|
||||
{version: "3.11"},
|
||||
{version: "3"},
|
||||
{version: ""},
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ type ConfigFile struct {
|
||||
PruneFilters []string `json:"pruneFilters,omitempty"`
|
||||
Proxies map[string]ProxyConfig `json:"proxies,omitempty"`
|
||||
Experimental string `json:"experimental,omitempty"`
|
||||
StackOrchestrator string `json:"stackOrchestrator,omitempty"` // Deprecated: swarm is now the default orchestrator, and this option is ignored.
|
||||
CurrentContext string `json:"currentContext,omitempty"`
|
||||
CLIPluginsExtraDirs []string `json:"cliPluginsExtraDirs,omitempty"`
|
||||
Plugins map[string]map[string]string `json:"plugins,omitempty"`
|
||||
@@ -94,6 +95,9 @@ func (configFile *ConfigFile) ContainsAuth() bool {
|
||||
|
||||
// GetAuthConfigs returns the mapping of repo to auth configuration
|
||||
func (configFile *ConfigFile) GetAuthConfigs() map[string]types.AuthConfig {
|
||||
if configFile.AuthConfigs == nil {
|
||||
configFile.AuthConfigs = make(map[string]types.AuthConfig)
|
||||
}
|
||||
return configFile.AuthConfigs
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,8 @@ func (c *fileStore) GetAll() (map[string]types.AuthConfig, error) {
|
||||
|
||||
// Store saves the given credentials in the file store.
|
||||
func (c *fileStore) Store(authConfig types.AuthConfig) error {
|
||||
c.file.GetAuthConfigs()[authConfig.ServerAddress] = authConfig
|
||||
authConfigs := c.file.GetAuthConfigs()
|
||||
authConfigs[authConfig.ServerAddress] = authConfig
|
||||
return c.file.Save()
|
||||
}
|
||||
|
||||
|
||||
@@ -47,12 +47,7 @@ func getConnectionHelper(daemonURL string, sshFlags []string) (*ConnectionHelper
|
||||
}
|
||||
return &ConnectionHelper{
|
||||
Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
args := []string{"docker"}
|
||||
if sp.Path != "" {
|
||||
args = append(args, "--host", "unix://"+sp.Path)
|
||||
}
|
||||
args = append(args, "system", "dial-stdio")
|
||||
return commandconn.New(ctx, "ssh", append(sshFlags, sp.Args(args...)...)...)
|
||||
return commandconn.New(ctx, "ssh", append(sshFlags, sp.Args("docker", "system", "dial-stdio")...)...)
|
||||
},
|
||||
Host: "http://docker.example.com",
|
||||
}, nil
|
||||
|
||||
@@ -30,7 +30,9 @@ func ParseURL(daemonURL string) (*Spec, error) {
|
||||
return nil, errors.Errorf("no host specified")
|
||||
}
|
||||
sp.Port = u.Port()
|
||||
sp.Path = u.Path
|
||||
if u.Path != "" {
|
||||
return nil, errors.Errorf("extra path after the host: %q", u.Path)
|
||||
}
|
||||
if u.RawQuery != "" {
|
||||
return nil, errors.Errorf("extra query after the host: %q", u.RawQuery)
|
||||
}
|
||||
@@ -45,7 +47,6 @@ type Spec struct {
|
||||
User string
|
||||
Host string
|
||||
Port string
|
||||
Path string
|
||||
}
|
||||
|
||||
// Args returns args except "ssh" itself combined with optional additional command args
|
||||
|
||||
@@ -32,10 +32,8 @@ func TestParseURL(t *testing.T) {
|
||||
expectedError: "plain-text password is not supported",
|
||||
},
|
||||
{
|
||||
url: "ssh://foo/bar",
|
||||
expectedArgs: []string{
|
||||
"--", "foo",
|
||||
},
|
||||
url: "ssh://foo/bar",
|
||||
expectedError: `extra path after the host: "/bar"`,
|
||||
},
|
||||
{
|
||||
url: "ssh://foo?bar",
|
||||
|
||||
@@ -25,6 +25,12 @@ type EndpointMeta = context.EndpointMetaBase
|
||||
type Endpoint struct {
|
||||
EndpointMeta
|
||||
TLSData *context.TLSData
|
||||
|
||||
// Deprecated: Use of encrypted TLS private keys has been deprecated, and
|
||||
// will be removed in a future release. Golang has deprecated support for
|
||||
// legacy PEM encryption (as specified in RFC 1423), as it is insecure by
|
||||
// design (see https://go-review.googlesource.com/c/go/+/264159).
|
||||
TLSPassword string
|
||||
}
|
||||
|
||||
// WithTLSData loads TLS materials for the endpoint
|
||||
|
||||
@@ -494,6 +494,20 @@ func importEndpointTLS(tlsData *ContextTLSData, path string, data []byte) error
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsErrContextDoesNotExist checks if the given error is a "context does not exist" condition.
|
||||
//
|
||||
// Deprecated: use github.com/docker/docker/errdefs.IsNotFound()
|
||||
func IsErrContextDoesNotExist(err error) bool {
|
||||
return errdefs.IsNotFound(err)
|
||||
}
|
||||
|
||||
// IsErrTLSDataDoesNotExist checks if the given error is a "context does not exist" condition
|
||||
//
|
||||
// Deprecated: use github.com/docker/docker/errdefs.IsNotFound()
|
||||
func IsErrTLSDataDoesNotExist(err error) bool {
|
||||
return errdefs.IsNotFound(err)
|
||||
}
|
||||
|
||||
type contextdir string
|
||||
|
||||
func contextdirOf(name string) contextdir {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package flags
|
||||
|
||||
// CommonOptions are options common to both the client and the daemon.
|
||||
//
|
||||
// Deprecated: use [ClientOptions].
|
||||
type CommonOptions = ClientOptions
|
||||
|
||||
// NewCommonOptions returns a new CommonOptions
|
||||
//
|
||||
// Deprecated: use [NewClientOptions].
|
||||
var NewCommonOptions = NewClientOptions
|
||||
@@ -7,9 +7,11 @@ import (
|
||||
"strings"
|
||||
|
||||
manifesttypes "github.com/docker/cli/cli/manifest/types"
|
||||
"github.com/docker/cli/cli/trust"
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/reference"
|
||||
distributionclient "github.com/docker/distribution/registry/client"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
@@ -35,7 +37,7 @@ func NewRegistryClient(resolver AuthConfigResolver, userAgent string, insecure b
|
||||
}
|
||||
|
||||
// AuthConfigResolver returns Auth Configuration for an index
|
||||
type AuthConfigResolver func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig
|
||||
type AuthConfigResolver func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig
|
||||
|
||||
// PutManifestOptions is the data sent to push a manifest
|
||||
type PutManifestOptions struct {
|
||||
@@ -77,6 +79,7 @@ func (c *client) MountBlob(ctx context.Context, sourceRef reference.Canonical, t
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoEndpoint.actions = trust.ActionsPushAndPull
|
||||
repo, err := c.getRepositoryForReference(ctx, targetRef, repoEndpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -102,6 +105,7 @@ func (c *client) PutManifest(ctx context.Context, ref reference.Named, manifest
|
||||
return digest.Digest(""), err
|
||||
}
|
||||
|
||||
repoEndpoint.actions = trust.ActionsPushAndPull
|
||||
repo, err := c.getRepositoryForReference(ctx, ref, repoEndpoint)
|
||||
if err != nil {
|
||||
return digest.Digest(""), err
|
||||
@@ -151,7 +155,9 @@ func (c *client) getHTTPTransportForRepoEndpoint(ctx context.Context, repoEndpoi
|
||||
c.authConfigResolver(ctx, repoEndpoint.info.Index),
|
||||
repoEndpoint.endpoint,
|
||||
repoEndpoint.Name(),
|
||||
c.userAgent)
|
||||
c.userAgent,
|
||||
repoEndpoint.actions,
|
||||
)
|
||||
return httpTransport, errors.Wrap(err, "failed to configure transport")
|
||||
}
|
||||
|
||||
|
||||
@@ -6,10 +6,11 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/cli/trust"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/distribution/registry/client/auth"
|
||||
"github.com/docker/distribution/registry/client/transport"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
authtypes "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -17,6 +18,7 @@ import (
|
||||
type repositoryEndpoint struct {
|
||||
info *registry.RepositoryInfo
|
||||
endpoint registry.APIEndpoint
|
||||
actions []string
|
||||
}
|
||||
|
||||
// Name returns the repository name
|
||||
@@ -74,7 +76,7 @@ func getDefaultEndpointFromRepoInfo(repoInfo *registry.RepositoryInfo) (registry
|
||||
}
|
||||
|
||||
// getHTTPTransport builds a transport for use in communicating with a registry
|
||||
func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.APIEndpoint, repoName string, userAgent string) (http.RoundTripper, error) {
|
||||
func getHTTPTransport(authConfig authtypes.AuthConfig, endpoint registry.APIEndpoint, repoName, userAgent string, actions []string) (http.RoundTripper, error) {
|
||||
// get the http transport, this will be used in a client to upload manifest
|
||||
base := &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
@@ -98,8 +100,11 @@ func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.API
|
||||
passThruTokenHandler := &existingTokenHandler{token: authConfig.RegistryToken}
|
||||
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, passThruTokenHandler))
|
||||
} else {
|
||||
if len(actions) == 0 {
|
||||
actions = trust.ActionsPullOnly
|
||||
}
|
||||
creds := registry.NewStaticCredentialStore(&authConfig)
|
||||
tokenHandler := auth.NewTokenHandler(authTransport, creds, repoName, "push", "pull")
|
||||
tokenHandler := auth.NewTokenHandler(authTransport, creds, repoName, actions...)
|
||||
basicHandler := auth.NewBasicHandler(creds)
|
||||
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler))
|
||||
}
|
||||
|
||||
+11
-16
@@ -9,42 +9,38 @@ import (
|
||||
"github.com/moby/term"
|
||||
)
|
||||
|
||||
// In is an input stream to read user input. It implements [io.ReadCloser]
|
||||
// with additional utilities, such as putting the terminal in raw mode.
|
||||
// In is an input stream used by the DockerCli to read user input
|
||||
type In struct {
|
||||
commonStream
|
||||
in io.ReadCloser
|
||||
}
|
||||
|
||||
// Read implements the [io.Reader] interface.
|
||||
func (i *In) Read(p []byte) (int, error) {
|
||||
return i.in.Read(p)
|
||||
}
|
||||
|
||||
// Close implements the [io.Closer] interface.
|
||||
// Close implements the Closer interface
|
||||
func (i *In) Close() error {
|
||||
return i.in.Close()
|
||||
}
|
||||
|
||||
// SetRawTerminal sets raw mode on the input terminal. It is a no-op if In
|
||||
// is not a TTY, or if the "NORAW" environment variable is set to a non-empty
|
||||
// value.
|
||||
// SetRawTerminal sets raw mode on the input terminal
|
||||
func (i *In) SetRawTerminal() (err error) {
|
||||
if !i.isTerminal || os.Getenv("NORAW") != "" {
|
||||
if os.Getenv("NORAW") != "" || !i.commonStream.isTerminal {
|
||||
return nil
|
||||
}
|
||||
i.state, err = term.SetRawTerminal(i.fd)
|
||||
i.commonStream.state, err = term.SetRawTerminal(i.commonStream.fd)
|
||||
return err
|
||||
}
|
||||
|
||||
// CheckTty checks if we are trying to attach to a container TTY
|
||||
// from a non-TTY client input stream, and if so, returns an error.
|
||||
// CheckTty checks if we are trying to attach to a container tty
|
||||
// from a non-tty client input stream, and if so, returns an error.
|
||||
func (i *In) CheckTty(attachStdin, ttyMode bool) error {
|
||||
// In order to attach to a container tty, input stream for the client must
|
||||
// be a tty itself: redirecting or piping the client standard input is
|
||||
// incompatible with `docker run -t`, `docker exec -t` or `docker attach`.
|
||||
if ttyMode && attachStdin && !i.isTerminal {
|
||||
const eText = "the input device is not a TTY"
|
||||
eText := "the input device is not a TTY"
|
||||
if runtime.GOOS == "windows" {
|
||||
return errors.New(eText + ". If you are using mintty, try prefixing the command with 'winpty'")
|
||||
}
|
||||
@@ -53,9 +49,8 @@ func (i *In) CheckTty(attachStdin, ttyMode bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewIn returns a new [In] from an [io.ReadCloser].
|
||||
// NewIn returns a new In object from a ReadCloser
|
||||
func NewIn(in io.ReadCloser) *In {
|
||||
i := &In{in: in}
|
||||
i.fd, i.isTerminal = term.GetFdInfo(in)
|
||||
return i
|
||||
fd, isTerminal := term.GetFdInfo(in)
|
||||
return &In{commonStream: commonStream{fd: fd, isTerminal: isTerminal}, in: in}
|
||||
}
|
||||
|
||||
+11
-19
@@ -8,9 +8,8 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Out is an output stream to write normal program output. It implements
|
||||
// an [io.Writer], with additional utilities for detecting whether a terminal
|
||||
// is connected, getting the TTY size, and putting the terminal in raw mode.
|
||||
// Out is an output stream used by the DockerCli to write normal program
|
||||
// output.
|
||||
type Out struct {
|
||||
commonStream
|
||||
out io.Writer
|
||||
@@ -20,29 +19,23 @@ func (o *Out) Write(p []byte) (int, error) {
|
||||
return o.out.Write(p)
|
||||
}
|
||||
|
||||
// SetRawTerminal puts the output of the terminal connected to the stream
|
||||
// into raw mode.
|
||||
//
|
||||
// On UNIX, this does nothing. On Windows, it disables LF -> CRLF/ translation.
|
||||
// It is a no-op if Out is not a TTY, or if the "NORAW" environment variable is
|
||||
// set to a non-empty value.
|
||||
// SetRawTerminal sets raw mode on the input terminal
|
||||
func (o *Out) SetRawTerminal() (err error) {
|
||||
if !o.isTerminal || os.Getenv("NORAW") != "" {
|
||||
if os.Getenv("NORAW") != "" || !o.commonStream.isTerminal {
|
||||
return nil
|
||||
}
|
||||
o.state, err = term.SetRawTerminalOutput(o.fd)
|
||||
o.commonStream.state, err = term.SetRawTerminalOutput(o.commonStream.fd)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetTtySize returns the height and width in characters of the TTY, or
|
||||
// zero for both if no TTY is connected.
|
||||
func (o *Out) GetTtySize() (height uint, width uint) {
|
||||
// GetTtySize returns the height and width in characters of the tty
|
||||
func (o *Out) GetTtySize() (uint, uint) {
|
||||
if !o.isTerminal {
|
||||
return 0, 0
|
||||
}
|
||||
ws, err := term.GetWinsize(o.fd)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Debug("Error getting TTY size")
|
||||
logrus.Debugf("Error getting size: %s", err)
|
||||
if ws == nil {
|
||||
return 0, 0
|
||||
}
|
||||
@@ -50,9 +43,8 @@ func (o *Out) GetTtySize() (height uint, width uint) {
|
||||
return uint(ws.Height), uint(ws.Width)
|
||||
}
|
||||
|
||||
// NewOut returns a new [Out] from an [io.Writer].
|
||||
// NewOut returns a new Out object from a Writer
|
||||
func NewOut(out io.Writer) *Out {
|
||||
o := &Out{out: out}
|
||||
o.fd, o.isTerminal = term.GetFdInfo(out)
|
||||
return o
|
||||
fd, isTerminal := term.GetFdInfo(out)
|
||||
return &Out{commonStream: commonStream{fd: fd, isTerminal: isTerminal}, out: out}
|
||||
}
|
||||
|
||||
@@ -4,32 +4,31 @@ import (
|
||||
"github.com/moby/term"
|
||||
)
|
||||
|
||||
// commonStream is an input stream used by the DockerCli to read user input
|
||||
type commonStream struct {
|
||||
fd uintptr
|
||||
isTerminal bool
|
||||
state *term.State
|
||||
}
|
||||
|
||||
// FD returns the file descriptor number for this stream.
|
||||
// FD returns the file descriptor number for this stream
|
||||
func (s *commonStream) FD() uintptr {
|
||||
return s.fd
|
||||
}
|
||||
|
||||
// IsTerminal returns true if this stream is connected to a terminal.
|
||||
// IsTerminal returns true if this stream is connected to a terminal
|
||||
func (s *commonStream) IsTerminal() bool {
|
||||
return s.isTerminal
|
||||
}
|
||||
|
||||
// RestoreTerminal restores normal mode to the terminal.
|
||||
// RestoreTerminal restores normal mode to the terminal
|
||||
func (s *commonStream) RestoreTerminal() {
|
||||
if s.state != nil {
|
||||
_ = term.RestoreTerminal(s.fd, s.state)
|
||||
term.RestoreTerminal(s.fd, s.state)
|
||||
}
|
||||
}
|
||||
|
||||
// SetIsTerminal overrides whether a terminal is connected. It is used to
|
||||
// override this property in unit-tests, and should not be depended on for
|
||||
// other purposes.
|
||||
// SetIsTerminal sets the boolean used for isTerminal
|
||||
func (s *commonStream) SetIsTerminal(isTerminal bool) {
|
||||
s.isTerminal = isTerminal
|
||||
}
|
||||
|
||||
+15
-8
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/docker/distribution/registry/client/auth"
|
||||
"github.com/docker/distribution/registry/client/auth/challenge"
|
||||
"github.com/docker/distribution/registry/client/transport"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
@@ -78,7 +79,7 @@ func Server(index *registrytypes.IndexInfo) (string, error) {
|
||||
}
|
||||
|
||||
type simpleCredentialStore struct {
|
||||
auth registrytypes.AuthConfig
|
||||
auth types.AuthConfig
|
||||
}
|
||||
|
||||
func (scs simpleCredentialStore) Basic(*url.URL) (string, string) {
|
||||
@@ -94,7 +95,7 @@ func (scs simpleCredentialStore) SetRefreshToken(*url.URL, string, string) {}
|
||||
// GetNotaryRepository returns a NotaryRepository which stores all the
|
||||
// information needed to operate on a notary repository.
|
||||
// It creates an HTTP transport providing authentication support.
|
||||
func GetNotaryRepository(in io.Reader, out io.Writer, userAgent string, repoInfo *registry.RepositoryInfo, authConfig *registrytypes.AuthConfig, actions ...string) (client.Repository, error) {
|
||||
func GetNotaryRepository(in io.Reader, out io.Writer, userAgent string, repoInfo *registry.RepositoryInfo, authConfig *types.AuthConfig, actions ...string) (client.Repository, error) {
|
||||
server, err := Server(repoInfo.Index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -158,7 +159,7 @@ func GetNotaryRepository(in io.Reader, out io.Writer, userAgent string, repoInfo
|
||||
scope := auth.RepositoryScope{
|
||||
Repository: repoInfo.Name.Name(),
|
||||
Actions: actions,
|
||||
Class: repoInfo.Class, // TODO(thaJeztah): Class is no longer needed for plugins and can likely be removed; see https://github.com/docker/cli/pull/4114#discussion_r1145430825
|
||||
Class: repoInfo.Class,
|
||||
}
|
||||
creds := simpleCredentialStore{auth: *authConfig}
|
||||
tokenHandlerOptions := auth.TokenHandlerOptions{
|
||||
@@ -290,7 +291,7 @@ func GetSignableRoles(repo client.Repository, target *client.Target) ([]data.Rol
|
||||
// ImageRefAndAuth contains all reference information and the auth config for an image request
|
||||
type ImageRefAndAuth struct {
|
||||
original string
|
||||
authConfig *registrytypes.AuthConfig
|
||||
authConfig *types.AuthConfig
|
||||
reference reference.Named
|
||||
repoInfo *registry.RepositoryInfo
|
||||
tag string
|
||||
@@ -299,8 +300,8 @@ type ImageRefAndAuth struct {
|
||||
|
||||
// GetImageReferencesAndAuth retrieves the necessary reference and auth information for an image name
|
||||
// as an ImageRefAndAuth struct
|
||||
func GetImageReferencesAndAuth(ctx context.Context,
|
||||
authResolver func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig,
|
||||
func GetImageReferencesAndAuth(ctx context.Context, rs registry.Service,
|
||||
authResolver func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig,
|
||||
imgName string,
|
||||
) (ImageRefAndAuth, error) {
|
||||
ref, err := reference.ParseNormalizedNamed(imgName)
|
||||
@@ -309,7 +310,13 @@ func GetImageReferencesAndAuth(ctx context.Context,
|
||||
}
|
||||
|
||||
// Resolve the Repository name from fqn to RepositoryInfo
|
||||
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
||||
var repoInfo *registry.RepositoryInfo
|
||||
if rs != nil {
|
||||
repoInfo, err = rs.ResolveRepository(ref)
|
||||
} else {
|
||||
repoInfo, err = registry.ParseRepositoryInfo(ref)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return ImageRefAndAuth{}, err
|
||||
}
|
||||
@@ -348,7 +355,7 @@ func getDigest(ref reference.Named) digest.Digest {
|
||||
}
|
||||
|
||||
// AuthConfig returns the auth information (username, etc) for a given ImageRefAndAuth
|
||||
func (imgRefAuth *ImageRefAndAuth) AuthConfig() *registrytypes.AuthConfig {
|
||||
func (imgRefAuth *ImageRefAndAuth) AuthConfig() *types.AuthConfig {
|
||||
return imgRefAuth.authConfig
|
||||
}
|
||||
|
||||
|
||||
+11
-3
@@ -402,14 +402,22 @@ func areFlagsSupported(cmd *cobra.Command, details versionDetails) error {
|
||||
errs := []string{}
|
||||
|
||||
cmd.Flags().VisitAll(func(f *pflag.Flag) {
|
||||
if !f.Changed {
|
||||
if !f.Changed || len(f.Annotations) == 0 {
|
||||
return
|
||||
}
|
||||
if !isVersionSupported(f, details.CurrentVersion()) {
|
||||
// Important: in the code below, calls to "details.CurrentVersion()" and
|
||||
// "details.ServerInfo()" are deliberately executed inline to make them
|
||||
// be executed "lazily". This is to prevent making a connection with the
|
||||
// daemon to perform a "ping" (even for flags that do not require a
|
||||
// daemon connection).
|
||||
//
|
||||
// See commit b39739123b845f872549e91be184cc583f5b387c for details.
|
||||
|
||||
if _, ok := f.Annotations["version"]; ok && !isVersionSupported(f, details.CurrentVersion()) {
|
||||
errs = append(errs, fmt.Sprintf(`"--%s" requires API version %s, but the Docker daemon API version is %s`, f.Name, getFlagAnnotation(f, "version"), details.CurrentVersion()))
|
||||
return
|
||||
}
|
||||
if !isOSTypeSupported(f, details.ServerInfo().OSType) {
|
||||
if _, ok := f.Annotations["ostype"]; ok && !isOSTypeSupported(f, details.ServerInfo().OSType) {
|
||||
errs = append(errs, fmt.Sprintf(
|
||||
`"--%s" is only supported on a Docker daemon running on %s, but the Docker daemon is running on %s`,
|
||||
f.Name,
|
||||
|
||||
@@ -84,13 +84,13 @@ __docker_q() {
|
||||
# precedence over the environment setting.
|
||||
__docker_configs() {
|
||||
local format
|
||||
if [ "${1-}" = "--id" ] ; then
|
||||
if [ "$1" = "--id" ] ; then
|
||||
format='{{.ID}}'
|
||||
shift
|
||||
elif [ "${1-}" = "--name" ] ; then
|
||||
elif [ "$1" = "--name" ] ; then
|
||||
format='{{.Name}}'
|
||||
shift
|
||||
elif [ "${DOCKER_COMPLETION_SHOW_CONFIG_IDS-}" = yes ] ; then
|
||||
elif [ "$DOCKER_COMPLETION_SHOW_CONFIG_IDS" = yes ] ; then
|
||||
format='{{.ID}} {{.Name}}'
|
||||
else
|
||||
format='{{.Name}}'
|
||||
@@ -120,13 +120,13 @@ __docker_complete_configs() {
|
||||
# precedence over the environment setting.
|
||||
__docker_containers() {
|
||||
local format
|
||||
if [ "${1-}" = "--id" ] ; then
|
||||
if [ "$1" = "--id" ] ; then
|
||||
format='{{.ID}}'
|
||||
shift
|
||||
elif [ "${1-}" = "--name" ] ; then
|
||||
elif [ "$1" = "--name" ] ; then
|
||||
format='{{.Names}}'
|
||||
shift
|
||||
elif [ "${DOCKER_COMPLETION_SHOW_CONTAINER_IDS-}" = yes ] ; then
|
||||
elif [ "${DOCKER_COMPLETION_SHOW_CONTAINER_IDS}" = yes ] ; then
|
||||
format='{{.ID}} {{.Names}}'
|
||||
else
|
||||
format='{{.Names}}'
|
||||
@@ -139,7 +139,7 @@ __docker_containers() {
|
||||
# Additional filters may be appended, see `__docker_containers`.
|
||||
__docker_complete_containers() {
|
||||
local current="$cur"
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@@ -191,7 +191,7 @@ __docker_complete_container_ids() {
|
||||
__docker_contexts() {
|
||||
local add=()
|
||||
while true ; do
|
||||
case "${1-}" in
|
||||
case "$1" in
|
||||
--add)
|
||||
add+=("$2")
|
||||
shift 2
|
||||
@@ -236,12 +236,12 @@ __docker_images() {
|
||||
local all
|
||||
local format
|
||||
|
||||
if [ "${DOCKER_COMPLETION_SHOW_IMAGE_IDS-}" = "all" ] ; then
|
||||
if [ "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" = "all" ] ; then
|
||||
all='--all'
|
||||
fi
|
||||
|
||||
while true ; do
|
||||
case "${1-}" in
|
||||
case "$1" in
|
||||
--repo)
|
||||
format+="$repo_format\n"
|
||||
shift
|
||||
@@ -253,7 +253,7 @@ __docker_images() {
|
||||
shift
|
||||
;;
|
||||
--id)
|
||||
if [[ ${DOCKER_COMPLETION_SHOW_IMAGE_IDS-} =~ ^(all|non-intermediate)$ ]] ; then
|
||||
if [[ $DOCKER_COMPLETION_SHOW_IMAGE_IDS =~ ^(all|non-intermediate)$ ]] ; then
|
||||
format+="$id_format\n"
|
||||
fi
|
||||
shift
|
||||
@@ -269,7 +269,7 @@ __docker_images() {
|
||||
esac
|
||||
done
|
||||
|
||||
__docker_q image ls --no-trunc --format "${format%\\n}" ${all-} "$@" | grep -v '<none>$'
|
||||
__docker_q image ls --no-trunc --format "${format%\\n}" $all "$@" | grep -v '<none>$'
|
||||
}
|
||||
|
||||
# __docker_complete_images applies completion of images based on the current value of `$cur` or
|
||||
@@ -277,7 +277,7 @@ __docker_images() {
|
||||
# See __docker_images for customization of the returned items.
|
||||
__docker_complete_images() {
|
||||
local current="$cur"
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@@ -295,13 +295,13 @@ __docker_complete_images() {
|
||||
# precedence over the environment setting.
|
||||
__docker_networks() {
|
||||
local format
|
||||
if [ "${1-}" = "--id" ] ; then
|
||||
if [ "$1" = "--id" ] ; then
|
||||
format='{{.ID}}'
|
||||
shift
|
||||
elif [ "${1-}" = "--name" ] ; then
|
||||
elif [ "$1" = "--name" ] ; then
|
||||
format='{{.Name}}'
|
||||
shift
|
||||
elif [ "${DOCKER_COMPLETION_SHOW_NETWORK_IDS-}" = yes ] ; then
|
||||
elif [ "${DOCKER_COMPLETION_SHOW_NETWORK_IDS}" = yes ] ; then
|
||||
format='{{.ID}} {{.Name}}'
|
||||
else
|
||||
format='{{.Name}}'
|
||||
@@ -314,7 +314,7 @@ __docker_networks() {
|
||||
# Additional filters may be appended, see `__docker_networks`.
|
||||
__docker_complete_networks() {
|
||||
local current="$cur"
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@@ -340,7 +340,7 @@ __docker_volumes() {
|
||||
# Additional filters may be appended, see `__docker_volumes`.
|
||||
__docker_complete_volumes() {
|
||||
local current="$cur"
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@@ -356,7 +356,7 @@ __docker_complete_volumes() {
|
||||
__docker_plugins_bundled() {
|
||||
local type add=() remove=()
|
||||
while true ; do
|
||||
case "${1-}" in
|
||||
case "$1" in
|
||||
--type)
|
||||
type="$2"
|
||||
shift 2
|
||||
@@ -390,7 +390,7 @@ __docker_plugins_bundled() {
|
||||
# `__docker_complete_plugins_installed`.
|
||||
__docker_complete_plugins_bundled() {
|
||||
local current="$cur"
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@@ -406,7 +406,7 @@ __docker_complete_plugins_bundled() {
|
||||
# For built-in pugins, see `__docker_plugins_bundled`.
|
||||
__docker_plugins_installed() {
|
||||
local format
|
||||
if [ "${DOCKER_COMPLETION_SHOW_PLUGIN_IDS-}" = yes ] ; then
|
||||
if [ "$DOCKER_COMPLETION_SHOW_PLUGIN_IDS" = yes ] ; then
|
||||
format='{{.ID}} {{.Name}}'
|
||||
else
|
||||
format='{{.Name}}'
|
||||
@@ -421,7 +421,7 @@ __docker_plugins_installed() {
|
||||
# For completion of built-in pugins, see `__docker_complete_plugins_bundled`.
|
||||
__docker_complete_plugins_installed() {
|
||||
local current="$cur"
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@@ -446,13 +446,13 @@ __docker_complete_runtimes() {
|
||||
# precedence over the environment setting.
|
||||
__docker_secrets() {
|
||||
local format
|
||||
if [ "${1-}" = "--id" ] ; then
|
||||
if [ "$1" = "--id" ] ; then
|
||||
format='{{.ID}}'
|
||||
shift
|
||||
elif [ "${1-}" = "--name" ] ; then
|
||||
elif [ "$1" = "--name" ] ; then
|
||||
format='{{.Name}}'
|
||||
shift
|
||||
elif [ "${DOCKER_COMPLETION_SHOW_SECRET_IDS-}" = yes ] ; then
|
||||
elif [ "$DOCKER_COMPLETION_SHOW_SECRET_IDS" = yes ] ; then
|
||||
format='{{.ID}} {{.Name}}'
|
||||
else
|
||||
format='{{.Name}}'
|
||||
@@ -465,7 +465,7 @@ __docker_secrets() {
|
||||
# of `$cur` or the value of the optional first option `--cur`, if given.
|
||||
__docker_complete_secrets() {
|
||||
local current="$cur"
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@@ -481,7 +481,7 @@ __docker_stacks() {
|
||||
# of `$cur` or the value of the optional first option `--cur`, if given.
|
||||
__docker_complete_stacks() {
|
||||
local current="$cur"
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@@ -499,7 +499,7 @@ __docker_complete_stacks() {
|
||||
# Completions may be added with `--add`, e.g. `--add self`.
|
||||
__docker_nodes() {
|
||||
local format
|
||||
if [ "${DOCKER_COMPLETION_SHOW_NODE_IDS-}" = yes ] ; then
|
||||
if [ "$DOCKER_COMPLETION_SHOW_NODE_IDS" = yes ] ; then
|
||||
format='{{.ID}} {{.Hostname}}'
|
||||
else
|
||||
format='{{.Hostname}}'
|
||||
@@ -508,7 +508,7 @@ __docker_nodes() {
|
||||
local add=()
|
||||
|
||||
while true ; do
|
||||
case "${1-}" in
|
||||
case "$1" in
|
||||
--id)
|
||||
format='{{.ID}}'
|
||||
shift
|
||||
@@ -535,7 +535,7 @@ __docker_nodes() {
|
||||
# Additional filters may be appended, see `__docker_nodes`.
|
||||
__docker_complete_nodes() {
|
||||
local current="$cur"
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@@ -552,12 +552,12 @@ __docker_complete_nodes() {
|
||||
# precedence over the environment setting.
|
||||
__docker_services() {
|
||||
local format='{{.Name}}' # default: service name only
|
||||
[ "${DOCKER_COMPLETION_SHOW_SERVICE_IDS-}" = yes ] && format='{{.ID}} {{.Name}}' # ID & name
|
||||
[ "${DOCKER_COMPLETION_SHOW_SERVICE_IDS}" = yes ] && format='{{.ID}} {{.Name}}' # ID & name
|
||||
|
||||
if [ "${1-}" = "--id" ] ; then
|
||||
if [ "$1" = "--id" ] ; then
|
||||
format='{{.ID}}' # IDs only
|
||||
shift
|
||||
elif [ "${1-}" = "--name" ] ; then
|
||||
elif [ "$1" = "--name" ] ; then
|
||||
format='{{.Name}}' # names only
|
||||
shift
|
||||
fi
|
||||
@@ -570,7 +570,7 @@ __docker_services() {
|
||||
# Additional filters may be appended, see `__docker_services`.
|
||||
__docker_complete_services() {
|
||||
local current="$cur"
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@@ -601,7 +601,7 @@ __docker_append_to_completions() {
|
||||
# several variables with the results.
|
||||
# The result is cached for the duration of one invocation of bash completion.
|
||||
__docker_fetch_info() {
|
||||
if [ -z "${info_fetched-}" ] ; then
|
||||
if [ -z "$info_fetched" ] ; then
|
||||
read -r server_experimental server_os <<< "$(__docker_q version -f '{{.Server.Experimental}} {{.Server.Os}}')"
|
||||
info_fetched=true
|
||||
fi
|
||||
@@ -629,7 +629,7 @@ __docker_server_os_is() {
|
||||
# you should pass a glob describing those options, e.g. "--option1|-o|--option2"
|
||||
# Use this function to restrict completions to exact positions after the argument list.
|
||||
__docker_pos_first_nonflag() {
|
||||
local argument_flags=${1-}
|
||||
local argument_flags=$1
|
||||
|
||||
local counter=$((${subcommand_pos:-${command_pos}} + 1))
|
||||
while [ "$counter" -le "$cword" ]; do
|
||||
@@ -766,7 +766,7 @@ __docker_local_interfaces() {
|
||||
command -v ip >/dev/null 2>&1 || return
|
||||
|
||||
local format
|
||||
if [ "${1-}" = "--ip-only" ] ; then
|
||||
if [ "$1" = "--ip-only" ] ; then
|
||||
format='\1'
|
||||
shift
|
||||
else
|
||||
@@ -781,7 +781,7 @@ __docker_local_interfaces() {
|
||||
# An additional value can be added to the possible completions with an `--add` argument.
|
||||
__docker_complete_local_interfaces() {
|
||||
local additional_interface
|
||||
if [ "${1-}" = "--add" ] ; then
|
||||
if [ "$1" = "--add" ] ; then
|
||||
additional_interface="$2"
|
||||
shift 2
|
||||
fi
|
||||
@@ -1125,7 +1125,7 @@ __docker_complete_ulimits() {
|
||||
sigpending
|
||||
stack
|
||||
"
|
||||
if [ "${1-}" = "--rm" ] ; then
|
||||
if [ "$1" = "--rm" ] ; then
|
||||
COMPREPLY=( $( compgen -W "$limits" -- "$cur" ) )
|
||||
else
|
||||
COMPREPLY=( $( compgen -W "$limits" -S = -- "$cur" ) )
|
||||
@@ -1142,7 +1142,10 @@ __docker_complete_user_group() {
|
||||
fi
|
||||
}
|
||||
|
||||
DOCKER_PLUGINS_PATH=$(docker info --format '{{range .ClientInfo.Plugins}}{{.Path}}:{{end}}')
|
||||
__docker_plugins_path() {
|
||||
local docker_plugins_path=$(docker info --format '{{range .ClientInfo.Plugins}}{{.Path}}:{{end}}')
|
||||
echo "${docker_plugins_path//:/ }"
|
||||
}
|
||||
|
||||
__docker_complete_plugin() {
|
||||
local path=$1
|
||||
@@ -1888,7 +1891,6 @@ _docker_container_run() {
|
||||
_docker_container_run_and_create() {
|
||||
local options_with_args="
|
||||
--add-host
|
||||
--annotation
|
||||
--attach -a
|
||||
--blkio-weight
|
||||
--blkio-weight-device
|
||||
@@ -2649,7 +2651,7 @@ _docker_daemon() {
|
||||
return
|
||||
;;
|
||||
--storage-driver|-s)
|
||||
COMPREPLY=( $( compgen -W "btrfs overlay2 vfs zfs" -- "$(echo "$cur" | tr '[:upper:]' '[:lower:]')" ) )
|
||||
COMPREPLY=( $( compgen -W "aufs btrfs overlay2 vfs zfs" -- "$(echo "$cur" | tr '[:upper:]' '[:lower:]')" ) )
|
||||
return
|
||||
;;
|
||||
--storage-opt)
|
||||
@@ -2822,7 +2824,7 @@ _docker_image_build() {
|
||||
"
|
||||
fi
|
||||
|
||||
if [ "${DOCKER_BUILDKIT-}" = "1" ] ; then
|
||||
if [ "$DOCKER_BUILDKIT" = "1" ] ; then
|
||||
options_with_args+="
|
||||
--output -o
|
||||
--progress
|
||||
@@ -3170,7 +3172,7 @@ _docker_inspect() {
|
||||
local preselected_type
|
||||
local type
|
||||
|
||||
if [ "${1-}" = "--type" ] ; then
|
||||
if [ "$1" = "--type" ] ; then
|
||||
preselected_type=yes
|
||||
type="$2"
|
||||
else
|
||||
@@ -5504,7 +5506,7 @@ _docker() {
|
||||
# Create completion functions for all registered plugins
|
||||
local known_plugin_commands=()
|
||||
local plugin_name=""
|
||||
for plugin_path in ${DOCKER_PLUGINS_PATH//:/ }; do
|
||||
for plugin_path in $(__docker_plugins_path); do
|
||||
plugin_name=$(basename "$plugin_path" | sed 's/ *$//')
|
||||
plugin_name=${plugin_name#docker-}
|
||||
plugin_name=${plugin_name%%.*}
|
||||
@@ -5517,7 +5519,7 @@ _docker() {
|
||||
)
|
||||
|
||||
local commands=(${management_commands[*]} ${top_level_commands[*]} ${known_plugin_commands[*]})
|
||||
[ -z "${DOCKER_HIDE_LEGACY_COMMANDS-}" ] && commands+=(${legacy_commands[*]})
|
||||
[ -z "$DOCKER_HIDE_LEGACY_COMMANDS" ] && commands+=(${legacy_commands[*]})
|
||||
|
||||
# These options are valid as global options for all client commands
|
||||
# and valid as command options for `docker daemon`
|
||||
|
||||
@@ -178,7 +178,6 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from cp' -l help -d 'Print u
|
||||
# create
|
||||
complete -c docker -f -n '__fish_docker_no_subcommand' -a create -d 'Create a new container'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l add-host -d 'Add a custom host-to-IP mapping (host:ip)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l annotation -d 'Add an annotation to the container (passed through to the OCI runtime)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s a -l attach -d 'Attach to STDIN, STDOUT or STDERR.'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l blkio-weight -d 'Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l blkio-weight-device -d 'Block IO weight (relative device weight)'
|
||||
@@ -454,7 +453,6 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from rmi' -a '(__fish_print_
|
||||
|
||||
# run
|
||||
complete -c docker -f -n '__fish_docker_no_subcommand' -a run -d 'Create and run a new container from an image'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l annotation -d 'Add an annotation to the container (passed through to the OCI runtime)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s a -l attach -d 'Attach to STDIN, STDOUT or STDERR.'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l add-host -d 'Add a custom host-to-IP mapping (host:ip)'
|
||||
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s c -l cpu-shares -d 'CPU shares (relative weight)'
|
||||
|
||||
@@ -602,7 +602,6 @@ __docker_container_subcommand() {
|
||||
opts_create_run=(
|
||||
"($help -a --attach)"{-a=,--attach=}"[Attach to stdin, stdout or stderr]:device:(STDIN STDOUT STDERR)"
|
||||
"($help)*--add-host=[Add a custom host-to-IP mapping]:host\:ip mapping: "
|
||||
"($help)*--annotation=[Add an annotation to the container (passed through to the OCI runtime)]:annotations: "
|
||||
"($help)*--blkio-weight-device=[Block IO (relative device weight)]:device:Block IO weight: "
|
||||
"($help)*--cap-add=[Add Linux capabilities]:capability: "
|
||||
"($help)*--cap-drop=[Drop Linux capabilities]:capability: "
|
||||
@@ -2777,7 +2776,7 @@ __docker_subcommand() {
|
||||
"($help)--raw-logs[Full timestamps without ANSI coloring]" \
|
||||
"($help)*--registry-mirror=[Preferred registry mirror]:registry mirror: " \
|
||||
"($help)--seccomp-profile=[Path to seccomp profile]:path:_files -g \"*.json\"" \
|
||||
"($help -s --storage-driver)"{-s=,--storage-driver=}"[Storage driver to use]:driver:(btrfs devicemapper overlay2 vfs zfs)" \
|
||||
"($help -s --storage-driver)"{-s=,--storage-driver=}"[Storage driver to use]:driver:(aufs btrfs devicemapper overlay overlay2 vfs zfs)" \
|
||||
"($help)--selinux-enabled[Enable selinux support]" \
|
||||
"($help)--shutdown-timeout=[Set the shutdown timeout value in seconds]:time: " \
|
||||
"($help)*--storage-opt=[Storage driver options]:storage driver options: " \
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
variable "GO_VERSION" {
|
||||
default = "1.20.4"
|
||||
default = "1.20.7"
|
||||
}
|
||||
variable "VERSION" {
|
||||
default = ""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG ALPINE_VERSION=3.17
|
||||
|
||||
FROM alpine:${ALPINE_VERSION} AS gen
|
||||
RUN apk add --no-cache bash git
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.20.4
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG GO_VERSION=1.20.7
|
||||
ARG ALPINE_VERSION=3.17
|
||||
|
||||
ARG BUILDX_VERSION=0.10.4
|
||||
ARG BUILDX_VERSION=0.11.2
|
||||
FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx
|
||||
|
||||
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS golang
|
||||
@@ -18,7 +18,7 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
&& gofumpt --version
|
||||
|
||||
FROM golang AS gotestsum
|
||||
ARG GOTESTSUM_VERSION=v1.8.2
|
||||
ARG GOTESTSUM_VERSION=v1.10.0
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=type=tmpfs,target=/go/src/ \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.20.4
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG GO_VERSION=1.20.7
|
||||
ARG ALPINE_VERSION=3.17
|
||||
ARG GOLANGCI_LINT_VERSION=v1.52.2
|
||||
|
||||
FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.20.4
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG GO_VERSION=1.20.7
|
||||
ARG ALPINE_VERSION=3.17
|
||||
ARG MODOUTDATED_VERSION=v0.8.0
|
||||
|
||||
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base
|
||||
@@ -9,7 +9,7 @@ RUN apk add --no-cache bash git rsync
|
||||
WORKDIR /src
|
||||
|
||||
FROM base AS vendored
|
||||
ENV GOPROXY=direct
|
||||
ENV GOPROXY=https://proxy.golang.org|direct
|
||||
RUN --mount=target=/context \
|
||||
--mount=target=.,type=tmpfs \
|
||||
--mount=target=/go/pkg/mod,type=cache <<EOT
|
||||
|
||||
+129
-112
@@ -48,88 +48,66 @@ The table below provides an overview of the current status of deprecated feature
|
||||
alternatives. In such cases, a warning may be printed, and users should not rely
|
||||
on this feature.
|
||||
|
||||
| Status | Feature | Deprecated | Remove |
|
||||
|------------|------------------------------------------------------------------------------------------------------------------------------------|------------|--------|
|
||||
| Deprecated | [OOM-score adjust for the daemon](#oom-score-adjust-for-the-daemon) | v24.0 | v25.0 |
|
||||
| Removed | [Buildkit build information](#buildkit-build-information) | v23.0 | v24.0 |
|
||||
| Deprecated | [Legacy builder for Linux images](#legacy-builder-for-linux-images) | v23.0 | - |
|
||||
| Deprecated | [Legacy builder fallback](#legacy-builder-fallback) | v23.0 | - |
|
||||
| Removed | [Btrfs storage driver on CentOS 7 and RHEL 7](#btrfs-storage-driver-on-centos-7-and-rhel-7) | v20.10 | v23.0 |
|
||||
| Removed | [Support for encrypted TLS private keys](#support-for-encrypted-tls-private-keys) | v20.10 | v23.0 |
|
||||
| Removed | [Kubernetes stack and context support](#kubernetes-stack-and-context-support) | v20.10 | v23.0 |
|
||||
| Deprecated | [Pulling images from non-compliant image registries](#pulling-images-from-non-compliant-image-registries) | v20.10 | - |
|
||||
| Removed | [Linux containers on Windows (LCOW)](#linux-containers-on-windows-lcow-experimental) | v20.10 | v23.0 |
|
||||
| Deprecated | [BLKIO weight options with cgroups v1](#blkio-weight-options-with-cgroups-v1) | v20.10 | - |
|
||||
| Removed | [Kernel memory limit](#kernel-memory-limit) | v20.10 | v23.0 |
|
||||
| Removed | [Classic Swarm and overlay networks using external key/value stores](#classic-swarm-and-overlay-networks-using-cluster-store) | v20.10 | v23.0 |
|
||||
| Removed | [Support for the legacy `~/.dockercfg` configuration file for authentication](#support-for-legacy-dockercfg-configuration-files) | v20.10 | v23.0 |
|
||||
| Deprecated | [CLI plugins support](#cli-plugins-support) | v20.10 | - |
|
||||
| Deprecated | [Dockerfile legacy `ENV name value` syntax](#dockerfile-legacy-env-name-value-syntax) | v20.10 | - |
|
||||
| Removed | [`docker build --stream` flag (experimental)](#docker-build---stream-flag-experimental) | v20.10 | v20.10 |
|
||||
| Deprecated | [`fluentd-async-connect` log opt](#fluentd-async-connect-log-opt) | v20.10 | - |
|
||||
| Removed | [Configuration options for experimental CLI features](#configuration-options-for-experimental-cli-features) | v19.03 | v23.0 |
|
||||
| Deprecated | [Pushing and pulling with image manifest v2 schema 1](#pushing-and-pulling-with-image-manifest-v2-schema-1) | v19.03 | v20.10 |
|
||||
| Removed | [`docker engine` subcommands](#docker-engine-subcommands) | v19.03 | v20.10 |
|
||||
| Removed | [Top-level `docker deploy` subcommand (experimental)](#top-level-docker-deploy-subcommand-experimental) | v19.03 | v20.10 |
|
||||
| Removed | [`docker stack deploy` using "dab" files (experimental)](#docker-stack-deploy-using-dab-files-experimental) | v19.03 | v20.10 |
|
||||
| Removed | [Support for the `overlay2.override_kernel_check` storage option](#support-for-the-overlay2override_kernel_check-storage-option) | v19.03 | v24.0 |
|
||||
| Removed | [AuFS storage driver](#aufs-storage-driver) | v19.03 | v24.0 |
|
||||
| Removed | [Legacy "overlay" storage driver](#legacy-overlay-storage-driver) | v18.09 | v24.0 |
|
||||
| Disabled | [Device mapper storage driver](#device-mapper-storage-driver) | v18.09 | - |
|
||||
| Removed | [Use of reserved namespaces in engine labels](#use-of-reserved-namespaces-in-engine-labels) | v18.06 | v20.10 |
|
||||
| Removed | [`--disable-legacy-registry` override daemon option](#--disable-legacy-registry-override-daemon-option) | v17.12 | v19.03 |
|
||||
| Removed | [Interacting with V1 registries](#interacting-with-v1-registries) | v17.06 | v17.12 |
|
||||
| Removed | [Asynchronous `service create` and `service update` as default](#asynchronous-service-create-and-service-update-as-default) | v17.05 | v17.10 |
|
||||
| Removed | [`-g` and `--graph` flags on `dockerd`](#-g-and---graph-flags-on-dockerd) | v17.05 | - |
|
||||
| Deprecated | [Top-level network properties in NetworkSettings](#top-level-network-properties-in-networksettings) | v1.13 | v17.12 |
|
||||
| Removed | [`filter` param for `/images/json` endpoint](#filter-param-for-imagesjson-endpoint) | v1.13 | v20.10 |
|
||||
| Removed | [`repository:shortid` image references](#repositoryshortid-image-references) | v1.13 | v17.12 |
|
||||
| Removed | [`docker daemon` subcommand](#docker-daemon-subcommand) | v1.13 | v17.12 |
|
||||
| Removed | [Duplicate keys with conflicting values in engine labels](#duplicate-keys-with-conflicting-values-in-engine-labels) | v1.13 | v17.12 |
|
||||
| Deprecated | [`MAINTAINER` in Dockerfile](#maintainer-in-dockerfile) | v1.13 | - |
|
||||
| Deprecated | [API calls without a version](#api-calls-without-a-version) | v1.13 | v17.12 |
|
||||
| Removed | [Backing filesystem without `d_type` support for overlay/overlay2](#backing-filesystem-without-d_type-support-for-overlayoverlay2) | v1.13 | v17.12 |
|
||||
| Removed | [`--automated` and `--stars` flags on `docker search`](#--automated-and---stars-flags-on-docker-search) | v1.12 | v20.10 |
|
||||
| Deprecated | [`-h` shorthand for `--help`](#-h-shorthand-for---help) | v1.12 | v17.09 |
|
||||
| Removed | [`-e` and `--email` flags on `docker login`](#-e-and---email-flags-on-docker-login) | v1.11 | v17.06 |
|
||||
| Deprecated | [Separator (`:`) of `--security-opt` flag on `docker run`](#separator--of---security-opt-flag-on-docker-run) | v1.11 | v17.06 |
|
||||
| Deprecated | [Ambiguous event fields in API](#ambiguous-event-fields-in-api) | v1.10 | - |
|
||||
| Removed | [`-f` flag on `docker tag`](#-f-flag-on-docker-tag) | v1.10 | v1.12 |
|
||||
| Removed | [HostConfig at API container start](#hostconfig-at-api-container-start) | v1.10 | v1.12 |
|
||||
| Removed | [`--before` and `--since` flags on `docker ps`](#--before-and---since-flags-on-docker-ps) | v1.10 | v1.12 |
|
||||
| Removed | [Driver-specific log tags](#driver-specific-log-tags) | v1.9 | v1.12 |
|
||||
| Removed | [Docker Content Trust `ENV` passphrase variables name change](#docker-content-trust-env-passphrase-variables-name-change) | v1.9 | v1.12 |
|
||||
| Removed | [`/containers/(id or name)/copy` endpoint](#containersid-or-namecopy-endpoint) | v1.8 | v1.12 |
|
||||
| Removed | [LXC built-in exec driver](#lxc-built-in-exec-driver) | v1.8 | v1.10 |
|
||||
| Removed | [Old Command Line Options](#old-command-line-options) | v1.8 | v1.10 |
|
||||
| Removed | [`--api-enable-cors` flag on `dockerd`](#--api-enable-cors-flag-on-dockerd) | v1.6 | v17.09 |
|
||||
| Removed | [`--run` flag on `docker commit`](#--run-flag-on-docker-commit) | v0.10 | v1.13 |
|
||||
| Removed | [Three arguments form in `docker import`](#three-arguments-form-in-docker-import) | v0.6.7 | v1.12 |
|
||||
|
||||
### OOM-score adjust for the daemon
|
||||
|
||||
**Deprecated in Release: v24.0**
|
||||
**Target For Removal In Release: v25.0**
|
||||
|
||||
The `oom-score-adjust` option was added to prevent the daemon from being
|
||||
OOM-killed before other processes. This option was mostly added as a
|
||||
convenience, as running the daemon as a systemd unit was not yet common.
|
||||
|
||||
Having the daemon set its own limits is not best-practice, and something
|
||||
better handled by the process-manager starting the daemon.
|
||||
|
||||
Docker v20.10 and newer no longer adjust the daemon's OOM score by default,
|
||||
instead setting the OOM-score to the systemd unit (OOMScoreAdjust) that's
|
||||
shipped with the packages.
|
||||
|
||||
Users currently depending on this feature are recommended to adjust the
|
||||
daemon's OOM score using systemd or through other means, when starting
|
||||
the daemon.
|
||||
| Status | Feature | Deprecated | Remove |
|
||||
|------------|------------------------------------------------------------------------------------------------------------------------------------|------------|---------|
|
||||
| Deprecated | [Buildkit build information](#buildkit-build-information) | v23.0.0 | v24.0.0 |
|
||||
| Deprecated | [Legacy builder for Linux images](#legacy-builder-for-linux-images) | v23.0.0 | - |
|
||||
| Deprecated | [Legacy builder fallback](#legacy-builder-fallback) | v23.0.0 | - |
|
||||
| Removed | [Btrfs storage driver on CentOS 7 and RHEL 7](#btrfs-storage-driver-on-centos-7-and-rhel-7) | v20.10 | v23.0.0 |
|
||||
| Removed | [Support for encrypted TLS private keys](#support-for-encrypted-tls-private-keys) | v20.10 | v23.0.0 |
|
||||
| Removed | [Kubernetes stack and context support](#kubernetes-stack-and-context-support) | v20.10 | v23.0.0 |
|
||||
| Deprecated | [Pulling images from non-compliant image registries](#pulling-images-from-non-compliant-image-registries) | v20.10 | - |
|
||||
| Removed | [Linux containers on Windows (LCOW)](#linux-containers-on-windows-lcow-experimental) | v20.10 | v23.0.0 |
|
||||
| Deprecated | [BLKIO weight options with cgroups v1](#blkio-weight-options-with-cgroups-v1) | v20.10 | - |
|
||||
| Removed | [Kernel memory limit](#kernel-memory-limit) | v20.10 | v23.0.0 |
|
||||
| Removed | [Classic Swarm and overlay networks using external key/value stores](#classic-swarm-and-overlay-networks-using-cluster-store) | v20.10 | v23.0.0 |
|
||||
| Removed | [Support for the legacy `~/.dockercfg` configuration file for authentication](#support-for-legacy-dockercfg-configuration-files) | v20.10 | v23.0.0 |
|
||||
| Deprecated | [CLI plugins support](#cli-plugins-support) | v20.10 | - |
|
||||
| Deprecated | [Dockerfile legacy `ENV name value` syntax](#dockerfile-legacy-env-name-value-syntax) | v20.10 | - |
|
||||
| Removed | [`docker build --stream` flag (experimental)](#docker-build---stream-flag-experimental) | v20.10 | v20.10 |
|
||||
| Deprecated | [`fluentd-async-connect` log opt](#fluentd-async-connect-log-opt) | v20.10 | - |
|
||||
| Removed | [Configuration options for experimental CLI features](#configuration-options-for-experimental-cli-features) | v19.03 | v23.0.0 |
|
||||
| Deprecated | [Pushing and pulling with image manifest v2 schema 1](#pushing-and-pulling-with-image-manifest-v2-schema-1) | v19.03 | v20.10 |
|
||||
| Removed | [`docker engine` subcommands](#docker-engine-subcommands) | v19.03 | v20.10 |
|
||||
| Removed | [Top-level `docker deploy` subcommand (experimental)](#top-level-docker-deploy-subcommand-experimental) | v19.03 | v20.10 |
|
||||
| Removed | [`docker stack deploy` using "dab" files (experimental)](#docker-stack-deploy-using-dab-files-experimental) | v19.03 | v20.10 |
|
||||
| Disabled | [Support for the `overlay2.override_kernel_check` storage option](#support-for-the-overlay2override_kernel_check-storage-option) | v19.03 | - |
|
||||
| Disabled | [AuFS storage driver](#aufs-storage-driver) | v19.03 | - |
|
||||
| Disabled | [Legacy "overlay" storage driver](#legacy-overlay-storage-driver) | v18.09 | - |
|
||||
| Disabled | [Device mapper storage driver](#device-mapper-storage-driver) | v18.09 | - |
|
||||
| Removed | [Use of reserved namespaces in engine labels](#use-of-reserved-namespaces-in-engine-labels) | v18.06 | v20.10 |
|
||||
| Removed | [`--disable-legacy-registry` override daemon option](#--disable-legacy-registry-override-daemon-option) | v17.12 | v19.03 |
|
||||
| Removed | [Interacting with V1 registries](#interacting-with-v1-registries) | v17.06 | v17.12 |
|
||||
| Removed | [Asynchronous `service create` and `service update` as default](#asynchronous-service-create-and-service-update-as-default) | v17.05 | v17.10 |
|
||||
| Removed | [`-g` and `--graph` flags on `dockerd`](#-g-and---graph-flags-on-dockerd) | v17.05 | - |
|
||||
| Deprecated | [Top-level network properties in NetworkSettings](#top-level-network-properties-in-networksettings) | v1.13 | v17.12 |
|
||||
| Removed | [`filter` param for `/images/json` endpoint](#filter-param-for-imagesjson-endpoint) | v1.13 | v20.10 |
|
||||
| Removed | [`repository:shortid` image references](#repositoryshortid-image-references) | v1.13 | v17.12 |
|
||||
| Removed | [`docker daemon` subcommand](#docker-daemon-subcommand) | v1.13 | v17.12 |
|
||||
| Removed | [Duplicate keys with conflicting values in engine labels](#duplicate-keys-with-conflicting-values-in-engine-labels) | v1.13 | v17.12 |
|
||||
| Deprecated | [`MAINTAINER` in Dockerfile](#maintainer-in-dockerfile) | v1.13 | - |
|
||||
| Deprecated | [API calls without a version](#api-calls-without-a-version) | v1.13 | v17.12 |
|
||||
| Removed | [Backing filesystem without `d_type` support for overlay/overlay2](#backing-filesystem-without-d_type-support-for-overlayoverlay2) | v1.13 | v17.12 |
|
||||
| Removed | [`--automated` and `--stars` flags on `docker search`](#--automated-and---stars-flags-on-docker-search) | v1.12 | v20.10 |
|
||||
| Deprecated | [`-h` shorthand for `--help`](#-h-shorthand-for---help) | v1.12 | v17.09 |
|
||||
| Removed | [`-e` and `--email` flags on `docker login`](#-e-and---email-flags-on-docker-login) | v1.11 | v17.06 |
|
||||
| Deprecated | [Separator (`:`) of `--security-opt` flag on `docker run`](#separator--of---security-opt-flag-on-docker-run) | v1.11 | v17.06 |
|
||||
| Deprecated | [Ambiguous event fields in API](#ambiguous-event-fields-in-api) | v1.10 | - |
|
||||
| Removed | [`-f` flag on `docker tag`](#-f-flag-on-docker-tag) | v1.10 | v1.12 |
|
||||
| Removed | [HostConfig at API container start](#hostconfig-at-api-container-start) | v1.10 | v1.12 |
|
||||
| Removed | [`--before` and `--since` flags on `docker ps`](#--before-and---since-flags-on-docker-ps) | v1.10 | v1.12 |
|
||||
| Removed | [Driver-specific log tags](#driver-specific-log-tags) | v1.9 | v1.12 |
|
||||
| Removed | [Docker Content Trust `ENV` passphrase variables name change](#docker-content-trust-env-passphrase-variables-name-change) | v1.9 | v1.12 |
|
||||
| Removed | [`/containers/(id or name)/copy` endpoint](#containersid-or-namecopy-endpoint) | v1.8 | v1.12 |
|
||||
| Removed | [LXC built-in exec driver](#lxc-built-in-exec-driver) | v1.8 | v1.10 |
|
||||
| Removed | [Old Command Line Options](#old-command-line-options) | v1.8 | v1.10 |
|
||||
| Removed | [`--api-enable-cors` flag on `dockerd`](#--api-enable-cors-flag-on-dockerd) | v1.6 | v17.09 |
|
||||
| Removed | [`--run` flag on `docker commit`](#--run-flag-on-docker-commit) | v0.10 | v1.13 |
|
||||
| Removed | [Three arguments form in `docker import`](#three-arguments-form-in-docker-import) | v0.6.7 | v1.12 |
|
||||
|
||||
### Buildkit build information
|
||||
|
||||
**Deprecated in Release: v23.0**
|
||||
**Removed in Release: v24.0**
|
||||
**Deprecated in Release: v23.0.0**
|
||||
|
||||
[Build information](https://github.com/moby/buildkit/blob/v0.11/docs/buildinfo.md)
|
||||
structures have been introduced in [BuildKit v0.10.0](https://github.com/moby/buildkit/releases/tag/v0.10.0)
|
||||
@@ -140,9 +118,9 @@ information is also embedded into the image configuration if one is generated.
|
||||
|
||||
### Legacy builder for Linux images
|
||||
|
||||
**Deprecated in Release: v23.0**
|
||||
**Deprecated in Release: v23.0.0**
|
||||
|
||||
Docker v23.0 now uses BuildKit by default to build Linux images, and uses the
|
||||
Docker v23.0.0 now uses BuildKit by default to build Linux images, and uses the
|
||||
[Buildx](https://docs.docker.com/buildx/working-with-buildx/) CLI component for
|
||||
`docker build`. With this change, `docker build` now exposes all advanced features
|
||||
that BuildKit provides and which were previously only available through the
|
||||
@@ -171,14 +149,14 @@ you to report issues in the [BuildKit issue tracker on GitHub](https://github.co
|
||||
|
||||
### Legacy builder fallback
|
||||
|
||||
**Deprecated in Release: v23.0**
|
||||
**Deprecated in Release: v23.0.0**
|
||||
|
||||
[Docker v23.0 now uses BuildKit by default to build Linux images](#legacy-builder-for-linux-images),
|
||||
[Docker v23.0.0 now uses BuildKit by default to build Linux images](#legacy-builder-for-linux-images),
|
||||
which requires the Buildx component to build images with BuildKit. There may be
|
||||
situations where the Buildx component is not available, and BuildKit cannot be
|
||||
used.
|
||||
|
||||
To provide a smooth transition to BuildKit as the default builder, Docker v23.0
|
||||
To provide a smooth transition to BuildKit as the default builder, Docker v23.0.0
|
||||
has an automatic fallback for some situations, or produces an error to assist
|
||||
users to resolve the problem.
|
||||
|
||||
@@ -217,7 +195,7 @@ be possible in a future release.
|
||||
|
||||
### Btrfs storage driver on CentOS 7 and RHEL 7
|
||||
|
||||
**Removed in Release: v23.0**
|
||||
**Removed in Release: v23.0.0**
|
||||
|
||||
The `btrfs` storage driver on CentOS and RHEL was provided as a technology preview
|
||||
by CentOS and RHEL, but has been deprecated since the [Red Hat Enterprise Linux 7.4 release](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/storage_administration_guide/ch-btrfs),
|
||||
@@ -231,7 +209,7 @@ of Docker will no longer provide this driver.
|
||||
|
||||
**Deprecated in Release: v20.10**
|
||||
|
||||
**Removed in Release: v23.0**
|
||||
**Removed in Release: v23.0.0**
|
||||
|
||||
Use of encrypted TLS private keys has been deprecated, and has been removed.
|
||||
Golang has deprecated support for legacy PEM encryption (as specified in
|
||||
@@ -246,7 +224,7 @@ to decrypt the private key, and store it un-encrypted to continue using it.
|
||||
### Kubernetes stack and context support
|
||||
|
||||
**Deprecated in Release: v20.10**
|
||||
**Removed in Release: v23.0**
|
||||
**Removed in Release: v23.0.0**
|
||||
|
||||
Following the deprecation of [Compose on Kubernetes](https://github.com/docker/compose-on-kubernetes),
|
||||
support for Kubernetes in the `stack` and `context` commands has been removed from
|
||||
@@ -307,7 +285,7 @@ major release.
|
||||
### Linux containers on Windows (LCOW) (experimental)
|
||||
|
||||
**Deprecated in Release: v20.10**
|
||||
**Removed in Release: v23.0**
|
||||
**Removed in Release: v23.0.0**
|
||||
|
||||
The experimental feature to run Linux containers on Windows (LCOW) was introduced
|
||||
as a technical preview in Docker 17.09. While many enhancements were made after
|
||||
@@ -330,7 +308,7 @@ When using cgroups v2, the `--blkio-weight` options are implemented using
|
||||
### Kernel memory limit
|
||||
|
||||
**Deprecated in Release: v20.10**
|
||||
**Removed in Release: v23.0**
|
||||
**Removed in Release: v23.0.0**
|
||||
|
||||
Specifying kernel memory limit (`docker run --kernel-memory`) is no longer supported
|
||||
because the [Linux kernel deprecated `kmem.limit_in_bytes` in v5.4](https://github.com/torvalds/linux/commit/0158115f702b0ba208ab0b5adf44cae99b3ebcc7).
|
||||
@@ -358,7 +336,7 @@ take no effect.
|
||||
### Classic Swarm and overlay networks using cluster store
|
||||
|
||||
**Deprecated in Release: v20.10**
|
||||
**Removed in Release: v23.0**
|
||||
**Removed in Release: v23.0.0**
|
||||
|
||||
Standalone ("classic") Swarm has been deprecated, and with that the use of overlay
|
||||
networks using an external key/value store. The corresponding`--cluster-advertise`,
|
||||
@@ -367,7 +345,7 @@ networks using an external key/value store. The corresponding`--cluster-advertis
|
||||
### Support for legacy `~/.dockercfg` configuration files
|
||||
|
||||
**Deprecated in Release: v20.10**
|
||||
**Removed in Release: v23.0**
|
||||
**Removed in Release: v23.0.0**
|
||||
|
||||
The docker CLI up until v1.7.0 used the `~/.dockercfg` file to store credentials
|
||||
after authenticating to a registry (`docker login`). Docker v1.7.0 replaced this
|
||||
@@ -387,13 +365,13 @@ notifying the user that the legacy file is present, but ignored.
|
||||
|
||||
**Deprecated in Release: v19.03**
|
||||
|
||||
**Removed in Release: v23.0**
|
||||
**Removed in Release: v23.0.0**
|
||||
|
||||
The `DOCKER_CLI_EXPERIMENTAL` environment variable and the corresponding `experimental`
|
||||
field in the CLI configuration file are deprecated. Experimental features are
|
||||
enabled by default, and these configuration options are no longer functional.
|
||||
|
||||
Starting with v23.0, the Docker CLI no longer prints `Experimental` for the client
|
||||
Starting with v23.0.0, the Docker CLI no longer prints `Experimental` for the client
|
||||
in the output of `docker version`, and the field has been removed from the JSON
|
||||
format.
|
||||
|
||||
@@ -515,7 +493,7 @@ using compose files.
|
||||
### Support for the `overlay2.override_kernel_check` storage option
|
||||
|
||||
**Deprecated in Release: v19.03**
|
||||
**Removed in Release: v24.0**
|
||||
**Disabled in Release: v19.03**
|
||||
|
||||
This daemon configuration option disabled the Linux kernel version check used
|
||||
to detect if the kernel supported OverlayFS with multiple lower dirs, which is
|
||||
@@ -523,17 +501,20 @@ required for the overlay2 storage driver. Starting with Docker v19.03.7, the
|
||||
detection was improved to no longer depend on the kernel _version_, so this
|
||||
option was no longer used.
|
||||
|
||||
Docker v23.0.0 logs a warning in the daemon logs if this option is set, and
|
||||
users should remove this option from their daemon configuration.
|
||||
|
||||
### AuFS storage driver
|
||||
|
||||
**Deprecated in Release: v19.03**
|
||||
**Removed in Release: v24.0**
|
||||
**Disabled by default in Release: v23.0.0**
|
||||
|
||||
The `aufs` storage driver is deprecated in favor of `overlay2`, and has been
|
||||
removed in a Docker Engine v24.0. Users of the `aufs` storage driver must
|
||||
migrate to a different storage driver, such as `overlay2`, before upgrading
|
||||
to Docker Engine v24.0.
|
||||
The `aufs` storage driver is deprecated in favor of `overlay2`, and will
|
||||
be removed in a future release. Users of the `aufs` storage driver are
|
||||
recommended to migrate to a different storage driver, such as `overlay2`, which
|
||||
is now the default storage driver.
|
||||
|
||||
The `aufs` storage driver facilitated running Docker on distros that have no
|
||||
The `aufs` storage driver facilitates running Docker on distros that have no
|
||||
support for OverlayFS, such as Ubuntu 14.04 LTS, which originally shipped with
|
||||
a 3.14 kernel.
|
||||
|
||||
@@ -542,26 +523,62 @@ is available to all supported distros (as they are either on kernel 4.x, or have
|
||||
support for multiple lowerdirs backported), there is no reason to continue
|
||||
maintenance of the `aufs` storage driver.
|
||||
|
||||
### Legacy overlay storage driver
|
||||
#### Disabled by default in v23.0.0
|
||||
|
||||
Docker already prevented deprecated storage drivers from being automatically
|
||||
selected on new installations, but continued to use these drivers when upgrading
|
||||
existing installations. Starting with the v23.0.0 release, the Docker Engine will
|
||||
fail to start if a deprecated storage driver is used (see [moby#43378](https://github.com/moby/moby/pull/43378):
|
||||
|
||||
```console
|
||||
failed to start daemon: error initializing graphdriver: prior storage driver
|
||||
aufs is deprecated and will be removed in a future release; update the the daemon
|
||||
configuration and explicitly choose this storage driver to continue using it;
|
||||
visit https://docs.docker.com/go/storage-driver/ for more information.
|
||||
```
|
||||
|
||||
To continue using the storage driver, update the daemon configuration to use
|
||||
explicitly use the given storage driver. Users are encouraged to migrate to
|
||||
different storage driver.
|
||||
|
||||
### Legacy "overlay" storage driver
|
||||
|
||||
**Deprecated in Release: v18.09**
|
||||
**Removed in Release: v24.0**
|
||||
**Disabled by default in Release: v23.0.0**
|
||||
|
||||
The `overlay` storage driver is deprecated in favor of the `overlay2` storage
|
||||
driver, which has all the benefits of `overlay`, without its limitations (excessive
|
||||
inode consumption). The legacy `overlay` storage driver has been removed in
|
||||
Docker Engine v24.0. Users of the `overlay` storage driver should migrate to the
|
||||
`overlay2` storage driver before upgrading to Docker Engine v24.0.
|
||||
inode consumption). The legacy `overlay` storage driver will be removed in a future
|
||||
release. Users of the `overlay` storage driver should migrate to the `overlay2`
|
||||
storage driver.
|
||||
|
||||
The legacy `overlay` storage driver allowed using overlayFS-backed filesystems
|
||||
on pre 4.x kernels. Now that all supported distributions are able to run `overlay2`
|
||||
(as they are either on kernel 4.x, or have support for multiple lowerdirs
|
||||
backported), there is no reason to keep maintaining the `overlay` storage driver.
|
||||
|
||||
#### Disabled by default in v23.0.0
|
||||
|
||||
Docker already prevented deprecated storage drivers from being automatically
|
||||
selected on new installations, but continued to use these drivers when upgrading
|
||||
existing installations. Starting with the v23.0.0 release, the Docker Engine will
|
||||
fail to start if a deprecated storage driver is used (see [moby#43378](https://github.com/moby/moby/pull/43378):
|
||||
|
||||
```console
|
||||
failed to start daemon: error initializing graphdriver: prior storage driver
|
||||
overlay is deprecated and will be removed in a future release; update the the daemon
|
||||
configuration and explicitly choose this storage driver to continue using it;
|
||||
visit https://docs.docker.com/go/storage-driver/ for more information.
|
||||
```
|
||||
|
||||
To continue using the storage driver, update the daemon configuration to use
|
||||
explicitly use the given storage driver. Users are encouraged to migrate to
|
||||
different storage driver.
|
||||
|
||||
### Device mapper storage driver
|
||||
|
||||
**Deprecated in Release: v18.09**
|
||||
**Disabled by default in Release: v23.0**
|
||||
**Disabled by default in Release: v23.0.0**
|
||||
|
||||
The `devicemapper` storage driver is deprecated in favor of `overlay2`, and will
|
||||
be removed in a future release. Users of the `devicemapper` storage driver are
|
||||
@@ -569,17 +586,17 @@ recommended to migrate to a different storage driver, such as `overlay2`, which
|
||||
is now the default storage driver.
|
||||
|
||||
The `devicemapper` storage driver facilitates running Docker on older (3.x) kernels
|
||||
that have no support for other storage drivers (such as overlay2, or btrfs).
|
||||
that have no support for other storage drivers (such as overlay2, or AUFS).
|
||||
|
||||
Now that support for `overlay2` is added to all supported distros (as they are
|
||||
either on kernel 4.x, or have support for multiple lowerdirs backported), there
|
||||
is no reason to continue maintenance of the `devicemapper` storage driver.
|
||||
|
||||
#### Disabled by default in v23.0
|
||||
#### Disabled by default in v23.0.0
|
||||
|
||||
Docker already prevented deprecated storage drivers from being automatically
|
||||
selected on new installations, but continued to use these drivers when upgrading
|
||||
existing installations. Starting with the v23.0 release, the Docker Engine will
|
||||
existing installations. Starting with the v23.0.0 release, the Docker Engine will
|
||||
fail to start if a deprecated storage driver is used (see [moby#43378](https://github.com/moby/moby/pull/43378):
|
||||
|
||||
```console
|
||||
@@ -655,12 +672,12 @@ and `docker service scale` in Docker 17.10.
|
||||
|
||||
**Deprecated In Release: v17.05**
|
||||
|
||||
**Removed In Release: v23.0**
|
||||
**Removed In Release: v23.0.0**
|
||||
|
||||
The `-g` or `--graph` flag for the `dockerd` or `docker daemon` command was
|
||||
used to indicate the directory in which to store persistent data and resource
|
||||
configuration and has been replaced with the more descriptive `--data-root`
|
||||
flag. These flags were deprecated and hidden in v17.05, and removed in v23.0.
|
||||
flag. These flags were deprecated and hidden in v17.05, and removed in v23.0.0.
|
||||
|
||||
### Top-level network properties in NetworkSettings
|
||||
|
||||
@@ -738,7 +755,7 @@ The overlay and overlay2 storage driver does not work as expected if the backing
|
||||
filesystem does not support `d_type`. For example, XFS does not support `d_type`
|
||||
if it is formatted with the `ftype=0` option.
|
||||
|
||||
Support for these setups has been removed, and Docker v23.0 and up now fails to
|
||||
Support for these setups has been removed, and Docker v23.0.0 and up now fails to
|
||||
start when attempting to use the `overlay2` or `overlay` storage driver on a
|
||||
backing filesystem without `d_type` support.
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ advisory: experimental
|
||||
|
||||
Docker graph driver plugins enable admins to use an external/out-of-process
|
||||
graph driver for use with Docker engine. This is an alternative to using the
|
||||
built-in storage drivers, such as overlay2.
|
||||
built-in storage drivers, such as aufs/overlay/devicemapper/btrfs.
|
||||
|
||||
You need to install and enable the plugin and then restart the Docker daemon
|
||||
before using the plugin. See the following example for the correct ordering
|
||||
|
||||
@@ -12,7 +12,6 @@ Create a new container
|
||||
| Name | Type | Default | Description |
|
||||
|:--------------------------|:--------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--add-host` | `list` | | Add a custom host-to-IP mapping (host:ip) |
|
||||
| `--annotation` | `map` | `map[]` | Add an annotation to the container (passed through to the OCI runtime) |
|
||||
| `-a`, `--attach` | `list` | | Attach to STDIN, STDOUT or STDERR |
|
||||
| `--blkio-weight` | `uint16` | `0` | Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0) |
|
||||
| `--blkio-weight-device` | `list` | | Block IO weight (relative device weight) |
|
||||
|
||||
@@ -12,7 +12,6 @@ Create and run a new container from an image
|
||||
| Name | Type | Default | Description |
|
||||
|:--------------------------|:--------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--add-host` | `list` | | Add a custom host-to-IP mapping (host:ip) |
|
||||
| `--annotation` | `map` | `map[]` | Add an annotation to the container (passed through to the OCI runtime) |
|
||||
| `-a`, `--attach` | `list` | | Attach to STDIN, STDOUT or STDERR |
|
||||
| `--blkio-weight` | `uint16` | `0` | Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0) |
|
||||
| `--blkio-weight-device` | `list` | | Block IO weight (relative device weight) |
|
||||
|
||||
@@ -12,7 +12,6 @@ Create a new container
|
||||
| Name | Type | Default | Description |
|
||||
|:--------------------------|:--------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--add-host` | `list` | | Add a custom host-to-IP mapping (host:ip) |
|
||||
| `--annotation` | `map` | `map[]` | Add an annotation to the container (passed through to the OCI runtime) |
|
||||
| `-a`, `--attach` | `list` | | Attach to STDIN, STDOUT or STDERR |
|
||||
| `--blkio-weight` | `uint16` | `0` | Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0) |
|
||||
| `--blkio-weight-device` | `list` | | Block IO weight (relative device weight) |
|
||||
|
||||
@@ -242,7 +242,6 @@ precedence over `HTTP_PROXY`.
|
||||
The Docker client supports connecting to a remote daemon via SSH:
|
||||
|
||||
```console
|
||||
$ docker -H ssh://me@example.com:22/var/run/docker.sock ps
|
||||
$ docker -H ssh://me@example.com:22 ps
|
||||
$ docker -H ssh://me@example.com ps
|
||||
$ docker -H ssh://example.com ps
|
||||
@@ -323,7 +322,7 @@ $ docker -H tcp://127.0.0.1:2375 pull ubuntu
|
||||
### Daemon storage-driver
|
||||
|
||||
On Linux, the Docker daemon has support for several different image layer storage
|
||||
drivers: `overlay2`, `fuse-overlayfs`, `btrfs`, `zfs`, and `devicemapper`.
|
||||
drivers: `aufs`, `devicemapper`, `btrfs`, `zfs`, `overlay`, `overlay2`, and `fuse-overlayfs`.
|
||||
|
||||
`overlay2` is the preferred storage driver for all currently supported Linux distributions,
|
||||
and is selected by default. Unless users have a strong reason to prefer another storage driver,
|
||||
|
||||
@@ -47,8 +47,7 @@ information about the `overlay2` storage driver is shown:
|
||||
```console
|
||||
$ docker info
|
||||
|
||||
Client: Docker Engine - Community
|
||||
Version: 24.0.0
|
||||
Client:
|
||||
Context: default
|
||||
Debug Mode: false
|
||||
Plugins:
|
||||
@@ -102,6 +101,7 @@ Server:
|
||||
Docker Root Dir: /var/lib/docker
|
||||
Debug Mode: false
|
||||
Username: gordontheturtle
|
||||
Registry: https://index.docker.io/v1/
|
||||
Experimental: false
|
||||
Insecure Registries:
|
||||
myinsecurehost:5000
|
||||
@@ -126,8 +126,7 @@ Here is a sample output for a daemon running on Windows Server:
|
||||
```console
|
||||
C:\> docker info
|
||||
|
||||
Client: Docker Engine - Community
|
||||
Version: 24.0.0
|
||||
Client:
|
||||
Context: default
|
||||
Debug Mode: false
|
||||
Plugins:
|
||||
@@ -163,6 +162,7 @@ Server:
|
||||
ID: 2880d38d-464e-4d01-91bd-c76f33ba3981
|
||||
Docker Root Dir: C:\ProgramData\docker
|
||||
Debug Mode: false
|
||||
Registry: https://index.docker.io/v1/
|
||||
Experimental: true
|
||||
Insecure Registries:
|
||||
myregistry:5000
|
||||
|
||||
@@ -32,9 +32,9 @@ Running `docker ps --no-trunc` showing 2 linked containers.
|
||||
```console
|
||||
$ docker ps --no-trunc
|
||||
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
ca5534a51dd04bbcebe9b23ba05f389466cf0c190f1f8f182d7eea92a9671d00 ubuntu:22.04 bash 17 seconds ago Up 16 seconds 3300-3310/tcp webapp
|
||||
9ca9747b233100676a48cc7806131586213fa5dab86dd1972d6a8732e3a84a4d crosbymichael/redis:latest /redis-server --dir 33 minutes ago Up 33 minutes 6379/tcp redis,webapp/db
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
4c01db0b339c ubuntu:22.04 bash 17 seconds ago Up 16 seconds 3300-3310/tcp webapp
|
||||
d7886598dbe2 crosbymichael/redis:latest /redis-server --dir 33 minutes ago Up 33 minutes 6379/tcp redis,webapp/db
|
||||
```
|
||||
|
||||
### <a name="all"></a> Show both running and stopped containers (-a, --all)
|
||||
|
||||
@@ -12,7 +12,6 @@ Create and run a new container from an image
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------------------------------------|:--------------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [`--add-host`](#add-host) | `list` | | Add a custom host-to-IP mapping (host:ip) |
|
||||
| `--annotation` | `map` | `map[]` | Add an annotation to the container (passed through to the OCI runtime) |
|
||||
| [`-a`](#attach), [`--attach`](#attach) | `list` | | Attach to STDIN, STDOUT or STDERR |
|
||||
| `--blkio-weight` | `uint16` | `0` | Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0) |
|
||||
| `--blkio-weight-device` | `list` | | Block IO weight (relative device weight) |
|
||||
|
||||
@@ -16,10 +16,21 @@ keywords: "glossary, docker, terms, definitions"
|
||||
|
||||
A list of terms used around the Docker project.
|
||||
|
||||
## aufs
|
||||
|
||||
aufs (advanced multi layered unification filesystem) is a Linux [filesystem](#filesystem) that
|
||||
Docker supports as a storage backend. It implements the
|
||||
[union mount](https://en.wikipedia.org/wiki/Union_mount) for Linux file systems.
|
||||
|
||||
## base image
|
||||
|
||||
An image that has no parent is a **base image**.
|
||||
|
||||
## boot2docker
|
||||
|
||||
[boot2docker](https://boot2docker.io/) is a lightweight Linux distribution made
|
||||
specifically to run Docker containers. The boot2docker management tool for Mac and Windows was deprecated and replaced by [`docker-machine`](#machine) which you can install with the Docker Toolbox.
|
||||
|
||||
## bridge
|
||||
|
||||
In terms of generic networking, a bridge is a Link Layer device which forwards
|
||||
@@ -172,7 +183,7 @@ and assign them locations for efficient storage and retrieval.
|
||||
|
||||
Examples :
|
||||
|
||||
- Linux : ext4, btrfs, zfs
|
||||
- Linux : ext4, aufs, btrfs, zfs
|
||||
- Windows : NTFS
|
||||
- macOS : HFS+
|
||||
|
||||
@@ -203,6 +214,15 @@ links provide a legacy interface to connect Docker containers running on the
|
||||
same host to each other without exposing the hosts' network ports. Use the
|
||||
Docker networks feature instead.
|
||||
|
||||
## Machine
|
||||
|
||||
[Machine](https://github.com/docker/machine) is a Docker tool which
|
||||
makes it really easy to create Docker hosts on your computer, on
|
||||
cloud providers and inside your own data center. It creates servers,
|
||||
installs Docker on them, then configures the Docker client to talk to them.
|
||||
|
||||
*Also known as : docker-machine*
|
||||
|
||||
## node
|
||||
|
||||
A [node](https://docs.docker.com/engine/swarm/how-swarm-mode-works/nodes/) is a physical or virtual
|
||||
@@ -308,18 +328,38 @@ containers.
|
||||
|
||||

|
||||
|
||||
## Toolbox
|
||||
|
||||
[Docker Toolbox](https://docs.docker.com/toolbox/overview/) is a legacy
|
||||
installer for Mac and Windows users. It uses Oracle VirtualBox for
|
||||
virtualization.
|
||||
|
||||
For Macs running OS X El Capitan 10.11 and newer macOS releases, [Docker for
|
||||
Mac](https://docs.docker.com/docker-for-mac/) is the better solution.
|
||||
|
||||
For Windows 10 systems that support Microsoft Hyper-V (Professional, Enterprise
|
||||
and Education), [Docker for
|
||||
Windows](https://docs.docker.com/docker-for-windows/) is the better solution.
|
||||
|
||||
## Union file system
|
||||
|
||||
Union file systems implement a [union mount](https://en.wikipedia.org/wiki/Union_mount) and operate by creating
|
||||
Union file systems implement a [union
|
||||
mount](https://en.wikipedia.org/wiki/Union_mount) and operate by creating
|
||||
layers. Docker uses union file systems in conjunction with
|
||||
[copy-on-write](#copy-on-write) techniques to provide the building blocks for
|
||||
containers, making them very lightweight and fast.
|
||||
|
||||
For more on Docker and union file systems, see [OverlayFS storage driver](https://docs.docker.com/storage/storagedriver/overlayfs-driver/),
|
||||
and [Btrfs storage driver](https://docs.docker.com/storage/storagedriver/btrfs-driver/).
|
||||
For more on Docker and union file systems, see [Docker and AUFS in
|
||||
practice](https://docs.docker.com/engine/userguide/storagedriver/aufs-driver/),
|
||||
[Docker and Btrfs in
|
||||
practice](https://docs.docker.com/engine/userguide/storagedriver/btrfs-driver/),
|
||||
and [Docker and OverlayFS in
|
||||
practice](https://docs.docker.com/engine/userguide/storagedriver/overlayfs-driver/)
|
||||
|
||||
Example implementations of union file systems are
|
||||
[UnionFS](https://en.wikipedia.org/wiki/UnionFS), and [Btrfs](https://btrfs.wiki.kernel.org/index.php/Main_Page).
|
||||
[UnionFS](https://en.wikipedia.org/wiki/UnionFS),
|
||||
[AUFS](https://en.wikipedia.org/wiki/Aufs), and
|
||||
[Btrfs](https://btrfs.wiki.kernel.org/index.php/Main_Page).
|
||||
|
||||
## virtual machine
|
||||
|
||||
|
||||
@@ -18,10 +18,6 @@ const registryPrefix = "registry:5000"
|
||||
func TestRunAttachedFromRemoteImageAndRemove(t *testing.T) {
|
||||
skip.If(t, environment.RemoteDaemon())
|
||||
|
||||
// Digests in golden file are linux/amd64 specific.
|
||||
// TODO: Fix this test and make it work on all platforms.
|
||||
environment.SkipIfNotPlatform(t, "linux/amd64")
|
||||
|
||||
image := createRemoteImage(t)
|
||||
|
||||
result := icmd.RunCommand("docker", "run", "--rm", image,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Unable to find image 'registry:5000/alpine:test-run-pulls' locally
|
||||
test-run-pulls: Pulling from alpine
|
||||
Digest: sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501
|
||||
Digest: sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d
|
||||
Status: Downloaded newer image for registry:5000/alpine:test-run-pulls
|
||||
|
||||
@@ -44,7 +44,7 @@ func TestBuildFromContextDirectoryWithTag(t *testing.T) {
|
||||
result.Assert(t, icmd.Expected{Err: buildkitDisabledWarning})
|
||||
output.Assert(t, result.Stdout(), map[int]func(string) error{
|
||||
0: output.Prefix("Sending build context to Docker daemon"),
|
||||
1: output.Suffix("Step 1/4 : FROM registry:5000/alpine:frozen"),
|
||||
1: output.Suffix("Step 1/4 : FROM registry:5000/alpine:3.6"),
|
||||
3: output.Suffix("Step 2/4 : COPY run /usr/bin/run"),
|
||||
5: output.Suffix("Step 3/4 : RUN run"),
|
||||
7: output.Suffix("running"),
|
||||
|
||||
@@ -17,10 +17,6 @@ const registryPrefix = "registry:5000"
|
||||
func TestPullWithContentTrust(t *testing.T) {
|
||||
skip.If(t, environment.RemoteDaemon())
|
||||
|
||||
// Digests in golden files are linux/amd64 specific.
|
||||
// TODO: Fix this test and make it work on all platforms.
|
||||
environment.SkipIfNotPlatform(t, "linux/amd64")
|
||||
|
||||
dir := fixtures.SetupConfigFile(t)
|
||||
defer dir.Remove()
|
||||
image := fixtures.CreateMaskedTrustedRemoteImage(t, registryPrefix, "trust-pull", "latest")
|
||||
@@ -41,7 +37,7 @@ func TestPullWithContentTrust(t *testing.T) {
|
||||
func TestPullQuiet(t *testing.T) {
|
||||
result := icmd.RunCommand("docker", "pull", "--quiet", fixtures.AlpineImage)
|
||||
result.Assert(t, icmd.Success)
|
||||
assert.Check(t, is.Equal(result.Stdout(), "registry:5000/alpine:frozen\n"))
|
||||
assert.Check(t, is.Equal(result.Stdout(), "registry:5000/alpine:3.6\n"))
|
||||
assert.Check(t, is.Equal(result.Stderr(), ""))
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user