daemon_test.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package daemon // import "github.com/docker/docker/integration/daemon"
  2. import (
  3. "context"
  4. "runtime"
  5. "testing"
  6. "github.com/docker/docker/api/types"
  7. "github.com/docker/docker/api/types/mount"
  8. "github.com/docker/docker/api/types/volume"
  9. "github.com/docker/docker/integration/internal/container"
  10. "github.com/docker/docker/testutil/daemon"
  11. "gotest.tools/v3/assert"
  12. "gotest.tools/v3/skip"
  13. )
  14. func TestLiveRestore(t *testing.T) {
  15. skip.If(t, runtime.GOOS == "windows", "cannot start multiple daemons on windows")
  16. t.Run("volume references", testLiveRestoreVolumeReferences)
  17. }
  18. func testLiveRestoreVolumeReferences(t *testing.T) {
  19. t.Parallel()
  20. d := daemon.New(t)
  21. d.StartWithBusybox(t, "--live-restore", "--iptables=false")
  22. defer func() {
  23. d.Stop(t)
  24. d.Cleanup(t)
  25. }()
  26. c := d.NewClientT(t)
  27. ctx := context.Background()
  28. runTest := func(t *testing.T, policy string) {
  29. t.Run(policy, func(t *testing.T) {
  30. volName := "test-live-restore-volume-references-" + policy
  31. _, err := c.VolumeCreate(ctx, volume.VolumeCreateBody{Name: volName})
  32. assert.NilError(t, err)
  33. // Create a container that uses the volume
  34. m := mount.Mount{
  35. Type: mount.TypeVolume,
  36. Source: volName,
  37. Target: "/foo",
  38. }
  39. cID := container.Run(ctx, t, c, container.WithMount(m), container.WithCmd("top"), container.WithRestartPolicy(policy))
  40. defer c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true})
  41. // Stop the daemon
  42. d.Restart(t, "--live-restore", "--iptables=false")
  43. // Try to remove the volume
  44. err = c.VolumeRemove(ctx, volName, false)
  45. assert.ErrorContains(t, err, "volume is in use")
  46. _, err = c.VolumeInspect(ctx, volName)
  47. assert.NilError(t, err)
  48. })
  49. }
  50. t.Run("restartPolicy", func(t *testing.T) {
  51. runTest(t, "always")
  52. runTest(t, "unless-stopped")
  53. runTest(t, "on-failure")
  54. runTest(t, "no")
  55. })
  56. // Make sure that the local volume driver's mount ref count is restored
  57. // Addresses https://github.com/moby/moby/issues/44422
  58. t.Run("local volume with mount options", func(t *testing.T) {
  59. v, err := c.VolumeCreate(ctx, volume.VolumeCreateBody{
  60. Driver: "local",
  61. Name: "test-live-restore-volume-references-local",
  62. DriverOpts: map[string]string{
  63. "type": "tmpfs",
  64. "device": "tmpfs",
  65. },
  66. })
  67. assert.NilError(t, err)
  68. m := mount.Mount{
  69. Type: mount.TypeVolume,
  70. Source: v.Name,
  71. Target: "/foo",
  72. }
  73. cID := container.Run(ctx, t, c, container.WithMount(m), container.WithCmd("top"))
  74. defer c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true})
  75. d.Restart(t, "--live-restore", "--iptables=false")
  76. // Try to remove the volume
  77. // This should fail since its used by a container
  78. err = c.VolumeRemove(ctx, v.Name, false)
  79. assert.ErrorContains(t, err, "volume is in use")
  80. // Remove that container which should free the references in the volume
  81. err = c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true})
  82. assert.NilError(t, err)
  83. // Now we should be able to remove the volume
  84. err = c.VolumeRemove(ctx, v.Name, false)
  85. assert.NilError(t, err)
  86. })
  87. }