daemon: cleanupContainer: slightly cleanup error messages

Also remove integration-cli: `DockerAPISuite.TestContainerAPIDeleteConflict`,
which was testing the same conditions as `TestRemoveContainerRunning` in
integration/container.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2023-08-13 21:47:25 +02:00
parent 69cf2ad6a5
commit 2b583c0923
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
5 changed files with 30 additions and 42 deletions

View file

@ -88,13 +88,11 @@ func (daemon *Daemon) rmLink(cfg *config.Config, container *container.Container,
func (daemon *Daemon) cleanupContainer(container *container.Container, config types.ContainerRmConfig) error {
if container.IsRunning() {
if !config.ForceRemove {
state := container.StateString()
procedure := "Stop the container before attempting removal or force remove"
if state == "paused" {
procedure = "Unpause and then " + strings.ToLower(procedure)
if state := container.StateString(); state == "paused" {
return errdefs.Conflict(fmt.Errorf("cannot remove container %q: container is %s and must be unpaused first", container.Name, state))
} else {
return errdefs.Conflict(fmt.Errorf("cannot remove container %q: container is %s: stop the container before removing or force remove", container.Name, state))
}
err := fmt.Errorf("You cannot remove a %s container %s. %s", state, container.ID, procedure)
return errdefs.Conflict(err)
}
if err := daemon.Kill(container); err != nil && !isNotRunning(err) {
return fmt.Errorf("cannot remove container %q: could not kill: %w", container.Name, err)

View file

@ -8,6 +8,7 @@ import (
"github.com/docker/docker/api/types"
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/container"
"github.com/docker/docker/errdefs"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)
@ -34,23 +35,21 @@ func newContainerWithState(state *container.State) *container.Container {
// TestContainerDelete tests that a useful error message and instructions is
// given when attempting to remove a container (#30842)
func TestContainerDelete(t *testing.T) {
tt := []struct {
tests := []struct {
doc string
errMsg string
fixMsg string
initContainer func() *container.Container
}{
// a paused container
{
errMsg: "cannot remove a paused container",
fixMsg: "Unpause and then stop the container before attempting removal or force remove",
doc: "paused container",
errMsg: "container is paused and must be unpaused first",
initContainer: func() *container.Container {
return newContainerWithState(&container.State{Paused: true, Running: true})
},
},
// a restarting container
{
errMsg: "cannot remove a restarting container",
fixMsg: "Stop the container before attempting removal or force remove",
doc: "restarting container",
errMsg: "container is restarting: stop the container before removing or force remove",
initContainer: func() *container.Container {
c := newContainerWithState(container.NewState())
c.SetRunning(nil, nil, true)
@ -58,25 +57,27 @@ func TestContainerDelete(t *testing.T) {
return c
},
},
// a running container
{
errMsg: "cannot remove a running container",
fixMsg: "Stop the container before attempting removal or force remove",
doc: "running container",
errMsg: "container is running: stop the container before removing or force remove",
initContainer: func() *container.Container {
return newContainerWithState(&container.State{Running: true})
},
},
}
for _, te := range tt {
c := te.initContainer()
d, cleanup := newDaemonWithTmpRoot(t)
defer cleanup()
d.containers.Add(c.ID, c)
for _, tc := range tests {
tc := tc
t.Run(tc.doc, func(t *testing.T) {
c := tc.initContainer()
d, cleanup := newDaemonWithTmpRoot(t)
defer cleanup()
d.containers.Add(c.ID, c)
err := d.ContainerRm(c.ID, &types.ContainerRmConfig{ForceRemove: false})
assert.Check(t, is.ErrorContains(err, te.errMsg))
assert.Check(t, is.ErrorContains(err, te.fixMsg))
err := d.ContainerRm(c.ID, &types.ContainerRmConfig{ForceRemove: false})
assert.Check(t, is.ErrorType(err, errdefs.IsConflict))
assert.Check(t, is.ErrorContains(err, tc.errMsg))
})
}
}

View file

@ -23,10 +23,12 @@ source hack/make/.integration-test-helpers
# TODO re-enable test_attach_no_stream after https://github.com/docker/docker-py/issues/2513 is resolved
# TODO re-enable test_create_with_device_cgroup_rules after https://github.com/docker/docker-py/issues/2939 is resolved
# TODO re-enable test_prune_volumes after https://github.com/docker/docker-py/pull/3051 is resolved
# TODO re-enable test_create_with_restart_policy after https://github.com/docker/docker-py/pull/3165 is included in a release
# TODO re-enable test_api_error_parses_json after https://github.com/docker/docker-py/pull/3165 is included in a release
# TODO re-enable test_connect_with_ipv6_address after we updated to a version of docker-py with https://github.com/docker/docker-py/pull/3169
# TODO re-enable test_create_network_ipv6_enabled after we updated to a version of docker-py with https://github.com/docker/docker-py/pull/3169
# TODO re-enable test_create_with_ipv6_address after we updated to a version of docker-py with https://github.com/docker/docker-py/pull/3169
: "${PY_TEST_OPTIONS:=--junitxml=${DEST}/junit-report.xml --deselect=tests/integration/api_container_test.py::AttachContainerTest::test_attach_no_stream --deselect=tests/integration/api_container_test.py::CreateContainerTest::test_create_with_device_cgroup_rules --deselect=tests/integration/api_volume_test.py::TestVolumes::test_prune_volumes --deselect=tests/integration/api_network_test.py::TestNetworks::test_connect_with_ipv6_address --deselect=tests/integration/api_network_test.py::TestNetworks::test_create_network_ipv6_enabled --deselect=tests/integration/api_network_test.py::TestNetworks::test_create_with_ipv6_address}"
: "${PY_TEST_OPTIONS:=--junitxml=${DEST}/junit-report.xml --deselect=tests/integration/api_container_test.py::AttachContainerTest::test_attach_no_stream --deselect=tests/integration/api_container_test.py::CreateContainerTest::test_create_with_device_cgroup_rules --deselect=tests/integration/api_container_test.py::CreateContainerTest::test_create_with_restart_policy --deselect=tests/integration/api_volume_test.py::TestVolumes::test_prune_volumes --deselect=tests/integration/errors_test.py::ErrorsTest::test_api_error_parses_json --deselect=tests/integration/api_network_test.py::TestNetworks::test_connect_with_ipv6_address --deselect=tests/integration/api_network_test.py::TestNetworks::test_create_network_ipv6_enabled --deselect=tests/integration/api_network_test.py::TestNetworks::test_create_with_ipv6_address}"
(
bundle .integration-daemon-start

View file

@ -1174,21 +1174,6 @@ func (s *DockerAPISuite) TestContainerAPIDeleteRemoveLinks(c *testing.T) {
assert.Equal(c, linksPostRm, "null", "call to api deleteContainer links should have removed the specified links")
}
func (s *DockerAPISuite) TestContainerAPIDeleteConflict(c *testing.T) {
out := runSleepingContainer(c)
id := strings.TrimSpace(out)
assert.NilError(c, waitRun(id))
apiClient, err := client.NewClientWithOpts(client.FromEnv)
assert.NilError(c, err)
defer apiClient.Close()
err = apiClient.ContainerRemove(context.Background(), id, types.ContainerRemoveOptions{})
expected := "cannot remove a running container"
assert.ErrorContains(c, err, expected)
}
func (s *DockerAPISuite) TestContainerAPIDeleteRemoveVolume(c *testing.T) {
testRequires(c, testEnv.IsLocalDaemon)

View file

@ -9,6 +9,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/volume"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/integration/internal/container"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
@ -88,7 +89,8 @@ func TestRemoveContainerRunning(t *testing.T) {
cID := container.Run(ctx, t, apiClient)
err := apiClient.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{})
assert.Check(t, is.ErrorContains(err, "cannot remove a running container"))
assert.Check(t, is.ErrorType(err, errdefs.IsConflict))
assert.Check(t, is.ErrorContains(err, "container is running"))
}
func TestRemoveContainerForceRemoveRunning(t *testing.T) {