build, mount: allow realtive mountpoints wrt to work dir
When working with `--mount=type=bind` and `--mount=type=cache` allow `target` to accept relative paths w.r.t to the configured work dir. Closes: https://github.com/containers/buildah/issues/4309 Signed-off-by: Aditya R <arajan@redhat.com>
This commit is contained in:
parent
3c94e53452
commit
d9578d32cd
|
@ -168,7 +168,7 @@ func runCmd(c *cobra.Command, args []string, iopts runInputOptions) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("building system context: %w", err)
|
||||
}
|
||||
mounts, mountedImages, targetLocks, err := internalParse.GetVolumes(systemContext, store, iopts.volumes, iopts.mounts, iopts.contextDir)
|
||||
mounts, mountedImages, targetLocks, err := internalParse.GetVolumes(systemContext, store, iopts.volumes, iopts.mounts, iopts.contextDir, iopts.workingDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -49,7 +50,7 @@ var (
|
|||
// GetBindMount parses a single bind mount entry from the --mount flag.
|
||||
// Returns specifiedMount and a string which contains name of image that we mounted otherwise its empty.
|
||||
// Caller is expected to perform unmount of any mounted images
|
||||
func GetBindMount(ctx *types.SystemContext, args []string, contextDir string, store storage.Store, imageMountLabel string, additionalMountPoints map[string]internal.StageMountDetails) (specs.Mount, string, error) {
|
||||
func GetBindMount(ctx *types.SystemContext, args []string, contextDir string, store storage.Store, imageMountLabel string, additionalMountPoints map[string]internal.StageMountDetails, workDir string) (specs.Mount, string, error) {
|
||||
newMount := specs.Mount{
|
||||
Type: define.TypeBind,
|
||||
}
|
||||
|
@ -101,10 +102,14 @@ func GetBindMount(ctx *types.SystemContext, args []string, contextDir string, st
|
|||
if len(kv) == 1 {
|
||||
return newMount, "", fmt.Errorf("%v: %w", kv[0], errBadOptionArg)
|
||||
}
|
||||
if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil {
|
||||
targetPath := kv[1]
|
||||
if !path.IsAbs(targetPath) {
|
||||
targetPath = filepath.Join(workDir, targetPath)
|
||||
}
|
||||
if err := parse.ValidateVolumeCtrDir(targetPath); err != nil {
|
||||
return newMount, "", err
|
||||
}
|
||||
newMount.Destination = kv[1]
|
||||
newMount.Destination = targetPath
|
||||
setDest = true
|
||||
case "consistency":
|
||||
// Option for OS X only, has no meaning on other platforms
|
||||
|
@ -189,7 +194,7 @@ func GetBindMount(ctx *types.SystemContext, args []string, contextDir string, st
|
|||
// GetCacheMount parses a single cache mount entry from the --mount flag.
|
||||
//
|
||||
// If this function succeeds and returns a non-nil *lockfile.LockFile, the caller must unlock it (when??).
|
||||
func GetCacheMount(args []string, store storage.Store, imageMountLabel string, additionalMountPoints map[string]internal.StageMountDetails) (specs.Mount, *lockfile.LockFile, error) {
|
||||
func GetCacheMount(args []string, store storage.Store, imageMountLabel string, additionalMountPoints map[string]internal.StageMountDetails, workDir string) (specs.Mount, *lockfile.LockFile, error) {
|
||||
var err error
|
||||
var mode uint64
|
||||
var buildahLockFilesDir string
|
||||
|
@ -257,10 +262,14 @@ func GetCacheMount(args []string, store storage.Store, imageMountLabel string, a
|
|||
if len(kv) == 1 {
|
||||
return newMount, nil, fmt.Errorf("%v: %w", kv[0], errBadOptionArg)
|
||||
}
|
||||
if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil {
|
||||
targetPath := kv[1]
|
||||
if !path.IsAbs(targetPath) {
|
||||
targetPath = filepath.Join(workDir, targetPath)
|
||||
}
|
||||
if err := parse.ValidateVolumeCtrDir(targetPath); err != nil {
|
||||
return newMount, nil, err
|
||||
}
|
||||
newMount.Destination = kv[1]
|
||||
newMount.Destination = targetPath
|
||||
setDest = true
|
||||
case "src", "source":
|
||||
if len(kv) == 1 {
|
||||
|
@ -506,8 +515,8 @@ func UnlockLockArray(locks []*lockfile.LockFile) {
|
|||
// GetVolumes gets the volumes from --volume and --mount
|
||||
//
|
||||
// If this function succeeds, the caller must unlock the returned *lockfile.LockFile s if any (when??).
|
||||
func GetVolumes(ctx *types.SystemContext, store storage.Store, volumes []string, mounts []string, contextDir string) ([]specs.Mount, []string, []*lockfile.LockFile, error) {
|
||||
unifiedMounts, mountedImages, targetLocks, err := getMounts(ctx, store, mounts, contextDir)
|
||||
func GetVolumes(ctx *types.SystemContext, store storage.Store, volumes []string, mounts []string, contextDir string, workDir string) ([]specs.Mount, []string, []*lockfile.LockFile, error) {
|
||||
unifiedMounts, mountedImages, targetLocks, err := getMounts(ctx, store, mounts, contextDir, workDir)
|
||||
if err != nil {
|
||||
return nil, mountedImages, nil, err
|
||||
}
|
||||
|
@ -542,7 +551,7 @@ func GetVolumes(ctx *types.SystemContext, store storage.Store, volumes []string,
|
|||
// buildah run --mount type=tmpfs,target=/dev/shm ...
|
||||
//
|
||||
// If this function succeeds, the caller must unlock the returned *lockfile.LockFile s if any (when??).
|
||||
func getMounts(ctx *types.SystemContext, store storage.Store, mounts []string, contextDir string) (map[string]specs.Mount, []string, []*lockfile.LockFile, error) {
|
||||
func getMounts(ctx *types.SystemContext, store storage.Store, mounts []string, contextDir string, workDir string) (map[string]specs.Mount, []string, []*lockfile.LockFile, error) {
|
||||
// If `type` is not set default to "bind"
|
||||
mountType := define.TypeBind
|
||||
finalMounts := make(map[string]specs.Mount)
|
||||
|
@ -576,7 +585,7 @@ func getMounts(ctx *types.SystemContext, store storage.Store, mounts []string, c
|
|||
}
|
||||
switch mountType {
|
||||
case define.TypeBind:
|
||||
mount, image, err := GetBindMount(ctx, tokens, contextDir, store, "", nil)
|
||||
mount, image, err := GetBindMount(ctx, tokens, contextDir, store, "", nil, workDir)
|
||||
if err != nil {
|
||||
return nil, mountedImages, nil, err
|
||||
}
|
||||
|
@ -586,7 +595,7 @@ func getMounts(ctx *types.SystemContext, store storage.Store, mounts []string, c
|
|||
finalMounts[mount.Destination] = mount
|
||||
mountedImages = append(mountedImages, image)
|
||||
case TypeCache:
|
||||
mount, tl, err := GetCacheMount(tokens, store, "", nil)
|
||||
mount, tl, err := GetCacheMount(tokens, store, "", nil, workDir)
|
||||
if err != nil {
|
||||
return nil, mountedImages, nil, err
|
||||
}
|
||||
|
|
2
run.go
2
run.go
|
@ -183,6 +183,8 @@ type runMountArtifacts struct {
|
|||
|
||||
// RunMountInfo are the available run mounts for this run
|
||||
type runMountInfo struct {
|
||||
// WorkDir is the current working directory inside the container.
|
||||
WorkDir string
|
||||
// ContextDir is the root directory for the source location for bind mounts.
|
||||
ContextDir string
|
||||
// Secrets are the available secrets to use in a RUN
|
||||
|
|
|
@ -1510,7 +1510,7 @@ func (b *Builder) runSetupRunMounts(mounts []string, sources runMountInfo, idMap
|
|||
sshCount++
|
||||
}
|
||||
case define.TypeBind:
|
||||
mount, image, err := b.getBindMount(tokens, sources.SystemContext, sources.ContextDir, sources.StageMountPoints, idMaps)
|
||||
mount, image, err := b.getBindMount(tokens, sources.SystemContext, sources.ContextDir, sources.StageMountPoints, idMaps, sources.WorkDir)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -1528,7 +1528,7 @@ func (b *Builder) runSetupRunMounts(mounts []string, sources runMountInfo, idMap
|
|||
finalMounts = append(finalMounts, *mount)
|
||||
mountTargets = append(mountTargets, mount.Destination)
|
||||
case "cache":
|
||||
mount, tl, err := b.getCacheMount(tokens, sources.StageMountPoints, idMaps)
|
||||
mount, tl, err := b.getCacheMount(tokens, sources.StageMountPoints, idMaps, sources.WorkDir)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -1553,12 +1553,12 @@ func (b *Builder) runSetupRunMounts(mounts []string, sources runMountInfo, idMap
|
|||
return finalMounts, artifacts, nil
|
||||
}
|
||||
|
||||
func (b *Builder) getBindMount(tokens []string, context *imageTypes.SystemContext, contextDir string, stageMountPoints map[string]internal.StageMountDetails, idMaps IDMaps) (*spec.Mount, string, error) {
|
||||
func (b *Builder) getBindMount(tokens []string, context *imageTypes.SystemContext, contextDir string, stageMountPoints map[string]internal.StageMountDetails, idMaps IDMaps, workDir string) (*spec.Mount, string, error) {
|
||||
if contextDir == "" {
|
||||
return nil, "", errors.New("Context Directory for current run invocation is not configured")
|
||||
}
|
||||
var optionMounts []specs.Mount
|
||||
mount, image, err := internalParse.GetBindMount(context, tokens, contextDir, b.store, b.MountLabel, stageMountPoints)
|
||||
mount, image, err := internalParse.GetBindMount(context, tokens, contextDir, b.store, b.MountLabel, stageMountPoints, workDir)
|
||||
if err != nil {
|
||||
return nil, image, err
|
||||
}
|
||||
|
|
|
@ -305,7 +305,7 @@ func setupSpecialMountSpecChanges(spec *spec.Spec, shmSize string) ([]specs.Moun
|
|||
}
|
||||
|
||||
// If this function succeeds and returns a non-nil *lockfile.LockFile, the caller must unlock it (when??).
|
||||
func (b *Builder) getCacheMount(tokens []string, stageMountPoints map[string]internal.StageMountDetails, idMaps IDMaps) (*spec.Mount, *lockfile.LockFile, error) {
|
||||
func (b *Builder) getCacheMount(tokens []string, stageMountPoints map[string]internal.StageMountDetails, idMaps IDMaps, workDir string) (*spec.Mount, *lockfile.LockFile, error) {
|
||||
return nil, nil, errors.New("cache mounts not supported on freebsd")
|
||||
}
|
||||
|
||||
|
|
|
@ -114,8 +114,10 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
|||
return err
|
||||
}
|
||||
|
||||
workDir := b.WorkDir()
|
||||
if options.WorkingDir != "" {
|
||||
g.SetProcessCwd(options.WorkingDir)
|
||||
workDir = options.WorkingDir
|
||||
} else if b.WorkDir() != "" {
|
||||
g.SetProcessCwd(b.WorkDir())
|
||||
}
|
||||
|
@ -320,6 +322,7 @@ rootless=%d
|
|||
}
|
||||
|
||||
runMountInfo := runMountInfo{
|
||||
WorkDir: workDir,
|
||||
ContextDir: options.ContextDir,
|
||||
Secrets: options.Secrets,
|
||||
SSHSources: options.SSHSources,
|
||||
|
@ -1199,9 +1202,9 @@ func checkIdsGreaterThan5(ids []spec.LinuxIDMapping) bool {
|
|||
}
|
||||
|
||||
// If this function succeeds and returns a non-nil *lockfile.LockFile, the caller must unlock it (when??).
|
||||
func (b *Builder) getCacheMount(tokens []string, stageMountPoints map[string]internal.StageMountDetails, idMaps IDMaps) (*spec.Mount, *lockfile.LockFile, error) {
|
||||
func (b *Builder) getCacheMount(tokens []string, stageMountPoints map[string]internal.StageMountDetails, idMaps IDMaps, workDir string) (*spec.Mount, *lockfile.LockFile, error) {
|
||||
var optionMounts []specs.Mount
|
||||
mount, targetLock, err := internalParse.GetCacheMount(tokens, b.store, b.MountLabel, stageMountPoints)
|
||||
mount, targetLock, err := internalParse.GetCacheMount(tokens, b.store, b.MountLabel, stageMountPoints, workDir)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
|
@ -508,6 +508,30 @@ _EOF
|
|||
expect_output --substring "Groups: 1000"
|
||||
}
|
||||
|
||||
@test "build-test --mount=type=cache test relative to workdir mount" {
|
||||
local contextdir=${TEST_SCRATCH_DIR}/bud/platform
|
||||
mkdir -p $contextdir
|
||||
## write-cache
|
||||
cat > $contextdir/Dockerfile << _EOF
|
||||
FROM alpine
|
||||
RUN mkdir test
|
||||
WORKDIR test
|
||||
RUN --mount=type=cache,id=YfHI60aApFM-target,target=target echo world > /test/target/hello
|
||||
_EOF
|
||||
|
||||
run_buildah build $WITH_POLICY_JSON -t source -f $contextdir/Dockerfile
|
||||
|
||||
cat > $contextdir/Dockerfile << _EOF
|
||||
FROM alpine
|
||||
RUN mkdir test
|
||||
WORKDIR test
|
||||
RUN --mount=type=cache,id=YfHI60aApFM-target,target=target cat /test/target/hello
|
||||
_EOF
|
||||
|
||||
run_buildah build $WITH_POLICY_JSON -t source -f $contextdir/Dockerfile
|
||||
expect_output --substring "world"
|
||||
}
|
||||
|
||||
@test "build-test skipping unwanted stages with --skip-unused-stages=false and --skip-unused-stages=true" {
|
||||
local contextdir=${TEST_SCRATCH_DIR}/bud/platform
|
||||
mkdir -p $contextdir
|
||||
|
|
Loading…
Reference in New Issue