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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"github.com/GoogleContainerTools/kaniko/pkg/constants"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/moby/buildkit/frontend/dockerfile/instructions"
|
"github.com/moby/buildkit/frontend/dockerfile/instructions"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"os"
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/constants"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
"github.com/GoogleContainerTools/kaniko/pkg/dockerfile"
|
||||||
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
"github.com/GoogleContainerTools/kaniko/pkg/util"
|
||||||
|
|
@ -63,6 +62,7 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
|
||||||
if cwd == "" {
|
if cwd == "" {
|
||||||
cwd = constants.RootDir
|
cwd = constants.RootDir
|
||||||
}
|
}
|
||||||
|
|
||||||
destPath, err := util.DestinationFilepath(src, dest, cwd)
|
destPath, err := util.DestinationFilepath(src, dest, cwd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -76,11 +76,7 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
|
||||||
}
|
}
|
||||||
|
|
||||||
if fi.IsDir() {
|
if fi.IsDir() {
|
||||||
if !filepath.IsAbs(dest) {
|
copiedFiles, err := util.CopyDir(fullPath, destPath, c.buildcontext)
|
||||||
// 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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -197,21 +193,43 @@ func (cr *CachingCopyCommand) From() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveIfSymlink(destPath string) (string, error) {
|
func resolveIfSymlink(destPath string) (string, error) {
|
||||||
baseDir := filepath.Dir(destPath)
|
if !filepath.IsAbs(destPath) {
|
||||||
if info, err := os.Lstat(baseDir); err == nil {
|
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(); {
|
switch mode := info.Mode(); {
|
||||||
case mode&os.ModeSymlink != 0:
|
case mode&os.ModeSymlink != 0:
|
||||||
linkPath, err := os.Readlink(baseDir)
|
linkPath, err := os.Readlink(currentPath)
|
||||||
if err != nil {
|
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)
|
if filepath.IsAbs(linkPath) {
|
||||||
newPath := filepath.Join(absLinkPath, filepath.Base(destPath))
|
pathPrefix = linkPath
|
||||||
logrus.Tracef("Updating destination path from %v to %v due to symlink", destPath, newPath)
|
} else {
|
||||||
return newPath, nil
|
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(
|
func copyCmdFilesUsedFromContext(
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,19 @@ func Test_resolveIfSymlink(t *testing.T) {
|
||||||
if err := os.Symlink(filepath.Base(thepath), symLink); err != nil {
|
if err := os.Symlink(filepath.Base(thepath), symLink); err != nil {
|
||||||
t.Error(err)
|
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 {
|
for i, c := range cases {
|
||||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
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 dir, copy it to /dest/relpath
|
||||||
// If dest is a file, copy directly to dest
|
// If dest is a file, copy directly to dest
|
||||||
// If source is a dir:
|
// 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
|
// If dest is not an absolute filepath, add /cwd to the beginning
|
||||||
func DestinationFilepath(src, dest, cwd string) (string, error) {
|
func DestinationFilepath(src, dest, cwd string) (string, error) {
|
||||||
if IsDestDir(dest) {
|
_, srcFileName := filepath.Split(src)
|
||||||
destPath := filepath.Join(dest, filepath.Base(src))
|
newDest := dest
|
||||||
if filepath.IsAbs(dest) {
|
|
||||||
return destPath, nil
|
if IsDestDir(newDest) {
|
||||||
}
|
newDest = filepath.Join(newDest, srcFileName)
|
||||||
return filepath.Join(cwd, destPath), nil
|
|
||||||
}
|
}
|
||||||
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
|
// URLDestinationFilepath gives the destination a file from a remote URL should be saved to
|
||||||
|
|
|
||||||
|
|
@ -153,13 +153,13 @@ var destinationFilepathTests = []struct {
|
||||||
src: "context/bar/",
|
src: "context/bar/",
|
||||||
cwd: "/",
|
cwd: "/",
|
||||||
dest: "pkg/",
|
dest: "pkg/",
|
||||||
expectedFilepath: "/pkg/bar",
|
expectedFilepath: "/pkg/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: "context/bar/",
|
src: "context/bar/",
|
||||||
cwd: "/newdir",
|
cwd: "/newdir",
|
||||||
dest: "pkg/",
|
dest: "pkg/",
|
||||||
expectedFilepath: "/newdir/pkg/bar",
|
expectedFilepath: "/newdir/pkg/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: "./context/empty",
|
src: "./context/empty",
|
||||||
|
|
@ -177,7 +177,7 @@ var destinationFilepathTests = []struct {
|
||||||
src: "./",
|
src: "./",
|
||||||
cwd: "/",
|
cwd: "/",
|
||||||
dest: "/dir",
|
dest: "/dir",
|
||||||
expectedFilepath: "/dir",
|
expectedFilepath: "/dir/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: "context/foo",
|
src: "context/foo",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue