daemon/delete_test.go
4f0d95fa
 package daemon // import "github.com/docker/docker/daemon"
c4e49d10
 
 import (
9a58f298
 	"fmt"
c4e49d10
 	"io/ioutil"
 	"os"
 	"testing"
 
91e197d6
 	"github.com/docker/docker/api/types"
 	containertypes "github.com/docker/docker/api/types/container"
6bb0d181
 	"github.com/docker/docker/container"
38457285
 	"gotest.tools/assert"
 	is "gotest.tools/assert/cmp"
c4e49d10
 )
 
2759194d
 func newDaemonWithTmpRoot(t *testing.T) (*Daemon, func()) {
c4e49d10
 	tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-")
6be0f709
 	assert.NilError(t, err)
2759194d
 	d := &Daemon{
c4e49d10
 		repository: tmp,
 		root:       tmp,
 	}
2759194d
 	d.containers = container.NewMemoryStore()
 	return d, func() { os.RemoveAll(tmp) }
 }
 
8f517469
 func newContainerWithState(state *container.State) *container.Container {
 	return &container.Container{
55f8828e
 		ID:     "test",
 		State:  state,
 		Config: &containertypes.Config{},
2759194d
 	}
 }
 
8f517469
 // 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 {
 		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",
 			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",
 			initContainer: func() *container.Container {
 				c := newContainerWithState(container.NewState())
 				c.SetRunning(0, true)
 				c.SetRestarting(&container.ExitStatus{})
 				return c
 			}},
 		// a running container
 		{
 			errMsg: "cannot remove a running container",
 			fixMsg: "Stop the container before attempting removal or force remove",
 			initContainer: func() *container.Container {
 				return newContainerWithState(&container.State{Running: true})
 			}},
2759194d
 	}
 
8f517469
 	for _, te := range tt {
 		c := te.initContainer()
 		d, cleanup := newDaemonWithTmpRoot(t)
 		defer cleanup()
 		d.containers.Add(c.ID, c)
2759194d
 
8f517469
 		err := d.ContainerRm(c.ID, &types.ContainerRmConfig{ForceRemove: false})
55bebbae
 		assert.Check(t, is.ErrorContains(err, te.errMsg))
 		assert.Check(t, is.ErrorContains(err, te.fixMsg))
2759194d
 	}
 }
 
 func TestContainerDoubleDelete(t *testing.T) {
8f517469
 	c := newContainerWithState(container.NewState())
c4e49d10
 
 	// Mark the container as having a delete in progress
2759194d
 	c.SetRemovalInProgress()
 
 	d, cleanup := newDaemonWithTmpRoot(t)
 	defer cleanup()
 	d.containers.Add(c.ID, c)
c4e49d10
 
9a58f298
 	// Try to remove the container when its state is removalInProgress.
 	// It should return an error indicating it is under removal progress.
2759194d
 	err := d.ContainerRm(c.ID, &types.ContainerRmConfig{ForceRemove: true})
55bebbae
 	assert.Check(t, is.ErrorContains(err, fmt.Sprintf("removal of container %s is already in progress", c.ID)))
c4e49d10
 }