Skip to content

Commit

Permalink
feat(import): add "copy" support for import
Browse files Browse the repository at this point in the history
Currently, "import:" directive only allows for temporarily mounting
previously layers, and actual copying would have to be done via "run:"
directive. But in cases where there is no shell in the current layer,
there was no way to achieve this, greatly limiting usability for
packaging golang binaries.

Adding support using "dest:" option under "import:" directive.

Signed-off-by: Ramkumar Chinchani <[email protected]>
  • Loading branch information
rchincha committed Dec 3, 2022
1 parent ac366f9 commit 731bb36
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 13 deletions.
6 changes: 5 additions & 1 deletion base.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@ type BaseLayerOpts struct {
func GetBase(o BaseLayerOpts) error {
switch o.Layer.From.Type {
case types.BuiltLayer:
fallthrough
case types.ScratchLayer:
return nil
case types.TarLayer:
cacheDir := path.Join(o.Config.StackerDir, "layer-bases")
if err := os.MkdirAll(cacheDir, 0755); err != nil {
return err
}

_, err := acquireUrl(o.Config, o.Storage, o.Layer.From.Url, cacheDir, o.Progress, "")
_, err := acquireUrl(o.Config, o.Storage, o.Layer.From.Url, cacheDir, o.Progress, "", nil, nil, nil)
return err
/* now we can do all the containers/image types */
case types.OCILayer:
Expand Down Expand Up @@ -74,6 +76,8 @@ func SetupRootfs(o BaseLayerOpts) error {
}

switch o.Layer.From.Type {
case types.ScratchLayer:
return o.Storage.SetupEmptyRootfs(o.Name)
case types.TarLayer:
err := o.Storage.SetupEmptyRootfs(o.Name)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@ func (c *BuildCache) getBaseHash(name string) (string, error) {
}

return fmt.Sprintf("%d", baseHash), nil
case types.ScratchLayer:
return "", nil
case types.TarLayer:
// use the hash of the input tarball
cacheDir := path.Join(c.config.StackerDir, "layer-bases")
Expand Down
2 changes: 1 addition & 1 deletion cmd/grab.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ func doGrab(ctx *cli.Context) error {
return err
}

return stacker.Grab(config, s, name, parts[1], cwd)
return stacker.Grab(config, s, name, parts[1], cwd, nil, nil, nil)
}
30 changes: 30 additions & 0 deletions cmd/internal_go.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ var internalGoCmd = cli.Command{
Name: "cp",
Action: doCP,
},
cli.Command{
Name: "chmod",
Action: doChmod,
},
cli.Command{
Name: "chown",
Action: doChown,
},
cli.Command{
Name: "check-aa-profile",
Action: doCheckAAProfile,
Expand Down Expand Up @@ -109,6 +117,28 @@ func doCP(ctx *cli.Context) error {
)
}

func doChmod(ctx *cli.Context) error {
if len(ctx.Args()) != 2 {
return errors.Errorf("wrong number of args")
}

return lib.Chmod(
ctx.Args()[0],
ctx.Args()[1],
)
}

func doChown(ctx *cli.Context) error {
if len(ctx.Args()) != 2 {
return errors.Errorf("wrong number of args")
}

return lib.Chown(
ctx.Args()[0],
ctx.Args()[1],
)
}

func doCheckAAProfile(ctx *cli.Context) error {
toCheck := ctx.Args()[0]
command := fmt.Sprintf("changeprofile %s", toCheck)
Expand Down
31 changes: 29 additions & 2 deletions grab.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package stacker

import (
"fmt"
"io/fs"
"os"
"path"

Expand All @@ -10,7 +11,9 @@ import (
"github.com/project-stacker/stacker/types"
)

func Grab(sc types.StackerConfig, storage types.Storage, name string, source string, targetDir string) error {
func Grab(sc types.StackerConfig, storage types.Storage, name string, source string, targetDir string,
perms *fs.FileMode, uid, gid *int,
) error {
c, err := container.New(sc, name)
if err != nil {
return err
Expand Down Expand Up @@ -38,5 +41,29 @@ func Grab(sc types.StackerConfig, storage types.Storage, name string, source str
return err
}

return c.Execute(fmt.Sprintf("/static-stacker internal-go cp %s /stacker/%s", source, path.Base(source)), nil)
err = c.Execute(fmt.Sprintf("/static-stacker internal-go cp %s /stacker/%s", source, path.Base(source)), nil)
if err != nil {
return err
}

if perms != nil {
err = c.Execute(fmt.Sprintf("/static-stacker internal-go chmod %s /stacker/%s", fmt.Sprintf("%o", *perms), path.Base(source)), nil)
if err != nil {
return err
}
}

if uid != nil {
owns := fmt.Sprintf("%d", *uid)
if gid != nil {
owns += fmt.Sprintf(":%d", *gid)
}

err = c.Execute(fmt.Sprintf("/static-stacker internal-go chown %s /stacker/%s", owns, path.Base(source)), nil)
if err != nil {
return err
}
}

return nil
}
60 changes: 57 additions & 3 deletions import.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package stacker

import (
"io/fs"
"os"
"path"
"strings"
Expand Down Expand Up @@ -213,7 +214,9 @@ func validateHash(hash string) error {
return nil
}

func acquireUrl(c types.StackerConfig, storage types.Storage, i string, cache string, progress bool, expectedHash string) (string, error) {
func acquireUrl(c types.StackerConfig, storage types.Storage, i string, cache string, progress bool, expectedHash string,
perms *fs.FileMode, uid, gid *int,
) (string, error) {
url, err := types.NewDockerishUrl(i)
if err != nil {
return "", err
Expand Down Expand Up @@ -254,7 +257,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)
err = Grab(c, storage, snap, url.Path, cache, perms, uid, gid)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -311,7 +314,58 @@ func Import(c types.StackerConfig, storage types.Storage, name string, imports t
}

for _, i := range imports {
name, err := acquireUrl(c, storage, i.Path, dir, progress, i.Hash)
cache := dir
if i.Dest != "" {
cache, err = os.MkdirTemp(dir, "import-copy-*")
if err != nil {
return errors.Wrapf(err, "couldn't create a temp dir to copy imports")
}
// FIXME: now make this dir a overlay_dirs entry
}

name, err := acquireUrl(c, storage, i.Path, cache, progress, i.Hash, i.Perms, i.Uid, i.Gid)
if err != nil {
return err
}

for i, ext := range existing {
if ext.Name() == path.Base(name) {
existing = append(existing[:i], existing[i+1:]...)
break
}
}
}

// Now, delete all the old imports.
for _, ext := range existing {
err = os.RemoveAll(path.Join(dir, ext.Name()))
if err != nil {
return err
}
}

return nil
}

func ImportAndCopy(c types.StackerConfig, storage types.Storage, name string, imports types.Imports, progress bool) error {
dir := path.Join(c.StackerDir, "imports", name)

if err := os.MkdirAll(dir, 0755); err != nil {
return err
}

existing, err := os.ReadDir(dir)
if err != nil {
return errors.Wrapf(err, "couldn't read existing directory")
}

for _, i := range imports {
if i.Dest == "" {
// skip these, they
continue
}

name, err := acquireUrl(c, storage, i.Path, dir, progress, i.Hash, i.Perms, i.Uid, i.Gid)
if err != nil {
return err
}
Expand Down
55 changes: 55 additions & 0 deletions lib/dir.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package lib

import (
"io/fs"
"os"
"path"
"strconv"
"strings"

"github.com/pkg/errors"
)
Expand Down Expand Up @@ -73,3 +76,55 @@ func CopyThing(srcpath, destpath string) error {
return FileCopy(destpath, srcpath)
}
}

// Chmod changes file permissions
func Chmod(perms, destpath string) error {
destInfo, err := os.Lstat(destpath)
if err != nil {
return errors.WithStack(err)
}

if destInfo.IsDir() {
return errors.WithStack(os.ErrInvalid)
}

// read as an octal value
iperms, err := strconv.ParseUint(perms, 8, 32)
if err != nil {
return errors.WithStack(err)
}

return os.Chmod(destpath, fs.FileMode(iperms))
}

// Chown changes file ownership
func Chown(owner, destpath string) error {
destInfo, err := os.Lstat(destpath)
if err != nil {
return errors.WithStack(err)
}

if destInfo.IsDir() {
return errors.WithStack(os.ErrInvalid)
}

owns := strings.Split(owner, ":")
if len(owns) > 2 {
return errors.WithStack(os.ErrInvalid)
}

uid, err := strconv.ParseInt(owns[0], 10, 32)
if err != nil {
return errors.WithStack(err)
}

gid := int64(-1)
if len(owns) > 1 {
gid, err = strconv.ParseInt(owns[1], 10, 32)
if err != nil {
return errors.WithStack(err)
}
}

return os.Chown(destpath, int(uid), int(gid))
}
44 changes: 44 additions & 0 deletions test/import.bats
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,47 @@ EOF

stacker build
}

@test "different import types with perms" {
touch test_file
test_file_sha=$(sha test_file) || { stderr "failed sha $test_file"; return 1; }
touch test_file2
cat > stacker.yaml <<EOF
first:
from:
type: oci
url: $CENTOS_OCI
import:
- path: test_file
hash: $test_file_sha
uid: 1000
gid: 1000
- test_file2
- https://bing.com/favicon.ico
run: |
[ -f /stacker/test_file ]
[ -f /stacker/test_file2 ]
cp /stacker/test_file /test_file
build_only: true
second:
from:
type: built
tag: first
import:
path: stacker://first/test_file
perms: 0777
hash: $test_file_sha
run: |
[ -f /stacker/test_file ]
third:
from:
type: scratch
import:
path: stacker://first/test_file
perms: 0777
hash: $test_file_sha
dest: /test_file
EOF

stacker build
}
18 changes: 12 additions & 6 deletions types/layer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package types

import (
"fmt"
"io/fs"
"os"
"path/filepath"
"reflect"
Expand All @@ -15,10 +16,11 @@ import (
)

const (
DockerLayer = "docker"
TarLayer = "tar"
OCILayer = "oci"
BuiltLayer = "built"
DockerLayer = "docker"
TarLayer = "tar"
OCILayer = "oci"
BuiltLayer = "built"
ScratchLayer = "scratch"
)

func IsContainersImageLayer(from string) bool {
Expand All @@ -33,8 +35,12 @@ func IsContainersImageLayer(from string) bool {
}

type Import struct {
Path string `yaml:"path"`
Hash string `yaml:"hash"`
Path string `yaml:"path"`
Hash string `yaml:"hash"`
Dest string `yaml:"dest"`
Perms *fs.FileMode `yaml:"perms"`
Uid *int `yaml:"uid"`
Gid *int `yaml:"gid"`
}

type OverlayDir struct {
Expand Down

0 comments on commit 731bb36

Please sign in to comment.