test spring-cleaning

This makes a quick pass through our tests;

Discard output/err
----------------------------------------------

Many tests were testing for error-conditions, but didn't discard output.
This produced a lot of noise when running the tests, and made it hard
to discover if there were actual failures, or if the output was expected.
For example:

    === RUN   TestConfigCreateErrors
    Error: "create" requires exactly 2 arguments.
    See 'create --help'.

    Usage:  create [OPTIONS] CONFIG file|- [flags]

    Create a config from a file or STDIN
    Error: "create" requires exactly 2 arguments.
    See 'create --help'.

    Usage:  create [OPTIONS] CONFIG file|- [flags]

    Create a config from a file or STDIN
    Error: error creating config
    --- PASS: TestConfigCreateErrors (0.00s)

And after discarding output:

    === RUN   TestConfigCreateErrors
    --- PASS: TestConfigCreateErrors (0.00s)

Use sub-tests where possible
----------------------------------------------

Some tests were already set-up to use test-tables, and even had a usable
name (or in some cases "error" to check for). Change them to actual sub-
tests. Same test as above, but now with sub-tests and output discarded:

    === RUN   TestConfigCreateErrors
    === RUN   TestConfigCreateErrors/requires_exactly_2_arguments
    === RUN   TestConfigCreateErrors/requires_exactly_2_arguments#01
    === RUN   TestConfigCreateErrors/error_creating_config
    --- PASS: TestConfigCreateErrors (0.00s)
        --- PASS: TestConfigCreateErrors/requires_exactly_2_arguments (0.00s)
        --- PASS: TestConfigCreateErrors/requires_exactly_2_arguments#01 (0.00s)
        --- PASS: TestConfigCreateErrors/error_creating_config (0.00s)
    PASS

It's not perfect in all cases (in the above, there's duplicate "expected"
errors, but Go conveniently adds "#01" for the duplicate). There's probably
also various tests I missed that could still use the same changes applied;
we can improve these in follow-ups.

Set cmd.Args to prevent test-failures
----------------------------------------------

When running tests from my IDE, it compiles the tests before running,
then executes the compiled binary to run the tests. Cobra doesn't like
that, because in that situation `os.Args` is taken as argument for the
command that's executed. The command that's tested now sees the test-
flags as arguments (`-test.v -test.run ..`), which causes various tests
to fail ("Command XYZ does not accept arguments").

    # compile the tests:
    go test -c -o foo.test

    # execute the test:
    ./foo.test -test.v -test.run TestFoo
    === RUN   TestFoo
    Error: "foo" accepts no arguments.

The Cobra maintainers ran into the same situation, and for their own
use have added a special case to ignore `os.Args` in these cases;
https://github.com/spf13/cobra/blob/v1.8.1/command.go#L1078-L1083

    args := c.args

    // Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155
    if c.args == nil && filepath.Base(os.Args[0]) != "cobra.test" {
        args = os.Args[1:]
    }

Unfortunately, that exception is too specific (only checks for `cobra.test`),
so doesn't automatically fix the issue for other test-binaries. They did
provide a `cmd.SetArgs()` utility for this purpose
https://github.com/spf13/cobra/blob/v1.8.1/command.go#L276-L280

    // SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
    // particularly useful when testing.
    func (c *Command) SetArgs(a []string) {
        c.args = a
    }

And the fix is to explicitly set the command's args to an empty slice to
prevent Cobra from falling back to using `os.Args[1:]` as arguments.

    cmd := newSomeThingCommand()
    cmd.SetArgs([]string{})

Some tests already take this issue into account, and I updated some tests
for this, but there's likely many other ones that can use the same treatment.

Perhaps the Cobra maintainers would accept a contribution to make their
condition less specific and to look for binaries ending with a `.test`
suffix (which is what compiled binaries usually are named as).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit ab230240ad)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2024-07-04 01:29:04 +02:00
parent a2a0fb73ea
commit ca9636a1c3
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
87 changed files with 676 additions and 372 deletions

View File

@ -3,6 +3,7 @@ package builder
import (
"context"
"errors"
"io"
"testing"
"github.com/docker/cli/internal/test"
@ -19,5 +20,7 @@ func TestBuilderPromptTermination(t *testing.T) {
},
})
cmd := NewPruneCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
test.TerminatePrompt(ctx, t, cmd, cli)
}

View File

