Fixed an issue where the image is broken if there are symlink in the destination path when ADD, COPY
This commit is contained in:
parent
eafb80227b
commit
d6fe98aa49
|
|
@ -18,14 +18,13 @@ package commands
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/GoogleContainerTools/kaniko/pkg/constants"
|
||||
"github.com/moby/buildkit/frontend/dockerfile/instructions"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/GoogleContainerTools/kaniko/pkg/constants"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
||||
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||
|
|
@ -63,6 +62,7 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
|
|||
if cwd == "" {
|
||||
cwd = constants.RootDir
|
||||
}
|
||||
|
||||
destPath, err := util.DestinationFilepath(src, dest, cwd)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -76,11 +76,7 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
|
|||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
if !filepath.IsAbs(dest) {
|
||||
// we need to add '/' to the end to indicate the destination is a directory
|
||||
dest = filepath.Join(cwd, dest) + "/"
|
||||
}
|
||||
copiedFiles, err := util.CopyDir(fullPath, dest, c.buildcontext)
|
||||
copiedFiles, err := util.CopyDir(fullPath, destPath, c.buildcontext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -197,21 +193,43 @@ func (cr *CachingCopyCommand) From() string {
|
|||
}
|
||||
|
||||
func resolveIfSymlink(destPath string) (string, error) {
|
||||
baseDir := filepath.Dir(destPath)
|
||||
if info, err := os.Lstat(baseDir); err == nil {
|
||||
if !filepath.IsAbs(destPath) {
|
||||
return "", errors.New("dest path must be abs")
|
||||
}
|
||||
|
||||
pathPrefix := "/"
|
||||
pathTokens := strings.Split(destPath, string(os.PathSeparator))
|
||||
for i, pathToken := range pathTokens {
|
||||
currentPath := filepath.Join(pathPrefix, pathToken)
|
||||
info, err := os.Lstat(currentPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
pathPrefix = filepath.Join(append([]string{currentPath}, pathTokens[i+1:]...)...)
|
||||
break
|
||||
} else {
|
||||
return "", errors.Wrap(err, "failed to lstat")
|
||||
}
|
||||
}
|
||||
|
||||
switch mode := info.Mode(); {
|
||||
case mode&os.ModeSymlink != 0:
|
||||
linkPath, err := os.Readlink(baseDir)
|
||||
linkPath, err := os.Readlink(currentPath)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error reading symlink")
|
||||
return "", errors.Wrap(err, "failed to read symlink")
|
||||
}
|
||||
absLinkPath := filepath.Join(filepath.Dir(baseDir), linkPath)
|
||||
newPath := filepath.Join(absLinkPath, filepath.Base(destPath))
|
||||
logrus.Tracef("Updating destination path from %v to %v due to symlink", destPath, newPath)
|
||||
return newPath, nil
|
||||
if filepath.IsAbs(linkPath) {
|
||||
pathPrefix = linkPath
|
||||
} else {
|
||||
pathPrefix = filepath.Join(pathPrefix, linkPath)
|
||||
}
|
||||
default:
|
||||
pathPrefix = filepath.Join(pathPrefix, pathToken)
|
||||
}
|
||||
}
|
||||
return destPath, nil
|
||||
if destPath != pathPrefix {
|
||||
logrus.Tracef("Updating destination path from %v to %v due to symlink", destPath, pathPrefix)
|
||||
}
|
||||
return filepath.Clean(pathPrefix), nil
|
||||
}
|
||||
|
||||
func copyCmdFilesUsedFromContext(
|
||||
|
|
|
|||
|
|
@ -201,7 +201,19 @@ func Test_resolveIfSymlink(t *testing.T) {
|
|||
if err := os.Symlink(filepath.Base(thepath), symLink); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
cases = append(cases, testCase{filepath.Join(symLink, "foo.txt"), filepath.Join(thepath, "foo.txt"), nil})
|
||||
cases = append(cases,
|
||||
testCase{filepath.Join(symLink, "foo.txt"), filepath.Join(thepath, "foo.txt"), nil},
|
||||
testCase{filepath.Join(symLink, "inner", "foo.txt"), filepath.Join(thepath, "inner", "foo.txt"), nil},
|
||||
)
|
||||
|
||||
absSymlink := filepath.Join(tmpDir, "abs-symlink")
|
||||
if err := os.Symlink(thepath, absSymlink); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
cases = append(cases,
|
||||
testCase{filepath.Join(absSymlink, "foo.txt"), filepath.Join(thepath, "foo.txt"), nil},
|
||||
testCase{filepath.Join(absSymlink, "inner", "foo.txt"), filepath.Join(thepath, "inner", "foo.txt"), nil},
|
||||
)
|
||||
|
||||
for i, c := range cases {
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -164,20 +164,25 @@ func IsDestDir(path string) bool {
|
|||
// If dest is a dir, copy it to /dest/relpath
|
||||
// If dest is a file, copy directly to dest
|
||||
// If source is a dir:
|
||||
// Assume dest is also a dir, and copy to dest/relpath
|
||||
// Assume dest is also a dir, and copy to dest/
|
||||
// If dest is not an absolute filepath, add /cwd to the beginning
|
||||
func DestinationFilepath(src, dest, cwd string) (string, error) {
|
||||
if IsDestDir(dest) {
|
||||
destPath := filepath.Join(dest, filepath.Base(src))
|
||||
if filepath.IsAbs(dest) {
|
||||
return destPath, nil
|
||||
}
|
||||
return filepath.Join(cwd, destPath), nil
|
||||
_, srcFileName := filepath.Split(src)
|
||||
newDest := dest
|
||||
|
||||
if IsDestDir(newDest) {
|
||||
newDest = filepath.Join(newDest, srcFileName)
|
||||
}
|
||||
if filepath.IsAbs(dest) {
|
||||
return dest, nil
|
||||
|
||||
if !filepath.IsAbs(newDest) {
|
||||
newDest = filepath.Join(cwd, newDest)
|
||||
}
|
||||
return filepath.Join(cwd, dest), nil
|
||||
|
||||
if len(srcFileName) <= 0 && !strings.HasSuffix(newDest, "/") {
|
||||
newDest += "/"
|
||||
}
|
||||
|
||||
return newDest, nil
|
||||
}
|
||||
|
||||
// URLDestinationFilepath gives the destination a file from a remote URL should be saved to
|
||||
|
|
|
|||
|
|
@ -153,13 +153,13 @@ var destinationFilepathTests = []struct {
|
|||
src: "context/bar/",
|
||||
cwd: "/",
|
||||
dest: "pkg/",
|
||||
expectedFilepath: "/pkg/bar",
|
||||
expectedFilepath: "/pkg/",
|
||||
},
|
||||
{
|
||||
src: "context/bar/",
|
||||
cwd: "/newdir",
|
||||
dest: "pkg/",
|
||||
expectedFilepath: "/newdir/pkg/bar",
|
||||
expectedFilepath: "/newdir/pkg/",
|
||||
},
|
||||
{
|
||||
src: "./context/empty",
|
||||
|
|
@ -177,7 +177,7 @@ var destinationFilepathTests = []struct {
|
|||
src: "./",
|
||||
cwd: "/",
|
||||
dest: "/dir",
|
||||
expectedFilepath: "/dir",
|
||||
expectedFilepath: "/dir/",
|
||||
},
|
||||
{
|
||||
src: "context/foo",
|
||||
|
|
|
|||
Loading…
Reference in New Issue