Просмотр исходного кода

Merge pull request #45720 from ndeloof/copy_uidgid

fix `docker cp -a` failing to access `/` in container
Sebastiaan van Stijn 2 лет назад
Родитель
Сommit
a9788886e6
2 измененных файлов с 39 добавлено и 20 удалено
  1. 35 19
      integration/container/copy_test.go
  2. 4 1
      pkg/idtools/idtools_unix.go

+ 35 - 19
integration/container/copy_test.go

@@ -65,6 +65,34 @@ func TestCopyToContainerPathDoesNotExist(t *testing.T) {
 func TestCopyEmptyFile(t *testing.T) {
 	defer setupTest(t)()
 
+	ctx := context.Background()
+	apiclient := testEnv.APIClient()
+	cid := container.Create(ctx, t, apiclient)
+
+	// empty content
+	dstDir, _ := makeEmptyArchive(t)
+	err := apiclient.CopyToContainer(ctx, cid, dstDir, bytes.NewReader([]byte("")), types.CopyToContainerOptions{})
+	assert.NilError(t, err)
+
+	// tar with empty file
+	dstDir, preparedArchive := makeEmptyArchive(t)
+	err = apiclient.CopyToContainer(ctx, cid, dstDir, preparedArchive, types.CopyToContainerOptions{})
+	assert.NilError(t, err)
+
+	// tar with empty file archive mode
+	dstDir, preparedArchive = makeEmptyArchive(t)
+	err = apiclient.CopyToContainer(ctx, cid, dstDir, preparedArchive, types.CopyToContainerOptions{
+		CopyUIDGID: true,
+	})
+	assert.NilError(t, err)
+
+	// copy from empty file
+	rdr, _, err := apiclient.CopyFromContainer(ctx, cid, dstDir)
+	assert.NilError(t, err)
+	defer rdr.Close()
+}
+
+func makeEmptyArchive(t *testing.T) (string, io.ReadCloser) {
 	tmpDir := t.TempDir()
 	srcPath := filepath.Join(tmpDir, "empty-file.txt")
 	err := os.WriteFile(srcPath, []byte(""), 0400)
@@ -77,30 +105,18 @@ func TestCopyEmptyFile(t *testing.T) {
 
 	srcArchive, err := archive.TarResource(srcInfo)
 	assert.NilError(t, err)
-	defer srcArchive.Close()
+	t.Cleanup(func() {
+		srcArchive.Close()
+	})
 
 	ctrPath := "/empty-file.txt"
 	dstInfo := archive.CopyInfo{Path: ctrPath}
 	dstDir, preparedArchive, err := archive.PrepareArchiveCopy(srcArchive, srcInfo, dstInfo)
 	assert.NilError(t, err)
-	defer preparedArchive.Close()
-
-	ctx := context.Background()
-	apiclient := testEnv.APIClient()
-	cid := container.Create(ctx, t, apiclient)
-
-	// empty content
-	err = apiclient.CopyToContainer(ctx, cid, dstDir, bytes.NewReader([]byte("")), types.CopyToContainerOptions{})
-	assert.NilError(t, err)
-
-	// tar with empty file
-	err = apiclient.CopyToContainer(ctx, cid, dstDir, preparedArchive, types.CopyToContainerOptions{})
-	assert.NilError(t, err)
-
-	// copy from empty file
-	rdr, _, err := apiclient.CopyFromContainer(ctx, cid, dstDir)
-	assert.NilError(t, err)
-	defer rdr.Close()
+	t.Cleanup(func() {
+		preparedArchive.Close()
+	})
+	return dstDir, preparedArchive
 }
 
 func TestCopyToContainerPathIsNotDir(t *testing.T) {

+ 4 - 1
pkg/idtools/idtools_unix.go

@@ -166,7 +166,10 @@ func callGetent(database, key string) (io.Reader, error) {
 	if getentCmd == "" {
 		return nil, fmt.Errorf("unable to find getent command")
 	}
-	out, err := exec.Command(getentCmd, database, key).CombinedOutput()
+	command := exec.Command(getentCmd, database, key)
+	// we run getent within container filesystem, but without /dev so /dev/null is not available for exec to mock stdin
+	command.Stdin = io.NopCloser(bytes.NewReader(nil))
+	out, err := command.CombinedOutput()
 	if err != nil {
 		exitCode, errC := getExitCode(err)
 		if errC != nil {