@ -42,6 +42,7 @@ func TestCheckpointCreateErrors(t *testing.T) {
cmd := newCreateCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -42,6 +42,7 @@ func TestCheckpointListErrors(t *testing.T) {
cmd := newListCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -41,6 +41,7 @@ func TestCheckpointRemoveErrors(t *testing.T) {
cmd := newRemoveCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -43,6 +43,8 @@ func TestConfigCreateErrors(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.expectedError, func(t *testing.T) {
cmd := newConfigCreateCommand(
test.NewFakeCli(&fakeClient{
configCreateFunc: tc.configCreateFunc,
@ -50,7 +52,9 @@ func TestConfigCreateErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}

View File

@ -61,6 +61,7 @@ func TestConfigInspectErrors(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -42,6 +42,7 @@ func TestConfigListErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -37,6 +37,7 @@ func TestConfigRemoveErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -74,6 +75,7 @@ func TestConfigRemoveContinueAfterError(t *testing.T) {
cmd := newConfigRemoveCommand(cli)
cmd.SetArgs(names)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Error(t, cmd.Execute(), "error removing config: foo")
assert.Check(t, is.DeepEqual(names, removedConfigs))
}

View File

@ -69,10 +69,14 @@ 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)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}

View File

@ -178,13 +178,14 @@ func TestSplitCpArg(t *testing.T) {
expectedContainer: "container",
},
}
for _, testcase := range testcases {
t.Run(testcase.doc, func(t *testing.T) {
skip.If(t, testcase.os != "" && testcase.os != runtime.GOOS)
for _, tc := range testcases {
tc := tc
t.Run(tc.doc, func(t *testing.T) {
skip.If(t, tc.os == "windows" && runtime.GOOS != "windows" || tc.os == "linux" && runtime.GOOS == "windows")
ctr, path := splitCpArg(testcase.path)
assert.Check(t, is.Equal(testcase.expectedContainer, ctr))
assert.Check(t, is.Equal(testcase.expectedPath, path))
ctr, path := splitCpArg(tc.path)
assert.Check(t, is.Equal(tc.expectedContainer, ctr))
assert.Check(t, is.Equal(tc.expectedPath, path))
})
}
}

View File

@ -236,6 +236,7 @@ func TestNewCreateCommandWithContentTrustErrors(t *testing.T) {
fakeCLI.SetNotaryClient(tc.notaryFunc)
cmd := NewCreateCommand(fakeCLI)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.ErrorContains(t, err, tc.expectedError)

View File

@ -39,6 +39,7 @@ func TestContainerExportOutputToIrregularFile(t *testing.T) {
})
cmd := NewExportCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs([]string{"-o", "/dev/random", "container"})
err := cmd.Execute()

View File

@ -163,6 +163,7 @@ func TestContainerListErrors(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -2,6 +2,7 @@ package container
import (
"context"
"io"
"testing"
"github.com/docker/cli/internal/test"
@ -20,5 +21,7 @@ func TestContainerPrunePromptTermination(t *testing.T) {
},
})
cmd := NewPruneCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
test.TerminatePrompt(ctx, t, cmd, cli)
}

View File

@ -45,6 +45,7 @@ func TestRemoveForce(t *testing.T) {
})
cmd := NewRmCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()

View File

@ -127,6 +127,8 @@ 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,
hostConfig *container.HostConfig,
@ -141,9 +143,11 @@ func TestRunCommandWithContentTrustErrors(t *testing.T) {
cmd := NewRunCommand(fakeCLI)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
err := cmd.Execute()
assert.Assert(t, err != nil)
assert.Assert(t, is.Contains(fakeCLI.ErrBuffer().String(), tc.expectedError))
})
}
}

View File

@ -127,6 +127,7 @@ func TestRunBuildFromGitHubSpecialCase(t *testing.T) {
// Clone a small repo that exists so git doesn't prompt for credentials
cmd.SetArgs([]string{"github.com/docker/for-win"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
err := cmd.Execute()
assert.ErrorContains(t, err, "unable to prepare context")
assert.ErrorContains(t, err, "docker-build-git")

View File

@ -35,10 +35,14 @@ 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)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}

View File

@ -36,6 +36,7 @@ func TestNewImportCommandErrors(t *testing.T) {
for _, tc := range testCases {
cmd := NewImportCommand(test.NewFakeCli(&fakeClient{imageImportFunc: tc.imageImportFunc}))
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
@ -44,6 +45,7 @@ func TestNewImportCommandErrors(t *testing.T) {
func TestNewImportCommandInvalidFile(t *testing.T) {
cmd := NewImportCommand(test.NewFakeCli(&fakeClient{}))
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs([]string{"testdata/import-command-success.unexistent-file"})
assert.ErrorContains(t, cmd.Execute(), "testdata/import-command-success.unexistent-file")
}
@ -96,9 +98,13 @@ 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)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.NilError(t, cmd.Execute())
})
}
}

View File

@ -25,10 +25,14 @@ 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)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}

View File

@ -35,10 +35,14 @@ 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)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -79,14 +83,18 @@ 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})
cmd := NewImagesCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.NilError(t, err)
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("list-command-success.%s.golden", tc.name))
})
}
}

View File

@ -40,12 +40,16 @@ 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)
cmd := NewLoadCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -53,6 +57,7 @@ func TestNewLoadCommandInvalidInput(t *testing.T) {
expectedError := "open *"
cmd := NewLoadCommand(test.NewFakeCli(&fakeClient{}))
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs([]string{"--input", "*"})
err := cmd.Execute()
assert.ErrorContains(t, err, expectedError)
@ -89,6 +94,8 @@ 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)
cmd.SetOut(io.Discard)
@ -96,5 +103,6 @@ func TestNewLoadCommandSuccess(t *testing.T) {
err := cmd.Execute()
assert.NilError(t, err)
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("load-command-success.%s.golden", tc.name))
})
}
}

