Merge pull request #1114 from tejal29/fix_copy

Add more tests for Copy and some fixes.
This commit is contained in:
Tejal Desai 2020-03-10 11:00:24 -07:00 committed by GitHub
commit c718dc61a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 516 additions and 56 deletions

View File

@ -1,14 +1,10 @@
FROM busybox as t
RUN echo "hello" > /tmp/target
RUN ln -s /tmp/target /tmp/link
## Relative link
RUN cd tmp && ln -s target relative_link
RUN mkdir temp
RUN echo "hello" > temp/target
RUN ln -s target temp/link
## Relative link with paths
RUN mkdir workdir && cd workdir && ln -s ../tmp/target relative_dir_link
RUN mkdir workdir && cd workdir && ln -s ../temp/target relative_link
FROM scratch
COPY --from=t /tmp/link /tmp/
COPY --from=t /tmp/relative_link /tmp/
COPY --from=t /workdir/relative_dir_link /workdir/
COPY --from=t temp/ dest/
COPY --from=t /workdir/relative_link /workdirAnother/

View File

@ -21,6 +21,7 @@ import (
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/moby/buildkit/frontend/dockerfile/instructions"
"github.com/pkg/errors"
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
@ -66,18 +67,18 @@ func (a *AddCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui
}
logrus.Infof("Adding remote URL %s to %s", src, urlDest)
if err := util.DownloadFileToDest(src, urlDest); err != nil {
return err
return errors.Wrap(err, "downloading remote source file")
}
a.snapshotFiles = append(a.snapshotFiles, urlDest)
} else if util.IsFileLocalTarArchive(fullPath) {
tarDest, err := util.DestinationFilepath("", dest, config.WorkingDir)
if err != nil {
return err
return errors.Wrap(err, "determining dest for tar")
}
logrus.Infof("Unpacking local tar archive %s to %s", src, tarDest)
extractedFiles, err := util.UnpackLocalTarArchive(fullPath, tarDest)
if err != nil {
return err
return errors.Wrap(err, "unpacking local tar")
}
logrus.Debugf("Added %v from local tar archive %s", extractedFiles, src)
a.snapshotFiles = append(a.snapshotFiles, extractedFiles...)
@ -98,7 +99,7 @@ func (a *AddCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bui
}
if err := copyCmd.ExecuteCommand(config, buildArgs); err != nil {
return err
return errors.Wrap(err, "executing copy command")
}
a.snapshotFiles = append(a.snapshotFiles, copyCmd.snapshotFiles...)
return nil

View File

@ -54,17 +54,18 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
uid, gid, err := getUserGroup(c.cmd.Chown, replacementEnvs)
if err != nil {
return err
return errors.Wrap(err, "getting user group from chowm")
}
srcs, dest, err := util.ResolveEnvAndWildcards(c.cmd.SourcesAndDest, c.buildcontext, replacementEnvs)
if err != nil {
return err
return errors.Wrap(err, "resolving src")
}
// For each source, iterate through and copy it over
for _, src := range srcs {
fullPath := filepath.Join(c.buildcontext, src)
fi, err := os.Lstat(fullPath)
if err != nil {
return errors.Wrap(err, "could not copy source")
@ -79,27 +80,27 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
destPath, err := util.DestinationFilepath(fullPath, dest, cwd)
if err != nil {
return err
return errors.Wrap(err, "find destination path")
}
// If the destination dir is a symlink we need to resolve the path and use
// that instead of the symlink path
destPath, err = resolveIfSymlink(destPath)
if err != nil {
return err
return errors.Wrap(err, "resolving dest symlink")
}
if fi.IsDir() {
copiedFiles, err := util.CopyDir(fullPath, destPath, c.buildcontext, uid, gid)
if err != nil {
return err
return errors.Wrap(err, "copying dir")
}
c.snapshotFiles = append(c.snapshotFiles, copiedFiles...)
} else if util.IsSymlink(fi) {
// If file is a symlink, we want to copy the target file to destPath
exclude, err := util.CopySymlink(fullPath, destPath, c.buildcontext, uid, gid)
exclude, err := util.CopySymlink(fullPath, destPath, c.buildcontext)
if err != nil {
return err
return errors.Wrap(err, "copying symlink")
}
if exclude {
continue
@ -109,7 +110,7 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
// ... Else, we want to copy over a file
exclude, err := util.CopyFile(fullPath, destPath, c.buildcontext, uid, gid)
if err != nil {
return err
return errors.Wrap(err, "copying file")
}
if exclude {
continue

View File

@ -442,3 +442,449 @@ func TestGetUserGroup(t *testing.T) {
})
}
}
func TestCopyCommand_ExecuteCommand_Extended(t *testing.T) {
setupDirs := func(t *testing.T) (string, string) {
testDir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal(err)
}
dir := filepath.Join(testDir, "bar")
if err := os.MkdirAll(dir, 0777); err != nil {
t.Fatal(err)
}
file := filepath.Join(dir, "bam.txt")
if err := ioutil.WriteFile(file, []byte("meow"), 0777); err != nil {
t.Fatal(err)
}
targetPath := filepath.Join(dir, "dam.txt")
if err := ioutil.WriteFile(targetPath, []byte("woof"), 0777); err != nil {
t.Fatal(err)
}
if err := os.Symlink("dam.txt", filepath.Join(dir, "sym.link")); err != nil {
t.Fatal(err)
}
return testDir, filepath.Base(dir)
}
t.Run("copy dir to another dir", func(t *testing.T) {
testDir, srcDir := setupDirs(t)
defer os.RemoveAll(testDir)
expected, err := ioutil.ReadDir(filepath.Join(testDir, srcDir))
if err != nil {
t.Fatal(err)
}
cmd := CopyCommand{
cmd: &instructions.CopyCommand{
SourcesAndDest: []string{srcDir, "dest"},
},
buildcontext: testDir,
}
cfg := &v1.Config{
Cmd: nil,
Env: []string{},
WorkingDir: testDir,
}
err = cmd.ExecuteCommand(cfg, dockerfile.NewBuildArgs([]string{}))
if err != nil {
t.Fatal(err)
}
testutil.CheckNoError(t, err)
// Check if "dest" dir exists with contents of srcDir
actual, err := ioutil.ReadDir(filepath.Join(testDir, "dest"))
if err != nil {
t.Fatal(err)
}
for i, f := range actual {
testutil.CheckDeepEqual(t, expected[i].Name(), f.Name())
testutil.CheckDeepEqual(t, expected[i].Mode(), f.Mode())
}
})
t.Run("copy file to a dir", func(t *testing.T) {
testDir, srcDir := setupDirs(t)
defer os.RemoveAll(testDir)
cmd := CopyCommand{
cmd: &instructions.CopyCommand{
SourcesAndDest: []string{filepath.Join(srcDir, "bam.txt"), "dest/"},
},
buildcontext: testDir,
}
cfg := &v1.Config{
Cmd: nil,
Env: []string{},
WorkingDir: testDir,
}
err := cmd.ExecuteCommand(cfg, dockerfile.NewBuildArgs([]string{}))
testutil.CheckNoError(t, err)
// Check if "dest" dir exists with file bam.txt
files, err := ioutil.ReadDir(filepath.Join(testDir, "dest"))
if err != nil {
t.Fatal(err)
}
testutil.CheckDeepEqual(t, 1, len(files))
testutil.CheckDeepEqual(t, files[0].Name(), "bam.txt")
})
t.Run("copy file to a filepath", func(t *testing.T) {
testDir, srcDir := setupDirs(t)
defer os.RemoveAll(testDir)
cmd := CopyCommand{
cmd: &instructions.CopyCommand{
SourcesAndDest: []string{filepath.Join(srcDir, "bam.txt"), "dest"},
},
buildcontext: testDir,
}
cfg := &v1.Config{
Cmd: nil,
Env: []string{},
WorkingDir: testDir,
}
err := cmd.ExecuteCommand(cfg, dockerfile.NewBuildArgs([]string{}))
testutil.CheckNoError(t, err)
// Check if bam.txt is copied to dest file
if _, err := os.Lstat(filepath.Join(testDir, "dest")); err != nil {
t.Fatal(err)
}
})
t.Run("copy file to a dir without trailing /", func(t *testing.T) {
testDir, srcDir := setupDirs(t)
defer os.RemoveAll(testDir)
destDir := filepath.Join(testDir, "dest")
if err := os.MkdirAll(destDir, 0777); err != nil {
t.Fatal(err)
}
cmd := CopyCommand{
cmd: &instructions.CopyCommand{
SourcesAndDest: []string{filepath.Join(srcDir, "bam.txt"), "dest"},
},
buildcontext: testDir,
}
cfg := &v1.Config{
Cmd: nil,
Env: []string{},
WorkingDir: testDir,
}
err := cmd.ExecuteCommand(cfg, dockerfile.NewBuildArgs([]string{}))
testutil.CheckNoError(t, err)
// Check if "dest" dir exists with file bam.txt
files, err := ioutil.ReadDir(filepath.Join(testDir, "dest"))
if err != nil {
t.Fatal(err)
}
testutil.CheckDeepEqual(t, 1, len(files))
testutil.CheckDeepEqual(t, files[0].Name(), "bam.txt")
})
t.Run("copy symlink file to a dir", func(t *testing.T) {
testDir, srcDir := setupDirs(t)
defer os.RemoveAll(testDir)
cmd := CopyCommand{
cmd: &instructions.CopyCommand{
SourcesAndDest: []string{filepath.Join(srcDir, "sym.link"), "dest/"},
},
buildcontext: testDir,
}
cfg := &v1.Config{
Cmd: nil,
Env: []string{},
WorkingDir: testDir,
}
err := cmd.ExecuteCommand(cfg, dockerfile.NewBuildArgs([]string{}))
testutil.CheckNoError(t, err)
// Check if "dest" dir exists with link sym.link
files, err := ioutil.ReadDir(filepath.Join(testDir, "dest"))
if err != nil {
t.Fatal(err)
}
// bam.txt and sym.link should be present
testutil.CheckDeepEqual(t, 1, len(files))
testutil.CheckDeepEqual(t, files[0].Name(), "sym.link")
testutil.CheckDeepEqual(t, true, files[0].Mode()&os.ModeSymlink != 0)
linkName, err := os.Readlink(filepath.Join(testDir, "dest", "sym.link"))
if err != nil {
t.Fatal(err)
}
testutil.CheckDeepEqual(t, linkName, "dam.txt")
})
t.Run("copy deadlink symlink file to a dir", func(t *testing.T) {
testDir, srcDir := setupDirs(t)
defer os.RemoveAll(testDir)
doesNotExists := filepath.Join(testDir, "dead.txt")
if err := ioutil.WriteFile(doesNotExists, []byte("remove me"), 0777); err != nil {
t.Fatal(err)
}
if err := os.Symlink("../dead.txt", filepath.Join(testDir, srcDir, "dead.link")); err != nil {
t.Fatal(err)
}
if err := os.Remove(doesNotExists); err != nil {
t.Fatal(err)
}
cmd := CopyCommand{
cmd: &instructions.CopyCommand{
SourcesAndDest: []string{filepath.Join(srcDir, "dead.link"), "dest/"},
},
buildcontext: testDir,
}
cfg := &v1.Config{
Cmd: nil,
Env: []string{},
WorkingDir: testDir,
}
err := cmd.ExecuteCommand(cfg, dockerfile.NewBuildArgs([]string{}))
testutil.CheckNoError(t, err)
// Check if "dest" dir exists with link dead.link
files, err := ioutil.ReadDir(filepath.Join(testDir, "dest"))
if err != nil {
t.Fatal(err)
}
testutil.CheckDeepEqual(t, 1, len(files))
testutil.CheckDeepEqual(t, files[0].Name(), "dead.link")
testutil.CheckDeepEqual(t, true, files[0].Mode()&os.ModeSymlink != 0)
linkName, err := os.Readlink(filepath.Join(testDir, "dest", "dead.link"))
if err != nil {
t.Fatal(err)
}
testutil.CheckDeepEqual(t, linkName, "../dead.txt")
})
t.Run("copy src symlink dir to a dir", func(t *testing.T) {
testDir, srcDir := setupDirs(t)
defer os.RemoveAll(testDir)
expected, err := ioutil.ReadDir(filepath.Join(testDir, srcDir))
if err != nil {
t.Fatal(err)
}
another := filepath.Join(testDir, "another")
os.Symlink(filepath.Join(testDir, srcDir), another)
cmd := CopyCommand{
cmd: &instructions.CopyCommand{
SourcesAndDest: []string{"another", "dest"},
},
buildcontext: testDir,
}
cfg := &v1.Config{
Cmd: nil,
Env: []string{},
WorkingDir: testDir,
}
err = cmd.ExecuteCommand(cfg, dockerfile.NewBuildArgs([]string{}))
testutil.CheckNoError(t, err)
// Check if "dest" dir exists with contents of srcDir
actual, err := ioutil.ReadDir(filepath.Join(testDir, "dest"))
if err != nil {
t.Fatal(err)
}
for i, f := range actual {
testutil.CheckDeepEqual(t, expected[i].Name(), f.Name())
testutil.CheckDeepEqual(t, expected[i].Mode(), f.Mode())
}
})
t.Run("copy dir with a symlink to a file outside of current src dir", func(t *testing.T) {
testDir, srcDir := setupDirs(t)
defer os.RemoveAll(testDir)
expected, err := ioutil.ReadDir(filepath.Join(testDir, srcDir))
if err != nil {
t.Fatal(err)
}
anotherSrc := filepath.Join(testDir, "anotherSrc")
if err := os.MkdirAll(anotherSrc, 0777); err != nil {
t.Fatal(err)
}
targetPath := filepath.Join(anotherSrc, "target.txt")
if err := ioutil.WriteFile(targetPath, []byte("woof"), 0777); err != nil {
t.Fatal(err)
}
if err := os.Symlink(targetPath, filepath.Join(testDir, srcDir, "zSym.link")); err != nil {
t.Fatal(err)
}
cmd := CopyCommand{
cmd: &instructions.CopyCommand{
SourcesAndDest: []string{srcDir, "dest"},
},
buildcontext: testDir,
}
cfg := &v1.Config{
Cmd: nil,
Env: []string{},
WorkingDir: testDir,
}
err = cmd.ExecuteCommand(cfg, dockerfile.NewBuildArgs([]string{}))
testutil.CheckNoError(t, err)
// Check if "dest" dir exists contents of srcDir and an extra zSym.link created
// in this test
actual, err := ioutil.ReadDir(filepath.Join(testDir, "dest"))
if err != nil {
t.Fatal(err)
}
testutil.CheckDeepEqual(t, 4, len(actual))
for i, f := range expected {
testutil.CheckDeepEqual(t, f.Name(), actual[i].Name())
testutil.CheckDeepEqual(t, f.Mode(), actual[i].Mode())
}
linkName, err := os.Readlink(filepath.Join(testDir, "dest", "zSym.link"))
if err != nil {
t.Fatal(err)
}
testutil.CheckDeepEqual(t, linkName, targetPath)
})
t.Run("copy src symlink dir to a dir", func(t *testing.T) {
testDir, srcDir := setupDirs(t)
defer os.RemoveAll(testDir)
expected, err := ioutil.ReadDir(filepath.Join(testDir, srcDir))
if err != nil {
t.Fatal(err)
}
another := filepath.Join(testDir, "another")
os.Symlink(filepath.Join(testDir, srcDir), another)
cmd := CopyCommand{
cmd: &instructions.CopyCommand{
SourcesAndDest: []string{"another", "dest"},
},
buildcontext: testDir,
}
cfg := &v1.Config{
Cmd: nil,
Env: []string{},
WorkingDir: testDir,
}
err = cmd.ExecuteCommand(cfg, dockerfile.NewBuildArgs([]string{}))
testutil.CheckNoError(t, err)
// Check if "dest" dir exists with bam.txt and "dest" dir is a symlink
actual, err := ioutil.ReadDir(filepath.Join(testDir, "dest"))
if err != nil {
t.Fatal(err)
}
for i, f := range actual {
testutil.CheckDeepEqual(t, expected[i].Name(), f.Name())
testutil.CheckDeepEqual(t, expected[i].Mode(), f.Mode())
}
})
t.Run("copy src dir to a dest dir which is a symlink", func(t *testing.T) {
testDir, srcDir := setupDirs(t)
defer os.RemoveAll(testDir)
expected, err := ioutil.ReadDir(filepath.Join(testDir, srcDir))
if err != nil {
t.Fatal(err)
}
dest := filepath.Join(testDir, "dest")
if err := os.MkdirAll(dest, 0777); err != nil {
t.Fatal(err)
}
linkedDest := filepath.Join(testDir, "linkDest")
if err := os.Symlink(dest, linkedDest); err != nil {
t.Fatal(err)
}
cmd := CopyCommand{
cmd: &instructions.CopyCommand{
SourcesAndDest: []string{srcDir, linkedDest},
},
buildcontext: testDir,
}
cfg := &v1.Config{
Cmd: nil,
Env: []string{},
WorkingDir: testDir,
}
err = cmd.ExecuteCommand(cfg, dockerfile.NewBuildArgs([]string{}))
testutil.CheckNoError(t, err)
// Check if "linkdest" dir exists with contents of srcDir
actual, err := ioutil.ReadDir(filepath.Join(testDir, "linkDest"))
if err != nil {
t.Fatal(err)
}
for i, f := range expected {
testutil.CheckDeepEqual(t, f.Name(), actual[i].Name())
testutil.CheckDeepEqual(t, f.Mode(), actual[i].Mode())
}
// Check if linkDest -> dest
linkName, err := os.Readlink(filepath.Join(testDir, "linkDest"))
if err != nil {
t.Fatal(err)
}
testutil.CheckDeepEqual(t, linkName, dest)
})
t.Run("copy src file to a dest dir which is a symlink", func(t *testing.T) {
testDir, srcDir := setupDirs(t)
defer os.RemoveAll(testDir)
dest := filepath.Join(testDir, "dest")
if err := os.MkdirAll(dest, 0777); err != nil {
t.Fatal(err)
}
linkedDest := filepath.Join(testDir, "linkDest")
if err := os.Symlink(dest, linkedDest); err != nil {
t.Fatal(err)
}
cmd := CopyCommand{
cmd: &instructions.CopyCommand{
SourcesAndDest: []string{fmt.Sprintf("%s/bam.txt", srcDir), linkedDest},
},
buildcontext: testDir,
}
cfg := &v1.Config{
Cmd: nil,
Env: []string{},
WorkingDir: testDir,
}
err := cmd.ExecuteCommand(cfg, dockerfile.NewBuildArgs([]string{}))
testutil.CheckNoError(t, err)
// Check if "linkDest" link is same.
actual, err := ioutil.ReadDir(filepath.Join(testDir, "dest"))
if err != nil {
t.Fatal(err)
}
testutil.CheckDeepEqual(t, "bam.txt", actual[0].Name())
c, err := ioutil.ReadFile(filepath.Join(testDir, "dest", "bam.txt"))
if err != nil {
t.Fatal(err)
}
testutil.CheckDeepEqual(t, "meow", string(c))
// Check if linkDest -> dest
linkName, err := os.Readlink(filepath.Join(testDir, "linkDest"))
if err != nil {
t.Fatal(err)
}
testutil.CheckDeepEqual(t, linkName, dest)
})
}

View File

@ -339,7 +339,7 @@ func (s *stageBuilder) build() error {
v := command.(commands.Cached)
layer := v.Layer()
if err := s.saveLayerToImage(layer, command.String()); err != nil {
return err
return errors.Wrap(err, "failed to save layer")
}
} else {
tarPath, err := s.takeSnapshot(files)

View File

@ -35,6 +35,7 @@ import (
// * Add all ancestors of each path to the output set.
func ResolvePaths(paths []string, wl []util.WhitelistEntry) (pathsToAdd []string, err error) {
logrus.Info("Resolving paths")
logrus.Debugf("Resolving paths %s", paths)
fileSet := make(map[string]bool)
@ -47,8 +48,7 @@ func ResolvePaths(paths []string, wl []util.WhitelistEntry) (pathsToAdd []string
link, e := resolveSymlinkAncestor(f)
if e != nil {
err = e
return
continue
}
if f != link {
@ -64,9 +64,9 @@ func ResolvePaths(paths []string, wl []util.WhitelistEntry) (pathsToAdd []string
// If the path is a symlink we need to also consider the target of that
// link
evaled, err = filepath.EvalSymlinks(f)
if err != nil {
if !os.IsNotExist(err) {
evaled, e = filepath.EvalSymlinks(f)
if e != nil {
if !os.IsNotExist(e) {
logrus.Errorf("couldn't eval %s with link %s", f, link)
return
}
@ -133,7 +133,7 @@ loop:
for newPath != "/" {
fi, err := os.Lstat(newPath)
if err != nil {
return "", errors.Wrap(err, "failed to lstat")
return "", errors.Wrap(err, "resolvePaths: failed to lstat")
}
if util.IsSymlink(fi) {

View File

@ -26,7 +26,6 @@ import (
"github.com/GoogleContainerTools/kaniko/pkg/filesystem"
"github.com/GoogleContainerTools/kaniko/pkg/timing"
"github.com/karrick/godirwalk"
"github.com/GoogleContainerTools/kaniko/pkg/constants"

3
pkg/util/.editorconfig Normal file
View File

@ -0,0 +1,3 @@
root = true
[*]

View File

@ -35,6 +35,10 @@ import (
"github.com/sirupsen/logrus"
)
const (
pathSeparator = "/"
)
// ResolveEnvironmentReplacementList resolves a list of values by calling resolveEnvironmentReplacement
func ResolveEnvironmentReplacementList(values, envs []string, isFilepath bool) ([]string, error) {
var resolvedValues []string
@ -114,13 +118,14 @@ func ResolveSources(srcs []string, root string) ([]string, error) {
logrus.Infof("Resolving srcs %v...", srcs)
files, err := RelativeFiles("", root)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "resolving sources")
}
resolved, err := matchSources(srcs, files)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "matching sources")
}
logrus.Debugf("Resolved sources to %v", resolved)
fmt.Println("end of resolve sources")
return resolved, nil
}
@ -154,7 +159,7 @@ func IsDestDir(path string) bool {
fileInfo, err := os.Stat(path)
if err != nil {
// fall back to string-based determination
return strings.HasSuffix(path, "/") || path == "."
return strings.HasSuffix(path, pathSeparator) || path == "."
}
// if it's a real path, check the fs response
return fileInfo.IsDir()
@ -171,16 +176,19 @@ func DestinationFilepath(src, dest, cwd string) (string, error) {
_, srcFileName := filepath.Split(src)
newDest := dest
if !filepath.IsAbs(newDest) {
newDest = filepath.Join(cwd, newDest)
// join call clean on all results.
if strings.HasSuffix(dest, pathSeparator) || strings.HasSuffix(dest, ".") {
newDest += pathSeparator
}
}
if IsDestDir(newDest) {
newDest = filepath.Join(newDest, srcFileName)
}
if !filepath.IsAbs(newDest) {
newDest = filepath.Join(cwd, newDest)
}
if len(srcFileName) <= 0 && !strings.HasSuffix(newDest, "/") {
newDest += "/"
if len(srcFileName) <= 0 && !strings.HasSuffix(newDest, pathSeparator) {
newDest += pathSeparator
}
return newDest, nil

View File

@ -442,7 +442,7 @@ func DetectFilesystemWhitelist(path string) error {
func RelativeFiles(fp string, root string) ([]string, error) {
var files []string
fullPath := filepath.Join(root, fp)
logrus.Debugf("Getting files and contents at root %s", fullPath)
logrus.Debugf("Getting files and contents at root %s for %s", root, fullPath)
err := filepath.Walk(fullPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
@ -505,15 +505,16 @@ func FilepathExists(path string) bool {
func CreateFile(path string, reader io.Reader, perm os.FileMode, uid uint32, gid uint32) error {
// Create directory path if it doesn't exist
if err := createParentDirectory(path); err != nil {
return err
return errors.Wrap(err, "creating parent dir")
}
dest, err := os.Create(path)
if err != nil {
return err
return errors.Wrap(err, "creating file")
}
defer dest.Close()
if _, err := io.Copy(dest, reader); err != nil {
return err
return errors.Wrap(err, "copying file")
}
return setFilePermissions(path, perm, int(uid), int(gid))
}
@ -570,7 +571,7 @@ func DetermineTargetFileOwnership(fi os.FileInfo, uid, gid int64) (int64, int64)
func CopyDir(src, dest, buildcontext string, uid, gid int64) ([]string, error) {
files, err := RelativeFiles("", src)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "copying dir")
}
var copiedFiles []string
for _, file := range files {
@ -594,7 +595,7 @@ func CopyDir(src, dest, buildcontext string, uid, gid int64) ([]string, error) {
}
} else if IsSymlink(fi) {
// If file is a symlink, we want to create the same relative symlink
if _, err := CopySymlink(fullPath, destPath, buildcontext, uid, gid); err != nil {
if _, err := CopySymlink(fullPath, destPath, buildcontext); err != nil {
return nil, err
}
} else {
@ -608,16 +609,12 @@ func CopyDir(src, dest, buildcontext string, uid, gid int64) ([]string, error) {
return copiedFiles, nil
}
// CopySymlink copies the symlink at src to dest
func CopySymlink(src, dest, buildcontext string, uid int64, gid int64) (bool, error) {
// CopySymlink copies the symlink at src to dest.
func CopySymlink(src, dest, buildcontext string) (bool, error) {
if ExcludeFile(src, buildcontext) {
logrus.Debugf("%s found in .dockerignore, ignoring", src)
return true, nil
}
link, err := filepath.EvalSymlinks(src)
if err != nil {
return false, err
}
if FilepathExists(dest) {
if err := os.RemoveAll(dest); err != nil {
return false, err
@ -626,7 +623,11 @@ func CopySymlink(src, dest, buildcontext string, uid int64, gid int64) (bool, er
if err := createParentDirectory(dest); err != nil {
return false, err
}
return CopyFile(link, dest, buildcontext, uid, gid)
link, err := os.Readlink(src)
if err != nil {
logrus.Debugf("could not read link for %s", src)
}
return false, os.Symlink(link, dest)
}
// CopyFile copies the file at src to dest
@ -827,15 +828,14 @@ func getSymlink(path string) error {
func CopyFileOrSymlink(src string, destDir string) error {
destFile := filepath.Join(destDir, src)
if fi, _ := os.Lstat(src); IsSymlink(fi) {
link, err := EvalSymLink(src)
link, err := os.Readlink(src)
if err != nil {
return err
}
linkPath := filepath.Join(destDir, link)
if err := createParentDirectory(destFile); err != nil {
return err
}
return os.Symlink(linkPath, destFile)
return os.Symlink(link, destFile)
}
return otiai10Cpy.Copy(src, destFile)
}

View File

@ -835,7 +835,7 @@ func TestCopySymlink(t *testing.T) {
if err := os.Symlink(tc.linkTarget, link); err != nil {
t.Fatal(err)
}
if _, err := CopySymlink(link, dest, "", DoNotChangeUID, DoNotChangeGID); err != nil {
if _, err := CopySymlink(link, dest, ""); err != nil {
t.Fatal(err)
}
if _, err := os.Lstat(dest); err != nil {

View File

@ -68,6 +68,12 @@ func CheckError(t *testing.T, shouldErr bool, err error) {
}
}
func CheckNoError(t *testing.T, err error) {
if err != nil {
t.Error(err)
}
}
func checkErr(shouldErr bool, err error) error {
if err == nil && shouldErr {
return fmt.Errorf("Expected error, but returned none")