diff --git a/cmd/stacker/grab.go b/cmd/stacker/grab.go index 7524d6e0..bb3bb241 100644 --- a/cmd/stacker/grab.go +++ b/cmd/stacker/grab.go @@ -43,5 +43,5 @@ func doGrab(ctx *cli.Context) error { return err } - return stacker.Grab(config, s, name, parts[1], cwd, nil, -1, -1) + return stacker.Grab(config, s, name, parts[1], cwd, "", nil, -1, -1) } diff --git a/pkg/overlay/overlay-dirs.go b/pkg/overlay/overlay-dirs.go index 645fad86..249642f5 100644 --- a/pkg/overlay/overlay-dirs.go +++ b/pkg/overlay/overlay-dirs.go @@ -108,6 +108,8 @@ func validateOverlayDirs(name string, overlayDirs []types.OverlayDir, rootfs str break } + log.Debugf("overlayDirs: %+v", overlayDirs) + for ovlindex, ovldir := range overlayDirs { if ovldir.Dest == "" { continue @@ -124,6 +126,15 @@ func validateOverlayDirs(name string, overlayDirs []types.OverlayDir, rootfs str return errors.Wrapf(err, "unable to stat %s", contents) } + contents, err = filepath.EvalSymlinks(contents) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + continue + } + + return errors.Wrapf(err, "unable to eval symlink %s", contents) + } + dest := path.Join(contents, ovldir.Dest) realdest, err := filepath.EvalSymlinks(dest) if err != nil { @@ -135,6 +146,10 @@ func validateOverlayDirs(name string, overlayDirs []types.OverlayDir, rootfs str } overlayDirs[ovlindex].Dest = strings.TrimPrefix(realdest, contents) + if overlayDirs[ovlindex].Dest == "" { + overlayDirs[ovlindex].Dest = ovldir.Dest + } + if ovldir.Dest != overlayDirs[ovlindex].Dest { log.Infof("overlay dest %s is a symlink, patching to %s", ovldir.Dest, overlayDirs[ovlindex].Dest) break diff --git a/pkg/stacker/grab.go b/pkg/stacker/grab.go index 33974cf1..fdb58c92 100644 --- a/pkg/stacker/grab.go +++ b/pkg/stacker/grab.go @@ -11,7 +11,7 @@ import ( ) func Grab(sc types.StackerConfig, storage types.Storage, name string, source string, targetDir string, - mode *fs.FileMode, uid, gid int, + idest string, mode *fs.FileMode, uid, gid int, ) error { c, err := container.New(sc, name) if err != nil { @@ -31,7 +31,12 @@ func Grab(sc types.StackerConfig, storage types.Storage, name string, source str } bcmd := []string{insideStaticStacker, "internal-go"} - err = c.Execute(append(bcmd, "cp", source, "/stacker/"+path.Base(source)), nil) + + if idest == "" || source[len(source)-1:] != "/" { + err = c.Execute(append(bcmd, "cp", source, "/stacker/"+path.Base(source)), nil) + } else { + err = c.Execute(append(bcmd, "cp", source, "/stacker/"), nil) + } if err != nil { return err } diff --git a/pkg/stacker/import.go b/pkg/stacker/import.go index f4d4f4a6..377b64ff 100644 --- a/pkg/stacker/import.go +++ b/pkg/stacker/import.go @@ -124,7 +124,17 @@ func importFile(imp string, cacheDir string, hash string, idest string, mode *fs return dest, nil } - dest := path.Join(cacheDir, path.Base(imp)) + var dest string + if imp[len(imp)-1:] != "/" { + if idest != "" && path.Base(imp) != path.Base(idest) { + dest = path.Join(cacheDir, path.Base(idest)) + } else { + dest = path.Join(cacheDir, path.Base(imp)) + } + } else { + dest = cacheDir + } + if err := os.MkdirAll(dest, 0755); err != nil { return "", errors.Wrapf(err, "failed making cache dir") } @@ -156,7 +166,20 @@ func importFile(imp string, cacheDir string, hash string, idest string, mode *fs fallthrough case mtree.Extra: srcpath := path.Join(imp, d.Path()) - destpath := path.Join(cacheDir, path.Base(imp), d.Path()) + var destpath string + if imp[len(imp)-1:] != "/" { + if idest != "" && path.Base(imp) != path.Base(idest) { + if idest[len(idest)-1:] != "/" { + destpath = path.Join(cacheDir, path.Base(idest), d.Path()) + } else { + destpath = path.Join(cacheDir, path.Base(imp), d.Path()) + } + } else { + destpath = path.Join(cacheDir, path.Base(imp), d.Path()) + } + } else { + destpath = path.Join(cacheDir, d.Path()) + } if d.New().IsDir() { fi, err := os.Lstat(destpath) @@ -260,7 +283,7 @@ func acquireUrl(c types.StackerConfig, storage types.Storage, i string, cache st return "", err } defer cleanup() - err = Grab(c, storage, snap, url.Path, cache, mode, uid, gid) + err = Grab(c, storage, snap, url.Path, cache, idest, mode, uid, gid) if err != nil { return "", err } @@ -349,7 +372,7 @@ func Import(c types.StackerConfig, storage types.Storage, name string, imports t dest := i.Dest - if i.Dest[len(i.Dest)-1:] != "/" { + if i.Dest[len(i.Dest)-1:] != "/" && i.Path[len(i.Path)-1:] != "/" { dest = path.Dir(i.Dest) } diff --git a/pkg/types/layer.go b/pkg/types/layer.go index 232303bd..2390384f 100644 --- a/pkg/types/layer.go +++ b/pkg/types/layer.go @@ -389,6 +389,9 @@ func (l Layer) absolutify(referenceDirectory string) (Layer, error) { if err != nil { return ret, err } + if rawImport.Path[len(rawImport.Path)-1:] == "/" { + absImportPath += "/" + } absImport := Import{Hash: rawImport.Hash, Path: absImportPath, Dest: rawImport.Dest, Mode: rawImport.Mode, Uid: rawImport.Uid, Gid: rawImport.Gid} ret.Imports = append(ret.Imports, absImport) } diff --git a/test/import.bats b/test/import.bats index 4623ae60..436f4f1a 100644 --- a/test/import.bats +++ b/test/import.bats @@ -390,6 +390,130 @@ eigth: [ -f /dir/file2 ] [ -f /dir/files/file3 ] EOF + stacker build +} + +@test "import with dir contents" { + mkdir folder1 + touch folder1/file1 + mkdir folder1/subfolder2 + touch folder1/subfolder2/subfile1 + cat > stacker.yaml < stacker.yaml <