delete_test.go 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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. // a restarting container
  45. {
  46. errMsg: "cannot remove a restarting container",
  47. fixMsg: "Stop the container before attempting removal or force remove",
  48. initContainer: func() *container.Container {
  49. c := newContainerWithState(container.NewState())
  50. c.SetRunning(0, true)
  51. c.SetRestarting(&container.ExitStatus{})
  52. return c
  53. }},
  54. // a running container
  55. {
  56. errMsg: "cannot remove a running container",
  57. fixMsg: "Stop the container before attempting removal or force remove",
  58. initContainer: func() *container.Container {
  59. return newContainerWithState(&container.State{Running: true})
  60. }},
  61. }
  62. for _, te := range tt {
  63. c := te.initContainer()
  64. d, cleanup := newDaemonWithTmpRoot(t)
  65. defer cleanup()
  66. d.containers.Add(c.ID, c)
  67. err := d.ContainerRm(c.ID, &types.ContainerRmConfig{ForceRemove: false})
  68. assert.Check(t, is.ErrorContains(err, te.errMsg))
  69. assert.Check(t, is.ErrorContains(err, te.fixMsg))
  70. }
  71. }
  72. func TestContainerDoubleDelete(t *testing.T) {
  73. c := newContainerWithState(container.NewState())
  74. // Mark the container as having a delete in progress
  75. c.SetRemovalInProgress()
  76. d, cleanup := newDaemonWithTmpRoot(t)
  77. defer cleanup()
  78. d.containers.Add(c.ID, c)
  79. // Try to remove the container when its state is removalInProgress.
  80. // It should return an error indicating it is under removal progress.
  81. err := d.ContainerRm(c.ID, &types.ContainerRmConfig{ForceRemove: true})
  82. assert.Check(t, is.ErrorContains(err, fmt.Sprintf("removal of container %s is already in progress", c.ID)))
  83. }