diff --git a/cli/command/container/client_test.go b/cli/command/container/client_test.go index 67ae04904f..3643550b92 100644 --- a/cli/command/container/client_test.go +++ b/cli/command/container/client_test.go @@ -31,6 +31,7 @@ type fakeClient struct { containerListFunc func(types.ContainerListOptions) ([]types.Container, error) containerExportFunc func(string) (io.ReadCloser, error) containerExecResizeFunc func(id string, options types.ResizeOptions) error + containerRemoveFunc func(ctx context.Context, container string, options types.ContainerRemoveOptions) error Version string } @@ -80,6 +81,13 @@ func (f *fakeClient) ContainerCreate( return container.ContainerCreateCreatedBody{}, nil } +func (f *fakeClient) ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error { + if f.containerRemoveFunc != nil { + return f.containerRemoveFunc(ctx, container, options) + } + return nil +} + func (f *fakeClient) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) { if f.imageCreateFunc != nil { return f.imageCreateFunc(parentReference, options) diff --git a/cli/command/container/rm.go b/cli/command/container/rm.go index 54ce2ad1a8..2a2528c6f4 100644 --- a/cli/command/container/rm.go +++ b/cli/command/container/rm.go @@ -8,6 +8,7 @@ import ( "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/docker/api/types" + "github.com/docker/docker/errdefs" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -61,6 +62,10 @@ func runRm(dockerCli command.Cli, opts *rmOptions) error { for _, name := range opts.containers { if err := <-errChan; err != nil { + if opts.force && errdefs.IsNotFound(err) { + fmt.Fprintln(dockerCli.Err(), err) + continue + } errs = append(errs, err.Error()) continue } diff --git a/cli/command/container/rm_test.go b/cli/command/container/rm_test.go new file mode 100644 index 0000000000..07c3f490f0 --- /dev/null +++ b/cli/command/container/rm_test.go @@ -0,0 +1,46 @@ +package container + +import ( + "context" + "fmt" + "io/ioutil" + "sort" + "testing" + + "github.com/docker/cli/internal/test" + "github.com/docker/docker/api/types" + "github.com/docker/docker/errdefs" + "gotest.tools/v3/assert" +) + +func TestRemoveForce(t *testing.T) { + var removed []string + + cli := test.NewFakeCli(&fakeClient{ + containerRemoveFunc: func(ctx context.Context, container string, options types.ContainerRemoveOptions) error { + removed = append(removed, container) + if container == "nosuchcontainer" { + return errdefs.NotFound(fmt.Errorf("Error: No such container: " + container)) + } + return nil + }, + Version: "1.36", + }) + cmd := NewRmCommand(cli) + cmd.SetOut(ioutil.Discard) + + t.Run("without force", func(t *testing.T) { + cmd.SetArgs([]string{"nosuchcontainer", "mycontainer"}) + removed = []string{} + assert.ErrorContains(t, cmd.Execute(), "No such container") + sort.Strings(removed) + assert.DeepEqual(t, removed, []string{"mycontainer", "nosuchcontainer"}) + }) + t.Run("with force", func(t *testing.T) { + cmd.SetArgs([]string{"--force", "nosuchcontainer", "mycontainer"}) + removed = []string{} + assert.NilError(t, cmd.Execute()) + sort.Strings(removed) + assert.DeepEqual(t, removed, []string{"mycontainer", "nosuchcontainer"}) + }) +}