copy_test.go 5.0 KB

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