mirror of https://github.com/docker/cli.git
Compare commits
59 Commits
0012b18b3b
...
f985c12182
Author | SHA1 | Date |
---|---|---|
piotrostr | f985c12182 | |
Sebastiaan van Stijn | 9c01d924fb | |
Sebastiaan van Stijn | 8c22315e31 | |
Laura Brehm | 13754f6776 | |
Sebastiaan van Stijn | 9eb7b52189 | |
David Karlsson | 172f340112 | |
Sebastiaan van Stijn | 750b8ebcdc | |
Sebastiaan van Stijn | 4a7b04d412 | |
Sebastiaan van Stijn | d77760fe53 | |
Sebastiaan van Stijn | 32b40deb46 | |
Sebastiaan van Stijn | 40833fd296 | |
Sebastiaan van Stijn | 78a7e15032 | |
Sebastiaan van Stijn | 4a71ce02e6 | |
Sebastiaan van Stijn | 7d9ea25564 | |
Sebastiaan van Stijn | 046ac9714c | |
Sebastiaan van Stijn | 762b5a8df3 | |
Sebastiaan van Stijn | 417974cdc3 | |
Sebastiaan van Stijn | bf37e26b33 | |
Sebastiaan van Stijn | 6489a777e5 | |
Sebastiaan van Stijn | 20de861134 | |
Sebastiaan van Stijn | 1448cecba1 | |
Sebastiaan van Stijn | 67458f710d | |
Sebastiaan van Stijn | b45477bffa | |
Noah Silas | 0c999fe95b | |
Sebastiaan van Stijn | 5f1311ae8d | |
Sebastiaan van Stijn | 10c5a57927 | |
Sebastiaan van Stijn | 5e40d288c7 | |
Sebastiaan van Stijn | 9ba73a1a05 | |
Sebastiaan van Stijn | f3cf1b4213 | |
Sebastiaan van Stijn | cae19e3928 | |
Sebastiaan van Stijn | 074d1028b5 | |
Sebastiaan van Stijn | 1dbcce2057 | |
Sebastiaan van Stijn | 1bba009944 | |
Sebastiaan van Stijn | e3942d46a0 | |
Sebastiaan van Stijn | 97ff1b7c0a | |
Sebastiaan van Stijn | 4c85feb4dd | |
Sebastiaan van Stijn | 3b48a57b04 | |
Sebastiaan van Stijn | 36e6c42977 | |
Sebastiaan van Stijn | 84bfa52a6c | |
Sebastiaan van Stijn | 7a94f592ed | |
Sebastiaan van Stijn | ef197f7314 | |
Sebastiaan van Stijn | 02b92c699d | |
Laura Brehm | 2995631498 | |
Paweł Gronowski | fb103cb982 | |
Sebastiaan van Stijn | 42cda38840 | |
Sebastiaan van Stijn | 5e51513a8b | |
Giedrius Jonikas | 0b16070ae6 | |
Sebastiaan van Stijn | 9af049c618 | |
Sebastiaan van Stijn | 745629bd55 | |
Sebastiaan van Stijn | 7451339ab0 | |
Sebastiaan van Stijn | 020f3a7ad9 | |
Sebastiaan van Stijn | aa331e94cc | |
Sebastiaan van Stijn | 1875d9fdcb | |
Harald Albers | e1c5180dba | |
Harald Albers | d4f4cf1418 | |
Sebastiaan van Stijn | 59b90305f7 | |
Sebastiaan van Stijn | 32ff200fe6 | |
Sebastiaan van Stijn | e9ae9f788b | |
Piotr Ostrowski | b1c7307ff1 |
|
@ -62,7 +62,7 @@ jobs:
|
|||
name: Update Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.22.8
|
||||
go-version: 1.23.2
|
||||
-
|
||||
name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
|
|
|
@ -68,7 +68,7 @@ jobs:
|
|||
name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.22.8
|
||||
go-version: 1.23.2
|
||||
-
|
||||
name: Test
|
||||
run: |
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
linters:
|
||||
enable:
|
||||
- bodyclose
|
||||
- copyloopvar # Detects places where loop variables are copied.
|
||||
- depguard
|
||||
- dogsled
|
||||
- dupword # Detects duplicate words.
|
||||
- durationcheck
|
||||
- errchkjson
|
||||
- exportloopref # Detects pointers to enclosing loop variables.
|
||||
- gocritic # Metalinter; detects bugs, performance, and styling issues.
|
||||
- gocyclo
|
||||
- gofumpt # Detects whether code was gofumpt-ed.
|
||||
|
@ -41,6 +41,9 @@ linters:
|
|||
- errcheck
|
||||
|
||||
run:
|
||||
# prevent golangci-lint from deducting the go version to lint for through go.mod,
|
||||
# which causes it to fallback to go1.17 semantics.
|
||||
go: "1.23.2"
|
||||
timeout: 5m
|
||||
|
||||
linters-settings:
|
||||
|
@ -52,6 +55,13 @@ linters-settings:
|
|||
desc: The io/ioutil package has been deprecated, see https://go.dev/doc/go1.16#ioutil
|
||||
gocyclo:
|
||||
min-complexity: 16
|
||||
gosec:
|
||||
excludes:
|
||||
- G104 # G104: Errors unhandled; (TODO: reduce unhandled errors, or explicitly ignore)
|
||||
- G113 # G113: Potential uncontrolled memory consumption in Rat.SetString (CVE-2022-23772); (only affects go < 1.16.14. and go < 1.17.7)
|
||||
- G115 # G115: integer overflow conversion; (TODO: verify these: https://github.com/docker/cli/issues/5584)
|
||||
- G306 # G306: Expect WriteFile permissions to be 0600 or less (too restrictive; also flags "0o644" permissions)
|
||||
- G307 # G307: Deferring unsafe method "*os.File" on type "Close" (also EXC0008); (TODO: evaluate these and fix where needed: G307: Deferring unsafe method "*os.File" on type "Close")
|
||||
govet:
|
||||
enable:
|
||||
- shadow
|
||||
|
@ -87,6 +97,10 @@ issues:
|
|||
# The default exclusion rules are a bit too permissive, so copying the relevant ones below
|
||||
exclude-use-default: false
|
||||
|
||||
# This option has been defined when Go modules was not existed and when the
|
||||
# golangci-lint core was different, this is not something we still recommend.
|
||||
exclude-dirs-use-default: false
|
||||
|
||||
exclude:
|
||||
- parameter .* always receives
|
||||
|
||||
|
@ -104,6 +118,9 @@ issues:
|
|||
#
|
||||
# These exclusion patterns are copied from the default excluses at:
|
||||
# https://github.com/golangci/golangci-lint/blob/v1.44.0/pkg/config/issues.go#L10-L104
|
||||
#
|
||||
# The default list of exclusions can be found at:
|
||||
# https://golangci-lint.run/usage/false-positives/#default-exclusions
|
||||
|
||||
# EXC0001
|
||||
- text: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*print(f|ln)?|os\\.(Un)?Setenv). is not checked"
|
||||
|
@ -121,11 +138,6 @@ issues:
|
|||
- text: "Subprocess launch(ed with variable|ing should be audited)"
|
||||
linters:
|
||||
- gosec
|
||||
# EXC0008
|
||||
# TODO: evaluate these and fix where needed: G307: Deferring unsafe method "*os.File" on type "Close" (gosec)
|
||||
- text: "G307"
|
||||
linters:
|
||||
- gosec
|
||||
# EXC0009
|
||||
- text: "(Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less)"
|
||||
linters:
|
||||
|
@ -135,26 +147,6 @@ issues:
|
|||
linters:
|
||||
- gosec
|
||||
|
||||
# G113 Potential uncontrolled memory consumption in Rat.SetString (CVE-2022-23772)
|
||||
# only affects gp < 1.16.14. and go < 1.17.7
|
||||
- text: "G113"
|
||||
linters:
|
||||
- gosec
|
||||
# TODO: G104: Errors unhandled. (gosec)
|
||||
- text: "G104"
|
||||
linters:
|
||||
- gosec
|
||||
# Looks like the match in "EXC0007" above doesn't catch this one
|
||||
# TODO: consider upstreaming this to golangci-lint's default exclusion rules
|
||||
- text: "G204: Subprocess launched with a potential tainted input or cmd arguments"
|
||||
linters:
|
||||
- gosec
|
||||
# Looks like the match in "EXC0009" above doesn't catch this one
|
||||
# TODO: consider upstreaming this to golangci-lint's default exclusion rules
|
||||
- text: "G306: Expect WriteFile permissions to be 0600 or less"
|
||||
linters:
|
||||
- gosec
|
||||
|
||||
# TODO: make sure all packages have a description. Currently, there's 67 packages without.
|
||||
- text: "package-comments: should have a package comment"
|
||||
linters:
|
||||
|
|
|
@ -4,7 +4,7 @@ ARG BASE_VARIANT=alpine
|
|||
ARG ALPINE_VERSION=3.20
|
||||
ARG BASE_DEBIAN_DISTRO=bookworm
|
||||
|
||||
ARG GO_VERSION=1.22.8
|
||||
ARG GO_VERSION=1.23.2
|
||||
ARG XX_VERSION=1.5.0
|
||||
ARG GOVERSIONINFO_VERSION=v1.3.0
|
||||
ARG GOTESTSUM_VERSION=v1.10.0
|
||||
|
|
|
@ -17,5 +17,5 @@ func (c *candidate) Path() string {
|
|||
}
|
||||
|
||||
func (c *candidate) Metadata() ([]byte, error) {
|
||||
return exec.Command(c.path, MetadataSubcommandName).Output()
|
||||
return exec.Command(c.path, MetadataSubcommandName).Output() // #nosec G204 -- ignore "Subprocess launched with a potential tainted input or cmd arguments"
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) (err e
|
|||
return
|
||||
}
|
||||
for _, p := range plugins {
|
||||
p := p
|
||||
vendor := p.Vendor
|
||||
if vendor == "" {
|
||||
vendor = "unknown"
|
||||
|
|
|
@ -240,7 +240,8 @@ func PluginRunCommand(dockerCli command.Cli, name string, rootcmd *cobra.Command
|
|||
// TODO: why are we not returning plugin.Err?
|
||||
return nil, errPluginNotFound(name)
|
||||
}
|
||||
cmd := exec.Command(plugin.Path, args...)
|
||||
cmd := exec.Command(plugin.Path, args...) // #nosec G204 -- ignore "Subprocess launched with a potential tainted input or cmd arguments"
|
||||
|
||||
// Using dockerCli.{In,Out,Err}() here results in a hang until something is input.
|
||||
// See: - https://github.com/golang/go/issues/10338
|
||||
// - https://github.com/golang/go/commit/d000e8742a173aa0659584aa01b7ba2834ba28ab
|
||||
|
|
|
@ -112,7 +112,7 @@ func (p *Plugin) RunHook(ctx context.Context, hookData HookPluginData) ([]byte,
|
|||
return nil, wrapAsPluginError(err, "failed to marshall hook data")
|
||||
}
|
||||
|
||||
pCmd := exec.CommandContext(ctx, p.Path, p.Name, HookSubcommandName, string(hDataBytes))
|
||||
pCmd := exec.CommandContext(ctx, p.Path, p.Name, HookSubcommandName, string(hDataBytes)) // #nosec G204 -- ignore "Subprocess launched with a potential tainted input or cmd arguments"
|
||||
pCmd.Env = os.Environ()
|
||||
pCmd.Env = append(pCmd.Env, ReexecEnvvar+"="+os.Args[0])
|
||||
hookCmdOutput, err := pCmd.Output()
|
||||
|
|
|
@ -187,19 +187,18 @@ func TestInitializeFromClient(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
for _, testcase := range testcases {
|
||||
testcase := testcase
|
||||
t.Run(testcase.doc, func(t *testing.T) {
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
apiclient := &fakeClient{
|
||||
pingFunc: testcase.pingFunc,
|
||||
pingFunc: tc.pingFunc,
|
||||
version: defaultVersion,
|
||||
}
|
||||
|
||||
cli := &DockerCli{client: apiclient}
|
||||
err := cli.Initialize(flags.NewClientOptions())
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, cli.ServerInfo(), testcase.expectedServer)
|
||||
assert.Equal(t, apiclient.negotiated, testcase.negotiated)
|
||||
assert.DeepEqual(t, cli.ServerInfo(), tc.expectedServer)
|
||||
assert.Equal(t, apiclient.negotiated, tc.negotiated)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -277,10 +276,9 @@ func TestExperimentalCLI(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
for _, testcase := range testcases {
|
||||
testcase := testcase
|
||||
t.Run(testcase.doc, func(t *testing.T) {
|
||||
dir := fs.NewDir(t, testcase.doc, fs.WithFile("config.json", testcase.configfile))
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
dir := fs.NewDir(t, tc.doc, fs.WithFile("config.json", tc.configfile))
|
||||
defer dir.Remove()
|
||||
apiclient := &fakeClient{
|
||||
version: defaultVersion,
|
||||
|
|
|
@ -150,7 +150,6 @@ func TestCompleteContainerNames(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
if tc.showIDs {
|
||||
t.Setenv("DOCKER_COMPLETION_SHOW_CONTAINER_IDS", "yes")
|
||||
|
@ -227,7 +226,6 @@ func TestCompleteImageNames(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
comp := ImageNames(fakeCLI{&fakeClient{
|
||||
imageListFunc: func(options image.ListOptions) ([]image.Summary, error) {
|
||||
|
@ -273,7 +271,6 @@ func TestCompleteNetworkNames(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
comp := NetworkNames(fakeCLI{&fakeClient{
|
||||
networkListFunc: func(ctx context.Context, options network.ListOptions) ([]network.Summary, error) {
|
||||
|
@ -331,7 +328,6 @@ func TestCompleteVolumeNames(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
comp := VolumeNames(fakeCLI{&fakeClient{
|
||||
volumeListFunc: func(filter filters.Args) (volume.ListResponse, error) {
|
||||
|
|
|
@ -43,7 +43,6 @@ func TestConfigCreateErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.expectedError, func(t *testing.T) {
|
||||
cmd := newConfigCreateCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
|
|
|
@ -61,7 +61,6 @@ id_rsa
|
|||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
|
|
@ -73,7 +73,6 @@ func TestNewAttachCommandErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := NewAttachCommand(test.NewFakeCli(&fakeClient{inspectFunc: tc.containerInspectFunc}))
|
||||
cmd.SetOut(io.Discard)
|
||||
|
|
|
@ -178,7 +178,6 @@ func TestSplitCpArg(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
if tc.os == "windows" && runtime.GOOS != "windows" {
|
||||
t.Skip("skipping windows test on non-windows platform")
|
||||
|
|
|
@ -113,7 +113,6 @@ func TestCreateContainerImagePullPolicy(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.PullPolicy, func(t *testing.T) {
|
||||
pullCounter := 0
|
||||
|
||||
|
@ -176,7 +175,6 @@ func TestCreateContainerImagePullPolicyInvalid(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.PullPolicy, func(t *testing.T) {
|
||||
dockerCli := test.NewFakeCli(&fakeClient{})
|
||||
err := runCreate(
|
||||
|
@ -207,7 +205,6 @@ func TestCreateContainerValidateFlags(t *testing.T) {
|
|||
expectedErr: `invalid argument "STDINFO" for "-a, --attach" flag: valid streams are STDIN, STDOUT and STDERR`,
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := NewCreateCommand(test.NewFakeCli(&fakeClient{}))
|
||||
cmd.SetOut(io.Discard)
|
||||
|
@ -251,7 +248,6 @@ func TestNewCreateCommandWithContentTrustErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
fakeCLI := test.NewFakeCli(&fakeClient{
|
||||
createContainerFunc: func(config *container.Config,
|
||||
hostConfig *container.HostConfig,
|
||||
|
@ -312,7 +308,6 @@ func TestNewCreateCommandWithWarnings(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
fakeCLI := test.NewFakeCli(&fakeClient{
|
||||
createContainerFunc: func(config *container.Config,
|
||||
|
|
|
@ -47,7 +47,6 @@ D: /usr/app/old_app.js
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
out := bytes.NewBufferString("")
|
||||
tc.context.Output = out
|
||||
|
|
|
@ -178,7 +178,6 @@ container2 -- --
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
@ -223,7 +222,6 @@ func TestContainerStatsContextWriteWithNoStats(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
err := statsFormatWrite(tc.context, []StatsEntry{}, "linux", false)
|
||||
assert.NilError(t, err)
|
||||
|
@ -265,7 +263,6 @@ func TestContainerStatsContextWriteWithNoStatsWindows(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
err := statsFormatWrite(tc.context, []StatsEntry{}, "windows", false)
|
||||
assert.NilError(t, err)
|
||||
|
|
|
@ -42,7 +42,7 @@ func NewPsCommand(dockerCLI command.Cli) *cobra.Command {
|
|||
},
|
||||
Annotations: map[string]string{
|
||||
"category-top": "3",
|
||||
"aliases": "docker container ls, docker container list, docker container ps, docker ps",
|
||||
"aliases": "docker container ls, docker container list, docker container ps, docker ps, docker containers",
|
||||
},
|
||||
ValidArgsFunction: completion.NoComplete,
|
||||
}
|
||||
|
|
|
@ -277,7 +277,6 @@ func TestContainerListFormatSizeSetsOption(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
containerListFunc: func(options container.ListOptions) ([]container.Summary, error) {
|
||||
|
|
|
@ -23,7 +23,6 @@ import (
|
|||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/go-connections/nat"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/pflag"
|
||||
cdi "tags.cncf.io/container-device-interface/pkg/parser"
|
||||
)
|
||||
|
@ -364,10 +363,6 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
|
|||
return nil, errors.Errorf("invalid value: %d. Valid memory swappiness range is 0-100", swappiness)
|
||||
}
|
||||
|
||||
mounts := copts.mounts.Value()
|
||||
if len(mounts) > 0 && copts.volumeDriver != "" {
|
||||
logrus.Warn("`--volume-driver` is ignored for volumes specified via `--mount`. Use `--mount type=volume,volume-driver=...` instead.")
|
||||
}
|
||||
var binds []string
|
||||
volumes := copts.volumes.GetMap()
|
||||
// add any bind targets to the list of container volumes
|
||||
|
@ -697,7 +692,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
|
|||
Tmpfs: tmpfs,
|
||||
Sysctls: copts.sysctls.GetAll(),
|
||||
Runtime: copts.runtime,
|
||||
Mounts: mounts,
|
||||
Mounts: copts.mounts.Value(),
|
||||
MaskedPaths: maskedPaths,
|
||||
ReadonlyPaths: readonlyPaths,
|
||||
Annotations: copts.annotations.GetAll(),
|
||||
|
@ -767,7 +762,6 @@ func parseNetworkOpts(copts *containerOptions) (map[string]*networktypes.Endpoin
|
|||
}
|
||||
|
||||
for i, n := range copts.netMode.Value() {
|
||||
n := n
|
||||
if container.NetworkMode(n.Target).IsUserDefined() {
|
||||
hasUserDefined = true
|
||||
} else {
|
||||
|
|
|
@ -126,7 +126,6 @@ func TestParseRunAttach(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.input, func(t *testing.T) {
|
||||
config, _, _ := mustParse(t, tc.input)
|
||||
assert.Equal(t, config.AttachStdin, tc.expected.AttachStdin)
|
||||
|
@ -802,7 +801,6 @@ func TestParseRestartPolicy(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.input, func(t *testing.T) {
|
||||
_, hostConfig, _, err := parseRun([]string{"--restart=" + tc.input, "img", "cmd"})
|
||||
if tc.expectedErr != "" {
|
||||
|
|
|
@ -43,7 +43,6 @@ func TestNewPortCommandOutput(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
inspectFunc: func(string) (container.InspectResponse, error) {
|
||||
|
|
|
@ -58,7 +58,6 @@ func TestRestart(t *testing.T) {
|
|||
expectedErr: "conflicting options: cannot specify both --timeout and --time",
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var restarted []string
|
||||
mutex := new(sync.Mutex)
|
||||
|
|
|
@ -23,7 +23,6 @@ func TestRemoveForce(t *testing.T) {
|
|||
{name: "without force", args: []string{"nosuchcontainer", "mycontainer"}, expectedErr: "no such container"},
|
||||
{name: "with force", args: []string{"--force", "nosuchcontainer", "mycontainer"}, expectedErr: ""},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var removed []string
|
||||
mutex := new(sync.Mutex)
|
||||
|
|
|
@ -35,7 +35,6 @@ func TestRunValidateFlags(t *testing.T) {
|
|||
expectedErr: "conflicting options: cannot specify both --attach and --detach",
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := NewRunCommand(test.NewFakeCli(&fakeClient{}))
|
||||
cmd.SetOut(io.Discard)
|
||||
|
@ -245,7 +244,6 @@ func TestRunCommandWithContentTrustErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
fakeCLI := test.NewFakeCli(&fakeClient{
|
||||
createContainerFunc: func(config *container.Config,
|
||||
|
@ -286,7 +284,6 @@ func TestRunContainerImagePullPolicyInvalid(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.PullPolicy, func(t *testing.T) {
|
||||
dockerCli := test.NewFakeCli(&fakeClient{})
|
||||
err := runRun(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -264,31 +265,40 @@ func RunStats(ctx context.Context, dockerCLI command.Cli, options *StatsOptions)
|
|||
// so we unlikely hit this code in practice.
|
||||
daemonOSType = dockerCLI.ServerInfo().OSType
|
||||
}
|
||||
|
||||
// Buffer to store formatted stats text.
|
||||
// Once formatted, it will be printed in one write to avoid screen flickering.
|
||||
var statsTextBuffer bytes.Buffer
|
||||
|
||||
statsCtx := formatter.Context{
|
||||
Output: dockerCLI.Out(),
|
||||
Output: &statsTextBuffer,
|
||||
Format: NewStatsFormat(format, daemonOSType),
|
||||
}
|
||||
cleanScreen := func() {
|
||||
if !options.NoStream {
|
||||
_, _ = fmt.Fprint(dockerCLI.Out(), "\033[2J")
|
||||
_, _ = fmt.Fprint(dockerCLI.Out(), "\033[H")
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
ticker := time.NewTicker(500 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
cleanScreen()
|
||||
var ccStats []StatsEntry
|
||||
cStats.mu.RLock()
|
||||
for _, c := range cStats.cs {
|
||||
ccStats = append(ccStats, c.GetStatistics())
|
||||
}
|
||||
cStats.mu.RUnlock()
|
||||
|
||||
if !options.NoStream {
|
||||
// Start by clearing the screen and moving the cursor to the top-left
|
||||
_, _ = fmt.Fprint(&statsTextBuffer, "\033[2J\033[H")
|
||||
}
|
||||
|
||||
if err = statsFormatWrite(statsCtx, ccStats, daemonOSType, !options.NoTrunc); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprint(dockerCLI.Out(), statsTextBuffer.String())
|
||||
|
||||
statsTextBuffer.Reset()
|
||||
|
||||
if len(cStats.cs) == 0 && !showAll {
|
||||
break
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ func TestStop(t *testing.T) {
|
|||
expectedErr: "conflicting options: cannot specify both --timeout and --time",
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var stopped []string
|
||||
mutex := new(sync.Mutex)
|
||||
|
|
|
@ -94,7 +94,6 @@ func TestCreate(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.options.Name, func(t *testing.T) {
|
||||
err := RunCreate(cli, &tc.options)
|
||||
if tc.expecterErr == "" {
|
||||
|
@ -164,25 +163,24 @@ func TestCreateFromContext(t *testing.T) {
|
|||
|
||||
cli.SetCurrentContext("dummy")
|
||||
|
||||
for _, c := range cases {
|
||||
c := c
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli.ResetOutputBuffers()
|
||||
err := RunCreate(cli, &CreateOptions{
|
||||
From: "original",
|
||||
Name: c.name,
|
||||
Description: c.description,
|
||||
Docker: c.docker,
|
||||
Name: tc.name,
|
||||
Description: tc.description,
|
||||
Docker: tc.docker,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assertContextCreateLogging(t, cli, c.name)
|
||||
newContext, err := cli.ContextStore().GetMetadata(c.name)
|
||||
assertContextCreateLogging(t, cli, tc.name)
|
||||
newContext, err := cli.ContextStore().GetMetadata(tc.name)
|
||||
assert.NilError(t, err)
|
||||
newContextTyped, err := command.GetDockerContext(newContext)
|
||||
assert.NilError(t, err)
|
||||
dockerEndpoint, err := docker.EndpointFromContext(newContext)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, newContextTyped.Description, c.expectedDescription)
|
||||
assert.Equal(t, newContextTyped.Description, tc.expectedDescription)
|
||||
assert.Equal(t, dockerEndpoint.Host, "tcp://42.42.42.42:2375")
|
||||
})
|
||||
}
|
||||
|
@ -219,23 +217,22 @@ func TestCreateFromCurrent(t *testing.T) {
|
|||
|
||||
cli.SetCurrentContext("original")
|
||||
|
||||
for _, c := range cases {
|
||||
c := c
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli.ResetOutputBuffers()
|
||||
err := RunCreate(cli, &CreateOptions{
|
||||
Name: c.name,
|
||||
Description: c.description,
|
||||
Name: tc.name,
|
||||
Description: tc.description,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assertContextCreateLogging(t, cli, c.name)
|
||||
newContext, err := cli.ContextStore().GetMetadata(c.name)
|
||||
assertContextCreateLogging(t, cli, tc.name)
|
||||
newContext, err := cli.ContextStore().GetMetadata(tc.name)
|
||||
assert.NilError(t, err)
|
||||
newContextTyped, err := command.GetDockerContext(newContext)
|
||||
assert.NilError(t, err)
|
||||
dockerEndpoint, err := docker.EndpointFromContext(newContext)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, newContextTyped.Description, c.expectedDescription)
|
||||
assert.Equal(t, newContextTyped.Description, tc.expectedDescription)
|
||||
assert.Equal(t, dockerEndpoint.Host, "tcp://42.42.42.42:2375")
|
||||
})
|
||||
}
|
||||
|
|
|
@ -346,7 +346,6 @@ size: 0B
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
@ -411,7 +410,6 @@ func TestContainerContextWriteWithNoContainers(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
err := ContainerWrite(tc.context, containers)
|
||||
assert.NilError(t, err)
|
||||
|
|
|
@ -106,7 +106,6 @@ Build Cache 0 0 0B 0B
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
|
|
@ -304,7 +304,6 @@ image_id: imageID3
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
@ -365,7 +364,6 @@ func TestImageContextWriteWithNoImage(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
err := ImageWrite(tc.context, images)
|
||||
assert.NilError(t, err)
|
||||
|
|
|
@ -131,7 +131,6 @@ foobar_bar
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
|
|
@ -255,7 +255,6 @@ imageID6 17 years ago /bin/bash echo 183MB
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
err := HistoryWrite(tc.context, true, histories)
|
||||
assert.NilError(t, err)
|
||||
|
|
|
@ -42,7 +42,6 @@ func TestNewHistoryCommandErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := NewHistoryCommand(test.NewFakeCli(&fakeClient{imageHistoryFunc: tc.imageHistoryFunc}))
|
||||
cmd.SetOut(io.Discard)
|
||||
|
@ -109,7 +108,6 @@ func TestNewHistoryCommandSuccess(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Set to UTC timezone as timestamps in output are
|
||||
// printed in the current timezone
|
||||
|
|
|
@ -98,7 +98,6 @@ func TestNewImportCommandSuccess(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := NewImportCommand(test.NewFakeCli(&fakeClient{imageImportFunc: tc.imageImportFunc}))
|
||||
cmd.SetOut(io.Discard)
|
||||
|
|
|
@ -25,7 +25,6 @@ func TestNewInspectCommandErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := newInspectCommand(test.NewFakeCli(&fakeClient{}))
|
||||
cmd.SetOut(io.Discard)
|
||||
|
@ -79,7 +78,6 @@ func TestNewInspectCommandSuccess(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
imageInspectInvocationCount = 0
|
||||
cli := test.NewFakeCli(&fakeClient{imageInspectFunc: tc.imageInspectFunc})
|
||||
|
|
|
@ -35,7 +35,6 @@ func TestNewImagesCommandErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := NewImagesCommand(test.NewFakeCli(&fakeClient{imageListFunc: tc.imageListFunc}))
|
||||
cmd.SetOut(io.Discard)
|
||||
|
@ -83,7 +82,6 @@ func TestNewImagesCommandSuccess(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{imageListFunc: tc.imageListFunc})
|
||||
cli.SetConfigFile(&configfile.ConfigFile{ImagesFormat: tc.imageFormat})
|
||||
|
|
|
@ -52,7 +52,6 @@ func TestNewLoadCommandErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{imageLoadFunc: tc.imageLoadFunc})
|
||||
cli.In().SetIsTerminal(tc.isTerminalIn)
|
||||
|
@ -116,7 +115,6 @@ func TestNewLoadCommandSuccess(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{imageLoadFunc: tc.imageLoadFunc})
|
||||
cmd := NewLoadCommand(cli)
|
||||
|
|
|
@ -39,7 +39,6 @@ func TestNewPruneCommandErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := NewPruneCommand(test.NewFakeCli(&fakeClient{
|
||||
imagesPruneFunc: tc.imagesPruneFunc,
|
||||
|
@ -98,7 +97,6 @@ func TestNewPruneCommandSuccess(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{imagesPruneFunc: tc.imagesPruneFunc})
|
||||
// when prompted, answer "Y" to confirm the prune.
|
||||
|
|
|
@ -38,7 +38,6 @@ func TestNewPullCommandErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cmd := NewPullCommand(cli)
|
||||
|
@ -73,7 +72,6 @@ func TestNewPullCommandSuccess(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
imagePullFunc: func(ref string, options image.PullOptions) (io.ReadCloser, error) {
|
||||
|
@ -119,7 +117,6 @@ func TestNewPullCommandWithContentTrustErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
imagePullFunc: func(ref string, options image.PullOptions) (io.ReadCloser, error) {
|
||||
|
|
|
@ -38,7 +38,6 @@ func TestNewPushCommandErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{imagePushFunc: tc.imagePushFunc})
|
||||
cmd := NewPushCommand(cli)
|
||||
|
@ -68,7 +67,6 @@ func TestNewPushCommandSuccess(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
imagePushFunc: func(ref string, options image.PushOptions) (io.ReadCloser, error) {
|
||||
|
|
|
@ -62,7 +62,6 @@ func TestNewRemoveCommandErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := NewRemoveCommand(test.NewFakeCli(&fakeClient{
|
||||
imageRemoveFunc: tc.imageRemoveFunc,
|
||||
|
@ -121,7 +120,6 @@ func TestNewRemoveCommandSuccess(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{imageRemoveFunc: tc.imageRemoveFunc})
|
||||
cmd := NewRemoveCommand(cli)
|
||||
|
|
|
@ -59,7 +59,6 @@ func TestNewSaveCommandErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{imageSaveFunc: tc.imageSaveFunc})
|
||||
cli.Out().SetIsTerminal(tc.isTerminal)
|
||||
|
@ -113,7 +112,6 @@ func TestNewSaveCommandSuccess(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(strings.Join(tc.args, " "), func(t *testing.T) {
|
||||
cmd := NewSaveCommand(test.NewFakeCli(&fakeClient{
|
||||
imageSaveFunc: tc.imageSaveFunc,
|
||||
|
|
|
@ -56,7 +56,6 @@ func runTree(ctx context.Context, dockerCLI command.Cli, opts treeOptions) error
|
|||
continue
|
||||
}
|
||||
|
||||
im := im
|
||||
sub := subImage{
|
||||
Platform: platforms.Format(im.ImageData.Platform),
|
||||
Available: im.Available,
|
||||
|
|
|
@ -31,7 +31,6 @@ func TestManifestCreateErrors(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.expectedError, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(nil)
|
||||
cmd := newCreateListCommand(cli)
|
||||
|
|
|
@ -218,7 +218,6 @@ func TestNetworkCreateIPv6(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
networkCreateFunc: func(ctx context.Context, name string, createBody network.CreateOptions) (network.CreateResponse, error) {
|
||||
|
|
|
@ -161,7 +161,6 @@ foobar_bar 2017-01-01 00:00:00 +0000 UTC
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
|
|
@ -83,7 +83,6 @@ func TestNetworkList(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{networkListFunc: tc.networkListFunc})
|
||||
cmd := newListCommand(cli)
|
||||
|
|
|
@ -63,7 +63,6 @@ func TestNetworkRemoveForce(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
fakeCli := test.NewFakeCli(&fakeClient{
|
||||
networkRemoveFunc: func(ctx context.Context, networkID string) error {
|
||||
|
|
|
@ -202,7 +202,6 @@ foobar_boo Unknown
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
|
|
@ -106,7 +106,6 @@ func TestNodeInspectPretty(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
nodeInspectFunc: tc.nodeInspectFunc,
|
||||
|
|
|
@ -134,7 +134,6 @@ func TestNodePs(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
infoFunc: tc.infoFunc,
|
||||
|
|
|
@ -131,7 +131,6 @@ foobar_bar
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
|
|
@ -66,7 +66,6 @@ func TestInspectErrors(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{pluginInspectFunc: tc.inspectFunc})
|
||||
cmd := newInspectCommand(cli)
|
||||
|
@ -138,7 +137,6 @@ func TestInspect(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{pluginInspectFunc: tc.inspectFunc})
|
||||
cmd := newInspectCommand(cli)
|
||||
|
|
|
@ -54,7 +54,6 @@ func TestInstallErrors(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{pluginInstallFunc: tc.installFunc})
|
||||
cmd := newInstallCommand(cli)
|
||||
|
@ -94,7 +93,6 @@ func TestInstallContentTrustErrors(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
pluginInstallFunc: func(name string, options types.PluginInstallOptions) (io.ReadCloser, error) {
|
||||
|
@ -138,7 +136,6 @@ func TestInstall(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{pluginInstallFunc: tc.installFunc})
|
||||
cmd := newInstallCommand(cli)
|
||||
|
|
|
@ -46,7 +46,6 @@ func TestListErrors(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{pluginListFunc: tc.listFunc})
|
||||
cmd := newListCommand(cli)
|
||||
|
@ -166,7 +165,6 @@ func TestList(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{pluginListFunc: tc.listFunc})
|
||||
cmd := newListCommand(cli)
|
||||
|
|
|
@ -203,7 +203,6 @@ result2 5
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
err := SearchWrite(formatter.Context{Format: tc.format, Output: &out}, results)
|
||||
|
|
|
@ -61,7 +61,6 @@ id_rsa
|
|||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
|
|
@ -93,7 +93,6 @@ func TestSecretInspectWithoutFormat(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretInspectFunc: tc.secretInspectFunc,
|
||||
|
@ -132,7 +131,6 @@ func TestSecretInspectWithFormat(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
secretInspectFunc: tc.secretInspectFunc,
|
||||
|
|
|
@ -223,7 +223,6 @@ zarp2
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
|
|
@ -168,7 +168,6 @@ func TestServiceListServiceStatus(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range matrix {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
if tc.cluster == nil {
|
||||
tc.cluster = generateCluster(t, tc.opts)
|
||||
|
|
|
@ -50,7 +50,6 @@ func TestCredentialSpecOpt(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var cs credentialSpecOpt
|
||||
|
||||
|
|
|
@ -91,7 +91,6 @@ func TestRollbackWithErrors(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := newRollbackCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
|
|
|
@ -1058,7 +1058,6 @@ func updatePorts(flags *pflag.FlagSet, portConfig *[]swarm.PortConfig) error {
|
|||
|
||||
// Build the current list of portConfig
|
||||
for _, entry := range *portConfig {
|
||||
entry := entry
|
||||
if _, ok := portSet[portConfigToString(&entry)]; !ok {
|
||||
portSet[portConfigToString(&entry)] = entry
|
||||
}
|
||||
|
@ -1086,7 +1085,6 @@ portLoop:
|
|||
ports := flags.Lookup(flagPublishAdd).Value.(*opts.PortOpt).Value()
|
||||
|
||||
for _, port := range ports {
|
||||
port := port
|
||||
if _, ok := portSet[portConfigToString(&port)]; ok {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -1690,7 +1690,6 @@ func TestUpdateUlimits(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
svc := swarm.ServiceSpec{
|
||||
TaskTemplate: swarm.TaskSpec{
|
||||
|
|
|
@ -51,7 +51,6 @@ bar
|
|||
{Name: "bar", Services: 1},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
|
|
@ -48,7 +48,6 @@ func TestListErrors(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.expectedError, func(t *testing.T) {
|
||||
cmd := newListCommand(test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: tc.serviceListFunc,
|
||||
|
@ -104,7 +103,6 @@ func TestStackList(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
var services []swarm.Service
|
||||
for _, name := range tc.serviceNames {
|
||||
|
|
|
@ -40,7 +40,6 @@ func TestStackPsErrors(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.expectedError, func(t *testing.T) {
|
||||
cmd := newPsCommand(test.NewFakeCli(&fakeClient{
|
||||
taskListFunc: tc.taskListFunc,
|
||||
|
@ -160,7 +159,6 @@ func TestStackPs(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
taskListFunc: tc.taskListFunc,
|
||||
|
|
|
@ -67,7 +67,6 @@ func TestStackServicesErrors(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.expectedError, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: tc.serviceListFunc,
|
||||
|
|
|
@ -88,7 +88,6 @@ func TestServiceUpdateResolveImageChanged(t *testing.T) {
|
|||
ctx := context.Background()
|
||||
|
||||
for _, tc := range testcases {
|
||||
tc := tc
|
||||
t.Run(tc.image, func(t *testing.T) {
|
||||
spec := map[string]swarm.ServiceSpec{
|
||||
"myservice": {
|
||||
|
|
|
@ -63,7 +63,6 @@ func TestSwarmInitErrorOnAPIFailure(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := newInitCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
|
|
|
@ -48,7 +48,6 @@ func TestSwarmJoinErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := newJoinCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
|
@ -93,7 +92,6 @@ func TestSwarmJoin(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
infoFunc: tc.infoFunc,
|
||||
|
|
|
@ -87,7 +87,6 @@ func TestSwarmJoinTokenErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
swarmInspectFunc: tc.swarmInspectFunc,
|
||||
|
@ -198,7 +197,6 @@ func TestSwarmJoinToken(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
swarmInspectFunc: tc.swarmInspectFunc,
|
||||
|
|
|
@ -32,7 +32,6 @@ func TestSwarmLeaveErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := newLeaveCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
|
|
|
@ -80,7 +80,6 @@ func TestSwarmUnlockKeyErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := newUnlockKeyCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
|
@ -158,7 +157,6 @@ func TestSwarmUnlockKey(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
swarmInspectFunc: tc.swarmInspectFunc,
|
||||
|
|
|
@ -64,7 +64,6 @@ func TestSwarmUnlockErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := newUnlockCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
|
|
|
@ -65,7 +65,6 @@ func TestSwarmUpdateErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := newUpdateCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
|
@ -169,7 +168,6 @@ func TestSwarmUpdate(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
swarmInspectFunc: tc.swarmInspectFunc,
|
||||
|
|
|
@ -7,7 +7,11 @@ import (
|
|||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/api/types/system"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
|
@ -15,22 +19,27 @@ type fakeClient struct {
|
|||
client.Client
|
||||
|
||||
version string
|
||||
serverVersion func(ctx context.Context) (types.Version, error)
|
||||
eventsFn func(context.Context, events.ListOptions) (<-chan events.Message, <-chan error)
|
||||
containerListFunc func(context.Context, container.ListOptions) ([]container.Summary, error)
|
||||
containerPruneFunc func(ctx context.Context, pruneFilters filters.Args) (container.PruneReport, error)
|
||||
eventsFn func(context.Context, events.ListOptions) (<-chan events.Message, <-chan error)
|
||||
imageListFunc func(ctx context.Context, options image.ListOptions) ([]image.Summary, error)
|
||||
infoFunc func(ctx context.Context) (system.Info, error)
|
||||
networkListFunc func(ctx context.Context, options network.ListOptions) ([]network.Summary, error)
|
||||
networkPruneFunc func(ctx context.Context, pruneFilter filters.Args) (network.PruneReport, error)
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServerVersion(ctx context.Context) (types.Version, error) {
|
||||
return cli.serverVersion(ctx)
|
||||
nodeListFunc func(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error)
|
||||
serverVersion func(ctx context.Context) (types.Version, error)
|
||||
volumeListFunc func(ctx context.Context, options volume.ListOptions) (volume.ListResponse, error)
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ClientVersion() string {
|
||||
return cli.version
|
||||
}
|
||||
|
||||
func (cli *fakeClient) Events(ctx context.Context, opts events.ListOptions) (<-chan events.Message, <-chan error) {
|
||||
return cli.eventsFn(ctx, opts)
|
||||
func (cli *fakeClient) ContainerList(ctx context.Context, options container.ListOptions) ([]container.Summary, error) {
|
||||
if cli.containerListFunc != nil {
|
||||
return cli.containerListFunc(ctx, options)
|
||||
}
|
||||
return []container.Summary{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (container.PruneReport, error) {
|
||||
|
@ -40,9 +49,52 @@ func (cli *fakeClient) ContainersPrune(ctx context.Context, pruneFilters filters
|
|||
return container.PruneReport{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) Events(ctx context.Context, opts events.ListOptions) (<-chan events.Message, <-chan error) {
|
||||
return cli.eventsFn(ctx, opts)
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ImageList(ctx context.Context, options image.ListOptions) ([]image.Summary, error) {
|
||||
if cli.imageListFunc != nil {
|
||||
return cli.imageListFunc(ctx, options)
|
||||
}
|
||||
return []image.Summary{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) Info(ctx context.Context) (system.Info, error) {
|
||||
if cli.infoFunc != nil {
|
||||
return cli.infoFunc(ctx)
|
||||
}
|
||||
return system.Info{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NetworkList(ctx context.Context, options network.ListOptions) ([]network.Summary, error) {
|
||||
if cli.networkListFunc != nil {
|
||||
return cli.networkListFunc(ctx, options)
|
||||
}
|
||||
return []network.Summary{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NetworksPrune(ctx context.Context, pruneFilter filters.Args) (network.PruneReport, error) {
|
||||
if cli.networkPruneFunc != nil {
|
||||
return cli.networkPruneFunc(ctx, pruneFilter)
|
||||
}
|
||||
return network.PruneReport{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) {
|
||||
if cli.nodeListFunc != nil {
|
||||
return cli.nodeListFunc(ctx, options)
|
||||
}
|
||||
return []swarm.Node{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServerVersion(ctx context.Context) (types.Version, error) {
|
||||
return cli.serverVersion(ctx)
|
||||
}
|
||||
|
||||
func (cli *fakeClient) VolumeList(ctx context.Context, options volume.ListOptions) (volume.ListResponse, error) {
|
||||
if cli.volumeListFunc != nil {
|
||||
return cli.volumeListFunc(ctx, options)
|
||||
}
|
||||
return volume.ListResponse{}, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/docker/cli/cli/command/completion"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
eventFilters = []string{"container", "daemon", "event", "image", "label", "network", "node", "scope", "type", "volume"}
|
||||
|
||||
// eventTypes is a list of all event types.
|
||||
// This should be moved to the moby codebase once its usage is consolidated here.
|
||||
eventTypes = []events.Type{
|
||||
events.BuilderEventType,
|
||||
events.ConfigEventType,
|
||||
events.ContainerEventType,
|
||||
events.DaemonEventType,
|
||||
events.ImageEventType,
|
||||
events.NetworkEventType,
|
||||
events.NodeEventType,
|
||||
events.PluginEventType,
|
||||
events.SecretEventType,
|
||||
events.ServiceEventType,
|
||||
events.VolumeEventType,
|
||||
}
|
||||
|
||||
// eventActions is a list of all event actions.
|
||||
// This should be moved to the moby codebase once its usage is consolidated here.
|
||||
eventActions = []events.Action{
|
||||
events.ActionCreate,
|
||||
events.ActionStart,
|
||||
events.ActionRestart,
|
||||
events.ActionStop,
|
||||
events.ActionCheckpoint,
|
||||
events.ActionPause,
|
||||
events.ActionUnPause,
|
||||
events.ActionAttach,
|
||||
events.ActionDetach,
|
||||
events.ActionResize,
|
||||
events.ActionUpdate,
|
||||
events.ActionRename,
|
||||
events.ActionKill,
|
||||
events.ActionDie,
|
||||
events.ActionOOM,
|
||||
events.ActionDestroy,
|
||||
events.ActionRemove,
|
||||
events.ActionCommit,
|
||||
events.ActionTop,
|
||||
events.ActionCopy,
|
||||
events.ActionArchivePath,
|
||||
events.ActionExtractToDir,
|
||||
events.ActionExport,
|
||||
events.ActionImport,
|
||||
events.ActionSave,
|
||||
events.ActionLoad,
|
||||
events.ActionTag,
|
||||
events.ActionUnTag,
|
||||
events.ActionPush,
|
||||
events.ActionPull,
|
||||
events.ActionPrune,
|
||||
events.ActionDelete,
|
||||
events.ActionEnable,
|
||||
events.ActionDisable,
|
||||
events.ActionConnect,
|
||||
events.ActionDisconnect,
|
||||
events.ActionReload,
|
||||
events.ActionMount,
|
||||
events.ActionUnmount,
|
||||
events.ActionExecCreate,
|
||||
events.ActionExecStart,
|
||||
events.ActionExecDie,
|
||||
events.ActionExecDetach,
|
||||
events.ActionHealthStatus,
|
||||
events.ActionHealthStatusRunning,
|
||||
events.ActionHealthStatusHealthy,
|
||||
events.ActionHealthStatusUnhealthy,
|
||||
}
|
||||
)
|
||||
|
||||
// completeEventFilters provides completion for the filters that can be used with `--filter`.
|
||||
func completeEventFilters(dockerCLI completion.APIClientProvider) completion.ValidArgsFn {
|
||||
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
key, _, ok := strings.Cut(toComplete, "=")
|
||||
if !ok {
|
||||
return postfixWith("=", eventFilters), cobra.ShellCompDirectiveNoSpace
|
||||
}
|
||||
switch key {
|
||||
case "container":
|
||||
return prefixWith("container=", containerNames(dockerCLI, cmd, args, toComplete)), cobra.ShellCompDirectiveNoFileComp
|
||||
case "daemon":
|
||||
return prefixWith("daemon=", daemonNames(dockerCLI, cmd)), cobra.ShellCompDirectiveNoFileComp
|
||||
case "event":
|
||||
return prefixWith("event=", validEventNames()), cobra.ShellCompDirectiveNoFileComp
|
||||
case "image":
|
||||
return prefixWith("image=", imageNames(dockerCLI, cmd)), cobra.ShellCompDirectiveNoFileComp
|
||||
case "label":
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
case "network":
|
||||
return prefixWith("network=", networkNames(dockerCLI, cmd)), cobra.ShellCompDirectiveNoFileComp
|
||||
case "node":
|
||||
return prefixWith("node=", nodeNames(dockerCLI, cmd)), cobra.ShellCompDirectiveNoFileComp
|
||||
case "scope":
|
||||
return prefixWith("scope=", []string{"local", "swarm"}), cobra.ShellCompDirectiveNoFileComp
|
||||
case "type":
|
||||
return prefixWith("type=", eventTypeNames()), cobra.ShellCompDirectiveNoFileComp
|
||||
case "volume":
|
||||
return prefixWith("volume=", volumeNames(dockerCLI, cmd)), cobra.ShellCompDirectiveNoFileComp
|
||||
default:
|
||||
return postfixWith("=", eventFilters), cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prefixWith prefixes every element in the slice with the given prefix.
|
||||
func prefixWith(prefix string, values []string) []string {
|
||||
result := make([]string, len(values))
|
||||
for i, v := range values {
|
||||
result[i] = prefix + v
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// postfixWith appends postfix to every element in the slice.
|
||||
func postfixWith(postfix string, values []string) []string {
|
||||
result := make([]string, len(values))
|
||||
for i, v := range values {
|
||||
result[i] = v + postfix
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// eventTypeNames provides a list of all event types.
|
||||
// The list is derived from eventTypes.
|
||||
func eventTypeNames() []string {
|
||||
names := make([]string, len(eventTypes))
|
||||
for i, eventType := range eventTypes {
|
||||
names[i] = string(eventType)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// validEventNames provides a list of all event actions.
|
||||
// The list is derived from eventActions.
|
||||
// Actions that are not suitable for usage in completions are removed.
|
||||
func validEventNames() []string {
|
||||
names := make([]string, 0, len(eventActions))
|
||||
for _, eventAction := range eventActions {
|
||||
if strings.Contains(string(eventAction), " ") {
|
||||
continue
|
||||
}
|
||||
names = append(names, string(eventAction))
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// containerNames contacts the API to get names and optionally IDs of containers.
|
||||
// In case of an error, an empty list is returned.
|
||||
func containerNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command, args []string, toComplete string) []string {
|
||||
names, _ := completion.ContainerNames(dockerCLI, true)(cmd, args, toComplete)
|
||||
if names == nil {
|
||||
return []string{}
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// daemonNames contacts the API to get name and ID of the current docker daemon.
|
||||
// In case of an error, an empty list is returned.
|
||||
func daemonNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
|
||||
info, err := dockerCLI.Client().Info(cmd.Context())
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
return []string{info.Name, info.ID}
|
||||
}
|
||||
|
||||
// imageNames contacts the API to get a list of image names.
|
||||
// In case of an error, an empty list is returned.
|
||||
func imageNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
|
||||
list, err := dockerCLI.Client().ImageList(cmd.Context(), image.ListOptions{})
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
names := make([]string, 0, len(list))
|
||||
for _, img := range list {
|
||||
names = append(names, img.RepoTags...)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// networkNames contacts the API to get a list of network names.
|
||||
// In case of an error, an empty list is returned.
|
||||
func networkNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
|
||||
list, err := dockerCLI.Client().NetworkList(cmd.Context(), network.ListOptions{})
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
names := make([]string, 0, len(list))
|
||||
for _, nw := range list {
|
||||
names = append(names, nw.Name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// nodeNames contacts the API to get a list of node names.
|
||||
// In case of an error, an empty list is returned.
|
||||
func nodeNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
|
||||
list, err := dockerCLI.Client().NodeList(cmd.Context(), types.NodeListOptions{})
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
names := make([]string, 0, len(list))
|
||||
for _, node := range list {
|
||||
names = append(names, node.Description.Hostname)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// volumeNames contacts the API to get a list of volume names.
|
||||
// In case of an error, an empty list is returned.
|
||||
func volumeNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
|
||||
list, err := dockerCLI.Client().VolumeList(cmd.Context(), volume.ListOptions{})
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
names := make([]string, 0, len(list.Volumes))
|
||||
for _, v := range list.Volumes {
|
||||
names = append(names, v.Name)
|
||||
}
|
||||
return names
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/internal/test"
|
||||
"github.com/docker/cli/internal/test/builders"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/api/types/system"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
"github.com/spf13/cobra"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestCompleteEventFilter(t *testing.T) {
|
||||
tests := []struct {
|
||||
client *fakeClient
|
||||
toComplete string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
client: &fakeClient{
|
||||
containerListFunc: func(_ context.Context, _ container.ListOptions) ([]container.Summary, error) {
|
||||
return []container.Summary{
|
||||
*builders.Container("c1"),
|
||||
*builders.Container("c2"),
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
toComplete: "container=",
|
||||
expected: []string{"container=c1", "container=c2"},
|
||||
},
|
||||
{
|
||||
client: &fakeClient{
|
||||
containerListFunc: func(_ context.Context, _ container.ListOptions) ([]container.Summary, error) {
|
||||
return nil, errors.New("API error")
|
||||
},
|
||||
},
|
||||
toComplete: "container=",
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
client: &fakeClient{
|
||||
infoFunc: func(ctx context.Context) (system.Info, error) {
|
||||
return system.Info{
|
||||
ID: "daemon-id",
|
||||
Name: "daemon-name",
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
toComplete: "daemon=",
|
||||
expected: []string{"daemon=daemon-name", "daemon=daemon-id"},
|
||||
},
|
||||
{
|
||||
client: &fakeClient{
|
||||
infoFunc: func(ctx context.Context) (system.Info, error) {
|
||||
return system.Info{}, errors.New("API error")
|
||||
},
|
||||
},
|
||||
toComplete: "daemon=",
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
client: &fakeClient{
|
||||
imageListFunc: func(_ context.Context, _ image.ListOptions) ([]image.Summary, error) {
|
||||
return []image.Summary{
|
||||
{RepoTags: []string{"img:1"}},
|
||||
{RepoTags: []string{"img:2"}},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
toComplete: "image=",
|
||||
expected: []string{"image=img:1", "image=img:2"},
|
||||
},
|
||||
{
|
||||
client: &fakeClient{
|
||||
imageListFunc: func(_ context.Context, _ image.ListOptions) ([]image.Summary, error) {
|
||||
return []image.Summary{}, errors.New("API error")
|
||||
},
|
||||
},
|
||||
toComplete: "image=",
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
client: &fakeClient{
|
||||
networkListFunc: func(_ context.Context, _ network.ListOptions) ([]network.Summary, error) {
|
||||
return []network.Summary{
|
||||
*builders.NetworkResource(builders.NetworkResourceName("nw1")),
|
||||
*builders.NetworkResource(builders.NetworkResourceName("nw2")),
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
toComplete: "network=",
|
||||
expected: []string{"network=nw1", "network=nw2"},
|
||||
},
|
||||
{
|
||||
client: &fakeClient{
|
||||
networkListFunc: func(_ context.Context, _ network.ListOptions) ([]network.Summary, error) {
|
||||
return nil, errors.New("API error")
|
||||
},
|
||||
},
|
||||
toComplete: "network=",
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
client: &fakeClient{
|
||||
nodeListFunc: func(_ context.Context, _ types.NodeListOptions) ([]swarm.Node, error) {
|
||||
return []swarm.Node{
|
||||
*builders.Node(builders.Hostname("n1")),
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
toComplete: "node=",
|
||||
expected: []string{"node=n1"},
|
||||
},
|
||||
{
|
||||
client: &fakeClient{
|
||||
nodeListFunc: func(_ context.Context, _ types.NodeListOptions) ([]swarm.Node, error) {
|
||||
return []swarm.Node{}, errors.New("API error")
|
||||
},
|
||||
},
|
||||
toComplete: "node=",
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
client: &fakeClient{
|
||||
volumeListFunc: func(ctx context.Context, options volume.ListOptions) (volume.ListResponse, error) {
|
||||
return volume.ListResponse{
|
||||
Volumes: []*volume.Volume{
|
||||
builders.Volume(builders.VolumeName("v1")),
|
||||
builders.Volume(builders.VolumeName("v2")),
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
toComplete: "volume=",
|
||||
expected: []string{"volume=v1", "volume=v2"},
|
||||
},
|
||||
{
|
||||
client: &fakeClient{
|
||||
volumeListFunc: func(ctx context.Context, options volume.ListOptions) (volume.ListResponse, error) {
|
||||
return volume.ListResponse{}, errors.New("API error")
|
||||
},
|
||||
},
|
||||
toComplete: "volume=",
|
||||
expected: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
cli := test.NewFakeCli(tc.client)
|
||||
|
||||
completions, directive := completeEventFilters(cli)(NewEventsCommand(cli), nil, tc.toComplete)
|
||||
|
||||
assert.DeepEqual(t, completions, tc.expected)
|
||||
assert.Equal(t, directive, cobra.ShellCompDirectiveNoFileComp, fmt.Sprintf("wrong directive in completion for '%s'", tc.toComplete))
|
||||
}
|
||||
}
|
|
@ -50,6 +50,8 @@ func NewEventsCommand(dockerCli command.Cli) *cobra.Command {
|
|||
flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided")
|
||||
flags.StringVar(&options.format, "format", "", flagsHelper.InspectFormatHelp) // using the same flag description as "inspect" commands for now.
|
||||
|
||||
_ = cmd.RegisterFlagCompletionFunc("filter", completeEventFilters(dockerCli))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@ func TestEventsFormat(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Set to UTC timezone as timestamps in output are
|
||||
// printed in the current timezone
|
||||
|
|
|
@ -374,7 +374,6 @@ func TestPrettyPrintInfo(t *testing.T) {
|
|||
expectedError: "errors pretty printing info",
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
err := prettyPrintInfo(cli, tc.dockerInfo)
|
||||
|
@ -452,7 +451,6 @@ func TestFormatInfo(t *testing.T) {
|
|||
expectedError: `template: :1:2: executing "" at <.badString>: can't evaluate field badString in type system.dockerInfo`,
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
info := dockerInfo{
|
||||
|
@ -518,7 +516,6 @@ func TestNeedsServerInfo(t *testing.T) {
|
|||
|
||||
inf := dockerInfo{ClientInfo: &clientInfo{}}
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
assert.Equal(t, needsServerInfo(tc.template, inf), tc.expected)
|
||||
})
|
||||
|
|
|
@ -51,7 +51,7 @@ func NewInspectCommand(dockerCli command.Cli) *cobra.Command {
|
|||
func runInspect(ctx context.Context, dockerCli command.Cli, opts inspectOptions) error {
|
||||
var elementSearcher inspect.GetRefFunc
|
||||
switch opts.inspectType {
|
||||
case "", "container", "image", "node", "network", "service", "volume", "task", "plugin", "secret":
|
||||
case "", "config", "container", "image", "network", "node", "plugin", "secret", "service", "task", "volume":
|
||||
elementSearcher = inspectAll(ctx, dockerCli, opts.size, opts.inspectType)
|
||||
default:
|
||||
return errors.Errorf("%q is not a valid value for --type", opts.inspectType)
|
||||
|
@ -114,6 +114,12 @@ func inspectSecret(ctx context.Context, dockerCli command.Cli) inspect.GetRefFun
|
|||
}
|
||||
}
|
||||
|
||||
func inspectConfig(ctx context.Context, dockerCLI command.Cli) inspect.GetRefFunc {
|
||||
return func(ref string) (any, []byte, error) {
|
||||
return dockerCLI.Client().ConfigInspectWithRaw(ctx, ref)
|
||||
}
|
||||
}
|
||||
|
||||
func inspectAll(ctx context.Context, dockerCli command.Cli, getSize bool, typeConstraint string) inspect.GetRefFunc {
|
||||
inspectAutodetect := []struct {
|
||||
objectType string
|
||||
|
@ -162,6 +168,11 @@ func inspectAll(ctx context.Context, dockerCli command.Cli, getSize bool, typeCo
|
|||
isSwarmObject: true,
|
||||
objectInspector: inspectSecret(ctx, dockerCli),
|
||||
},
|
||||
{
|
||||
objectType: "config",
|
||||
isSwarmObject: true,
|
||||
objectInspector: inspectConfig(ctx, dockerCli),
|
||||
},
|
||||
}
|
||||
|
||||
// isSwarmManager does an Info API call to verify that the daemon is
|
||||
|
|
|
@ -71,7 +71,6 @@ foobar_bar foo2
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
|
|
@ -56,7 +56,6 @@ func TestGetFullCommandName(t *testing.T) {
|
|||
expected: "root child grandchild",
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
actual := getFullCommandName(tc.cmd)
|
||||
|
@ -91,7 +90,6 @@ func TestGetCommandName(t *testing.T) {
|
|||
expected: "child grandchild",
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
actual := getCommandName(tc.cmd)
|
||||
|
@ -130,7 +128,6 @@ func TestStdioAttributes(t *testing.T) {
|
|||
},
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.test, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
cli := &DockerCli{
|
||||
|
@ -179,7 +176,6 @@ func TestAttributesFromError(t *testing.T) {
|
|||
},
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.testName, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
actual := attributesFromError(tc.err)
|
||||
|
|
|
@ -127,7 +127,6 @@ tag3 bbbbbbbb
|
|||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
@ -231,7 +230,6 @@ eve foobarbazquxquux, key31, key32
|
|||
{Name: "eve", Keys: []string{"key31", "key32", "foobarbazquxquux"}},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
|
|
@ -116,7 +116,6 @@ var testKeys = map[string][]byte{
|
|||
func TestLoadKeyFromPath(t *testing.T) {
|
||||
skip.If(t, runtime.GOOS == "windows")
|
||||
for keyID, keyBytes := range testKeys {
|
||||
keyID, keyBytes := keyID, keyBytes
|
||||
t.Run(fmt.Sprintf("load-key-id-%s-from-path", keyID), func(t *testing.T) {
|
||||
privKeyFilepath := filepath.Join(t.TempDir(), "privkey.pem")
|
||||
assert.NilError(t, os.WriteFile(privKeyFilepath, keyBytes, notary.PrivNoExecPerms))
|
||||
|
@ -163,7 +162,6 @@ func TestLoadKeyFromPath(t *testing.T) {
|
|||
func TestLoadKeyTooPermissive(t *testing.T) {
|
||||
skip.If(t, runtime.GOOS == "windows")
|
||||
for keyID, keyBytes := range testKeys {
|
||||
keyID, keyBytes := keyID, keyBytes
|
||||
t.Run(fmt.Sprintf("load-key-id-%s-too-permissive", keyID), func(t *testing.T) {
|
||||
privKeyDir := t.TempDir()
|
||||
privKeyFilepath := filepath.Join(privKeyDir, "privkey477.pem")
|
||||
|
|
|
@ -30,7 +30,6 @@ func TestTrustSignerRemoveErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := newSignerRemoveCommand(
|
||||
test.NewFakeCli(&fakeClient{}))
|
||||
|
@ -66,7 +65,6 @@ func TestTrustSignerRemoveErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCasesWithOutput {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{})
|
||||
cli.SetNotaryClient(notaryfake.GetOfflineNotaryRepository)
|
||||
|
|
|
@ -52,7 +52,6 @@ func TestVolumePruneErrors(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := NewPruneCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
|
@ -104,7 +103,6 @@ func TestVolumePruneSuccess(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{volumePruneFunc: tc.volumePruneFunc})
|
||||
cmd := NewPruneCommand(cli)
|
||||
|
@ -166,7 +164,6 @@ func TestVolumePrunePromptNo(t *testing.T) {
|
|||
skip.If(t, runtime.GOOS == "windows", "TODO: fix test on windows")
|
||||
|
||||
for _, input := range []string{"n", "N", "no", "anything", "really"} {
|
||||
input := input
|
||||
t.Run(input, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
volumePruneFunc: simplePruneFunc,
|
||||
|
|
|
@ -409,7 +409,6 @@ func TestConvertCredentialSpec(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
namespace := NewNamespace(tc.name)
|
||||
swarmSpec, err := convertCredentialSpec(namespace, tc.in, tc.configs)
|
||||
|
@ -691,7 +690,6 @@ func TestConvertServiceCapAddAndCapDrop(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.title, func(t *testing.T) {
|
||||
result, err := Service("1.41", Namespace{name: "foo"}, tc.in, nil, nil, nil, nil)
|
||||
assert.NilError(t, err)
|
||||
|
|
|
@ -1626,13 +1626,12 @@ services:
|
|||
init: &booleanFalse,
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
testcase := testcase
|
||||
t.Run(testcase.doc, func(t *testing.T) {
|
||||
config, err := loadYAML(testcase.yaml)
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
config, err := loadYAML(tc.yaml)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Len(config.Services, 1))
|
||||
assert.Check(t, is.DeepEqual(testcase.init, config.Services[0].Init))
|
||||
assert.Check(t, is.DeepEqual(tc.init, config.Services[0].Init))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,6 @@ func mergeServices(base, override []types.ServiceConfig) ([]types.ServiceConfig,
|
|||
},
|
||||
}
|
||||
for name, overrideService := range overrideServices {
|
||||
overrideService := overrideService
|
||||
if baseService, ok := baseServices[name]; ok {
|
||||
if err := mergo.Merge(&baseService, &overrideService, mergo.WithAppendSlice, mergo.WithOverride, mergo.WithTransformers(specials)); err != nil {
|
||||
return base, errors.Wrapf(err, "cannot merge service %s", name)
|
||||
|
|
|
@ -215,7 +215,6 @@ func TestValidateCredentialSpecs(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.version, func(t *testing.T) {
|
||||
config := dict{
|
||||
"version": "99.99",
|
||||
|
|
|
@ -277,7 +277,6 @@ func TestExtractVariables(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
actual := ExtractVariables(tc.dict, defaultPattern)
|
||||
assert.Check(t, is.DeepEqual(actual, tc.expected))
|
||||
|
|
|
@ -433,7 +433,6 @@ func TestConfigPath(t *testing.T) {
|
|||
expectedErr: fmt.Sprintf("is outside of root config directory %q", "dummy"),
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
SetDir(tc.dir)
|
||||
f, err := Path(tc.path...)
|
||||
|
|
|
@ -297,7 +297,6 @@ func TestConvertToHostname(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.input, func(t *testing.T) {
|
||||
actual := ConvertToHostname(tc.input)
|
||||
assert.Equal(t, actual, tc.expected)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package oauth
|
||||
|
||||
import (
|
||||
"github.com/go-jose/go-jose/v3/jwt"
|
||||
"github.com/go-jose/go-jose/v4"
|
||||
"github.com/go-jose/go-jose/v4/jwt"
|
||||
)
|
||||
|
||||
// Claims represents standard claims along with some custom ones.
|
||||
|
@ -66,8 +67,23 @@ func GetClaims(accessToken string) (claims Claims, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// allowedSignatureAlgorithms is a list of allowed signature algorithms for JWTs.
|
||||
// We add all supported algorithms for Auth0, including with higher key lengths.
|
||||
// See auth0 docs: https://auth0.com/docs/get-started/applications/signing-algorithms
|
||||
var allowedSignatureAlgorithms = []jose.SignatureAlgorithm{
|
||||
jose.HS256,
|
||||
jose.HS384,
|
||||
jose.HS512,
|
||||
jose.RS256, // currently used for auth0
|
||||
jose.RS384,
|
||||
jose.RS512,
|
||||
jose.PS256,
|
||||
jose.PS384,
|
||||
jose.PS512,
|
||||
}
|
||||
|
||||
// parseSigned parses a JWT and returns the signature object or error. This does
|
||||
// not verify the validity of the JWT.
|
||||
func parseSigned(token string) (*jwt.JSONWebToken, error) {
|
||||
return jwt.ParseSigned(token)
|
||||
return jwt.ParseSigned(token, allowedSignatureAlgorithms)
|
||||
}
|
||||
|
|
|
@ -81,17 +81,16 @@ func TestStoreSaveAndGet(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
for _, testcase := range testcases {
|
||||
testcase := testcase
|
||||
t.Run(testcase.manifestRef.String(), func(t *testing.T) {
|
||||
actual, err := store.Get(testcase.listRef, testcase.manifestRef)
|
||||
if testcase.expectedErr != "" {
|
||||
assert.Error(t, err, testcase.expectedErr)
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.manifestRef.String(), func(t *testing.T) {
|
||||
actual, err := store.Get(tc.listRef, tc.manifestRef)
|
||||
if tc.expectedErr != "" {
|
||||
assert.Error(t, err, tc.expectedErr)
|
||||
assert.Check(t, IsNotFound(err))
|
||||
return
|
||||
}
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, testcase.expected, actual, cmpReferenceNamed)
|
||||
assert.DeepEqual(t, tc.expected, actual, cmpReferenceNamed)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,14 +64,13 @@ echo '{"SchemaVersion":"0.1.0","Vendor":"Docker Inc.","Version":"v0.6.3","ShortD
|
|||
)
|
||||
defer dir.Remove()
|
||||
|
||||
for _, tt := range testcases {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
ctx2, cancel2 := context.WithCancel(ctx)
|
||||
defer cancel2()
|
||||
|
||||
if tt.builder != "" {
|
||||
t.Setenv("BUILDX_BUILDER", tt.builder)
|
||||
if tc.builder != "" {
|
||||
t.Setenv("BUILDX_BUILDER", tc.builder)
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
|
@ -84,10 +83,10 @@ echo '{"SchemaVersion":"0.1.0","Vendor":"Docker Inc.","Version":"v0.6.3","ShortD
|
|||
assert.NilError(t, err)
|
||||
assert.NilError(t, dockerCli.Initialize(flags.NewClientOptions()))
|
||||
|
||||
if tt.context != "" {
|
||||
if tt.context != command.DefaultContextName {
|
||||
if tc.context != "" {
|
||||
if tc.context != command.DefaultContextName {
|
||||
assert.NilError(t, dockerCli.ContextStore().CreateOrUpdate(store.Metadata{
|
||||
Name: tt.context,
|
||||
Name: tc.context,
|
||||
Endpoints: map[string]any{
|
||||
"docker": map[string]any{
|
||||
"host": "unix://" + filepath.Join(t.TempDir(), "docker.sock"),
|
||||
|
@ -96,12 +95,12 @@ echo '{"SchemaVersion":"0.1.0","Vendor":"Docker Inc.","Version":"v0.6.3","ShortD
|
|||
}))
|
||||
}
|
||||
opts := flags.NewClientOptions()
|
||||
opts.Context = tt.context
|
||||
opts.Context = tc.context
|
||||
assert.NilError(t, dockerCli.Initialize(opts))
|
||||
}
|
||||
|
||||
dockerCli.ConfigFile().CLIPluginsExtraDirs = []string{dir.Path()}
|
||||
if tt.alias {
|
||||
if tc.alias {
|
||||
dockerCli.ConfigFile().Aliases = map[string]string{"builder": "buildx"}
|
||||
}
|
||||
|
||||
|
@ -115,8 +114,8 @@ echo '{"SchemaVersion":"0.1.0","Vendor":"Docker Inc.","Version":"v0.6.3","ShortD
|
|||
args, os.Args, envs, err = processBuilder(dockerCli, cmd, args, os.Args)
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, []string{builderDefaultPlugin, "build", "."}, args)
|
||||
if tt.expectedEnvs != nil {
|
||||
assert.DeepEqual(t, tt.expectedEnvs, envs)
|
||||
if tc.expectedEnvs != nil {
|
||||
assert.DeepEqual(t, tc.expectedEnvs, envs)
|
||||
} else {
|
||||
assert.Check(t, len(envs) == 0)
|
||||
}
|
||||
|
@ -289,10 +288,9 @@ func TestHasBuilderName(t *testing.T) {
|
|||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range cases {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.expected, hasBuilderName(tt.args, tt.envs))
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert.Equal(t, tc.expected, hasBuilderName(tc.args, tc.envs))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue