parent
53fa7382a3
commit
b7fd382230
|
@ -7,6 +7,7 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
@ -493,7 +494,7 @@ func dispatch(d *dispatchState, cmd command, opt dispatchOpt) error {
|
|||
case *instructions.WorkdirCommand:
|
||||
err = dispatchWorkdir(d, c, true, &opt)
|
||||
case *instructions.AddCommand:
|
||||
err = dispatchCopy(d, c.SourcesAndDest, opt.buildContext, true, c, c.Chown, c.Location(), opt)
|
||||
err = dispatchCopy(d, c.SourcesAndDest, opt.buildContext, true, c, c.Chown, c.Chmod, c.Location(), opt)
|
||||
if err == nil {
|
||||
for _, src := range c.Sources() {
|
||||
if !strings.HasPrefix(src, "http://") && !strings.HasPrefix(src, "https://") {
|
||||
|
@ -528,7 +529,7 @@ func dispatch(d *dispatchState, cmd command, opt dispatchOpt) error {
|
|||
if len(cmd.sources) != 0 {
|
||||
l = cmd.sources[0].state
|
||||
}
|
||||
err = dispatchCopy(d, c.SourcesAndDest, l, false, c, c.Chown, c.Location(), opt)
|
||||
err = dispatchCopy(d, c.SourcesAndDest, l, false, c, c.Chown, c.Chmod, c.Location(), opt)
|
||||
if err == nil && len(cmd.sources) == 0 {
|
||||
for _, src := range c.Sources() {
|
||||
d.ctxPaths[path.Join("/", filepath.ToSlash(src))] = struct{}{}
|
||||
|
@ -722,7 +723,7 @@ func dispatchWorkdir(d *dispatchState, c *instructions.WorkdirCommand, commit bo
|
|||
return nil
|
||||
}
|
||||
|
||||
func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceState llb.State, isAddCommand bool, cmdToPrint fmt.Stringer, chown string, loc []parser.Range, opt dispatchOpt) error {
|
||||
func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceState llb.State, isAddCommand bool, cmdToPrint fmt.Stringer, chown string, chmod string, loc []parser.Range, opt dispatchOpt) error {
|
||||
pp, err := pathRelativeToWorkingDir(d.state, c.Dest())
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -738,6 +739,15 @@ func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceS
|
|||
copyOpt = append(copyOpt, llb.WithUser(chown))
|
||||
}
|
||||
|
||||
var mode *os.FileMode
|
||||
if chmod != "" {
|
||||
p, err := strconv.ParseUint(chmod, 8, 32)
|
||||
if err == nil {
|
||||
perm := os.FileMode(p)
|
||||
mode = &perm
|
||||
}
|
||||
}
|
||||
|
||||
commitMessage := bytes.NewBufferString("")
|
||||
if isAddCommand {
|
||||
commitMessage.WriteString("ADD")
|
||||
|
@ -780,6 +790,7 @@ func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceS
|
|||
}
|
||||
} else {
|
||||
opts := append([]llb.CopyOption{&llb.CopyInfo{
|
||||
Mode: mode,
|
||||
FollowSymlinks: true,
|
||||
CopyDirContentsOnly: true,
|
||||
AttemptUnpack: isAddCommand,
|
||||
|
@ -820,9 +831,16 @@ func dispatchCopyFileOp(d *dispatchState, c instructions.SourcesAndDest, sourceS
|
|||
return commitToHistory(&d.image, commitMessage.String(), true, &d.state)
|
||||
}
|
||||
|
||||
func dispatchCopy(d *dispatchState, c instructions.SourcesAndDest, sourceState llb.State, isAddCommand bool, cmdToPrint fmt.Stringer, chown string, loc []parser.Range, opt dispatchOpt) error {
|
||||
func dispatchCopy(d *dispatchState, c instructions.SourcesAndDest, sourceState llb.State, isAddCommand bool, cmdToPrint fmt.Stringer, chown string, chmod string, loc []parser.Range, opt dispatchOpt) error {
|
||||
if useFileOp(opt.buildArgValues, opt.llbCaps) {
|
||||
return dispatchCopyFileOp(d, c, sourceState, isAddCommand, cmdToPrint, chown, loc, opt)
|
||||
return dispatchCopyFileOp(d, c, sourceState, isAddCommand, cmdToPrint, chown, chmod, loc, opt)
|
||||
}
|
||||
|
||||
if chmod != "" {
|
||||
if opt.llbCaps != nil && opt.llbCaps.Supports(pb.CapFileBase) != nil {
|
||||
return errors.Wrap(opt.llbCaps.Supports(pb.CapFileBase), "chmod is not supported")
|
||||
}
|
||||
return errors.New("chmod is not supported")
|
||||
}
|
||||
|
||||
img := llb.Image(opt.copyImage, llb.MarkImageInternal, llb.Platform(opt.buildPlatforms[0]), WithInternalName("helper image for file operations"))
|
||||
|
|
|
@ -113,6 +113,7 @@ var fileOpTests = []integration.Test{
|
|||
testNoSnapshotLeak,
|
||||
testCopySymlinks,
|
||||
testCopyChown,
|
||||
testCopyChmod,
|
||||
testCopyOverrideFiles,
|
||||
testCopyVarSubstitution,
|
||||
testCopyWildcards,
|
||||
|
@ -2914,6 +2915,77 @@ COPY --from=base /out /
|
|||
require.Equal(t, "1000 nogroup\n", string(dt))
|
||||
}
|
||||
|
||||
func testCopyChmod(t *testing.T, sb integration.Sandbox) {
|
||||
f := getFrontend(t, sb)
|
||||
isFileOp := getFileOp(t, sb)
|
||||
|
||||
dockerfile := []byte(`
|
||||
FROM busybox AS base
|
||||
|
||||
RUN mkdir -m 0777 /out
|
||||
COPY --chmod=0644 foo /
|
||||
COPY --chmod=777 bar /baz
|
||||
COPY --chmod=0 foo /foobis
|
||||
|
||||
RUN stat -c "%04a" /foo > /out/fooperm
|
||||
RUN stat -c "%04a" /baz > /out/barperm
|
||||
RUN stat -c "%04a" /foobis > /out/foobisperm
|
||||
FROM scratch
|
||||
COPY --from=base /out /
|
||||
`)
|
||||
|
||||
dir, err := tmpdir(
|
||||
fstest.CreateFile("Dockerfile", dockerfile, 0600),
|
||||
fstest.CreateFile("foo", []byte(`foo-contents`), 0600),
|
||||
fstest.CreateFile("bar", []byte(`bar-contents`), 0700),
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
c, err := client.New(context.TODO(), sb.Address())
|
||||
require.NoError(t, err)
|
||||
defer c.Close()
|
||||
|
||||
destDir, err := ioutil.TempDir("", "buildkit")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(destDir)
|
||||
|
||||
_, err = f.Solve(context.TODO(), c, client.SolveOpt{
|
||||
Exports: []client.ExportEntry{
|
||||
{
|
||||
Type: client.ExporterLocal,
|
||||
OutputDir: destDir,
|
||||
},
|
||||
},
|
||||
FrontendAttrs: map[string]string{
|
||||
"build-arg:BUILDKIT_DISABLE_FILEOP": strconv.FormatBool(!isFileOp),
|
||||
},
|
||||
LocalDirs: map[string]string{
|
||||
builder.DefaultLocalNameDockerfile: dir,
|
||||
builder.DefaultLocalNameContext: dir,
|
||||
},
|
||||
}, nil)
|
||||
|
||||
if !isFileOp {
|
||||
require.Contains(t, err.Error(), "chmod is not supported")
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
dt, err := ioutil.ReadFile(filepath.Join(destDir, "fooperm"))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "0644\n", string(dt))
|
||||
|
||||
dt, err = ioutil.ReadFile(filepath.Join(destDir, "barperm"))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "0777\n", string(dt))
|
||||
|
||||
dt, err = ioutil.ReadFile(filepath.Join(destDir, "foobisperm"))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "0000\n", string(dt))
|
||||
}
|
||||
|
||||
func testCopyOverrideFiles(t *testing.T, sb integration.Sandbox) {
|
||||
f := getFrontend(t, sb)
|
||||
isFileOp := getFileOp(t, sb)
|
||||
|
|
|
@ -188,6 +188,7 @@ type AddCommand struct {
|
|||
withNameAndCode
|
||||
SourcesAndDest
|
||||
Chown string
|
||||
Chmod string
|
||||
}
|
||||
|
||||
// Expand variables
|
||||
|
@ -209,6 +210,7 @@ type CopyCommand struct {
|
|||
SourcesAndDest
|
||||
From string
|
||||
Chown string
|
||||
Chmod string
|
||||
}
|
||||
|
||||
// Expand variables
|
||||
|
|
|
@ -239,6 +239,7 @@ func parseAdd(req parseRequest) (*AddCommand, error) {
|
|||
return nil, errNoDestinationArgument("ADD")
|
||||
}
|
||||
flChown := req.flags.AddString("chown", "")
|
||||
flChmod := req.flags.AddString("chmod", "")
|
||||
if err := req.flags.Parse(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -246,6 +247,7 @@ func parseAdd(req parseRequest) (*AddCommand, error) {
|
|||
SourcesAndDest: SourcesAndDest(req.args),
|
||||
withNameAndCode: newWithNameAndCode(req),
|
||||
Chown: flChown.Value,
|
||||
Chmod: flChmod.Value,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -255,6 +257,7 @@ func parseCopy(req parseRequest) (*CopyCommand, error) {
|
|||
}
|
||||
flChown := req.flags.AddString("chown", "")
|
||||
flFrom := req.flags.AddString("from", "")
|
||||
flChmod := req.flags.AddString("chmod", "")
|
||||
if err := req.flags.Parse(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -263,6 +266,7 @@ func parseCopy(req parseRequest) (*CopyCommand, error) {
|
|||
From: flFrom.Value,
|
||||
withNameAndCode: newWithNameAndCode(req),
|
||||
Chown: flChown.Value,
|
||||
Chmod: flChmod.Value,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -294,6 +294,7 @@ func (fb *Backend) Mkfile(ctx context.Context, m, user, group fileoptypes.Mount,
|
|||
|
||||
return mkfile(ctx, dir, action, u, mnt.m.IdentityMapping())
|
||||
}
|
||||
|
||||
func (fb *Backend) Rm(ctx context.Context, m fileoptypes.Mount, action pb.FileActionRm) error {
|
||||
mnt, ok := m.(*Mount)
|
||||
if !ok {
|
||||
|
@ -309,6 +310,7 @@ func (fb *Backend) Rm(ctx context.Context, m fileoptypes.Mount, action pb.FileAc
|
|||
|
||||
return rm(ctx, dir, action)
|
||||
}
|
||||
|
||||
func (fb *Backend) Copy(ctx context.Context, m1, m2, user, group fileoptypes.Mount, action pb.FileActionCopy) error {
|
||||
mnt1, ok := m1.(*Mount)
|
||||
if !ok {
|
||||
|
|
Loading…
Reference in New Issue