Compare commits
142 Commits
v23.0.2
...
v24.0.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
| 33961a79f1 | |||
| dcb6a0d182 | |||
| 8e6ac62d53 | |||
| e14f5fc1a7 | |||
| 05cffcbedf | |||
| a36a54d3ca | |||
| f4b22fb6cf | |||
| eb392ff4ce | |||
| de0d30ff24 | |||
| 92fb47f58a | |||
| 7189716d5a | |||
| bfa79fd75a | |||
| e86d2f4113 | |||
| cd9c6a4c02 | |||
| 5843fbd5f5 | |||
| 149d289638 | |||
| 6dca335d05 | |||
| 4389c966f8 | |||
| a798282877 | |||
| adbfa8208a | |||
| dfc98b2dec | |||
| b8747b0f91 | |||
| 399ded9b98 | |||
| 20a70cb530 | |||
| 90380d9576 | |||
| dd6ede2109 | |||
| 7c8680c69b | |||
| 6355bcee66 | |||
| 607f290f65 | |||
| 546cf6d985 | |||
| b32b28041d | |||
| 40a51d5543 | |||
| b0d0b0efcb | |||
| c69640d8c1 | |||
| 5254081fd6 | |||
| da3416c023 | |||
| 625988c3aa | |||
| 92d9e3bf69 | |||
| 316c4992c4 | |||
| ae5a86bb8d | |||
| 38ef40ee7a | |||
| 45b5676acd | |||
| 5563c5a91d | |||
| 9dd012aa5d | |||
| 66c66bdce7 | |||
| ac024a4d8b | |||
| a2d532819d | |||
| f5fad186c0 | |||
| 9252fae838 | |||
| 92506afd49 | |||
| c3d7f167bd | |||
| b4aff3a14d | |||
| f08252c10a | |||
| 78c474539b | |||
| be97731f1a | |||
| a9fff59809 | |||
| 378e35e915 | |||
| b9a1b0928a | |||
| 90b7bc36d4 | |||
| efd011b793 | |||
| e4436853e8 | |||
| fc6703bd3d | |||
| 9335690a66 | |||
| ccae6e9299 | |||
| f27927d934 | |||
| 88924b1802 | |||
| a39958846d | |||
| 69c54641f7 | |||
| c39c711a18 | |||
| 62f2358b99 | |||
| bebdb6fa2a | |||
| 21653863b1 | |||
| bec5d37e91 | |||
| 7f11449f35 | |||
| b201ce5efd | |||
| c6c33380da | |||
| d234a81de7 | |||
| 59ec357996 | |||
| 3ce95c7af0 | |||
| b854eff300 | |||
| f5d698a331 | |||
| 0ba820ed0b | |||
| 14482589df | |||
| a3d56e7d06 | |||
| bfe87fd39b | |||
| 742881fc58 | |||
| e3fa7280ad | |||
| 235b501b71 | |||
| ac38a77ff9 | |||
| 3c9e0073dd | |||
| db827d583b | |||
| 166de0ec97 | |||
| aa0aa4a6dc | |||
| 8805f8ea2d | |||
| e60c748c14 | |||
| 6c8cc226f0 | |||
| d213548bd0 | |||
| 3a0d492d1c | |||
| f40bbf4f7f | |||
| a85537d346 | |||
| 3e9c6e84ce | |||
| ca8783ef43 | |||
| 33806760a4 | |||
| 71e495aa54 | |||
| 12c6126a67 | |||
| 078b99feb4 | |||
| 74c4ed4171 | |||
| 23da1cec6c | |||
| 677aac9011 | |||
| 012b77952e | |||
| a47058bbd5 | |||
| c549fd7360 | |||
| 9733334487 | |||
| cb5463a728 | |||
| 8bc1aaceae | |||
| 179bc7a638 | |||
| 934dd5b5ce | |||
| 881c353576 | |||
| 89687d5b3f | |||
| b244ad61cc | |||
| a1953e19b2 | |||
| 0b05d28815 | |||
| f5ac664f8a | |||
| e636747a14 | |||
| dac79b19a7 | |||
| c2487c2997 | |||
| e921e103a4 | |||
| dfb36eaef8 | |||
| d2f726d5ad | |||
| c173316515 | |||
| 0f39598687 | |||
| 24b4924410 | |||
| 4254cd19b9 | |||
| f42e1ad1a7 | |||
| 6872164e45 | |||
| 7abb189120 | |||
| a04dee2638 | |||
| bbebebaedf | |||
| 5195db1ff5 | |||
| 9b5ceb52b0 | |||
| 56051b84b0 | |||
| 2753057c40 |
73
.github/workflows/build.yml
vendored
73
.github/workflows/build.yml
vendored
@ -9,20 +9,41 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- '[0-9]+.[0-9]{2}'
|
||||
- '[0-9]+.[0-9]+'
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-20.04
|
||||
outputs:
|
||||
matrix: ${{ steps.platforms.outputs.matrix }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Create matrix
|
||||
id: platforms
|
||||
run: |
|
||||
echo "matrix=$(docker buildx bake cross --print | jq -cr '.target."cross".platforms')" >>${GITHUB_OUTPUT}
|
||||
-
|
||||
name: Show matrix
|
||||
run: |
|
||||
echo ${{ steps.platforms.outputs.matrix }}
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
needs:
|
||||
- prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target:
|
||||
- cross
|
||||
- dynbinary-cross
|
||||
- binary
|
||||
- dynbinary
|
||||
platform: ${{ fromJson(needs.prepare.outputs.matrix) }}
|
||||
use_glibc:
|
||||
- ""
|
||||
- glibc
|
||||
@ -36,22 +57,22 @@ jobs:
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Run ${{ matrix.target }}
|
||||
name: Build
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
set: |
|
||||
*.platform=${{ matrix.platform }}
|
||||
env:
|
||||
USE_GLIBC: ${{ matrix.use_glibc }}
|
||||
-
|
||||
name: Flatten artifacts
|
||||
name: Create tarball
|
||||
working-directory: ./build
|
||||
run: |
|
||||
for dir in */; do
|
||||
base=$(basename "$dir")
|
||||
echo "Creating ${base}.tar.gz ..."
|
||||
tar -cvzf "${base}.tar.gz" "$dir"
|
||||
rm -rf "$dir"
|
||||
done
|
||||
mkdir /tmp/out
|
||||
platform=${{ matrix.platform }}
|
||||
platformPair=${platform//\//-}
|
||||
tar -cvzf "/tmp/out/docker-${platformPair}.tar.gz" .
|
||||
if [ -z "${{ matrix.use_glibc }}" ]; then
|
||||
echo "ARTIFACT_NAME=${{ matrix.target }}" >> $GITHUB_ENV
|
||||
else
|
||||
@ -62,11 +83,35 @@ jobs:
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.ARTIFACT_NAME }}
|
||||
path: ./build/*
|
||||
path: /tmp/out/*
|
||||
if-no-files-found: error
|
||||
|
||||
prepare-plugins:
|
||||
runs-on: ubuntu-20.04
|
||||
outputs:
|
||||
matrix: ${{ steps.platforms.outputs.matrix }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Create matrix
|
||||
id: platforms
|
||||
run: |
|
||||
echo "matrix=$(docker buildx bake plugins-cross --print | jq -cr '.target."plugins-cross".platforms')" >>${GITHUB_OUTPUT}
|
||||
-
|
||||
name: Show matrix
|
||||
run: |
|
||||
echo ${{ steps.platforms.outputs.matrix }}
|
||||
|
||||
plugins:
|
||||
runs-on: ubuntu-20.04
|
||||
needs:
|
||||
- prepare-plugins
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: ${{ fromJson(needs.prepare-plugins.outputs.matrix) }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
@ -75,7 +120,9 @@ jobs:
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Build plugins
|
||||
name: Build
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: plugins-cross
|
||||
set: |
|
||||
*.platform=${{ matrix.platform }}
|
||||
|
||||
2
.github/workflows/e2e.yml
vendored
2
.github/workflows/e2e.yml
vendored
@ -9,7 +9,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- '[0-9]+.[0-9]{2}'
|
||||
- '[0-9]+.[0-9]+'
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
|
||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@ -9,7 +9,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- '[0-9]+.[0-9]{2}'
|
||||
- '[0-9]+.[0-9]+'
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
@ -61,9 +61,9 @@ jobs:
|
||||
path: ${{ env.GOPATH }}/src/github.com/docker/cli
|
||||
-
|
||||
name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.19.4
|
||||
go-version: 1.20.2
|
||||
-
|
||||
name: Test
|
||||
run: |
|
||||
|
||||
2
.github/workflows/validate.yml
vendored
2
.github/workflows/validate.yml
vendored
@ -9,7 +9,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- '[0-9]+.[0-9]{2}'
|
||||
- '[0-9]+.[0-9]+'
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
|
||||
10
Dockerfile
10
Dockerfile
@ -1,12 +1,12 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG BASE_VARIANT=alpine
|
||||
ARG GO_VERSION=1.19.5
|
||||
ARG GO_VERSION=1.20.2
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG XX_VERSION=1.1.1
|
||||
ARG GOVERSIONINFO_VERSION=v1.3.0
|
||||
ARG GOTESTSUM_VERSION=v1.8.2
|
||||
ARG BUILDX_VERSION=0.9.1
|
||||
ARG BUILDX_VERSION=0.10.4
|
||||
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
||||
@ -125,8 +125,8 @@ CMD ./scripts/test/e2e/entry
|
||||
FROM build-base-${BASE_VARIANT} AS dev
|
||||
COPY . .
|
||||
|
||||
FROM scratch AS binary
|
||||
COPY --from=build /out .
|
||||
|
||||
FROM scratch AS plugins
|
||||
COPY --from=build-plugins /out .
|
||||
|
||||
FROM scratch AS binary
|
||||
COPY --from=build /out .
|
||||
|
||||
@ -49,9 +49,9 @@
|
||||
|
||||
people = [
|
||||
"bsousaa",
|
||||
"neersighted",
|
||||
"programmerq",
|
||||
"sam-thibault",
|
||||
"thajeztah",
|
||||
"vvoland"
|
||||
]
|
||||
|
||||
@ -103,6 +103,11 @@
|
||||
Email = "nicolas.deloof@gmail.com"
|
||||
GitHub = "ndeloof"
|
||||
|
||||
[people.neersighted]
|
||||
Name = "Bjorn Neergaard"
|
||||
Email = "bneergaard@mirantis.com"
|
||||
GitHub = "neersighted"
|
||||
|
||||
[people.programmerq]
|
||||
Name = "Jeff Anderson"
|
||||
Email = "jeff@docker.com"
|
||||
|
||||
@ -3,6 +3,7 @@ package manager
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/spf13/cobra"
|
||||
@ -31,64 +32,69 @@ const (
|
||||
CommandAnnotationPluginInvalid = "com.docker.cli.plugin-invalid"
|
||||
)
|
||||
|
||||
var pluginCommandStubsOnce sync.Once
|
||||
|
||||
// AddPluginCommandStubs adds a stub cobra.Commands for each valid and invalid
|
||||
// plugin. The command stubs will have several annotations added, see
|
||||
// `CommandAnnotationPlugin*`.
|
||||
func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) error {
|
||||
plugins, err := ListPlugins(dockerCli, rootCmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, p := range plugins {
|
||||
p := p
|
||||
vendor := p.Vendor
|
||||
if vendor == "" {
|
||||
vendor = "unknown"
|
||||
func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) (err error) {
|
||||
pluginCommandStubsOnce.Do(func() {
|
||||
var plugins []Plugin
|
||||
plugins, err = ListPlugins(dockerCli, rootCmd)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
annotations := map[string]string{
|
||||
CommandAnnotationPlugin: "true",
|
||||
CommandAnnotationPluginVendor: vendor,
|
||||
CommandAnnotationPluginVersion: p.Version,
|
||||
}
|
||||
if p.Err != nil {
|
||||
annotations[CommandAnnotationPluginInvalid] = p.Err.Error()
|
||||
}
|
||||
rootCmd.AddCommand(&cobra.Command{
|
||||
Use: p.Name,
|
||||
Short: p.ShortDescription,
|
||||
Run: func(_ *cobra.Command, _ []string) {},
|
||||
Annotations: annotations,
|
||||
DisableFlagParsing: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
flags := rootCmd.PersistentFlags()
|
||||
flags.SetOutput(nil)
|
||||
err := flags.Parse(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if flags.Changed("help") {
|
||||
cmd.HelpFunc()(rootCmd, args)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("docker: '%s' is not a docker command.\nSee 'docker --help'", cmd.Name())
|
||||
},
|
||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
// Delegate completion to plugin
|
||||
cargs := []string{p.Path, cobra.ShellCompRequestCmd, p.Name}
|
||||
cargs = append(cargs, args...)
|
||||
cargs = append(cargs, toComplete)
|
||||
os.Args = cargs
|
||||
runCommand, err := PluginRunCommand(dockerCli, p.Name, cmd)
|
||||
if err != nil {
|
||||
for _, p := range plugins {
|
||||
p := p
|
||||
vendor := p.Vendor
|
||||
if vendor == "" {
|
||||
vendor = "unknown"
|
||||
}
|
||||
annotations := map[string]string{
|
||||
CommandAnnotationPlugin: "true",
|
||||
CommandAnnotationPluginVendor: vendor,
|
||||
CommandAnnotationPluginVersion: p.Version,
|
||||
}
|
||||
if p.Err != nil {
|
||||
annotations[CommandAnnotationPluginInvalid] = p.Err.Error()
|
||||
}
|
||||
rootCmd.AddCommand(&cobra.Command{
|
||||
Use: p.Name,
|
||||
Short: p.ShortDescription,
|
||||
Run: func(_ *cobra.Command, _ []string) {},
|
||||
Annotations: annotations,
|
||||
DisableFlagParsing: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
flags := rootCmd.PersistentFlags()
|
||||
flags.SetOutput(nil)
|
||||
perr := flags.Parse(args)
|
||||
if perr != nil {
|
||||
return err
|
||||
}
|
||||
if flags.Changed("help") {
|
||||
cmd.HelpFunc()(rootCmd, args)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("docker: '%s' is not a docker command.\nSee 'docker --help'", cmd.Name())
|
||||
},
|
||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
// Delegate completion to plugin
|
||||
cargs := []string{p.Path, cobra.ShellCompRequestCmd, p.Name}
|
||||
cargs = append(cargs, args...)
|
||||
cargs = append(cargs, toComplete)
|
||||
os.Args = cargs
|
||||
runCommand, runErr := PluginRunCommand(dockerCli, p.Name, cmd)
|
||||
if runErr != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
runErr = runCommand.Run()
|
||||
if runErr == nil {
|
||||
os.Exit(0) // plugin already rendered complete data
|
||||
}
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
err = runCommand.Run()
|
||||
if err == nil {
|
||||
os.Exit(0) // plugin already rendered complete data
|
||||
}
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
},
|
||||
})
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
10
cli/cobra.go
10
cli/cobra.go
@ -204,6 +204,16 @@ func DisableFlagsInUseLine(cmd *cobra.Command) {
|
||||
})
|
||||
}
|
||||
|
||||
// HasCompletionArg returns true if a cobra completion arg request is found.
|
||||
func HasCompletionArg(args []string) bool {
|
||||
for _, arg := range args {
|
||||
if arg == cobra.ShellCompRequestCmd || arg == cobra.ShellCompNoDescRequestCmd {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var helpCommand = &cobra.Command{
|
||||
Use: "help [command]",
|
||||
Short: "Help about the command",
|
||||
|
||||
@ -14,21 +14,21 @@ type fakeClient struct {
|
||||
checkpointListFunc func(container string, options types.CheckpointListOptions) ([]types.Checkpoint, error)
|
||||
}
|
||||
|
||||
func (cli *fakeClient) CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error {
|
||||
func (cli *fakeClient) CheckpointCreate(_ context.Context, container string, options types.CheckpointCreateOptions) error {
|
||||
if cli.checkpointCreateFunc != nil {
|
||||
return cli.checkpointCreateFunc(container, options)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) CheckpointDelete(ctx context.Context, container string, options types.CheckpointDeleteOptions) error {
|
||||
func (cli *fakeClient) CheckpointDelete(_ context.Context, container string, options types.CheckpointDeleteOptions) error {
|
||||
if cli.checkpointDeleteFunc != nil {
|
||||
return cli.checkpointDeleteFunc(container, options)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) CheckpointList(ctx context.Context, container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) {
|
||||
func (cli *fakeClient) CheckpointList(_ context.Context, container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) {
|
||||
if cli.checkpointListFunc != nil {
|
||||
return cli.checkpointListFunc(container, options)
|
||||
}
|
||||
|
||||
@ -191,7 +191,7 @@ func (cli *DockerCli) ManifestStore() manifeststore.Store {
|
||||
// RegistryClient returns a client for communicating with a Docker distribution
|
||||
// registry
|
||||
func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient {
|
||||
resolver := func(ctx context.Context, index *registry.IndexInfo) types.AuthConfig {
|
||||
resolver := func(ctx context.Context, index *registry.IndexInfo) registry.AuthConfig {
|
||||
return ResolveAuthConfig(ctx, cli, index)
|
||||
}
|
||||
return registryclient.NewRegistryClient(resolver, UserAgent(), allowInsecure)
|
||||
|
||||
@ -6,7 +6,7 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -66,13 +66,13 @@ func ContainerNames(dockerCli command.Cli, all bool, filters ...func(types.Conta
|
||||
// VolumeNames offers completion for volumes
|
||||
func VolumeNames(dockerCli command.Cli) ValidArgsFn {
|
||||
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
list, err := dockerCli.Client().VolumeList(cmd.Context(), filters.Args{})
|
||||
list, err := dockerCli.Client().VolumeList(cmd.Context(), volume.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
var names []string
|
||||
for _, volume := range list.Volumes {
|
||||
names = append(names, volume.Name)
|
||||
for _, vol := range list.Volumes {
|
||||
names = append(names, vol.Name)
|
||||
}
|
||||
return names, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
@ -94,6 +94,6 @@ func NetworkNames(dockerCli command.Cli) ValidArgsFn {
|
||||
}
|
||||
|
||||
// NoComplete is used for commands where there's no relevant completion
|
||||
func NoComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
func NoComplete(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
@ -10,34 +10,34 @@ import (
|
||||
|
||||
type fakeClient struct {
|
||||
client.Client
|
||||
configCreateFunc func(swarm.ConfigSpec) (types.ConfigCreateResponse, error)
|
||||
configInspectFunc func(string) (swarm.Config, []byte, error)
|
||||
configListFunc func(types.ConfigListOptions) ([]swarm.Config, error)
|
||||
configCreateFunc func(context.Context, swarm.ConfigSpec) (types.ConfigCreateResponse, error)
|
||||
configInspectFunc func(context.Context, string) (swarm.Config, []byte, error)
|
||||
configListFunc func(context.Context, types.ConfigListOptions) ([]swarm.Config, error)
|
||||
configRemoveFunc func(string) error
|
||||
}
|
||||
|
||||
func (c *fakeClient) ConfigCreate(ctx context.Context, spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
||||
if c.configCreateFunc != nil {
|
||||
return c.configCreateFunc(spec)
|
||||
return c.configCreateFunc(ctx, spec)
|
||||
}
|
||||
return types.ConfigCreateResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) {
|
||||
if c.configInspectFunc != nil {
|
||||
return c.configInspectFunc(id)
|
||||
return c.configInspectFunc(ctx, id)
|
||||
}
|
||||
return swarm.Config{}, nil, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
if c.configListFunc != nil {
|
||||
return c.configListFunc(options)
|
||||
return c.configListFunc(ctx, options)
|
||||
}
|
||||
return []swarm.Config{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) ConfigRemove(ctx context.Context, name string) error {
|
||||
func (c *fakeClient) ConfigRemove(_ context.Context, name string) error {
|
||||
if c.configRemoveFunc != nil {
|
||||
return c.configRemoveFunc(name)
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -22,7 +23,7 @@ const configDataFile = "config-create-with-name.golden"
|
||||
func TestConfigCreateErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
configCreateFunc func(swarm.ConfigSpec) (types.ConfigCreateResponse, error)
|
||||
configCreateFunc func(context.Context, swarm.ConfigSpec) (types.ConfigCreateResponse, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
@ -35,7 +36,7 @@ func TestConfigCreateErrors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
args: []string{"name", filepath.Join("testdata", configDataFile)},
|
||||
configCreateFunc: func(configSpec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
||||
configCreateFunc: func(_ context.Context, configSpec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
||||
return types.ConfigCreateResponse{}, errors.Errorf("error creating config")
|
||||
},
|
||||
expectedError: "error creating config",
|
||||
@ -57,7 +58,7 @@ func TestConfigCreateWithName(t *testing.T) {
|
||||
name := "foo"
|
||||
var actual []byte
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
configCreateFunc: func(spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
||||
configCreateFunc: func(_ context.Context, spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
||||
if spec.Name != name {
|
||||
return types.ConfigCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
|
||||
}
|
||||
@ -96,7 +97,7 @@ func TestConfigCreateWithLabels(t *testing.T) {
|
||||
}
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
configCreateFunc: func(spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
||||
configCreateFunc: func(_ context.Context, spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
||||
if !reflect.DeepEqual(spec, expected) {
|
||||
return types.ConfigCreateResponse{}, errors.Errorf("expected %+v, got %+v", expected, spec)
|
||||
}
|
||||
@ -122,7 +123,7 @@ func TestConfigCreateWithTemplatingDriver(t *testing.T) {
|
||||
name := "foo"
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
configCreateFunc: func(spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
||||
configCreateFunc: func(_ context.Context, spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
|
||||
if spec.Name != name {
|
||||
return types.ConfigCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
@ -18,7 +19,7 @@ func TestConfigInspectErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
flags map[string]string
|
||||
configInspectFunc func(configID string) (swarm.Config, []byte, error)
|
||||
configInspectFunc func(_ context.Context, configID string) (swarm.Config, []byte, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
@ -26,7 +27,7 @@ func TestConfigInspectErrors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
args: []string{"foo"},
|
||||
configInspectFunc: func(configID string) (swarm.Config, []byte, error) {
|
||||
configInspectFunc: func(_ context.Context, configID string) (swarm.Config, []byte, error) {
|
||||
return swarm.Config{}, nil, errors.Errorf("error while inspecting the config")
|
||||
},
|
||||
expectedError: "error while inspecting the config",
|
||||
@ -40,7 +41,7 @@ func TestConfigInspectErrors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
args: []string{"foo", "bar"},
|
||||
configInspectFunc: func(configID string) (swarm.Config, []byte, error) {
|
||||
configInspectFunc: func(_ context.Context, configID string) (swarm.Config, []byte, error) {
|
||||
if configID == "foo" {
|
||||
return *Config(ConfigName("foo")), nil, nil
|
||||
}
|
||||
@ -68,12 +69,12 @@ func TestConfigInspectWithoutFormat(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
configInspectFunc func(configID string) (swarm.Config, []byte, error)
|
||||
configInspectFunc func(_ context.Context, configID string) (swarm.Config, []byte, error)
|
||||
}{
|
||||
{
|
||||
name: "single-config",
|
||||
args: []string{"foo"},
|
||||
configInspectFunc: func(name string) (swarm.Config, []byte, error) {
|
||||
configInspectFunc: func(_ context.Context, name string) (swarm.Config, []byte, error) {
|
||||
if name != "foo" {
|
||||
return swarm.Config{}, nil, errors.Errorf("Invalid name, expected %s, got %s", "foo", name)
|
||||
}
|
||||
@ -83,7 +84,7 @@ func TestConfigInspectWithoutFormat(t *testing.T) {
|
||||
{
|
||||
name: "multiple-configs-with-labels",
|
||||
args: []string{"foo", "bar"},
|
||||
configInspectFunc: func(name string) (swarm.Config, []byte, error) {
|
||||
configInspectFunc: func(_ context.Context, name string) (swarm.Config, []byte, error) {
|
||||
return *Config(ConfigID("ID-"+name), ConfigName(name), ConfigLabels(map[string]string{
|
||||
"label1": "label-foo",
|
||||
})), nil, nil
|
||||
@ -100,7 +101,7 @@ func TestConfigInspectWithoutFormat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestConfigInspectWithFormat(t *testing.T) {
|
||||
configInspectFunc := func(name string) (swarm.Config, []byte, error) {
|
||||
configInspectFunc := func(_ context.Context, name string) (swarm.Config, []byte, error) {
|
||||
return *Config(ConfigName("foo"), ConfigLabels(map[string]string{
|
||||
"label1": "label-foo",
|
||||
})), nil, nil
|
||||
@ -109,7 +110,7 @@ func TestConfigInspectWithFormat(t *testing.T) {
|
||||
name string
|
||||
format string
|
||||
args []string
|
||||
configInspectFunc func(name string) (swarm.Config, []byte, error)
|
||||
configInspectFunc func(_ context.Context, name string) (swarm.Config, []byte, error)
|
||||
}{
|
||||
{
|
||||
name: "simple-template",
|
||||
@ -139,11 +140,11 @@ func TestConfigInspectWithFormat(t *testing.T) {
|
||||
func TestConfigInspectPretty(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
configInspectFunc func(string) (swarm.Config, []byte, error)
|
||||
configInspectFunc func(context.Context, string) (swarm.Config, []byte, error)
|
||||
}{
|
||||
{
|
||||
name: "simple",
|
||||
configInspectFunc: func(id string) (swarm.Config, []byte, error) {
|
||||
configInspectFunc: func(_ context.Context, id string) (swarm.Config, []byte, error) {
|
||||
return *Config(
|
||||
ConfigLabels(map[string]string{
|
||||
"lbl1": "value1",
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
@ -19,7 +20,7 @@ import (
|
||||
func TestConfigListErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
configListFunc func(types.ConfigListOptions) ([]swarm.Config, error)
|
||||
configListFunc func(context.Context, types.ConfigListOptions) ([]swarm.Config, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
@ -27,7 +28,7 @@ func TestConfigListErrors(t *testing.T) {
|
||||
expectedError: "accepts no argument",
|
||||
},
|
||||
{
|
||||
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
return []swarm.Config{}, errors.Errorf("error listing configs")
|
||||
},
|
||||
expectedError: "error listing configs",
|
||||
@ -47,7 +48,7 @@ func TestConfigListErrors(t *testing.T) {
|
||||
|
||||
func TestConfigList(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
return []swarm.Config{
|
||||
*Config(ConfigID("ID-1-foo"),
|
||||
ConfigName("1-foo"),
|
||||
@ -77,7 +78,7 @@ func TestConfigList(t *testing.T) {
|
||||
|
||||
func TestConfigListWithQuietOption(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
return []swarm.Config{
|
||||
*Config(ConfigID("ID-foo"), ConfigName("foo")),
|
||||
*Config(ConfigID("ID-bar"), ConfigName("bar"), ConfigLabels(map[string]string{
|
||||
@ -94,7 +95,7 @@ func TestConfigListWithQuietOption(t *testing.T) {
|
||||
|
||||
func TestConfigListWithConfigFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
return []swarm.Config{
|
||||
*Config(ConfigID("ID-foo"), ConfigName("foo")),
|
||||
*Config(ConfigID("ID-bar"), ConfigName("bar"), ConfigLabels(map[string]string{
|
||||
@ -113,7 +114,7 @@ func TestConfigListWithConfigFormat(t *testing.T) {
|
||||
|
||||
func TestConfigListWithFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
return []swarm.Config{
|
||||
*Config(ConfigID("ID-foo"), ConfigName("foo")),
|
||||
*Config(ConfigID("ID-bar"), ConfigName("bar"), ConfigLabels(map[string]string{
|
||||
@ -130,7 +131,7 @@ func TestConfigListWithFormat(t *testing.T) {
|
||||
|
||||
func TestConfigListWithFilter(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
assert.Check(t, is.Equal("foo", options.Filters.Get("name")[0]))
|
||||
assert.Check(t, is.Equal("lbl1=Label-bar", options.Filters.Get("label")[0]))
|
||||
return []swarm.Config{
|
||||
|
||||
@ -64,7 +64,7 @@ func (f *fakeClient) ContainerExecInspect(_ context.Context, execID string) (typ
|
||||
return types.ContainerExecInspect{}, nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error {
|
||||
func (f *fakeClient) ContainerExecStart(context.Context, string, types.ExecStartCheck) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ func (f *fakeClient) ContainerRemove(ctx context.Context, container string, opti
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeClient) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) {
|
||||
func (f *fakeClient) ImageCreate(_ context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) {
|
||||
if f.imageCreateFunc != nil {
|
||||
return f.imageCreateFunc(parentReference, options)
|
||||
}
|
||||
|
||||
@ -1,15 +1,20 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
@ -48,26 +53,73 @@ type cpConfig struct {
|
||||
// copying files to/from a container.
|
||||
type copyProgressPrinter struct {
|
||||
io.ReadCloser
|
||||
toContainer bool
|
||||
total *float64
|
||||
writer io.Writer
|
||||
total *int64
|
||||
}
|
||||
|
||||
const (
|
||||
copyToContainerHeader = "Copying to container - "
|
||||
copyFromContainerHeader = "Copying from container - "
|
||||
copyProgressUpdateThreshold = 75 * time.Millisecond
|
||||
)
|
||||
|
||||
func (pt *copyProgressPrinter) Read(p []byte) (int, error) {
|
||||
n, err := pt.ReadCloser.Read(p)
|
||||
*pt.total += float64(n)
|
||||
atomic.AddInt64(pt.total, int64(n))
|
||||
return n, err
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
fmt.Fprint(pt.writer, aec.Restore)
|
||||
fmt.Fprint(pt.writer, aec.EraseLine(aec.EraseModes.All))
|
||||
if pt.toContainer {
|
||||
fmt.Fprintln(pt.writer, "Copying to container - "+units.HumanSize(*pt.total))
|
||||
} else {
|
||||
fmt.Fprintln(pt.writer, "Copying from container - "+units.HumanSize(*pt.total))
|
||||
}
|
||||
func copyProgress(ctx context.Context, dst io.Writer, header string, total *int64) (func(), <-chan struct{}) {
|
||||
done := make(chan struct{})
|
||||
if !streams.NewOut(dst).IsTerminal() {
|
||||
close(done)
|
||||
return func() {}, done
|
||||
}
|
||||
|
||||
return n, err
|
||||
fmt.Fprint(dst, aec.Save)
|
||||
fmt.Fprint(dst, "Preparing to copy...")
|
||||
|
||||
restore := func() {
|
||||
fmt.Fprint(dst, aec.Restore)
|
||||
fmt.Fprint(dst, aec.EraseLine(aec.EraseModes.All))
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer close(done)
|
||||
fmt.Fprint(dst, aec.Hide)
|
||||
defer fmt.Fprint(dst, aec.Show)
|
||||
|
||||
fmt.Fprint(dst, aec.Restore)
|
||||
fmt.Fprint(dst, aec.EraseLine(aec.EraseModes.All))
|
||||
fmt.Fprint(dst, header)
|
||||
|
||||
var last int64
|
||||
fmt.Fprint(dst, progressHumanSize(last))
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
ticker := time.NewTicker(copyProgressUpdateThreshold)
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
n := atomic.LoadInt64(total)
|
||||
if n == last {
|
||||
// Don't write to the terminal, if we don't need to.
|
||||
continue
|
||||
}
|
||||
|
||||
// Write to the buffer first to avoid flickering and context switching
|
||||
fmt.Fprint(buf, aec.Column(uint(len(header)+1)))
|
||||
fmt.Fprint(buf, aec.EraseLine(aec.EraseModes.Tail))
|
||||
fmt.Fprint(buf, progressHumanSize(n))
|
||||
|
||||
buf.WriteTo(dst)
|
||||
buf.Reset()
|
||||
last += n
|
||||
}
|
||||
}
|
||||
}()
|
||||
return restore, done
|
||||
}
|
||||
|
||||
// NewCopyCommand creates a new `docker cp` command
|
||||
@ -113,6 +165,10 @@ func NewCopyCommand(dockerCli command.Cli) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func progressHumanSize(n int64) string {
|
||||
return units.HumanSizeWithPrecision(float64(n), 3)
|
||||
}
|
||||
|
||||
func runCopy(dockerCli command.Cli, opts copyOptions) error {
|
||||
srcContainer, srcPath := splitCpArg(opts.source)
|
||||
destContainer, destPath := splitCpArg(opts.destination)
|
||||
@ -153,7 +209,7 @@ func resolveLocalPath(localPath string) (absPath string, err error) {
|
||||
if absPath, err = filepath.Abs(localPath); err != nil {
|
||||
return
|
||||
}
|
||||
return archive.PreserveTrailingDotOrSeparator(absPath, localPath, filepath.Separator), nil
|
||||
return archive.PreserveTrailingDotOrSeparator(absPath, localPath), nil
|
||||
}
|
||||
|
||||
func copyFromContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpConfig) (err error) {
|
||||
@ -193,6 +249,9 @@ func copyFromContainer(ctx context.Context, dockerCli command.Cli, copyConfig cp
|
||||
|
||||
}
|
||||
|
||||
ctx, cancel := signal.NotifyContext(ctx, os.Interrupt)
|
||||
defer cancel()
|
||||
|
||||
content, stat, err := client.CopyFromContainer(ctx, copyConfig.container, srcPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -211,13 +270,11 @@ func copyFromContainer(ctx context.Context, dockerCli command.Cli, copyConfig cp
|
||||
RebaseName: rebaseName,
|
||||
}
|
||||
|
||||
var copiedSize float64
|
||||
var copiedSize int64
|
||||
if !copyConfig.quiet {
|
||||
content = ©ProgressPrinter{
|
||||
ReadCloser: content,
|
||||
toContainer: false,
|
||||
writer: dockerCli.Err(),
|
||||
total: &copiedSize,
|
||||
ReadCloser: content,
|
||||
total: &copiedSize,
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,12 +288,12 @@ func copyFromContainer(ctx context.Context, dockerCli command.Cli, copyConfig cp
|
||||
return archive.CopyTo(preArchive, srcInfo, dstPath)
|
||||
}
|
||||
|
||||
fmt.Fprint(dockerCli.Err(), aec.Save)
|
||||
fmt.Fprintln(dockerCli.Err(), "Preparing to copy...")
|
||||
restore, done := copyProgress(ctx, dockerCli.Err(), copyFromContainerHeader, &copiedSize)
|
||||
res := archive.CopyTo(preArchive, srcInfo, dstPath)
|
||||
fmt.Fprint(dockerCli.Err(), aec.Restore)
|
||||
fmt.Fprint(dockerCli.Err(), aec.EraseLine(aec.EraseModes.All))
|
||||
fmt.Fprintln(dockerCli.Err(), "Successfully copied", units.HumanSize(copiedSize), "to", dstPath)
|
||||
cancel()
|
||||
<-done
|
||||
restore()
|
||||
fmt.Fprintln(dockerCli.Err(), "Successfully copied", progressHumanSize(copiedSize), "to", dstPath)
|
||||
|
||||
return res
|
||||
}
|
||||
@ -293,7 +350,7 @@ func copyToContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpCo
|
||||
var (
|
||||
content io.ReadCloser
|
||||
resolvedDstPath string
|
||||
copiedSize float64
|
||||
copiedSize int64
|
||||
)
|
||||
|
||||
if srcPath == "-" {
|
||||
@ -337,10 +394,8 @@ func copyToContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpCo
|
||||
content = preparedArchive
|
||||
if !copyConfig.quiet {
|
||||
content = ©ProgressPrinter{
|
||||
ReadCloser: content,
|
||||
toContainer: true,
|
||||
writer: dockerCli.Err(),
|
||||
total: &copiedSize,
|
||||
ReadCloser: content,
|
||||
total: &copiedSize,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -354,12 +409,13 @@ func copyToContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpCo
|
||||
return client.CopyToContainer(ctx, copyConfig.container, resolvedDstPath, content, options)
|
||||
}
|
||||
|
||||
fmt.Fprint(dockerCli.Err(), aec.Save)
|
||||
fmt.Fprintln(dockerCli.Err(), "Preparing to copy...")
|
||||
ctx, cancel := signal.NotifyContext(ctx, os.Interrupt)
|
||||
restore, done := copyProgress(ctx, dockerCli.Err(), copyToContainerHeader, &copiedSize)
|
||||
res := client.CopyToContainer(ctx, copyConfig.container, resolvedDstPath, content, options)
|
||||
fmt.Fprint(dockerCli.Err(), aec.Restore)
|
||||
fmt.Fprint(dockerCli.Err(), aec.EraseLine(aec.EraseModes.All))
|
||||
fmt.Fprintln(dockerCli.Err(), "Successfully copied", units.HumanSize(copiedSize), "to", copyConfig.container+":"+dstInfo.Path)
|
||||
cancel()
|
||||
<-done
|
||||
restore()
|
||||
fmt.Fprintln(dockerCli.Err(), "Successfully copied", progressHumanSize(copiedSize), "to", copyConfig.container+":"+dstInfo.Path)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
@ -227,7 +227,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
|
||||
|
||||
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && !opts.untrusted {
|
||||
var err error
|
||||
trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef, nil)
|
||||
trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -17,14 +17,15 @@ import (
|
||||
)
|
||||
|
||||
type psOptions struct {
|
||||
quiet bool
|
||||
size bool
|
||||
all bool
|
||||
noTrunc bool
|
||||
nLatest bool
|
||||
last int
|
||||
format string
|
||||
filter opts.FilterOpt
|
||||
quiet bool
|
||||
size bool
|
||||
sizeChanged bool
|
||||
all bool
|
||||
noTrunc bool
|
||||
nLatest bool
|
||||
last int
|
||||
format string
|
||||
filter opts.FilterOpt
|
||||
}
|
||||
|
||||
// NewPsCommand creates a new cobra.Command for `docker ps`
|
||||
@ -36,6 +37,7 @@ func NewPsCommand(dockerCli command.Cli) *cobra.Command {
|
||||
Short: "List containers",
|
||||
Args: cli.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
options.sizeChanged = cmd.Flags().Changed("size")
|
||||
return runPs(dockerCli, &options)
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
@ -78,13 +80,8 @@ func buildContainerListOptions(opts *psOptions) (*types.ContainerListOptions, er
|
||||
options.Limit = 1
|
||||
}
|
||||
|
||||
if !opts.quiet && !options.Size && len(opts.format) > 0 {
|
||||
// The --size option isn't set, but .Size may be used in the template.
|
||||
// Parse and execute the given template to detect if the .Size field is
|
||||
// used. If it is, then automatically enable the --size option. See #24696
|
||||
//
|
||||
// Only requesting container size information when needed is an optimization,
|
||||
// because calculating the size is a costly operation.
|
||||
// always validate template when `--format` is used, for consistency
|
||||
if len(opts.format) > 0 {
|
||||
tmpl, err := templates.NewParse("", opts.format)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse template")
|
||||
@ -98,8 +95,19 @@ func buildContainerListOptions(opts *psOptions) (*types.ContainerListOptions, er
|
||||
return nil, errors.Wrap(err, "failed to execute template")
|
||||
}
|
||||
|
||||
if _, ok := optionsProcessor.FieldsUsed["Size"]; ok {
|
||||
options.Size = true
|
||||
// if `size` was not explicitly set to false (with `--size=false`)
|
||||
// and `--quiet` is not set, request size if the template requires it
|
||||
if !opts.quiet && !options.Size && !opts.sizeChanged {
|
||||
// The --size option isn't set, but .Size may be used in the template.
|
||||
// Parse and execute the given template to detect if the .Size field is
|
||||
// used. If it is, then automatically enable the --size option. See #24696
|
||||
//
|
||||
// Only requesting container size information when needed is an optimization,
|
||||
// because calculating the size is a costly operation.
|
||||
|
||||
if _, ok := optionsProcessor.FieldsUsed["Size"]; ok {
|
||||
options.Size = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -231,15 +231,56 @@ func TestContainerListFormatTemplateWithArg(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestContainerListFormatSizeSetsOption(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(options types.ContainerListOptions) ([]types.Container, error) {
|
||||
assert.Check(t, options.Size)
|
||||
return []types.Container{}, nil
|
||||
tests := []struct {
|
||||
doc, format, sizeFlag string
|
||||
sizeExpected bool
|
||||
}{
|
||||
{
|
||||
doc: "detect with all fields",
|
||||
format: `{{json .}}`,
|
||||
sizeExpected: true,
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
cmd.Flags().Set("format", `{{.Size}}`)
|
||||
assert.NilError(t, cmd.Execute())
|
||||
{
|
||||
doc: "detect with explicit field",
|
||||
format: `{{.Size}}`,
|
||||
sizeExpected: true,
|
||||
},
|
||||
{
|
||||
doc: "detect no size",
|
||||
format: `{{.Names}}`,
|
||||
sizeExpected: false,
|
||||
},
|
||||
{
|
||||
doc: "override enable",
|
||||
format: `{{.Names}}`,
|
||||
sizeFlag: "true",
|
||||
sizeExpected: true,
|
||||
},
|
||||
{
|
||||
doc: "override disable",
|
||||
format: `{{.Size}}`,
|
||||
sizeFlag: "false",
|
||||
sizeExpected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(options types.ContainerListOptions) ([]types.Container, error) {
|
||||
assert.Check(t, is.Equal(options.Size, tc.sizeExpected))
|
||||
return []types.Container{}, nil
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
cmd.Flags().Set("format", tc.format)
|
||||
if tc.sizeFlag != "" {
|
||||
cmd.Flags().Set("size", tc.sizeFlag)
|
||||
}
|
||||
assert.NilError(t, cmd.Execute())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestContainerListWithConfigFormat(t *testing.T) {
|
||||
|
||||
@ -75,6 +75,6 @@ func runPrune(dockerCli command.Cli, options pruneOptions) (spaceReclaimed uint6
|
||||
|
||||
// RunPrune calls the Container Prune API
|
||||
// This returns the amount of space reclaimed and a detailed output string
|
||||
func RunPrune(dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error) {
|
||||
func RunPrune(dockerCli command.Cli, _ bool, filter opts.FilterOpt) (uint64, string, error) {
|
||||
return runPrune(dockerCli, pruneOptions{force: true, filter: filter})
|
||||
}
|
||||
|
||||
@ -173,11 +173,11 @@ func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptio
|
||||
dockerCli.ConfigFile().DetachKeys = opts.detachKeys
|
||||
}
|
||||
|
||||
close, err := attachContainer(ctx, dockerCli, &errCh, config, createResponse.ID)
|
||||
closeFn, err := attachContainer(ctx, dockerCli, &errCh, config, createResponse.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer close()
|
||||
defer closeFn()
|
||||
}
|
||||
|
||||
statusChan := waitExitOrRemoved(ctx, dockerCli, createResponse.ID, copts.autoRemove)
|
||||
@ -308,7 +308,8 @@ func runStartContainerErr(err error) error {
|
||||
strings.Contains(trimmedErr, "no such file or directory") ||
|
||||
strings.Contains(trimmedErr, "system cannot find the file specified") {
|
||||
statusError = cli.StatusError{StatusCode: 127}
|
||||
} else if strings.Contains(trimmedErr, syscall.EACCES.Error()) {
|
||||
} else if strings.Contains(trimmedErr, syscall.EACCES.Error()) ||
|
||||
strings.Contains(trimmedErr, syscall.EISDIR.Error()) {
|
||||
statusError = cli.StatusError{StatusCode: 126}
|
||||
}
|
||||
|
||||
|
||||
@ -118,10 +118,7 @@ func createNewContext(o *CreateOptions, cli command.Cli, s store.Writer) error {
|
||||
if err := s.CreateOrUpdate(contextMetadata); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.ResetTLSMaterial(o.Name, &contextTLSData); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return s.ResetTLSMaterial(o.Name, &contextTLSData)
|
||||
}
|
||||
|
||||
func checkContextNameForCreation(s store.Reader, name string) error {
|
||||
|
||||
@ -27,6 +27,9 @@ type ImageContext struct {
|
||||
}
|
||||
|
||||
func isDangling(image types.ImageSummary) bool {
|
||||
if len(image.RepoTags) == 0 && len(image.RepoDigests) == 0 {
|
||||
return true
|
||||
}
|
||||
return len(image.RepoTags) == 1 && image.RepoTags[0] == "<none>:<none>" && len(image.RepoDigests) == 1 && image.RepoDigests[0] == "<none>@<none>"
|
||||
}
|
||||
|
||||
|
||||
@ -14,14 +14,14 @@ type fakeClient struct {
|
||||
serviceInspectFunc func(string) (swarm.Service, []byte, error)
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error) {
|
||||
func (cli *fakeClient) NodeInspectWithRaw(_ context.Context, nodeID string) (swarm.Node, []byte, error) {
|
||||
if cli.nodeInspectFunc != nil {
|
||||
return cli.nodeInspectFunc(nodeID)
|
||||
}
|
||||
return swarm.Node{}, []byte{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServiceInspectWithRaw(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) {
|
||||
func (cli *fakeClient) ServiceInspectWithRaw(_ context.Context, serviceID string, _ types.ServiceInspectOptions) (swarm.Service, []byte, error) {
|
||||
if cli.serviceInspectFunc != nil {
|
||||
return cli.serviceInspectFunc(serviceID)
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ import (
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/builder/remotecontext/urlutil"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
@ -279,7 +280,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||
var resolvedTags []*resolvedTag
|
||||
if !options.untrusted {
|
||||
translator := func(ctx context.Context, ref reference.NamedTagged) (reference.Canonical, error) {
|
||||
return TrustedReference(ctx, dockerCli, ref, nil)
|
||||
return TrustedReference(ctx, dockerCli, ref)
|
||||
}
|
||||
// if there is a tar wrapper, the dockerfile needs to be replaced inside it
|
||||
if buildCtx != nil {
|
||||
@ -322,9 +323,9 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
|
||||
|
||||
configFile := dockerCli.ConfigFile()
|
||||
creds, _ := configFile.GetAllCredentials()
|
||||
authConfigs := make(map[string]types.AuthConfig, len(creds))
|
||||
authConfigs := make(map[string]registrytypes.AuthConfig, len(creds))
|
||||
for k, auth := range creds {
|
||||
authConfigs[k] = types.AuthConfig(auth)
|
||||
authConfigs[k] = registrytypes.AuthConfig(auth)
|
||||
}
|
||||
buildOptions := imageBuildOptions(dockerCli, options)
|
||||
buildOptions.Version = types.BuilderV1
|
||||
|
||||
@ -18,7 +18,7 @@ import (
|
||||
|
||||
const dockerfileContents = "FROM busybox"
|
||||
|
||||
func prepareEmpty(t *testing.T) string {
|
||||
func prepareEmpty(_ *testing.T) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
@ -87,11 +87,11 @@ func (cli *fakeClient) ImageLoad(_ context.Context, input io.Reader, quiet bool)
|
||||
return types.ImageLoadResponse{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) {
|
||||
func (cli *fakeClient) ImageList(_ context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) {
|
||||
if cli.imageListFunc != nil {
|
||||
return cli.imageListFunc(options)
|
||||
}
|
||||
return []types.ImageSummary{{}}, nil
|
||||
return []types.ImageSummary{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ImageInspectWithRaw(_ context.Context, image string) (types.ImageInspect, []byte, error) {
|
||||
|
||||
@ -30,7 +30,7 @@ func TestNewImagesCommandErrors(t *testing.T) {
|
||||
name: "failed-list",
|
||||
expectedError: "something went wrong",
|
||||
imageListFunc: func(options types.ImageListOptions) ([]types.ImageSummary, error) {
|
||||
return []types.ImageSummary{{}}, errors.Errorf("something went wrong")
|
||||
return []types.ImageSummary{}, errors.Errorf("something went wrong")
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -66,7 +66,7 @@ func TestNewImagesCommandSuccess(t *testing.T) {
|
||||
args: []string{"image"},
|
||||
imageListFunc: func(options types.ImageListOptions) ([]types.ImageSummary, error) {
|
||||
assert.Check(t, is.Equal("image", options.Filters.Get("reference")[0]))
|
||||
return []types.ImageSummary{{}}, nil
|
||||
return []types.ImageSummary{}, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -74,7 +74,7 @@ func TestNewImagesCommandSuccess(t *testing.T) {
|
||||
args: []string{"--filter", "name=value"},
|
||||
imageListFunc: func(options types.ImageListOptions) ([]types.ImageSummary, error) {
|
||||
assert.Check(t, is.Equal("value", options.Filters.Get("name")[0]))
|
||||
return []types.ImageSummary{{}}, nil
|
||||
return []types.ImageSummary{}, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ func RunPull(cli command.Cli, opts PullOptions) error {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, AuthResolver(cli), distributionRef.String())
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), distributionRef.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ type target struct {
|
||||
}
|
||||
|
||||
// TrustedPush handles content trust pushing of an image
|
||||
func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, options types.ImagePushOptions) error {
|
||||
func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig registrytypes.AuthConfig, options types.ImagePushOptions) error {
|
||||
responseBody, err := cli.Client().ImagePush(ctx, reference.FamiliarString(ref), options)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -44,7 +44,7 @@ func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.Reposi
|
||||
// PushTrustedReference pushes a canonical reference to the trust server.
|
||||
//
|
||||
//nolint:gocyclo
|
||||
func PushTrustedReference(streams command.Streams, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, in io.Reader) error {
|
||||
func PushTrustedReference(streams command.Streams, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig registrytypes.AuthConfig, in io.Reader) error {
|
||||
// If it is a trusted push we would like to find the target entry which match the
|
||||
// tag provided in the function and then do an AddTarget later.
|
||||
target := &client.Target{}
|
||||
@ -186,7 +186,7 @@ func trustedPull(ctx context.Context, cli command.Cli, imgRefAndAuth trust.Image
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, AuthResolver(cli), trustedRef.String())
|
||||
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), trustedRef.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -289,8 +289,8 @@ func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth tru
|
||||
}
|
||||
|
||||
// TrustedReference returns the canonical trusted reference for an image reference
|
||||
func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedTagged, rs registry.Service) (reference.Canonical, error) {
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, rs, AuthResolver(cli), ref.String())
|
||||
func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) {
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), ref.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -340,8 +340,8 @@ func TagTrusted(ctx context.Context, cli command.Cli, trustedRef reference.Canon
|
||||
}
|
||||
|
||||
// AuthResolver returns an auth resolver function from a command.Cli
|
||||
func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
|
||||
return func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
|
||||
func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
|
||||
return func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
|
||||
return command.ResolveAuthConfig(ctx, cli, index)
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,6 +52,6 @@ func (c *fakeClient) NetworkRemove(ctx context.Context, networkID string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) NetworkInspectWithRaw(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, []byte, error) {
|
||||
func (c *fakeClient) NetworkInspectWithRaw(context.Context, string, types.NetworkInspectOptions) (types.NetworkResource, []byte, error) {
|
||||
return types.NetworkResource{}, nil, nil
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ func runPrune(dockerCli command.Cli, options pruneOptions) (output string, err e
|
||||
|
||||
// RunPrune calls the Network Prune API
|
||||
// This returns the amount of space reclaimed and a detailed output string
|
||||
func RunPrune(dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error) {
|
||||
func RunPrune(dockerCli command.Cli, _ bool, filter opts.FilterOpt) (uint64, string, error) {
|
||||
output, err := runPrune(dockerCli, pruneOptions{force: true, filter: filter})
|
||||
return 0, output, err
|
||||
}
|
||||
|
||||
@ -20,49 +20,49 @@ type fakeClient struct {
|
||||
serviceInspectFunc func(ctx context.Context, serviceID string, opts types.ServiceInspectOptions) (swarm.Service, []byte, error)
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, ref string) (swarm.Node, []byte, error) {
|
||||
func (cli *fakeClient) NodeInspectWithRaw(context.Context, string) (swarm.Node, []byte, error) {
|
||||
if cli.nodeInspectFunc != nil {
|
||||
return cli.nodeInspectFunc()
|
||||
}
|
||||
return swarm.Node{}, []byte{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) {
|
||||
func (cli *fakeClient) NodeList(context.Context, types.NodeListOptions) ([]swarm.Node, error) {
|
||||
if cli.nodeListFunc != nil {
|
||||
return cli.nodeListFunc()
|
||||
}
|
||||
return []swarm.Node{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error {
|
||||
func (cli *fakeClient) NodeRemove(context.Context, string, types.NodeRemoveOptions) error {
|
||||
if cli.nodeRemoveFunc != nil {
|
||||
return cli.nodeRemoveFunc()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error {
|
||||
func (cli *fakeClient) NodeUpdate(_ context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error {
|
||||
if cli.nodeUpdateFunc != nil {
|
||||
return cli.nodeUpdateFunc(nodeID, version, node)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) Info(ctx context.Context) (types.Info, error) {
|
||||
func (cli *fakeClient) Info(context.Context) (types.Info, error) {
|
||||
if cli.infoFunc != nil {
|
||||
return cli.infoFunc()
|
||||
}
|
||||
return types.Info{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) {
|
||||
func (cli *fakeClient) TaskInspectWithRaw(_ context.Context, taskID string) (swarm.Task, []byte, error) {
|
||||
if cli.taskInspectFunc != nil {
|
||||
return cli.taskInspectFunc(taskID)
|
||||
}
|
||||
return swarm.Task{}, []byte{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
func (cli *fakeClient) TaskList(_ context.Context, options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
if cli.taskListFunc != nil {
|
||||
return cli.taskListFunc(options)
|
||||
}
|
||||
|
||||
@ -20,42 +20,42 @@ type fakeClient struct {
|
||||
pluginInspectFunc func(name string) (*types.Plugin, []byte, error)
|
||||
}
|
||||
|
||||
func (c *fakeClient) PluginCreate(ctx context.Context, createContext io.Reader, createOptions types.PluginCreateOptions) error {
|
||||
func (c *fakeClient) PluginCreate(_ context.Context, createContext io.Reader, createOptions types.PluginCreateOptions) error {
|
||||
if c.pluginCreateFunc != nil {
|
||||
return c.pluginCreateFunc(createContext, createOptions)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) PluginEnable(ctx context.Context, name string, enableOptions types.PluginEnableOptions) error {
|
||||
func (c *fakeClient) PluginEnable(_ context.Context, name string, enableOptions types.PluginEnableOptions) error {
|
||||
if c.pluginEnableFunc != nil {
|
||||
return c.pluginEnableFunc(name, enableOptions)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) PluginDisable(context context.Context, name string, disableOptions types.PluginDisableOptions) error {
|
||||
func (c *fakeClient) PluginDisable(_ context.Context, name string, disableOptions types.PluginDisableOptions) error {
|
||||
if c.pluginDisableFunc != nil {
|
||||
return c.pluginDisableFunc(name, disableOptions)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) PluginRemove(context context.Context, name string, removeOptions types.PluginRemoveOptions) error {
|
||||
func (c *fakeClient) PluginRemove(_ context.Context, name string, removeOptions types.PluginRemoveOptions) error {
|
||||
if c.pluginRemoveFunc != nil {
|
||||
return c.pluginRemoveFunc(name, removeOptions)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) PluginInstall(context context.Context, name string, installOptions types.PluginInstallOptions) (io.ReadCloser, error) {
|
||||
func (c *fakeClient) PluginInstall(_ context.Context, name string, installOptions types.PluginInstallOptions) (io.ReadCloser, error) {
|
||||
if c.pluginInstallFunc != nil {
|
||||
return c.pluginInstallFunc(name, installOptions)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) PluginList(context context.Context, filter filters.Args) (types.PluginsListResponse, error) {
|
||||
func (c *fakeClient) PluginList(_ context.Context, filter filters.Args) (types.PluginsListResponse, error) {
|
||||
if c.pluginListFunc != nil {
|
||||
return c.pluginListFunc(filter)
|
||||
}
|
||||
@ -63,7 +63,7 @@ func (c *fakeClient) PluginList(context context.Context, filter filters.Args) (t
|
||||
return types.PluginsListResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) {
|
||||
func (c *fakeClient) PluginInspectWithRaw(_ context.Context, name string) (*types.Plugin, []byte, error) {
|
||||
if c.pluginInspectFunc != nil {
|
||||
return c.pluginInspectFunc(name)
|
||||
}
|
||||
@ -71,6 +71,6 @@ func (c *fakeClient) PluginInspectWithRaw(ctx context.Context, name string) (*ty
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) Info(ctx context.Context) (types.Info, error) {
|
||||
func (c *fakeClient) Info(context.Context) (types.Info, error) {
|
||||
return types.Info{}, nil
|
||||
}
|
||||
|
||||
@ -54,26 +54,6 @@ func newInstallCommand(dockerCli command.Cli) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
type pluginRegistryService struct {
|
||||
registry.Service
|
||||
}
|
||||
|
||||
func (s pluginRegistryService) ResolveRepository(name reference.Named) (*registry.RepositoryInfo, error) {
|
||||
repoInfo, err := s.Service.ResolveRepository(name)
|
||||
if repoInfo != nil {
|
||||
repoInfo.Class = "plugin"
|
||||
}
|
||||
return repoInfo, err
|
||||
}
|
||||
|
||||
func newRegistryService() (registry.Service, error) {
|
||||
svc, err := registry.NewService(registry.ServiceOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pluginRegistryService{Service: svc}, nil
|
||||
}
|
||||
|
||||
func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOptions, cmdName string) (types.PluginInstallOptions, error) {
|
||||
// Names with both tag and digest will be treated by the daemon
|
||||
// as a pull by digest with a local name for the tag
|
||||
@ -98,12 +78,7 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
|
||||
return types.PluginInstallOptions{}, errors.Errorf("invalid name: %s", ref.String())
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
svc, err := newRegistryService()
|
||||
if err != nil {
|
||||
return types.PluginInstallOptions{}, err
|
||||
}
|
||||
trusted, err := image.TrustedReference(ctx, dockerCli, nt, svc)
|
||||
trusted, err := image.TrustedReference(context.Background(), dockerCli, nt)
|
||||
if err != nil {
|
||||
return types.PluginInstallOptions{}, err
|
||||
}
|
||||
|
||||
@ -68,7 +68,6 @@ func runPush(dockerCli command.Cli, opts pushOptions) error {
|
||||
defer responseBody.Close()
|
||||
|
||||
if !opts.untrusted {
|
||||
repoInfo.Class = "plugin"
|
||||
return image.PushTrustedReference(dockerCli, repoInfo, named, authConfig, responseBody)
|
||||
}
|
||||
|
||||
|
||||
@ -21,14 +21,8 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ElectAuthServer returns the default registry to use
|
||||
// Deprecated: use registry.IndexServer instead
|
||||
func ElectAuthServer(_ context.Context, _ Cli) string {
|
||||
return registry.IndexServer
|
||||
}
|
||||
|
||||
// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload
|
||||
func EncodeAuthToBase64(authConfig types.AuthConfig) (string, error) {
|
||||
func EncodeAuthToBase64(authConfig registrytypes.AuthConfig) (string, error) {
|
||||
buf, err := json.Marshal(authConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -58,19 +52,19 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
|
||||
// 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.
|
||||
func ResolveAuthConfig(_ context.Context, cli Cli, index *registrytypes.IndexInfo) types.AuthConfig {
|
||||
func ResolveAuthConfig(_ context.Context, cli Cli, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
|
||||
configKey := index.Name
|
||||
if index.Official {
|
||||
configKey = registry.IndexServer
|
||||
}
|
||||
|
||||
a, _ := cli.ConfigFile().GetAuthConfig(configKey)
|
||||
return types.AuthConfig(a)
|
||||
return registrytypes.AuthConfig(a)
|
||||
}
|
||||
|
||||
// GetDefaultAuthConfig gets the default auth config given a serverAddress
|
||||
// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it
|
||||
func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (types.AuthConfig, error) {
|
||||
func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) {
|
||||
if !isDefaultRegistry {
|
||||
serverAddress = registry.ConvertToHostname(serverAddress)
|
||||
}
|
||||
@ -79,19 +73,19 @@ func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, is
|
||||
if checkCredStore {
|
||||
authconfig, err = cli.ConfigFile().GetAuthConfig(serverAddress)
|
||||
if err != nil {
|
||||
return types.AuthConfig{
|
||||
return registrytypes.AuthConfig{
|
||||
ServerAddress: serverAddress,
|
||||
}, err
|
||||
}
|
||||
}
|
||||
authconfig.ServerAddress = serverAddress
|
||||
authconfig.IdentityToken = ""
|
||||
res := types.AuthConfig(authconfig)
|
||||
res := registrytypes.AuthConfig(authconfig)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// ConfigureAuth handles prompting of user's username and password if needed
|
||||
func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *types.AuthConfig, isDefaultRegistry bool) error {
|
||||
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
|
||||
if runtime.GOOS == "windows" {
|
||||
cli.SetIn(streams.NewIn(os.Stdin))
|
||||
@ -181,14 +175,14 @@ func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (str
|
||||
}
|
||||
|
||||
// resolveAuthConfigFromImage retrieves that AuthConfig using the image string
|
||||
func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (types.AuthConfig, error) {
|
||||
func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (registrytypes.AuthConfig, error) {
|
||||
registryRef, err := reference.ParseNormalizedNamed(image)
|
||||
if err != nil {
|
||||
return types.AuthConfig{}, err
|
||||
return registrytypes.AuthConfig{}, err
|
||||
}
|
||||
repoInfo, err := registry.ParseRepositoryInfo(registryRef)
|
||||
if err != nil {
|
||||
return types.AuthConfig{}, err
|
||||
return registrytypes.AuthConfig{}, err
|
||||
}
|
||||
return ResolveAuthConfig(ctx, cli, repoInfo.Index), nil
|
||||
}
|
||||
|
||||
@ -10,7 +10,6 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
configtypes "github.com/docker/cli/cli/config/types"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/errdefs"
|
||||
@ -164,7 +163,7 @@ func runLogin(dockerCli command.Cli, opts loginOptions) error { //nolint:gocyclo
|
||||
return nil
|
||||
}
|
||||
|
||||
func loginWithCredStoreCreds(ctx context.Context, dockerCli command.Cli, authConfig *types.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
func loginWithCredStoreCreds(ctx context.Context, dockerCli command.Cli, authConfig *registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
fmt.Fprintf(dockerCli.Out(), "Authenticating with existing credentials...\n")
|
||||
cliClient := dockerCli.Client()
|
||||
response, err := cliClient.RegistryLogin(ctx, *authConfig)
|
||||
@ -178,7 +177,7 @@ func loginWithCredStoreCreds(ctx context.Context, dockerCli command.Cli, authCon
|
||||
return response, err
|
||||
}
|
||||
|
||||
func loginClientSide(ctx context.Context, auth types.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
func loginClientSide(ctx context.Context, auth registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
svc, err := registry.NewService(registry.ServiceOptions{})
|
||||
if err != nil {
|
||||
return registrytypes.AuthenticateOKBody{}, err
|
||||
|
||||
@ -34,11 +34,11 @@ type fakeClient struct {
|
||||
client.Client
|
||||
}
|
||||
|
||||
func (c fakeClient) Info(ctx context.Context) (types.Info, error) {
|
||||
func (c fakeClient) Info(context.Context) (types.Info, error) {
|
||||
return types.Info{}, nil
|
||||
}
|
||||
|
||||
func (c fakeClient) RegistryLogin(ctx context.Context, auth types.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
func (c fakeClient) RegistryLogin(_ context.Context, auth registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
|
||||
if auth.Password == expiredPassword {
|
||||
return registrytypes.AuthenticateOKBody{}, fmt.Errorf("Invalid Username or Password")
|
||||
}
|
||||
@ -53,16 +53,16 @@ func (c fakeClient) RegistryLogin(ctx context.Context, auth types.AuthConfig) (r
|
||||
|
||||
func TestLoginWithCredStoreCreds(t *testing.T) {
|
||||
testCases := []struct {
|
||||
inputAuthConfig types.AuthConfig
|
||||
inputAuthConfig registrytypes.AuthConfig
|
||||
expectedMsg string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
inputAuthConfig: types.AuthConfig{},
|
||||
inputAuthConfig: registrytypes.AuthConfig{},
|
||||
expectedMsg: "Authenticating with existing credentials...\n",
|
||||
},
|
||||
{
|
||||
inputAuthConfig: types.AuthConfig{
|
||||
inputAuthConfig: registrytypes.AuthConfig{
|
||||
Username: userErr,
|
||||
},
|
||||
expectedMsg: "Authenticating with existing credentials...\n",
|
||||
|
||||
@ -6,16 +6,14 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
|
||||
// Prevents a circular import with "github.com/docker/cli/internal/test"
|
||||
|
||||
. "github.com/docker/cli/cli/command"
|
||||
. "github.com/docker/cli/cli/command" // Prevents a circular import with "github.com/docker/cli/internal/test"
|
||||
configtypes "github.com/docker/cli/cli/config/types"
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/client"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
type fakeClient struct {
|
||||
@ -23,7 +21,7 @@ type fakeClient struct {
|
||||
infoFunc func() (types.Info, error)
|
||||
}
|
||||
|
||||
var testAuthConfigs = []types.AuthConfig{
|
||||
var testAuthConfigs = []registry.AuthConfig{
|
||||
{
|
||||
ServerAddress: "https://index.docker.io/v1/",
|
||||
Username: "u0",
|
||||
@ -48,13 +46,13 @@ func TestGetDefaultAuthConfig(t *testing.T) {
|
||||
checkCredStore bool
|
||||
inputServerAddress string
|
||||
expectedErr string
|
||||
expectedAuthConfig types.AuthConfig
|
||||
expectedAuthConfig registry.AuthConfig
|
||||
}{
|
||||
{
|
||||
checkCredStore: false,
|
||||
inputServerAddress: "",
|
||||
expectedErr: "",
|
||||
expectedAuthConfig: types.AuthConfig{
|
||||
expectedAuthConfig: registry.AuthConfig{
|
||||
ServerAddress: "",
|
||||
Username: "",
|
||||
Password: "",
|
||||
@ -104,7 +102,7 @@ func TestGetDefaultAuthConfig_HelperError(t *testing.T) {
|
||||
cli.SetErr(errBuf)
|
||||
cli.ConfigFile().CredentialsStore = "fake-does-not-exist"
|
||||
serverAddress := "test-server-address"
|
||||
expectedAuthConfig := types.AuthConfig{
|
||||
expectedAuthConfig := registry.AuthConfig{
|
||||
ServerAddress: serverAddress,
|
||||
}
|
||||
authconfig, err := GetDefaultAuthConfig(cli, true, serverAddress, serverAddress == "https://index.docker.io/v1/")
|
||||
|
||||
@ -10,36 +10,36 @@ import (
|
||||
|
||||
type fakeClient struct {
|
||||
client.Client
|
||||
secretCreateFunc func(swarm.SecretSpec) (types.SecretCreateResponse, error)
|
||||
secretInspectFunc func(string) (swarm.Secret, []byte, error)
|
||||
secretListFunc func(types.SecretListOptions) ([]swarm.Secret, error)
|
||||
secretRemoveFunc func(string) error
|
||||
secretCreateFunc func(context.Context, swarm.SecretSpec) (types.SecretCreateResponse, error)
|
||||
secretInspectFunc func(context.Context, string) (swarm.Secret, []byte, error)
|
||||
secretListFunc func(context.Context, types.SecretListOptions) ([]swarm.Secret, error)
|
||||
secretRemoveFunc func(context.Context, string) error
|
||||
}
|
||||
|
||||
func (c *fakeClient) SecretCreate(ctx context.Context, spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
if c.secretCreateFunc != nil {
|
||||
return c.secretCreateFunc(spec)
|
||||
return c.secretCreateFunc(ctx, spec)
|
||||
}
|
||||
return types.SecretCreateResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) SecretInspectWithRaw(ctx context.Context, id string) (swarm.Secret, []byte, error) {
|
||||
if c.secretInspectFunc != nil {
|
||||
return c.secretInspectFunc(id)
|
||||
return c.secretInspectFunc(ctx, id)
|
||||
}
|
||||
return swarm.Secret{}, nil, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
if c.secretListFunc != nil {
|
||||
return c.secretListFunc(options)
|
||||
return c.secretListFunc(ctx, options)
|
||||
}
|
||||
return []swarm.Secret{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) SecretRemove(ctx context.Context, name string) error {
|
||||
if c.secretRemoveFunc != nil {
|
||||
return c.secretRemoveFunc(name)
|
||||
return c.secretRemoveFunc(ctx, name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package secret
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -21,7 +22,7 @@ const secretDataFile = "secret-create-with-name.golden"
|
||||
func TestSecretCreateErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
secretCreateFunc func(swarm.SecretSpec) (types.SecretCreateResponse, error)
|
||||
secretCreateFunc func(context.Context, swarm.SecretSpec) (types.SecretCreateResponse, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
@ -34,7 +35,7 @@ func TestSecretCreateErrors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
args: []string{"name", filepath.Join("testdata", secretDataFile)},
|
||||
secretCreateFunc: func(secretSpec swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
secretCreateFunc: func(_ context.Context, secretSpec swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
return types.SecretCreateResponse{}, errors.Errorf("error creating secret")
|
||||
},
|
||||
expectedError: "error creating secret",
|
||||
@ -66,7 +67,7 @@ func TestSecretCreateWithName(t *testing.T) {
|
||||
}
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
secretCreateFunc: func(_ context.Context, spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
if !reflect.DeepEqual(spec, expected) {
|
||||
return types.SecretCreateResponse{}, errors.Errorf("expected %+v, got %+v", expected, spec)
|
||||
}
|
||||
@ -89,7 +90,7 @@ func TestSecretCreateWithDriver(t *testing.T) {
|
||||
name := "foo"
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
secretCreateFunc: func(_ context.Context, spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
if spec.Name != name {
|
||||
return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
|
||||
}
|
||||
@ -118,7 +119,7 @@ func TestSecretCreateWithTemplatingDriver(t *testing.T) {
|
||||
name := "foo"
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
secretCreateFunc: func(_ context.Context, spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
if spec.Name != name {
|
||||
return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
|
||||
}
|
||||
@ -148,7 +149,7 @@ func TestSecretCreateWithLabels(t *testing.T) {
|
||||
name := "foo"
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
secretCreateFunc: func(_ context.Context, spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
if spec.Name != name {
|
||||
return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package secret
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
@ -18,7 +19,7 @@ func TestSecretInspectErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
flags map[string]string
|
||||
secretInspectFunc func(secretID string) (swarm.Secret, []byte, error)
|
||||
secretInspectFunc func(ctx context.Context, secretID string) (swarm.Secret, []byte, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
@ -26,7 +27,7 @@ func TestSecretInspectErrors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
args: []string{"foo"},
|
||||
secretInspectFunc: func(secretID string) (swarm.Secret, []byte, error) {
|
||||
secretInspectFunc: func(_ context.Context, secretID string) (swarm.Secret, []byte, error) {
|
||||
return swarm.Secret{}, nil, errors.Errorf("error while inspecting the secret")
|
||||
},
|
||||
expectedError: "error while inspecting the secret",
|
||||
@ -40,7 +41,7 @@ func TestSecretInspectErrors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
args: []string{"foo", "bar"},
|
||||
secretInspectFunc: func(secretID string) (swarm.Secret, []byte, error) {
|
||||
secretInspectFunc: func(_ context.Context, secretID string) (swarm.Secret, []byte, error) {
|
||||
if secretID == "foo" {
|
||||
return *Secret(SecretName("foo")), nil, nil
|
||||
}
|
||||
@ -68,12 +69,12 @@ func TestSecretInspectWithoutFormat(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
args []string
|
||||
secretInspectFunc func(secretID string) (swarm.Secret, []byte, error)
|
||||
secretInspectFunc func(ctx context.Context, secretID string) (swarm.Secret, []byte, error)
|
||||
}{
|
||||
{
|
||||
name: "single-secret",
|
||||
args: []string{"foo"},
|
||||
secretInspectFunc: func(name string) (swarm.Secret, []byte, error) {
|
||||
secretInspectFunc: func(_ context.Context, name string) (swarm.Secret, []byte, error) {
|
||||
if name != "foo" {
|
||||
return swarm.Secret{}, nil, errors.Errorf("Invalid name, expected %s, got %s", "foo", name)
|
||||
}
|
||||
@ -83,7 +84,7 @@ func TestSecretInspectWithoutFormat(t *testing.T) {
|
||||
{
|
||||
name: "multiple-secrets-with-labels",
|
||||
args: []string{"foo", "bar"},
|
||||
secretInspectFunc: func(name string) (swarm.Secret, []byte, error) {
|
||||
secretInspectFunc: func(_ context.Context, name string) (swarm.Secret, []byte, error) {
|
||||
return *Secret(SecretID("ID-"+name), SecretName(name), SecretLabels(map[string]string{
|
||||
"label1": "label-foo",
|
||||
})), nil, nil
|
||||
@ -102,7 +103,7 @@ func TestSecretInspectWithoutFormat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSecretInspectWithFormat(t *testing.T) {
|
||||
secretInspectFunc := func(name string) (swarm.Secret, []byte, error) {
|
||||
secretInspectFunc := func(_ context.Context, name string) (swarm.Secret, []byte, error) {
|
||||
return *Secret(SecretName("foo"), SecretLabels(map[string]string{
|
||||
"label1": "label-foo",
|
||||
})), nil, nil
|
||||
@ -111,7 +112,7 @@ func TestSecretInspectWithFormat(t *testing.T) {
|
||||
name string
|
||||
format string
|
||||
args []string
|
||||
secretInspectFunc func(name string) (swarm.Secret, []byte, error)
|
||||
secretInspectFunc func(_ context.Context, name string) (swarm.Secret, []byte, error)
|
||||
}{
|
||||
{
|
||||
name: "simple-template",
|
||||
@ -141,11 +142,11 @@ func TestSecretInspectWithFormat(t *testing.T) {
|
||||
func TestSecretInspectPretty(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
secretInspectFunc func(string) (swarm.Secret, []byte, error)
|
||||
secretInspectFunc func(context.Context, string) (swarm.Secret, []byte, error)
|
||||
}{
|
||||
{
|
||||
name: "simple",
|
||||
secretInspectFunc: func(id string) (swarm.Secret, []byte, error) {
|
||||
secretInspectFunc: func(_ context.Context, id string) (swarm.Secret, []byte, error) {
|
||||
return *Secret(
|
||||
SecretLabels(map[string]string{
|
||||
"lbl1": "value1",
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package secret
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
@ -19,7 +20,7 @@ import (
|
||||
func TestSecretListErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
secretListFunc func(types.SecretListOptions) ([]swarm.Secret, error)
|
||||
secretListFunc func(context.Context, types.SecretListOptions) ([]swarm.Secret, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
@ -27,7 +28,7 @@ func TestSecretListErrors(t *testing.T) {
|
||||
expectedError: "accepts no argument",
|
||||
},
|
||||
{
|
||||
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
return []swarm.Secret{}, errors.Errorf("error listing secrets")
|
||||
},
|
||||
expectedError: "error listing secrets",
|
||||
@ -47,7 +48,7 @@ func TestSecretListErrors(t *testing.T) {
|
||||
|
||||
func TestSecretList(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
return []swarm.Secret{
|
||||
*Secret(SecretID("ID-1-foo"),
|
||||
SecretName("1-foo"),
|
||||
@ -79,7 +80,7 @@ func TestSecretList(t *testing.T) {
|
||||
|
||||
func TestSecretListWithQuietOption(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
return []swarm.Secret{
|
||||
*Secret(SecretID("ID-foo"), SecretName("foo")),
|
||||
*Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{
|
||||
@ -96,7 +97,7 @@ func TestSecretListWithQuietOption(t *testing.T) {
|
||||
|
||||
func TestSecretListWithConfigFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
return []swarm.Secret{
|
||||
*Secret(SecretID("ID-foo"), SecretName("foo")),
|
||||
*Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{
|
||||
@ -115,7 +116,7 @@ func TestSecretListWithConfigFormat(t *testing.T) {
|
||||
|
||||
func TestSecretListWithFormat(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
return []swarm.Secret{
|
||||
*Secret(SecretID("ID-foo"), SecretName("foo")),
|
||||
*Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{
|
||||
@ -132,7 +133,7 @@ func TestSecretListWithFormat(t *testing.T) {
|
||||
|
||||
func TestSecretListWithFilter(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
assert.Check(t, is.Equal("foo", options.Filters.Get("name")[0]), "foo")
|
||||
assert.Check(t, is.Equal("lbl1=Label-bar", options.Filters.Get("label")[0]))
|
||||
return []swarm.Secret{
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package secret
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
@ -14,7 +15,7 @@ import (
|
||||
func TestSecretRemoveErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
secretRemoveFunc func(string) error
|
||||
secretRemoveFunc func(context.Context, string) error
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
@ -23,7 +24,7 @@ func TestSecretRemoveErrors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
args: []string{"foo"},
|
||||
secretRemoveFunc: func(name string) error {
|
||||
secretRemoveFunc: func(_ context.Context, name string) error {
|
||||
return errors.Errorf("error removing secret")
|
||||
},
|
||||
expectedError: "error removing secret",
|
||||
@ -45,7 +46,7 @@ func TestSecretRemoveWithName(t *testing.T) {
|
||||
names := []string{"foo", "bar"}
|
||||
var removedSecrets []string
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretRemoveFunc: func(name string) error {
|
||||
secretRemoveFunc: func(_ context.Context, name string) error {
|
||||
removedSecrets = append(removedSecrets, name)
|
||||
return nil
|
||||
},
|
||||
@ -62,7 +63,7 @@ func TestSecretRemoveContinueAfterError(t *testing.T) {
|
||||
var removedSecrets []string
|
||||
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretRemoveFunc: func(name string) error {
|
||||
secretRemoveFunc: func(_ context.Context, name string) error {
|
||||
removedSecrets = append(removedSecrets, name)
|
||||
if name == "foo" {
|
||||
return errors.Errorf("error removing secret: %s", name)
|
||||
|
||||
@ -414,7 +414,7 @@ type globalProgressUpdater struct {
|
||||
done bool
|
||||
}
|
||||
|
||||
func (u *globalProgressUpdater) update(service swarm.Service, tasks []swarm.Task, activeNodes map[string]struct{}, rollback bool) (bool, error) {
|
||||
func (u *globalProgressUpdater) update(_ swarm.Service, tasks []swarm.Task, activeNodes map[string]struct{}, rollback bool) (bool, error) {
|
||||
tasksByNode := u.tasksByNode(tasks)
|
||||
|
||||
// We don't have perfect knowledge of how many nodes meet the
|
||||
|
||||
@ -504,23 +504,23 @@ type secretAPIClientMock struct {
|
||||
listResult []swarm.Secret
|
||||
}
|
||||
|
||||
func (s secretAPIClientMock) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
func (s secretAPIClientMock) SecretList(context.Context, types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
return s.listResult, nil
|
||||
}
|
||||
|
||||
func (s secretAPIClientMock) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
func (s secretAPIClientMock) SecretCreate(context.Context, swarm.SecretSpec) (types.SecretCreateResponse, error) {
|
||||
return types.SecretCreateResponse{}, nil
|
||||
}
|
||||
|
||||
func (s secretAPIClientMock) SecretRemove(ctx context.Context, id string) error {
|
||||
func (s secretAPIClientMock) SecretRemove(context.Context, string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s secretAPIClientMock) SecretInspectWithRaw(ctx context.Context, name string) (swarm.Secret, []byte, error) {
|
||||
func (s secretAPIClientMock) SecretInspectWithRaw(context.Context, string) (swarm.Secret, []byte, error) {
|
||||
return swarm.Secret{}, []byte{}, nil
|
||||
}
|
||||
|
||||
func (s secretAPIClientMock) SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error {
|
||||
func (s secretAPIClientMock) SecretUpdate(context.Context, string, swarm.Version, swarm.SecretSpec) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ type fakeClient struct {
|
||||
configRemoveFunc func(configID string) error
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServerVersion(ctx context.Context) (types.Version, error) {
|
||||
func (cli *fakeClient) ServerVersion(context.Context) (types.Version, error) {
|
||||
return types.Version{
|
||||
Version: "docker-dev",
|
||||
APIVersion: api.DefaultVersion,
|
||||
@ -54,7 +54,7 @@ func (cli *fakeClient) ClientVersion() string {
|
||||
return cli.version
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
func (cli *fakeClient) ServiceList(_ context.Context, options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
if cli.serviceListFunc != nil {
|
||||
return cli.serviceListFunc(options)
|
||||
}
|
||||
@ -69,7 +69,7 @@ func (cli *fakeClient) ServiceList(ctx context.Context, options types.ServiceLis
|
||||
return servicesList, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
|
||||
func (cli *fakeClient) NetworkList(_ context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
|
||||
if cli.networkListFunc != nil {
|
||||
return cli.networkListFunc(options)
|
||||
}
|
||||
@ -84,7 +84,7 @@ func (cli *fakeClient) NetworkList(ctx context.Context, options types.NetworkLis
|
||||
return networksList, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
func (cli *fakeClient) SecretList(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
if cli.secretListFunc != nil {
|
||||
return cli.secretListFunc(options)
|
||||
}
|
||||
@ -99,7 +99,7 @@ func (cli *fakeClient) SecretList(ctx context.Context, options types.SecretListO
|
||||
return secretsList, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
func (cli *fakeClient) ConfigList(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
if cli.configListFunc != nil {
|
||||
return cli.configListFunc(options)
|
||||
}
|
||||
@ -114,28 +114,28 @@ func (cli *fakeClient) ConfigList(ctx context.Context, options types.ConfigListO
|
||||
return configsList, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
func (cli *fakeClient) TaskList(_ context.Context, options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
if cli.taskListFunc != nil {
|
||||
return cli.taskListFunc(options)
|
||||
}
|
||||
return []swarm.Task{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) {
|
||||
func (cli *fakeClient) NodeList(_ context.Context, options types.NodeListOptions) ([]swarm.Node, error) {
|
||||
if cli.nodeListFunc != nil {
|
||||
return cli.nodeListFunc(options)
|
||||
}
|
||||
return []swarm.Node{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, ref string) (swarm.Node, []byte, error) {
|
||||
func (cli *fakeClient) NodeInspectWithRaw(_ context.Context, ref string) (swarm.Node, []byte, error) {
|
||||
if cli.nodeInspectWithRaw != nil {
|
||||
return cli.nodeInspectWithRaw(ref)
|
||||
}
|
||||
return swarm.Node{}, nil, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
|
||||
func (cli *fakeClient) ServiceUpdate(_ context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
|
||||
if cli.serviceUpdateFunc != nil {
|
||||
return cli.serviceUpdateFunc(serviceID, version, service, options)
|
||||
}
|
||||
@ -143,7 +143,7 @@ func (cli *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, vers
|
||||
return types.ServiceUpdateResponse{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServiceRemove(ctx context.Context, serviceID string) error {
|
||||
func (cli *fakeClient) ServiceRemove(_ context.Context, serviceID string) error {
|
||||
if cli.serviceRemoveFunc != nil {
|
||||
return cli.serviceRemoveFunc(serviceID)
|
||||
}
|
||||
@ -152,7 +152,7 @@ func (cli *fakeClient) ServiceRemove(ctx context.Context, serviceID string) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NetworkRemove(ctx context.Context, networkID string) error {
|
||||
func (cli *fakeClient) NetworkRemove(_ context.Context, networkID string) error {
|
||||
if cli.networkRemoveFunc != nil {
|
||||
return cli.networkRemoveFunc(networkID)
|
||||
}
|
||||
@ -161,7 +161,7 @@ func (cli *fakeClient) NetworkRemove(ctx context.Context, networkID string) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) SecretRemove(ctx context.Context, secretID string) error {
|
||||
func (cli *fakeClient) SecretRemove(_ context.Context, secretID string) error {
|
||||
if cli.secretRemoveFunc != nil {
|
||||
return cli.secretRemoveFunc(secretID)
|
||||
}
|
||||
@ -170,7 +170,7 @@ func (cli *fakeClient) SecretRemove(ctx context.Context, secretID string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ConfigRemove(ctx context.Context, configID string) error {
|
||||
func (cli *fakeClient) ConfigRemove(_ context.Context, configID string) error {
|
||||
if cli.configRemoveFunc != nil {
|
||||
return cli.configRemoveFunc(configID)
|
||||
}
|
||||
@ -179,7 +179,7 @@ func (cli *fakeClient) ConfigRemove(ctx context.Context, configID string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServiceInspectWithRaw(ctx context.Context, serviceID string, opts types.ServiceInspectOptions) (swarm.Service, []byte, error) {
|
||||
func (cli *fakeClient) ServiceInspectWithRaw(_ context.Context, serviceID string, _ types.ServiceInspectOptions) (swarm.Service, []byte, error) {
|
||||
return swarm.Service{
|
||||
ID: serviceID,
|
||||
Spec: swarm.ServiceSpec{
|
||||
|
||||
@ -28,7 +28,7 @@ func newDeployCommand(dockerCli command.Cli) *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return RunDeploy(dockerCli, cmd.Flags(), config, opts)
|
||||
return swarm.RunDeploy(dockerCli, opts, config)
|
||||
},
|
||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
return completeNames(dockerCli)(cmd, args, toComplete)
|
||||
@ -47,7 +47,9 @@ func newDeployCommand(dockerCli command.Cli) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// RunDeploy performs a stack deploy against the specified swarm cluster
|
||||
func RunDeploy(dockerCli command.Cli, flags *pflag.FlagSet, config *composetypes.Config, opts options.Deploy) error {
|
||||
// RunDeploy performs a stack deploy against the specified swarm cluster.
|
||||
//
|
||||
// Deprecated: use [swarm.RunDeploy] instead.
|
||||
func RunDeploy(dockerCli command.Cli, _ *pflag.FlagSet, config *composetypes.Config, opts options.Deploy) error {
|
||||
return swarm.RunDeploy(dockerCli, opts, config)
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ func newListCommand(dockerCli command.Cli) *cobra.Command {
|
||||
Short: "List stacks",
|
||||
Args: cli.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return RunList(cmd, dockerCli, opts)
|
||||
return RunList(dockerCli, opts)
|
||||
},
|
||||
ValidArgsFunction: completion.NoComplete,
|
||||
}
|
||||
@ -34,24 +34,24 @@ func newListCommand(dockerCli command.Cli) *cobra.Command {
|
||||
}
|
||||
|
||||
// RunList performs a stack list against the specified swarm cluster
|
||||
func RunList(cmd *cobra.Command, dockerCli command.Cli, opts options.List) error {
|
||||
stacks := []*formatter.Stack{}
|
||||
func RunList(dockerCli command.Cli, opts options.List) error {
|
||||
ss, err := swarm.GetStacks(dockerCli)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stacks := make([]*formatter.Stack, 0, len(ss))
|
||||
stacks = append(stacks, ss...)
|
||||
return format(dockerCli, opts, stacks)
|
||||
}
|
||||
|
||||
func format(dockerCli command.Cli, opts options.List, stacks []*formatter.Stack) error {
|
||||
format := formatter.Format(opts.Format)
|
||||
if format == "" || format == formatter.TableFormatKey {
|
||||
format = formatter.SwarmStackTableFormat
|
||||
fmt := formatter.Format(opts.Format)
|
||||
if fmt == "" || fmt == formatter.TableFormatKey {
|
||||
fmt = formatter.SwarmStackTableFormat
|
||||
}
|
||||
stackCtx := formatter.Context{
|
||||
Output: dockerCli.Out(),
|
||||
Format: format,
|
||||
Format: fmt,
|
||||
}
|
||||
sort.Slice(stacks, func(i, j int) bool {
|
||||
return sortorder.NaturalLess(stacks[i].Name, stacks[j].Name) ||
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@ -104,9 +105,22 @@ func GetConfigDetails(composefiles []string, stdin io.Reader) (composetypes.Conf
|
||||
func buildEnvironment(env []string) (map[string]string, error) {
|
||||
result := make(map[string]string, len(env))
|
||||
for _, s := range env {
|
||||
if runtime.GOOS == "windows" && len(s) > 0 {
|
||||
// cmd.exe can have special environment variables which names start with "=".
|
||||
// They are only there for MS-DOS compatibility and we should ignore them.
|
||||
// See TestBuildEnvironment for examples.
|
||||
//
|
||||
// https://ss64.com/nt/syntax-variables.html
|
||||
// https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133
|
||||
// https://github.com/docker/cli/issues/4078
|
||||
if s[0] == '=' {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
k, v, ok := strings.Cut(s, "=")
|
||||
if !ok || k == "" {
|
||||
return result, errors.Errorf("unexpected environment %q", s)
|
||||
return result, errors.Errorf("unexpected environment variable '%s'", s)
|
||||
}
|
||||
// value may be set, but empty if "s" is like "K=", not "K".
|
||||
result[k] = v
|
||||
|
||||
@ -3,6 +3,7 @@ package loader
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@ -45,3 +46,34 @@ services:
|
||||
assert.Check(t, is.Equal("3.0", details.ConfigFiles[0].Config["version"]))
|
||||
assert.Check(t, is.Len(details.Environment, len(os.Environ())))
|
||||
}
|
||||
|
||||
func TestBuildEnvironment(t *testing.T) {
|
||||
inputEnv := []string{
|
||||
"LEGIT_VAR=LEGIT_VALUE",
|
||||
"EMPTY_VARIABLE=",
|
||||
}
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
inputEnv = []string{
|
||||
"LEGIT_VAR=LEGIT_VALUE",
|
||||
|
||||
// cmd.exe has some special environment variables which start with "=".
|
||||
// These should be ignored as they're only there for MS-DOS compatibility.
|
||||
"=ExitCode=00000041",
|
||||
"=ExitCodeAscii=A",
|
||||
`=C:=C:\some\dir`,
|
||||
`=D:=D:\some\different\dir`,
|
||||
`=X:=X:\`,
|
||||
`=::=::\`,
|
||||
|
||||
"EMPTY_VARIABLE=",
|
||||
}
|
||||
}
|
||||
|
||||
env, err := buildEnvironment(inputEnv)
|
||||
assert.NilError(t, err)
|
||||
|
||||
assert.Check(t, is.Len(env, 2))
|
||||
assert.Check(t, is.Equal("LEGIT_VALUE", env["LEGIT_VAR"]))
|
||||
assert.Check(t, is.Equal("", env["EMPTY_VARIABLE"]))
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ func newPsCommand(dockerCli command.Cli) *cobra.Command {
|
||||
if err := validateStackName(opts.Namespace); err != nil {
|
||||
return err
|
||||
}
|
||||
return RunPs(dockerCli, cmd.Flags(), opts)
|
||||
return swarm.RunPS(dockerCli, opts)
|
||||
},
|
||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
return completeNames(dockerCli)(cmd, args, toComplete)
|
||||
@ -38,7 +38,9 @@ func newPsCommand(dockerCli command.Cli) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// RunPs performs a stack ps against the specified swarm cluster
|
||||
func RunPs(dockerCli command.Cli, flags *pflag.FlagSet, opts options.PS) error {
|
||||
// RunPs performs a stack ps against the specified swarm cluster.
|
||||
//
|
||||
// Deprecated: use [swarm.RunPS] instead.
|
||||
func RunPs(dockerCli command.Cli, _ *pflag.FlagSet, opts options.PS) error {
|
||||
return swarm.RunPS(dockerCli, opts)
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ func newRemoveCommand(dockerCli command.Cli) *cobra.Command {
|
||||
if err := validateStackNames(opts.Namespaces); err != nil {
|
||||
return err
|
||||
}
|
||||
return RunRemove(dockerCli, cmd.Flags(), opts)
|
||||
return swarm.RunRemove(dockerCli, opts)
|
||||
},
|
||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
return completeNames(dockerCli)(cmd, args, toComplete)
|
||||
@ -31,7 +31,9 @@ func newRemoveCommand(dockerCli command.Cli) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// RunRemove performs a stack remove against the specified swarm cluster
|
||||
func RunRemove(dockerCli command.Cli, flags *pflag.FlagSet, opts options.Remove) error {
|
||||
// RunRemove performs a stack remove against the specified swarm cluster.
|
||||
//
|
||||
// Deprecated: use [swarm.RunRemove] instead.
|
||||
func RunRemove(dockerCli command.Cli, _ *pflag.FlagSet, opts options.Remove) error {
|
||||
return swarm.RunRemove(dockerCli, opts)
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ func newServicesCommand(dockerCli command.Cli) *cobra.Command {
|
||||
if err := validateStackName(opts.Namespace); err != nil {
|
||||
return err
|
||||
}
|
||||
return RunServices(dockerCli, cmd.Flags(), opts)
|
||||
return RunServices(dockerCli, opts)
|
||||
},
|
||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
return completeNames(dockerCli)(cmd, args, toComplete)
|
||||
@ -44,16 +44,18 @@ func newServicesCommand(dockerCli command.Cli) *cobra.Command {
|
||||
}
|
||||
|
||||
// RunServices performs a stack services against the specified swarm cluster
|
||||
func RunServices(dockerCli command.Cli, flags *pflag.FlagSet, opts options.Services) error {
|
||||
services, err := GetServices(dockerCli, flags, opts)
|
||||
func RunServices(dockerCli command.Cli, opts options.Services) error {
|
||||
services, err := swarm.GetServices(dockerCli, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return formatWrite(dockerCli, services, opts)
|
||||
}
|
||||
|
||||
// GetServices returns the services for the specified swarm cluster
|
||||
func GetServices(dockerCli command.Cli, flags *pflag.FlagSet, opts options.Services) ([]swarmtypes.Service, error) {
|
||||
// GetServices returns the services for the specified swarm cluster.
|
||||
//
|
||||
// Deprecated: use [swarm.GetServices] instead.
|
||||
func GetServices(dockerCli command.Cli, _ *pflag.FlagSet, opts options.Services) ([]swarmtypes.Service, error) {
|
||||
return swarm.GetServices(dockerCli, opts)
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ type fakeClient struct {
|
||||
configRemoveFunc func(configID string) error
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServerVersion(ctx context.Context) (types.Version, error) {
|
||||
func (cli *fakeClient) ServerVersion(context.Context) (types.Version, error) {
|
||||
return types.Version{
|
||||
Version: "docker-dev",
|
||||
APIVersion: api.DefaultVersion,
|
||||
@ -54,7 +54,7 @@ func (cli *fakeClient) ClientVersion() string {
|
||||
return cli.version
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
func (cli *fakeClient) ServiceList(_ context.Context, options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
if cli.serviceListFunc != nil {
|
||||
return cli.serviceListFunc(options)
|
||||
}
|
||||
@ -69,7 +69,7 @@ func (cli *fakeClient) ServiceList(ctx context.Context, options types.ServiceLis
|
||||
return servicesList, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
|
||||
func (cli *fakeClient) NetworkList(_ context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
|
||||
if cli.networkListFunc != nil {
|
||||
return cli.networkListFunc(options)
|
||||
}
|
||||
@ -84,7 +84,7 @@ func (cli *fakeClient) NetworkList(ctx context.Context, options types.NetworkLis
|
||||
return networksList, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
func (cli *fakeClient) SecretList(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
if cli.secretListFunc != nil {
|
||||
return cli.secretListFunc(options)
|
||||
}
|
||||
@ -99,7 +99,7 @@ func (cli *fakeClient) SecretList(ctx context.Context, options types.SecretListO
|
||||
return secretsList, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
func (cli *fakeClient) ConfigList(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
if cli.configListFunc != nil {
|
||||
return cli.configListFunc(options)
|
||||
}
|
||||
@ -114,28 +114,28 @@ func (cli *fakeClient) ConfigList(ctx context.Context, options types.ConfigListO
|
||||
return configsList, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
func (cli *fakeClient) TaskList(_ context.Context, options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
if cli.taskListFunc != nil {
|
||||
return cli.taskListFunc(options)
|
||||
}
|
||||
return []swarm.Task{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) {
|
||||
func (cli *fakeClient) NodeList(_ context.Context, options types.NodeListOptions) ([]swarm.Node, error) {
|
||||
if cli.nodeListFunc != nil {
|
||||
return cli.nodeListFunc(options)
|
||||
}
|
||||
return []swarm.Node{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, ref string) (swarm.Node, []byte, error) {
|
||||
func (cli *fakeClient) NodeInspectWithRaw(_ context.Context, ref string) (swarm.Node, []byte, error) {
|
||||
if cli.nodeInspectWithRaw != nil {
|
||||
return cli.nodeInspectWithRaw(ref)
|
||||
}
|
||||
return swarm.Node{}, nil, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
|
||||
func (cli *fakeClient) ServiceUpdate(_ context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
|
||||
if cli.serviceUpdateFunc != nil {
|
||||
return cli.serviceUpdateFunc(serviceID, version, service, options)
|
||||
}
|
||||
@ -143,7 +143,7 @@ func (cli *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, vers
|
||||
return types.ServiceUpdateResponse{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServiceRemove(ctx context.Context, serviceID string) error {
|
||||
func (cli *fakeClient) ServiceRemove(_ context.Context, serviceID string) error {
|
||||
if cli.serviceRemoveFunc != nil {
|
||||
return cli.serviceRemoveFunc(serviceID)
|
||||
}
|
||||
@ -152,7 +152,7 @@ func (cli *fakeClient) ServiceRemove(ctx context.Context, serviceID string) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NetworkRemove(ctx context.Context, networkID string) error {
|
||||
func (cli *fakeClient) NetworkRemove(_ context.Context, networkID string) error {
|
||||
if cli.networkRemoveFunc != nil {
|
||||
return cli.networkRemoveFunc(networkID)
|
||||
}
|
||||
@ -161,7 +161,7 @@ func (cli *fakeClient) NetworkRemove(ctx context.Context, networkID string) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) SecretRemove(ctx context.Context, secretID string) error {
|
||||
func (cli *fakeClient) SecretRemove(_ context.Context, secretID string) error {
|
||||
if cli.secretRemoveFunc != nil {
|
||||
return cli.secretRemoveFunc(secretID)
|
||||
}
|
||||
@ -170,7 +170,7 @@ func (cli *fakeClient) SecretRemove(ctx context.Context, secretID string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ConfigRemove(ctx context.Context, configID string) error {
|
||||
func (cli *fakeClient) ConfigRemove(_ context.Context, configID string) error {
|
||||
if cli.configRemoveFunc != nil {
|
||||
return cli.configRemoveFunc(configID)
|
||||
}
|
||||
|
||||
@ -21,63 +21,63 @@ type fakeClient struct {
|
||||
swarmUnlockFunc func(req swarm.UnlockRequest) error
|
||||
}
|
||||
|
||||
func (cli *fakeClient) Info(ctx context.Context) (types.Info, error) {
|
||||
func (cli *fakeClient) Info(context.Context) (types.Info, error) {
|
||||
if cli.infoFunc != nil {
|
||||
return cli.infoFunc()
|
||||
}
|
||||
return types.Info{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, ref string) (swarm.Node, []byte, error) {
|
||||
func (cli *fakeClient) NodeInspectWithRaw(context.Context, string) (swarm.Node, []byte, error) {
|
||||
if cli.nodeInspectFunc != nil {
|
||||
return cli.nodeInspectFunc()
|
||||
}
|
||||
return swarm.Node{}, []byte{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) {
|
||||
func (cli *fakeClient) SwarmInit(context.Context, swarm.InitRequest) (string, error) {
|
||||
if cli.swarmInitFunc != nil {
|
||||
return cli.swarmInitFunc()
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) SwarmInspect(ctx context.Context) (swarm.Swarm, error) {
|
||||
func (cli *fakeClient) SwarmInspect(context.Context) (swarm.Swarm, error) {
|
||||
if cli.swarmInspectFunc != nil {
|
||||
return cli.swarmInspectFunc()
|
||||
}
|
||||
return swarm.Swarm{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) SwarmGetUnlockKey(ctx context.Context) (types.SwarmUnlockKeyResponse, error) {
|
||||
func (cli *fakeClient) SwarmGetUnlockKey(context.Context) (types.SwarmUnlockKeyResponse, error) {
|
||||
if cli.swarmGetUnlockKeyFunc != nil {
|
||||
return cli.swarmGetUnlockKeyFunc()
|
||||
}
|
||||
return types.SwarmUnlockKeyResponse{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) SwarmJoin(ctx context.Context, req swarm.JoinRequest) error {
|
||||
func (cli *fakeClient) SwarmJoin(context.Context, swarm.JoinRequest) error {
|
||||
if cli.swarmJoinFunc != nil {
|
||||
return cli.swarmJoinFunc()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) SwarmLeave(ctx context.Context, force bool) error {
|
||||
func (cli *fakeClient) SwarmLeave(context.Context, bool) error {
|
||||
if cli.swarmLeaveFunc != nil {
|
||||
return cli.swarmLeaveFunc()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error {
|
||||
func (cli *fakeClient) SwarmUpdate(_ context.Context, _ swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error {
|
||||
if cli.swarmUpdateFunc != nil {
|
||||
return cli.swarmUpdateFunc(swarm, flags)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) SwarmUnlock(ctx context.Context, req swarm.UnlockRequest) error {
|
||||
func (cli *fakeClient) SwarmUnlock(_ context.Context, req swarm.UnlockRequest) error {
|
||||
if cli.swarmUnlockFunc != nil {
|
||||
return cli.swarmUnlockFunc(req)
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
// Helper function to set static slices
|
||||
func getCIDR(ip net.IP, cidr *net.IPNet, err error) net.IPNet {
|
||||
func getCIDR(_ net.IP, cidr *net.IPNet, _ error) net.IPNet {
|
||||
return *cidr
|
||||
}
|
||||
|
||||
|
||||
@ -14,14 +14,14 @@ type fakeClient struct {
|
||||
serviceInspectWithRaw func(ref string, options types.ServiceInspectOptions) (swarm.Service, []byte, error)
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, ref string) (swarm.Node, []byte, error) {
|
||||
func (cli *fakeClient) NodeInspectWithRaw(_ context.Context, ref string) (swarm.Node, []byte, error) {
|
||||
if cli.nodeInspectWithRaw != nil {
|
||||
return cli.nodeInspectWithRaw(ref)
|
||||
}
|
||||
return swarm.Node{}, nil, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServiceInspectWithRaw(ctx context.Context, ref string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) {
|
||||
func (cli *fakeClient) ServiceInspectWithRaw(_ context.Context, ref string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) {
|
||||
if cli.serviceInspectWithRaw != nil {
|
||||
return cli.serviceInspectWithRaw(ref, options)
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ type trustKey struct {
|
||||
// This information is to be pretty printed or serialized into a machine-readable format.
|
||||
func lookupTrustInfo(cli command.Cli, remote string) ([]trustTagRow, []client.RoleWithSignatures, []data.Role, error) {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), remote)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), remote)
|
||||
if err != nil {
|
||||
return []trustTagRow{}, []client.RoleWithSignatures{}, []data.Role{}, err
|
||||
}
|
||||
|
||||
@ -27,15 +27,15 @@ type fakeClient struct {
|
||||
apiclient.Client
|
||||
}
|
||||
|
||||
func (c *fakeClient) Info(ctx context.Context) (types.Info, error) {
|
||||
func (c *fakeClient) Info(context.Context) (types.Info, error) {
|
||||
return types.Info{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) {
|
||||
func (c *fakeClient) ImageInspectWithRaw(context.Context, string) (types.ImageInspect, []byte, error) {
|
||||
return types.ImageInspect{}, []byte{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) ImagePush(ctx context.Context, image string, options types.ImagePushOptions) (io.ReadCloser, error) {
|
||||
func (c *fakeClient) ImagePush(context.Context, string, types.ImagePushOptions) (io.ReadCloser, error) {
|
||||
return &utils.NoopCloser{Reader: bytes.NewBuffer([]byte{})}, nil
|
||||
}
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ func newRevokeCommand(dockerCli command.Cli) *cobra.Command {
|
||||
|
||||
func revokeTrust(cli command.Cli, remote string, options revokeOptions) error {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), remote)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), remote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ func newSignCommand(dockerCli command.Cli) *cobra.Command {
|
||||
func runSignImage(cli command.Cli, options signOptions) error {
|
||||
imageName := options.imageName
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), imageName)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), imageName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ func addSigner(cli command.Cli, options signerAddOptions) error {
|
||||
|
||||
func addSignerToRepo(cli command.Cli, signerName string, repoName string, signerPubKeys []data.PublicKey) error {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), repoName)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), repoName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ func isLastSignerForReleases(roleWithSig data.Role, allRoles []client.RoleWithSi
|
||||
// The signer not being removed doesn't necessarily raise an error e.g. user choosing "No" when prompted for confirmation.
|
||||
func removeSingleSigner(cli command.Cli, repoName, signerName string, forceYes bool) (bool, error) {
|
||||
ctx := context.Background()
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, image.AuthResolver(cli), repoName)
|
||||
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), repoName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@ -32,9 +32,9 @@ func (c *fakeClient) VolumeInspect(_ context.Context, volumeID string) (volume.V
|
||||
return volume.Volume{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) VolumeList(_ context.Context, filter filters.Args) (volume.ListResponse, error) {
|
||||
func (c *fakeClient) VolumeList(_ context.Context, options volume.ListOptions) (volume.ListResponse, error) {
|
||||
if c.volumeListFunc != nil {
|
||||
return c.volumeListFunc(filter)
|
||||
return c.volumeListFunc(options.Filters)
|
||||
}
|
||||
return volume.ListResponse{}, nil
|
||||
}
|
||||
|
||||
@ -50,6 +50,7 @@ func TestVolumeCreateErrors(t *testing.T) {
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,6 +62,7 @@ func TestVolumeInspectErrors(t *testing.T) {
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"github.com/docker/cli/cli/command/formatter"
|
||||
flagsHelper "github.com/docker/cli/cli/flags"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/fvbommel/sortorder"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -52,7 +53,7 @@ func newListCommand(dockerCli command.Cli) *cobra.Command {
|
||||
|
||||
func runList(dockerCli command.Cli, options listOptions) error {
|
||||
client := dockerCli.Client()
|
||||
volumes, err := client.VolumeList(context.Background(), options.filter.Value())
|
||||
volumes, err := client.VolumeList(context.Background(), volume.ListOptions{Filters: options.filter.Value()})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -70,9 +71,9 @@ func runList(dockerCli command.Cli, options listOptions) error {
|
||||
|
||||
// trick for filtering in place
|
||||
n := 0
|
||||
for _, volume := range volumes.Volumes {
|
||||
if volume.ClusterVolume != nil {
|
||||
volumes.Volumes[n] = volume
|
||||
for _, vol := range volumes.Volumes {
|
||||
if vol.ClusterVolume != nil {
|
||||
volumes.Volumes[n] = vol
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,6 +43,7 @@ func TestVolumeListErrors(t *testing.T) {
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,6 +75,6 @@ func runPrune(dockerCli command.Cli, options pruneOptions) (spaceReclaimed uint6
|
||||
|
||||
// RunPrune calls the Volume Prune API
|
||||
// This returns the amount of space reclaimed and a detailed output string
|
||||
func RunPrune(dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error) {
|
||||
func RunPrune(dockerCli command.Cli, _ bool, filter opts.FilterOpt) (uint64, string, error) {
|
||||
return runPrune(dockerCli, pruneOptions{force: true, filter: filter})
|
||||
}
|
||||
|
||||
@ -49,6 +49,7 @@ func TestVolumePruneErrors(t *testing.T) {
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
}
|
||||
}
|
||||
@ -109,7 +110,7 @@ func TestVolumePrunePromptNo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func simplePruneFunc(args filters.Args) (types.VolumesPruneReport, error) {
|
||||
func simplePruneFunc(filters.Args) (types.VolumesPruneReport, error) {
|
||||
return types.VolumesPruneReport{
|
||||
VolumesDeleted: []string{
|
||||
"foo", "bar", "baz",
|
||||
|
||||
@ -33,6 +33,7 @@ func TestVolumeRemoveErrors(t *testing.T) {
|
||||
}))
|
||||
cmd.SetArgs(tc.args)
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
@ -596,14 +596,14 @@ type fakeClient struct {
|
||||
configListFunc func(types.ConfigListOptions) ([]swarm.Config, error)
|
||||
}
|
||||
|
||||
func (c *fakeClient) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
func (c *fakeClient) SecretList(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
|
||||
if c.secretListFunc != nil {
|
||||
return c.secretListFunc(options)
|
||||
}
|
||||
return []swarm.Secret{}, nil
|
||||
}
|
||||
|
||||
func (c *fakeClient) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
func (c *fakeClient) ConfigList(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
|
||||
if c.configListFunc != nil {
|
||||
return c.configListFunc(options)
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ const (
|
||||
|
||||
type portsFormatChecker struct{}
|
||||
|
||||
func (checker portsFormatChecker) IsFormat(input interface{}) bool {
|
||||
func (checker portsFormatChecker) IsFormat(_ interface{}) bool {
|
||||
// TODO: implement this
|
||||
return true
|
||||
}
|
||||
|
||||
@ -186,7 +186,7 @@ func (c *mockNativeStore) GetAll() (map[string]types.AuthConfig, error) {
|
||||
return c.authConfigs, nil
|
||||
}
|
||||
|
||||
func (c *mockNativeStore) Store(authConfig types.AuthConfig) error {
|
||||
func (c *mockNativeStore) Store(_ types.AuthConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ import (
|
||||
)
|
||||
|
||||
// New returns net.Conn
|
||||
func New(ctx context.Context, cmd string, args ...string) (net.Conn, error) {
|
||||
func New(_ context.Context, cmd string, args ...string) (net.Conn, error) {
|
||||
var (
|
||||
c commandConn
|
||||
err error
|
||||
|
||||
@ -2,12 +2,14 @@ package store
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/fvbommel/sortorder"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -35,7 +37,7 @@ func (s *metadataStore) createOrUpdate(meta Metadata) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(filepath.Join(contextDir, metaFile), bytes, 0o644)
|
||||
return ioutils.AtomicWriteFile(filepath.Join(contextDir, metaFile), bytes, 0o644)
|
||||
}
|
||||
|
||||
func parseTypedOrMap(payload []byte, getter TypeGetter) (interface{}, error) {
|
||||
@ -65,7 +67,8 @@ func (s *metadataStore) get(name string) (Metadata, error) {
|
||||
}
|
||||
|
||||
func (s *metadataStore) getByID(id contextdir) (Metadata, error) {
|
||||
bytes, err := os.ReadFile(filepath.Join(s.contextDir(id), metaFile))
|
||||
fileName := filepath.Join(s.contextDir(id), metaFile)
|
||||
bytes, err := os.ReadFile(fileName)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return Metadata{}, errdefs.NotFound(errors.Wrap(err, "context not found"))
|
||||
@ -77,15 +80,15 @@ func (s *metadataStore) getByID(id contextdir) (Metadata, error) {
|
||||
Endpoints: make(map[string]interface{}),
|
||||
}
|
||||
if err := json.Unmarshal(bytes, &untyped); err != nil {
|
||||
return Metadata{}, err
|
||||
return Metadata{}, fmt.Errorf("parsing %s: %v", fileName, err)
|
||||
}
|
||||
r.Name = untyped.Name
|
||||
if r.Metadata, err = parseTypedOrMap(untyped.Metadata, s.config.contextType); err != nil {
|
||||
return Metadata{}, err
|
||||
return Metadata{}, fmt.Errorf("parsing %s: %v", fileName, err)
|
||||
}
|
||||
for k, v := range untyped.Endpoints {
|
||||
if r.Endpoints[k], err = parseTypedOrMap(v, s.config.endpointTypes[k]); err != nil {
|
||||
return Metadata{}, err
|
||||
return Metadata{}, fmt.Errorf("parsing %s: %v", fileName, err)
|
||||
}
|
||||
}
|
||||
return r, err
|
||||
|
||||
@ -7,9 +7,11 @@ import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/errdefs"
|
||||
@ -230,3 +232,28 @@ func TestImportZipInvalid(t *testing.T) {
|
||||
err = Import("zipInvalid", s, r)
|
||||
assert.ErrorContains(t, err, "unexpected context file")
|
||||
}
|
||||
|
||||
func TestCorruptMetadata(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
s := New(tempDir, testCfg)
|
||||
err := s.CreateOrUpdate(
|
||||
Metadata{
|
||||
Endpoints: map[string]interface{}{
|
||||
"ep1": endpoint{Foo: "bar"},
|
||||
},
|
||||
Metadata: context{Bar: "baz"},
|
||||
Name: "source",
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Simulate the meta.json file getting corrupted
|
||||
// by some external process.
|
||||
contextDir := s.meta.contextDir(contextdirOf("source"))
|
||||
contextFile := filepath.Join(contextDir, metaFile)
|
||||
err = os.WriteFile(contextFile, nil, 0o600)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Assert that the error message gives the user some clue where to look.
|
||||
_, err = s.GetMetadata("source")
|
||||
assert.ErrorContains(t, err, fmt.Sprintf("parsing %s: unexpected end of JSON input", contextFile))
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -31,7 +32,7 @@ func (s *tlsStore) createOrUpdate(name, endpointName, filename string, data []by
|
||||
if err := os.MkdirAll(endpointDir, 0o700); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(filepath.Join(endpointDir, filename), data, 0o600)
|
||||
return ioutils.AtomicWriteFile(filepath.Join(endpointDir, filename), data, 0o600)
|
||||
}
|
||||
|
||||
func (s *tlsStore) getData(name, endpointName, filename string) ([]byte, error) {
|
||||
|
||||
@ -10,7 +10,6 @@ import (
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/reference"
|
||||
distributionclient "github.com/docker/distribution/registry/client"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
@ -36,7 +35,7 @@ func NewRegistryClient(resolver AuthConfigResolver, userAgent string, insecure b
|
||||
}
|
||||
|
||||
// AuthConfigResolver returns Auth Configuration for an index
|
||||
type AuthConfigResolver func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig
|
||||
type AuthConfigResolver func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig
|
||||
|
||||
// PutManifestOptions is the data sent to push a manifest
|
||||
type PutManifestOptions struct {
|
||||
|
||||
@ -9,7 +9,7 @@ import (
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/distribution/registry/client/auth"
|
||||
"github.com/docker/distribution/registry/client/transport"
|
||||
authtypes "github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -74,7 +74,7 @@ func getDefaultEndpointFromRepoInfo(repoInfo *registry.RepositoryInfo) (registry
|
||||
}
|
||||
|
||||
// getHTTPTransport builds a transport for use in communicating with a registry
|
||||
func getHTTPTransport(authConfig authtypes.AuthConfig, endpoint registry.APIEndpoint, repoName string, userAgent string) (http.RoundTripper, error) {
|
||||
func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.APIEndpoint, repoName string, userAgent string) (http.RoundTripper, error) {
|
||||
// get the http transport, this will be used in a client to upload manifest
|
||||
base := &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
@ -120,7 +120,7 @@ type existingTokenHandler struct {
|
||||
token string
|
||||
}
|
||||
|
||||
func (th *existingTokenHandler) AuthorizeRequest(req *http.Request, params map[string]string) error {
|
||||
func (th *existingTokenHandler) AuthorizeRequest(req *http.Request, _ map[string]string) error {
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", th.token))
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -17,7 +17,6 @@ import (
|
||||
"github.com/docker/distribution/registry/client/auth"
|
||||
"github.com/docker/distribution/registry/client/auth/challenge"
|
||||
"github.com/docker/distribution/registry/client/transport"
|
||||
"github.com/docker/docker/api/types"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
@ -79,24 +78,23 @@ func Server(index *registrytypes.IndexInfo) (string, error) {
|
||||
}
|
||||
|
||||
type simpleCredentialStore struct {
|
||||
auth types.AuthConfig
|
||||
auth registrytypes.AuthConfig
|
||||
}
|
||||
|
||||
func (scs simpleCredentialStore) Basic(u *url.URL) (string, string) {
|
||||
func (scs simpleCredentialStore) Basic(*url.URL) (string, string) {
|
||||
return scs.auth.Username, scs.auth.Password
|
||||
}
|
||||
|
||||
func (scs simpleCredentialStore) RefreshToken(u *url.URL, service string) string {
|
||||
func (scs simpleCredentialStore) RefreshToken(*url.URL, string) string {
|
||||
return scs.auth.IdentityToken
|
||||
}
|
||||
|
||||
func (scs simpleCredentialStore) SetRefreshToken(*url.URL, string, string) {
|
||||
}
|
||||
func (scs simpleCredentialStore) SetRefreshToken(*url.URL, string, string) {}
|
||||
|
||||
// GetNotaryRepository returns a NotaryRepository which stores all the
|
||||
// information needed to operate on a notary repository.
|
||||
// It creates an HTTP transport providing authentication support.
|
||||
func GetNotaryRepository(in io.Reader, out io.Writer, userAgent string, repoInfo *registry.RepositoryInfo, authConfig *types.AuthConfig, actions ...string) (client.Repository, error) {
|
||||
func GetNotaryRepository(in io.Reader, out io.Writer, userAgent string, repoInfo *registry.RepositoryInfo, authConfig *registrytypes.AuthConfig, actions ...string) (client.Repository, error) {
|
||||
server, err := Server(repoInfo.Index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -160,7 +158,7 @@ func GetNotaryRepository(in io.Reader, out io.Writer, userAgent string, repoInfo
|
||||
scope := auth.RepositoryScope{
|
||||
Repository: repoInfo.Name.Name(),
|
||||
Actions: actions,
|
||||
Class: repoInfo.Class,
|
||||
Class: repoInfo.Class, // TODO(thaJeztah): Class is no longer needed for plugins and can likely be removed; see https://github.com/docker/cli/pull/4114#discussion_r1145430825
|
||||
}
|
||||
creds := simpleCredentialStore{auth: *authConfig}
|
||||
tokenHandlerOptions := auth.TokenHandlerOptions{
|
||||
@ -292,7 +290,7 @@ func GetSignableRoles(repo client.Repository, target *client.Target) ([]data.Rol
|
||||
// ImageRefAndAuth contains all reference information and the auth config for an image request
|
||||
type ImageRefAndAuth struct {
|
||||
original string
|
||||
authConfig *types.AuthConfig
|
||||
authConfig *registrytypes.AuthConfig
|
||||
reference reference.Named
|
||||
repoInfo *registry.RepositoryInfo
|
||||
tag string
|
||||
@ -301,8 +299,8 @@ type ImageRefAndAuth struct {
|
||||
|
||||
// GetImageReferencesAndAuth retrieves the necessary reference and auth information for an image name
|
||||
// as an ImageRefAndAuth struct
|
||||
func GetImageReferencesAndAuth(ctx context.Context, rs registry.Service,
|
||||
authResolver func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig,
|
||||
func GetImageReferencesAndAuth(ctx context.Context,
|
||||
authResolver func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig,
|
||||
imgName string,
|
||||
) (ImageRefAndAuth, error) {
|
||||
ref, err := reference.ParseNormalizedNamed(imgName)
|
||||
@ -311,13 +309,7 @@ func GetImageReferencesAndAuth(ctx context.Context, rs registry.Service,
|
||||
}
|
||||
|
||||
// Resolve the Repository name from fqn to RepositoryInfo
|
||||
var repoInfo *registry.RepositoryInfo
|
||||
if rs != nil {
|
||||
repoInfo, err = rs.ResolveRepository(ref)
|
||||
} else {
|
||||
repoInfo, err = registry.ParseRepositoryInfo(ref)
|
||||
}
|
||||
|
||||
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
||||
if err != nil {
|
||||
return ImageRefAndAuth{}, err
|
||||
}
|
||||
@ -356,7 +348,7 @@ func getDigest(ref reference.Named) digest.Digest {
|
||||
}
|
||||
|
||||
// AuthConfig returns the auth information (username, etc) for a given ImageRefAndAuth
|
||||
func (imgRefAuth *ImageRefAndAuth) AuthConfig() *types.AuthConfig {
|
||||
func (imgRefAuth *ImageRefAndAuth) AuthConfig() *registrytypes.AuthConfig {
|
||||
return imgRefAuth.authConfig
|
||||
}
|
||||
|
||||
|
||||
@ -133,13 +133,20 @@ func tryRunPluginHelp(dockerCli command.Cli, ccmd *cobra.Command, cargs []string
|
||||
func setHelpFunc(dockerCli command.Cli, cmd *cobra.Command) {
|
||||
defaultHelpFunc := cmd.HelpFunc()
|
||||
cmd.SetHelpFunc(func(ccmd *cobra.Command, args []string) {
|
||||
if pluginmanager.IsPluginCommand(ccmd) {
|
||||
if err := pluginmanager.AddPluginCommandStubs(dockerCli, ccmd.Root()); err != nil {
|
||||
ccmd.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(args) >= 1 {
|
||||
err := tryRunPluginHelp(dockerCli, ccmd, args)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
if !pluginmanager.IsNotFound(err) {
|
||||
ccmd.Println(err)
|
||||
return
|
||||
}
|
||||
cmd.PrintErrf("unknown help topic: %v\n", ccmd.Name())
|
||||
return
|
||||
}
|
||||
|
||||
if err := isSupported(ccmd, dockerCli); err != nil {
|
||||
@ -227,9 +234,14 @@ func runDocker(dockerCli *command.DockerCli) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = pluginmanager.AddPluginCommandStubs(dockerCli, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
if cli.HasCompletionArg(args) {
|
||||
// We add plugin command stubs early only for completion. We don't
|
||||
// want to add them for normal command execution as it would cause
|
||||
// a significant performance hit.
|
||||
err = pluginmanager.AddPluginCommandStubs(dockerCli, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(args) > 0 {
|
||||
|
||||
@ -84,13 +84,13 @@ __docker_q() {
|
||||
# precedence over the environment setting.
|
||||
__docker_configs() {
|
||||
local format
|
||||
if [ "$1" = "--id" ] ; then
|
||||
if [ "${1-}" = "--id" ] ; then
|
||||
format='{{.ID}}'
|
||||
shift
|
||||
elif [ "$1" = "--name" ] ; then
|
||||
elif [ "${1-}" = "--name" ] ; then
|
||||
format='{{.Name}}'
|
||||
shift
|
||||
elif [ "$DOCKER_COMPLETION_SHOW_CONFIG_IDS" = yes ] ; then
|
||||
elif [ "${DOCKER_COMPLETION_SHOW_CONFIG_IDS-}" = yes ] ; then
|
||||
format='{{.ID}} {{.Name}}'
|
||||
else
|
||||
format='{{.Name}}'
|
||||
@ -120,13 +120,13 @@ __docker_complete_configs() {
|
||||
# precedence over the environment setting.
|
||||
__docker_containers() {
|
||||
local format
|
||||
if [ "$1" = "--id" ] ; then
|
||||
if [ "${1-}" = "--id" ] ; then
|
||||
format='{{.ID}}'
|
||||
shift
|
||||
elif [ "$1" = "--name" ] ; then
|
||||
elif [ "${1-}" = "--name" ] ; then
|
||||
format='{{.Names}}'
|
||||
shift
|
||||
elif [ "${DOCKER_COMPLETION_SHOW_CONTAINER_IDS}" = yes ] ; then
|
||||
elif [ "${DOCKER_COMPLETION_SHOW_CONTAINER_IDS-}" = yes ] ; then
|
||||
format='{{.ID}} {{.Names}}'
|
||||
else
|
||||
format='{{.Names}}'
|
||||
@ -139,7 +139,7 @@ __docker_containers() {
|
||||
# Additional filters may be appended, see `__docker_containers`.
|
||||
__docker_complete_containers() {
|
||||
local current="$cur"
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@ -191,7 +191,7 @@ __docker_complete_container_ids() {
|
||||
__docker_contexts() {
|
||||
local add=()
|
||||
while true ; do
|
||||
case "$1" in
|
||||
case "${1-}" in
|
||||
--add)
|
||||
add+=("$2")
|
||||
shift 2
|
||||
@ -236,12 +236,12 @@ __docker_images() {
|
||||
local all
|
||||
local format
|
||||
|
||||
if [ "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" = "all" ] ; then
|
||||
if [ "${DOCKER_COMPLETION_SHOW_IMAGE_IDS-}" = "all" ] ; then
|
||||
all='--all'
|
||||
fi
|
||||
|
||||
while true ; do
|
||||
case "$1" in
|
||||
case "${1-}" in
|
||||
--repo)
|
||||
format+="$repo_format\n"
|
||||
shift
|
||||
@ -253,7 +253,7 @@ __docker_images() {
|
||||
shift
|
||||
;;
|
||||
--id)
|
||||
if [[ $DOCKER_COMPLETION_SHOW_IMAGE_IDS =~ ^(all|non-intermediate)$ ]] ; then
|
||||
if [[ ${DOCKER_COMPLETION_SHOW_IMAGE_IDS-} =~ ^(all|non-intermediate)$ ]] ; then
|
||||
format+="$id_format\n"
|
||||
fi
|
||||
shift
|
||||
@ -269,7 +269,7 @@ __docker_images() {
|
||||
esac
|
||||
done
|
||||
|
||||
__docker_q image ls --no-trunc --format "${format%\\n}" $all "$@" | grep -v '<none>$'
|
||||
__docker_q image ls --no-trunc --format "${format%\\n}" ${all-} "$@" | grep -v '<none>$'
|
||||
}
|
||||
|
||||
# __docker_complete_images applies completion of images based on the current value of `$cur` or
|
||||
@ -277,7 +277,7 @@ __docker_images() {
|
||||
# See __docker_images for customization of the returned items.
|
||||
__docker_complete_images() {
|
||||
local current="$cur"
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@ -295,13 +295,13 @@ __docker_complete_images() {
|
||||
# precedence over the environment setting.
|
||||
__docker_networks() {
|
||||
local format
|
||||
if [ "$1" = "--id" ] ; then
|
||||
if [ "${1-}" = "--id" ] ; then
|
||||
format='{{.ID}}'
|
||||
shift
|
||||
elif [ "$1" = "--name" ] ; then
|
||||
elif [ "${1-}" = "--name" ] ; then
|
||||
format='{{.Name}}'
|
||||
shift
|
||||
elif [ "${DOCKER_COMPLETION_SHOW_NETWORK_IDS}" = yes ] ; then
|
||||
elif [ "${DOCKER_COMPLETION_SHOW_NETWORK_IDS-}" = yes ] ; then
|
||||
format='{{.ID}} {{.Name}}'
|
||||
else
|
||||
format='{{.Name}}'
|
||||
@ -314,7 +314,7 @@ __docker_networks() {
|
||||
# Additional filters may be appended, see `__docker_networks`.
|
||||
__docker_complete_networks() {
|
||||
local current="$cur"
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@ -340,7 +340,7 @@ __docker_volumes() {
|
||||
# Additional filters may be appended, see `__docker_volumes`.
|
||||
__docker_complete_volumes() {
|
||||
local current="$cur"
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@ -356,7 +356,7 @@ __docker_complete_volumes() {
|
||||
__docker_plugins_bundled() {
|
||||
local type add=() remove=()
|
||||
while true ; do
|
||||
case "$1" in
|
||||
case "${1-}" in
|
||||
--type)
|
||||
type="$2"
|
||||
shift 2
|
||||
@ -390,7 +390,7 @@ __docker_plugins_bundled() {
|
||||
# `__docker_complete_plugins_installed`.
|
||||
__docker_complete_plugins_bundled() {
|
||||
local current="$cur"
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@ -406,7 +406,7 @@ __docker_complete_plugins_bundled() {
|
||||
# For built-in pugins, see `__docker_plugins_bundled`.
|
||||
__docker_plugins_installed() {
|
||||
local format
|
||||
if [ "$DOCKER_COMPLETION_SHOW_PLUGIN_IDS" = yes ] ; then
|
||||
if [ "${DOCKER_COMPLETION_SHOW_PLUGIN_IDS-}" = yes ] ; then
|
||||
format='{{.ID}} {{.Name}}'
|
||||
else
|
||||
format='{{.Name}}'
|
||||
@ -421,7 +421,7 @@ __docker_plugins_installed() {
|
||||
# For completion of built-in pugins, see `__docker_complete_plugins_bundled`.
|
||||
__docker_complete_plugins_installed() {
|
||||
local current="$cur"
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@ -446,13 +446,13 @@ __docker_complete_runtimes() {
|
||||
# precedence over the environment setting.
|
||||
__docker_secrets() {
|
||||
local format
|
||||
if [ "$1" = "--id" ] ; then
|
||||
if [ "${1-}" = "--id" ] ; then
|
||||
format='{{.ID}}'
|
||||
shift
|
||||
elif [ "$1" = "--name" ] ; then
|
||||
elif [ "${1-}" = "--name" ] ; then
|
||||
format='{{.Name}}'
|
||||
shift
|
||||
elif [ "$DOCKER_COMPLETION_SHOW_SECRET_IDS" = yes ] ; then
|
||||
elif [ "${DOCKER_COMPLETION_SHOW_SECRET_IDS-}" = yes ] ; then
|
||||
format='{{.ID}} {{.Name}}'
|
||||
else
|
||||
format='{{.Name}}'
|
||||
@ -465,7 +465,7 @@ __docker_secrets() {
|
||||
# of `$cur` or the value of the optional first option `--cur`, if given.
|
||||
__docker_complete_secrets() {
|
||||
local current="$cur"
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@ -481,7 +481,7 @@ __docker_stacks() {
|
||||
# of `$cur` or the value of the optional first option `--cur`, if given.
|
||||
__docker_complete_stacks() {
|
||||
local current="$cur"
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@ -499,7 +499,7 @@ __docker_complete_stacks() {
|
||||
# Completions may be added with `--add`, e.g. `--add self`.
|
||||
__docker_nodes() {
|
||||
local format
|
||||
if [ "$DOCKER_COMPLETION_SHOW_NODE_IDS" = yes ] ; then
|
||||
if [ "${DOCKER_COMPLETION_SHOW_NODE_IDS-}" = yes ] ; then
|
||||
format='{{.ID}} {{.Hostname}}'
|
||||
else
|
||||
format='{{.Hostname}}'
|
||||
@ -508,7 +508,7 @@ __docker_nodes() {
|
||||
local add=()
|
||||
|
||||
while true ; do
|
||||
case "$1" in
|
||||
case "${1-}" in
|
||||
--id)
|
||||
format='{{.ID}}'
|
||||
shift
|
||||
@ -535,7 +535,7 @@ __docker_nodes() {
|
||||
# Additional filters may be appended, see `__docker_nodes`.
|
||||
__docker_complete_nodes() {
|
||||
local current="$cur"
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@ -552,12 +552,12 @@ __docker_complete_nodes() {
|
||||
# precedence over the environment setting.
|
||||
__docker_services() {
|
||||
local format='{{.Name}}' # default: service name only
|
||||
[ "${DOCKER_COMPLETION_SHOW_SERVICE_IDS}" = yes ] && format='{{.ID}} {{.Name}}' # ID & name
|
||||
[ "${DOCKER_COMPLETION_SHOW_SERVICE_IDS-}" = yes ] && format='{{.ID}} {{.Name}}' # ID & name
|
||||
|
||||
if [ "$1" = "--id" ] ; then
|
||||
if [ "${1-}" = "--id" ] ; then
|
||||
format='{{.ID}}' # IDs only
|
||||
shift
|
||||
elif [ "$1" = "--name" ] ; then
|
||||
elif [ "${1-}" = "--name" ] ; then
|
||||
format='{{.Name}}' # names only
|
||||
shift
|
||||
fi
|
||||
@ -570,7 +570,7 @@ __docker_services() {
|
||||
# Additional filters may be appended, see `__docker_services`.
|
||||
__docker_complete_services() {
|
||||
local current="$cur"
|
||||
if [ "$1" = "--cur" ] ; then
|
||||
if [ "${1-}" = "--cur" ] ; then
|
||||
current="$2"
|
||||
shift 2
|
||||
fi
|
||||
@ -601,7 +601,7 @@ __docker_append_to_completions() {
|
||||
# several variables with the results.
|
||||
# The result is cached for the duration of one invocation of bash completion.
|
||||
__docker_fetch_info() {
|
||||
if [ -z "$info_fetched" ] ; then
|
||||
if [ -z "${info_fetched-}" ] ; then
|
||||
read -r server_experimental server_os <<< "$(__docker_q version -f '{{.Server.Experimental}} {{.Server.Os}}')"
|
||||
info_fetched=true
|
||||
fi
|
||||
@ -629,7 +629,7 @@ __docker_server_os_is() {
|
||||
# you should pass a glob describing those options, e.g. "--option1|-o|--option2"
|
||||
# Use this function to restrict completions to exact positions after the argument list.
|
||||
__docker_pos_first_nonflag() {
|
||||
local argument_flags=$1
|
||||
local argument_flags=${1-}
|
||||
|
||||
local counter=$((${subcommand_pos:-${command_pos}} + 1))
|
||||
while [ "$counter" -le "$cword" ]; do
|
||||
@ -766,7 +766,7 @@ __docker_local_interfaces() {
|
||||
command -v ip >/dev/null 2>&1 || return
|
||||
|
||||
local format
|
||||
if [ "$1" = "--ip-only" ] ; then
|
||||
if [ "${1-}" = "--ip-only" ] ; then
|
||||
format='\1'
|
||||
shift
|
||||
else
|
||||
@ -781,7 +781,7 @@ __docker_local_interfaces() {
|
||||
# An additional value can be added to the possible completions with an `--add` argument.
|
||||
__docker_complete_local_interfaces() {
|
||||
local additional_interface
|
||||
if [ "$1" = "--add" ] ; then
|
||||
if [ "${1-}" = "--add" ] ; then
|
||||
additional_interface="$2"
|
||||
shift 2
|
||||
fi
|
||||
@ -1125,7 +1125,7 @@ __docker_complete_ulimits() {
|
||||
sigpending
|
||||
stack
|
||||
"
|
||||
if [ "$1" = "--rm" ] ; then
|
||||
if [ "${1-}" = "--rm" ] ; then
|
||||
COMPREPLY=( $( compgen -W "$limits" -- "$cur" ) )
|
||||
else
|
||||
COMPREPLY=( $( compgen -W "$limits" -S = -- "$cur" ) )
|
||||
@ -1142,6 +1142,29 @@ __docker_complete_user_group() {
|
||||
fi
|
||||
}
|
||||
|
||||
DOCKER_PLUGINS_PATH=$(docker info --format '{{range .ClientInfo.Plugins}}{{.Path}}:{{end}}')
|
||||
|
||||
__docker_complete_plugin() {
|
||||
local path=$1
|
||||
local completionCommand="__completeNoDesc"
|
||||
local resultArray=($path $completionCommand)
|
||||
for value in "${words[@]:2}"; do
|
||||
if [ -z "$value" ]; then
|
||||
resultArray+=( "''" )
|
||||
else
|
||||
resultArray+=( "$value" )
|
||||
fi
|
||||
done
|
||||
local result=$(eval "${resultArray[*]}" 2> /dev/null | grep -v '^:[0-9]*$')
|
||||
|
||||
# if result empty, just use filename completion as fallback
|
||||
if [ -z "$result" ]; then
|
||||
_filedir
|
||||
else
|
||||
COMPREPLY=( $(compgen -W "${result}" -- "${current-}") )
|
||||
fi
|
||||
}
|
||||
|
||||
_docker_docker() {
|
||||
# global options that may appear after the docker command
|
||||
local boolean_options="
|
||||
@ -2785,7 +2808,7 @@ _docker_image_build() {
|
||||
"
|
||||
fi
|
||||
|
||||
if [ "$DOCKER_BUILDKIT" = "1" ] ; then
|
||||
if [ "${DOCKER_BUILDKIT-}" = "1" ] ; then
|
||||
options_with_args+="
|
||||
--output -o
|
||||
--progress
|
||||
@ -3133,7 +3156,7 @@ _docker_inspect() {
|
||||
local preselected_type
|
||||
local type
|
||||
|
||||
if [ "$1" = "--type" ] ; then
|
||||
if [ "${1-}" = "--type" ] ; then
|
||||
preselected_type=yes
|
||||
type="$2"
|
||||
else
|
||||
@ -5395,23 +5418,6 @@ _docker_wait() {
|
||||
_docker_container_wait
|
||||
}
|
||||
|
||||
COMPOSE_PLUGIN_PATH=$(docker info --format '{{range .ClientInfo.Plugins}}{{if eq .Name "compose"}}{{.Path}}{{end}}{{end}}')
|
||||
|
||||
_docker_compose() {
|
||||
local completionCommand="__completeNoDesc"
|
||||
local resultArray=($COMPOSE_PLUGIN_PATH $completionCommand compose)
|
||||
for value in "${words[@]:2}"; do
|
||||
if [ -z "$value" ]; then
|
||||
resultArray+=( "''" )
|
||||
else
|
||||
resultArray+=( "$value" )
|
||||
fi
|
||||
done
|
||||
local result=$(eval "${resultArray[*]}" 2> /dev/null | grep -v '^:[0-9]*$')
|
||||
|
||||
COMPREPLY=( $(compgen -W "${result}" -- "$current") )
|
||||
}
|
||||
|
||||
_docker() {
|
||||
local previous_extglob_setting=$(shopt -p extglob)
|
||||
shopt -s extglob
|
||||
@ -5481,18 +5487,23 @@ _docker() {
|
||||
wait
|
||||
)
|
||||
|
||||
# Create completion functions for all registered plugins
|
||||
local known_plugin_commands=()
|
||||
|
||||
if [ -f "$COMPOSE_PLUGIN_PATH" ] ; then
|
||||
known_plugin_commands+=("compose")
|
||||
fi
|
||||
local plugin_name=""
|
||||
for plugin_path in ${DOCKER_PLUGINS_PATH//:/ }; do
|
||||
plugin_name=$(basename "$plugin_path" | sed 's/ *$//')
|
||||
plugin_name=${plugin_name#docker-}
|
||||
plugin_name=${plugin_name%%.*}
|
||||
eval "_docker_${plugin_name}() { __docker_complete_plugin \"${plugin_path}\"; }"
|
||||
known_plugin_commands+=(${plugin_name})
|
||||
done
|
||||
|
||||
local experimental_server_commands=(
|
||||
checkpoint
|
||||
)
|
||||
|
||||
local commands=(${management_commands[*]} ${top_level_commands[*]} ${known_plugin_commands[*]})
|
||||
[ -z "$DOCKER_HIDE_LEGACY_COMMANDS" ] && commands+=(${legacy_commands[*]})
|
||||
[ -z "${DOCKER_HIDE_LEGACY_COMMANDS-}" ] && commands+=(${legacy_commands[*]})
|
||||
|
||||
# These options are valid as global options for all client commands
|
||||
# and valid as command options for `docker daemon`
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
variable "GO_VERSION" {
|
||||
default = "1.19.5"
|
||||
default = "1.20.2"
|
||||
}
|
||||
variable "VERSION" {
|
||||
default = ""
|
||||
@ -52,7 +52,7 @@ target "binary" {
|
||||
platforms = ["local"]
|
||||
output = ["build"]
|
||||
args = {
|
||||
BASE_VARIANT = USE_GLIBC != "" ? "bullseye" : "alpine"
|
||||
BASE_VARIANT = USE_GLIBC == "1" ? "bullseye" : "alpine"
|
||||
VERSION = VERSION
|
||||
PACKAGER_NAME = PACKAGER_NAME
|
||||
GO_STRIP = STRIP_TARGET
|
||||
@ -72,7 +72,7 @@ target "plugins" {
|
||||
platforms = ["local"]
|
||||
output = ["build"]
|
||||
args = {
|
||||
BASE_VARIANT = USE_GLIBC != "" ? "bullseye" : "alpine"
|
||||
BASE_VARIANT = USE_GLIBC == "1" ? "bullseye" : "alpine"
|
||||
VERSION = VERSION
|
||||
GO_STRIP = STRIP_TARGET
|
||||
}
|
||||
@ -155,7 +155,13 @@ target "e2e-image" {
|
||||
output = ["type=docker"]
|
||||
tags = ["${IMAGE_NAME}"]
|
||||
args = {
|
||||
BASE_VARIANT = USE_GLIBC != "" ? "bullseye" : "alpine"
|
||||
BASE_VARIANT = USE_GLIBC == "1" ? "bullseye" : "alpine"
|
||||
VERSION = VERSION
|
||||
}
|
||||
}
|
||||
|
||||
target "e2e-gencerts" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "./e2e/testdata/Dockerfile.gencerts"
|
||||
output = ["./e2e/testdata"]
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.19.5
|
||||
ARG GO_VERSION=1.20.2
|
||||
ARG ALPINE_VERSION=3.16
|
||||
|
||||
ARG BUILDX_VERSION=0.9.1
|
||||
ARG BUILDX_VERSION=0.10.4
|
||||
FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx
|
||||
|
||||
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS golang
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.19.5
|
||||
ARG GO_VERSION=1.20.2
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG GOLANGCI_LINT_VERSION=v1.49.0
|
||||
ARG GOLANGCI_LINT_VERSION=v1.52.2
|
||||
|
||||
FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.19.4
|
||||
ARG GO_VERSION=1.20.2
|
||||
ARG ALPINE_VERSION=3.16
|
||||
ARG MODOUTDATED_VERSION=v0.8.0
|
||||
|
||||
|
||||
@ -50,6 +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 |
|
||||
| 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 |
|
||||
@ -104,6 +105,17 @@ The table below provides an overview of the current status of deprecated feature
|
||||
| Removed | [`--run` flag on `docker commit`](#--run-flag-on-docker-commit) | v0.10 | v1.13 |
|
||||
| Removed | [Three arguments form in `docker import`](#three-arguments-form-in-docker-import) | v0.6.7 | v1.12 |
|
||||
|
||||
### Buildkit build information
|
||||
|
||||
**Deprecated in Release: v23.0.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)
|
||||
and are generated with build metadata that allows you to see all the sources
|
||||
(images, git repositories) that were used by the build with their exact
|
||||
versions and also the configuration that was passed to the build. This
|
||||
information is also embedded into the image configuration if one is generated.
|
||||
|
||||
### Legacy builder for Linux images
|
||||
|
||||
**Deprecated in Release: v23.0.0**
|
||||
|
||||
@ -295,57 +295,11 @@ $ docker -H tcp://127.0.0.1:2375 pull ubuntu
|
||||
On Linux, the Docker daemon has support for several different image layer storage
|
||||
drivers: `aufs`, `devicemapper`, `btrfs`, `zfs`, `overlay`, `overlay2`, and `fuse-overlayfs`.
|
||||
|
||||
The `aufs` driver is the oldest, but is based on a Linux kernel patch-set that
|
||||
is unlikely to be merged into the main kernel. These are also known to cause
|
||||
some serious kernel crashes. However `aufs` allows containers to share
|
||||
executable and shared library memory, so is a useful choice when running
|
||||
thousands of containers with the same program or libraries.
|
||||
`overlay2` is the preferred storage driver for all currently supported Linux distributions,
|
||||
and is selected by default. Unless users have a strong reason to prefer another storage driver,
|
||||
`overlay2` should be used.
|
||||
|
||||
The `devicemapper` driver uses thin provisioning and Copy on Write (CoW)
|
||||
snapshots. For each devicemapper graph location – typically
|
||||
`/var/lib/docker/devicemapper` – a thin pool is created based on two block
|
||||
devices, one for data and one for metadata. By default, these block devices
|
||||
are created automatically by using loopback mounts of automatically created
|
||||
sparse files. Refer to [Devicemapper options](#devicemapper-options) below
|
||||
for a way how to customize this setup.
|
||||
[~jpetazzo/Resizing Docker containers with the Device Mapper plugin](https://jpetazzo.github.io/2014/01/29/docker-device-mapper-resize/)
|
||||
article explains how to tune your existing setup without the use of options.
|
||||
|
||||
The `btrfs` driver is very fast for `docker build` - but like `devicemapper`
|
||||
does not share executable memory between devices. Use
|
||||
`dockerd --storage-driver btrfs --data-root /mnt/btrfs_partition`.
|
||||
|
||||
The `zfs` driver is probably not as fast as `btrfs` but has a longer track record
|
||||
on stability. Thanks to `Single Copy ARC` shared blocks between clones will be
|
||||
cached only once. Use `dockerd -s zfs`. To select a different zfs filesystem
|
||||
set `zfs.fsname` option as described in [ZFS options](#zfs-options).
|
||||
|
||||
The `overlay` is a very fast union filesystem. It is now merged in the main
|
||||
Linux kernel as of [3.18.0](https://lkml.org/lkml/2014/10/26/137). `overlay`
|
||||
also supports page cache sharing, this means multiple containers accessing
|
||||
the same file can share a single page cache entry (or entries), it makes
|
||||
`overlay` as efficient with memory as `aufs` driver. Call `dockerd -s overlay`
|
||||
to use it.
|
||||
|
||||
The `overlay2` uses the same fast union filesystem but takes advantage of
|
||||
[additional features](https://lkml.org/lkml/2015/2/11/106) added in Linux
|
||||
kernel 4.0 to avoid excessive inode consumption. Call `dockerd -s overlay2`
|
||||
to use it.
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> The `overlay` storage driver can cause excessive inode consumption (especially
|
||||
> as the number of images grows). We recommend using the `overlay2` storage
|
||||
> driver instead.
|
||||
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> Both `overlay` and `overlay2` are currently unsupported on `btrfs`
|
||||
> or any Copy on Write filesystem and should only be used over `ext4` partitions.
|
||||
|
||||
The `fuse-overlayfs` driver is similar to `overlay2` but works in userspace.
|
||||
The `fuse-overlayfs` driver is expected to be used for [Rootless mode](https://docs.docker.com/engine/security/rootless/).
|
||||
You can find out more about storage drivers and how to select one in [Select a storage driver](https://docs.docker.com/storage/storagedriver/select-storage-driver/).
|
||||
|
||||
On Windows, the Docker daemon only supports the `windowsfilter` storage driver.
|
||||
|
||||
@ -1189,7 +1143,7 @@ of the flag name, e.g., `labels` for the `label` flag.
|
||||
|
||||
The options set in the configuration file must not conflict with options set
|
||||
via flags. The docker daemon fails to start if an option is duplicated between
|
||||
the file and the flags, regardless their value. We do this to avoid
|
||||
the file and the flags, regardless of their value. We do this to avoid
|
||||
silently ignore changes introduced in configuration reloads.
|
||||
For example, the daemon fails to start if you set daemon labels
|
||||
in the configuration file and also set daemon labels via the `--label` flag.
|
||||
|
||||
@ -95,16 +95,16 @@ $ docker stats nginx --no-stream --format "{{ json . }}"
|
||||
Running `docker stats` with customized format on all (Running and Stopped) containers.
|
||||
|
||||
```console
|
||||
$ docker stats --all --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" fervent_panini 5acfcb1b4fd1 drunk_visvesvaraya big_heisenberg
|
||||
$ docker stats --all --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" fervent_panini 5acfcb1b4fd1 humble_visvesvaraya big_heisenberg
|
||||
|
||||
CONTAINER CPU % MEM USAGE / LIMIT
|
||||
fervent_panini 0.00% 56KiB / 15.57GiB
|
||||
5acfcb1b4fd1 0.07% 32.86MiB / 15.57GiB
|
||||
drunk_visvesvaraya 0.00% 0B / 0B
|
||||
humble_visvesvaraya 0.00% 0B / 0B
|
||||
big_heisenberg 0.00% 0B / 0B
|
||||
```
|
||||
|
||||
`drunk_visvesvaraya` and `big_heisenberg` are stopped containers in the above example.
|
||||
`humble_visvesvaraya` and `big_heisenberg` are stopped containers in the above example.
|
||||
|
||||
Running `docker stats` on all running containers against a Windows daemon.
|
||||
|
||||
|
||||
@ -83,7 +83,7 @@ func TestHelpBad(t *testing.T) {
|
||||
|
||||
res := icmd.RunCmd(run("help", "badmeta"))
|
||||
res.Assert(t, icmd.Expected{
|
||||
ExitCode: 0,
|
||||
ExitCode: 1,
|
||||
Out: icmd.None,
|
||||
})
|
||||
golden.Assert(t, res.Stderr(), "docker-help-badmeta-err.golden")
|
||||
@ -110,8 +110,8 @@ func TestBadHelp(t *testing.T) {
|
||||
res.Assert(t, icmd.Expected{
|
||||
ExitCode: 0,
|
||||
// This should be identical to the --help case above
|
||||
Out: usage,
|
||||
Err: shortHFlagDeprecated,
|
||||
Out: shortHFlagDeprecated + usage,
|
||||
Err: icmd.None,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
19
e2e/testdata/Dockerfile.gencerts
vendored
Normal file
19
e2e/testdata/Dockerfile.gencerts
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.20.2
|
||||
|
||||
FROM golang:${GO_VERSION}-alpine AS generated
|
||||
RUN go install github.com/dmcgowan/quicktls@master
|
||||
WORKDIR /tmp/gencerts/notary
|
||||
RUN --mount=type=bind,source=e2e/testdata/notary,target=/tmp/gencerts/notary,rw <<EOT
|
||||
set -eu
|
||||
mkdir -p ../notary-evil /out
|
||||
quicktls -exp 87600h -org=Docker -with-san notary-server notaryserver evil-notary-server evilnotaryserver localhost 127.0.0.1
|
||||
cat ca.pem >> notary-server.cert
|
||||
mv ca.pem root-ca.cert
|
||||
cp notary-server.cert notary-server.key root-ca.cert ../notary-evil
|
||||
cp -r /tmp/gencerts/notary* /out/
|
||||
EOT
|
||||
|
||||
FROM scratch
|
||||
COPY --from=generated /out /
|
||||
12
e2e/testdata/gen-certs.sh
vendored
12
e2e/testdata/gen-certs.sh
vendored
@ -1,12 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
# This script is used to generate the test-certificates in the notary-server and
|
||||
# evil-notary-server directories. Run this script to update the certificates if
|
||||
# they expire.
|
||||
GO111MODULE=off go get -u github.com/dmcgowan/quicktls
|
||||
cd notary
|
||||
quicktls -org=Docker -with-san notary-server notaryserver evil-notary-server evilnotaryserver localhost 127.0.0.1
|
||||
cat ca.pem >> notary-server.cert
|
||||
mv ca.pem root-ca.cert
|
||||
cp notary-server.cert notary-server.key root-ca.cert ../notary-evil/
|
||||
70
e2e/testdata/notary-evil/notary-server.cert
vendored
70
e2e/testdata/notary-evil/notary-server.cert
vendored
@ -1,38 +1,40 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDVDCCAjygAwIBAgIQQReeTsMMrsG9juzWS8eAjjANBgkqhkiG9w0BAQsFADAi
|
||||
MQ8wDQYDVQQKEwZEb2NrZXIxDzANBgNVBAMTBkRvY2tlcjAeFw0yMDA0MDkxNDQ3
|
||||
NTdaFw0yMzAzMjUxNDQ3NTdaMCkxDzANBgNVBAoTBkRvY2tlcjEWMBQGA1UEAxMN
|
||||
bm90YXJ5LXNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKA
|
||||
wO8S9Ux/e4TMOsTkPtCPfpFU+6l6z72uzrFhCNWb0lrTG7hcxwhP6sIesevTOM24
|
||||
GCyvzh+9SMTtdBmSQty4JNElqg9sB6r1tLTeTHo7lMiSiINftctoI1kYg9ni+IO9
|
||||
DVBSb9gQf9dDoizat9VhpbLNm3QXkQSeE9cumen6Pz+fcEtB7lFtIYxEEv/L7+VY
|
||||
QOvhtg0RXiRzfmtSGwFL+FZ9PBz4LOvPnPOLCMQewhR+6cAkO7Jch0ZMjCe8zXXw
|
||||
h8meeIedoevHt0opsr4HHikvr6llwlhWHL+E7zwTPO10xLGd/RIQGGhs8dXhzp1V
|
||||
lw/oe2VJoIFSOaGjRFcCAwEAAaN/MH0wDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB
|
||||
/wQCMAAwXQYDVR0RBFYwVIINbm90YXJ5LXNlcnZlcoIMbm90YXJ5c2VydmVyghJl
|
||||
dmlsLW5vdGFyeS1zZXJ2ZXKCEGV2aWxub3RhcnlzZXJ2ZXKCCWxvY2FsaG9zdIcE
|
||||
fwAAATANBgkqhkiG9w0BAQsFAAOCAQEAgwkZpp4s6reZWs9QatF/x9qWWXIXJzYh
|
||||
6BgzHL3s7UgeZSs0XhgfHYy6SO94ENpbzPADZwue/NjwNXmp7TLjbyUPjSo1DDt7
|
||||
OLG8bQ/hbcPKgMzirTZT36CEsetIBYmfyn39h+ZEIJ30J996/Tgq+X9sG7An2wq3
|
||||
/btn+C/BiMUgGnNxZ8p4n+uJCUKA95uVugdLjeioA+19HgQzrLSkeZUR/wsesq5F
|
||||
iP9k8va2oU3l3MsF079NpfIDl2gtIgXFYWPhyaJCaa+b8irjdoPnhDBuC5p77AWl
|
||||
UTPw/6ENKMMd1Pze6HLpBJAkPP8hTlULKgvuF0pWuGOejipkAKlOBQ==
|
||||
MIIDdzCCAl+gAwIBAgIQTujwx+1xxXeI5AbzAQ379TANBgkqhkiG9w0BAQsFADAi
|
||||
MQ8wDQYDVQQKEwZEb2NrZXIxDzANBgNVBAMTBkRvY2tlcjAeFw0yMzAzMjcxMTA5
|
||||
NTBaFw0zMzAzMjQxMTA5NTBaMCkxDzANBgNVBAoTBkRvY2tlcjEWMBQGA1UEAxMN
|
||||
bm90YXJ5LXNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPhZ
|
||||
pU7DRK/2nwbTu+kVYhU/XARDleVSiLrQ5RMR1Cz2xC4LWkOEVSj4aCBo85O66JAx
|
||||
p+WRVwoVEU2rdkK3k4983Xr34+7q5Hv4hmwlg6I7QLRRJapEgK5G5RB/9aQntolx
|
||||
h5E0KaoF4PJP25y4FHCUr4td4QyitaICsCpuOAN6XgmE9sM9TBf+AEjTSxwwvgEz
|
||||
DqHvyovl7pA+pQP2oTKBrf6KN8hHDOXmm9gd8ST9yKLrsYWhqExLLPnAD4lQEcKZ
|
||||
29g+iTd4eNoJUXctpuY+3IpqBcQSLq35mNKBP/FQco6g3q26/cB4zWGxTr3jGJqs
|
||||
ms8qdFLGZ2KiBCt+oDMCAwEAAaOBoTCBnjAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0T
|
||||
AQH/BAIwADAfBgNVHSMEGDAWgBTxYMNqgy2wkgmPZL/+bTCTQo6ulTBdBgNVHREE
|
||||
VjBUgg1ub3Rhcnktc2VydmVyggxub3RhcnlzZXJ2ZXKCEmV2aWwtbm90YXJ5LXNl
|
||||
cnZlcoIQZXZpbG5vdGFyeXNlcnZlcoIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3
|
||||
DQEBCwUAA4IBAQCDMjuZnNINFfqstFwhEEvAgWbjYW26ZQxhQffaqDlbMIQkWoXj
|
||||
8inld9bma9Mf5i/GAkUwFqCnEHD4LQ6vDgfAgL+pSOv9VI5SBEuk/gLqvIBUeIRu
|
||||
uHo1jWtll2Fr7eDLVdD4mPRPFC7V6mv6sFa9EN4tBN8eheQxHJvzwnnU7X28prfI
|
||||
/hWnwPWScVvttqBSsq1h2CUpVu2zGVToeCJ9xl4r/NyDtM5TyMgz7RLrer0p8NSu
|
||||
4Qp4ZXtxHDLduWcyMUHLGTprW05yjj9UVq89xfaCOqFSpx5i4oxotYm1PoOacHmN
|
||||
RMp9vaYMAmopoxIEYX6fDg5T3sQ5cidZJEvU
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
sK8jZi441ojEJ7OaggGPheO3mCU=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
50
e2e/testdata/notary-evil/notary-server.key
vendored
50
e2e/testdata/notary-evil/notary-server.key
vendored
@ -1,27 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
33
e2e/testdata/notary-evil/root-ca.cert
vendored
33
e2e/testdata/notary-evil/root-ca.cert
vendored
@ -1,18 +1,19 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
sK8jZi441ojEJ7OaggGPheO3mCU=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
70
e2e/testdata/notary/notary-server.cert
vendored
70
e2e/testdata/notary/notary-server.cert
vendored
@ -1,38 +1,40 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDVDCCAjygAwIBAgIQQReeTsMMrsG9juzWS8eAjjANBgkqhkiG9w0BAQsFADAi
|
||||
MQ8wDQYDVQQKEwZEb2NrZXIxDzANBgNVBAMTBkRvY2tlcjAeFw0yMDA0MDkxNDQ3
|
||||
NTdaFw0yMzAzMjUxNDQ3NTdaMCkxDzANBgNVBAoTBkRvY2tlcjEWMBQGA1UEAxMN
|
||||
bm90YXJ5LXNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKA
|
||||
wO8S9Ux/e4TMOsTkPtCPfpFU+6l6z72uzrFhCNWb0lrTG7hcxwhP6sIesevTOM24
|
||||
GCyvzh+9SMTtdBmSQty4JNElqg9sB6r1tLTeTHo7lMiSiINftctoI1kYg9ni+IO9
|
||||
DVBSb9gQf9dDoizat9VhpbLNm3QXkQSeE9cumen6Pz+fcEtB7lFtIYxEEv/L7+VY
|
||||
QOvhtg0RXiRzfmtSGwFL+FZ9PBz4LOvPnPOLCMQewhR+6cAkO7Jch0ZMjCe8zXXw
|
||||
h8meeIedoevHt0opsr4HHikvr6llwlhWHL+E7zwTPO10xLGd/RIQGGhs8dXhzp1V
|
||||
lw/oe2VJoIFSOaGjRFcCAwEAAaN/MH0wDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB
|
||||
/wQCMAAwXQYDVR0RBFYwVIINbm90YXJ5LXNlcnZlcoIMbm90YXJ5c2VydmVyghJl
|
||||
dmlsLW5vdGFyeS1zZXJ2ZXKCEGV2aWxub3RhcnlzZXJ2ZXKCCWxvY2FsaG9zdIcE
|
||||
fwAAATANBgkqhkiG9w0BAQsFAAOCAQEAgwkZpp4s6reZWs9QatF/x9qWWXIXJzYh
|
||||
6BgzHL3s7UgeZSs0XhgfHYy6SO94ENpbzPADZwue/NjwNXmp7TLjbyUPjSo1DDt7
|
||||
OLG8bQ/hbcPKgMzirTZT36CEsetIBYmfyn39h+ZEIJ30J996/Tgq+X9sG7An2wq3
|
||||
/btn+C/BiMUgGnNxZ8p4n+uJCUKA95uVugdLjeioA+19HgQzrLSkeZUR/wsesq5F
|
||||
iP9k8va2oU3l3MsF079NpfIDl2gtIgXFYWPhyaJCaa+b8irjdoPnhDBuC5p77AWl
|
||||
UTPw/6ENKMMd1Pze6HLpBJAkPP8hTlULKgvuF0pWuGOejipkAKlOBQ==
|
||||
MIIDdzCCAl+gAwIBAgIQTujwx+1xxXeI5AbzAQ379TANBgkqhkiG9w0BAQsFADAi
|
||||
MQ8wDQYDVQQKEwZEb2NrZXIxDzANBgNVBAMTBkRvY2tlcjAeFw0yMzAzMjcxMTA5
|
||||
NTBaFw0zMzAzMjQxMTA5NTBaMCkxDzANBgNVBAoTBkRvY2tlcjEWMBQGA1UEAxMN
|
||||
bm90YXJ5LXNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPhZ
|
||||
pU7DRK/2nwbTu+kVYhU/XARDleVSiLrQ5RMR1Cz2xC4LWkOEVSj4aCBo85O66JAx
|
||||
p+WRVwoVEU2rdkK3k4983Xr34+7q5Hv4hmwlg6I7QLRRJapEgK5G5RB/9aQntolx
|
||||
h5E0KaoF4PJP25y4FHCUr4td4QyitaICsCpuOAN6XgmE9sM9TBf+AEjTSxwwvgEz
|
||||
DqHvyovl7pA+pQP2oTKBrf6KN8hHDOXmm9gd8ST9yKLrsYWhqExLLPnAD4lQEcKZ
|
||||
29g+iTd4eNoJUXctpuY+3IpqBcQSLq35mNKBP/FQco6g3q26/cB4zWGxTr3jGJqs
|
||||
ms8qdFLGZ2KiBCt+oDMCAwEAAaOBoTCBnjAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0T
|
||||
AQH/BAIwADAfBgNVHSMEGDAWgBTxYMNqgy2wkgmPZL/+bTCTQo6ulTBdBgNVHREE
|
||||
VjBUgg1ub3Rhcnktc2VydmVyggxub3RhcnlzZXJ2ZXKCEmV2aWwtbm90YXJ5LXNl
|
||||
cnZlcoIQZXZpbG5vdGFyeXNlcnZlcoIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3
|
||||
DQEBCwUAA4IBAQCDMjuZnNINFfqstFwhEEvAgWbjYW26ZQxhQffaqDlbMIQkWoXj
|
||||
8inld9bma9Mf5i/GAkUwFqCnEHD4LQ6vDgfAgL+pSOv9VI5SBEuk/gLqvIBUeIRu
|
||||
uHo1jWtll2Fr7eDLVdD4mPRPFC7V6mv6sFa9EN4tBN8eheQxHJvzwnnU7X28prfI
|
||||
/hWnwPWScVvttqBSsq1h2CUpVu2zGVToeCJ9xl4r/NyDtM5TyMgz7RLrer0p8NSu
|
||||
4Qp4ZXtxHDLduWcyMUHLGTprW05yjj9UVq89xfaCOqFSpx5i4oxotYm1PoOacHmN
|
||||
RMp9vaYMAmopoxIEYX6fDg5T3sQ5cidZJEvU
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
sK8jZi441ojEJ7OaggGPheO3mCU=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user