github.com/wozhu6104/docker@v20.10.10+incompatible/daemon/delete_test.go (about) 1 package daemon // import "github.com/docker/docker/daemon" 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "testing" 8 9 "github.com/docker/docker/api/types" 10 containertypes "github.com/docker/docker/api/types/container" 11 "github.com/docker/docker/container" 12 "gotest.tools/v3/assert" 13 is "gotest.tools/v3/assert/cmp" 14 ) 15 16 func newDaemonWithTmpRoot(t *testing.T) (*Daemon, func()) { 17 tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-") 18 assert.NilError(t, err) 19 d := &Daemon{ 20 repository: tmp, 21 root: tmp, 22 } 23 d.containers = container.NewMemoryStore() 24 return d, func() { os.RemoveAll(tmp) } 25 } 26 27 func newContainerWithState(state *container.State) *container.Container { 28 return &container.Container{ 29 ID: "test", 30 State: state, 31 Config: &containertypes.Config{}, 32 } 33 } 34 35 // TestContainerDelete tests that a useful error message and instructions is 36 // given when attempting to remove a container (#30842) 37 func TestContainerDelete(t *testing.T) { 38 tt := []struct { 39 errMsg string 40 fixMsg string 41 initContainer func() *container.Container 42 }{ 43 // a paused container 44 { 45 errMsg: "cannot remove a paused container", 46 fixMsg: "Unpause and then stop the container before attempting removal or force remove", 47 initContainer: func() *container.Container { 48 return newContainerWithState(&container.State{Paused: true, Running: true}) 49 }}, 50 // a restarting container 51 { 52 errMsg: "cannot remove a restarting container", 53 fixMsg: "Stop the container before attempting removal or force remove", 54 initContainer: func() *container.Container { 55 c := newContainerWithState(container.NewState()) 56 c.SetRunning(0, true) 57 c.SetRestarting(&container.ExitStatus{}) 58 return c 59 }}, 60 // a running container 61 { 62 errMsg: "cannot remove a running container", 63 fixMsg: "Stop the container before attempting removal or force remove", 64 initContainer: func() *container.Container { 65 return newContainerWithState(&container.State{Running: true}) 66 }}, 67 } 68 69 for _, te := range tt { 70 c := te.initContainer() 71 d, cleanup := newDaemonWithTmpRoot(t) 72 defer cleanup() 73 d.containers.Add(c.ID, c) 74 75 err := d.ContainerRm(c.ID, &types.ContainerRmConfig{ForceRemove: false}) 76 assert.Check(t, is.ErrorContains(err, te.errMsg)) 77 assert.Check(t, is.ErrorContains(err, te.fixMsg)) 78 } 79 } 80 81 func TestContainerDoubleDelete(t *testing.T) { 82 c := newContainerWithState(container.NewState()) 83 84 // Mark the container as having a delete in progress 85 c.SetRemovalInProgress() 86 87 d, cleanup := newDaemonWithTmpRoot(t) 88 defer cleanup() 89 d.containers.Add(c.ID, c) 90 91 // Try to remove the container when its state is removalInProgress. 92 // It should return an error indicating it is under removal progress. 93 err := d.ContainerRm(c.ID, &types.ContainerRmConfig{ForceRemove: true}) 94 assert.Check(t, is.ErrorContains(err, fmt.Sprintf("removal of container %s is already in progress", c.ID))) 95 }