Преглед на файлове

Add --chown flag to Dockerfile ADD and COPY

Rebased by @estesp

Signed-off-by: Kara Alexandra <kalexandra@us.ibm.com>
Signed-off-by: Phil Estes <estesp@linux.vnet.ibm.com>
Kara Alexandra преди 8 години
родител
ревизия
858fad3795
променени са 3 файла, в които са добавени 105 реда и са изтрити 0 реда
  1. 2 0
      builder/dockerfile/dispatchers.go
  2. 31 0
      container/container.go
  3. 72 0
      integration-cli/docker_cli_build_test.go

+ 2 - 0
builder/dockerfile/dispatchers.go

@@ -146,6 +146,7 @@ func add(req dispatchRequest) error {
 		return errAtLeastTwoArguments("ADD")
 	}
 
+	flChown := req.flags.AddString("chown", "")
 	if err := req.flags.Parse(); err != nil {
 		return err
 	}
@@ -172,6 +173,7 @@ func dispatchCopy(req dispatchRequest) error {
 	}
 
 	flFrom := req.flags.AddString("from", "")
+	flChown := req.flags.AddString("chown", "")
 	if err := req.flags.Parse(); err != nil {
 		return err
 	}

+ 31 - 0
container/container.go

@@ -44,6 +44,7 @@ import (
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/types"
 	agentexec "github.com/docker/swarmkit/agent/exec"
+	"github.com/opencontainers/runc/libcontainer/user"
 	"golang.org/x/net/context"
 )
 
@@ -331,6 +332,36 @@ func (container *Container) GetRootResourcePath(path string) (string, error) {
 	return symlink.FollowSymlinkInScope(filepath.Join(container.Root, cleanPath), container.Root)
 }
 
+// ParseUserGrp takes `username` in the format of username, uid, username:groupname,
+// uid:gid, username:gid, or uid:groupname and parses the passwd file in the container
+// to return the ExecUser referred to by `username`.
+func (container *Container) ParseUserGrp(username string) (*user.ExecUser, error) {
+	passwdPath, err := user.GetPasswdPath()
+	if err != nil {
+		return nil, err
+	}
+	passwdPath, err = container.GetResourcePath(passwdPath)
+	if err != nil {
+		return nil, err
+	}
+
+	groupPath, err := user.GetGroupPath()
+	if err != nil {
+		return nil, err
+	}
+	groupPath, err = container.GetResourcePath(groupPath)
+	if err != nil {
+		return nil, err
+	}
+
+	execUser, err := user.GetExecUserPath(username, nil, passwdPath, groupPath)
+	if err != nil {
+		return nil, err
+	}
+
+	return execUser, nil
+}
+
 // ExitOnNext signals to the monitor that it should not restart the container
 // after we send the kill signal.
 func (container *Container) ExitOnNext() {

+ 72 - 0
integration-cli/docker_cli_build_test.go

@@ -602,6 +602,78 @@ RUN [ $(cat "/test dir/test_file6") = 'test6' ]`, command, command, command, com
 	}
 }
 
+func (s *DockerSuite) TestBuildAddChownFlag(c *check.C) {
+	testRequires(c, DaemonIsLinux) // Linux specific test
+	name := "testaddtonewdest"
+	ctx, err := fakeContext(`FROM busybox
+RUN echo 'test1:x:1001:1001::/bin:/bin/false' >> /etc/passwd
+RUN echo 'test1:x:1001:' >> /etc/group
+RUN echo 'test2:x:1002:' >> /etc/group
+ADD --chown=test1:1002 . /new_dir
+RUN ls -l /
+RUN [ $(ls -l / | grep new_dir | awk '{print $3":"$4}') = 'test1:test2' ]`,
+		map[string]string{
+			"test_dir/test_file": "test file",
+		})
+	if err != nil {
+		c.Fatal(err)
+	}
+	defer ctx.Close()
+
+	if _, err := buildImageFromContext(name, ctx, true); err != nil {
+		c.Fatal(err)
+	}
+}
+
+func (s *DockerDaemonSuite) TestBuildAddChownFlagUserNamespace(c *check.C) {
+	testRequires(c, DaemonIsLinux) // Linux specific test
+
+	c.Assert(s.d.StartWithBusybox("--userns-remap", "default"), checker.IsNil)
+
+	name := "testaddtonewdest"
+	ctx, err := fakeContext(`FROM busybox
+RUN echo 'test1:x:1001:1001::/bin:/bin/false' >> /etc/passwd
+RUN echo 'test1:x:1001:' >> /etc/group
+RUN echo 'test2:x:1002:' >> /etc/group
+ADD --chown=test1:1002 . /new_dir
+RUN ls -l /
+RUN [ $(ls -l / | grep new_dir | awk '{print $3":"$4}') = 'test1:test2' ]`,
+		map[string]string{
+			"test_dir/test_file": "test file",
+		})
+	if err != nil {
+		c.Fatal(err)
+	}
+	defer ctx.Close()
+
+	if _, err := buildImageFromContext(name, ctx, true); err != nil {
+		c.Fatal(err)
+	}
+}
+
+func (s *DockerSuite) TestBuildCopyChownFlag(c *check.C) {
+	testRequires(c, DaemonIsLinux) // Linux specific test
+	name := "testaddtonewdest"
+	ctx, err := fakeContext(`FROM busybox
+RUN echo 'test1:x:1001:1001::/bin:/bin/false' >> /etc/passwd
+RUN echo 'test1:x:1001:' >> /etc/group
+RUN echo 'test2:x:1002:' >> /etc/group
+COPY --chown=test1:1002 . /new_dir
+RUN ls -l /
+RUN [ $(ls -l / | grep new_dir | awk '{print $3":"$4}') = 'test1:test2' ]`,
+		map[string]string{
+			"test_dir/test_file": "test file",
+		})
+	if err != nil {
+		c.Fatal(err)
+	}
+	defer ctx.Close()
+
+	if _, err := buildImageFromContext(name, ctx, true); err != nil {
+		c.Fatal(err)
+	}
+}
+
 func (s *DockerSuite) TestBuildCopyFileWithWhitespaceOnWindows(c *check.C) {
 	testRequires(c, DaemonIsWindows)
 	dockerfile := `FROM ` + testEnv.MinimalBaseImage() + `