delete_test.go 2.8 KB

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