View File

@ -39,12 +39,16 @@ 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,
}))
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -94,6 +98,7 @@ 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.
@ -119,5 +124,8 @@ func TestPrunePromptTermination(t *testing.T) {
},
})
cmd := NewPruneCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
test.TerminatePrompt(ctx, t, cmd, cli)
}

View File

@ -38,11 +38,15 @@ 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)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -69,6 +73,8 @@ 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) {
assert.Check(t, is.Equal(tc.expectedTag, ref), tc.name)
@ -77,10 +83,12 @@ func TestNewPullCommandSuccess(t *testing.T) {
})
cmd := NewPullCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.NilError(t, err)
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("pull-command-success.%s.golden", tc.name))
})
}
}
@ -111,6 +119,8 @@ 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) {
return io.NopCloser(strings.NewReader("")), errors.New("shouldn't try to pull image")
@ -119,8 +129,10 @@ func TestNewPullCommandWithContentTrustErrors(t *testing.T) {
cli.SetNotaryClient(tc.notaryFunc)
cmd := NewPullCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.ErrorContains(t, err, tc.expectedError)
})
}
}

View File

@ -38,11 +38,15 @@ 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)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -73,6 +77,7 @@ func TestNewPushCommandSuccess(t *testing.T) {
})
cmd := NewPushCommand(cli)
cmd.SetOut(cli.OutBuffer())
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.NilError(t, cmd.Execute())
if tc.output != "" {

View File

@ -62,11 +62,13 @@ 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,
}))
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
@ -119,10 +121,12 @@ 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)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Equal(tc.expectedStderr, cli.ErrBuffer().String()))

View File

@ -52,12 +52,16 @@ 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)
cmd := NewSaveCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -77,7 +81,7 @@ func TestNewSaveCommandSuccess(t *testing.T) {
return io.NopCloser(strings.NewReader("")), nil
},
deferredFunc: func() {
os.Remove("save_tmp_file")
_ = os.Remove("save_tmp_file")
},
},
{
@ -92,16 +96,20 @@ 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: func(images []string) (io.ReadCloser, error) {
return io.NopCloser(strings.NewReader("")), nil
},
}))
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.NilError(t, cmd.Execute())
if tc.deferredFunc != nil {
tc.deferredFunc()
}
})
}
}

View File

@ -20,6 +20,7 @@ func TestCliNewTagCommandErrors(t *testing.T) {
cmd := NewTagCommand(test.NewFakeCli(&fakeClient{}))
cmd.SetArgs(args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), expectedError)
}
}

View File

@ -35,6 +35,7 @@ func TestManifestAnnotateError(t *testing.T) {
cmd := newAnnotateCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -52,6 +53,7 @@ func TestManifestAnnotate(t *testing.T) {
cmd := newAnnotateCommand(cli)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/fake:0.0"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
expectedError := "manifest for image example.com/fake:0.0 does not exist"
assert.ErrorContains(t, cmd.Execute(), expectedError)
@ -71,6 +73,7 @@ func TestManifestAnnotate(t *testing.T) {
err = cmd.Flags().Set("verbose", "true")
assert.NilError(t, err)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
cmd.SetErr(io.Discard)
assert.NilError(t, cmd.Execute())
actual := cli.OutBuffer()
expected := golden.Get(t, "inspect-annotate.golden")

View File

@ -31,11 +31,15 @@ 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)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -87,6 +91,7 @@ func TestManifestCreateRefuseAmend(t *testing.T) {
cmd := newCreateListCommand(cli)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
err = cmd.Execute()
assert.Error(t, err, "refusing to amend an existing manifest list with no --amend flag")
}
@ -109,6 +114,7 @@ func TestManifestCreateNoManifest(t *testing.T) {
cmd := newCreateListCommand(cli)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
err := cmd.Execute()
assert.Error(t, err, "No such image: example.com/alpine:3.0")
}

View File

@ -70,6 +70,7 @@ func TestInspectCommandLocalManifestNotFound(t *testing.T) {
cmd := newInspectCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
err := cmd.Execute()
assert.Error(t, err, "No such manifest: example.com/alpine:3.0")
@ -91,6 +92,7 @@ func TestInspectCommandNotFound(t *testing.T) {
cmd := newInspectCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs([]string{"example.com/alpine:3.0"})
err := cmd.Execute()
assert.Error(t, err, "No such manifest: example.com/alpine:3.0")

View File

@ -44,6 +44,7 @@ func TestManifestPushErrors(t *testing.T) {
cmd := newPushListCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -56,6 +56,7 @@ func TestRmManifestNotCreated(t *testing.T) {
cmd := newRmManifestListCommand(cli)
cmd.SetArgs([]string{"example.com/first:1", "example.com/second:2"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
err = cmd.Execute()
assert.Error(t, err, "No such manifest: example.com/first:1")

View File

@ -38,6 +38,7 @@ func TestNetworkConnectErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -137,6 +137,7 @@ func TestNetworkCreateErrors(t *testing.T) {
assert.NilError(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -36,6 +36,7 @@ func TestNetworkDisconnectErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -36,6 +36,7 @@ func TestNetworkListErrors(t *testing.T) {
}),
)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -82,6 +83,7 @@ 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)

View File

@ -2,6 +2,7 @@ package network
import (
"context"
"io"
"testing"
"github.com/docker/cli/internal/test"
@ -20,5 +21,8 @@ func TestNetworkPrunePromptTermination(t *testing.T) {
},
})
cmd := NewPruneCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
test.TerminatePrompt(ctx, t, cmd, cli)
}

View File

@ -114,5 +114,7 @@ func TestNetworkRemovePromptTermination(t *testing.T) {
})
cmd := newRemoveCommand(cli)
cmd.SetArgs([]string{"existing-network"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
test.TerminatePrompt(ctx, t, cmd, cli)
}

View File

@ -44,6 +44,7 @@ func TestNodeDemoteErrors(t *testing.T) {
}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -74,6 +74,7 @@ func TestNodeInspectErrors(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -105,6 +106,8 @@ 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,
})
@ -113,5 +116,6 @@ func TestNodeInspectPretty(t *testing.T) {
assert.Check(t, cmd.Flags().Set("pretty", "true"))
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("node-inspect-pretty.%s.golden", tc.name))
})
}
}

