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>
This commit is contained in:
Kara Alexandra 2016-09-30 12:40:06 -07:00 committed by Phil Estes
parent 4ac4c8ef4b
commit 858fad3795
No known key found for this signature in database
GPG key ID: 0F386284C03A1162
3 changed files with 105 additions and 0 deletions

View file

@ -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
}

View file

@ -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() {

View file

@ -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() + `