diff options
author | OpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com> | 2019-04-29 07:11:20 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-29 07:11:20 -0700 |
commit | 627bfd07d2e7650967e3eef206446211bf07db3d (patch) | |
tree | 9c4babbcb5e727827c4ba4a82bf317c0ab956c98 | |
parent | e0312334cca5d8f5adf9844100f15317a86068d4 (diff) | |
parent | 0a64268752da5b18d008c45c86639280a62b3b20 (diff) | |
download | podman-627bfd07d2e7650967e3eef206446211bf07db3d.tar.gz podman-627bfd07d2e7650967e3eef206446211bf07db3d.tar.bz2 podman-627bfd07d2e7650967e3eef206446211bf07db3d.zip |
Merge pull request #3016 from rhatdan/vendor
Vendor in latest containers/storage and containers/buildah
19 files changed, 440 insertions, 216 deletions
diff --git a/vendor.conf b/vendor.conf index 572ae5fdb..02283beb9 100644 --- a/vendor.conf +++ b/vendor.conf @@ -19,7 +19,7 @@ github.com/containers/image v1.5.1 github.com/vbauerster/mpb v3.3.4 github.com/mattn/go-isatty v0.0.4 github.com/VividCortex/ewma v1.1.1 -github.com/containers/storage v1.12.3 +github.com/containers/storage v1.12.5 github.com/containers/psgo v1.2.1 github.com/coreos/go-systemd v14 github.com/coreos/pkg v4 @@ -94,7 +94,7 @@ k8s.io/apimachinery kubernetes-1.10.13-beta.0 https://github.com/kubernetes/apim k8s.io/client-go kubernetes-1.10.13-beta.0 https://github.com/kubernetes/client-go github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7 github.com/varlink/go 3ac79db6fd6aec70924193b090962f92985fe199 -github.com/containers/buildah fcc12bdadf6a5fab77e62e1bd12663bb6fbc3eda +github.com/containers/buildah v1.8.0 # TODO: Gotty has not been updated since 2012. Can we find replacement? github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512 github.com/fsouza/go-dockerclient v1.3.0 diff --git a/vendor/github.com/containers/buildah/add.go b/vendor/github.com/containers/buildah/add.go index d42246d53..d67a481f1 100644 --- a/vendor/github.com/containers/buildah/add.go +++ b/vendor/github.com/containers/buildah/add.go @@ -292,7 +292,7 @@ func addHelper(excludes []DockerIgnore, extract bool, dest string, destfi os.Fil break } // combine the filename with the dest directory - fpath := strings.TrimPrefix(path, options.ContextDir) + fpath := strings.TrimPrefix(path, esrc) if err = copyFileWithTar(path, filepath.Join(dest, fpath)); err != nil { return errors.Wrapf(err, "error copying %q to %q", path, dest) } diff --git a/vendor/github.com/containers/buildah/buildah.go b/vendor/github.com/containers/buildah/buildah.go index 8b076630f..b6e6545ec 100644 --- a/vendor/github.com/containers/buildah/buildah.go +++ b/vendor/github.com/containers/buildah/buildah.go @@ -26,7 +26,7 @@ const ( Package = "buildah" // Version for the Package. Bump version in contrib/rpm/buildah.spec // too. - Version = "1.8-dev" + Version = "1.8.0" // The value we use to identify what type of information, currently a // serialized Builder structure, we are using as per-container state. // This should only be changed when we make incompatible changes to @@ -282,6 +282,8 @@ type CommonBuildOptions struct { CPUSetCPUs string // CPUSetMems memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems. CPUSetMems string + // HTTPProxy determines whether *_proxy env vars from the build host are passed into the container. + HTTPProxy bool // Memory is the upper limit (in bytes) on how much memory running containers can use. Memory int64 // DNSSearch is the list of DNS search domains to add to the build container's /etc/resolv.conf diff --git a/vendor/github.com/containers/buildah/chroot/run.go b/vendor/github.com/containers/buildah/chroot/run.go index ff39c2f24..1c3ac65f3 100644 --- a/vendor/github.com/containers/buildah/chroot/run.go +++ b/vendor/github.com/containers/buildah/chroot/run.go @@ -512,7 +512,7 @@ func runUsingChroot(spec *specs.Spec, bundlePath string, ctty *os.File, stdin io logNamespaceDiagnostics(spec) // If we have configured ID mappings, set them here so that they can apply to the child. - hostUidmap, hostGidmap, err := util.GetHostIDMappings("") + hostUidmap, hostGidmap, err := unshare.GetHostIDMappings("") if err != nil { return 1, err } diff --git a/vendor/github.com/containers/buildah/chroot/selinux.go b/vendor/github.com/containers/buildah/chroot/selinux.go index 3e62d743d..08e8f998b 100644 --- a/vendor/github.com/containers/buildah/chroot/selinux.go +++ b/vendor/github.com/containers/buildah/chroot/selinux.go @@ -13,7 +13,7 @@ import ( // setSelinuxLabel sets the process label for child processes that we'll start. func setSelinuxLabel(spec *specs.Spec) error { logrus.Debugf("setting selinux label") - if spec.Process.SelinuxLabel != "" && selinux.EnforceMode() != selinux.Disabled { + if spec.Process.SelinuxLabel != "" && selinux.GetEnabled() { if err := label.SetProcessLabel(spec.Process.SelinuxLabel); err != nil { return errors.Wrapf(err, "error setting process label to %q", spec.Process.SelinuxLabel) } diff --git a/vendor/github.com/containers/buildah/commit.go b/vendor/github.com/containers/buildah/commit.go index 5e73be881..05d1550b3 100644 --- a/vendor/github.com/containers/buildah/commit.go +++ b/vendor/github.com/containers/buildah/commit.go @@ -64,12 +64,9 @@ type CommitOptions struct { // manifest of the new image will reference the blobs rather than // on-disk layers. BlobDirectory string - - // OnBuild is a list of commands to be run by images based on this image - OnBuild []string - // Parent is the base image that this image was created by. - Parent string - + // EmptyLayer tells the builder to omit the diff for the working + // container. + EmptyLayer bool // OmitTimestamp forces epoch 0 as created timestamp to allow for // deterministic, content-addressable builds. OmitTimestamp bool @@ -169,7 +166,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options } } // Build an image reference from which we can copy the finished image. - src, err := b.makeImageRef(options.PreferredManifestType, options.Parent, exportBaseLayers, options.Squash, options.BlobDirectory, options.Compression, options.HistoryTimestamp, options.OmitTimestamp) + src, err := b.makeImageRef(options, exportBaseLayers) if err != nil { return imgID, nil, "", errors.Wrapf(err, "error computing layer digests and building metadata for container %q", b.ContainerID) } diff --git a/vendor/github.com/containers/buildah/image.go b/vendor/github.com/containers/buildah/image.go index 1cd329c85..215920cc3 100644 --- a/vendor/github.com/containers/buildah/image.go +++ b/vendor/github.com/containers/buildah/image.go @@ -56,6 +56,7 @@ type containerImageRef struct { preferredManifestType string exporting bool squash bool + emptyLayer bool tarPath func(path string) (io.ReadCloser, error) parent string blobDirectory string @@ -184,7 +185,7 @@ func (i *containerImageRef) createConfigsAndManifests() (v1.Image, v1.Manifest, if err := json.Unmarshal(i.dconfig, &dimage); err != nil { return v1.Image{}, v1.Manifest{}, docker.V2Image{}, docker.V2S2Manifest{}, err } - dimage.Parent = docker.ID(digest.FromString(i.parent)) + dimage.Parent = docker.ID(i.parent) // Always replace this value, since we're newer than our base image. dimage.Created = created // Clear the list of diffIDs, since we always repopulate it. @@ -290,6 +291,11 @@ func (i *containerImageRef) NewImageSource(ctx context.Context, sc *types.System if err != nil { return nil, errors.Wrapf(err, "unable to locate layer %q", layerID) } + // If we're up to the final layer, but we don't want to include + // a diff for it, we're done. + if i.emptyLayer && layerID == i.layerID { + continue + } // If we're not re-exporting the data, and we're reusing layers individually, reuse // the blobsum and diff IDs. if !i.exporting && !i.squash && layerID != i.layerID { @@ -433,7 +439,7 @@ func (i *containerImageRef) NewImageSource(ctx context.Context, sc *types.System CreatedBy: i.createdBy, Author: oimage.Author, Comment: i.historyComment, - EmptyLayer: false, + EmptyLayer: i.emptyLayer, } oimage.History = append(oimage.History, onews) dnews := docker.V2S2History{ @@ -441,11 +447,11 @@ func (i *containerImageRef) NewImageSource(ctx context.Context, sc *types.System CreatedBy: i.createdBy, Author: dimage.Author, Comment: i.historyComment, - EmptyLayer: false, + EmptyLayer: i.emptyLayer, } dimage.History = append(dimage.History, dnews) appendHistory(i.postEmptyLayers) - dimage.Parent = docker.ID(digest.FromString(i.parent)) + dimage.Parent = docker.ID(i.parent) // Sanity check that we didn't just create a mismatch between non-empty layers in the // history and the number of diffIDs. @@ -636,7 +642,7 @@ func (i *containerImageSource) GetBlob(ctx context.Context, blob types.BlobInfo, return ioutils.NewReadCloserWrapper(layerFile, closer), size, nil } -func (b *Builder) makeImageRef(manifestType, parent string, exporting bool, squash bool, blobDirectory string, compress archive.Compression, historyTimestamp *time.Time, omitTimestamp bool) (types.ImageReference, error) { +func (b *Builder) makeImageRef(options CommitOptions, exporting bool) (types.ImageReference, error) { var name reference.Named container, err := b.store.Container(b.ContainerID) if err != nil { @@ -647,6 +653,7 @@ func (b *Builder) makeImageRef(manifestType, parent string, exporting bool, squa name = parsed } } + manifestType := options.PreferredManifestType if manifestType == "" { manifestType = OCIv1ImageManifest } @@ -659,8 +666,8 @@ func (b *Builder) makeImageRef(manifestType, parent string, exporting bool, squa return nil, errors.Wrapf(err, "error encoding docker-format image configuration %#v", b.Docker) } created := time.Now().UTC() - if historyTimestamp != nil { - created = historyTimestamp.UTC() + if options.HistoryTimestamp != nil { + created = options.HistoryTimestamp.UTC() } createdBy := b.CreatedBy() if createdBy == "" { @@ -670,13 +677,21 @@ func (b *Builder) makeImageRef(manifestType, parent string, exporting bool, squa } } - if omitTimestamp { + if options.OmitTimestamp { created = time.Unix(0, 0) } + parent := "" + if b.FromImageID != "" { + parentDigest := digest.NewDigestFromEncoded(digest.Canonical, b.FromImageID) + if parentDigest.Validate() == nil { + parent = parentDigest.String() + } + } + ref := &containerImageRef{ store: b.store, - compression: compress, + compression: options.Compression, name: name, names: container.Names, containerID: container.ID, @@ -690,10 +705,11 @@ func (b *Builder) makeImageRef(manifestType, parent string, exporting bool, squa annotations: b.Annotations(), preferredManifestType: manifestType, exporting: exporting, - squash: squash, + squash: options.Squash, + emptyLayer: options.EmptyLayer, tarPath: b.tarPath(), parent: parent, - blobDirectory: blobDirectory, + blobDirectory: options.BlobDirectory, preEmptyLayers: b.PrependedEmptyLayers, postEmptyLayers: b.AppendedEmptyLayers, } diff --git a/vendor/github.com/containers/buildah/imagebuildah/build.go b/vendor/github.com/containers/buildah/imagebuildah/build.go index b692d3bcf..d9909cdc8 100644 --- a/vendor/github.com/containers/buildah/imagebuildah/build.go +++ b/vendor/github.com/containers/buildah/imagebuildah/build.go @@ -28,7 +28,7 @@ import ( "github.com/containers/storage" "github.com/containers/storage/pkg/archive" docker "github.com/fsouza/go-dockerclient" - "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/opencontainers/runtime-spec/specs-go" "github.com/openshift/imagebuilder" "github.com/openshift/imagebuilder/dockerfile/parser" @@ -215,9 +215,12 @@ type Executor struct { forceRmIntermediateCtrs bool imageMap map[string]string // Used to map images that we create to handle the AS construct. containerMap map[string]*buildah.Builder // Used to map from image names to only-created-for-the-rootfs containers. + baseMap map[string]bool // Holds the names of every base image, as given. + rootfsMap map[string]bool // Holds the names of every stage whose rootfs is referenced in a COPY or ADD instruction. blobDirectory string excludes []string unusedArgs map[string]struct{} + buildArgs map[string]string } // StageExecutor bundles up what we need to know when executing one stage of a @@ -480,6 +483,19 @@ func (s *StageExecutor) volumeCacheRestore() error { // imagebuilder tells us the instruction was "ADD" and not "COPY". func (s *StageExecutor) Copy(excludes []string, copies ...imagebuilder.Copy) error { for _, copy := range copies { + // If the file exists, check to see if it's a symlink. + // If it is a symlink, convert to it's target otherwise + // the symlink will be overwritten. + fileDest, _ := os.Lstat(filepath.Join(s.mountPoint, copy.Dest)) + if fileDest != nil { + if fileDest.Mode()&os.ModeSymlink != 0 { + if symLink, err := resolveSymlink(s.mountPoint, copy.Dest); err == nil { + copy.Dest = symLink + } else { + return errors.Wrapf(err, "error reading symbolic link to %q", copy.Dest) + } + } + } if copy.Download { logrus.Debugf("ADD %#v, %#v", excludes, copy) } else { @@ -590,7 +606,7 @@ func (s *StageExecutor) Run(run imagebuilder.Run, config docker.Config) error { // UnrecognizedInstruction is called when we encounter an instruction that the // imagebuilder parser didn't understand. func (s *StageExecutor) UnrecognizedInstruction(step *imagebuilder.Step) error { - errStr := fmt.Sprintf("Build error: Unknown instruction: %q ", step.Command) + errStr := fmt.Sprintf("Build error: Unknown instruction: %q ", strings.ToUpper(step.Command)) err := fmt.Sprintf(errStr+"%#v", step) if s.executor.ignoreUnrecognizedInstructions { logrus.Debugf(err) @@ -610,7 +626,7 @@ func (s *StageExecutor) UnrecognizedInstruction(step *imagebuilder.Step) error { } // NewExecutor creates a new instance of the imagebuilder.Executor interface. -func NewExecutor(store storage.Store, options BuildOptions) (*Executor, error) { +func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Node) (*Executor, error) { excludes, err := imagebuilder.ParseDockerignore(options.ContextDirectory) if err != nil { return nil, err @@ -656,8 +672,11 @@ func NewExecutor(store storage.Store, options BuildOptions) (*Executor, error) { forceRmIntermediateCtrs: options.ForceRmIntermediateCtrs, imageMap: make(map[string]string), containerMap: make(map[string]*buildah.Builder), + baseMap: make(map[string]bool), + rootfsMap: make(map[string]bool), blobDirectory: options.BlobDirectory, unusedArgs: make(map[string]struct{}), + buildArgs: options.Args, } if exec.err == nil { exec.err = os.Stderr @@ -679,6 +698,25 @@ func NewExecutor(store storage.Store, options BuildOptions) (*Executor, error) { exec.unusedArgs[arg] = struct{}{} } } + for _, line := range mainNode.Children { + node := line + for node != nil { // tokens on this line, though we only care about the first + switch strings.ToUpper(node.Value) { // first token - instruction + case "ARG": + arg := node.Next + if arg != nil { + // We have to be careful here - it's either an argument + // and value, or just an argument, since they can be + // separated by either "=" or whitespace. + list := strings.SplitN(arg.Value, "=", 2) + if _, stillUnused := exec.unusedArgs[list[0]]; stillUnused { + delete(exec.unusedArgs, list[0]) + } + } + } + break + } + } return &exec, nil } @@ -845,9 +883,9 @@ func (b *Executor) resolveNameToImageRef(output string) (types.ImageReference, e return imageRef, nil } -// stepRequiresCommit indicates whether or not the step should be followed by -// committing the in-progress container to create an intermediate image. -func (*StageExecutor) stepRequiresCommit(step *imagebuilder.Step) bool { +// stepRequiresLayer indicates whether or not the step should be followed by +// committing a layer container when creating an intermediate image. +func (*StageExecutor) stepRequiresLayer(step *imagebuilder.Step) bool { switch strings.ToUpper(step.Command) { case "ADD", "COPY", "RUN": return true @@ -875,6 +913,10 @@ func (s *StageExecutor) getImageRootfs(ctx context.Context, stage imagebuilder.S func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, base string) (imgID string, ref reference.Canonical, err error) { ib := stage.Builder checkForLayers := s.executor.layers && s.executor.useCache + moreStages := s.index < s.stages-1 + lastStage := !moreStages + imageIsUsedLater := moreStages && (s.executor.baseMap[stage.Name] || s.executor.baseMap[fmt.Sprintf("%d", stage.Position)]) + rootfsIsUsedLater := moreStages && (s.executor.rootfsMap[stage.Name] || s.executor.rootfsMap[fmt.Sprintf("%d", stage.Position)]) // If the base image's name corresponds to the result of an earlier // stage, substitute that image's ID for the base image's name here. @@ -896,7 +938,8 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b // A helper function to only log "COMMIT" as an explicit step if it's // the very last step of a (possibly multi-stage) build. logCommit := func(output string, instruction int) { - if instruction < len(children)-1 || s.index < s.stages-1 { + moreInstructions := instruction < len(children)-1 + if moreInstructions || moreStages { return } commitMessage := "COMMIT" @@ -921,7 +964,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b // squash the contents of the base image. Whichever is // the case, we need to commit() to create a new image. logCommit(s.output, -1) - if imgID, ref, err = s.commit(ctx, ib, getCreatedBy(nil), s.output); err != nil { + if imgID, ref, err = s.commit(ctx, ib, s.executor.getCreatedBy(nil), false, s.output); err != nil { return "", nil, errors.Wrapf(err, "error committing base container") } } else { @@ -936,6 +979,8 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b } for i, node := range children { + moreInstructions := i < len(children)-1 + lastInstruction := !moreInstructions // Resolve any arguments in this instruction. step := ib.Step() if err := step.Resolve(node); err != nil { @@ -946,30 +991,19 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b s.executor.log("%s", step.Original) } - // If this instruction declares an argument, remove it from the - // set of arguments that we were passed but which we haven't - // yet seen used by the Dockerfile. - if step.Command == "arg" { - for _, Arg := range step.Args { - list := strings.SplitN(Arg, "=", 2) - if _, stillUnused := s.executor.unusedArgs[list[0]]; stillUnused { - delete(s.executor.unusedArgs, list[0]) - } - } - } - // Check if there's a --from if the step command is COPY or // ADD. Set copyFrom to point to either the context directory // or the root of the container from the specified stage. s.copyFrom = s.executor.contextDir for _, n := range step.Flags { - if strings.Contains(n, "--from") && (step.Command == "copy" || step.Command == "add") { + command := strings.ToUpper(step.Command) + if strings.Contains(n, "--from") && (command == "COPY" || command == "ADD") { var mountPoint string arr := strings.Split(n, "=") otherStage, ok := s.executor.stages[arr[1]] if !ok { if mountPoint, err = s.getImageRootfs(ctx, stage, arr[1]); err != nil { - return "", nil, errors.Errorf("%s --from=%s: no stage or image found with that name", step.Command, arr[1]) + return "", nil, errors.Errorf("%s --from=%s: no stage or image found with that name", command, arr[1]) } } else { mountPoint = otherStage.mountPoint @@ -984,7 +1018,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b // contents of any volumes declared between now and when we // finish. noRunsRemaining := false - if i < len(children)-1 { + if moreInstructions { noRunsRemaining = !ib.RequiresStart(&parser.Node{Children: children[i+1:]}) } @@ -996,24 +1030,29 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b logrus.Debugf("%v", errors.Wrapf(err, "error building at step %+v", *step)) return "", nil, errors.Wrapf(err, "error building at STEP \"%s\"", step.Message) } - if i < len(children)-1 { + if moreInstructions { // There are still more instructions to process // for this stage. Make a note of the // instruction in the history that we'll write // for the image when we eventually commit it. now := time.Now() - s.builder.AddPrependedEmptyLayer(&now, getCreatedBy(node), "", "") + s.builder.AddPrependedEmptyLayer(&now, s.executor.getCreatedBy(node), "", "") continue } else { // This is the last instruction for this stage, // so we should commit this container to create - // an image. - logCommit(s.output, i) - imgID, ref, err = s.commit(ctx, ib, getCreatedBy(node), s.output) - if err != nil { - return "", nil, errors.Wrapf(err, "error committing container for step %+v", *step) + // an image, but only if it's the last one, or + // if it's used as the basis for a later stage. + if lastStage || imageIsUsedLater { + logCommit(s.output, i) + imgID, ref, err = s.commit(ctx, ib, s.executor.getCreatedBy(node), false, s.output) + if err != nil { + return "", nil, errors.Wrapf(err, "error committing container for step %+v", *step) + } + logImageID(imgID) + } else { + imgID = "" } - logImageID(imgID) break } } @@ -1028,18 +1067,14 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b // If we have to commit for this instruction, only assign the // stage's configured output name to the last layer. - if i == len(children)-1 { + if lastInstruction { commitName = s.output } // If we're using the cache, and we've managed to stick with // cached images so far, look for one that matches what we // expect to produce for this instruction. - // Only check at steps where we commit, so that we don't - // abandon the cache at this step just because we can't find an - // image with a history entry in it that we wouldn't have - // committed. - if checkForLayers && (s.stepRequiresCommit(step) || i == len(children)-1) && !(s.executor.squash && i == len(children)-1 && s.index == s.stages-1) { + if checkForLayers && !(s.executor.squash && lastInstruction && lastStage) { cacheID, err = s.layerExists(ctx, node, children[:i]) if err != nil { return "", nil, errors.Wrap(err, "error checking if cached image exists from a previous build") @@ -1059,17 +1094,32 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b // the last step in this stage, add the name to the // image. imgID = cacheID - if commitName != "" && (s.stepRequiresCommit(step) || i == len(children)-1) { - logCommit(s.output, i) + if commitName != "" { + logCommit(commitName, i) if imgID, ref, err = s.copyExistingImage(ctx, cacheID, commitName); err != nil { return "", nil, err } logImageID(imgID) } // Update our working container to be based off of the - // cached image, in case we need to read content from - // its root filesystem. - rebase = true + // cached image, if we might need to use it as a basis + // for the next instruction, or if we need the root + // filesystem to match the image contents for the sake + // of a later stage that wants to copy content from it. + rebase = moreInstructions || rootfsIsUsedLater + // If the instruction would affect our configuration, + // process the configuration change so that, if we fall + // off the cache path, the filesystem changes from the + // last cache image will be all that we need, since we + // still don't want to restart using the image's + // configuration blob. + if !s.stepRequiresLayer(step) { + err := ib.Run(step, s, noRunsRemaining) + if err != nil { + logrus.Debugf("%v", errors.Wrapf(err, "error building at step %+v", *step)) + return "", nil, errors.Wrapf(err, "error building at STEP \"%s\"", step.Message) + } + } } else { // If we didn't find a cached image that we could just reuse, // process the instruction directly. @@ -1078,36 +1128,20 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b logrus.Debugf("%v", errors.Wrapf(err, "error building at step %+v", *step)) return "", nil, errors.Wrapf(err, "error building at STEP \"%s\"", step.Message) } - if s.stepRequiresCommit(step) || i == len(children)-1 { - // Either this is the last instruction, or - // there are more instructions and we need to - // create a layer from this one before - // continuing. - // TODO: only commit for the last instruction - // case if we need to use this stage's image as - // a base image later, or if we're the final - // stage. - logCommit(s.output, i) - imgID, ref, err = s.commit(ctx, ib, getCreatedBy(node), commitName) - if err != nil { - return "", nil, errors.Wrapf(err, "error committing container for step %+v", *step) - } - logImageID(imgID) - // We only need to build a new container rootfs - // using this image if we plan on making - // further changes to it. Subsequent stages - // that just want to use the rootfs as a source - // for COPY or ADD will be content with what we - // already have. - rebase = i < len(children)-1 - } else { - // There are still more instructions to process - // for this stage, and we don't need to commit - // here. Make a note of the instruction in the - // history for the next commit. - now := time.Now() - s.builder.AddPrependedEmptyLayer(&now, getCreatedBy(node), "", "") + // Create a new image, maybe with a new layer. + logCommit(s.output, i) + imgID, ref, err = s.commit(ctx, ib, s.executor.getCreatedBy(node), !s.stepRequiresLayer(step), commitName) + if err != nil { + return "", nil, errors.Wrapf(err, "error committing container for step %+v", *step) } + logImageID(imgID) + // We only need to build a new container rootfs + // using this image if we plan on making + // further changes to it. Subsequent stages + // that just want to use the rootfs as a source + // for COPY or ADD will be content with what we + // already have. + rebase = moreInstructions } if rebase { @@ -1122,8 +1156,6 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b // creating a new working container with the // just-committed or updated cached image as its new // base image. - // TODO: only create a new container if we know that - // we'll need the updated root filesystem. if _, err := s.prepare(ctx, stage, imgID, false, true); err != nil { return "", nil, errors.Wrap(err, "error preparing container for next step") } @@ -1195,13 +1227,13 @@ func (s *StageExecutor) layerExists(ctx context.Context, currNode *parser.Node, // it means that this image is potentially a cached intermediate image from a previous // build. Next we double check that the history of this image is equivalent to the previous // lines in the Dockerfile up till the point we are at in the build. - if layer.Parent == s.executor.topLayers[len(s.executor.topLayers)-1] { + if layer.Parent == s.executor.topLayers[len(s.executor.topLayers)-1] || layer.ID == s.executor.topLayers[len(s.executor.topLayers)-1] { history, err := s.executor.getImageHistory(ctx, image.ID) if err != nil { return "", errors.Wrapf(err, "error getting history of %q", image.ID) } // children + currNode is the point of the Dockerfile we are currently at. - if historyMatches(append(children, currNode), history) { + if s.executor.historyMatches(append(children, currNode), history) { // This checks if the files copied during build have been changed if the node is // a COPY or ADD command. filesMatch, err := s.copiedFilesMatch(currNode, history[len(history)-1].Created) @@ -1225,21 +1257,26 @@ func (b *Executor) getImageHistory(ctx context.Context, imageID string) ([]v1.Hi } ref, err := imageRef.NewImage(ctx, nil) if err != nil { - return nil, errors.Wrap(err, "error creating new image from reference") + return nil, errors.Wrapf(err, "error creating new image from reference to image %q", imageID) } + defer ref.Close() oci, err := ref.OCIConfig(ctx) if err != nil { - return nil, errors.Wrapf(err, "error getting oci config of image %q", imageID) + return nil, errors.Wrapf(err, "error getting possibly-converted OCI config of image %q", imageID) } return oci.History, nil } // getCreatedBy returns the command the image at node will be created by. -func getCreatedBy(node *parser.Node) string { +func (b *Executor) getCreatedBy(node *parser.Node) string { if node == nil { return "/bin/sh" } if node.Value == "run" { + buildArgs := b.getBuildArgs() + if buildArgs != "" { + return "|" + strconv.Itoa(len(strings.Split(buildArgs, " "))) + " " + buildArgs + " /bin/sh -c " + node.Original[4:] + } return "/bin/sh -c " + node.Original[4:] } return "/bin/sh -c #(nop) " + node.Original @@ -1249,12 +1286,23 @@ func getCreatedBy(node *parser.Node) string { // in the Dockerfile till the point of build we are at. // Used to verify whether a cache of the intermediate image exists and whether // to run the build again. -func historyMatches(children []*parser.Node, history []v1.History) bool { +func (b *Executor) historyMatches(children []*parser.Node, history []v1.History) bool { i := len(history) - 1 for j := len(children) - 1; j >= 0; j-- { instruction := children[j].Original if children[j].Value == "run" { instruction = instruction[4:] + buildArgs := b.getBuildArgs() + // If a previous image was built with some build-args but the new build process doesn't have any build-args + // specified, so compare the lengths of the old instruction with the current one + // 11 is the length of "/bin/sh -c " that is used to run the run commands + if buildArgs == "" && len(history[i].CreatedBy) > len(instruction)+11 { + return false + } + // There are build-args, so check if anything with the build-args has changed + if buildArgs != "" && !strings.Contains(history[i].CreatedBy, buildArgs) { + return false + } } if !strings.Contains(history[i].CreatedBy, instruction) { return false @@ -1264,6 +1312,18 @@ func historyMatches(children []*parser.Node, history []v1.History) bool { return true } +// getBuildArgs returns a string of the build-args specified during the build process +// it excludes any build-args that were not used in the build process +func (b *Executor) getBuildArgs() string { + var buildArgs []string + for k, v := range b.buildArgs { + if _, ok := b.unusedArgs[k]; !ok { + buildArgs = append(buildArgs, k+"="+v) + } + } + return strings.Join(buildArgs, " ") +} + // getFilesToCopy goes through node to get all the src files that are copied, added or downloaded. // It is possible for the Dockerfile to have src as hom*, which means all files that have hom as a prefix. // Another format is hom?.txt, which means all files that have that name format with the ? replaced by another character. @@ -1348,7 +1408,7 @@ func urlContentModified(url string, historyTime *time.Time) (bool, error) { // commit writes the container's contents to an image, using a passed-in tag as // the name if there is one, generating a unique ID-based one otherwise. -func (s *StageExecutor) commit(ctx context.Context, ib *imagebuilder.Builder, createdBy, output string) (string, reference.Canonical, error) { +func (s *StageExecutor) commit(ctx context.Context, ib *imagebuilder.Builder, createdBy string, emptyLayer bool, output string) (string, reference.Canonical, error) { var imageRef types.ImageReference if output != "" { imageRef2, err := s.executor.resolveNameToImageRef(output) @@ -1438,8 +1498,8 @@ func (s *StageExecutor) commit(ctx context.Context, ib *imagebuilder.Builder, cr PreferredManifestType: s.executor.outputFormat, SystemContext: s.executor.systemContext, Squash: s.executor.squash, + EmptyLayer: emptyLayer, BlobDirectory: s.executor.blobDirectory, - Parent: s.builder.FromImageID, } imgID, _, manifestDigest, err := s.builder.Commit(ctx, imageRef, options) if err != nil { @@ -1510,6 +1570,46 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image } defer cleanup() + // Build maps of every named base image and every referenced stage root + // filesystem. Individual stages can use them to determine whether or + // not they can skip certain steps near the end of their stages. + for _, stage := range stages { + node := stage.Node // first line + for node != nil { // each line + for _, child := range node.Children { // tokens on this line, though we only care about the first + switch strings.ToUpper(child.Value) { // first token - instruction + case "FROM": + if child.Next != nil { // second token on this line + base := child.Next.Value + if base != "scratch" { + // TODO: this didn't undergo variable and arg + // expansion, so if the AS clause in another + // FROM instruction uses argument values, + // we might not record the right value here. + b.baseMap[base] = true + logrus.Debugf("base: %q", base) + } + } + case "ADD", "COPY": + for _, flag := range child.Flags { // flags for this instruction + if strings.HasPrefix(flag, "--from=") { + // TODO: this didn't undergo variable and + // arg expansion, so if the previous stage + // was named using argument values, we might + // not record the right value here. + rootfs := flag[7:] + b.rootfsMap[rootfs] = true + logrus.Debugf("rootfs: %q", rootfs) + } + } + } + break + } + node = node.Next // next line + } + } + + // Run through the build stages, one at a time. for stageIndex, stage := range stages { var lastErr error @@ -1555,7 +1655,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image // If this is an intermediate stage, make a note of the ID, so // that we can look it up later. - if stageIndex < len(stages)-1 { + if stageIndex < len(stages)-1 && imageID != "" { b.imageMap[stage.Name] = imageID // We're not populating the cache with intermediate // images, so add this one to the list of images that @@ -1671,7 +1771,7 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOpt } mainNode.Children = append(mainNode.Children, additionalNode.Children...) } - exec, err := NewExecutor(store, options) + exec, err := NewExecutor(store, options, mainNode) if err != nil { return "", nil, errors.Wrapf(err, "error creating build executor") } diff --git a/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go b/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go index 86bf7653b..0789c2b3c 100644 --- a/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go +++ b/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go @@ -129,20 +129,20 @@ func resolveModifiedTime(rootdir, filename, historyTime string) (bool, error) { func modTimeIsGreater(rootdir, path string, historyTime string) (bool, error) { var timeIsGreater bool - // the Walk below doesn't work if rootdir and path are equal - if rootdir == path { - return false, nil - } - // Convert historyTime from string to time.Time for comparison histTime, err := time.Parse(time.RFC3339Nano, historyTime) if err != nil { return false, errors.Wrapf(err, "error converting string to time.Time %q", historyTime) } + + // Since we are chroot in rootdir, we want a relative path, i.e (path - rootdir) + relPath, err := filepath.Rel(rootdir, path) + if err != nil { + return false, errors.Wrapf(err, "error making path %q relative to %q", path, rootdir) + } + // Walk the file tree and check the time stamps. - // Since we are chroot in rootdir, only want the path of the actual filename, i.e path - rootdir. - // +1 to account for the extra "/" (e.g rootdir=/home/user/mydir, path=/home/user/mydir/myfile.json) - err = filepath.Walk(path[len(rootdir)+1:], func(path string, info os.FileInfo, err error) error { + err = filepath.Walk(relPath, func(path string, info os.FileInfo, err error) error { // If using cached images, it is possible for files that are being copied to come from // previous build stages. But if using cached images, then the copied file won't exist // since a container won't have been created for the previous build stage and info will be nil. @@ -154,6 +154,9 @@ func modTimeIsGreater(rootdir, path string, historyTime string) (bool, error) { if info.Mode()&os.ModeSymlink == os.ModeSymlink { // Evaluate any symlink that occurs to get updated modified information resolvedPath, err := filepath.EvalSymlinks(path) + if err != nil && os.IsNotExist(err) { + return errors.Wrapf(errDanglingSymlink, "%q", path) + } if err != nil { return errors.Wrapf(err, "error evaluating symlink %q", path) } @@ -169,7 +172,12 @@ func modTimeIsGreater(rootdir, path string, historyTime string) (bool, error) { } return nil }) + if err != nil { + // if error is due to dangling symlink, ignore error and return nil + if errors.Cause(err) == errDanglingSymlink { + return false, nil + } return false, errors.Wrapf(err, "error walking file tree %q", path) } return timeIsGreater, err diff --git a/vendor/github.com/containers/buildah/imagebuildah/errors.go b/vendor/github.com/containers/buildah/imagebuildah/errors.go new file mode 100644 index 000000000..cf299656b --- /dev/null +++ b/vendor/github.com/containers/buildah/imagebuildah/errors.go @@ -0,0 +1,7 @@ +package imagebuildah + +import "errors" + +var ( + errDanglingSymlink = errors.New("error evaluating dangling symlink") +) diff --git a/vendor/github.com/containers/buildah/pkg/cli/common.go b/vendor/github.com/containers/buildah/pkg/cli/common.go index 6c4d14303..7fa0a7777 100644 --- a/vendor/github.com/containers/buildah/pkg/cli/common.go +++ b/vendor/github.com/containers/buildah/pkg/cli/common.go @@ -89,6 +89,7 @@ type FromAndBudResults struct { DNSSearch []string DNSServers []string DNSOptions []string + HttpProxy bool Isolation string Memory string MemorySwap string @@ -182,6 +183,7 @@ func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults, fs.StringSliceVar(&flags.DNSSearch, "dns-search", []string{}, "Set custom DNS search domains") fs.StringSliceVar(&flags.DNSServers, "dns", []string{}, "Set custom DNS servers") fs.StringSliceVar(&flags.DNSOptions, "dns-option", []string{}, "Set custom DNS options") + fs.BoolVar(&flags.HttpProxy, "http-proxy", true, "pass thru HTTP Proxy environment variables") fs.StringVar(&flags.Isolation, "isolation", DefaultIsolation(), "`type` of process isolation to use. Use BUILDAH_ISOLATION environment variable to override.") fs.StringVarP(&flags.Memory, "memory", "m", "", "memory limit (format: <number>[<unit>], where unit = b, k, m or g)") fs.StringVar(&flags.MemorySwap, "memory-swap", "", "swap limit equal to memory plus swap: '-1' to enable unlimited swap") diff --git a/vendor/github.com/containers/buildah/pkg/parse/parse.go b/vendor/github.com/containers/buildah/pkg/parse/parse.go index c4e3e4264..cc85136fd 100644 --- a/vendor/github.com/containers/buildah/pkg/parse/parse.go +++ b/vendor/github.com/containers/buildah/pkg/parse/parse.go @@ -86,6 +86,7 @@ func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) { cpuPeriod, _ := c.Flags().GetUint64("cpu-period") cpuQuota, _ := c.Flags().GetInt64("cpu-quota") cpuShares, _ := c.Flags().GetUint64("cpu-shared") + httpProxy, _ := c.Flags().GetBool("http-proxy") ulimit, _ := c.Flags().GetStringSlice("ulimit") commonOpts := &buildah.CommonBuildOptions{ AddHost: addHost, @@ -98,6 +99,7 @@ func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) { DNSSearch: dnsSearch, DNSServers: dnsServers, DNSOptions: dnsOptions, + HTTPProxy: httpProxy, Memory: memoryLimit, MemorySwap: memorySwap, ShmSize: c.Flag("shm-size").Value.String(), diff --git a/vendor/github.com/containers/buildah/pkg/unshare/unshare.go b/vendor/github.com/containers/buildah/pkg/unshare/unshare.go index 5b2e7d7d1..33232740e 100644 --- a/vendor/github.com/containers/buildah/pkg/unshare/unshare.go +++ b/vendor/github.com/containers/buildah/pkg/unshare/unshare.go @@ -3,6 +3,7 @@ package unshare import ( + "bufio" "bytes" "fmt" "io" @@ -15,7 +16,7 @@ import ( "sync" "syscall" - "github.com/containers/buildah/util" + "github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/reexec" "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -157,7 +158,7 @@ func (c *Cmd) Start() error { } if len(c.UidMappings) == 0 || len(c.GidMappings) == 0 { - uidmap, gidmap, err := util.GetHostIDMappings("") + uidmap, gidmap, err := GetHostIDMappings("") if err != nil { fmt.Fprintf(continueWrite, "error reading ID mappings in parent: %v", err) return errors.Wrapf(err, "error reading ID mappings in parent") @@ -352,7 +353,7 @@ func MaybeReexecUsingUserNamespace(evenForRoot bool) { // Read the set of ID mappings that we're allowed to use. Each // range in /etc/subuid and /etc/subgid file is a starting host // ID and a range size. - uidmap, gidmap, err = util.GetSubIDMappings(me.Username, me.Username) + uidmap, gidmap, err = GetSubIDMappings(me.Username, me.Username) bailOnError(err, "error reading allowed ID mappings") if len(uidmap) == 0 { logrus.Warnf("Found no UID ranges set aside for user %q in /etc/subuid.", me.Username) @@ -384,7 +385,7 @@ func MaybeReexecUsingUserNamespace(evenForRoot bool) { return } // Read the set of ID mappings that we're currently using. - uidmap, gidmap, err = util.GetHostIDMappings("") + uidmap, gidmap, err = GetHostIDMappings("") bailOnError(err, "error reading current ID mappings") // Just reuse them. for i := range uidmap { @@ -404,6 +405,16 @@ func MaybeReexecUsingUserNamespace(evenForRoot bool) { err = os.Setenv(UsernsEnvName, "1") bailOnError(err, "error setting %s=1 in environment", UsernsEnvName) + // Set the default isolation type to use the "rootless" method. + if _, present := os.LookupEnv("BUILDAH_ISOLATION"); !present { + if err = os.Setenv("BUILDAH_ISOLATION", "rootless"); err != nil { + if err := os.Setenv("BUILDAH_ISOLATION", "rootless"); err != nil { + logrus.Errorf("error setting BUILDAH_ISOLATION=rootless in environment: %v", err) + os.Exit(1) + } + } + } + // Reuse our stdio. cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout @@ -446,3 +457,89 @@ func ExecRunnable(cmd Runnable) { } os.Exit(0) } + +// getHostIDMappings reads mappings from the named node under /proc. +func getHostIDMappings(path string) ([]specs.LinuxIDMapping, error) { + var mappings []specs.LinuxIDMapping + f, err := os.Open(path) + if err != nil { + return nil, errors.Wrapf(err, "error reading ID mappings from %q", path) + } + defer f.Close() + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + fields := strings.Fields(line) + if len(fields) != 3 { + return nil, errors.Errorf("line %q from %q has %d fields, not 3", line, path, len(fields)) + } + cid, err := strconv.ParseUint(fields[0], 10, 32) + if err != nil { + return nil, errors.Wrapf(err, "error parsing container ID value %q from line %q in %q", fields[0], line, path) + } + hid, err := strconv.ParseUint(fields[1], 10, 32) + if err != nil { + return nil, errors.Wrapf(err, "error parsing host ID value %q from line %q in %q", fields[1], line, path) + } + size, err := strconv.ParseUint(fields[2], 10, 32) + if err != nil { + return nil, errors.Wrapf(err, "error parsing size value %q from line %q in %q", fields[2], line, path) + } + mappings = append(mappings, specs.LinuxIDMapping{ContainerID: uint32(cid), HostID: uint32(hid), Size: uint32(size)}) + } + return mappings, nil +} + +// GetHostIDMappings reads mappings for the specified process (or the current +// process if pid is "self" or an empty string) from the kernel. +func GetHostIDMappings(pid string) ([]specs.LinuxIDMapping, []specs.LinuxIDMapping, error) { + if pid == "" { + pid = "self" + } + uidmap, err := getHostIDMappings(fmt.Sprintf("/proc/%s/uid_map", pid)) + if err != nil { + return nil, nil, err + } + gidmap, err := getHostIDMappings(fmt.Sprintf("/proc/%s/gid_map", pid)) + if err != nil { + return nil, nil, err + } + return uidmap, gidmap, nil +} + +// GetSubIDMappings reads mappings from /etc/subuid and /etc/subgid. +func GetSubIDMappings(user, group string) ([]specs.LinuxIDMapping, []specs.LinuxIDMapping, error) { + mappings, err := idtools.NewIDMappings(user, group) + if err != nil { + return nil, nil, errors.Wrapf(err, "error reading subuid mappings for user %q and subgid mappings for group %q", user, group) + } + var uidmap, gidmap []specs.LinuxIDMapping + for _, m := range mappings.UIDs() { + uidmap = append(uidmap, specs.LinuxIDMapping{ + ContainerID: uint32(m.ContainerID), + HostID: uint32(m.HostID), + Size: uint32(m.Size), + }) + } + for _, m := range mappings.GIDs() { + gidmap = append(gidmap, specs.LinuxIDMapping{ + ContainerID: uint32(m.ContainerID), + HostID: uint32(m.HostID), + Size: uint32(m.Size), + }) + } + return uidmap, gidmap, nil +} + +// ParseIDMappings parses mapping triples. +func ParseIDMappings(uidmap, gidmap []string) ([]idtools.IDMap, []idtools.IDMap, error) { + uid, err := idtools.ParseIDMap(uidmap, "userns-uid-map") + if err != nil { + return nil, nil, err + } + gid, err := idtools.ParseIDMap(gidmap, "userns-gid-map") + if err != nil { + return nil, nil, err + } + return uid, gid, nil +} diff --git a/vendor/github.com/containers/buildah/pkg/unshare/unshare_unsupported.go b/vendor/github.com/containers/buildah/pkg/unshare/unshare_unsupported.go index d8d5f6f7a..bf4d567b8 100644 --- a/vendor/github.com/containers/buildah/pkg/unshare/unshare_unsupported.go +++ b/vendor/github.com/containers/buildah/pkg/unshare/unshare_unsupported.go @@ -4,6 +4,9 @@ package unshare import ( "os" + + "github.com/containers/storage/pkg/idtools" + "github.com/opencontainers/runtime-spec/specs-go" ) const ( @@ -29,3 +32,14 @@ func RootlessEnv() []string { // MaybeReexecUsingUserNamespace re-exec the process in a new namespace func MaybeReexecUsingUserNamespace(evenForRoot bool) { } + +// GetHostIDMappings reads mappings for the specified process (or the current +// process if pid is "self" or an empty string) from the kernel. +func GetHostIDMappings(pid string) ([]specs.LinuxIDMapping, []specs.LinuxIDMapping, error) { + return nil, nil, nil +} + +// ParseIDMappings parses mapping triples. +func ParseIDMappings(uidmap, gidmap []string) ([]idtools.IDMap, []idtools.IDMap, error) { + return nil, nil, nil +} diff --git a/vendor/github.com/containers/buildah/run.go b/vendor/github.com/containers/buildah/run.go index 5d28644d7..00eac8e39 100644 --- a/vendor/github.com/containers/buildah/run.go +++ b/vendor/github.com/containers/buildah/run.go @@ -865,7 +865,7 @@ func setupNamespaces(g *generate.Generator, namespaceOptions NamespaceOptions, i if err := g.AddOrReplaceLinuxNamespace(specs.UserNamespace, ""); err != nil { return false, nil, false, errors.Wrapf(err, "error adding new %q namespace for run", string(specs.UserNamespace)) } - hostUidmap, hostGidmap, err := util.GetHostIDMappings("") + hostUidmap, hostGidmap, err := unshare.GetHostIDMappings("") if err != nil { return false, nil, false, err } @@ -983,6 +983,24 @@ func (b *Builder) configureUIDGID(g *generate.Generator, mountPoint string, opti func (b *Builder) configureEnvironment(g *generate.Generator, options RunOptions) { g.ClearProcessEnv() + if b.CommonBuildOpts.HTTPProxy { + for _, envSpec := range []string{ + "http_proxy", + "HTTP_PROXY", + "https_proxy", + "HTTPS_PROXY", + "ftp_proxy", + "FTP_PROXY", + "no_proxy", + "NO_PROXY", + } { + envVal := os.Getenv(envSpec) + if envVal != "" { + g.AddProcessEnv(envSpec, envVal) + } + } + } + for _, envSpec := range append(b.Env(), options.Env...) { env := strings.SplitN(envSpec, "=", 2) if len(env) > 1 { diff --git a/vendor/github.com/containers/buildah/selinux.go b/vendor/github.com/containers/buildah/selinux.go index 2b850cf9f..e64eb6112 100644 --- a/vendor/github.com/containers/buildah/selinux.go +++ b/vendor/github.com/containers/buildah/selinux.go @@ -4,9 +4,12 @@ package buildah import ( "github.com/opencontainers/runtime-tools/generate" + selinux "github.com/opencontainers/selinux/go-selinux" ) func setupSelinux(g *generate.Generator, processLabel, mountLabel string) { - g.SetProcessSelinuxLabel(processLabel) - g.SetLinuxMountLabel(mountLabel) + if processLabel != "" && selinux.GetEnabled() { + g.SetProcessSelinuxLabel(processLabel) + g.SetLinuxMountLabel(mountLabel) + } } diff --git a/vendor/github.com/containers/buildah/util/util.go b/vendor/github.com/containers/buildah/util/util.go index 7f3bbaef4..698d79a81 100644 --- a/vendor/github.com/containers/buildah/util/util.go +++ b/vendor/github.com/containers/buildah/util/util.go @@ -1,13 +1,11 @@ package util import ( - "bufio" "fmt" "io" "net/url" "os" "path" - "strconv" "strings" "syscall" @@ -18,7 +16,6 @@ import ( "github.com/containers/image/transports" "github.com/containers/image/types" "github.com/containers/storage" - "github.com/containers/storage/pkg/idtools" "github.com/docker/distribution/registry/api/errcode" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -299,92 +296,6 @@ func GetHostRootIDs(spec *specs.Spec) (uint32, uint32, error) { return GetHostIDs(spec.Linux.UIDMappings, spec.Linux.GIDMappings, 0, 0) } -// getHostIDMappings reads mappings from the named node under /proc. -func getHostIDMappings(path string) ([]specs.LinuxIDMapping, error) { - var mappings []specs.LinuxIDMapping - f, err := os.Open(path) - if err != nil { - return nil, errors.Wrapf(err, "error reading ID mappings from %q", path) - } - defer f.Close() - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := scanner.Text() - fields := strings.Fields(line) - if len(fields) != 3 { - return nil, errors.Errorf("line %q from %q has %d fields, not 3", line, path, len(fields)) - } - cid, err := strconv.ParseUint(fields[0], 10, 32) - if err != nil { - return nil, errors.Wrapf(err, "error parsing container ID value %q from line %q in %q", fields[0], line, path) - } - hid, err := strconv.ParseUint(fields[1], 10, 32) - if err != nil { - return nil, errors.Wrapf(err, "error parsing host ID value %q from line %q in %q", fields[1], line, path) - } - size, err := strconv.ParseUint(fields[2], 10, 32) - if err != nil { - return nil, errors.Wrapf(err, "error parsing size value %q from line %q in %q", fields[2], line, path) - } - mappings = append(mappings, specs.LinuxIDMapping{ContainerID: uint32(cid), HostID: uint32(hid), Size: uint32(size)}) - } - return mappings, nil -} - -// GetHostIDMappings reads mappings for the specified process (or the current -// process if pid is "self" or an empty string) from the kernel. -func GetHostIDMappings(pid string) ([]specs.LinuxIDMapping, []specs.LinuxIDMapping, error) { - if pid == "" { - pid = "self" - } - uidmap, err := getHostIDMappings(fmt.Sprintf("/proc/%s/uid_map", pid)) - if err != nil { - return nil, nil, err - } - gidmap, err := getHostIDMappings(fmt.Sprintf("/proc/%s/gid_map", pid)) - if err != nil { - return nil, nil, err - } - return uidmap, gidmap, nil -} - -// GetSubIDMappings reads mappings from /etc/subuid and /etc/subgid. -func GetSubIDMappings(user, group string) ([]specs.LinuxIDMapping, []specs.LinuxIDMapping, error) { - mappings, err := idtools.NewIDMappings(user, group) - if err != nil { - return nil, nil, errors.Wrapf(err, "error reading subuid mappings for user %q and subgid mappings for group %q", user, group) - } - var uidmap, gidmap []specs.LinuxIDMapping - for _, m := range mappings.UIDs() { - uidmap = append(uidmap, specs.LinuxIDMapping{ - ContainerID: uint32(m.ContainerID), - HostID: uint32(m.HostID), - Size: uint32(m.Size), - }) - } - for _, m := range mappings.GIDs() { - gidmap = append(gidmap, specs.LinuxIDMapping{ - ContainerID: uint32(m.ContainerID), - HostID: uint32(m.HostID), - Size: uint32(m.Size), - }) - } - return uidmap, gidmap, nil -} - -// ParseIDMappings parses mapping triples. -func ParseIDMappings(uidmap, gidmap []string) ([]idtools.IDMap, []idtools.IDMap, error) { - uid, err := idtools.ParseIDMap(uidmap, "userns-uid-map") - if err != nil { - return nil, nil, err - } - gid, err := idtools.ParseIDMap(gidmap, "userns-gid-map") - if err != nil { - return nil, nil, err - } - return uid, gid, nil -} - // GetPolicyContext sets up, initializes and returns a new context for the specified policy func GetPolicyContext(ctx *types.SystemContext) (*signature.PolicyContext, error) { policy, err := signature.DefaultPolicy(ctx) diff --git a/vendor/github.com/containers/buildah/vendor.conf b/vendor/github.com/containers/buildah/vendor.conf index a77130acb..bec681e5c 100644 --- a/vendor/github.com/containers/buildah/vendor.conf +++ b/vendor/github.com/containers/buildah/vendor.conf @@ -8,7 +8,7 @@ github.com/vbauerster/mpb v3.3.4 github.com/mattn/go-isatty v0.0.4 github.com/VividCortex/ewma v1.1.1 github.com/boltdb/bolt v1.3.1 -github.com/containers/storage v1.12.2 +github.com/containers/storage v1.12.3 github.com/docker/distribution 5f6282db7d65e6d72ad7c2cc66310724a57be716 github.com/docker/docker 54dddadc7d5d89fe0be88f76979f6f6ab0dede83 github.com/docker/docker-credential-helpers v0.6.1 diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go index 69036a5c1..5d667d8c6 100644 --- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go +++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go @@ -16,7 +16,7 @@ import ( "sync" "syscall" - "github.com/containers/storage/drivers" + graphdriver "github.com/containers/storage/drivers" "github.com/containers/storage/drivers/overlayutils" "github.com/containers/storage/drivers/quota" "github.com/containers/storage/pkg/archive" @@ -320,6 +320,8 @@ func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGI mergedDir := filepath.Join(layerDir, "merged") lower1Dir := filepath.Join(layerDir, "lower1") lower2Dir := filepath.Join(layerDir, "lower2") + upperDir := filepath.Join(layerDir, "upper") + workDir := filepath.Join(layerDir, "work") defer func() { // Permitted to fail, since the various subdirectories // can be empty or not even there, and the home might @@ -331,7 +333,9 @@ func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGI _ = idtools.MkdirAs(mergedDir, 0700, rootUID, rootGID) _ = idtools.MkdirAs(lower1Dir, 0700, rootUID, rootGID) _ = idtools.MkdirAs(lower2Dir, 0700, rootUID, rootGID) - flags := fmt.Sprintf("lowerdir=%s:%s", lower1Dir, lower2Dir) + _ = idtools.MkdirAs(upperDir, 0700, rootUID, rootGID) + _ = idtools.MkdirAs(workDir, 0700, rootUID, rootGID) + flags := fmt.Sprintf("lowerdir=%s:%s,upperdir=%s,workdir=%s", lower1Dir, lower2Dir, upperDir, workDir) if len(flags) < unix.Getpagesize() { err := mountFrom(filepath.Dir(home), "overlay", mergedDir, "overlay", 0, flags) if err == nil { @@ -341,7 +345,7 @@ func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGI logrus.Debugf("overlay test mount with multiple lowers failed %v", err) } } - flags = fmt.Sprintf("lowerdir=%s", lower1Dir) + flags = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lower1Dir, upperDir, workDir) if len(flags) < unix.Getpagesize() { err := mountFrom(filepath.Dir(home), "overlay", mergedDir, "overlay", 0, flags) if err == nil { @@ -677,6 +681,40 @@ func (d *Driver) Remove(id string) error { return nil } +// recreateSymlinks goes through the driver's home directory and checks if the diff directory +// under each layer has a symlink created for it under the linkDir. If the symlink does not +// exist, it creates them +func (d *Driver) recreateSymlinks() error { + // List all the directories under the home directory + dirs, err := ioutil.ReadDir(d.home) + if err != nil { + return fmt.Errorf("error reading driver home directory %q: %v", d.home, err) + } + for _, dir := range dirs { + // Skip over the linkDir + if dir.Name() == linkDir || dir.Mode().IsRegular() { + continue + } + // Read the "link" file under each layer to get the name of the symlink + data, err := ioutil.ReadFile(path.Join(d.dir(dir.Name()), "link")) + if err != nil { + return fmt.Errorf("error reading name of symlink for %q: %v", dir, err) + } + linkPath := path.Join(d.home, linkDir, strings.Trim(string(data), "\n")) + // Check if the symlink exists, and if it doesn't create it again with the name we + // got from the "link" file + _, err = os.Stat(linkPath) + if err != nil && os.IsNotExist(err) { + if err := os.Symlink(path.Join("..", dir.Name(), "diff"), linkPath); err != nil { + return err + } + } else if err != nil { + return fmt.Errorf("error trying to stat %q: %v", linkPath, err) + } + } + return nil +} + // Get creates and mounts the required file system for the given id and returns the mount path. func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr error) { return d.get(id, false, options) @@ -732,7 +770,16 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO } lower = "" } - if lower == "" { + // if it is a "not found" error, that means the symlinks were lost in a sudden reboot + // so call the recreateSymlinks function to go through all the layer dirs and recreate + // the symlinks with the name from their respective "link" files + if lower == "" && os.IsNotExist(err) { + logrus.Warnf("Can't stat lower layer %q because it does not exist. Going through storage to recreate the missing symlinks.", newpath) + if err := d.recreateSymlinks(); err != nil { + return "", fmt.Errorf("error recreating the missing symlinks: %v", err) + } + lower = newpath + } else if lower == "" { return "", fmt.Errorf("Can't stat lower layer %q: %v", newpath, err) } } else { |