View File

@ -48,6 +48,7 @@ func TestNodeListErrorOnAPIFailure(t *testing.T) {
})
cmd := newListCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Error(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -44,6 +44,7 @@ func TestNodePromoteErrors(t *testing.T) {
}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -61,6 +61,7 @@ func TestNodePsErrors(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Error(t, cmd.Execute(), tc.expectedError)
}
}
@ -133,6 +134,8 @@ 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,
nodeInspectFunc: tc.nodeInspectFunc,
@ -147,5 +150,6 @@ func TestNodePs(t *testing.T) {
}
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("node-ps.%s.golden", tc.name))
})
}
}

View File

@ -33,6 +33,7 @@ func TestNodeRemoveErrors(t *testing.T) {
}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -64,6 +64,7 @@ func TestNodeUpdateErrors(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -41,6 +41,7 @@ func TestCreateErrors(t *testing.T) {
cmd := newCreateCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -53,6 +54,7 @@ func TestCreateErrorOnFileAsContextDir(t *testing.T) {
cmd := newCreateCommand(cli)
cmd.SetArgs([]string{"plugin-foo", tmpFile.Path()})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "context must be a directory")
}
@ -64,6 +66,7 @@ func TestCreateErrorOnContextDirWithoutConfig(t *testing.T) {
cmd := newCreateCommand(cli)
cmd.SetArgs([]string{"plugin-foo", tmpDir.Path()})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
expectedErr := "config.json: no such file or directory"
if runtime.GOOS == "windows" {
@ -82,6 +85,7 @@ func TestCreateErrorOnInvalidConfig(t *testing.T) {
cmd := newCreateCommand(cli)
cmd.SetArgs([]string{"plugin-foo", tmpDir.Path()})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "invalid")
}
@ -98,6 +102,7 @@ func TestCreateErrorFromDaemon(t *testing.T) {
}))
cmd.SetArgs([]string{"plugin-foo", tmpDir.Path()})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "error creating plugin")
}

View File

@ -41,6 +41,7 @@ func TestPluginDisableErrors(t *testing.T) {
}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -51,6 +51,7 @@ func TestPluginEnableErrors(t *testing.T) {
cmd.Flags().Set(key, value)
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -66,6 +66,7 @@ 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)
@ -74,6 +75,7 @@ func TestInspectErrors(t *testing.T) {
cmd.Flags().Set(key, value)
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
@ -136,6 +138,7 @@ 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)

View File

@ -54,11 +54,15 @@ 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)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -90,6 +94,8 @@ 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) {
return nil, errors.New("should not try to install plugin")
@ -99,7 +105,9 @@ func TestInstallContentTrustErrors(t *testing.T) {
cmd := newInstallCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -130,10 +138,13 @@ 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)
cmd.SetArgs(tc.args)
assert.NilError(t, cmd.Execute())
assert.Check(t, strings.Contains(cli.OutBuffer().String(), tc.expectedOutput))
})
}
}

View File

@ -46,6 +46,8 @@ 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)
cmd.SetArgs(tc.args)
@ -53,7 +55,9 @@ func TestListErrors(t *testing.T) {
cmd.Flags().Set(key, value)
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -162,6 +166,8 @@ 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)
cmd.SetArgs(tc.args)
@ -170,5 +176,6 @@ func TestList(t *testing.T) {
}
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), tc.golden)
})
}
}

View File

