mirror of https://github.com/docker/cli.git
207 lines
5.8 KiB
Go
207 lines
5.8 KiB
Go
package container
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/docker/cli/internal/test"
|
|
"github.com/docker/docker/api/types/container"
|
|
"github.com/docker/docker/pkg/archive"
|
|
"gotest.tools/v3/assert"
|
|
is "gotest.tools/v3/assert/cmp"
|
|
"gotest.tools/v3/fs"
|
|
)
|
|
|
|
func TestRunCopyWithInvalidArguments(t *testing.T) {
|
|
testcases := []struct {
|
|
doc string
|
|
options copyOptions
|
|
expectedErr string
|
|
}{
|
|
{
|
|
doc: "copy between container",
|
|
options: copyOptions{
|
|
source: "first:/path",
|
|
destination: "second:/path",
|
|
},
|
|
expectedErr: "copying between containers is not supported",
|
|
},
|
|
{
|
|
doc: "copy without a container",
|
|
options: copyOptions{
|
|
source: "./source",
|
|
destination: "./dest",
|
|
},
|
|
expectedErr: "must specify at least one container source",
|
|
},
|
|
}
|
|
for _, testcase := range testcases {
|
|
t.Run(testcase.doc, func(t *testing.T) {
|
|
err := runCopy(context.TODO(), test.NewFakeCli(nil), testcase.options)
|
|
assert.Error(t, err, testcase.expectedErr)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRunCopyFromContainerToStdout(t *testing.T) {
|
|
tarContent := "the tar content"
|
|
|
|
cli := test.NewFakeCli(&fakeClient{
|
|
containerCopyFromFunc: func(ctr, srcPath string) (io.ReadCloser, container.PathStat, error) {
|
|
assert.Check(t, is.Equal("container", ctr))
|
|
return io.NopCloser(strings.NewReader(tarContent)), container.PathStat{}, nil
|
|
},
|
|
})
|
|
err := runCopy(context.TODO(), cli, copyOptions{
|
|
source: "container:/path",
|
|
destination: "-",
|
|
})
|
|
assert.NilError(t, err)
|
|
assert.Check(t, is.Equal(tarContent, cli.OutBuffer().String()))
|
|
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
|
}
|
|
|
|
func TestRunCopyFromContainerToFilesystem(t *testing.T) {
|
|
destDir := fs.NewDir(t, "cp-test",
|
|
fs.WithFile("file1", "content\n"))
|
|
defer destDir.Remove()
|
|
|
|
cli := test.NewFakeCli(&fakeClient{
|
|
containerCopyFromFunc: func(ctr, srcPath string) (io.ReadCloser, container.PathStat, error) {
|
|
assert.Check(t, is.Equal("container", ctr))
|
|
readCloser, err := archive.TarWithOptions(destDir.Path(), &archive.TarOptions{})
|
|
return readCloser, container.PathStat{}, err
|
|
},
|
|
})
|
|
err := runCopy(context.TODO(), cli, copyOptions{
|
|
source: "container:/path",
|
|
destination: destDir.Path(),
|
|
quiet: true,
|
|
})
|
|
assert.NilError(t, err)
|
|
assert.Check(t, is.Equal("", cli.OutBuffer().String()))
|
|
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
|
|
|
|
content, err := os.ReadFile(destDir.Join("file1"))
|
|
assert.NilError(t, err)
|
|
assert.Check(t, is.Equal("content\n", string(content)))
|
|
}
|
|
|
|
func TestRunCopyFromContainerToFilesystemMissingDestinationDirectory(t *testing.T) {
|
|
destDir := fs.NewDir(t, "cp-test",
|
|
fs.WithFile("file1", "content\n"))
|
|
defer destDir.Remove()
|
|
|
|
cli := test.NewFakeCli(&fakeClient{
|
|
containerCopyFromFunc: func(ctr, srcPath string) (io.ReadCloser, container.PathStat, error) {
|
|
assert.Check(t, is.Equal("container", ctr))
|
|
readCloser, err := archive.TarWithOptions(destDir.Path(), &archive.TarOptions{})
|
|
return readCloser, container.PathStat{}, err
|
|
},
|
|
})
|
|
err := runCopy(context.TODO(), cli, copyOptions{
|
|
source: "container:/path",
|
|
destination: destDir.Join("missing", "foo"),
|
|
})
|
|
assert.ErrorContains(t, err, destDir.Join("missing"))
|
|
}
|
|
|
|
func TestRunCopyToContainerFromFileWithTrailingSlash(t *testing.T) {
|
|
srcFile := fs.NewFile(t, t.Name())
|
|
defer srcFile.Remove()
|
|
|
|
cli := test.NewFakeCli(&fakeClient{})
|
|
err := runCopy(context.TODO(), cli, copyOptions{
|
|
source: srcFile.Path() + string(os.PathSeparator),
|
|
destination: "container:/path",
|
|
})
|
|
|
|
expectedError := "not a directory"
|
|
if runtime.GOOS == "windows" {
|
|
expectedError = "The filename, directory name, or volume label syntax is incorrect"
|
|
}
|
|
assert.ErrorContains(t, err, expectedError)
|
|
}
|
|
|
|
func TestRunCopyToContainerSourceDoesNotExist(t *testing.T) {
|
|
cli := test.NewFakeCli(&fakeClient{})
|
|
err := runCopy(context.TODO(), cli, copyOptions{
|
|
source: "/does/not/exist",
|
|
destination: "container:/path",
|
|
})
|
|
expected := "no such file or directory"
|
|
if runtime.GOOS == "windows" {
|
|
expected = "cannot find the file specified"
|
|
}
|
|
assert.ErrorContains(t, err, expected)
|
|
}
|
|
|
|
func TestSplitCpArg(t *testing.T) {
|
|
testcases := []struct {
|
|
doc string
|
|
path string
|
|
os string
|
|
expectedContainer string
|
|
expectedPath string
|
|
}{
|
|
{
|
|
doc: "absolute path with colon",
|
|
os: "unix",
|
|
path: "/abs/path:withcolon",
|
|
expectedPath: "/abs/path:withcolon",
|
|
},
|
|
{
|
|
doc: "relative path with colon",
|
|
path: "./relative:path",
|
|
expectedPath: "./relative:path",
|
|
},
|
|
{
|
|
doc: "absolute path with drive",
|
|
os: "windows",
|
|
path: `d:\abs\path`,
|
|
expectedPath: `d:\abs\path`,
|
|
},
|
|
{
|
|
doc: "no separator",
|
|
path: "relative/path",
|
|
expectedPath: "relative/path",
|
|
},
|
|
{
|
|
doc: "with separator",
|
|
path: "container:/opt/foo",
|
|
expectedPath: "/opt/foo",
|
|
expectedContainer: "container",
|
|
},
|
|
}
|
|
for _, tc := range testcases {
|
|
tc := tc
|
|
t.Run(tc.doc, func(t *testing.T) {
|
|
if tc.os == "windows" && runtime.GOOS != "windows" {
|
|
t.Skip("skipping windows test on non-windows platform")
|
|
}
|
|
if tc.os == "unix" && runtime.GOOS == "windows" {
|
|
t.Skip("skipping unix test on windows")
|
|
}
|
|
|
|
ctr, path := splitCpArg(tc.path)
|
|
assert.Check(t, is.Equal(tc.expectedContainer, ctr))
|
|
assert.Check(t, is.Equal(tc.expectedPath, path))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRunCopyFromContainerToFilesystemIrregularDestination(t *testing.T) {
|
|
cli := test.NewFakeCli(nil)
|
|
err := runCopy(context.TODO(), cli, copyOptions{
|
|
source: "container:/dev/null",
|
|
destination: "/dev/random",
|
|
})
|
|
assert.Assert(t, err != nil)
|
|
expected := `"/dev/random" must be a directory or a regular file`
|
|
assert.ErrorContains(t, err, expected)
|
|
}
|