copy_test.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package container // import "github.com/docker/docker/integration/container"
  2. import (
  3. "archive/tar"
  4. "context"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "os"
  9. "testing"
  10. "github.com/docker/docker/api/types"
  11. "github.com/docker/docker/client"
  12. "github.com/docker/docker/integration/internal/container"
  13. "github.com/docker/docker/pkg/jsonmessage"
  14. "github.com/docker/docker/testutil/fakecontext"
  15. "gotest.tools/v3/assert"
  16. is "gotest.tools/v3/assert/cmp"
  17. "gotest.tools/v3/skip"
  18. )
  19. func TestCopyFromContainerPathDoesNotExist(t *testing.T) {
  20. defer setupTest(t)()
  21. ctx := context.Background()
  22. apiclient := testEnv.APIClient()
  23. cid := container.Create(ctx, t, apiclient)
  24. _, _, err := apiclient.CopyFromContainer(ctx, cid, "/dne")
  25. assert.Check(t, client.IsErrNotFound(err))
  26. expected := fmt.Sprintf("No such container:path: %s:%s", cid, "/dne")
  27. assert.Check(t, is.ErrorContains(err, expected))
  28. }
  29. func TestCopyFromContainerPathIsNotDir(t *testing.T) {
  30. defer setupTest(t)()
  31. ctx := context.Background()
  32. apiclient := testEnv.APIClient()
  33. cid := container.Create(ctx, t, apiclient)
  34. path := "/etc/passwd/"
  35. expected := "not a directory"
  36. if testEnv.OSType == "windows" {
  37. path = "c:/windows/system32/drivers/etc/hosts/"
  38. expected = "The filename, directory name, or volume label syntax is incorrect."
  39. }
  40. _, _, err := apiclient.CopyFromContainer(ctx, cid, path)
  41. assert.Assert(t, is.ErrorContains(err, expected))
  42. }
  43. func TestCopyToContainerPathDoesNotExist(t *testing.T) {
  44. defer setupTest(t)()
  45. ctx := context.Background()
  46. apiclient := testEnv.APIClient()
  47. cid := container.Create(ctx, t, apiclient)
  48. err := apiclient.CopyToContainer(ctx, cid, "/dne", nil, types.CopyToContainerOptions{})
  49. assert.Check(t, client.IsErrNotFound(err))
  50. expected := fmt.Sprintf("No such container:path: %s:%s", cid, "/dne")
  51. assert.Check(t, is.ErrorContains(err, expected))
  52. }
  53. func TestCopyToContainerPathIsNotDir(t *testing.T) {
  54. defer setupTest(t)()
  55. ctx := context.Background()
  56. apiclient := testEnv.APIClient()
  57. cid := container.Create(ctx, t, apiclient)
  58. path := "/etc/passwd/"
  59. if testEnv.OSType == "windows" {
  60. path = "c:/windows/system32/drivers/etc/hosts/"
  61. }
  62. err := apiclient.CopyToContainer(ctx, cid, path, nil, types.CopyToContainerOptions{})
  63. assert.Assert(t, is.ErrorContains(err, "not a directory"))
  64. }
  65. func TestCopyFromContainer(t *testing.T) {
  66. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  67. defer setupTest(t)()
  68. ctx := context.Background()
  69. apiClient := testEnv.APIClient()
  70. dir, err := os.MkdirTemp("", t.Name())
  71. assert.NilError(t, err)
  72. defer os.RemoveAll(dir)
  73. buildCtx := fakecontext.New(t, dir, fakecontext.WithFile("foo", "hello"), fakecontext.WithFile("baz", "world"), fakecontext.WithDockerfile(`
  74. FROM busybox
  75. COPY foo /foo
  76. COPY baz /bar/quux/baz
  77. RUN ln -s notexist /bar/notarget && ln -s quux/baz /bar/filesymlink && ln -s quux /bar/dirsymlink && ln -s / /bar/root
  78. CMD /fake
  79. `))
  80. defer buildCtx.Close()
  81. resp, err := apiClient.ImageBuild(ctx, buildCtx.AsTarReader(t), types.ImageBuildOptions{})
  82. assert.NilError(t, err)
  83. defer resp.Body.Close()
  84. var imageID string
  85. err = jsonmessage.DisplayJSONMessagesStream(resp.Body, io.Discard, 0, false, func(msg jsonmessage.JSONMessage) {
  86. var r types.BuildResult
  87. assert.NilError(t, json.Unmarshal(*msg.Aux, &r))
  88. imageID = r.ID
  89. })
  90. assert.NilError(t, err)
  91. assert.Assert(t, imageID != "")
  92. cid := container.Create(ctx, t, apiClient, container.WithImage(imageID))
  93. for _, x := range []struct {
  94. src string
  95. expect map[string]string
  96. }{
  97. {"/", map[string]string{"/": "", "/foo": "hello", "/bar/quux/baz": "world", "/bar/filesymlink": "", "/bar/dirsymlink": "", "/bar/notarget": ""}},
  98. {"/bar/root", map[string]string{"root": ""}},
  99. {"/bar/root/", map[string]string{"root/": "", "root/foo": "hello", "root/bar/quux/baz": "world", "root/bar/filesymlink": "", "root/bar/dirsymlink": "", "root/bar/notarget": ""}},
  100. {"bar/quux", map[string]string{"quux/": "", "quux/baz": "world"}},
  101. {"bar/quux/", map[string]string{"quux/": "", "quux/baz": "world"}},
  102. {"bar/quux/baz", map[string]string{"baz": "world"}},
  103. {"bar/filesymlink", map[string]string{"filesymlink": ""}},
  104. {"bar/dirsymlink", map[string]string{"dirsymlink": ""}},
  105. {"bar/dirsymlink/", map[string]string{"dirsymlink/": "", "dirsymlink/baz": "world"}},
  106. {"bar/notarget", map[string]string{"notarget": ""}},
  107. } {
  108. t.Run(x.src, func(t *testing.T) {
  109. rdr, _, err := apiClient.CopyFromContainer(ctx, cid, x.src)
  110. assert.NilError(t, err)
  111. defer rdr.Close()
  112. found := make(map[string]bool, len(x.expect))
  113. var numFound int
  114. tr := tar.NewReader(rdr)
  115. for numFound < len(x.expect) {
  116. h, err := tr.Next()
  117. if err == io.EOF {
  118. break
  119. }
  120. assert.NilError(t, err)
  121. expected, exists := x.expect[h.Name]
  122. if !exists {
  123. // this archive will have extra stuff in it since we are copying from root
  124. // and docker adds a bunch of stuff
  125. continue
  126. }
  127. numFound++
  128. found[h.Name] = true
  129. buf, err := io.ReadAll(tr)
  130. if err == nil {
  131. assert.Check(t, is.Equal(string(buf), expected))
  132. }
  133. }
  134. for f := range x.expect {
  135. assert.Check(t, found[f], f+" not found in archive")
  136. }
  137. })
  138. }
  139. }