@ -37,6 +37,7 @@ func TestRemoveErrors(t *testing.T) {
cmd := newRemoveCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -32,6 +32,8 @@ func TestUpgradePromptTermination(t *testing.T) {
// need to set a remote address that does not match the plugin
// reference sent by the `pluginInspectFunc`
cmd.SetArgs([]string{"foo/bar", "localhost:5000/foo/bar:v1.0.0"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
test.TerminatePrompt(ctx, t, cmd, cli)
golden.Assert(t, cli.OutBuffer().String(), "plugin-upgrade-terminate.golden")
}

View File

@ -49,6 +49,7 @@ func TestSecretCreateErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -61,6 +61,7 @@ func TestSecretInspectErrors(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -92,6 +93,8 @@ 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,
})
@ -99,6 +102,7 @@ func TestSecretInspectWithoutFormat(t *testing.T) {
cmd.SetArgs(tc.args)
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("secret-inspect-without-format.%s.golden", tc.name))
})
}
}
@ -128,6 +132,8 @@ 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,
})
@ -136,6 +142,7 @@ func TestSecretInspectWithFormat(t *testing.T) {
assert.Check(t, cmd.Flags().Set("format", tc.format))
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("secret-inspect-with-format.%s.golden", tc.name))
})
}
}

View File

@ -42,6 +42,7 @@ func TestSecretListErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -38,6 +38,7 @@ func TestSecretRemoveErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -74,6 +75,7 @@ func TestSecretRemoveContinueAfterError(t *testing.T) {
cmd := newSecretRemoveCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(names)
assert.Error(t, cmd.Execute(), "error removing secret: foo")
assert.Check(t, is.DeepEqual(names, removedSecrets))

View File

@ -91,6 +91,8 @@ func TestRollbackWithErrors(t *testing.T) {
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
cmd := newRollbackCommand(
test.NewFakeCli(&fakeClient{
serviceInspectWithRawFunc: tc.serviceInspectWithRawFunc,
@ -99,6 +101,8 @@ func TestRollbackWithErrors(t *testing.T) {
cmd.SetArgs(tc.args)
cmd.Flags().Set("quiet", "true")
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}

View File

@ -13,6 +13,7 @@ import (
func TestConfigWithEmptyComposeFile(t *testing.T) {
cmd := newConfigCommand(test.NewFakeCli(&fakeClient{}))
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), `Specify a Compose file`)
}

View File

@ -12,6 +12,7 @@ func TestDeployWithEmptyName(t *testing.T) {
cmd := newDeployCommand(test.NewFakeCli(&fakeClient{}))
cmd.SetArgs([]string{"' '"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), `invalid stack name: "' '"`)
}

View File

@ -25,18 +25,21 @@ func TestListErrors(t *testing.T) {
expectedError: "accepts no argument",
},
{
args: []string{},
flags: map[string]string{
"format": "{{invalid format}}",
},
expectedError: "template parsing error",
},
{
args: []string{},
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
return []swarm.Service{}, errors.Errorf("error getting services")
},
expectedError: "error getting services",
},
{
args: []string{},
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
return []swarm.Service{*builders.Service()}, nil
},
@ -45,15 +48,19 @@ 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,
}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
for key, value := range tc.flags {
assert.Check(t, cmd.Flags().Set(key, value))
}
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -97,6 +104,7 @@ 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 {

View File

@ -40,12 +40,16 @@ 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,
}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -156,6 +160,7 @@ 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,
@ -169,6 +174,7 @@ func TestStackPs(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
if tc.expectedErr != "" {
assert.Error(t, cmd.Execute(), tc.expectedErr)

View File

@ -45,6 +45,7 @@ func TestRemoveWithEmptyName(t *testing.T) {
cmd := newRemoveCommand(test.NewFakeCli(&fakeClient{}))
cmd.SetArgs([]string{"good", "' '", "alsogood"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), `invalid stack name: "' '"`)
}
@ -157,6 +158,7 @@ func TestRemoveContinueAfterError(t *testing.T) {
}
cmd := newRemoveCommand(test.NewFakeCli(cli))
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs([]string{"foo", "bar"})
assert.Error(t, cmd.Execute(), "Failed to remove some resources from stack: foo")

View File

@ -80,6 +80,7 @@ func TestStackServicesErrors(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
@ -89,6 +90,7 @@ func TestRunServicesWithEmptyName(t *testing.T) {
cmd := newServicesCommand(test.NewFakeCli(&fakeClient{}))
cmd.SetArgs([]string{"' '"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), `invalid stack name: "' '"`)
}

View File

@ -145,6 +145,7 @@ func TestDisplayTrustRootInvalidFlags(t *testing.T) {
}))
assert.Check(t, cmd.Flags().Parse(testCase.args))
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), testCase.errorMsg)
}
}

View File

@ -63,6 +63,8 @@ func TestSwarmInitErrorOnAPIFailure(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
cmd := newInitCommand(
test.NewFakeCli(&fakeClient{
swarmInitFunc: tc.swarmInitFunc,
@ -74,7 +76,9 @@ func TestSwarmInitErrorOnAPIFailure(t *testing.T) {
cmd.Flags().Set(key, value)
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Error(t, cmd.Execute(), tc.expectedError)
})
}
}

View File

@ -48,6 +48,8 @@ func TestSwarmJoinErrors(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
cmd := newJoinCommand(
test.NewFakeCli(&fakeClient{
swarmJoinFunc: tc.swarmJoinFunc,
@ -55,7 +57,9 @@ func TestSwarmJoinErrors(t *testing.T) {
}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -89,6 +93,8 @@ 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,
})
@ -96,5 +102,6 @@ func TestSwarmJoin(t *testing.T) {
cmd.SetArgs([]string{"remote"})
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Equal(strings.TrimSpace(cli.OutBuffer().String()), tc.expected))
})
}
}

