Fix Symlinks not being copies across stages
This commit is contained in:
parent
6e80e627ac
commit
da7e9928e4
|
|
@ -0,0 +1,5 @@
|
|||
FROM alpine:3.11 as t
|
||||
RUN apk add gcc
|
||||
|
||||
FROM scratch
|
||||
COPY --from=t /usr/lib/libstdc++.so.6 /usr/lib/
|
||||
|
|
@ -85,7 +85,7 @@ func (c *CopyCommand) ExecuteCommand(config *v1.Config, buildArgs *dockerfile.Bu
|
|||
return err
|
||||
}
|
||||
c.snapshotFiles = append(c.snapshotFiles, copiedFiles...)
|
||||
} else if fi.Mode()&os.ModeSymlink != 0 {
|
||||
} else if util.IsSymlink(fi) {
|
||||
// If file is a symlink, we want to create the same relative symlink
|
||||
exclude, err := util.CopySymlink(fullPath, destPath, c.buildcontext)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
otiai10Cpy "github.com/otiai10/copy"
|
||||
|
||||
"github.com/google/go-containerregistry/pkg/v1/partial"
|
||||
|
||||
"github.com/moby/buildkit/frontend/dockerfile/instructions"
|
||||
|
|
@ -565,6 +563,7 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) {
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
filesToSave, err := filesToSave(crossStageDependencies[index])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -574,8 +573,8 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) {
|
|||
return nil, err
|
||||
}
|
||||
for _, p := range filesToSave {
|
||||
logrus.Infof("Saving file %s for later use.", p)
|
||||
otiai10Cpy.Copy(p, filepath.Join(dstDir, p))
|
||||
logrus.Infof("Saving file %s for later use", p)
|
||||
util.CopyFileOrSymlink(p, dstDir)
|
||||
}
|
||||
|
||||
// Delete the filesystem
|
||||
|
|
@ -587,16 +586,28 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// fileToSave returns all the files matching the given pattern in deps.
|
||||
// If a file is a symlink, it also returns the target file.
|
||||
// It first returns all the target files and then symlinks so they can copied
|
||||
// in that order to the kaniko workspace.
|
||||
func filesToSave(deps []string) ([]string, error) {
|
||||
allFiles := []string{}
|
||||
srcFiles := []string{}
|
||||
symLinks := []string{}
|
||||
for _, src := range deps {
|
||||
srcs, err := filepath.Glob(src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
allFiles = append(allFiles, srcs...)
|
||||
for _, f := range srcs {
|
||||
if link, err := util.CanonicalizeLink(f); err == nil {
|
||||
symLinks = append(symLinks, f)
|
||||
srcFiles = append(srcFiles, link)
|
||||
} else {
|
||||
srcFiles = append(srcFiles, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
return allFiles, nil
|
||||
return append(srcFiles, symLinks...), nil
|
||||
}
|
||||
|
||||
func fetchExtraStages(stages []config.KanikoStage, opts *config.KanikoOptions) error {
|
||||
|
|
|
|||
|
|
@ -112,7 +112,6 @@ func (s *Snapshotter) TakeSnapshotFS() (string, error) {
|
|||
if err := writeToTar(t, filesToAdd, filesToWhiteOut); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return f.Name(), nil
|
||||
}
|
||||
|
||||
|
|
@ -170,7 +169,7 @@ func (s *Snapshotter) scanFullFilesystem() ([]string, []string, error) {
|
|||
filesToAdd := []string{}
|
||||
for path := range memFs {
|
||||
if util.CheckWhitelist(path) {
|
||||
logrus.Tracef("Not adding %s to layer, as it's whitelisted", path)
|
||||
logrus.Infof("Not adding %s to layer, as it's whitelisted", path)
|
||||
continue
|
||||
}
|
||||
// Only add changed files.
|
||||
|
|
@ -179,8 +178,12 @@ func (s *Snapshotter) scanFullFilesystem() ([]string, []string, error) {
|
|||
return nil, nil, fmt.Errorf("could not check if file has changed %s %s", path, err)
|
||||
}
|
||||
if fileChanged {
|
||||
logrus.Tracef("Adding %s to layer, because it was changed.", path)
|
||||
filesToAdd = append(filesToAdd, path)
|
||||
files, err := filesWithLinks(path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
logrus.Debug("Adding files %s to layer, because it was changed.", files)
|
||||
filesToAdd = append(filesToAdd, files...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +191,6 @@ func (s *Snapshotter) scanFullFilesystem() ([]string, []string, error) {
|
|||
filesToAdd = filesWithParentDirs(filesToAdd)
|
||||
|
||||
sort.Strings(filesToAdd)
|
||||
|
||||
// Add files to the layered map
|
||||
for _, file := range filesToAdd {
|
||||
if err := s.l.Add(file); err != nil {
|
||||
|
|
@ -236,3 +238,13 @@ func filesWithParentDirs(files []string) []string {
|
|||
|
||||
return newFiles
|
||||
}
|
||||
|
||||
func filesWithLinks(path string) ([]string, error) {
|
||||
link, err := util.CanonicalizeLink(path)
|
||||
if err == util.NotSymLink {
|
||||
return []string{path}, nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []string{path, link}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
otiai10Cpy "github.com/otiai10/copy"
|
||||
|
||||
"github.com/GoogleContainerTools/kaniko/pkg/constants"
|
||||
"github.com/docker/docker/builder/dockerignore"
|
||||
"github.com/docker/docker/pkg/fileutils"
|
||||
|
|
@ -443,18 +445,8 @@ func FilepathExists(path string) bool {
|
|||
// CreateFile creates a file at path and copies over contents from the reader
|
||||
func CreateFile(path string, reader io.Reader, perm os.FileMode, uid uint32, gid uint32) error {
|
||||
// Create directory path if it doesn't exist
|
||||
baseDir := filepath.Dir(path)
|
||||
if info, err := os.Lstat(baseDir); os.IsNotExist(err) {
|
||||
logrus.Tracef("baseDir %s for file %s does not exist. Creating.", baseDir, path)
|
||||
if err := os.MkdirAll(baseDir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
switch mode := info.Mode(); {
|
||||
case mode&os.ModeSymlink != 0:
|
||||
logrus.Infof("destination cannot be a symlink %v", baseDir)
|
||||
return errors.New("destination cannot be a symlink")
|
||||
}
|
||||
if err := createParentDirectory(path); err != nil {
|
||||
return err
|
||||
}
|
||||
dest, err := os.Create(path)
|
||||
if err != nil {
|
||||
|
|
@ -531,7 +523,7 @@ func CopyDir(src, dest, buildcontext string) ([]string, error) {
|
|||
if err := mkdirAllWithPermissions(destPath, mode, uid, gid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if fi.Mode()&os.ModeSymlink != 0 {
|
||||
} else if IsSymlink(fi) {
|
||||
// If file is a symlink, we want to create the same relative symlink
|
||||
if _, err := CopySymlink(fullPath, destPath, buildcontext); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -553,7 +545,7 @@ func CopySymlink(src, dest, buildcontext string) (bool, error) {
|
|||
logrus.Debugf("%s found in .dockerignore, ignoring", src)
|
||||
return true, nil
|
||||
}
|
||||
link, err := os.Readlink(src)
|
||||
link, err := filepath.EvalSymlinks(src)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
@ -562,6 +554,9 @@ func CopySymlink(src, dest, buildcontext string) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
}
|
||||
if err := createParentDirectory(dest); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return false, os.Symlink(link, dest)
|
||||
}
|
||||
|
||||
|
|
@ -690,3 +685,50 @@ func CreateTargetTarfile(tarpath string) (*os.File, error) {
|
|||
return os.Create(tarpath)
|
||||
|
||||
}
|
||||
|
||||
// Returns true if a file is a symlink
|
||||
func IsSymlink(fi os.FileInfo) bool {
|
||||
return fi.Mode()&os.ModeSymlink != 0
|
||||
}
|
||||
|
||||
var NotSymLink = fmt.Errorf("not a symlink")
|
||||
|
||||
func CanonicalizeLink(path string) (string, error) {
|
||||
fi, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !IsSymlink(fi) {
|
||||
return "", NotSymLink
|
||||
}
|
||||
return filepath.EvalSymlinks(path)
|
||||
}
|
||||
|
||||
// otiai10Cpy.Copy in case the src file is a symlink, will copy the target
|
||||
// file at destination instead of creating a symlink. See #915 for more details.
|
||||
func CopyFileOrSymlink(src string, destDir string) error {
|
||||
destFile := filepath.Join(destDir, src)
|
||||
if fi, _ := os.Lstat(src); IsSymlink(fi) {
|
||||
if link, err := os.Readlink(src); err != nil {
|
||||
return err
|
||||
} else {
|
||||
return os.Symlink(link, destFile)
|
||||
}
|
||||
} else {
|
||||
return otiai10Cpy.Copy(src, destFile)
|
||||
}
|
||||
}
|
||||
|
||||
func createParentDirectory(path string) error {
|
||||
baseDir := filepath.Dir(path)
|
||||
if info, err := os.Lstat(baseDir); os.IsNotExist(err) {
|
||||
logrus.Tracef("baseDir %s for file %s does not exist. Creating.", baseDir, path)
|
||||
if err := os.MkdirAll(baseDir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if IsSymlink(info) {
|
||||
logrus.Infof("destination cannot be a symlink %v", baseDir)
|
||||
return errors.New("destination cannot be a symlink")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue