Skip to content

Commit

Permalink
build: Add support for buildkit like --mount=type=bind
Browse files Browse the repository at this point in the history
Following commit adds support for using buildkit like
`--mount=type=bind` with `RUN` statements. Mounts created by `--mount`
are transient in nature and only scoped to current RUN statements.

Signed-off-by: Aditya Rajan <arajan@redhat.com>
  • Loading branch information
flouthoc committed Sep 28, 2021
1 parent a62fcb9 commit 2029320
Show file tree
Hide file tree
Showing 8 changed files with 296,330 additions and 9 deletions.
4 changes: 4 additions & 0 deletions buildah.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ type Builder struct {

// Args define variables that users can pass at build-time to the builder
Args map[string]string
// Context Dir for current build
ContextDir string
// Type is used to help identify a build container's metadata. It
// should not be modified.
Type string `json:"type"`
Expand Down Expand Up @@ -259,6 +261,8 @@ type BuilderOptions struct {
FromImage string
// Container is a desired name for the build container.
Container string
// ContextDirectory of current build
ContextDir string
// PullPolicy decides whether or not we should pull the image that
// we're using as a base image. It should be PullIfMissing,
// PullAlways, or PullNever.
Expand Down
1 change: 1 addition & 0 deletions imagebuildah/stage_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,7 @@ func (s *StageExecutor) prepare(ctx context.Context, from string, initializeIBCo
ConfigureNetwork: s.executor.configureNetwork,
CNIPluginPath: s.executor.cniPluginPath,
CNIConfigDir: s.executor.cniConfigDir,
ContextDir: s.executor.contextDir,
IDMappingOptions: s.executor.idmappingOptions,
CommonBuildOpts: s.executor.commonBuildOptions,
DefaultMountsFilePath: s.executor.defaultMountsFilePath,
Expand Down
1 change: 1 addition & 0 deletions new.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions
FromImageDigest: imageDigest,
Container: name,
ContainerID: container.ID,
ContextDir: options.ContextDir,
ImageAnnotations: imageAnnotations,
ImageCreatedBy: "",
ProcessLabel: container.ProcessLabel(),
Expand Down
76 changes: 67 additions & 9 deletions run_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -518,12 +518,18 @@ func (b *Builder) setupMounts(mountPoint string, spec *specs.Spec, bundlePath st
return nil, err
}

// Get host UID and GID of the container process.
processUID, processGID, err := util.GetHostIDs(spec.Linux.UIDMappings, spec.Linux.GIDMappings, spec.Process.User.UID, spec.Process.User.GID)
if err != nil {
return nil, err
}

// Get the list of subscriptions mounts.
subscriptionMounts := subscriptions.MountsWithUIDGID(b.MountLabel, cdir, b.DefaultMountsFilePath, mountPoint, int(rootUID), int(rootGID), unshare.IsRootless(), false)

// Get the list of mounts that are just for this Run() call.
// TODO: acui: de-spaghettify run mounts
runMounts, mountArtifacts, err := runSetupRunMounts(runFileMounts, secrets, sshSources, b.MountLabel, cdir, spec.Linux.UIDMappings, spec.Linux.GIDMappings, b.ProcessLabel)
runMounts, mountArtifacts, err := b.runSetupRunMounts(runFileMounts, secrets, sshSources, cdir, spec.Linux.UIDMappings, spec.Linux.GIDMappings, int(rootUID), int(rootGID), int(processUID), int(processGID))
if err != nil {
return nil, err
}
Expand All @@ -533,11 +539,6 @@ func (b *Builder) setupMounts(mountPoint string, spec *specs.Spec, bundlePath st
if err != nil {
return nil, err
}
// Get host UID and GID of the container process.
processUID, processGID, err := util.GetHostIDs(spec.Linux.UIDMappings, spec.Linux.GIDMappings, spec.Process.User.UID, spec.Process.User.GID)
if err != nil {
return nil, err
}

// Get the list of explicitly-specified volume mounts.
volumes, err := b.runSetupVolumeMounts(spec.Linux.MountLabel, volumeMounts, optionMounts, int(rootUID), int(rootGID), int(processUID), int(processGID))
Expand Down Expand Up @@ -2325,7 +2326,7 @@ func init() {
}

// runSetupRunMounts sets up mounts that exist only in this RUN, not in subsequent runs
func runSetupRunMounts(mounts []string, secrets map[string]string, sshSources map[string]*sshagent.Source, mountlabel string, containerWorkingDir string, uidmap []spec.LinuxIDMapping, gidmap []spec.LinuxIDMapping, processLabel string) ([]spec.Mount, *runMountArtifacts, error) {
func (b *Builder) runSetupRunMounts(mounts []string, secrets map[string]string, sshSources map[string]*sshagent.Source, containerWorkingDir string, uidmap []spec.LinuxIDMapping, gidmap []spec.LinuxIDMapping, rootUID int, rootGID int, processUID int, processGID int) ([]spec.Mount, *runMountArtifacts, error) {
mountTargets := make([]string, 0, 10)
finalMounts := make([]specs.Mount, 0, len(mounts))
agents := make([]*sshagent.AgentServer, 0, len(mounts))
Expand All @@ -2345,7 +2346,7 @@ func runSetupRunMounts(mounts []string, secrets map[string]string, sshSources ma
// For now, we only support type secret.
switch kv[1] {
case "secret":
mount, err := getSecretMount(tokens, secrets, mountlabel, containerWorkingDir, uidmap, gidmap)
mount, err := getSecretMount(tokens, secrets, b.MountLabel, containerWorkingDir, uidmap, gidmap)
if err != nil {
return nil, nil, err
}
Expand All @@ -2355,7 +2356,7 @@ func runSetupRunMounts(mounts []string, secrets map[string]string, sshSources ma

}
case "ssh":
mount, agent, err := getSSHMount(tokens, sshCount, sshSources, mountlabel, uidmap, gidmap, processLabel)
mount, agent, err := getSSHMount(tokens, sshCount, sshSources, b.MountLabel, uidmap, gidmap, b.ProcessLabel)
if err != nil {
return nil, nil, err
}
Expand All @@ -2369,6 +2370,15 @@ func runSetupRunMounts(mounts []string, secrets map[string]string, sshSources ma
// Count is needed as the default destination of the ssh sock inside the container is /run/buildkit/ssh_agent.{i}
sshCount++
}
case "bind":
mount, err := getBindMount(b, tokens, rootUID, rootGID, processUID, processGID)
if err != nil {
return nil, nil, err
}
if mount != nil {
finalMounts = append(finalMounts, *mount)
mountTargets = append(mountTargets, mount.Destination)
}
default:
return nil, nil, errors.Errorf("invalid mount type %q", kv[1])
}
Expand All @@ -2381,6 +2391,54 @@ func runSetupRunMounts(mounts []string, secrets map[string]string, sshSources ma
return finalMounts, artifacts, nil
}

func getBindMount(builderInstance *Builder, tokens []string, rootUID, rootGID, processUID, processGID int) (*spec.Mount, error) {
errInvalidSyntax := errors.New("--mount should have syntax source=path[optional],target=path")
if len(tokens) == 0 {
return nil, errInvalidSyntax
}
var source, target, mountOpts string
var volumeMounts []string

for _, val := range tokens {
kv := strings.SplitN(val, "=", 2)
switch kv[0] {
case "source":
source = kv[1]
case "target", "dst", "destination":
target = kv[1]
default:
return nil, errInvalidSyntax
}
}
if source == "" || source == "." {
// buildkit parity use current buildcontext
// if source is empty or `.`
source = builderInstance.ContextDir
}
if target == "" {
//target cannot be empty
return nil, errInvalidSyntax
}
// check if target has format /mnt:options
targetOptions := strings.SplitN(target, ":", 2)
if len(targetOptions) > 1 {
mountOpts = targetOptions[1]
}

//defaults to readonly mount
if mountOpts == "" {
mountOpts = "z"
}
mountStmt := fmt.Sprintf("%s:%s:%s", source, targetOptions[0], mountOpts)
volumeMounts = append(volumeMounts, mountStmt)

volumes, err := builderInstance.runSetupVolumeMounts(builderInstance.MountLabel, volumeMounts, nil, rootUID, rootGID, processUID, processGID)
if err != nil {
return nil, err
}
return &volumes[0], nil
}

func getSecretMount(tokens []string, secrets map[string]string, mountlabel string, containerWorkingDir string, uidmap []spec.LinuxIDMapping, gidmap []spec.LinuxIDMapping) (*spec.Mount, error) {
errInvalidSyntax := errors.New("secret should have syntax id=id[,target=path,required=bool,mode=uint,uid=uint,gid=uint")
if len(tokens) == 0 {
Expand Down

0 comments on commit 2029320

Please sign in to comment.