View File

@ -87,6 +87,8 @@ 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,
swarmUpdateFunc: tc.swarmUpdateFunc,
@ -99,7 +101,9 @@ func TestSwarmJoinTokenErrors(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -194,6 +198,8 @@ 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,
infoFunc: tc.infoFunc,
@ -206,5 +212,6 @@ func TestSwarmJoinToken(t *testing.T) {
}
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("jointoken-%s.golden", tc.name))
})
}
}

View File

@ -32,13 +32,17 @@ func TestSwarmLeaveErrors(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
cmd := newLeaveCommand(
test.NewFakeCli(&fakeClient{
swarmLeaveFunc: tc.swarmLeaveFunc,
}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}

View File

@ -80,6 +80,8 @@ func TestSwarmUnlockKeyErrors(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
cmd := newUnlockKeyCommand(
test.NewFakeCli(&fakeClient{
swarmInspectFunc: tc.swarmInspectFunc,
@ -91,7 +93,9 @@ func TestSwarmUnlockKeyErrors(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -154,6 +158,8 @@ 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,
swarmUpdateFunc: tc.swarmUpdateFunc,
@ -166,5 +172,6 @@ func TestSwarmUnlockKey(t *testing.T) {
}
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("unlockkeys-%s.golden", tc.name))
})
}
}

View File

@ -64,6 +64,8 @@ func TestSwarmUnlockErrors(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
cmd := newUnlockCommand(
test.NewFakeCli(&fakeClient{
infoFunc: tc.infoFunc,
@ -71,7 +73,9 @@ func TestSwarmUnlockErrors(t *testing.T) {
}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}

View File

@ -65,6 +65,8 @@ func TestSwarmUpdateErrors(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
cmd := newUpdateCommand(
test.NewFakeCli(&fakeClient{
swarmInspectFunc: tc.swarmInspectFunc,
@ -76,7 +78,9 @@ func TestSwarmUpdateErrors(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -165,18 +169,25 @@ 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,
swarmUpdateFunc: tc.swarmUpdateFunc,
swarmGetUnlockKeyFunc: tc.swarmGetUnlockKeyFunc,
})
cmd := newUpdateCommand(cli)
if tc.args == nil {
cmd.SetArgs([]string{})
} else {
cmd.SetArgs(tc.args)
}
for key, value := range tc.flags {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(cli.OutBuffer())
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("update-%s.golden", tc.name))
})
}
}

View File

@ -2,6 +2,7 @@ package system
import (
"context"
"io"
"testing"
"github.com/docker/cli/cli/config/configfile"
@ -18,6 +19,8 @@ func TestPrunePromptPre131DoesNotIncludeBuildCache(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{version: "1.30"})
cmd := newPruneCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "system prune has been cancelled")
expected := `WARNING! This will remove:
- all stopped containers
@ -35,6 +38,8 @@ func TestPrunePromptFilters(t *testing.T) {
})
cmd := newPruneCommand(cli)
cmd.SetArgs([]string{"--filter", "until=24h", "--filter", "label=hello-world", "--filter", "label!=foo=bar", "--filter", "label=bar=baz"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "system prune has been cancelled")
expected := `WARNING! This will remove:
@ -69,5 +74,8 @@ func TestSystemPrunePromptTermination(t *testing.T) {
})
cmd := newPruneCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
test.TerminatePrompt(ctx, t, cmd, cli)
}

View File

@ -3,6 +3,7 @@ package system
import (
"context"
"errors"
"io"
"strings"
"testing"
@ -20,7 +21,9 @@ func TestVersionWithoutServer(t *testing.T) {
},
})
cmd := NewVersionCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(cli.Err())
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "no server")
out := cli.OutBuffer().String()
// TODO: use an assertion like e2e/image/build_test.go:assertBuildOutput()

View File

