mirror of
https://github.com/docker/cli.git
synced 2026-08-28 02:24:15 -05:00
Compare commits
80
Commits
@@ -63,7 +63,7 @@ jobs:
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.20.2
|
||||
go-version: 1.20.3
|
||||
-
|
||||
name: Test
|
||||
run: |
|
||||
|
||||
@@ -29,14 +29,33 @@ jobs:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
-
|
||||
name: Run
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
# check that the generated Markdown and the checked-in files match
|
||||
validate-md:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Generate
|
||||
shell: 'script --return --quiet --command "bash {0}"'
|
||||
run: |
|
||||
make -f docker.Makefile mddocs
|
||||
-
|
||||
name: Validate
|
||||
run: |
|
||||
if [[ $(git diff --stat) != '' ]]; then
|
||||
echo 'fail: generated files do not match checked-in files'
|
||||
git --no-pager diff
|
||||
exit 1
|
||||
fi
|
||||
|
||||
validate-make:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
@@ -49,8 +68,6 @@ jobs:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
-
|
||||
name: Run
|
||||
shell: 'script --return --quiet --command "bash {0}"'
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG BASE_VARIANT=alpine
|
||||
ARG GO_VERSION=1.20.2
|
||||
ARG GO_VERSION=1.20.3
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG XX_VERSION=1.1.1
|
||||
ARG GOVERSIONINFO_VERSION=v1.3.0
|
||||
|
||||
@@ -74,7 +74,7 @@ func TestValidateCandidate(t *testing.T) {
|
||||
{name: "experimental + allowing experimental", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: metaExperimental}},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
p, err := newPlugin(tc.c, fakeroot)
|
||||
p, err := newPlugin(tc.c, fakeroot.Commands())
|
||||
if tc.err != "" {
|
||||
assert.ErrorContains(t, err, tc.err)
|
||||
} else if tc.invalid != "" {
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/config"
|
||||
"github.com/fvbommel/sortorder"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/sync/errgroup"
|
||||
exec "golang.org/x/sys/execabs"
|
||||
)
|
||||
|
||||
@@ -120,7 +123,7 @@ func GetPlugin(name string, dockerCli command.Cli, rootcmd *cobra.Command) (*Plu
|
||||
return nil, errPluginNotFound(name)
|
||||
}
|
||||
c := &candidate{paths[0]}
|
||||
p, err := newPlugin(c, rootcmd)
|
||||
p, err := newPlugin(c, rootcmd.Commands())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -146,19 +149,32 @@ func ListPlugins(dockerCli command.Cli, rootcmd *cobra.Command) ([]Plugin, error
|
||||
}
|
||||
|
||||
var plugins []Plugin
|
||||
var mu sync.Mutex
|
||||
eg, _ := errgroup.WithContext(context.TODO())
|
||||
cmds := rootcmd.Commands()
|
||||
for _, paths := range candidates {
|
||||
if len(paths) == 0 {
|
||||
continue
|
||||
}
|
||||
c := &candidate{paths[0]}
|
||||
p, err := newPlugin(c, rootcmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !IsNotFound(p.Err) {
|
||||
p.ShadowedPaths = paths[1:]
|
||||
plugins = append(plugins, p)
|
||||
}
|
||||
func(paths []string) {
|
||||
eg.Go(func() error {
|
||||
if len(paths) == 0 {
|
||||
return nil
|
||||
}
|
||||
c := &candidate{paths[0]}
|
||||
p, err := newPlugin(c, cmds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !IsNotFound(p.Err) {
|
||||
p.ShadowedPaths = paths[1:]
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
plugins = append(plugins, p)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}(paths)
|
||||
}
|
||||
if err := eg.Wait(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sort.Slice(plugins, func(i, j int) bool {
|
||||
@@ -199,7 +215,7 @@ func PluginRunCommand(dockerCli command.Cli, name string, rootcmd *cobra.Command
|
||||
}
|
||||
|
||||
c := &candidate{path: path}
|
||||
plugin, err := newPlugin(c, rootcmd)
|
||||
plugin, err := newPlugin(c, rootcmd.Commands())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ type Plugin struct {
|
||||
// is set, and is always a `pluginError`, but the `Plugin` is still
|
||||
// returned with no error. An error is only returned due to a
|
||||
// non-recoverable error.
|
||||
func newPlugin(c Candidate, rootcmd *cobra.Command) (Plugin, error) {
|
||||
func newPlugin(c Candidate, cmds []*cobra.Command) (Plugin, error) {
|
||||
path := c.Path()
|
||||
if path == "" {
|
||||
return Plugin{}, errors.New("plugin candidate path cannot be empty")
|
||||
@@ -62,22 +62,20 @@ func newPlugin(c Candidate, rootcmd *cobra.Command) (Plugin, error) {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
if rootcmd != nil {
|
||||
for _, cmd := range rootcmd.Commands() {
|
||||
// Ignore conflicts with commands which are
|
||||
// just plugin stubs (i.e. from a previous
|
||||
// call to AddPluginCommandStubs).
|
||||
if IsPluginCommand(cmd) {
|
||||
continue
|
||||
}
|
||||
if cmd.Name() == p.Name {
|
||||
p.Err = NewPluginError("plugin %q duplicates builtin command", p.Name)
|
||||
return p, nil
|
||||
}
|
||||
if cmd.HasAlias(p.Name) {
|
||||
p.Err = NewPluginError("plugin %q duplicates an alias of builtin command %q", p.Name, cmd.Name())
|
||||
return p, nil
|
||||
}
|
||||
for _, cmd := range cmds {
|
||||
// Ignore conflicts with commands which are
|
||||
// just plugin stubs (i.e. from a previous
|
||||
// call to AddPluginCommandStubs).
|
||||
if IsPluginCommand(cmd) {
|
||||
continue
|
||||
}
|
||||
if cmd.Name() == p.Name {
|
||||
p.Err = NewPluginError("plugin %q duplicates builtin command", p.Name)
|
||||
return p, nil
|
||||
}
|
||||
if cmd.HasAlias(p.Name) {
|
||||
p.Err = NewPluginError("plugin %q duplicates an alias of builtin command %q", p.Name, cmd.Name())
|
||||
return p, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -426,7 +426,7 @@ func invalidPluginReason(cmd *cobra.Command) string {
|
||||
return cmd.Annotations[pluginmanager.CommandAnnotationPluginInvalid]
|
||||
}
|
||||
|
||||
var usageTemplate = `Usage:
|
||||
const 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}}
|
||||
`
|
||||
|
||||
var helpTemplate = `
|
||||
const helpTemplate = `
|
||||
{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
|
||||
|
||||
+1
-3
@@ -48,9 +48,7 @@ type Streams interface {
|
||||
// Cli represents the docker command line client.
|
||||
type Cli interface {
|
||||
Client() client.APIClient
|
||||
Out() *streams.Out
|
||||
Err() io.Writer
|
||||
In() *streams.In
|
||||
Streams
|
||||
SetIn(in *streams.In)
|
||||
Apply(ops ...DockerCliOption) error
|
||||
ConfigFile() *configfile.ConfigFile
|
||||
|
||||
@@ -12,6 +12,7 @@ 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"
|
||||
@@ -19,7 +20,6 @@ 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)
|
||||
containerConfig, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
|
||||
containerCfg, 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(containerConfig, dockerCli.Client().ClientVersion()); err != nil {
|
||||
if err = validateAPIVersion(containerCfg, dockerCli.Client().ClientVersion()); err != nil {
|
||||
reportError(dockerCli.Err(), "create", err.Error(), true)
|
||||
return cli.StatusError{StatusCode: 125}
|
||||
}
|
||||
response, err := createContainer(context.Background(), dockerCli, containerConfig, options)
|
||||
response, err := createContainer(context.Background(), dockerCli, containerCfg, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -112,41 +112,27 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, options *createOptio
|
||||
return nil
|
||||
}
|
||||
|
||||
func pullImage(ctx context.Context, dockerCli command.Cli, image string, platform string, out io.Writer) error {
|
||||
ref, err := reference.ParseNormalizedNamed(image)
|
||||
// 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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 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{
|
||||
responseBody, err := dockerCli.Client().ImageCreate(ctx, image, types.ImageCreateOptions{
|
||||
RegistryAuth: encodedAuth,
|
||||
Platform: platform,
|
||||
}
|
||||
|
||||
responseBody, err := dockerCli.Client().ImageCreate(ctx, image, options)
|
||||
Platform: opts.platform,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseBody.Close()
|
||||
|
||||
return jsonmessage.DisplayJSONMessagesStream(
|
||||
responseBody,
|
||||
out,
|
||||
dockerCli.Out().FD(),
|
||||
dockerCli.Out().IsTerminal(),
|
||||
nil)
|
||||
out := dockerCli.Err()
|
||||
if opts.quiet {
|
||||
out = io.Discard
|
||||
}
|
||||
return jsonmessage.DisplayJSONMessagesToStream(responseBody, streams.NewOut(out), nil)
|
||||
}
|
||||
|
||||
type cidFile struct {
|
||||
@@ -199,10 +185,10 @@ func newCIDFile(path string) (*cidFile, error) {
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig *containerConfig, opts *createOptions) (*container.CreateResponse, error) {
|
||||
config := containerConfig.Config
|
||||
hostConfig := containerConfig.HostConfig
|
||||
networkingConfig := containerConfig.NetworkingConfig
|
||||
func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *containerConfig, opts *createOptions) (*container.CreateResponse, error) {
|
||||
config := containerCfg.Config
|
||||
hostConfig := containerCfg.HostConfig
|
||||
networkingConfig := containerCfg.NetworkingConfig
|
||||
|
||||
warnOnOomKillDisable(*hostConfig, dockerCli.Err())
|
||||
warnOnLocalhostDNS(*hostConfig, dockerCli.Err())
|
||||
@@ -236,11 +222,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
||||
}
|
||||
|
||||
pullAndTagImage := func() error {
|
||||
pullOut := dockerCli.Err()
|
||||
if opts.quiet {
|
||||
pullOut = io.Discard
|
||||
}
|
||||
if err := pullImage(ctx, dockerCli, config.Image, opts.platform, pullOut); err != nil {
|
||||
if err := pullImage(ctx, dockerCli, config.Image, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && trustedRef != nil {
|
||||
@@ -293,8 +275,8 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
||||
}
|
||||
}
|
||||
|
||||
for _, warning := range response.Warnings {
|
||||
fmt.Fprintf(dockerCli.Err(), "WARNING: %s\n", warning)
|
||||
for _, w := range response.Warnings {
|
||||
fmt.Fprintf(dockerCli.Err(), "WARNING: %s\n", w)
|
||||
}
|
||||
err = containerIDFile.Write(response.ID)
|
||||
return &response, err
|
||||
|
||||
@@ -120,6 +120,8 @@ 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,8 +309,22 @@ func TestContainerListWithFormat(t *testing.T) {
|
||||
}, nil
|
||||
},
|
||||
})
|
||||
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")
|
||||
|
||||
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")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -49,11 +49,11 @@ func parseRun(args []string) (*container.Config, *container.HostConfig, *network
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
// TODO: fix tests to accept ContainerConfig
|
||||
containerConfig, err := parse(flags, copts, runtime.GOOS)
|
||||
containerCfg, err := parse(flags, copts, runtime.GOOS)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
return containerConfig.Config, containerConfig.HostConfig, containerConfig.NetworkingConfig, err
|
||||
return containerCfg.Config, containerCfg.HostConfig, containerCfg.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)
|
||||
containerConfig, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
|
||||
containerCfg, 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(containerConfig, dockerCli.CurrentVersion()); err != nil {
|
||||
if err = validateAPIVersion(containerCfg, dockerCli.CurrentVersion()); err != nil {
|
||||
reportError(dockerCli.Err(), "run", err.Error(), true)
|
||||
return cli.StatusError{StatusCode: 125}
|
||||
}
|
||||
return runContainer(dockerCli, ropts, copts, containerConfig)
|
||||
return runContainer(dockerCli, ropts, copts, containerCfg)
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptions, containerConfig *containerConfig) error {
|
||||
config := containerConfig.Config
|
||||
func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptions, containerCfg *containerConfig) error {
|
||||
config := containerCfg.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, containerConfig, &opts.createOptions)
|
||||
createResponse, err := createContainer(ctx, dockerCli, containerCfg, &opts.createOptions)
|
||||
if err != nil {
|
||||
reportError(stderr, "run", err.Error(), true)
|
||||
return runStartContainerErr(err)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
container_id
|
||||
container_id
|
||||
@@ -55,6 +55,9 @@ 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)},
|
||||
"IMAGE\nubuntu\nubuntu\n",
|
||||
"containerID1\ncontainerID2\n",
|
||||
},
|
||||
{
|
||||
Context{Format: NewContainerFormat("table", true, false)},
|
||||
|
||||
@@ -84,10 +84,3 @@ 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 ""
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ const (
|
||||
JSONFormatKey = "json"
|
||||
|
||||
DefaultQuietFormat = "{{.ID}}"
|
||||
jsonFormat = "{{json .}}"
|
||||
JSONFormat = "{{json .}}"
|
||||
)
|
||||
|
||||
// Format is the format string rendered using the Context
|
||||
@@ -62,7 +62,7 @@ func (c *Context) preFormat() {
|
||||
case c.Format.IsTable():
|
||||
c.finalFormat = c.finalFormat[len(TableFormatKey):]
|
||||
case c.Format.IsJSON():
|
||||
c.finalFormat = jsonFormat
|
||||
c.finalFormat = JSONFormat
|
||||
}
|
||||
|
||||
c.finalFormat = strings.Trim(c.finalFormat, " ")
|
||||
|
||||
@@ -11,6 +11,7 @@ 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"
|
||||
@@ -76,7 +77,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 := command.EncodeAuthToBase64(authConfig)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -262,20 +262,17 @@ 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 {
|
||||
ref := reference.FamiliarString(imgRefAndAuth.Reference())
|
||||
|
||||
encodedAuth, err := command.EncodeAuthToBase64(*imgRefAndAuth.AuthConfig())
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(*imgRefAndAuth.AuthConfig())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(cli, imgRefAndAuth.RepoInfo().Index, "pull")
|
||||
options := types.ImagePullOptions{
|
||||
responseBody, err := cli.Client().ImagePull(ctx, reference.FamiliarString(imgRefAndAuth.Reference()), 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
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ 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"
|
||||
@@ -86,8 +87,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
|
||||
}
|
||||
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
|
||||
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
if err != nil {
|
||||
return types.PluginInstallOptions{}, err
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ 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"
|
||||
@@ -55,8 +56,7 @@ func runPush(dockerCli command.Cli, opts pushOptions) error {
|
||||
return err
|
||||
}
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
|
||||
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+46
-28
@@ -3,8 +3,6 @@ package command
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@@ -21,13 +19,11 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload
|
||||
// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload.
|
||||
//
|
||||
// Deprecated: use [registrytypes.EncodeAuthConfig] instead.
|
||||
func EncodeAuthToBase64(authConfig registrytypes.AuthConfig) (string, error) {
|
||||
buf, err := json.Marshal(authConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64.URLEncoding.EncodeToString(buf), nil
|
||||
return registrytypes.EncodeAuthConfig(authConfig)
|
||||
}
|
||||
|
||||
// RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info
|
||||
@@ -45,13 +41,16 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return EncodeAuthToBase64(authConfig)
|
||||
return registrytypes.EncodeAuthConfig(authConfig)
|
||||
}
|
||||
}
|
||||
|
||||
// ResolveAuthConfig is like registry.ResolveAuthConfig, but if using the
|
||||
// default index, it uses the default index name for the daemon's platform,
|
||||
// not the client's platform.
|
||||
// ResolveAuthConfig returns auth-config for the given registry from the
|
||||
// credential-store. It returns an empty AuthConfig if no credentials were
|
||||
// found.
|
||||
//
|
||||
// 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 {
|
||||
configKey := index.Name
|
||||
if index.Official {
|
||||
@@ -86,7 +85,14 @@ func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, is
|
||||
|
||||
// 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. Fixes #14336/#14210
|
||||
// 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.
|
||||
if runtime.GOOS == "windows" {
|
||||
cli.SetIn(streams.NewIn(os.Stdin))
|
||||
}
|
||||
@@ -110,8 +116,11 @@ 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)
|
||||
flUser = readInput(cli.In(), cli.Out())
|
||||
flUser = strings.TrimSpace(flUser)
|
||||
var err error
|
||||
flUser, err = readInput(cli.In())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if flUser == "" {
|
||||
flUser = authconfig.Username
|
||||
}
|
||||
@@ -125,12 +134,15 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(cli.Out(), "Password: ")
|
||||
term.DisableEcho(cli.In().FD(), oldState)
|
||||
|
||||
flPassword = readInput(cli.In(), cli.Out())
|
||||
_ = term.DisableEcho(cli.In().FD(), oldState)
|
||||
defer func() {
|
||||
_ = term.RestoreTerminal(cli.In().FD(), oldState)
|
||||
}()
|
||||
flPassword, err = readInput(cli.In())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprint(cli.Out(), "\n")
|
||||
|
||||
term.RestoreTerminal(cli.In().FD(), oldState)
|
||||
if flPassword == "" {
|
||||
return errors.Errorf("Error: Password Required")
|
||||
}
|
||||
@@ -142,14 +154,15 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes
|
||||
return nil
|
||||
}
|
||||
|
||||
func readInput(in io.Reader, out io.Writer) string {
|
||||
reader := bufio.NewReader(in)
|
||||
line, _, err := reader.ReadLine()
|
||||
// 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()
|
||||
if err != nil {
|
||||
fmt.Fprintln(out, err.Error())
|
||||
os.Exit(1)
|
||||
return "", errors.Wrap(err, "error while reading input")
|
||||
}
|
||||
return string(line)
|
||||
return strings.TrimSpace(string(line)), nil
|
||||
}
|
||||
|
||||
func promptWithDefault(out io.Writer, prompt string, configDefault string) {
|
||||
@@ -160,14 +173,19 @@ func promptWithDefault(out io.Writer, prompt string, configDefault string) {
|
||||
}
|
||||
}
|
||||
|
||||
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete image
|
||||
// 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
|
||||
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 := EncodeAuthToBase64(authConfig)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ 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"
|
||||
)
|
||||
@@ -54,25 +55,19 @@ func runSearch(dockerCli command.Cli, options searchOptions) error {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
authConfig := command.ResolveAuthConfig(ctx, dockerCli, indexInfo)
|
||||
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search")
|
||||
|
||||
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
searchOptions := types.ImageSearchOptions{
|
||||
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search")
|
||||
results, err := dockerCli.Client().ImageSearch(ctx, options.term, 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
|
||||
}
|
||||
|
||||
+19
-10
@@ -1,23 +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 github.com/docker/cli/cli/streams.In instead
|
||||
//
|
||||
// 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 github.com/docker/cli/cli/streams.Out instead
|
||||
//
|
||||
// Deprecated: Use [streams.Out] instead.
|
||||
type OutStream = streams.Out
|
||||
|
||||
var (
|
||||
// NewInStream returns a new InStream object from a ReadCloser
|
||||
// Deprecated: Use github.com/docker/cli/cli/streams.NewIn instead
|
||||
NewInStream = streams.NewIn
|
||||
// NewOutStream returns a new OutStream object from a Writer
|
||||
// Deprecated: Use github.com/docker/cli/cli/streams.NewOut instead
|
||||
NewOutStream = streams.NewOut
|
||||
)
|
||||
// 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)
|
||||
}
|
||||
|
||||
+28
-10
@@ -12,7 +12,9 @@ import (
|
||||
pluginmanager "github.com/docker/cli/cli-plugins/manager"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/cli/cli/debug"
|
||||
flagsHelper "github.com/docker/cli/cli/flags"
|
||||
"github.com/docker/cli/templates"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
@@ -26,8 +28,8 @@ type infoOptions struct {
|
||||
}
|
||||
|
||||
type clientInfo struct {
|
||||
Debug bool
|
||||
Context string
|
||||
Debug bool
|
||||
clientVersion
|
||||
Plugins []pluginmanager.Plugin
|
||||
Warnings []string
|
||||
}
|
||||
@@ -44,6 +46,13 @@ type info struct {
|
||||
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
|
||||
@@ -62,18 +71,18 @@ func NewInfoCommand(dockerCli command.Cli) *cobra.Command {
|
||||
ValidArgsFunction: completion.NoComplete,
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template")
|
||||
|
||||
cmd.Flags().StringVarP(&opts.format, "format", "f", "", flagsHelper.InspectFormatHelp)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runInfo(cmd *cobra.Command, dockerCli command.Cli, opts *infoOptions) error {
|
||||
info := info{
|
||||
ClientInfo: &clientInfo{
|
||||
Context: dockerCli.CurrentContext(),
|
||||
Debug: debug.IsEnabled(),
|
||||
// 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(),
|
||||
},
|
||||
Info: &types.Info{},
|
||||
}
|
||||
@@ -148,7 +157,12 @@ func needsServerInfo(template string, info info) bool {
|
||||
}
|
||||
|
||||
func prettyPrintInfo(dockerCli command.Cli, info info) error {
|
||||
fmt.Fprintln(dockerCli.Out(), "Client:")
|
||||
// Only append the platform info if it's not empty, to prevent printing a trailing space.
|
||||
if p := info.clientPlatform(); p != "" {
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), "Client:", p)
|
||||
} else {
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), "Client:")
|
||||
}
|
||||
if info.ClientInfo != nil {
|
||||
prettyPrintClientInfo(dockerCli, *info.ClientInfo)
|
||||
}
|
||||
@@ -174,6 +188,7 @@ func prettyPrintInfo(dockerCli command.Cli, info info) error {
|
||||
}
|
||||
|
||||
func prettyPrintClientInfo(dockerCli command.Cli, info clientInfo) {
|
||||
fprintlnNonEmpty(dockerCli.Out(), " Version: ", info.Version)
|
||||
fmt.Fprintln(dockerCli.Out(), " Context: ", info.Context)
|
||||
fmt.Fprintln(dockerCli.Out(), " Debug Mode:", info.Debug)
|
||||
|
||||
@@ -309,7 +324,6 @@ func prettyPrintServerInfo(dockerCli command.Cli, info types.Info) []error {
|
||||
if len(u) > 0 {
|
||||
fmt.Fprintln(dockerCli.Out(), " Username:", u)
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), " Registry:", info.IndexServerAddress)
|
||||
}
|
||||
|
||||
if len(info.Labels) > 0 {
|
||||
@@ -507,6 +521,10 @@ func printServerWarningsLegacy(dockerCli command.Cli, info types.Info) {
|
||||
}
|
||||
|
||||
func formatInfo(dockerCli command.Cli, info info, format string) error {
|
||||
if format == formatter.JSONFormatKey {
|
||||
format = formatter.JSONFormat
|
||||
}
|
||||
|
||||
// Ensure slice/array fields render as `[]` not `null`
|
||||
if info.ClientInfo != nil && info.ClientInfo.Plugins == nil {
|
||||
info.ClientInfo.Plugins = make([]pluginmanager.Plugin, 0)
|
||||
|
||||
@@ -278,8 +278,12 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoNoSwarm,
|
||||
ClientInfo: &clientInfo{
|
||||
Context: "default",
|
||||
Debug: true,
|
||||
clientVersion: clientVersion{
|
||||
Platform: &platformInfo{Name: "Docker Engine - Community"},
|
||||
Version: "24.0.0",
|
||||
Context: "default",
|
||||
},
|
||||
Debug: true,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-no-swarm",
|
||||
@@ -290,8 +294,8 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoNoSwarm,
|
||||
ClientInfo: &clientInfo{
|
||||
Context: "default",
|
||||
Plugins: samplePluginsInfo,
|
||||
clientVersion: clientVersion{Context: "default"},
|
||||
Plugins: samplePluginsInfo,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-plugins",
|
||||
@@ -302,7 +306,7 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
doc: "info with nil labels",
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoLabelsNil,
|
||||
ClientInfo: &clientInfo{Context: "default"},
|
||||
ClientInfo: &clientInfo{clientVersion: clientVersion{Context: "default"}},
|
||||
},
|
||||
prettyGolden: "docker-info-with-labels-nil",
|
||||
},
|
||||
@@ -310,7 +314,7 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
doc: "info with empty labels",
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoLabelsEmpty,
|
||||
ClientInfo: &clientInfo{Context: "default"},
|
||||
ClientInfo: &clientInfo{clientVersion: clientVersion{Context: "default"}},
|
||||
},
|
||||
prettyGolden: "docker-info-with-labels-empty",
|
||||
},
|
||||
@@ -319,8 +323,8 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &infoWithSwarm,
|
||||
ClientInfo: &clientInfo{
|
||||
Context: "default",
|
||||
Debug: false,
|
||||
clientVersion: clientVersion{Context: "default"},
|
||||
Debug: false,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-with-swarm",
|
||||
@@ -331,8 +335,12 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &infoWithWarningsLinux,
|
||||
ClientInfo: &clientInfo{
|
||||
Context: "default",
|
||||
Debug: true,
|
||||
clientVersion: clientVersion{
|
||||
Platform: &platformInfo{Name: "Docker Engine - Community"},
|
||||
Version: "24.0.0",
|
||||
Context: "default",
|
||||
},
|
||||
Debug: true,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-no-swarm",
|
||||
@@ -344,8 +352,12 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
dockerInfo: info{
|
||||
Info: &sampleInfoDaemonWarnings,
|
||||
ClientInfo: &clientInfo{
|
||||
Context: "default",
|
||||
Debug: true,
|
||||
clientVersion: clientVersion{
|
||||
Platform: &platformInfo{Name: "Docker Engine - Community"},
|
||||
Version: "24.0.0",
|
||||
Context: "default",
|
||||
},
|
||||
Debug: true,
|
||||
},
|
||||
},
|
||||
prettyGolden: "docker-info-no-swarm",
|
||||
@@ -376,6 +388,7 @@ 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)
|
||||
@@ -396,6 +409,11 @@ func TestPrettyPrintInfo(t *testing.T) {
|
||||
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, tc.dockerInfo, "json"))
|
||||
golden.Assert(t, cli.OutBuffer().String(), tc.jsonGolden+".json.golden")
|
||||
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -424,6 +442,7 @@ 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{
|
||||
|
||||
@@ -0,0 +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":""}}
|
||||
@@ -41,7 +41,6 @@ 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,"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,"Platform":{"Name":"Docker Engine - Community"},"Version":"24.0.0","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,"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,"Platform":{"Name":"Docker Engine - Community"},"Version":"24.0.0","Context":"default","Plugins":[],"Warnings":null}}
|
||||
|
||||
+2
-2
@@ -1,4 +1,5 @@
|
||||
Client:
|
||||
Client: Docker Engine - Community
|
||||
Version: 24.0.0
|
||||
Context: default
|
||||
Debug Mode: true
|
||||
|
||||
@@ -45,7 +46,6 @@ 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,"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,"Platform":{"Name":"Docker Engine - Community"},"Version":"24.0.0","Context":"default","Plugins":[],"Warnings":null}}
|
||||
|
||||
@@ -51,7 +51,6 @@ 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,7 +45,6 @@ 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,7 +45,6 @@ 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,7 +67,6 @@ Server:
|
||||
Goroutines: 135
|
||||
System Time: 2017-08-24T17:44:34.077811894Z
|
||||
EventsListeners: 0
|
||||
Registry: https://index.docker.io/v1/
|
||||
Labels:
|
||||
provider=digitalocean
|
||||
Experimental: false
|
||||
|
||||
@@ -11,7 +11,9 @@ import (
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/cli/cli/command/formatter/tabwriter"
|
||||
flagsHelper "github.com/docker/cli/cli/flags"
|
||||
"github.com/docker/cli/cli/version"
|
||||
"github.com/docker/cli/templates"
|
||||
"github.com/docker/docker/api/types"
|
||||
@@ -20,8 +22,8 @@ import (
|
||||
"github.com/tonistiigi/go-rosetta"
|
||||
)
|
||||
|
||||
var versionTemplate = `{{with .Client -}}
|
||||
Client:{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}
|
||||
const defaultVersionTemplate = `{{with .Client -}}
|
||||
Client:{{if ne .Platform nil}}{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}{{end}}
|
||||
Version: {{.Version}}
|
||||
API version: {{.APIVersion}}{{if ne .APIVersion .DefaultAPIVersion}} (downgraded from {{.DefaultAPIVersion}}){{end}}
|
||||
Go version: {{.GoVersion}}
|
||||
@@ -31,7 +33,7 @@ Client:{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}
|
||||
Context: {{.Context}}
|
||||
{{- end}}
|
||||
|
||||
{{- if .ServerOK}}{{with .Server}}
|
||||
{{- if ne .Server nil}}{{with .Server}}
|
||||
|
||||
Server:{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}
|
||||
{{- range $component := .Components}}
|
||||
@@ -64,24 +66,45 @@ type versionInfo struct {
|
||||
Server *types.Version
|
||||
}
|
||||
|
||||
type clientVersion struct {
|
||||
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
|
||||
type platformInfo struct {
|
||||
Name string `json:"Name,omitempty"`
|
||||
}
|
||||
|
||||
// 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
|
||||
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"`
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// NewVersionCommand creates a new cobra.Command for `docker version`
|
||||
@@ -101,9 +124,7 @@ func NewVersionCommand(dockerCli command.Cli) *cobra.Command {
|
||||
ValidArgsFunction: completion.NoComplete,
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template")
|
||||
|
||||
cmd.Flags().StringVarP(&opts.format, "format", "f", "", flagsHelper.InspectFormatHelp)
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -133,20 +154,8 @@ func runVersion(dockerCli command.Cli, opts *versionOptions) error {
|
||||
// TODO print error if kubernetes is used?
|
||||
|
||||
vd := versionInfo{
|
||||
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(),
|
||||
},
|
||||
Client: newClientVersion(dockerCli.CurrentContext(), dockerCli),
|
||||
}
|
||||
|
||||
sv, err := dockerCli.Client().ServerVersion(context.Background())
|
||||
if err == nil {
|
||||
vd.Server = &sv
|
||||
@@ -194,8 +203,11 @@ func prettyPrintVersion(dockerCli command.Cli, vd versionInfo, tmpl *template.Te
|
||||
}
|
||||
|
||||
func newVersionTemplate(templateFormat string) (*template.Template, error) {
|
||||
if templateFormat == "" {
|
||||
templateFormat = versionTemplate
|
||||
switch templateFormat {
|
||||
case "":
|
||||
templateFormat = defaultVersionTemplate
|
||||
case formatter.JSONFormatKey:
|
||||
templateFormat = formatter.JSONFormat
|
||||
}
|
||||
tmpl := templates.New("version").Funcs(template.FuncMap{"getDetailsOrder": getDetailsOrder})
|
||||
tmpl, err := tmpl.Parse(templateFormat)
|
||||
|
||||
@@ -6,12 +6,11 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/docker/api/types"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/golden"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/docker/api/types"
|
||||
)
|
||||
|
||||
func TestVersionWithoutServer(t *testing.T) {
|
||||
@@ -30,7 +29,7 @@ func TestVersionWithoutServer(t *testing.T) {
|
||||
assert.Assert(t, !strings.Contains(out, "Server:"), "actual: %s", out)
|
||||
}
|
||||
|
||||
func TestVersionAlign(t *testing.T) {
|
||||
func TestVersionFormat(t *testing.T) {
|
||||
vi := versionInfo{
|
||||
Client: clientVersion{
|
||||
Version: "18.99.5-ce",
|
||||
@@ -104,10 +103,28 @@ func TestVersionAlign(t *testing.T) {
|
||||
},
|
||||
})
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
tmpl, err := newVersionTemplate("")
|
||||
assert.NilError(t, err)
|
||||
assert.NilError(t, prettyPrintVersion(cli, vi, tmpl))
|
||||
assert.Check(t, golden.String(cli.OutBuffer().String(), "docker-client-version.golden"))
|
||||
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
||||
t.Run("default", func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
tmpl, err := newVersionTemplate("")
|
||||
assert.NilError(t, err)
|
||||
assert.NilError(t, prettyPrintVersion(cli, vi, tmpl))
|
||||
assert.Check(t, golden.String(cli.OutBuffer().String(), "docker-client-version.golden"))
|
||||
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
||||
})
|
||||
t.Run("json", func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
tmpl, err := newVersionTemplate("json")
|
||||
assert.NilError(t, err)
|
||||
assert.NilError(t, prettyPrintVersion(cli, vi, tmpl))
|
||||
assert.Check(t, golden.String(cli.OutBuffer().String(), "docker-client-version.json.golden"))
|
||||
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
||||
})
|
||||
t.Run("json template", func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
tmpl, err := newVersionTemplate("{{json .}}")
|
||||
assert.NilError(t, err)
|
||||
assert.NilError(t, prettyPrintVersion(cli, vi, tmpl))
|
||||
assert.Check(t, golden.String(cli.OutBuffer().String(), "docker-client-version.json.golden"))
|
||||
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ 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"
|
||||
@@ -93,7 +94,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 := command.EncodeAuthToBase64(authConfig)
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ 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"`
|
||||
|
||||
@@ -25,12 +25,6 @@ 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,20 +494,6 @@ 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 {
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
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
|
||||
+16
-11
@@ -9,38 +9,42 @@ import (
|
||||
"github.com/moby/term"
|
||||
)
|
||||
|
||||
// In is an input stream used by the DockerCli to read user input
|
||||
// In is an input stream to read user input. It implements [io.ReadCloser]
|
||||
// with additional utilities, such as putting the terminal in raw mode.
|
||||
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 Closer interface
|
||||
// Close implements the [io.Closer] interface.
|
||||
func (i *In) Close() error {
|
||||
return i.in.Close()
|
||||
}
|
||||
|
||||
// SetRawTerminal sets raw mode on the input terminal
|
||||
// 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.
|
||||
func (i *In) SetRawTerminal() (err error) {
|
||||
if os.Getenv("NORAW") != "" || !i.commonStream.isTerminal {
|
||||
if !i.isTerminal || os.Getenv("NORAW") != "" {
|
||||
return nil
|
||||
}
|
||||
i.commonStream.state, err = term.SetRawTerminal(i.commonStream.fd)
|
||||
i.state, err = term.SetRawTerminal(i.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 {
|
||||
eText := "the input device is not a TTY"
|
||||
const 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'")
|
||||
}
|
||||
@@ -49,8 +53,9 @@ func (i *In) CheckTty(attachStdin, ttyMode bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewIn returns a new In object from a ReadCloser
|
||||
// NewIn returns a new [In] from an [io.ReadCloser].
|
||||
func NewIn(in io.ReadCloser) *In {
|
||||
fd, isTerminal := term.GetFdInfo(in)
|
||||
return &In{commonStream: commonStream{fd: fd, isTerminal: isTerminal}, in: in}
|
||||
i := &In{in: in}
|
||||
i.fd, i.isTerminal = term.GetFdInfo(in)
|
||||
return i
|
||||
}
|
||||
|
||||
+19
-11
@@ -8,8 +8,9 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Out is an output stream used by the DockerCli to write normal program
|
||||
// output.
|
||||
// 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.
|
||||
type Out struct {
|
||||
commonStream
|
||||
out io.Writer
|
||||
@@ -19,23 +20,29 @@ func (o *Out) Write(p []byte) (int, error) {
|
||||
return o.out.Write(p)
|
||||
}
|
||||
|
||||
// SetRawTerminal sets raw mode on the input terminal
|
||||
// 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.
|
||||
func (o *Out) SetRawTerminal() (err error) {
|
||||
if os.Getenv("NORAW") != "" || !o.commonStream.isTerminal {
|
||||
if !o.isTerminal || os.Getenv("NORAW") != "" {
|
||||
return nil
|
||||
}
|
||||
o.commonStream.state, err = term.SetRawTerminalOutput(o.commonStream.fd)
|
||||
o.state, err = term.SetRawTerminalOutput(o.fd)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetTtySize returns the height and width in characters of the tty
|
||||
func (o *Out) GetTtySize() (uint, uint) {
|
||||
// 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) {
|
||||
if !o.isTerminal {
|
||||
return 0, 0
|
||||
}
|
||||
ws, err := term.GetWinsize(o.fd)
|
||||
if err != nil {
|
||||
logrus.Debugf("Error getting size: %s", err)
|
||||
logrus.WithError(err).Debug("Error getting TTY size")
|
||||
if ws == nil {
|
||||
return 0, 0
|
||||
}
|
||||
@@ -43,8 +50,9 @@ func (o *Out) GetTtySize() (uint, uint) {
|
||||
return uint(ws.Height), uint(ws.Width)
|
||||
}
|
||||
|
||||
// NewOut returns a new Out object from a Writer
|
||||
// NewOut returns a new [Out] from an [io.Writer].
|
||||
func NewOut(out io.Writer) *Out {
|
||||
fd, isTerminal := term.GetFdInfo(out)
|
||||
return &Out{commonStream: commonStream{fd: fd, isTerminal: isTerminal}, out: out}
|
||||
o := &Out{out: out}
|
||||
o.fd, o.isTerminal = term.GetFdInfo(out)
|
||||
return o
|
||||
}
|
||||
|
||||
@@ -4,31 +4,32 @@ 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 sets the boolean used for isTerminal
|
||||
// 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.
|
||||
func (s *commonStream) SetIsTerminal(isTerminal bool) {
|
||||
s.isTerminal = isTerminal
|
||||
}
|
||||
|
||||
@@ -1155,7 +1155,20 @@ __docker_complete_plugin() {
|
||||
resultArray+=( "$value" )
|
||||
fi
|
||||
done
|
||||
local result=$(eval "${resultArray[*]}" 2> /dev/null | grep -v '^:[0-9]*$')
|
||||
local rawResult=$(eval "${resultArray[*]}" 2> /dev/null)
|
||||
local result=$(grep -v '^:[0-9]*$' <<< "$rawResult")
|
||||
|
||||
# Compose V2 completions sometimes returns returns `:8` (ShellCompDirectiveFilterFileExt)
|
||||
# with the expected file extensions (such as `yml`, `yaml`) to indicate that the shell should
|
||||
# provide autocompletions for files with matching extensions
|
||||
local completionFlag=$(tail -1 <<< "$rawResult")
|
||||
if [ "$completionFlag" == ":8" ]; then
|
||||
# format a valid glob pattern for the provided file extensions
|
||||
local filePattern=$(tr '\n' '|' <<< "$result")
|
||||
|
||||
_filedir "$filePattern"
|
||||
return
|
||||
fi
|
||||
|
||||
# if result empty, just use filename completion as fallback
|
||||
if [ -z "$result" ]; then
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
variable "GO_VERSION" {
|
||||
default = "1.20.2"
|
||||
default = "1.20.3"
|
||||
}
|
||||
variable "VERSION" {
|
||||
default = ""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.20.2
|
||||
ARG GO_VERSION=1.20.3
|
||||
ARG ALPINE_VERSION=3.16
|
||||
|
||||
ARG BUILDX_VERSION=0.10.4
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.20.2
|
||||
ARG GO_VERSION=1.20.3
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG GOLANGCI_LINT_VERSION=v1.52.2
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.20.2
|
||||
ARG GO_VERSION=1.20.3
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG MODOUTDATED_VERSION=v0.8.0
|
||||
|
||||
|
||||
+2
-1
@@ -50,7 +50,7 @@ The table below provides an overview of the current status of deprecated feature
|
||||
|
||||
| Status | Feature | Deprecated | Remove |
|
||||
|------------|------------------------------------------------------------------------------------------------------------------------------------|------------|---------|
|
||||
| Deprecated | [Buildkit build information](#buildkit-build-information) | v23.0.0 | v23.1.0 |
|
||||
| Removed | [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 |
|
||||
@@ -108,6 +108,7 @@ The table below provides an overview of the current status of deprecated feature
|
||||
### Buildkit build information
|
||||
|
||||
**Deprecated in Release: v23.0.0**
|
||||
**Removed in Release: v24.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)
|
||||
|
||||
@@ -661,7 +661,7 @@ The `--squash` option has a number of known limitations:
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
The example on this page is using experimental mode in Docker 19.03.
|
||||
The example on this page is using experimental mode in Docker 23.03.
|
||||
|
||||
Experimental mode can be enabled by using the `--experimental` flag when starting
|
||||
the Docker daemon or setting `experimental: true` in the `daemon.json` configuration
|
||||
@@ -673,21 +673,21 @@ line in the `Engine` section:
|
||||
|
||||
```console
|
||||
Client: Docker Engine - Community
|
||||
Version: 19.03.8
|
||||
API version: 1.40
|
||||
Go version: go1.12.17
|
||||
Git commit: afacb8b
|
||||
Built: Wed Mar 11 01:21:11 2020
|
||||
Version: 23.0.3
|
||||
API version: 1.42
|
||||
Go version: go1.19.7
|
||||
Git commit: 3e7cbfd
|
||||
Built: Tue Apr 4 22:05:41 2023
|
||||
OS/Arch: darwin/amd64
|
||||
Experimental: false
|
||||
Context: default
|
||||
|
||||
Server: Docker Engine - Community
|
||||
Engine:
|
||||
Version: 19.03.8
|
||||
API version: 1.40 (minimum version 1.12)
|
||||
Go version: go1.12.17
|
||||
Git commit: afacb8b
|
||||
Built: Wed Mar 11 01:29:16 2020
|
||||
Version: 23.0.3
|
||||
API version: 1.42 (minimum version 1.12)
|
||||
Go version: go1.19.7
|
||||
Git commit: 59118bf
|
||||
Built: Tue Apr 4 22:05:41 2023
|
||||
OS/Arch: linux/amd64
|
||||
Experimental: true
|
||||
[...]
|
||||
|
||||
@@ -123,30 +123,31 @@ the [installation](https://docs.docker.com/install/) instructions for your opera
|
||||
The following list of environment variables are supported by the `docker` command
|
||||
line:
|
||||
|
||||
| Variable | Description |
|
||||
|:------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `DOCKER_API_VERSION` | Override the negotiated API version to use for debugging (e.g. `1.19`) |
|
||||
| `DOCKER_CERT_PATH` | Location of your authentication keys. This variable is used both by the `docker` CLI and the [`dockerd` daemon](dockerd.md) |
|
||||
| `DOCKER_CONFIG` | The location of your client configuration files. |
|
||||
| `DOCKER_CONTENT_TRUST_SERVER` | The URL of the Notary server to use. Defaults to the same URL as the registry. |
|
||||
| `DOCKER_CONTENT_TRUST` | When set Docker uses notary to sign and verify images. Equates to `--disable-content-trust=false` for build, create, pull, push, run. |
|
||||
| `DOCKER_CONTEXT` | Name of the `docker context` to use (overrides `DOCKER_HOST` env var and default context set with `docker context use`) |
|
||||
| `DOCKER_DEFAULT_PLATFORM` | Default platform for commands that take the `--platform` flag. |
|
||||
| `DOCKER_HIDE_LEGACY_COMMANDS` | When set, Docker hides "legacy" top-level commands (such as `docker rm`, and `docker pull`) in `docker help` output, and only `Management commands` per object-type (e.g., `docker container`) are printed. This may become the default in a future release, at which point this environment-variable is removed. |
|
||||
| `DOCKER_HOST` | Daemon socket to connect to. |
|
||||
| `DOCKER_TLS_VERIFY` | When set Docker uses TLS and verifies the remote. This variable is used both by the `docker` CLI and the [`dockerd` daemon](dockerd.md) |
|
||||
| `BUILDKIT_PROGRESS` | Set type of progress output (`auto`, `plain`, `tty`) when [building](build.md) with [BuildKit backend](https://docs.docker.com/build/buildkit/). Use plain to show container output (default `auto`). |
|
||||
| Variable | Description |
|
||||
|:------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `DOCKER_API_VERSION` | Override the negotiated API version to use for debugging (e.g. `1.19`) |
|
||||
| `DOCKER_CERT_PATH` | Location of your authentication keys. This variable is used both by the `docker` CLI and the [`dockerd` daemon](dockerd.md) |
|
||||
| `DOCKER_CONFIG` | The location of your client configuration files. |
|
||||
| `DOCKER_CONTENT_TRUST_SERVER` | The URL of the Notary server to use. Defaults to the same URL as the registry. |
|
||||
| `DOCKER_CONTENT_TRUST` | When set Docker uses notary to sign and verify images. Equates to `--disable-content-trust=false` for build, create, pull, push, run. |
|
||||
| `DOCKER_CONTEXT` | Name of the `docker context` to use (overrides `DOCKER_HOST` env var and default context set with `docker context use`) |
|
||||
| `DOCKER_DEFAULT_PLATFORM` | Default platform for commands that take the `--platform` flag. |
|
||||
| `DOCKER_HIDE_LEGACY_COMMANDS` | When set, Docker hides "legacy" top-level commands (such as `docker rm`, and `docker pull`) in `docker help` output, and only `Management commands` per object-type (e.g., `docker container`) are printed. This may become the default in a future release. |
|
||||
| `DOCKER_HOST` | Daemon socket to connect to. |
|
||||
| `DOCKER_TLS_VERIFY` | When set Docker uses TLS and verifies the remote. This variable is used both by the `docker` CLI and the [`dockerd` daemon](dockerd.md) |
|
||||
| `BUILDKIT_PROGRESS` | Set type of progress output (`auto`, `plain`, `tty`) when [building](build.md) with [BuildKit backend](https://docs.docker.com/build/buildkit/). Use plain to show container output (default `auto`). |
|
||||
|
||||
Because Docker is developed using Go, you can also use any environment
|
||||
variables used by the Go runtime. In particular, you may find these useful:
|
||||
|
||||
* `HTTP_PROXY`
|
||||
* `HTTPS_PROXY`
|
||||
* `NO_PROXY`
|
||||
| Variable | Description |
|
||||
|:--------------|:-------------------------------------------------------------------------------|
|
||||
| `HTTP_PROXY` | Proxy URL for HTTP requests unless overridden by NoProxy. |
|
||||
| `HTTPS_PROXY` | Proxy URL for HTTPS requests unless overridden by NoProxy. |
|
||||
| `NO_PROXY` | Comma-separated values specifying hosts that should be excluded from proxying. |
|
||||
|
||||
These Go environment variables are case-insensitive. See the
|
||||
[Go specification](https://golang.org/pkg/net/http/) for details on these
|
||||
variables.
|
||||
See the [Go specification](https://pkg.go.dev/golang.org/x/net/http/httpproxy#Config)
|
||||
for details on these variables.
|
||||
|
||||
## Configuration files
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Remove one or more containers
|
||||
|
||||
### Aliases
|
||||
|
||||
`docker container rm`, `docker rm`
|
||||
`docker container rm`, `docker container remove`, `docker rm`
|
||||
|
||||
### Options
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ redirect_from:
|
||||
# daemon
|
||||
|
||||
```markdown
|
||||
Usage: dockerd COMMAND
|
||||
Usage: dockerd [OPTIONS]
|
||||
|
||||
A self-sufficient runtime for containers.
|
||||
|
||||
@@ -35,14 +35,14 @@ Options:
|
||||
--containerd-namespace string Containerd namespace to use (default "moby")
|
||||
--containerd-plugins-namespace string Containerd namespace to use for plugins (default "plugins.moby")
|
||||
--cpu-rt-period int Limit the CPU real-time period in microseconds for the
|
||||
parent cgroup for all containers
|
||||
parent cgroup for all containers (not supported with cgroups v2)
|
||||
--cpu-rt-runtime int Limit the CPU real-time runtime in microseconds for the
|
||||
parent cgroup for all containers
|
||||
parent cgroup for all containers (not supported with cgroups v2)
|
||||
--cri-containerd start containerd with cri
|
||||
--data-root string Root directory of persistent Docker state (default "/var/lib/docker")
|
||||
-D, --debug Enable debug mode
|
||||
--default-address-pool pool-options Default address pools for node specific local networks
|
||||
--default-cgroupns-mode string Default mode for containers cgroup namespace ("host" | "private") (default "host")
|
||||
--default-cgroupns-mode string Default mode for containers cgroup namespace ("host" | "private") (default "private")
|
||||
--default-gateway ip Container default gateway IPv4 address
|
||||
--default-gateway-v6 ip Container default gateway IPv6 address
|
||||
--default-ipc-mode string Default mode for containers ipc ("shareable" | "private") (default "private")
|
||||
@@ -62,6 +62,8 @@ Options:
|
||||
-H, --host list Daemon socket(s) to connect to
|
||||
--host-gateway-ip ip IP address that the special 'host-gateway' string in --add-host resolves to.
|
||||
Defaults to the IP address of the default bridge
|
||||
--http-proxy string HTTP proxy URL to use for outgoing traffic
|
||||
--https-proxy string HTTPS proxy URL to use for outgoing traffic
|
||||
--icc Enable inter-container communication (default true)
|
||||
--init Run an init in the container to forward signals and reap processes
|
||||
--init-path string Path to the docker-init binary
|
||||
@@ -69,8 +71,8 @@ Options:
|
||||
--ip ip Default IP when binding container ports (default 0.0.0.0)
|
||||
--ip-forward Enable net.ipv4.ip_forward (default true)
|
||||
--ip-masq Enable IP masquerading (default true)
|
||||
--ip6tables Enable addition of ip6tables rules (experimental)
|
||||
--iptables Enable addition of iptables rules (default true)
|
||||
--ip6tables Enable addition of ip6tables rules (default false)
|
||||
--ipv6 Enable IPv6 networking
|
||||
--label list Set key=value labels to the daemon
|
||||
--live-restore Enable live restore of docker when containers are still running
|
||||
@@ -81,16 +83,17 @@ Options:
|
||||
--max-concurrent-uploads int Set the max concurrent uploads (default 5)
|
||||
--max-download-attempts int Set the max download attempts for each pull (default 5)
|
||||
--metrics-addr string Set default address and port to serve the metrics api on
|
||||
--mtu int Set the containers network MTU
|
||||
--mtu int Set the containers network MTU (default 1500)
|
||||
--network-control-plane-mtu int Network Control plane MTU (default 1500)
|
||||
--no-new-privileges Set no-new-privileges by default for new containers
|
||||
--no-proxy string Comma-separated list of hosts or IP addresses for which the proxy is skipped
|
||||
--node-generic-resource list Advertise user-defined resource
|
||||
--oom-score-adjust int Set the oom_score_adj for the daemon (default -500)
|
||||
--oom-score-adjust int Set the oom_score_adj for the daemon
|
||||
-p, --pidfile string Path to use for daemon PID file (default "/var/run/docker.pid")
|
||||
--raw-logs Full timestamps without ANSI coloring
|
||||
--registry-mirror list Preferred registry mirror
|
||||
--rootless Enable rootless mode; typically used with RootlessKit
|
||||
--seccomp-profile string Path to seccomp profile
|
||||
--seccomp-profile string Path to seccomp profile. Use "unconfined" to disable the default seccomp profile (default "builtin")
|
||||
--selinux-enabled Enable selinux support
|
||||
--shutdown-timeout int Set the default shutdown timeout (default 15)
|
||||
-s, --storage-driver string Storage driver to use
|
||||
@@ -129,16 +132,42 @@ to [the `daemon.json` file](#daemon-configuration-file).
|
||||
For easy reference, the following list of environment variables are supported
|
||||
by the `dockerd` command line:
|
||||
|
||||
* `DOCKER_DRIVER` The graph driver to use.
|
||||
* `DOCKER_NOWARN_KERNEL_VERSION` Prevent warnings that your Linux kernel is
|
||||
unsuitable for Docker.
|
||||
* `DOCKER_RAMDISK` If set this will disable 'pivot_root'.
|
||||
* `DOCKER_TMPDIR` Location for temporary Docker files.
|
||||
* `MOBY_DISABLE_PIGZ` Do not use [`unpigz`](https://linux.die.net/man/1/pigz) to
|
||||
decompress layers in parallel when pulling images, even if it is installed.
|
||||
| Variable | Description |
|
||||
|:--------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `DOCKER_CERT_PATH` | Location of your authentication keys. This variable is used both by the [`docker` CLI](cli.md) and the `dockerd` daemon. |
|
||||
| `DOCKER_DRIVER` | The storage driver to use. |
|
||||
| `DOCKER_RAMDISK` | If set this disables 'pivot_root'. |
|
||||
| `DOCKER_TLS_VERIFY` | When set Docker uses TLS and verifies the remote. This variable is used both by the [`docker` CLI](cli.md) and the `dockerd` daemon. |
|
||||
| `DOCKER_TMPDIR` | Location for temporary files created by the daemon. |
|
||||
| `HTTP_PROXY` | Proxy URL for HTTP requests unless overridden by NoProxy. See the [Go specification](https://pkg.go.dev/golang.org/x/net/http/httpproxy#Config) for details. |
|
||||
| `HTTPS_PROXY` | Proxy URL for HTTPS requests unless overridden by NoProxy. See the [Go specification](https://pkg.go.dev/golang.org/x/net/http/httpproxy#Config) for details. |
|
||||
| `MOBY_DISABLE_PIGZ` | Disables the use of [`unpigz`](https://linux.die.net/man/1/pigz) to decompress layers in parallel when pulling images, even if it is installed. | |
|
||||
| `NO_PROXY` | Comma-separated values specifying hosts that should be excluded from proxying. See the [Go specification](https://pkg.go.dev/golang.org/x/net/http/httpproxy#Config) for details. |
|
||||
|
||||
## Examples
|
||||
|
||||
### Proxy configuration
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Refer to the [Docker Desktop manual](https://docs.docker.com/desktop/networking/#httphttps-proxy-support)
|
||||
> if you are running [Docker Desktop](https://docs.docker.com/desktop/).
|
||||
|
||||
If you are behind an HTTP proxy server, for example in corporate settings,
|
||||
you may have to configure the Docker daemon to use the proxy server for
|
||||
operations such as pulling and pushing images. The daemon can be configured
|
||||
in three ways:
|
||||
|
||||
1. Using environment variables (`HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`).
|
||||
2. Using the "http-proxy", "https-proxy", and "no-proxy" fields in the
|
||||
[daemon configuration file](#daemon-configuration-file) (Docker Engine 23.0 or newer).
|
||||
3. Using the `--http-proxy`, `--https-proxy`, and `--no-proxy` command-line
|
||||
options. (Docker Engine 23.0 or newer).
|
||||
|
||||
The command-line and configuration file options take precedence over environment
|
||||
variables. Refer to [control and configure Docker with systemd](https://docs.docker.com/config/daemon/systemd/#httphttps-proxy)
|
||||
to set these environment variables on a host using `systemd`.
|
||||
|
||||
### Daemon socket option
|
||||
|
||||
The Docker daemon can listen for [Docker Engine API](https://docs.docker.com/engine/api/)
|
||||
@@ -1222,6 +1251,9 @@ This is a full example of the allowed configuration options on Linux:
|
||||
"fixed-cidr-v6": "",
|
||||
"group": "",
|
||||
"hosts": [],
|
||||
"http-proxy": "http://proxy.example.com:80",
|
||||
"https-proxy": "https://proxy.example.com:443",
|
||||
"no-proxy": "*.test.example.com,.example.org",
|
||||
"icc": false,
|
||||
"init": false,
|
||||
"init-path": "/usr/libexec/docker-init",
|
||||
@@ -1255,7 +1287,7 @@ This is a full example of the allowed configuration options on Linux:
|
||||
"NVIDIA-GPU=UUID1",
|
||||
"NVIDIA-GPU=UUID2"
|
||||
],
|
||||
"oom-score-adjust": -500,
|
||||
"oom-score-adjust": 0,
|
||||
"pidfile": "",
|
||||
"raw-logs": false,
|
||||
"registry-mirrors": [],
|
||||
|
||||
@@ -9,9 +9,9 @@ Display system-wide information
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:---------------------------------------|:---------|:--------|:----------------------------------------------|
|
||||
| [`-f`](#format), [`--format`](#format) | `string` | | Format the output using the given Go template |
|
||||
| Name | Type | Default | Description |
|
||||
|:---------------------------------------|:---------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [`-f`](#format), [`--format`](#format) | `string` | | Format output using a custom template:<br>'json': Print in JSON format<br>'TEMPLATE': Print output using the given Go template.<br>Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
@@ -47,19 +47,17 @@ information about the `overlay2` storage driver is shown:
|
||||
```console
|
||||
$ docker info
|
||||
|
||||
Client:
|
||||
Client: Docker Engine - Community
|
||||
Version: 24.0.0
|
||||
Context: default
|
||||
Debug Mode: false
|
||||
Plugins:
|
||||
buildx: Docker Buildx (Docker Inc.)
|
||||
Version: v0.8.2
|
||||
Version: v0.10.4
|
||||
Path: /usr/libexec/docker/cli-plugins/docker-buildx
|
||||
compose: Docker Compose (Docker Inc.)
|
||||
Version: v2.6.0
|
||||
Version: v2.17.2
|
||||
Path: /usr/libexec/docker/cli-plugins/docker-compose
|
||||
scan: Docker Scan (Docker Inc.)
|
||||
Version: v0.17.0
|
||||
Path: /usr/libexec/docker/cli-plugins/docker-scan
|
||||
|
||||
Server:
|
||||
Containers: 14
|
||||
@@ -67,7 +65,7 @@ Server:
|
||||
Paused: 1
|
||||
Stopped: 10
|
||||
Images: 52
|
||||
Server Version: 22.06.0
|
||||
Server Version: 23.0.3
|
||||
Storage Driver: overlay2
|
||||
Backing Filesystem: extfs
|
||||
Supports d_type: true
|
||||
@@ -82,11 +80,11 @@ Server:
|
||||
Network: bridge host ipvlan macvlan null overlay
|
||||
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
|
||||
Swarm: inactive
|
||||
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
|
||||
Runtimes: io.containerd.runc.v2 runc
|
||||
Default Runtime: runc
|
||||
Init Binary: docker-init
|
||||
containerd version: 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16
|
||||
runc version: v1.1.1-0-g52de29d
|
||||
containerd version: 2806fc1057397dbaeefbea0e4e17bddfbd388f38
|
||||
runc version: v1.1.5-0-gf19387a
|
||||
init version: de40ad0
|
||||
Security Options:
|
||||
apparmor
|
||||
@@ -104,9 +102,8 @@ Server:
|
||||
Docker Root Dir: /var/lib/docker
|
||||
Debug Mode: false
|
||||
Username: gordontheturtle
|
||||
Registry: https://index.docker.io/v1/
|
||||
Experimental: false
|
||||
Insecure registries:
|
||||
Insecure Registries:
|
||||
myinsecurehost:5000
|
||||
127.0.0.0/8
|
||||
Live Restore Enabled: false
|
||||
@@ -119,7 +116,7 @@ You can also specify the output format:
|
||||
```console
|
||||
$ docker info --format '{{json .}}'
|
||||
|
||||
{"ID":"I54V:OLXT:HVMM:TPKO:JPHQ:CQCD:JNLC:O3BZ:4ZVJ:43XJ:PFHZ:6N2S","Containers":14, ...}
|
||||
{"ID":"4cee4408-10d2-4e17-891c-a41736ac4536","Containers":14, ...}
|
||||
```
|
||||
|
||||
### Run `docker info` on Windows
|
||||
@@ -129,13 +126,17 @@ Here is a sample output for a daemon running on Windows Server:
|
||||
```console
|
||||
C:\> docker info
|
||||
|
||||
Client:
|
||||
Client: Docker Engine - Community
|
||||
Version: 24.0.0
|
||||
Context: default
|
||||
Debug Mode: false
|
||||
Plugins:
|
||||
buildx: Docker Buildx (Docker Inc., v0.8.2-docker)
|
||||
compose: Docker Compose (Docker Inc., v2.6.0)
|
||||
scan: Docker Scan (Docker Inc., v0.17.0)
|
||||
buildx: Docker Buildx (Docker Inc.)
|
||||
Version: v0.10.4
|
||||
Path: C:\Program Files\Docker\cli-plugins\docker-buildx.exe
|
||||
compose: Docker Compose (Docker Inc.)
|
||||
Version: v2.17.2
|
||||
Path: C:\Program Files\Docker\cli-plugins\docker-compose.exe
|
||||
|
||||
Server:
|
||||
Containers: 1
|
||||
@@ -143,7 +144,7 @@ Server:
|
||||
Paused: 0
|
||||
Stopped: 1
|
||||
Images: 17
|
||||
Server Version: 20.10.16
|
||||
Server Version: 23.0.3
|
||||
Storage Driver: windowsfilter
|
||||
Logging Driver: json-file
|
||||
Plugins:
|
||||
@@ -162,7 +163,6 @@ 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
|
||||
|
||||
@@ -110,10 +110,10 @@ Show all nodes that have a `region` node label set:
|
||||
$ docker node ls --filter node.label=region
|
||||
|
||||
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
|
||||
yg550ettvsjn6g6t840iaiwgb * swarm-test-01 Ready Active Leader 20.10.2
|
||||
2lm9w9kbepgvkzkkeyku40e65 swarm-test-02 Ready Active Reachable 20.10.2
|
||||
hc0pu7ntc7s4uvj4pv7z7pz15 swarm-test-03 Ready Active Reachable 20.10.2
|
||||
n41b2cijmhifxxvz56vwrs12q swarm-test-04 Ready Active 20.10.2
|
||||
yg550ettvsjn6g6t840iaiwgb * swarm-test-01 Ready Active Leader 23.0.3
|
||||
2lm9w9kbepgvkzkkeyku40e65 swarm-test-02 Ready Active Reachable 23.0.3
|
||||
hc0pu7ntc7s4uvj4pv7z7pz15 swarm-test-03 Ready Active Reachable 23.0.3
|
||||
n41b2cijmhifxxvz56vwrs12q swarm-test-04 Ready Active 23.0.3
|
||||
```
|
||||
|
||||
Show all nodes that have a `region` node label, with value `region-a`:
|
||||
@@ -122,8 +122,8 @@ Show all nodes that have a `region` node label, with value `region-a`:
|
||||
$ docker node ls --filter node.label=region=region-a
|
||||
|
||||
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
|
||||
yg550ettvsjn6g6t840iaiwgb * swarm-test-01 Ready Active Leader 20.10.2
|
||||
2lm9w9kbepgvkzkkeyku40e65 swarm-test-02 Ready Active Reachable 20.10.2
|
||||
yg550ettvsjn6g6t840iaiwgb * swarm-test-01 Ready Active Leader 23.0.3
|
||||
2lm9w9kbepgvkzkkeyku40e65 swarm-test-02 Ready Active Reachable 23.0.3
|
||||
```
|
||||
|
||||
#### membership
|
||||
@@ -203,7 +203,7 @@ e216jshn25ckzbvmwlnh5jr3g: swarm-manager1 Ready
|
||||
To list all nodes in JSON format, use the `json` directive:
|
||||
```console
|
||||
$ docker node ls --format json
|
||||
{"Availability":"Active","EngineVersion":"20.10.5","Hostname":"docker-desktop","ID":"k8f4w7qtzpj5sqzclcqafw35g","ManagerStatus":"Leader","Self":true,"Status":"Ready","TLSStatus":"Ready"}
|
||||
{"Availability":"Active","EngineVersion":"23.0.3","Hostname":"docker-desktop","ID":"k8f4w7qtzpj5sqzclcqafw35g","ManagerStatus":"Leader","Self":true,"Status":"Ready","TLSStatus":"Ready"}
|
||||
```
|
||||
|
||||
## Related commands
|
||||
|
||||
@@ -34,10 +34,8 @@ use `docker pull`.
|
||||
|
||||
If you are behind an HTTP proxy server, for example in corporate settings,
|
||||
before open a connect to registry, you may need to configure the Docker
|
||||
daemon's proxy settings, using the `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`
|
||||
environment variables. To set these environment variables on a host using
|
||||
`systemd`, refer to the [control and configure Docker with systemd](https://docs.docker.com/config/daemon/systemd/#httphttps-proxy)
|
||||
for variables configuration.
|
||||
daemon's proxy settings, refer to the [dockerd command-line reference](dockerd.md#proxy-configuration)
|
||||
for details.
|
||||
|
||||
### Concurrent downloads
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Remove one or more containers
|
||||
|
||||
### Aliases
|
||||
|
||||
`docker container rm`, `docker rm`
|
||||
`docker container rm`, `docker container remove`, `docker rm`
|
||||
|
||||
### Options
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ Display system-wide information
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:-----------------|:---------|:--------|:----------------------------------------------|
|
||||
| `-f`, `--format` | `string` | | Format the output using the given Go template |
|
||||
| Name | Type | Default | Description |
|
||||
|:-----------------|:---------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `-f`, `--format` | `string` | | Format output using a custom template:<br>'json': Print in JSON format<br>'TEMPLATE': Print output using the given Go template.<br>Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,9 +5,9 @@ Show the Docker version information
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:---------------------------------------|:---------|:--------|:----------------------------------------------|
|
||||
| [`-f`](#format), [`--format`](#format) | `string` | | Format the output using the given Go template |
|
||||
| Name | Type | Default | Description |
|
||||
|:---------------------------------------|:---------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [`-f`](#format), [`--format`](#format) | `string` | | Format output using a custom template:<br>'json': Print in JSON format<br>'TEMPLATE': Print output using the given Go template.<br>Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
@@ -37,30 +37,30 @@ machine running Docker Desktop:
|
||||
```console
|
||||
$ docker version
|
||||
|
||||
Client:
|
||||
Version: 20.10.16
|
||||
API version: 1.41
|
||||
Go version: go1.17.10
|
||||
Git commit: aa7e414
|
||||
Built: Thu May 12 09:17:28 2022
|
||||
Client: Docker Engine - Community
|
||||
Version: 23.0.3
|
||||
API version: 1.42
|
||||
Go version: go1.19.7
|
||||
Git commit: 3e7cbfd
|
||||
Built: Tue Apr 4 22:05:41 2023
|
||||
OS/Arch: darwin/amd64
|
||||
Context: default
|
||||
|
||||
Server: Docker Desktop 4.8.2 (77141)
|
||||
Server: Docker Desktop 4.19.0 (12345)
|
||||
Engine:
|
||||
Version: 20.10.16
|
||||
API version: 1.41 (minimum version 1.12)
|
||||
Go version: go1.17.10
|
||||
Git commit: f756502
|
||||
Built: Thu May 12 09:15:33 2022
|
||||
Version: 23.0.3
|
||||
API version: 1.42 (minimum version 1.12)
|
||||
Go version: go1.19.7
|
||||
Git commit: 59118bf
|
||||
Built: Tue Apr 4 22:05:41 2023
|
||||
OS/Arch: linux/amd64
|
||||
Experimental: false
|
||||
containerd:
|
||||
Version: 1.6.4
|
||||
GitCommit: 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16
|
||||
Version: 1.6.20
|
||||
GitCommit: 2806fc1057397dbaeefbea0e4e17bddfbd388f38
|
||||
runc:
|
||||
Version: 1.1.1
|
||||
GitCommit: v1.1.1-0-g52de29d
|
||||
Version: 1.1.5
|
||||
GitCommit: v1.1.5-0-gf19387a
|
||||
docker-init:
|
||||
Version: 0.19.0
|
||||
GitCommit: de40ad0
|
||||
@@ -82,12 +82,12 @@ remote-test-server
|
||||
|
||||
$ docker version
|
||||
|
||||
Client:
|
||||
Version: 20.10.16
|
||||
API version: 1.40 (downgraded from 1.41)
|
||||
Go version: go1.17.10
|
||||
Git commit: aa7e414
|
||||
Built: Thu May 12 09:17:28 2022
|
||||
Client: Docker Engine - Community
|
||||
Version: 23.0.3
|
||||
API version: 1.40 (downgraded from 1.42)
|
||||
Go version: go1.19.7
|
||||
Git commit: 3e7cbfd
|
||||
Built: Tue Apr 4 22:05:41 2023
|
||||
OS/Arch: darwin/amd64
|
||||
Context: remote-test-server
|
||||
|
||||
@@ -142,7 +142,7 @@ $ docker version --format '{{.Client.APIVersion}}'
|
||||
|
||||
$ unset DOCKER_API_VERSION
|
||||
$ docker version --format '{{.Client.APIVersion}}'
|
||||
1.41
|
||||
1.42
|
||||
```
|
||||
|
||||
## Examples
|
||||
@@ -159,7 +159,7 @@ page for details of the format.
|
||||
```console
|
||||
$ docker version --format '{{.Server.Version}}'
|
||||
|
||||
20.10.16
|
||||
23.0.3
|
||||
```
|
||||
|
||||
### Get the client API version
|
||||
@@ -169,7 +169,7 @@ The following example prints the API version that is used by the client:
|
||||
```console
|
||||
$ docker version --format '{{.Client.APIVersion}}'
|
||||
|
||||
1.41
|
||||
1.42
|
||||
```
|
||||
|
||||
The version shown is the API version that is negotiated between the client
|
||||
@@ -181,5 +181,5 @@ above for more information.
|
||||
```console
|
||||
$ docker version --format '{{json .}}'
|
||||
|
||||
{"Client":{"Platform":{"Name":"Docker Engine - Community"},"Version":"19.03.8","ApiVersion":"1.40","DefaultAPIVersion":"1.40","GitCommit":"afacb8b","GoVersion":"go1.12.17","Os":"darwin","Arch":"amd64","BuildTime":"Wed Mar 11 01:21:11 2020","Experimental":true},"Server":{"Platform":{"Name":"Docker Engine - Community"},"Components":[{"Name":"Engine","Version":"19.03.8","Details":{"ApiVersion":"1.40","Arch":"amd64","BuildTime":"Wed Mar 11 01:29:16 2020","Experimental":"true","GitCommit":"afacb8b","GoVersion":"go1.12.17","KernelVersion":"4.19.76-linuxkit","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"containerd","Version":"v1.2.13","Details":{"GitCommit":"7ad184331fa3e55e52b890ea95e65ba581ae3429"}},{"Name":"runc","Version":"1.0.0-rc10","Details":{"GitCommit":"dc9208a3303feef5b3839f4323d9beb36df0a9dd"}},{"Name":"docker-init","Version":"0.18.0","Details":{"GitCommit":"fec3683"}}],"Version":"19.03.8","ApiVersion":"1.40","MinAPIVersion":"1.12","GitCommit":"afacb8b","GoVersion":"go1.12.17","Os":"linux","Arch":"amd64","KernelVersion":"4.19.76-linuxkit","Experimental":true,"BuildTime":"2020-03-11T01:29:16.000000000+00:00"}}
|
||||
{"Client":"Version":"23.0.3","ApiVersion":"1.42", ...}
|
||||
```
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.20.2
|
||||
ARG GO_VERSION=1.20.3
|
||||
|
||||
FROM golang:${GO_VERSION}-alpine AS generated
|
||||
RUN go install github.com/dmcgowan/quicktls@master
|
||||
|
||||
+16
-4
@@ -35,6 +35,8 @@ dockerd - Enable daemon mode
|
||||
[**-G**|**--group**[=*docker*]]
|
||||
[**-H**|**--host**[=*[]*]]
|
||||
[**--help**]
|
||||
[**--http-proxy**[*""*]]
|
||||
[**--https-proxy**[*""*]]
|
||||
[**--icc**[=*true*]]
|
||||
[**--init**[=*false*]]
|
||||
[**--init-path**[=*""*]]
|
||||
@@ -54,6 +56,7 @@ dockerd - Enable daemon mode
|
||||
[**--max-concurrent-downloads**[=*3*]]
|
||||
[**--max-concurrent-uploads**[=*5*]]
|
||||
[**--max-download-attempts**[=*5*]]
|
||||
[**--no-proxy**[*""*]]
|
||||
[**--node-generic-resources**[=*[]*]]
|
||||
[**-p**|**--pidfile**[=*/var/run/docker.pid*]]
|
||||
[**--raw-logs**]
|
||||
@@ -151,7 +154,7 @@ $ sudo dockerd --add-runtime runc=runc --add-runtime custom=/usr/local/bin/my-ru
|
||||
Set parent cgroup for all containers. Default is "/docker" for fs cgroup
|
||||
driver and "system.slice" for systemd cgroup driver.
|
||||
|
||||
**--config-file**="/etc/docker/daemon.json"
|
||||
**--config-file**=*"/etc/docker/daemon.json"*
|
||||
Specifies the JSON file path to load the configuration from.
|
||||
|
||||
**--containerd**=""
|
||||
@@ -165,7 +168,7 @@ $ sudo dockerd --add-runtime runc=runc --add-runtime custom=/usr/local/bin/my-ru
|
||||
**-D**, **--debug**=*true*|*false*
|
||||
Enable debug mode. Default is false.
|
||||
|
||||
**--default-cgroupns-mode**="**host**|**private**"
|
||||
**--default-cgroupns-mode**="*host*|*private*"
|
||||
Set the default cgroup namespace mode for newly created containers. The argument
|
||||
can either be **host** or **private**. If unset, this defaults to `host` on cgroup v1,
|
||||
`private` on cgroup v2.
|
||||
@@ -182,10 +185,10 @@ $ sudo dockerd --add-runtime runc=runc --add-runtime custom=/usr/local/bin/my-ru
|
||||
Example: base=172.30.0.0/16,size=24 will set the default
|
||||
address pools for the selected scope networks to {172.30.[0-255].0/24}
|
||||
|
||||
**--default-runtime**="runc"
|
||||
**--default-runtime**=*"runc"*
|
||||
Set default runtime if there're more than one specified by `--add-runtime`.
|
||||
|
||||
**--default-ipc-mode**="**private**|**shareable**"
|
||||
**--default-ipc-mode**="*private*|*shareable*"
|
||||
Set the default IPC mode for newly created containers. The argument
|
||||
can either be **private** or **shareable**.
|
||||
|
||||
@@ -233,6 +236,12 @@ unix://[/path/to/socket] to use.
|
||||
**--help**
|
||||
Print usage statement
|
||||
|
||||
**--http-proxy***""*
|
||||
Proxy URL for HTTP requests unless overridden by NoProxy.
|
||||
|
||||
**--https-proxy***""*
|
||||
Proxy URL for HTTPS requests unless overridden by NoProxy.
|
||||
|
||||
**--icc**=*true*|*false*
|
||||
Allow unrestricted inter\-container and Docker daemon host communication. If
|
||||
disabled, containers can still be linked together using the **--link** option
|
||||
@@ -325,6 +334,9 @@ unix://[/path/to/socket] to use.
|
||||
**--max-download-attempts**=*5*
|
||||
Set the max download attempts for each pull. Default is `5`.
|
||||
|
||||
**--no-proxy**=*""*"
|
||||
Comma-separated values specifying hosts that should be excluded from proxying.
|
||||
|
||||
**--node-generic-resources**=*[]*
|
||||
Advertise user-defined resource. Default is `[]`.
|
||||
Use this if your swarm cluster has some nodes with custom
|
||||
|
||||
+10
-13
@@ -27,19 +27,17 @@ information about the `overlay2` storage driver is shown:
|
||||
```console
|
||||
$ docker info
|
||||
|
||||
Client:
|
||||
Client: Docker Engine - Community
|
||||
Version: 24.0.0
|
||||
Context: default
|
||||
Debug Mode: false
|
||||
Plugins:
|
||||
buildx: Docker Buildx (Docker Inc.)
|
||||
Version: v0.8.2
|
||||
Version: v0.10.4
|
||||
Path: /usr/libexec/docker/cli-plugins/docker-buildx
|
||||
compose: Docker Compose (Docker Inc.)
|
||||
Version: v2.6.0
|
||||
Version: v2.17.2
|
||||
Path: /usr/libexec/docker/cli-plugins/docker-compose
|
||||
scan: Docker Scan (Docker Inc.)
|
||||
Version: v0.17.0
|
||||
Path: /usr/libexec/docker/cli-plugins/docker-scan
|
||||
|
||||
Server:
|
||||
Containers: 14
|
||||
@@ -47,7 +45,7 @@ Server:
|
||||
Paused: 1
|
||||
Stopped: 10
|
||||
Images: 52
|
||||
Server Version: 22.06.0
|
||||
Server Version: 23.0.3
|
||||
Storage Driver: overlay2
|
||||
Backing Filesystem: extfs
|
||||
Supports d_type: true
|
||||
@@ -62,11 +60,11 @@ Server:
|
||||
Network: bridge host ipvlan macvlan null overlay
|
||||
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
|
||||
Swarm: inactive
|
||||
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
|
||||
Runtimes: io.containerd.runc.v2 runc
|
||||
Default Runtime: runc
|
||||
Init Binary: docker-init
|
||||
containerd version: 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16
|
||||
runc version: v1.1.1-0-g52de29d
|
||||
containerd version: 2806fc1057397dbaeefbea0e4e17bddfbd388f38
|
||||
runc version: v1.1.5-0-gf19387a
|
||||
init version: de40ad0
|
||||
Security Options:
|
||||
apparmor
|
||||
@@ -84,9 +82,8 @@ Server:
|
||||
Docker Root Dir: /var/lib/docker
|
||||
Debug Mode: false
|
||||
Username: gordontheturtle
|
||||
Registry: https://index.docker.io/v1/
|
||||
Experimental: false
|
||||
Insecure registries:
|
||||
Insecure Registries:
|
||||
myinsecurehost:5000
|
||||
127.0.0.0/8
|
||||
Live Restore Enabled: false
|
||||
@@ -95,4 +92,4 @@ Server:
|
||||
You can also specify the output format:
|
||||
|
||||
$ docker info --format '{{json .}}'
|
||||
{"ID":"I54V:OLXT:HVMM:TPKO:JPHQ:CQCD:JNLC:O3BZ:4ZVJ:43XJ:PFHZ:6N2S","Containers":14, ...}
|
||||
{"ID":"4cee4408-10d2-4e17-891c-a41736ac4536","Containers":14, ...}
|
||||
|
||||
+40
-20
@@ -1,37 +1,57 @@
|
||||
This command displays version information for both the Docker client and
|
||||
daemon.
|
||||
The version command prints the current version number for all independently
|
||||
versioned Docker components.
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
## Display Docker version information
|
||||
|
||||
The default output:
|
||||
The default output renders all version information divided into two sections;
|
||||
the "Client" section contains information about the Docker CLI and client
|
||||
components, and the "Server" section contains information about the Docker
|
||||
Engine and components used by the Engine, such as the "Containerd" and "Runc"
|
||||
OCI Runtimes.
|
||||
|
||||
The information shown may differ depending on how you installed Docker and
|
||||
what components are in use. The following example shows the output on a macOS
|
||||
machine running Docker Desktop:
|
||||
|
||||
$ docker version
|
||||
Client:
|
||||
Version: 1.8.0
|
||||
API version: 1.20
|
||||
Go version: go1.4.2
|
||||
Git commit: f5bae0a
|
||||
Built: Tue Jun 23 17:56:00 UTC 2015
|
||||
OS/Arch: linux/amd64
|
||||
|
||||
Server:
|
||||
Version: 1.8.0
|
||||
API version: 1.20
|
||||
Go version: go1.4.2
|
||||
Git commit: f5bae0a
|
||||
Built: Tue Jun 23 17:56:00 UTC 2015
|
||||
OS/Arch: linux/amd64
|
||||
Client: Docker Engine - Community
|
||||
Version: 23.0.3
|
||||
API version: 1.42
|
||||
Go version: go1.19.7
|
||||
Git commit: 3e7cbfd
|
||||
Built: Tue Apr 4 22:05:41 2023
|
||||
OS/Arch: darwin/amd64
|
||||
Context: default
|
||||
|
||||
Server: Docker Desktop 4.19.0 (12345)
|
||||
Engine:
|
||||
Version: 23.0.3
|
||||
API version: 1.42 (minimum version 1.12)
|
||||
Go version: go1.19.7
|
||||
Git commit: 59118bf
|
||||
Built: Tue Apr 4 22:05:41 2023
|
||||
OS/Arch: linux/amd64
|
||||
Experimental: false
|
||||
containerd:
|
||||
Version: 1.6.20
|
||||
GitCommit: 2806fc1057397dbaeefbea0e4e17bddfbd388f38
|
||||
runc:
|
||||
Version: 1.1.5
|
||||
GitCommit: v1.1.5-0-gf19387a
|
||||
docker-init:
|
||||
Version: 0.19.0
|
||||
GitCommit: de40ad0
|
||||
|
||||
Get server version:
|
||||
|
||||
$ docker version --format '{{.Server.Version}}'
|
||||
1.8.0
|
||||
23.0.3
|
||||
|
||||
Dump raw data:
|
||||
|
||||
To view all available fields, you can use the format `{{json .}}`.
|
||||
|
||||
$ docker version --format '{{json .}}'
|
||||
{"Client":{"Version":"1.8.0","ApiVersion":"1.20","GitCommit":"f5bae0a","GoVersion":"go1.4.2","Os":"linux","Arch":"amd64","BuildTime":"Tue Jun 23 17:56:00 UTC 2015"},"ServerOK":true,"Server":{"Version":"1.8.0","ApiVersion":"1.20","GitCommit":"f5bae0a","GoVersion":"go1.4.2","Os":"linux","Arch":"amd64","KernelVersion":"3.13.2-gentoo","BuildTime":"Tue Jun 23 17:56:00 UTC 2015"}}
|
||||
{"Client":"Version":"23.0.3","ApiVersion":"1.42", ...}
|
||||
|
||||
@@ -25,11 +25,11 @@ trap clean EXIT
|
||||
# install cli-docs-tool and copy docs/tools.go in root folder
|
||||
# to be able to fetch the required depedencies
|
||||
go mod edit -modfile=vendor.mod -require=github.com/docker/cli-docs-tool@${CLI_DOCS_TOOL_VERSION}
|
||||
cp docs/tools.go .
|
||||
cp docs/generate/tools.go .
|
||||
# update vendor
|
||||
./scripts/vendor update
|
||||
# build docsgen
|
||||
go build -mod=vendor -modfile=vendor.mod -tags docsgen -o /tmp/docsgen ./docs/generate.go
|
||||
go build -mod=vendor -modfile=vendor.mod -tags docsgen -o /tmp/docsgen ./docs/generate/generate.go
|
||||
)
|
||||
|
||||
# yaml generation on docs repo needs the cli.md file: https://github.com/docker/cli/pull/3924#discussion_r1059986605
|
||||
|
||||
+3
-14
@@ -6,23 +6,11 @@ module github.com/docker/cli
|
||||
|
||||
go 1.18
|
||||
|
||||
// This is github.com/docker/docker "master". Unfortunately, go modules version
|
||||
// resolution is very broken, and updating the dependency to "master" without
|
||||
// a replace rule will roll it back to v23.0.0-rc.2+incompatible, likely because
|
||||
// that version is used by some dependencies (BuildKit, SwarmKit).
|
||||
//
|
||||
// Why 20.10.3? Go modules generates pseudo versions based on the latest non-
|
||||
// pre-release on the branch that "looks like SemVer" (v20.10.2 in this case).
|
||||
// Pseudo versions are prefixed with "vMajor.Minor.Patch+1", so the version
|
||||
// becomes "v20.10.3-0.20230207102624-b5568723cee5+incompatible" (latest stable
|
||||
// (v20.10.2) "+1" (v20.10.3), followed by the commit-date, and sha.
|
||||
replace github.com/docker/docker => github.com/docker/docker v20.10.3-0.20230330223104-7c93e4a09be1+incompatible
|
||||
|
||||
require (
|
||||
github.com/containerd/containerd v1.6.20
|
||||
github.com/creack/pty v1.1.11
|
||||
github.com/docker/distribution v2.8.1+incompatible
|
||||
github.com/docker/docker v23.0.2+incompatible // replaced; currently using master branch (v24.0.0-dev)
|
||||
github.com/docker/docker v24.0.0-beta.1+incompatible
|
||||
github.com/docker/docker-credential-helpers v0.7.0
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/docker/go-units v0.5.0
|
||||
@@ -44,11 +32,12 @@ require (
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/theupdateframework/notary v0.7.1-0.20210315103452-bf96a202a09a
|
||||
github.com/tonistiigi/go-rosetta v0.0.0-20200727161949-f79598599c5d
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/sys v0.6.0
|
||||
golang.org/x/term v0.5.0
|
||||
golang.org/x/text v0.7.0
|
||||
|
||||
+6
-5
@@ -101,8 +101,8 @@ github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xb
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
|
||||
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v20.10.3-0.20230330223104-7c93e4a09be1+incompatible h1:DPj58Fm9w777umTlCnFhJBo+sTyW4bVKG9gDBBnvkO4=
|
||||
github.com/docker/docker v20.10.3-0.20230330223104-7c93e4a09be1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v24.0.0-beta.1+incompatible h1:asqxFz/4xQRqFpQZFbEfNLOZsD1n7ET4m4AN29/rRKM=
|
||||
github.com/docker/docker v24.0.0-beta.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
|
||||
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||
@@ -230,7 +230,6 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
|
||||
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
|
||||
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8 h1:CZkYfurY6KGhVtlalI4QwQ6T0Cu6iuY3e0x5RLu96WE=
|
||||
@@ -379,8 +378,8 @@ github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs
|
||||
github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94 h1:JmfC365KywYwHB946TTiQWEb8kqPY+pybPLoGE9GgVk=
|
||||
github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
|
||||
github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||
github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431 h1:XTHrT015sxHyJ5FnQ0AeemSspZWaDq7DoTRW0EVsDCE=
|
||||
github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
@@ -523,6 +522,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Copyright 2013-2022 The Cobra Authors
|
||||
# Copyright 2013-2023 The Cobra Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
||||
+4
-4
@@ -5,10 +5,6 @@ ifeq (, $(shell which golangci-lint))
|
||||
$(warning "could not find golangci-lint in $(PATH), run: curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh")
|
||||
endif
|
||||
|
||||
ifeq (, $(shell which richgo))
|
||||
$(warning "could not find richgo in $(PATH), run: go install github.com/kyoh86/richgo@latest")
|
||||
endif
|
||||
|
||||
.PHONY: fmt lint test install_deps clean
|
||||
|
||||
default: all
|
||||
@@ -25,6 +21,10 @@ lint:
|
||||
|
||||
test: install_deps
|
||||
$(info ******************** running tests ********************)
|
||||
go test -v ./...
|
||||
|
||||
richtest: install_deps
|
||||
$(info ******************** running tests with kyoh86/richgo ********************)
|
||||
richgo test -v ./...
|
||||
|
||||
install_deps:
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
|
||||
Cobra is a library for creating powerful modern CLI applications.
|
||||
|
||||
@@ -6,7 +6,7 @@ Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/),
|
||||
[Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to
|
||||
name a few. [This list](./projects_using_cobra.md) contains a more extensive list of projects using Cobra.
|
||||
|
||||
[](https://github.com/spf13/cobra/actions?query=workflow%3ATest)
|
||||
[](https://github.com/spf13/cobra/actions?query=workflow%3ATest)
|
||||
[](https://pkg.go.dev/github.com/spf13/cobra)
|
||||
[](https://goreportcard.com/report/github.com/spf13/cobra)
|
||||
[](https://gophers.slack.com/archives/CD3LP1199)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
|
||||
type PositionalArgs func(cmd *Command, args []string) error
|
||||
|
||||
// Legacy arg validation has the following behaviour:
|
||||
// legacyArgs validation has the following behaviour:
|
||||
// - root commands with no subcommands can take arbitrary arguments
|
||||
// - root commands with subcommands will do subcommand validity checking
|
||||
// - subcommands will always accept arbitrary arguments
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -532,7 +532,7 @@ func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) {
|
||||
}
|
||||
}
|
||||
|
||||
// Setup annotations for go completions for registered flags
|
||||
// prepareCustomAnnotationsForFlags setup annotations for go completions for registered flags
|
||||
func prepareCustomAnnotationsForFlags(cmd *Command) {
|
||||
flagCompletionMutex.RLock()
|
||||
defer flagCompletionMutex.RUnlock()
|
||||
|
||||
+42
-29
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -38,7 +38,7 @@ func genBashComp(buf io.StringWriter, name string, includeDesc bool) {
|
||||
|
||||
__%[1]s_debug()
|
||||
{
|
||||
if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then
|
||||
if [[ -n ${BASH_COMP_DEBUG_FILE-} ]]; then
|
||||
echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
|
||||
fi
|
||||
}
|
||||
@@ -65,7 +65,7 @@ __%[1]s_get_completion_results() {
|
||||
lastChar=${lastParam:$((${#lastParam}-1)):1}
|
||||
__%[1]s_debug "lastParam ${lastParam}, lastChar ${lastChar}"
|
||||
|
||||
if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then
|
||||
if [[ -z ${cur} && ${lastChar} != = ]]; then
|
||||
# If the last parameter is complete (there is a space following it)
|
||||
# We add an extra empty parameter so we can indicate this to the go method.
|
||||
__%[1]s_debug "Adding extra empty parameter"
|
||||
@@ -75,7 +75,7 @@ __%[1]s_get_completion_results() {
|
||||
# When completing a flag with an = (e.g., %[1]s -n=<TAB>)
|
||||
# bash focuses on the part after the =, so we need to remove
|
||||
# the flag part from $cur
|
||||
if [[ "${cur}" == -*=* ]]; then
|
||||
if [[ ${cur} == -*=* ]]; then
|
||||
cur="${cur#*=}"
|
||||
fi
|
||||
|
||||
@@ -87,7 +87,7 @@ __%[1]s_get_completion_results() {
|
||||
directive=${out##*:}
|
||||
# Remove the directive
|
||||
out=${out%%:*}
|
||||
if [ "${directive}" = "${out}" ]; then
|
||||
if [[ ${directive} == "${out}" ]]; then
|
||||
# There is not directive specified
|
||||
directive=0
|
||||
fi
|
||||
@@ -101,22 +101,36 @@ __%[1]s_process_completion_results() {
|
||||
local shellCompDirectiveNoFileComp=%[5]d
|
||||
local shellCompDirectiveFilterFileExt=%[6]d
|
||||
local shellCompDirectiveFilterDirs=%[7]d
|
||||
local shellCompDirectiveKeepOrder=%[8]d
|
||||
|
||||
if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
|
||||
if (((directive & shellCompDirectiveError) != 0)); then
|
||||
# Error code. No completion.
|
||||
__%[1]s_debug "Received error from custom completion go code"
|
||||
return
|
||||
else
|
||||
if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
|
||||
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||
if (((directive & shellCompDirectiveNoSpace) != 0)); then
|
||||
if [[ $(type -t compopt) == builtin ]]; then
|
||||
__%[1]s_debug "Activating no space"
|
||||
compopt -o nospace
|
||||
else
|
||||
__%[1]s_debug "No space directive not supported in this version of bash"
|
||||
fi
|
||||
fi
|
||||
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
|
||||
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||
if (((directive & shellCompDirectiveKeepOrder) != 0)); then
|
||||
if [[ $(type -t compopt) == builtin ]]; then
|
||||
# no sort isn't supported for bash less than < 4.4
|
||||
if [[ ${BASH_VERSINFO[0]} -lt 4 || ( ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 4 ) ]]; then
|
||||
__%[1]s_debug "No sort directive not supported in this version of bash"
|
||||
else
|
||||
__%[1]s_debug "Activating keep order"
|
||||
compopt -o nosort
|
||||
fi
|
||||
else
|
||||
__%[1]s_debug "No sort directive not supported in this version of bash"
|
||||
fi
|
||||
fi
|
||||
if (((directive & shellCompDirectiveNoFileComp) != 0)); then
|
||||
if [[ $(type -t compopt) == builtin ]]; then
|
||||
__%[1]s_debug "Activating no file completion"
|
||||
compopt +o default
|
||||
else
|
||||
@@ -130,7 +144,7 @@ __%[1]s_process_completion_results() {
|
||||
local activeHelp=()
|
||||
__%[1]s_extract_activeHelp
|
||||
|
||||
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
|
||||
if (((directive & shellCompDirectiveFilterFileExt) != 0)); then
|
||||
# File extension filtering
|
||||
local fullFilter filter filteringCmd
|
||||
|
||||
@@ -143,13 +157,12 @@ __%[1]s_process_completion_results() {
|
||||
filteringCmd="_filedir $fullFilter"
|
||||
__%[1]s_debug "File filtering command: $filteringCmd"
|
||||
$filteringCmd
|
||||
elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
|
||||
elif (((directive & shellCompDirectiveFilterDirs) != 0)); then
|
||||
# File completion for directories only
|
||||
|
||||
# Use printf to strip any trailing newline
|
||||
local subdir
|
||||
subdir=$(printf "%%s" "${completions[0]}")
|
||||
if [ -n "$subdir" ]; then
|
||||
subdir=${completions[0]}
|
||||
if [[ -n $subdir ]]; then
|
||||
__%[1]s_debug "Listing directories in $subdir"
|
||||
pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
|
||||
else
|
||||
@@ -164,7 +177,7 @@ __%[1]s_process_completion_results() {
|
||||
__%[1]s_handle_special_char "$cur" =
|
||||
|
||||
# Print the activeHelp statements before we finish
|
||||
if [ ${#activeHelp[*]} -ne 0 ]; then
|
||||
if ((${#activeHelp[*]} != 0)); then
|
||||
printf "\n";
|
||||
printf "%%s\n" "${activeHelp[@]}"
|
||||
printf "\n"
|
||||
@@ -184,21 +197,21 @@ __%[1]s_process_completion_results() {
|
||||
# Separate activeHelp lines from real completions.
|
||||
# Fills the $activeHelp and $completions arrays.
|
||||
__%[1]s_extract_activeHelp() {
|
||||
local activeHelpMarker="%[8]s"
|
||||
local activeHelpMarker="%[9]s"
|
||||
local endIndex=${#activeHelpMarker}
|
||||
|
||||
while IFS='' read -r comp; do
|
||||
if [ "${comp:0:endIndex}" = "$activeHelpMarker" ]; then
|
||||
if [[ ${comp:0:endIndex} == $activeHelpMarker ]]; then
|
||||
comp=${comp:endIndex}
|
||||
__%[1]s_debug "ActiveHelp found: $comp"
|
||||
if [ -n "$comp" ]; then
|
||||
if [[ -n $comp ]]; then
|
||||
activeHelp+=("$comp")
|
||||
fi
|
||||
else
|
||||
# Not an activeHelp line but a normal completion
|
||||
completions+=("$comp")
|
||||
fi
|
||||
done < <(printf "%%s\n" "${out}")
|
||||
done <<<"${out}"
|
||||
}
|
||||
|
||||
__%[1]s_handle_completion_types() {
|
||||
@@ -254,7 +267,7 @@ __%[1]s_handle_standard_completion_case() {
|
||||
done < <(printf "%%s\n" "${completions[@]}")
|
||||
|
||||
# If there is a single completion left, remove the description text
|
||||
if [ ${#COMPREPLY[*]} -eq 1 ]; then
|
||||
if ((${#COMPREPLY[*]} == 1)); then
|
||||
__%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}"
|
||||
comp="${COMPREPLY[0]%%%%$tab*}"
|
||||
__%[1]s_debug "Removed description from single completion, which is now: ${comp}"
|
||||
@@ -271,8 +284,8 @@ __%[1]s_handle_special_char()
|
||||
if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then
|
||||
local word=${comp%%"${comp##*${char}}"}
|
||||
local idx=${#COMPREPLY[*]}
|
||||
while [[ $((--idx)) -ge 0 ]]; do
|
||||
COMPREPLY[$idx]=${COMPREPLY[$idx]#"$word"}
|
||||
while ((--idx >= 0)); do
|
||||
COMPREPLY[idx]=${COMPREPLY[idx]#"$word"}
|
||||
done
|
||||
fi
|
||||
}
|
||||
@@ -298,7 +311,7 @@ __%[1]s_format_comp_descriptions()
|
||||
|
||||
# Make sure we can fit a description of at least 8 characters
|
||||
# if we are to align the descriptions.
|
||||
if [[ $maxdesclength -gt 8 ]]; then
|
||||
if ((maxdesclength > 8)); then
|
||||
# Add the proper number of spaces to align the descriptions
|
||||
for ((i = ${#comp} ; i < longest ; i++)); do
|
||||
comp+=" "
|
||||
@@ -310,8 +323,8 @@ __%[1]s_format_comp_descriptions()
|
||||
|
||||
# If there is enough space for any description text,
|
||||
# truncate the descriptions that are too long for the shell width
|
||||
if [ $maxdesclength -gt 0 ]; then
|
||||
if [ ${#desc} -gt $maxdesclength ]; then
|
||||
if ((maxdesclength > 0)); then
|
||||
if ((${#desc} > maxdesclength)); then
|
||||
desc=${desc:0:$(( maxdesclength - 1 ))}
|
||||
desc+="…"
|
||||
fi
|
||||
@@ -332,9 +345,9 @@ __start_%[1]s()
|
||||
# Call _init_completion from the bash-completion package
|
||||
# to prepare the arguments properly
|
||||
if declare -F _init_completion >/dev/null 2>&1; then
|
||||
_init_completion -n "=:" || return
|
||||
_init_completion -n =: || return
|
||||
else
|
||||
__%[1]s_init_completion -n "=:" || return
|
||||
__%[1]s_init_completion -n =: || return
|
||||
fi
|
||||
|
||||
__%[1]s_debug
|
||||
@@ -361,7 +374,7 @@ fi
|
||||
# ex: ts=4 sw=4 et filetype=sh
|
||||
`, name, compCmd,
|
||||
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs,
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder,
|
||||
activeHelpMarker))
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -167,8 +167,8 @@ func appendIfNotPresent(s, stringToAppend string) string {
|
||||
|
||||
// rpad adds padding to the right of a string.
|
||||
func rpad(s string, padding int) string {
|
||||
template := fmt.Sprintf("%%-%ds", padding)
|
||||
return fmt.Sprintf(template, s)
|
||||
formattedString := fmt.Sprintf("%%-%ds", padding)
|
||||
return fmt.Sprintf(formattedString, s)
|
||||
}
|
||||
|
||||
// tmpl executes the given template text on data, writing the result to w.
|
||||
|
||||
+39
-15
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -35,7 +35,7 @@ const FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra"
|
||||
// FParseErrWhitelist configures Flag parse errors to be ignored
|
||||
type FParseErrWhitelist flag.ParseErrorsWhitelist
|
||||
|
||||
// Structure to manage groups for commands
|
||||
// Group Structure to manage groups for commands
|
||||
type Group struct {
|
||||
ID string
|
||||
Title string
|
||||
@@ -47,7 +47,7 @@ type Group struct {
|
||||
// definition to ensure usability.
|
||||
type Command struct {
|
||||
// Use is the one-line usage message.
|
||||
// Recommended syntax is as follow:
|
||||
// Recommended syntax is as follows:
|
||||
// [ ] identifies an optional argument. Arguments that are not enclosed in brackets are required.
|
||||
// ... indicates that you can specify multiple values for the previous argument.
|
||||
// | indicates mutually exclusive information. You can use the argument to the left of the separator or the
|
||||
@@ -321,7 +321,7 @@ func (c *Command) SetHelpCommand(cmd *Command) {
|
||||
c.helpCommand = cmd
|
||||
}
|
||||
|
||||
// SetHelpCommandGroup sets the group id of the help command.
|
||||
// SetHelpCommandGroupID sets the group id of the help command.
|
||||
func (c *Command) SetHelpCommandGroupID(groupID string) {
|
||||
if c.helpCommand != nil {
|
||||
c.helpCommand.GroupID = groupID
|
||||
@@ -330,7 +330,7 @@ func (c *Command) SetHelpCommandGroupID(groupID string) {
|
||||
c.helpCommandGroupID = groupID
|
||||
}
|
||||
|
||||
// SetCompletionCommandGroup sets the group id of the completion command.
|
||||
// SetCompletionCommandGroupID sets the group id of the completion command.
|
||||
func (c *Command) SetCompletionCommandGroupID(groupID string) {
|
||||
// completionCommandGroupID is used if no completion command is defined by the user
|
||||
c.Root().completionCommandGroupID = groupID
|
||||
@@ -655,20 +655,44 @@ Loop:
|
||||
|
||||
// argsMinusFirstX removes only the first x from args. Otherwise, commands that look like
|
||||
// openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]).
|
||||
func argsMinusFirstX(args []string, x string) []string {
|
||||
for i, y := range args {
|
||||
if x == y {
|
||||
ret := []string{}
|
||||
ret = append(ret, args[:i]...)
|
||||
ret = append(ret, args[i+1:]...)
|
||||
return ret
|
||||
// Special care needs to be taken not to remove a flag value.
|
||||
func (c *Command) argsMinusFirstX(args []string, x string) []string {
|
||||
if len(args) == 0 {
|
||||
return args
|
||||
}
|
||||
c.mergePersistentFlags()
|
||||
flags := c.Flags()
|
||||
|
||||
Loop:
|
||||
for pos := 0; pos < len(args); pos++ {
|
||||
s := args[pos]
|
||||
switch {
|
||||
case s == "--":
|
||||
// -- means we have reached the end of the parseable args. Break out of the loop now.
|
||||
break Loop
|
||||
case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags):
|
||||
fallthrough
|
||||
case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags):
|
||||
// This is a flag without a default value, and an equal sign is not used. Increment pos in order to skip
|
||||
// over the next arg, because that is the value of this flag.
|
||||
pos++
|
||||
continue
|
||||
case !strings.HasPrefix(s, "-"):
|
||||
// This is not a flag or a flag value. Check to see if it matches what we're looking for, and if so,
|
||||
// return the args, excluding the one at this position.
|
||||
if s == x {
|
||||
ret := []string{}
|
||||
ret = append(ret, args[:pos]...)
|
||||
ret = append(ret, args[pos+1:]...)
|
||||
return ret
|
||||
}
|
||||
}
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func isFlagArg(arg string) bool {
|
||||
return ((len(arg) >= 3 && arg[1] == '-') ||
|
||||
return ((len(arg) >= 3 && arg[0:2] == "--") ||
|
||||
(len(arg) >= 2 && arg[0] == '-' && arg[1] != '-'))
|
||||
}
|
||||
|
||||
@@ -686,7 +710,7 @@ func (c *Command) Find(args []string) (*Command, []string, error) {
|
||||
|
||||
cmd := c.findNext(nextSubCmd)
|
||||
if cmd != nil {
|
||||
return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd))
|
||||
return innerfind(cmd, c.argsMinusFirstX(innerArgs, nextSubCmd))
|
||||
}
|
||||
return c, innerArgs
|
||||
}
|
||||
@@ -1272,7 +1296,7 @@ func (c *Command) AllChildCommandsHaveGroup() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ContainGroups return if groupID exists in the list of command groups.
|
||||
// ContainsGroup return if groupID exists in the list of command groups.
|
||||
func (c *Command) ContainsGroup(groupID string) bool {
|
||||
for _, x := range c.commandgroups {
|
||||
if x.ID == groupID {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
+10
-3
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -77,6 +77,10 @@ const (
|
||||
// obtain the same behavior but only for flags.
|
||||
ShellCompDirectiveFilterDirs
|
||||
|
||||
// ShellCompDirectiveKeepOrder indicates that the shell should preserve the order
|
||||
// in which the completions are provided
|
||||
ShellCompDirectiveKeepOrder
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
// All directives using iota should be above this one.
|
||||
@@ -159,6 +163,9 @@ func (d ShellCompDirective) string() string {
|
||||
if d&ShellCompDirectiveFilterDirs != 0 {
|
||||
directives = append(directives, "ShellCompDirectiveFilterDirs")
|
||||
}
|
||||
if d&ShellCompDirectiveKeepOrder != 0 {
|
||||
directives = append(directives, "ShellCompDirectiveKeepOrder")
|
||||
}
|
||||
if len(directives) == 0 {
|
||||
directives = append(directives, "ShellCompDirectiveDefault")
|
||||
}
|
||||
@@ -169,7 +176,7 @@ func (d ShellCompDirective) string() string {
|
||||
return strings.Join(directives, ", ")
|
||||
}
|
||||
|
||||
// Adds a special hidden command that can be used to request custom completions.
|
||||
// initCompleteCmd adds a special hidden command that can be used to request custom completions.
|
||||
func (c *Command) initCompleteCmd(args []string) {
|
||||
completeCmd := &Command{
|
||||
Use: fmt.Sprintf("%s [command-line]", ShellCompRequestCmd),
|
||||
@@ -727,7 +734,7 @@ to enable it. You can execute the following once:
|
||||
|
||||
To load completions in your current shell session:
|
||||
|
||||
source <(%[1]s completion zsh); compdef _%[1]s %[1]s
|
||||
source <(%[1]s completion zsh)
|
||||
|
||||
To load completions for every new session, execute once:
|
||||
|
||||
|
||||
+68
-10
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -53,7 +53,7 @@ function __%[1]s_perform_completion
|
||||
__%[1]s_debug "last arg: $lastArg"
|
||||
|
||||
# Disable ActiveHelp which is not supported for fish shell
|
||||
set -l requestComp "%[9]s=0 $args[1] %[3]s $args[2..-1] $lastArg"
|
||||
set -l requestComp "%[10]s=0 $args[1] %[3]s $args[2..-1] $lastArg"
|
||||
|
||||
__%[1]s_debug "Calling $requestComp"
|
||||
set -l results (eval $requestComp 2> /dev/null)
|
||||
@@ -89,6 +89,60 @@ function __%[1]s_perform_completion
|
||||
printf "%%s\n" "$directiveLine"
|
||||
end
|
||||
|
||||
# this function limits calls to __%[1]s_perform_completion, by caching the result behind $__%[1]s_perform_completion_once_result
|
||||
function __%[1]s_perform_completion_once
|
||||
__%[1]s_debug "Starting __%[1]s_perform_completion_once"
|
||||
|
||||
if test -n "$__%[1]s_perform_completion_once_result"
|
||||
__%[1]s_debug "Seems like a valid result already exists, skipping __%[1]s_perform_completion"
|
||||
return 0
|
||||
end
|
||||
|
||||
set --global __%[1]s_perform_completion_once_result (__%[1]s_perform_completion)
|
||||
if test -z "$__%[1]s_perform_completion_once_result"
|
||||
__%[1]s_debug "No completions, probably due to a failure"
|
||||
return 1
|
||||
end
|
||||
|
||||
__%[1]s_debug "Performed completions and set __%[1]s_perform_completion_once_result"
|
||||
return 0
|
||||
end
|
||||
|
||||
# this function is used to clear the $__%[1]s_perform_completion_once_result variable after completions are run
|
||||
function __%[1]s_clear_perform_completion_once_result
|
||||
__%[1]s_debug ""
|
||||
__%[1]s_debug "========= clearing previously set __%[1]s_perform_completion_once_result variable =========="
|
||||
set --erase __%[1]s_perform_completion_once_result
|
||||
__%[1]s_debug "Succesfully erased the variable __%[1]s_perform_completion_once_result"
|
||||
end
|
||||
|
||||
function __%[1]s_requires_order_preservation
|
||||
__%[1]s_debug ""
|
||||
__%[1]s_debug "========= checking if order preservation is required =========="
|
||||
|
||||
__%[1]s_perform_completion_once
|
||||
if test -z "$__%[1]s_perform_completion_once_result"
|
||||
__%[1]s_debug "Error determining if order preservation is required"
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1])
|
||||
__%[1]s_debug "Directive is: $directive"
|
||||
|
||||
set -l shellCompDirectiveKeepOrder %[9]d
|
||||
set -l keeporder (math (math --scale 0 $directive / $shellCompDirectiveKeepOrder) %% 2)
|
||||
__%[1]s_debug "Keeporder is: $keeporder"
|
||||
|
||||
if test $keeporder -ne 0
|
||||
__%[1]s_debug "This does require order preservation"
|
||||
return 0
|
||||
end
|
||||
|
||||
__%[1]s_debug "This doesn't require order preservation"
|
||||
return 1
|
||||
end
|
||||
|
||||
|
||||
# This function does two things:
|
||||
# - Obtain the completions and store them in the global __%[1]s_comp_results
|
||||
# - Return false if file completion should be performed
|
||||
@@ -99,17 +153,17 @@ function __%[1]s_prepare_completions
|
||||
# Start fresh
|
||||
set --erase __%[1]s_comp_results
|
||||
|
||||
set -l results (__%[1]s_perform_completion)
|
||||
__%[1]s_debug "Completion results: $results"
|
||||
__%[1]s_perform_completion_once
|
||||
__%[1]s_debug "Completion results: $__%[1]s_perform_completion_once_result"
|
||||
|
||||
if test -z "$results"
|
||||
if test -z "$__%[1]s_perform_completion_once_result"
|
||||
__%[1]s_debug "No completion, probably due to a failure"
|
||||
# Might as well do file completion, in case it helps
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l directive (string sub --start 2 $results[-1])
|
||||
set --global __%[1]s_comp_results $results[1..-2]
|
||||
set -l directive (string sub --start 2 $__%[1]s_perform_completion_once_result[-1])
|
||||
set --global __%[1]s_comp_results $__%[1]s_perform_completion_once_result[1..-2]
|
||||
|
||||
__%[1]s_debug "Completions are: $__%[1]s_comp_results"
|
||||
__%[1]s_debug "Directive is: $directive"
|
||||
@@ -205,13 +259,17 @@ end
|
||||
# Remove any pre-existing completions for the program since we will be handling all of them.
|
||||
complete -c %[2]s -e
|
||||
|
||||
# this will get called after the two calls below and clear the $__%[1]s_perform_completion_once_result global
|
||||
complete -c %[2]s -n '__%[1]s_clear_perform_completion_once_result'
|
||||
# The call to __%[1]s_prepare_completions will setup __%[1]s_comp_results
|
||||
# which provides the program's completion choices.
|
||||
complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
|
||||
|
||||
# If this doesn't require order preservation, we don't use the -k flag
|
||||
complete -c %[2]s -n 'not __%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
|
||||
# otherwise we use the -k flag
|
||||
complete -k -c %[2]s -n '__%[1]s_requires_order_preservation && __%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
|
||||
`, nameForVar, name, compCmd,
|
||||
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name)))
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name)))
|
||||
}
|
||||
|
||||
// GenFishCompletion generates fish completion file and writes to the passed writer.
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
+21
-6
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -77,6 +77,7 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
||||
$ShellCompDirectiveNoFileComp=%[6]d
|
||||
$ShellCompDirectiveFilterFileExt=%[7]d
|
||||
$ShellCompDirectiveFilterDirs=%[8]d
|
||||
$ShellCompDirectiveKeepOrder=%[9]d
|
||||
|
||||
# Prepare the command to request completions for the program.
|
||||
# Split the command at the first space to separate the program and arguments.
|
||||
@@ -106,13 +107,22 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
||||
# If the last parameter is complete (there is a space following it)
|
||||
# We add an extra empty parameter so we can indicate this to the go method.
|
||||
__%[1]s_debug "Adding extra empty parameter"
|
||||
`+" # We need to use `\"`\" to pass an empty argument a \"\" or '' does not work!!!"+`
|
||||
`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+`
|
||||
# PowerShell 7.2+ changed the way how the arguments are passed to executables,
|
||||
# so for pre-7.2 or when Legacy argument passing is enabled we need to use
|
||||
`+" # `\"`\" to pass an empty argument, a \"\" or '' does not work!!!"+`
|
||||
if ($PSVersionTable.PsVersion -lt [version]'7.2.0' -or
|
||||
($PSVersionTable.PsVersion -lt [version]'7.3.0' -and -not [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -or
|
||||
(($PSVersionTable.PsVersion -ge [version]'7.3.0' -or [ExperimentalFeature]::IsEnabled("PSNativeCommandArgumentPassing")) -and
|
||||
$PSNativeCommandArgumentPassing -eq 'Legacy')) {
|
||||
`+" $RequestComp=\"$RequestComp\" + ' `\"`\"'"+`
|
||||
} else {
|
||||
$RequestComp="$RequestComp" + ' ""'
|
||||
}
|
||||
}
|
||||
|
||||
__%[1]s_debug "Calling $RequestComp"
|
||||
# First disable ActiveHelp which is not supported for Powershell
|
||||
$env:%[9]s=0
|
||||
$env:%[10]s=0
|
||||
|
||||
#call the command store the output in $out and redirect stderr and stdout to null
|
||||
# $Out is an array contains each line per element
|
||||
@@ -137,7 +147,7 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
||||
}
|
||||
|
||||
$Longest = 0
|
||||
$Values = $Out | ForEach-Object {
|
||||
[Array]$Values = $Out | ForEach-Object {
|
||||
#Split the output in name and description
|
||||
`+" $Name, $Description = $_.Split(\"`t\",2)"+`
|
||||
__%[1]s_debug "Name: $Name Description: $Description"
|
||||
@@ -182,6 +192,11 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
||||
}
|
||||
}
|
||||
|
||||
# we sort the values in ascending order by name if keep order isn't passed
|
||||
if (($Directive -band $ShellCompDirectiveKeepOrder) -eq 0 ) {
|
||||
$Values = $Values | Sort-Object -Property Name
|
||||
}
|
||||
|
||||
if (($Directive -band $ShellCompDirectiveNoFileComp) -ne 0 ) {
|
||||
__%[1]s_debug "ShellCompDirectiveNoFileComp is called"
|
||||
|
||||
@@ -267,7 +282,7 @@ filter __%[1]s_escapeStringWithSpecialChars {
|
||||
Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock $__%[2]sCompleterBlock
|
||||
`, name, nameForVar, compCmd,
|
||||
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name)))
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name)))
|
||||
}
|
||||
|
||||
func (c *Command) genPowerShellCompletion(w io.Writer, includeDesc bool) error {
|
||||
|
||||
+5
-1
@@ -1,11 +1,13 @@
|
||||
## Projects using Cobra
|
||||
|
||||
- [Allero](https://github.com/allero-io/allero)
|
||||
- [Arewefastyet](https://benchmark.vitess.io)
|
||||
- [Arduino CLI](https://github.com/arduino/arduino-cli)
|
||||
- [Bleve](https://blevesearch.com/)
|
||||
- [Cilium](https://cilium.io/)
|
||||
- [CloudQuery](https://github.com/cloudquery/cloudquery)
|
||||
- [CockroachDB](https://www.cockroachlabs.com/)
|
||||
- [Constellation](https://github.com/edgelesssys/constellation)
|
||||
- [Cosmos SDK](https://github.com/cosmos/cosmos-sdk)
|
||||
- [Datree](https://github.com/datreeio/datree)
|
||||
- [Delve](https://github.com/derekparker/delve)
|
||||
@@ -25,7 +27,7 @@
|
||||
- [Istio](https://istio.io)
|
||||
- [Kool](https://github.com/kool-dev/kool)
|
||||
- [Kubernetes](https://kubernetes.io/)
|
||||
- [Kubescape](https://github.com/armosec/kubescape)
|
||||
- [Kubescape](https://github.com/kubescape/kubescape)
|
||||
- [KubeVirt](https://github.com/kubevirt/kubevirt)
|
||||
- [Linkerd](https://linkerd.io/)
|
||||
- [Mattermost-server](https://github.com/mattermost/mattermost-server)
|
||||
@@ -51,10 +53,12 @@
|
||||
- [Random](https://github.com/erdaltsksn/random)
|
||||
- [Rclone](https://rclone.org/)
|
||||
- [Scaleway CLI](https://github.com/scaleway/scaleway-cli)
|
||||
- [Sia](https://github.com/SiaFoundation/siad)
|
||||
- [Skaffold](https://skaffold.dev/)
|
||||
- [Tendermint](https://github.com/tendermint/tendermint)
|
||||
- [Twitch CLI](https://github.com/twitchdev/twitch-cli)
|
||||
- [UpCloud CLI (`upctl`)](https://github.com/UpCloudLtd/upcloud-cli)
|
||||
- [Vitess](https://vitess.io)
|
||||
- VMware's [Tanzu Community Edition](https://github.com/vmware-tanzu/community-edition) & [Tanzu Framework](https://github.com/vmware-tanzu/tanzu-framework)
|
||||
- [Werf](https://werf.io/)
|
||||
- [ZITADEL](https://github.com/zitadel/zitadel)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
+19
-11
@@ -71,7 +71,7 @@ PowerShell:
|
||||
`,cmd.Root().Name()),
|
||||
DisableFlagsInUseLine: true,
|
||||
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
|
||||
Args: cobra.ExactValidArgs(1),
|
||||
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
switch args[0] {
|
||||
case "bash":
|
||||
@@ -162,16 +162,7 @@ cmd := &cobra.Command{
|
||||
}
|
||||
```
|
||||
|
||||
The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by
|
||||
the completion algorithm if entered manually, e.g. in:
|
||||
|
||||
```bash
|
||||
$ kubectl get rc [tab][tab]
|
||||
backend frontend database
|
||||
```
|
||||
|
||||
Note that without declaring `rc` as an alias, the completion algorithm would not know to show the list of
|
||||
replication controllers following `rc`.
|
||||
The aliases are shown to the user on tab completion only if no completions were found within sub-commands or `ValidArgs`.
|
||||
|
||||
### Dynamic completion of nouns
|
||||
|
||||
@@ -237,6 +228,10 @@ ShellCompDirectiveFilterFileExt
|
||||
// return []string{"themes"}, ShellCompDirectiveFilterDirs
|
||||
//
|
||||
ShellCompDirectiveFilterDirs
|
||||
|
||||
// ShellCompDirectiveKeepOrder indicates that the shell should preserve the order
|
||||
// in which the completions are provided
|
||||
ShellCompDirectiveKeepOrder
|
||||
```
|
||||
|
||||
***Note***: When using the `ValidArgsFunction`, Cobra will call your registered function after having parsed all flags and arguments provided in the command-line. You therefore don't need to do this parsing yourself. For example, when a user calls `helm status --namespace my-rook-ns [tab][tab]`, Cobra will call your registered `ValidArgsFunction` after having parsed the `--namespace` flag, as it would have done when calling the `RunE` function.
|
||||
@@ -385,6 +380,19 @@ or
|
||||
```go
|
||||
ValidArgs: []string{"bash\tCompletions for bash", "zsh\tCompletions for zsh"}
|
||||
```
|
||||
|
||||
If you don't want to show descriptions in the completions, you can add `--no-descriptions` to the default `completion` command to disable them, like:
|
||||
|
||||
```bash
|
||||
$ source <(helm completion bash)
|
||||
$ helm completion [tab][tab]
|
||||
bash (generate autocompletion script for bash) powershell (generate autocompletion script for powershell)
|
||||
fish (generate autocompletion script for fish) zsh (generate autocompletion script for zsh)
|
||||
|
||||
$ source <(helm completion bash --no-descriptions)
|
||||
$ helm completion [tab][tab]
|
||||
bash fish powershell zsh
|
||||
```
|
||||
## Bash completions
|
||||
|
||||
### Dependencies
|
||||
|
||||
+34
-3
@@ -188,6 +188,37 @@ var versionCmd = &cobra.Command{
|
||||
}
|
||||
```
|
||||
|
||||
### Organizing subcommands
|
||||
|
||||
A command may have subcommands which in turn may have other subcommands. This is achieved by using
|
||||
`AddCommand`. In some cases, especially in larger applications, each subcommand may be defined in
|
||||
its own go package.
|
||||
|
||||
The suggested approach is for the parent command to use `AddCommand` to add its most immediate
|
||||
subcommands. For example, consider the following directory structure:
|
||||
|
||||
```text
|
||||
├── cmd
|
||||
│ ├── root.go
|
||||
│ └── sub1
|
||||
│ ├── sub1.go
|
||||
│ └── sub2
|
||||
│ ├── leafA.go
|
||||
│ ├── leafB.go
|
||||
│ └── sub2.go
|
||||
└── main.go
|
||||
```
|
||||
|
||||
In this case:
|
||||
|
||||
* The `init` function of `root.go` adds the command defined in `sub1.go` to the root command.
|
||||
* The `init` function of `sub1.go` adds the command defined in `sub2.go` to the sub1 command.
|
||||
* The `init` function of `sub2.go` adds the commands defined in `leafA.go` and `leafB.go` to the
|
||||
sub2 command.
|
||||
|
||||
This approach ensures the subcommands are always included at compile time while avoiding cyclic
|
||||
references.
|
||||
|
||||
### Returning and handling errors
|
||||
|
||||
If you wish to return an error to the caller of a command, `RunE` can be used.
|
||||
@@ -313,8 +344,8 @@ rootCmd.MarkFlagsRequiredTogether("username", "password")
|
||||
You can also prevent different flags from being provided together if they represent mutually
|
||||
exclusive options such as specifying an output format as either `--json` or `--yaml` but never both:
|
||||
```go
|
||||
rootCmd.Flags().BoolVar(&u, "json", false, "Output in JSON")
|
||||
rootCmd.Flags().BoolVar(&pw, "yaml", false, "Output in YAML")
|
||||
rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON")
|
||||
rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML")
|
||||
rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")
|
||||
```
|
||||
|
||||
@@ -349,7 +380,7 @@ shown below:
|
||||
```go
|
||||
var cmd = &cobra.Command{
|
||||
Short: "hello",
|
||||
Args: MatchAll(ExactArgs(2), OnlyValidArgs),
|
||||
Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("Hello, World!")
|
||||
},
|
||||
|
||||
+12
-5
@@ -1,4 +1,4 @@
|
||||
// Copyright 2013-2022 The Cobra Authors
|
||||
// Copyright 2013-2023 The Cobra Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -90,6 +90,7 @@ func genZshComp(buf io.StringWriter, name string, includeDesc bool) {
|
||||
compCmd = ShellCompNoDescRequestCmd
|
||||
}
|
||||
WriteStringAndCheck(buf, fmt.Sprintf(`#compdef %[1]s
|
||||
compdef _%[1]s %[1]s
|
||||
|
||||
# zsh completion for %-36[1]s -*- shell-script -*-
|
||||
|
||||
@@ -108,8 +109,9 @@ _%[1]s()
|
||||
local shellCompDirectiveNoFileComp=%[5]d
|
||||
local shellCompDirectiveFilterFileExt=%[6]d
|
||||
local shellCompDirectiveFilterDirs=%[7]d
|
||||
local shellCompDirectiveKeepOrder=%[8]d
|
||||
|
||||
local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace
|
||||
local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace keepOrder
|
||||
local -a completions
|
||||
|
||||
__%[1]s_debug "\n========= starting completion logic =========="
|
||||
@@ -177,7 +179,7 @@ _%[1]s()
|
||||
return
|
||||
fi
|
||||
|
||||
local activeHelpMarker="%[8]s"
|
||||
local activeHelpMarker="%[9]s"
|
||||
local endIndex=${#activeHelpMarker}
|
||||
local startIndex=$((${#activeHelpMarker}+1))
|
||||
local hasActiveHelp=0
|
||||
@@ -227,6 +229,11 @@ _%[1]s()
|
||||
noSpace="-S ''"
|
||||
fi
|
||||
|
||||
if [ $((directive & shellCompDirectiveKeepOrder)) -ne 0 ]; then
|
||||
__%[1]s_debug "Activating keep order."
|
||||
keepOrder="-V"
|
||||
fi
|
||||
|
||||
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
|
||||
# File extension filtering
|
||||
local filteringCmd
|
||||
@@ -262,7 +269,7 @@ _%[1]s()
|
||||
return $result
|
||||
else
|
||||
__%[1]s_debug "Calling _describe"
|
||||
if eval _describe "completions" completions $flagPrefix $noSpace; then
|
||||
if eval _describe $keepOrder "completions" completions $flagPrefix $noSpace; then
|
||||
__%[1]s_debug "_describe found some completions"
|
||||
|
||||
# Return the success of having called _describe
|
||||
@@ -296,6 +303,6 @@ if [ "$funcstack[1]" = "_%[1]s" ]; then
|
||||
fi
|
||||
`, name, compCmd,
|
||||
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs,
|
||||
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder,
|
||||
activeHelpMarker))
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the Go project.
|
||||
|
||||
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||
patent license to make, have made, use, offer to sell, sell, import,
|
||||
transfer and otherwise run, modify and propagate the contents of this
|
||||
implementation of Go, where such license applies only to those patent
|
||||
claims, both currently owned or controlled by Google and acquired in
|
||||
the future, licensable by Google that are necessarily infringed by this
|
||||
implementation of Go. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of Go or any code incorporated within this
|
||||
implementation of Go constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of Go
|
||||
shall terminate as of the date such litigation is filed.
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package errgroup provides synchronization, error propagation, and Context
|
||||
// cancelation for groups of goroutines working on subtasks of a common task.
|
||||
package errgroup
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type token struct{}
|
||||
|
||||
// A Group is a collection of goroutines working on subtasks that are part of
|
||||
// the same overall task.
|
||||
//
|
||||
// A zero Group is valid, has no limit on the number of active goroutines,
|
||||
// and does not cancel on error.
|
||||
type Group struct {
|
||||
cancel func()
|
||||
|
||||
wg sync.WaitGroup
|
||||
|
||||
sem chan token
|
||||
|
||||
errOnce sync.Once
|
||||
err error
|
||||
}
|
||||
|
||||
func (g *Group) done() {
|
||||
if g.sem != nil {
|
||||
<-g.sem
|
||||
}
|
||||
g.wg.Done()
|
||||
}
|
||||
|
||||
// WithContext returns a new Group and an associated Context derived from ctx.
|
||||
//
|
||||
// The derived Context is canceled the first time a function passed to Go
|
||||
// returns a non-nil error or the first time Wait returns, whichever occurs
|
||||
// first.
|
||||
func WithContext(ctx context.Context) (*Group, context.Context) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
return &Group{cancel: cancel}, ctx
|
||||
}
|
||||
|
||||
// Wait blocks until all function calls from the Go method have returned, then
|
||||
// returns the first non-nil error (if any) from them.
|
||||
func (g *Group) Wait() error {
|
||||
g.wg.Wait()
|
||||
if g.cancel != nil {
|
||||
g.cancel()
|
||||
}
|
||||
return g.err
|
||||
}
|
||||
|
||||
// Go calls the given function in a new goroutine.
|
||||
// It blocks until the new goroutine can be added without the number of
|
||||
// active goroutines in the group exceeding the configured limit.
|
||||
//
|
||||
// The first call to return a non-nil error cancels the group's context, if the
|
||||
// group was created by calling WithContext. The error will be returned by Wait.
|
||||
func (g *Group) Go(f func() error) {
|
||||
if g.sem != nil {
|
||||
g.sem <- token{}
|
||||
}
|
||||
|
||||
g.wg.Add(1)
|
||||
go func() {
|
||||
defer g.done()
|
||||
|
||||
if err := f(); err != nil {
|
||||
g.errOnce.Do(func() {
|
||||
g.err = err
|
||||
if g.cancel != nil {
|
||||
g.cancel()
|
||||
}
|
||||
})
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// TryGo calls the given function in a new goroutine only if the number of
|
||||
// active goroutines in the group is currently below the configured limit.
|
||||
//
|
||||
// The return value reports whether the goroutine was started.
|
||||
func (g *Group) TryGo(f func() error) bool {
|
||||
if g.sem != nil {
|
||||
select {
|
||||
case g.sem <- token{}:
|
||||
// Note: this allows barging iff channels in general allow barging.
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
g.wg.Add(1)
|
||||
go func() {
|
||||
defer g.done()
|
||||
|
||||
if err := f(); err != nil {
|
||||
g.errOnce.Do(func() {
|
||||
g.err = err
|
||||
if g.cancel != nil {
|
||||
g.cancel()
|
||||
}
|
||||
})
|
||||
}
|
||||
}()
|
||||
return true
|
||||
}
|
||||
|
||||
// SetLimit limits the number of active goroutines in this group to at most n.
|
||||
// A negative value indicates no limit.
|
||||
//
|
||||
// Any subsequent call to the Go method will block until it can add an active
|
||||
// goroutine without exceeding the configured limit.
|
||||
//
|
||||
// The limit must not be modified while any goroutines in the group are active.
|
||||
func (g *Group) SetLimit(n int) {
|
||||
if n < 0 {
|
||||
g.sem = nil
|
||||
return
|
||||
}
|
||||
if len(g.sem) != 0 {
|
||||
panic(fmt.Errorf("errgroup: modify limit while %v goroutines in the group are still active", len(g.sem)))
|
||||
}
|
||||
g.sem = make(chan token, n)
|
||||
}
|
||||
Vendored
+5
-3
@@ -40,7 +40,7 @@ github.com/docker/distribution/registry/client/transport
|
||||
github.com/docker/distribution/registry/storage/cache
|
||||
github.com/docker/distribution/registry/storage/cache/memory
|
||||
github.com/docker/distribution/uuid
|
||||
# github.com/docker/docker v23.0.2+incompatible => github.com/docker/docker v20.10.3-0.20230330223104-7c93e4a09be1+incompatible
|
||||
# github.com/docker/docker v24.0.0-beta.1+incompatible
|
||||
## explicit
|
||||
github.com/docker/docker/api
|
||||
github.com/docker/docker/api/types
|
||||
@@ -227,7 +227,7 @@ github.com/rivo/uniseg
|
||||
# github.com/sirupsen/logrus v1.9.0
|
||||
## explicit; go 1.13
|
||||
github.com/sirupsen/logrus
|
||||
# github.com/spf13/cobra v1.6.1
|
||||
# github.com/spf13/cobra v1.7.0
|
||||
## explicit; go 1.15
|
||||
github.com/spf13/cobra
|
||||
# github.com/spf13/pflag v1.0.5
|
||||
@@ -278,6 +278,9 @@ golang.org/x/net/internal/socks
|
||||
golang.org/x/net/internal/timeseries
|
||||
golang.org/x/net/proxy
|
||||
golang.org/x/net/trace
|
||||
# golang.org/x/sync v0.1.0
|
||||
## explicit
|
||||
golang.org/x/sync/errgroup
|
||||
# golang.org/x/sys v0.6.0
|
||||
## explicit; go 1.17
|
||||
golang.org/x/sys/execabs
|
||||
@@ -403,4 +406,3 @@ gotest.tools/v3/internal/format
|
||||
gotest.tools/v3/internal/source
|
||||
gotest.tools/v3/poll
|
||||
gotest.tools/v3/skip
|
||||
# github.com/docker/docker => github.com/docker/docker v20.10.3-0.20230330223104-7c93e4a09be1+incompatible
|
||||
|
||||
Reference in New Issue
Block a user