Update to the latest version of buildah

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2020-02-18 18:03:48 -05:00
parent f2bcc9cc7d
commit 96de762eed
80 changed files with 3323 additions and 1815 deletions

View File

@@ -13,11 +13,11 @@ import (
"strings"
"github.com/containers/buildah"
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/types"
"github.com/containers/storage"
"github.com/containers/storage/pkg/archive"
"github.com/opencontainers/runc/libcontainer/configs"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/openshift/imagebuilder"
"github.com/pkg/errors"
@@ -66,7 +66,7 @@ type BuildOptions struct {
// RuntimeArgs adds global arguments for the runtime.
RuntimeArgs []string
// TransientMounts is a list of mounts that won't be kept in the image.
TransientMounts []Mount
TransientMounts []string
// Compression specifies the type of compression which is applied to
// layer blobs. The default is to not use compression, but
// archive.Gzip is recommended.
@@ -156,10 +156,16 @@ type BuildOptions struct {
ForceRmIntermediateCtrs bool
// BlobDirectory is a directory which we'll use for caching layer blobs.
BlobDirectory string
// Target the targeted FROM in the Dockerfile to build
// Target the targeted FROM in the Dockerfile to build.
Target string
// Devices are the additional devices to add to the containers
Devices []configs.Device
// Devices are the additional devices to add to the containers.
Devices []string
// SignBy is the fingerprint of a GPG key to use for signing images.
SignBy string
// Architecture specifies the target architecture of the image to be built.
Architecture string
// OS is the specifies the operating system of the image to be built.
OS string
}
// BuildDockerfiles parses a set of one or more Dockerfiles (which may be
@@ -250,6 +256,11 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOpt
return "", nil, errors.Wrapf(err, "error creating build executor")
}
b := imagebuilder.NewBuilder(options.Args)
defaultContainerConfig, err := config.Default()
if err != nil {
return "", nil, errors.Wrapf(err, "failed to get container config")
}
b.Env = append(defaultContainerConfig.GetDefaultEnv(), b.Env...)
stages, err := imagebuilder.NewStages(mainNode, b)
if err != nil {
return "", nil, errors.Wrap(err, "error reading multiple stages")

View File

@@ -11,7 +11,9 @@ import (
"strings"
"github.com/containers/buildah"
"github.com/containers/buildah/pkg/parse"
"github.com/containers/buildah/util"
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
is "github.com/containers/image/v5/storage"
"github.com/containers/image/v5/transports"
@@ -91,17 +93,44 @@ type Executor struct {
excludes []string
unusedArgs map[string]struct{}
buildArgs map[string]string
addCapabilities []string
dropCapabilities []string
capabilities []string
devices []configs.Device
signBy string
architecture string
os string
}
// NewExecutor creates a new instance of the imagebuilder.Executor interface.
func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Node) (*Executor, error) {
defaultContainerConfig, err := config.Default()
if err != nil {
return nil, errors.Wrapf(err, "failed to get container config")
}
excludes, err := imagebuilder.ParseDockerignore(options.ContextDirectory)
if err != nil {
return nil, err
}
capabilities := defaultContainerConfig.Capabilities("", options.AddCapabilities, options.DropCapabilities)
devices := []configs.Device{}
for _, device := range append(defaultContainerConfig.Containers.AdditionalDevices, options.Devices...) {
dev, err := parse.DeviceFromPath(device)
if err != nil {
return nil, err
}
devices = append(dev, devices...)
}
transientMounts := []Mount{}
for _, volume := range append(defaultContainerConfig.Containers.AdditionalVolumes, options.TransientMounts...) {
mount, err := parse.Volume(volume)
if err != nil {
return nil, err
}
transientMounts = append([]Mount{Mount(mount)}, transientMounts...)
}
exec := Executor{
store: store,
@@ -113,7 +142,7 @@ func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Nod
quiet: options.Quiet,
runtime: options.Runtime,
runtimeArgs: options.RuntimeArgs,
transientMounts: options.TransientMounts,
transientMounts: transientMounts,
compression: options.Compression,
output: options.Output,
outputFormat: options.OutputFormat,
@@ -148,9 +177,11 @@ func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Nod
blobDirectory: options.BlobDirectory,
unusedArgs: make(map[string]struct{}),
buildArgs: options.Args,
addCapabilities: options.AddCapabilities,
dropCapabilities: options.DropCapabilities,
devices: options.Devices,
capabilities: capabilities,
devices: devices,
signBy: options.SignBy,
architecture: options.Architecture,
os: options.OS,
}
if exec.err == nil {
exec.err = os.Stderr
@@ -527,7 +558,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
if err := cleanup(); err != nil {
return "", nil, err
}
logrus.Debugf("printing final image id %q", imageID)
if b.iidfile != "" {
if err = ioutil.WriteFile(b.iidfile, []byte(imageID), 0644); err != nil {
return imageID, ref, errors.Wrapf(err, "failed to write image ID to file %q", b.iidfile)
@@ -537,7 +568,6 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
return imageID, ref, errors.Wrapf(err, "failed to write image ID to stdout")
}
}
return imageID, ref, nil
}

View File

@@ -253,7 +253,7 @@ func (s *StageExecutor) volumeCacheRestore() error {
// don't care about the details of where in the filesystem the content actually
// goes, because we're not actually going to add it here, so this is less
// involved than Copy().
func (s *StageExecutor) digestSpecifiedContent(node *parser.Node, argValues []string) (string, error) {
func (s *StageExecutor) digestSpecifiedContent(node *parser.Node, argValues []string, envValues []string) (string, error) {
// No instruction: done.
if node == nil {
return "", nil
@@ -298,10 +298,11 @@ func (s *StageExecutor) digestSpecifiedContent(node *parser.Node, argValues []st
}
}
varValues := append(argValues, envValues...)
for _, src := range srcs {
// If src has an argument within it, resolve it to its
// value. Otherwise just return the value found.
name, err := imagebuilder.ProcessWord(src, argValues)
name, err := imagebuilder.ProcessWord(src, varValues)
if err != nil {
return "", errors.Wrapf(err, "unable to resolve source %q", src)
}
@@ -315,8 +316,12 @@ func (s *StageExecutor) digestSpecifiedContent(node *parser.Node, argValues []st
} else {
// Source is not a URL, so it's a location relative to
// the all-content-comes-from-below-this-directory
// directory.
// directory. Also raise an error if the src escapes
// the context directory.
contextSrc, err := securejoin.SecureJoin(contextDir, src)
if err == nil && strings.HasPrefix(src, "../") {
err = errors.New("escaping context directory error")
}
if err != nil {
return "", errors.Wrapf(err, "forbidden path for %q, it is outside of the build context %q", src, contextDir)
}
@@ -345,7 +350,7 @@ func (s *StageExecutor) digestSpecifiedContent(node *parser.Node, argValues []st
// If destination.Value has an argument within it, resolve it to its
// value. Otherwise just return the value found.
destValue, destErr := imagebuilder.ProcessWord(destination.Value, argValues)
destValue, destErr := imagebuilder.ProcessWord(destination.Value, varValues)
if destErr != nil {
return "", errors.Wrapf(destErr, "unable to resolve destination %q", destination.Value)
}
@@ -434,8 +439,12 @@ func (s *StageExecutor) Copy(excludes []string, copies ...imagebuilder.Copy) err
// Treat the source, which is not a URL, as a
// location relative to the
// all-content-comes-from-below-this-directory
// directory.
// directory. Also raise an error if the src
// escapes the context directory.
srcSecure, err := securejoin.SecureJoin(contextDir, src)
if err == nil && strings.HasPrefix(src, "../") {
err = errors.New("escaping context directory error")
}
if err != nil {
return errors.Wrapf(err, "forbidden path for %q, it is outside of the build context %q", src, contextDir)
}
@@ -452,6 +461,11 @@ func (s *StageExecutor) Copy(excludes []string, copies ...imagebuilder.Copy) err
Excludes: copyExcludes,
IDMappingOptions: idMappingOptions,
}
// If we've a tar file, it will create a directory using the name of the tar
// file if we don't blank it out.
if strings.HasSuffix(srcName, ".tar") || strings.HasSuffix(srcName, ".gz") {
srcName = ""
}
if err := s.builder.Add(filepath.Join(copy.Dest, srcName), copy.Download, options, srcSecure); err != nil {
return err
}
@@ -605,8 +619,7 @@ func (s *StageExecutor) prepare(ctx context.Context, stage imagebuilder.Stage, f
CommonBuildOpts: s.executor.commonBuildOptions,
DefaultMountsFilePath: s.executor.defaultMountsFilePath,
Format: s.executor.outputFormat,
AddCapabilities: s.executor.addCapabilities,
DropCapabilities: s.executor.dropCapabilities,
Capabilities: s.executor.capabilities,
Devices: s.executor.devices,
}
@@ -771,8 +784,12 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
}
}
logImageID := func(imgID string) {
if len(imgID) > 11 {
imgID = imgID[0:11]
}
if s.executor.iidfile == "" {
fmt.Fprintf(s.executor.out, "%s\n", imgID)
fmt.Fprintf(s.executor.out, "--> %s\n", imgID)
}
}
@@ -869,7 +886,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
return "", nil, errors.Wrapf(err, "error building at STEP \"%s\"", step.Message)
}
// In case we added content, retrieve its digest.
addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments())
addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments(), ib.Config().Env)
if err != nil {
return "", nil, err
}
@@ -918,7 +935,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
// cached images so far, look for one that matches what we
// expect to produce for this instruction.
if checkForLayers && !(s.executor.squash && lastInstruction && lastStage) {
addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments())
addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments(), ib.Config().Env)
if err != nil {
return "", nil, err
}
@@ -976,7 +993,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
return "", nil, errors.Wrapf(err, "error building at STEP \"%s\"", step.Message)
}
// In case we added content, retrieve its digest.
addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments())
addedContentDigest, err := s.digestSpecifiedContent(node, ib.Arguments(), ib.Config().Env)
if err != nil {
return "", nil, err
}
@@ -1013,7 +1030,6 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
}
}
}
return imgID, ref, nil
}
@@ -1132,6 +1148,8 @@ func (s *StageExecutor) commit(ctx context.Context, ib *imagebuilder.Builder, cr
}
s.builder.SetHostname(config.Hostname)
s.builder.SetDomainname(config.Domainname)
s.builder.SetArchitecture(s.executor.architecture)
s.builder.SetOS(s.executor.os)
s.builder.SetUser(config.User)
s.builder.ClearPorts()
for p := range config.ExposedPorts {
@@ -1204,6 +1222,7 @@ func (s *StageExecutor) commit(ctx context.Context, ib *imagebuilder.Builder, cr
Squash: s.executor.squash,
EmptyLayer: emptyLayer,
BlobDirectory: s.executor.blobDirectory,
SignBy: s.executor.signBy,
}
imgID, _, manifestDigest, err := s.builder.Commit(ctx, imageRef, options)
if err != nil {