@ -67,6 +67,7 @@ func TestTrustInspectPrettyCommandErrors(t *testing.T) {
test.NewFakeCli(&fakeClient{}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.Flags().Set("pretty", "true")
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
@ -79,6 +80,7 @@ func TestTrustInspectPrettyCommandOfflineErrors(t *testing.T) {
cmd.Flags().Set("pretty", "true")
cmd.SetArgs([]string{"nonexistent-reg-name.io/image"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "no signatures or cannot access nonexistent-reg-name.io/image")
cli = test.NewFakeCli(&fakeClient{})
@ -87,6 +89,7 @@ func TestTrustInspectPrettyCommandOfflineErrors(t *testing.T) {
cmd.Flags().Set("pretty", "true")
cmd.SetArgs([]string{"nonexistent-reg-name.io/image:tag"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "no signatures or cannot access nonexistent-reg-name.io/image")
}
@ -97,6 +100,7 @@ func TestTrustInspectPrettyCommandUninitializedErrors(t *testing.T) {
cmd.Flags().Set("pretty", "true")
cmd.SetArgs([]string{"reg/unsigned-img"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "no signatures or cannot access reg/unsigned-img")
cli = test.NewFakeCli(&fakeClient{})
@ -105,6 +109,7 @@ func TestTrustInspectPrettyCommandUninitializedErrors(t *testing.T) {
cmd.Flags().Set("pretty", "true")
cmd.SetArgs([]string{"reg/unsigned-img:tag"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "no signatures or cannot access reg/unsigned-img:tag")
}
@ -115,6 +120,7 @@ func TestTrustInspectPrettyCommandEmptyNotaryRepoErrors(t *testing.T) {
cmd.Flags().Set("pretty", "true")
cmd.SetArgs([]string{"reg/img:unsigned-tag"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Contains(cli.OutBuffer().String(), "No signatures for reg/img:unsigned-tag"))
assert.Check(t, is.Contains(cli.OutBuffer().String(), "Administrative keys for reg/img"))
@ -125,6 +131,7 @@ func TestTrustInspectPrettyCommandEmptyNotaryRepoErrors(t *testing.T) {
cmd.Flags().Set("pretty", "true")
cmd.SetArgs([]string{"reg/img"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Contains(cli.OutBuffer().String(), "No signatures for reg/img"))
assert.Check(t, is.Contains(cli.OutBuffer().String(), "Administrative keys for reg/img"))

View File

@ -39,6 +39,7 @@ func TestTrustInspectCommandErrors(t *testing.T) {
cmd.Flags().Set("pretty", "true")
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -86,6 +87,7 @@ func TestTrustInspectCommandRepositoryErrors(t *testing.T) {
cmd := newInspectCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.err)
if tc.golden != "" {
golden.Assert(t, cli.OutBuffer().String(), tc.golden)

View File

@ -42,6 +42,7 @@ func TestTrustKeyGenerateErrors(t *testing.T) {
cmd := newKeyGenerateCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -50,8 +51,8 @@ func TestGenerateKeySuccess(t *testing.T) {
pubKeyCWD := t.TempDir()
privKeyStorageDir := t.TempDir()
passwd := "password"
cannedPasswordRetriever := passphrase.ConstantRetriever(passwd)
const testPass = "password"
cannedPasswordRetriever := passphrase.ConstantRetriever(testPass)
// generate a single key
keyName := "alice"
privKeyFileStore, err := trustmanager.NewKeyFileStore(privKeyStorageDir, cannedPasswordRetriever)
@ -87,7 +88,7 @@ func TestGenerateKeySuccess(t *testing.T) {
// assert encrypted header
assert.Check(t, is.Equal("ENCRYPTED PRIVATE KEY", privKeyPEM.Type))
// check that the passphrase matches
_, err = tufutils.ParsePKCS8ToTufKey(privKeyPEM.Bytes, []byte(passwd))
_, err = tufutils.ParsePKCS8ToTufKey(privKeyPEM.Bytes, []byte(testPass))
assert.NilError(t, err)
// check that the public key exists at the correct path if we use the helper:

View File

@ -63,6 +63,7 @@ func TestTrustKeyLoadErrors(t *testing.T) {
cmd := newKeyLoadCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
assert.Check(t, is.Contains(cli.OutBuffer().String(), tc.expectedOutput))
}

View File

@ -52,6 +52,7 @@ func TestTrustRevokeCommandErrors(t *testing.T) {
test.NewFakeCli(&fakeClient{}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -139,6 +140,7 @@ func TestTrustRevokeCommand(t *testing.T) {
cmd := newRevokeCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
if tc.expectedErr != "" {
assert.ErrorContains(t, cmd.Execute(), tc.expectedErr)
} else {
@ -164,6 +166,8 @@ func TestRevokeTrustPromptTermination(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cmd := newRevokeCommand(cli)
cmd.SetArgs([]string{"example/trust-demo"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
test.TerminatePrompt(ctx, t, cmd, cli)
golden.Assert(t, cli.OutBuffer().String(), "trust-revoke-prompt-termination.golden")
}

View File

@ -67,6 +67,7 @@ func TestTrustSignCommandErrors(t *testing.T) {
test.NewFakeCli(&fakeClient{}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -77,6 +78,7 @@ func TestTrustSignCommandOfflineErrors(t *testing.T) {
cmd := newSignCommand(cli)
cmd.SetArgs([]string{"reg-name.io/image:tag"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "client is offline")
}
@ -260,6 +262,7 @@ func TestSignCommandChangeListIsCleanedOnError(t *testing.T) {
cmd := newSignCommand(cli)
cmd.SetArgs([]string{"ubuntu:latest"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
err := cmd.Execute()
assert.Assert(t, err != nil)
@ -277,5 +280,6 @@ func TestSignCommandLocalFlag(t *testing.T) {
cmd := newSignCommand(cli)
cmd.SetArgs([]string{"--local", "reg-name.io/image:red"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "error contacting notary server: dial tcp: lookup reg-name.io")
}

View File

@ -60,6 +60,7 @@ func TestTrustSignerAddErrors(t *testing.T) {
cmd := newSignerAddCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -78,6 +79,7 @@ func TestSignerAddCommandNoTargetsKey(t *testing.T) {
cmd.SetArgs([]string{"--key", tmpfile.Name(), "alice", "alpine", "linuxkit/alpine"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Error(t, cmd.Execute(), fmt.Sprintf("could not parse public key from file: %s: no valid public key found", tmpfile.Name()))
}
@ -90,6 +92,7 @@ func TestSignerAddCommandBadKeyPath(t *testing.T) {
cmd.SetArgs([]string{"--key", "/path/to/key.pem", "alice", "alpine"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
expectedError := "unable to read public key from file: open /path/to/key.pem: no such file or directory"
if runtime.GOOS == "windows" {
expectedError = "unable to read public key from file: open /path/to/key.pem: The system cannot find the path specified."
@ -111,6 +114,7 @@ func TestSignerAddCommandInvalidRepoName(t *testing.T) {
cmd.SetArgs([]string{"--key", pubKeyFilepath, "alice", imageName})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Error(t, cmd.Execute(), "failed to add signer to: 870d292919d01a0af7e7f056271dc78792c05f55f49b9b9012b6d89725bd9abd")
expectedErr := fmt.Sprintf("invalid repository name (%s), cannot specify 64-byte hexadecimal strings\n\n", imageName)

View File

@ -30,41 +30,54 @@ func TestTrustSignerRemoveErrors(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
cmd := newSignerRemoveCommand(
test.NewFakeCli(&fakeClient{}))
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
testCasesWithOutput := []struct {
name string
args []string
expectedError string
expectedErrOut string
}{
{
name: "not-an-image",
args: []string{"user", "notanimage"},
expectedError: "error retrieving signers for notanimage",
expectedError: "error removing signer from: notanimage",
expectedErrOut: "error retrieving signers for notanimage",
},
{
name: "sha-reference",
args: []string{"user", "870d292919d01a0af7e7f056271dc78792c05f55f49b9b9012b6d89725bd9abd"},
expectedError: "invalid repository name",
expectedError: "error removing signer from: 870d292919d01a0af7e7f056271dc78792c05f55f49b9b9012b6d89725bd9abd",
expectedErrOut: "invalid repository name",
},
{
name: "invalid-img-reference",
args: []string{"user", "ALPINE"},
expectedError: "invalid reference format",
expectedError: "error removing signer from: ALPINE",
expectedErrOut: "invalid reference format",
},
}
for _, tc := range testCasesWithOutput {
tc := tc
t.Run(tc.name, func(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(notaryfake.GetOfflineNotaryRepository)
cmd := newSignerRemoveCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.Execute()
assert.Check(t, is.Contains(cli.ErrBuffer().String(), tc.expectedError))
cmd.SetErr(io.Discard)
err := cmd.Execute()
assert.Check(t, is.Error(err, tc.expectedError))
assert.Check(t, is.Contains(cli.ErrBuffer().String(), tc.expectedErrOut))
})
}
}

View File

@ -166,6 +166,8 @@ 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,
})
@ -173,8 +175,11 @@ func TestVolumePrunePromptNo(t *testing.T) {
cli.SetIn(streams.NewIn(io.NopCloser(strings.NewReader(input))))
cmd := NewPruneCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), "volume prune has been cancelled")
golden.Assert(t, cli.OutBuffer().String(), "volume-prune-no.golden")
})
}
}
@ -199,6 +204,8 @@ func TestVolumePrunePromptTerminate(t *testing.T) {
cmd := NewPruneCommand(cli)
cmd.SetArgs([]string{})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
test.TerminatePrompt(ctx, t, cmd, cli)
golden.Assert(t, cli.OutBuffer().String(), "volume-prune-terminate.golden")
}

View File

@ -303,6 +303,7 @@ func (configFile *ConfigFile) GetAllCredentials() (map[string]types.AuthConfig,
for registryHostname := range configFile.CredentialHelpers {
newAuth, err := configFile.GetAuthConfig(registryHostname)
if err != nil {
// TODO(thaJeztah): use context-logger, so that this output can be suppressed (in tests).
logrus.WithError(err).Warnf("Failed to get credentials for registry: %s", registryHostname)
continue
}

View File

@ -144,5 +144,6 @@ func newDummyCommand(validationFunc cobra.PositionalArgs) *cobra.Command {
},
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
return cmd
}

View File

@ -149,6 +149,7 @@ func ConvertPortToPortConfig(
for _, binding := range portBindings[port] {
if p := net.ParseIP(binding.HostIP); p != nil && !p.IsUnspecified() {
// TODO(thaJeztah): use context-logger, so that this output can be suppressed (in tests).
logrus.Warnf("ignoring IP-address (%s:%s) service will listen on '0.0.0.0'", net.JoinHostPort(binding.HostIP, binding.HostPort), port)
}