diff options
author | Matthew Heon <matthew.heon@gmail.com> | 2018-10-16 13:25:27 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-16 13:25:27 -0400 |
commit | 81e63ac309e8bde6603faf07a98a7963e9397188 (patch) | |
tree | e2b174bc848a57bc9107e84657be3ad0e54346d0 | |
parent | 2bc9a3c4bbaade50264b1dbf348d1521cdd8d8b5 (diff) | |
parent | 6dd6ce1ebcdb17023f09fad93698d09408227385 (diff) | |
download | podman-81e63ac309e8bde6603faf07a98a7963e9397188.tar.gz podman-81e63ac309e8bde6603faf07a98a7963e9397188.tar.bz2 podman-81e63ac309e8bde6603faf07a98a7963e9397188.zip |
Merge pull request #1609 from giuseppe/fix-volume-rootless
volume: resolve symlink paths in volumes
21 files changed, 301 insertions, 158 deletions
diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 447aa1d8b..40159194f 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -13,6 +13,7 @@ import ( "strings" "syscall" + "github.com/containers/buildah/imagebuildah" "github.com/containers/libpod/pkg/chrootuser" "github.com/containers/libpod/pkg/hooks" "github.com/containers/libpod/pkg/hooks/exec" @@ -1193,8 +1194,6 @@ func (c *Container) addLocalVolumes(ctx context.Context, g *generate.Generator) continue } volumePath := filepath.Join(c.config.StaticDir, "volumes", k) - srcPath := filepath.Join(mountPoint, k) - var ( uid uint32 gid uint32 @@ -1209,31 +1208,43 @@ func (c *Container) addLocalVolumes(ctx context.Context, g *generate.Generator) } } + // Ensure the symlinks are resolved + resolvedSymlink, err := imagebuildah.ResolveSymLink(mountPoint, k) + if err != nil { + return errors.Wrapf(ErrCtrStateInvalid, "cannot resolve %s in %s for container %s", k, mountPoint, c.ID()) + } + var srcPath string + if resolvedSymlink != "" { + srcPath = filepath.Join(mountPoint, resolvedSymlink) + } else { + srcPath = filepath.Join(mountPoint, k) + } + if _, err := os.Stat(srcPath); os.IsNotExist(err) { logrus.Infof("Volume image mount point %s does not exist in root FS, need to create it", k) if err = os.MkdirAll(srcPath, 0755); err != nil { - return errors.Wrapf(err, "error creating directory %q for volume %q in container %q", volumePath, k, c.ID) + return errors.Wrapf(err, "error creating directory %q for volume %q in container %q", volumePath, k, c.ID()) } if err = os.Chown(srcPath, int(uid), int(gid)); err != nil { - return errors.Wrapf(err, "error chowning directory %q for volume %q in container %q", srcPath, k, c.ID) + return errors.Wrapf(err, "error chowning directory %q for volume %q in container %q", srcPath, k, c.ID()) } } if _, err := os.Stat(volumePath); os.IsNotExist(err) { if err = os.MkdirAll(volumePath, 0755); err != nil { - return errors.Wrapf(err, "error creating directory %q for volume %q in container %q", volumePath, k, c.ID) + return errors.Wrapf(err, "error creating directory %q for volume %q in container %q", volumePath, k, c.ID()) } if err = os.Chown(volumePath, int(uid), int(gid)); err != nil { - return errors.Wrapf(err, "error chowning directory %q for volume %q in container %q", volumePath, k, c.ID) + return errors.Wrapf(err, "error chowning directory %q for volume %q in container %q", volumePath, k, c.ID()) } if err = label.Relabel(volumePath, c.config.MountLabel, false); err != nil { - return errors.Wrapf(err, "error relabeling directory %q for volume %q in container %q", volumePath, k, c.ID) + return errors.Wrapf(err, "error relabeling directory %q for volume %q in container %q", volumePath, k, c.ID()) } if err = chrootarchive.NewArchiver(nil).CopyWithTar(srcPath, volumePath); err != nil && !os.IsNotExist(err) { - return errors.Wrapf(err, "error populating directory %q for volume %q in container %q using contents of %q", volumePath, k, c.ID, srcPath) + return errors.Wrapf(err, "error populating directory %q for volume %q in container %q using contents of %q", volumePath, k, c.ID(), srcPath) } // Set the volume path with the same owner and permission of source path diff --git a/vendor.conf b/vendor.conf index be89c418e..a74953e37 100644 --- a/vendor.conf +++ b/vendor.conf @@ -91,7 +91,7 @@ k8s.io/kube-openapi 275e2ce91dec4c05a4094a7b1daee5560b555ac9 https://github.com/ k8s.io/utils 258e2a2fa64568210fbd6267cf1d8fd87c3cb86e https://github.com/kubernetes/utils github.com/mrunalp/fileutils master github.com/varlink/go master -github.com/containers/buildah af8cb28f84d81ee1bca04c893142cd790b908c75 +github.com/containers/buildah 9d50d04b9324a22bbb64df9e66b5d9d53ed3daae github.com/Nvveen/Gotty master github.com/fsouza/go-dockerclient master github.com/openshift/imagebuilder master diff --git a/vendor/github.com/containers/buildah/add.go b/vendor/github.com/containers/buildah/add.go index b1747db94..6542b0377 100644 --- a/vendor/github.com/containers/buildah/add.go +++ b/vendor/github.com/containers/buildah/add.go @@ -49,7 +49,7 @@ func addURL(destination, srcurl string, owner idtools.IDPair, hasher io.Writer) return errors.Wrapf(err, "error creating %q", destination) } if err = f.Chown(owner.UID, owner.GID); err != nil { - return errors.Wrapf(err, "error setting owner of %q", destination) + return errors.Wrapf(err, "error setting owner of %q to %d:%d", destination, owner.UID, owner.GID) } if last := resp.Header.Get("Last-Modified"); last != "" { if mtime, err2 := time.Parse(time.RFC1123, last); err2 != nil { @@ -57,7 +57,7 @@ func addURL(destination, srcurl string, owner idtools.IDPair, hasher io.Writer) } else { defer func() { if err3 := os.Chtimes(destination, time.Now(), mtime); err3 != nil { - logrus.Debugf("error setting mtime to Last-Modified time %q: %v", last, err3) + logrus.Debugf("error setting mtime on %q to Last-Modified time %q: %v", destination, last, err3) } }() } @@ -69,10 +69,10 @@ func addURL(destination, srcurl string, owner idtools.IDPair, hasher io.Writer) } n, err := io.Copy(f, bodyReader) if err != nil { - return errors.Wrapf(err, "error reading contents for %q", destination) + return errors.Wrapf(err, "error reading contents for %q from %q", destination, srcurl) } if resp.ContentLength >= 0 && n != resp.ContentLength { - return errors.Errorf("error reading contents for %q: wrong length (%d != %d)", destination, n, resp.ContentLength) + return errors.Errorf("error reading contents for %q from %q: wrong length (%d != %d)", destination, srcurl, n, resp.ContentLength) } if err := f.Chmod(0600); err != nil { return errors.Wrapf(err, "error setting permissions on %q", destination) @@ -109,7 +109,7 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption dest = filepath.Join(dest, destination) } else { if err = idtools.MkdirAllAndChownNew(filepath.Join(dest, b.WorkDir()), 0755, hostOwner); err != nil { - return err + return errors.Wrapf(err, "error creating directory %q", filepath.Join(dest, b.WorkDir())) } dest = filepath.Join(dest, b.WorkDir(), destination) } @@ -118,7 +118,7 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption // and any files we're copying will be placed in the directory. if len(destination) > 0 && destination[len(destination)-1] == os.PathSeparator { if err = idtools.MkdirAllAndChownNew(dest, 0755, hostOwner); err != nil { - return err + return errors.Wrapf(err, "error creating directory %q", dest) } } // Make sure the destination's parent directory is usable. @@ -154,7 +154,7 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption if destfi != nil && destfi.IsDir() { d = filepath.Join(dest, path.Base(url.Path)) } - if err := addURL(d, src, hostOwner, options.Hasher); err != nil { + if err = addURL(d, src, hostOwner, options.Hasher); err != nil { return err } continue @@ -182,10 +182,10 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption // to create it first, so that if there's a problem, // we'll discover why that won't work. if err = idtools.MkdirAllAndChownNew(dest, 0755, hostOwner); err != nil { - return err + return errors.Wrapf(err, "error creating directory %q", dest) } logrus.Debugf("copying %q to %q", esrc+string(os.PathSeparator)+"*", dest+string(os.PathSeparator)+"*") - if err := copyWithTar(esrc, dest); err != nil { + if err = copyWithTar(esrc, dest); err != nil { return errors.Wrapf(err, "error copying %q to %q", esrc, dest) } continue @@ -200,14 +200,14 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption } // Copy the file, preserving attributes. logrus.Debugf("copying %q to %q", esrc, d) - if err := copyFileWithTar(esrc, d); err != nil { + if err = copyFileWithTar(esrc, d); err != nil { return errors.Wrapf(err, "error copying %q to %q", esrc, d) } continue } // We're extracting an archive into the destination directory. logrus.Debugf("extracting contents of %q into %q", esrc, dest) - if err := untarPath(esrc, dest); err != nil { + if err = untarPath(esrc, dest); err != nil { return errors.Wrapf(err, "error extracting %q into %q", esrc, dest) } } diff --git a/vendor/github.com/containers/buildah/buildah.go b/vendor/github.com/containers/buildah/buildah.go index 79704d7b1..f94c5cc08 100644 --- a/vendor/github.com/containers/buildah/buildah.go +++ b/vendor/github.com/containers/buildah/buildah.go @@ -16,6 +16,7 @@ import ( "github.com/containers/storage/pkg/ioutils" "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) const ( @@ -421,15 +422,14 @@ func OpenBuilder(store storage.Store, container string) (*Builder, error) { } buildstate, err := ioutil.ReadFile(filepath.Join(cdir, stateFile)) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "error reading %q", filepath.Join(cdir, stateFile)) } b := &Builder{} - err = json.Unmarshal(buildstate, &b) - if err != nil { - return nil, err + if err = json.Unmarshal(buildstate, &b); err != nil { + return nil, errors.Wrapf(err, "error parsing %q, read from %q", string(buildstate), filepath.Join(cdir, stateFile)) } if b.Type != containerType { - return nil, errors.Errorf("container is not a %s container", Package) + return nil, errors.Errorf("container %q is not a %s container (is a %q container)", container, Package, b.Type) } b.store = store b.fixupConfig() @@ -445,7 +445,7 @@ func OpenBuilderByPath(store storage.Store, path string) (*Builder, error) { } abs, err := filepath.Abs(path) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "error turning %q into an absolute path", path) } builderMatchesPath := func(b *Builder, path string) bool { return (b.MountPoint == path) @@ -457,7 +457,7 @@ func OpenBuilderByPath(store storage.Store, path string) (*Builder, error) { } buildstate, err := ioutil.ReadFile(filepath.Join(cdir, stateFile)) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "error reading %q", filepath.Join(cdir, stateFile)) } b := &Builder{} err = json.Unmarshal(buildstate, &b) @@ -466,6 +466,11 @@ func OpenBuilderByPath(store storage.Store, path string) (*Builder, error) { b.fixupConfig() return b, nil } + if err != nil { + logrus.Debugf("error parsing %q, read from %q: %v", string(buildstate), filepath.Join(cdir, stateFile), err) + } else if b.Type != containerType { + logrus.Debugf("container %q is not a %s container (is a %q container)", container.ID, Package, b.Type) + } } return nil, storage.ErrContainerUnknown } @@ -484,6 +489,7 @@ func OpenAllBuilders(store storage.Store) (builders []*Builder, err error) { } buildstate, err := ioutil.ReadFile(filepath.Join(cdir, stateFile)) if err != nil && os.IsNotExist(err) { + logrus.Debugf("error reading %q: %v", filepath.Join(cdir, stateFile), err) continue } b := &Builder{} @@ -492,6 +498,12 @@ func OpenAllBuilders(store storage.Store) (builders []*Builder, err error) { b.store = store b.fixupConfig() builders = append(builders, b) + continue + } + if err != nil { + logrus.Debugf("error parsing %q, read from %q: %v", string(buildstate), filepath.Join(cdir, stateFile), err) + } else if b.Type != containerType { + logrus.Debugf("container %q is not a %s container (is a %q container)", container.ID, Package, b.Type) } } return builders, nil @@ -509,5 +521,8 @@ func (b *Builder) Save() error { if err != nil { return err } - return ioutils.AtomicWriteFile(filepath.Join(cdir, stateFile), buildstate, 0600) + if err = ioutils.AtomicWriteFile(filepath.Join(cdir, stateFile), buildstate, 0600); err != nil { + return errors.Wrapf(err, "error saving builder state to %q", filepath.Join(cdir, stateFile)) + } + return nil } diff --git a/vendor/github.com/containers/buildah/commit.go b/vendor/github.com/containers/buildah/commit.go index c07a5881b..28dc4ec7c 100644 --- a/vendor/github.com/containers/buildah/commit.go +++ b/vendor/github.com/containers/buildah/commit.go @@ -120,18 +120,18 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options if transport, destIsStorage := dest.Transport().(is.StoreTransport); destIsStorage && b.FromImageID != "" { if baseref, err := transport.ParseReference(b.FromImageID); baseref != nil && err == nil { if img, err := transport.GetImage(baseref); img != nil && err == nil { + logrus.Debugf("base image %q is already present in local storage, no need to copy its layers", b.FromImageID) exportBaseLayers = false } } } src, err := b.makeImageRef(options.PreferredManifestType, options.Parent, exportBaseLayers, options.Squash, options.Compression, options.HistoryTimestamp) if err != nil { - return imgID, errors.Wrapf(err, "error computing layer digests and building metadata") + return imgID, errors.Wrapf(err, "error computing layer digests and building metadata for container %q", b.ContainerID) } // "Copy" our image to where it needs to be. - err = cp.Image(ctx, policyContext, dest, src, getCopyOptions(options.ReportWriter, src, nil, dest, systemContext, "")) - if err != nil { - return imgID, errors.Wrapf(err, "error copying layers and metadata") + if err = cp.Image(ctx, policyContext, dest, src, getCopyOptions(options.ReportWriter, src, nil, dest, systemContext, "")); err != nil { + return imgID, errors.Wrapf(err, "error copying layers and metadata for container %q", b.ContainerID) } if len(options.AdditionalTags) > 0 { switch dest.Transport().Name() { @@ -140,8 +140,7 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options if err != nil { return imgID, errors.Wrapf(err, "error locating just-written image %q", transports.ImageName(dest)) } - err = util.AddImageNames(b.store, "", systemContext, img, options.AdditionalTags) - if err != nil { + if err = util.AddImageNames(b.store, "", systemContext, img, options.AdditionalTags); err != nil { return imgID, errors.Wrapf(err, "error setting image names to %v", append(img.Names, options.AdditionalTags...)) } logrus.Debugf("assigned names %v to image %q", img.Names, img.ID) @@ -152,15 +151,15 @@ func (b *Builder) Commit(ctx context.Context, dest types.ImageReference, options img, err := is.Transport.GetStoreImage(b.store, dest) if err != nil && err != storage.ErrImageUnknown { - return imgID, err + return imgID, errors.Wrapf(err, "error locating image %q in local storage", transports.ImageName(dest)) } if err == nil { imgID = img.ID if options.IIDFile != "" { - if err := ioutil.WriteFile(options.IIDFile, []byte(img.ID), 0644); err != nil { - return imgID, errors.Wrapf(err, "failed to write Image ID File %q", options.IIDFile) + if err = ioutil.WriteFile(options.IIDFile, []byte(img.ID), 0644); err != nil { + return imgID, errors.Wrapf(err, "failed to write image ID to file %q", options.IIDFile) } } } @@ -194,9 +193,8 @@ func Push(ctx context.Context, image string, dest types.ImageReference, options return err } // Copy everything. - err = cp.Image(ctx, policyContext, dest, src, getCopyOptions(options.ReportWriter, src, nil, dest, systemContext, options.ManifestType)) - if err != nil { - return errors.Wrapf(err, "error copying layers and metadata") + if err = cp.Image(ctx, policyContext, dest, src, getCopyOptions(options.ReportWriter, src, nil, dest, systemContext, options.ManifestType)); err != nil { + return errors.Wrapf(err, "error copying layers and metadata from %q to %q", transports.ImageName(src), transports.ImageName(dest)) } if options.ReportWriter != nil { fmt.Fprintf(options.ReportWriter, "") diff --git a/vendor/github.com/containers/buildah/config.go b/vendor/github.com/containers/buildah/config.go index f6a742d59..89224b674 100644 --- a/vendor/github.com/containers/buildah/config.go +++ b/vendor/github.com/containers/buildah/config.go @@ -44,7 +44,7 @@ func unmarshalConvertedConfig(ctx context.Context, dest interface{}, img types.I return errors.Wrapf(err, "error reading %s config from %q", wantedManifestMIMEType, transports.ImageName(img.Reference())) } if err := json.Unmarshal(config, dest); err != nil { - return errors.Wrapf(err, "error parsing %s configuration from %q", wantedManifestMIMEType, transports.ImageName(img.Reference())) + return errors.Wrapf(err, "error parsing %s configuration %q from %q", wantedManifestMIMEType, string(config), transports.ImageName(img.Reference())) } return nil } @@ -78,7 +78,7 @@ func (b *Builder) initConfig(ctx context.Context, img types.Image) error { // Attempt to recover format-specific data from the manifest. v1Manifest := ociv1.Manifest{} if err := json.Unmarshal(b.Manifest, &v1Manifest); err != nil { - return errors.Wrapf(err, "error parsing OCI manifest") + return errors.Wrapf(err, "error parsing OCI manifest %q", string(b.Manifest)) } b.ImageAnnotations = v1Manifest.Annotations } @@ -220,7 +220,7 @@ func (b *Builder) ClearOnBuild() { // discarded when writing images using OCIv1 formats. func (b *Builder) SetOnBuild(onBuild string) { if onBuild != "" && b.Format != Dockerv2ImageManifest { - logrus.Errorf("ONBUILD is not supported for OCI Image formats, %s will be ignored. Must use `docker` format", onBuild) + logrus.Errorf("ONBUILD is not supported for OCI image format, %s will be ignored. Must use `docker` format", onBuild) } b.Docker.Config.OnBuild = append(b.Docker.Config.OnBuild, onBuild) } @@ -252,7 +252,7 @@ func (b *Builder) Shell() []string { // discarded when writing images using OCIv1 formats. func (b *Builder) SetShell(shell []string) { if len(shell) > 0 && b.Format != Dockerv2ImageManifest { - logrus.Errorf("SHELL is not supported for OCI Image format, %s will be ignored. Must use `docker` format", shell) + logrus.Errorf("SHELL is not supported for OCI image format, %s will be ignored. Must use `docker` format", shell) } b.Docker.Config.Shell = copyStringSlice(shell) @@ -475,7 +475,7 @@ func (b *Builder) Hostname() string { // discarded when writing images using OCIv1 formats. func (b *Builder) SetHostname(name string) { if name != "" && b.Format != Dockerv2ImageManifest { - logrus.Errorf("HOSTNAME is not supported for OCI Image format, hostname %s will be ignored. Must use `docker` format", name) + logrus.Errorf("HOSTNAME is not supported for OCI image format, hostname %s will be ignored. Must use `docker` format", name) } b.Docker.Config.Hostname = name } @@ -492,7 +492,7 @@ func (b *Builder) Domainname() string { // discarded when writing images using OCIv1 formats. func (b *Builder) SetDomainname(name string) { if name != "" && b.Format != Dockerv2ImageManifest { - logrus.Errorf("DOMAINNAME is not supported for OCI Image format, domainname %s will be ignored. Must use `docker` format", name) + logrus.Errorf("DOMAINNAME is not supported for OCI image format, domainname %s will be ignored. Must use `docker` format", name) } b.Docker.Config.Domainname = name } @@ -514,7 +514,7 @@ func (b *Builder) Comment() string { // discarded when writing images using OCIv1 formats. func (b *Builder) SetComment(comment string) { if comment != "" && b.Format != Dockerv2ImageManifest { - logrus.Errorf("COMMENT is not supported for OCI Image format, comment %s will be ignored. Must use `docker` format", comment) + logrus.Errorf("COMMENT is not supported for OCI image format, comment %s will be ignored. Must use `docker` format", comment) } b.Docker.Comment = comment } diff --git a/vendor/github.com/containers/buildah/delete.go b/vendor/github.com/containers/buildah/delete.go index 8de774ff9..25f76cf74 100644 --- a/vendor/github.com/containers/buildah/delete.go +++ b/vendor/github.com/containers/buildah/delete.go @@ -9,7 +9,7 @@ import ( // be used after this method is called. func (b *Builder) Delete() error { if err := b.store.DeleteContainer(b.ContainerID); err != nil { - return errors.Wrapf(err, "error deleting build container") + return errors.Wrapf(err, "error deleting build container %q", b.ContainerID) } b.MountPoint = "" b.Container = "" diff --git a/vendor/github.com/containers/buildah/image.go b/vendor/github.com/containers/buildah/image.go index fb2e87f93..31aff9eea 100644 --- a/vendor/github.com/containers/buildah/image.go +++ b/vendor/github.com/containers/buildah/image.go @@ -134,15 +134,14 @@ func (i *containerImageRef) computeLayerMIMEType(what string) (omediaType, dmedi func (i *containerImageRef) extractRootfs() (io.ReadCloser, error) { mountPoint, err := i.store.Mount(i.containerID, i.mountLabel) if err != nil { - return nil, errors.Wrapf(err, "error extracting container %q", i.containerID) + return nil, errors.Wrapf(err, "error mounting container %q", i.containerID) } rc, err := i.tarPath(mountPoint) if err != nil { - return nil, errors.Wrapf(err, "error extracting container %q", i.containerID) + return nil, errors.Wrapf(err, "error extracting rootfs from container %q", i.containerID) } return ioutils.NewReadCloserWrapper(rc, func() error { - err := rc.Close() - if err != nil { + if err = rc.Close(); err != nil { err = errors.Wrapf(err, "error closing tar archive of container %q", i.containerID) } if _, err2 := i.store.Unmount(i.containerID, false); err == nil { @@ -254,14 +253,14 @@ func (i *containerImageRef) NewImageSource(ctx context.Context, sc *types.System // Make a temporary directory to hold blobs. path, err := ioutil.TempDir(os.TempDir(), Package) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "error creating temporary directory to hold layer blobs") } logrus.Debugf("using %q to hold temporary data", path) defer func() { if src == nil { err2 := os.RemoveAll(path) if err2 != nil { - logrus.Errorf("error removing %q: %v", path, err) + logrus.Errorf("error removing layer blob directory %q: %v", path, err) } } }() @@ -370,9 +369,8 @@ func (i *containerImageRef) NewImageSource(ctx context.Context, sc *types.System } logrus.Debugf("%s size is %d bytes", what, size) // Rename the layer so that we can more easily find it by digest later. - err = os.Rename(filepath.Join(path, "layer"), filepath.Join(path, destHasher.Digest().String())) - if err != nil { - return nil, errors.Wrapf(err, "error storing %s to file", what) + if err = os.Rename(filepath.Join(path, "layer"), filepath.Join(path, destHasher.Digest().String())); err != nil { + return nil, errors.Wrapf(err, "error storing %s to file while renaming %q to %q", what, filepath.Join(path, "layer"), filepath.Join(path, destHasher.Digest().String())) } // Add a note in the manifest about the layer. The blobs are identified by their possibly- // compressed blob digests. @@ -426,7 +424,7 @@ func (i *containerImageRef) NewImageSource(ctx context.Context, sc *types.System // Encode the image configuration blob. oconfig, err := json.Marshal(&oimage) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "error encoding %#v as json", oimage) } logrus.Debugf("OCIv1 config = %s", oconfig) @@ -438,14 +436,14 @@ func (i *containerImageRef) NewImageSource(ctx context.Context, sc *types.System // Encode the manifest. omanifestbytes, err := json.Marshal(&omanifest) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "error encoding %#v as json", omanifest) } logrus.Debugf("OCIv1 manifest = %s", omanifestbytes) // Encode the image configuration blob. dconfig, err := json.Marshal(&dimage) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "error encoding %#v as json", dimage) } logrus.Debugf("Docker v2s2 config = %s", dconfig) @@ -457,7 +455,7 @@ func (i *containerImageRef) NewImageSource(ctx context.Context, sc *types.System // Encode the manifest. dmanifestbytes, err := json.Marshal(&dmanifest) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "error encoding %#v as json", dmanifest) } logrus.Debugf("Docker v2s2 manifest = %s", dmanifestbytes) @@ -527,9 +525,9 @@ func (i *containerImageRef) Transport() types.ImageTransport { func (i *containerImageSource) Close() error { err := os.RemoveAll(i.path) if err != nil { - logrus.Errorf("error removing %q: %v", i.path, err) + return errors.Wrapf(err, "error removing layer blob directory %q", i.path) } - return err + return nil } func (i *containerImageSource) Reference() types.ImageReference { @@ -567,7 +565,7 @@ func (i *containerImageSource) GetBlob(ctx context.Context, blob types.BlobInfo) layerFile, err := os.OpenFile(filepath.Join(i.path, blob.Digest.String()), os.O_RDONLY, 0600) if err != nil { logrus.Debugf("error reading layer %q: %v", blob.Digest.String(), err) - return nil, -1, err + return nil, -1, errors.Wrapf(err, "error opening file %q to buffer layer blob", filepath.Join(i.path, blob.Digest.String())) } size = -1 st, err := layerFile.Stat() @@ -578,8 +576,10 @@ func (i *containerImageSource) GetBlob(ctx context.Context, blob types.BlobInfo) } logrus.Debugf("reading layer %q", blob.Digest.String()) closer := func() error { - layerFile.Close() logrus.Debugf("finished reading layer %q", blob.Digest.String()) + if err := layerFile.Close(); err != nil { + return errors.Wrapf(err, "error closing layer %q after reading", blob.Digest.String()) + } return nil } return ioutils.NewReadCloserWrapper(layerFile, closer), size, nil @@ -601,11 +601,11 @@ func (b *Builder) makeImageRef(manifestType, parent string, exporting bool, squa } oconfig, err := json.Marshal(&b.OCIv1) if err != nil { - return nil, errors.Wrapf(err, "error encoding OCI-format image configuration") + return nil, errors.Wrapf(err, "error encoding OCI-format image configuration %#v", b.OCIv1) } dconfig, err := json.Marshal(&b.Docker) if err != nil { - return nil, errors.Wrapf(err, "error encoding docker-format image configuration") + return nil, errors.Wrapf(err, "error encoding docker-format image configuration %#v", b.Docker) } created := time.Now().UTC() if historyTimestamp != nil { diff --git a/vendor/github.com/containers/buildah/imagebuildah/build.go b/vendor/github.com/containers/buildah/imagebuildah/build.go index 727e41c38..3d644dfbd 100644 --- a/vendor/github.com/containers/buildah/imagebuildah/build.go +++ b/vendor/github.com/containers/buildah/imagebuildah/build.go @@ -219,7 +219,9 @@ type Executor struct { noCache bool removeIntermediateCtrs bool forceRmIntermediateCtrs bool - containerIDs []string // Stores the IDs of the successful intermediate containers used during layer build + containerIDs []string // Stores the IDs of the successful intermediate containers used during layer build + imageMap map[string]string // Used to map images that we create to handle the AS construct. + } // withName creates a new child executor that will be used whenever a COPY statement uses --from=NAME. @@ -276,7 +278,7 @@ func (b *Executor) Preserve(path string) error { // Try and resolve the symlink (if one exists) // Set archivedPath and path based on whether a symlink is found or not - if symLink, err := resolveSymLink(b.mountPoint, path); err == nil { + if symLink, err := ResolveSymLink(b.mountPoint, path); err == nil { archivedPath = filepath.Join(b.mountPoint, symLink) path = symLink } else { @@ -614,7 +616,10 @@ func NewExecutor(store storage.Store, options BuildOptions) (*Executor, error) { // Prepare creates a working container based on specified image, or if one // isn't specified, the first FROM instruction we can find in the parsed tree. -func (b *Executor) Prepare(ctx context.Context, ib *imagebuilder.Builder, node *parser.Node, from string) error { +func (b *Executor) Prepare(ctx context.Context, stage imagebuilder.Stage, from string) error { + ib := stage.Builder + node := stage.Node + if from == "" { base, err := ib.From(node) if err != nil { @@ -623,10 +628,22 @@ func (b *Executor) Prepare(ctx context.Context, ib *imagebuilder.Builder, node * } from = base } - logrus.Debugf("FROM %#v", from) + displayFrom := from + // stage.Name will be a string of integers for all stages without an "AS" clause + asImageName := stage.Name + if asImageName != "" { + if _, err := strconv.Atoi(asImageName); err != nil { + displayFrom = from + " AS " + asImageName + } else { + asImageName = "" + } + } + + logrus.Debugf("FROM %#v", displayFrom) if !b.quiet { - b.log("FROM %s", from) + b.log("FROM %s", displayFrom) } + builderOptions := buildah.BuilderOptions{ Args: ib.Args, FromImage: from, @@ -646,10 +663,19 @@ func (b *Executor) Prepare(ctx context.Context, ib *imagebuilder.Builder, node * DefaultMountsFilePath: b.defaultMountsFilePath, Format: b.outputFormat, } - builder, err := buildah.NewBuilder(ctx, b.store, builderOptions) + + var builder *buildah.Builder + var err error + // Check and see if the image was declared previously with + // an AS clause in the Dockerfile. + if asImageFound, ok := b.imageMap[from]; ok { + builderOptions.FromImage = asImageFound + } + builder, err = buildah.NewBuilder(ctx, b.store, builderOptions) if err != nil { return errors.Wrapf(err, "error creating build container") } + volumes := map[string]struct{}{} for _, v := range builder.Volumes() { volumes[v] = struct{}{} @@ -758,11 +784,14 @@ func (b *Executor) resolveNameToImageRef() (types.ImageReference, error) { } // Execute runs each of the steps in the parsed tree, in turn. -func (b *Executor) Execute(ctx context.Context, ib *imagebuilder.Builder, node *parser.Node) error { +func (b *Executor) Execute(ctx context.Context, stage imagebuilder.Stage) error { + ib := stage.Builder + node := stage.Node checkForLayers := true children := node.Children commitName := b.output b.containerIDs = nil + for i, node := range node.Children { step := ib.Step() if err := step.Resolve(node); err != nil { @@ -847,7 +876,7 @@ func (b *Executor) Execute(ctx context.Context, ib *imagebuilder.Builder, node * b.containerIDs = append(b.containerIDs, b.builder.ContainerID) // Prepare for the next step with imgID as the new base image. if i != len(children)-1 { - if err := b.Prepare(ctx, ib, node, imgID); err != nil { + if err := b.Prepare(ctx, stage, imgID); err != nil { return errors.Wrap(err, "error preparing container for next step") } } @@ -882,7 +911,7 @@ func (b *Executor) copyExistingImage(ctx context.Context, cacheID string) error } // layerExists returns true if an intermediate image of currNode exists in the image store from a previous build. -// It verifies tihis by checking the parent of the top layer of the image and the history. +// It verifies this by checking the parent of the top layer of the image and the history. func (b *Executor) layerExists(ctx context.Context, currNode *parser.Node, children []*parser.Node) (string, error) { // Get the list of images available in the image store images, err := b.store.Images() @@ -1156,9 +1185,11 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) error stageExecutor *Executor lastErr error ) + b.imageMap = make(map[string]string) + stageCount := 0 for _, stage := range stages { stageExecutor = b.withName(stage.Name, stage.Position) - if err := stageExecutor.Prepare(ctx, stage.Builder, stage.Node, ""); err != nil { + if err := stageExecutor.Prepare(ctx, stage, ""); err != nil { return err } // Always remove the intermediate/build containers, even if the build was unsuccessful. @@ -1167,7 +1198,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) error if b.forceRmIntermediateCtrs || (!b.layers && !b.noCache) { defer stageExecutor.Delete() } - if err := stageExecutor.Execute(ctx, stage.Builder, stage.Node); err != nil { + if err := stageExecutor.Execute(ctx, stage); err != nil { lastErr = err } @@ -1180,6 +1211,18 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) error return lastErr } b.containerIDs = append(b.containerIDs, stageExecutor.containerIDs...) + // If we've a stage.Name with alpha and not numeric, we've an + // AS clause in play. Create an intermediate image for this + // stage to be used by other FROM statements that will want + // to use it later in the Dockerfile. Note the id in our map. + if _, err := strconv.Atoi(stage.Name); err != nil { + imgID, err := stageExecutor.Commit(ctx, stages[stageCount].Builder, "") + if err != nil { + return err + } + b.imageMap[stage.Name] = imgID + } + stageCount++ } if !b.layers && !b.noCache { @@ -1201,6 +1244,12 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) error return errors.Errorf("Failed to cleanup intermediate containers") } } + // Remove intermediate images that we created for AS clause handling + for _, value := range b.imageMap { + if _, err := b.store.DeleteImage(value, true); err != nil { + logrus.Debugf("unable to remove intermediate image %q: %v", value, err) + } + } return nil } @@ -1217,6 +1266,7 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOpt d.Close() } }(dockerfiles...) + for _, dfile := range paths { var data io.ReadCloser diff --git a/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go b/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go index f1fec7f70..20e396f1f 100644 --- a/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go +++ b/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go @@ -24,7 +24,8 @@ func init() { func resolveChrootedSymlinks() { status := 0 flag.Parse() - if len(flag.Args()) < 1 { + if len(flag.Args()) < 2 { + fmt.Fprintf(os.Stderr, "%s needs two arguments\n", symlinkChrootedCommand) os.Exit(1) } // Our first parameter is the directory to chroot into. @@ -50,7 +51,8 @@ func resolveChrootedSymlinks() { os.Exit(status) } -func resolveSymLink(rootdir, filename string) (string, error) { +// ResolveSymlink resolves any symlink in filename in the context of rootdir. +func ResolveSymLink(rootdir, filename string) (string, error) { // The child process expects a chroot and one path that // will be consulted relative to the chroot directory and evaluated // for any symbolic links present. diff --git a/vendor/github.com/containers/buildah/mount.go b/vendor/github.com/containers/buildah/mount.go index 4f1ae3c6e..0eb9cbcea 100644 --- a/vendor/github.com/containers/buildah/mount.go +++ b/vendor/github.com/containers/buildah/mount.go @@ -1,17 +1,21 @@ package buildah +import ( + "github.com/pkg/errors" +) + // Mount mounts a container's root filesystem in a location which can be // accessed from the host, and returns the location. func (b *Builder) Mount(label string) (string, error) { mountpoint, err := b.store.Mount(b.ContainerID, label) if err != nil { - return "", err + return "", errors.Wrapf(err, "error mounting build container %q", b.ContainerID) } b.MountPoint = mountpoint err = b.Save() if err != nil { - return "", err + return "", errors.Wrapf(err, "error saving updated state for build container %q", b.ContainerID) } return mountpoint, nil } diff --git a/vendor/github.com/containers/buildah/new.go b/vendor/github.com/containers/buildah/new.go index 3b94459e7..e271d2b4d 100644 --- a/vendor/github.com/containers/buildah/new.go +++ b/vendor/github.com/containers/buildah/new.go @@ -49,7 +49,7 @@ func pullAndFindImage(ctx context.Context, store storage.Store, imageName string img, err := is.Transport.GetStoreImage(store, ref) if err != nil { logrus.Debugf("error reading pulled image %q: %v", imageName, err) - return nil, nil, err + return nil, nil, errors.Wrapf(err, "error locating image %q in local storage", transports.ImageName(ref)) } return img, ref, nil } @@ -60,7 +60,7 @@ func getImageName(name string, img *storage.Image) string { imageName = img.Names[0] // When the image used by the container is a tagged image // the container name might be set to the original image instead of - // the image given in the "form" command line. + // the image given in the "from" command line. // This loop is supposed to fix this. for _, n := range img.Names { if strings.Contains(n, name) { @@ -144,6 +144,7 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store logrus.Debugf("error parsing image name %q: %v", image, err) continue } + logrus.Debugf("error parsing image name %q as given, trying with transport %q: %v", image, options.Transport, err) transport := options.Transport if transport != DefaultTransport { transport = transport + ":" @@ -151,7 +152,7 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store srcRef2, err := alltransports.ParseImageName(transport + image) if err != nil { pullErrors = multierror.Append(pullErrors, err) - logrus.Debugf("error parsing image name %q: %v", image, err) + logrus.Debugf("error parsing image name %q: %v", transport+image, err) continue } srcRef = srcRef2 @@ -322,7 +323,7 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions if options.Mount { _, err = builder.Mount(mountLabel) if err != nil { - return nil, errors.Wrapf(err, "error mounting build container") + return nil, errors.Wrapf(err, "error mounting build container %q", builder.ContainerID) } } @@ -331,7 +332,7 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions } err = builder.Save() if err != nil { - return nil, errors.Wrapf(err, "error saving builder state") + return nil, errors.Wrapf(err, "error saving builder state for container %q", builder.ContainerID) } return builder, nil diff --git a/vendor/github.com/containers/buildah/pkg/cli/common.go b/vendor/github.com/containers/buildah/pkg/cli/common.go index 4baf0da69..b54663f5d 100644 --- a/vendor/github.com/containers/buildah/pkg/cli/common.go +++ b/vendor/github.com/containers/buildah/pkg/cli/common.go @@ -83,7 +83,7 @@ var ( }, cli.StringFlag{ Name: "authfile", - Usage: "path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override. ", + Usage: "path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json", }, cli.StringSliceFlag{ Name: "build-arg", diff --git a/vendor/github.com/containers/buildah/pkg/parse/parse.go b/vendor/github.com/containers/buildah/pkg/parse/parse.go index 1f13cfdee..b87eb95c7 100644 --- a/vendor/github.com/containers/buildah/pkg/parse/parse.go +++ b/vendor/github.com/containers/buildah/pkg/parse/parse.go @@ -545,14 +545,16 @@ func NamespaceOptions(c *cli.Context) (namespaceOptions buildah.NamespaceOptions func defaultIsolation() (buildah.Isolation, error) { isolation, isSet := os.LookupEnv("BUILDAH_ISOLATION") if isSet { - if strings.HasPrefix(strings.ToLower(isolation), "oci") { + switch strings.ToLower(isolation) { + case "oci": return buildah.IsolationOCI, nil - } else if strings.HasPrefix(strings.ToLower(isolation), "rootless") { + case "rootless": return buildah.IsolationOCIRootless, nil - } else if strings.HasPrefix(strings.ToLower(isolation), "chroot") { + case "chroot": return buildah.IsolationChroot, nil + default: + return 0, errors.Errorf("unrecognized $BUILDAH_ISOLATION value %q", isolation) } - return 0, errors.Errorf("unrecognized $BUILDAH_ISOLATION value %q", isolation) } return buildah.IsolationDefault, nil } @@ -560,14 +562,15 @@ func defaultIsolation() (buildah.Isolation, error) { // IsolationOption parses the --isolation flag. func IsolationOption(c *cli.Context) (buildah.Isolation, error) { if c.String("isolation") != "" { - if strings.HasPrefix(strings.ToLower(c.String("isolation")), "oci") { + switch strings.ToLower(c.String("isolation")) { + case "oci": return buildah.IsolationOCI, nil - } else if strings.HasPrefix(strings.ToLower(c.String("isolation")), "rootless") { + case "rootless": return buildah.IsolationOCIRootless, nil - } else if strings.HasPrefix(strings.ToLower(c.String("isolation")), "chroot") { + case "chroot": return buildah.IsolationChroot, nil - } else { - return buildah.IsolationDefault, errors.Errorf("unrecognized isolation type %q", c.String("isolation")) + default: + return 0, errors.Errorf("unrecognized isolation type %q", c.String("isolation")) } } return defaultIsolation() diff --git a/vendor/github.com/containers/buildah/pull.go b/vendor/github.com/containers/buildah/pull.go index b7a106b2f..3cf5c6343 100644 --- a/vendor/github.com/containers/buildah/pull.go +++ b/vendor/github.com/containers/buildah/pull.go @@ -54,11 +54,11 @@ func localImageNameForReference(ctx context.Context, store storage.Store, srcRef case util.DockerArchive: tarSource, err := tarfile.NewSourceFromFile(file) if err != nil { - return "", err + return "", errors.Wrapf(err, "error opening tarfile %q as a source image", file) } manifest, err := tarSource.LoadTarManifest() if err != nil { - return "", errors.Errorf("error retrieving manifest.json: %v", err) + return "", errors.Errorf("error retrieving manifest.json from tarfile %q: %v", file, err) } // to pull the first image stored in the tar file if len(manifest) == 0 { @@ -82,7 +82,7 @@ func localImageNameForReference(ctx context.Context, store storage.Store, srcRef // retrieve the manifest from index.json to access the image name manifest, err := ociarchive.LoadManifestDescriptor(srcRef) if err != nil { - return "", errors.Wrapf(err, "error loading manifest for %q", srcRef) + return "", errors.Wrapf(err, "error loading manifest for %q", transports.ImageName(srcRef)) } // if index.json has no reference name, compute the image digest instead if manifest.Annotations == nil || manifest.Annotations["org.opencontainers.image.ref.name"] == "" { @@ -108,11 +108,12 @@ func localImageNameForReference(ctx context.Context, store storage.Store, srcRef if err == nil { return name, nil } + logrus.Debugf("error parsing local storage reference %q: %v", name, err) if strings.LastIndex(name, "/") != -1 { name = name[strings.LastIndex(name, "/")+1:] _, err = is.Transport.ParseStoreReference(store, name) if err == nil { - return name, nil + return name, errors.Wrapf(err, "error parsing local storage reference %q", name) } } return "", errors.Errorf("reference to image %q is not a named reference", transports.ImageName(srcRef)) @@ -135,7 +136,7 @@ func localImageNameForReference(ctx context.Context, store storage.Store, srcRef return name, nil } -// Pull copies the contents of the image from somewhere else. +// Pull copies the contents of the image from somewhere else to local storage. func Pull(ctx context.Context, imageName string, options PullOptions) (types.ImageReference, error) { systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath) return pullImage(ctx, options.Store, imageName, options, systemContext) @@ -146,8 +147,9 @@ func pullImage(ctx context.Context, store storage.Store, imageName string, optio srcRef, err := alltransports.ParseImageName(spec) if err != nil { if options.Transport == "" { - return nil, errors.Wrapf(err, "error parsing image name %q", spec) + options.Transport = DefaultTransport } + logrus.Debugf("error parsing image name %q, trying with transport %q: %v", spec, options.Transport, err) transport := options.Transport if transport != DefaultTransport { transport = transport + ":" @@ -159,6 +161,7 @@ func pullImage(ctx context.Context, store storage.Store, imageName string, optio } srcRef = srcRef2 } + logrus.Debugf("parsed image name %q", spec) blocked, err := isReferenceBlocked(srcRef, sc) if err != nil { @@ -207,14 +210,17 @@ func pullImage(ctx context.Context, store storage.Store, imageName string, optio registryPath := sysregistries.RegistriesConfPath(sc) searchRegistries, err := getRegistries(sc) if err != nil { - return nil, err + logrus.Debugf("error getting list of registries: %v", err) + return nil, errors.Wrapf(pullError, "error copying image from %q to %q", transports.ImageName(srcRef), transports.ImageName(destRef)) } hasRegistryInName, err := hasRegistry(imageName) if err != nil { - return nil, err + logrus.Debugf("error checking if image name %q includes a registry component: %v", imageName, err) + return nil, errors.Wrapf(pullError, "error copying image from %q to %q", transports.ImageName(srcRef), transports.ImageName(destRef)) } if !hasRegistryInName && len(searchRegistries) == 0 { - return nil, errors.Errorf("image name provided is a short name and no search registries are defined in %s: %s", registryPath, pullError) + logrus.Debugf("copying %q to %q failed: %v", pullError) + return nil, errors.Errorf("image name provided does not include a registry name and no search registries are defined in %s: %s", registryPath, pullError) } return nil, pullError } @@ -224,13 +230,13 @@ func pullImage(ctx context.Context, store storage.Store, imageName string, optio func getImageDigest(ctx context.Context, src types.ImageReference, sc *types.SystemContext) (string, error) { newImg, err := src.NewImage(ctx, sc) if err != nil { - return "", err + return "", errors.Wrapf(err, "error opening image %q for reading", transports.ImageName(src)) } defer newImg.Close() digest := newImg.ConfigInfo().Digest if err = digest.Validate(); err != nil { - return "", errors.Wrapf(err, "error getting config info") + return "", errors.Wrapf(err, "error getting config info from image %q", transports.ImageName(src)) } return "@" + digest.Hex(), nil } diff --git a/vendor/github.com/containers/buildah/run.go b/vendor/github.com/containers/buildah/run.go index d73f0d239..4f39b4625 100644 --- a/vendor/github.com/containers/buildah/run.go +++ b/vendor/github.com/containers/buildah/run.go @@ -213,7 +213,7 @@ func DefaultNamespaceOptions() (NamespaceOptions, error) { } g, err := generate.New("linux") if err != nil { - return options, err + return options, errors.Wrapf(err, "error generating new 'linux' runtime spec") } spec := g.Config if spec.Linux != nil { @@ -295,7 +295,7 @@ func addHostsToFile(hosts []string, filename string) error { } file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.ModeAppend) if err != nil { - return err + return errors.Wrapf(err, "error creating hosts file %q", filename) } defer file.Close() return addHosts(hosts, file) @@ -370,6 +370,7 @@ func (b *Builder) setupMounts(mountPoint string, spec *specs.Spec, bundlePath st specMount.Options = []string{"nosuid", "noexec", "nodev", "mode=1777", "size=" + shmSize} if hostIPC && !hostUser { if _, err := os.Stat("/dev/shm"); err != nil && os.IsNotExist(err) { + logrus.Debugf("/dev/shm is not present, not binding into container") continue } specMount = specs.Mount{ @@ -383,6 +384,7 @@ func (b *Builder) setupMounts(mountPoint string, spec *specs.Spec, bundlePath st if specMount.Destination == "/dev/mqueue" { if hostIPC && !hostUser { if _, err := os.Stat("/dev/mqueue"); err != nil && os.IsNotExist(err) { + logrus.Debugf("/dev/mqueue is not present, not binding into container") continue } specMount = specs.Mount{ @@ -397,6 +399,7 @@ func (b *Builder) setupMounts(mountPoint string, spec *specs.Spec, bundlePath st if hostNetwork && !hostUser { mountCgroups = false if _, err := os.Stat("/sys"); err != nil && os.IsNotExist(err) { + logrus.Debugf("/sys is not present, not binding into container") continue } specMount = specs.Mount{ @@ -498,7 +501,8 @@ func runSetupBuiltinVolumes(mountLabel, mountPoint, containerDir string, copyWit subdir := digest.Canonical.FromString(volume).Hex() volumePath := filepath.Join(containerDir, "buildah-volumes", subdir) // If we need to, initialize the volume path's initial contents. - if _, err := os.Stat(volumePath); os.IsNotExist(err) { + if _, err := os.Stat(volumePath); err != nil && os.IsNotExist(err) { + logrus.Debugf("setting up built-in volume at %q", volumePath) if err = os.MkdirAll(volumePath, 0755); err != nil { return nil, errors.Wrapf(err, "error creating directory %q for volume %q", volumePath, volume) } @@ -576,6 +580,7 @@ func runSetupVolumeMounts(mountLabel string, volumeMounts []string, optionMounts } // Bind mount volumes specified for this particular Run() invocation for _, i := range optionMounts { + logrus.Debugf("setting up mounted volume at %q", i.Destination) mount, err := parseMount(i.Source, i.Destination, append(i.Options, "rbind")) if err != nil { return nil, err @@ -701,10 +706,7 @@ func setupCapabilities(g *generate.Generator, firstAdds, firstDrops, secondAdds, if err := setupCapAdd(g, secondAdds...); err != nil { return err } - if err := setupCapDrop(g, secondDrops...); err != nil { - return err - } - return nil + return setupCapDrop(g, secondDrops...) } func setupTerminal(g *generate.Generator, terminalPolicy TerminalPolicy, terminalSize *specs.Box) { @@ -937,13 +939,13 @@ func (b *Builder) configureNamespaces(g *generate.Generator, options RunOptions) func (b *Builder) Run(command []string, options RunOptions) error { p, err := ioutil.TempDir("", Package) if err != nil { - return err + return errors.Wrapf(err, "run: error creating temporary directory under %q", os.TempDir()) } // On some hosts like AH, /tmp is a symlink and we need an // absolute path. path, err := filepath.EvalSymlinks(p) if err != nil { - return err + return errors.Wrapf(err, "run: error evaluating %q for symbolic links", p) } logrus.Debugf("using %q to hold bundle data", path) defer func() { @@ -954,7 +956,7 @@ func (b *Builder) Run(command []string, options RunOptions) error { gp, err := generate.New("linux") if err != nil { - return err + return errors.Wrapf(err, "error generating new 'linux' runtime spec") } g := &gp @@ -987,7 +989,7 @@ func (b *Builder) Run(command []string, options RunOptions) error { setupSelinux(g, b.ProcessLabel, b.MountLabel) mountPoint, err := b.Mount(b.MountLabel) if err != nil { - return err + return errors.Wrapf(err, "error mounting container %q", b.ContainerID) } defer func() { if err := b.Unmount(); err != nil { @@ -1065,7 +1067,7 @@ func (b *Builder) Run(command []string, options RunOptions) error { } err = b.setupMounts(mountPoint, spec, path, options.Mounts, bindFiles, b.Volumes(), b.CommonBuildOpts.Volumes, b.CommonBuildOpts.ShmSize, append(b.NamespaceOptions, options.NamespaceOptions...)) if err != nil { - return errors.Wrapf(err, "error resolving mountpoints for container") + return errors.Wrapf(err, "error resolving mountpoints for container %q", b.ContainerID) } if options.CNIConfigDir == "" { @@ -1262,16 +1264,25 @@ func (b *Builder) runUsingRuntimeSubproc(options RunOptions, configureNetwork bo confwg.Add(1) go func() { _, conferr = io.Copy(pwriter, bytes.NewReader(config)) + if conferr != nil { + conferr = errors.Wrapf(conferr, "error while copying configuration down pipe to child process") + } confwg.Done() }() cmd.ExtraFiles = append([]*os.File{preader}, cmd.ExtraFiles...) defer preader.Close() defer pwriter.Close() err = cmd.Run() + if err != nil { + err = errors.Wrapf(err, "error while running runtime") + } confwg.Wait() if err == nil { return conferr } + if conferr != nil { + logrus.Debugf("%v", conferr) + } return err } @@ -1340,10 +1351,10 @@ func runUsingRuntime(options RunOptions, configureNetwork bool, configureNetwork // Write the runtime configuration. specbytes, err := json.Marshal(spec) if err != nil { - return 1, err + return 1, errors.Wrapf(err, "error encoding configuration %#v as json", spec) } if err = ioutils.AtomicWriteFile(filepath.Join(bundlePath, "config.json"), specbytes, 0600); err != nil { - return 1, errors.Wrapf(err, "error storing runtime configuration") + return 1, errors.Wrapf(err, "error storing runtime configuration in %q", filepath.Join(bundlePath, "config.json")) } logrus.Debugf("config = %v", string(specbytes)) @@ -1378,7 +1389,7 @@ func runUsingRuntime(options RunOptions, configureNetwork bool, configureNetwork socketPath := filepath.Join(bundlePath, "console.sock") consoleListener, err = net.ListenUnix("unix", &net.UnixAddr{Name: socketPath, Net: "unix"}) if err != nil { - return 1, errors.Wrapf(err, "error creating socket to receive terminal descriptor") + return 1, errors.Wrapf(err, "error creating socket %q to receive terminal descriptor", consoleListener.Addr()) } // Add console socket arguments. moreCreateArgs = append(moreCreateArgs, "--console-socket", socketPath) @@ -1792,7 +1803,7 @@ func runCopyStdio(stdio *sync.WaitGroup, copyPipes bool, stdioPipe [][]int, copy return true } } - logrus.Error(what) + logrus.Errorf("%s: %v", what, err) return false } // Pass data back and forth. @@ -1924,7 +1935,7 @@ func runAcceptTerminal(consoleListener *net.UnixListener, terminalSize *specs.Bo oob := make([]byte, 8192) n, oobn, _, _, err := c.ReadMsgUnix(b, oob) if err != nil { - return -1, errors.Wrapf(err, "error reading socket descriptor: %v") + return -1, errors.Wrapf(err, "error reading socket descriptor") } if n > 0 { logrus.Debugf("socket descriptor is for %q", string(b[:n])) diff --git a/vendor/github.com/containers/buildah/unmount.go b/vendor/github.com/containers/buildah/unmount.go index cdb511170..b86ad92fd 100644 --- a/vendor/github.com/containers/buildah/unmount.go +++ b/vendor/github.com/containers/buildah/unmount.go @@ -1,11 +1,19 @@ package buildah +import ( + "github.com/pkg/errors" +) + // Unmount unmounts a build container. func (b *Builder) Unmount() error { _, err := b.store.Unmount(b.ContainerID, false) - if err == nil { - b.MountPoint = "" - err = b.Save() + if err != nil { + return errors.Wrapf(err, "error unmounting build container %q", b.ContainerID) + } + b.MountPoint = "" + err = b.Save() + if err != nil { + return errors.Wrapf(err, "error saving updated state for build container %q", b.ContainerID) } - return err + return nil } diff --git a/vendor/github.com/containers/buildah/unshare/unshare.c b/vendor/github.com/containers/buildah/unshare/unshare.c index ae4185ea4..6873e49c2 100644 --- a/vendor/github.com/containers/buildah/unshare/unshare.c +++ b/vendor/github.com/containers/buildah/unshare/unshare.c @@ -9,9 +9,11 @@ #include <stdlib.h> #include <string.h> #include <termios.h> +#include <errno.h> #include <unistd.h> -const char *_max_user_namespaces = "/proc/sys/user/max_user_namespaces"; +static const char *_max_user_namespaces = "/proc/sys/user/max_user_namespaces"; +static const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivileged_userns_clone"; static int _buildah_unshare_parse_envint(const char *envname) { char *p, *q; @@ -31,12 +33,35 @@ static int _buildah_unshare_parse_envint(const char *envname) { return l; } -void _buildah_unshare(void) +static void _check_proc_sys_file(const char *path) { FILE *fp; - int flags, pidfd, continuefd, n, pgrp, sid, ctty; - long max_userns; + char buf[32]; size_t n_read; + long r; + + fp = fopen(path, "r"); + if (fp == NULL) { + if (errno != ENOENT) + fprintf(stderr, "Error reading %s: %m\n", _max_user_namespaces); + } else { + memset(buf, 0, sizeof(buf)); + n_read = fread(buf, 1, sizeof(buf) - 1, fp); + if (n_read > 0) { + r = atoi(buf); + if (r == 0) { + fprintf(stderr, "User namespaces are not enabled in %s.\n", path); + } + } else { + fprintf(stderr, "Error reading %s: no contents, should contain a number greater than 0.\n", path); + } + fclose(fp); + } +} + +void _buildah_unshare(void) +{ + int flags, pidfd, continuefd, n, pgrp, sid, ctty; char buf[2048]; flags = _buildah_unshare_parse_envint("_Buildah-unshare"); @@ -46,22 +71,8 @@ void _buildah_unshare(void) if ((flags & CLONE_NEWUSER) != 0) { if (unshare(CLONE_NEWUSER) == -1) { fprintf(stderr, "Error during unshare(CLONE_NEWUSER): %m\n"); - fp = fopen(_max_user_namespaces, "r"); - if (fp != NULL) { - memset(buf, 0, sizeof(buf)); - n_read = fread(buf, 1, sizeof(buf) - 1, fp); - if (n_read > 0) { - max_userns = atoi(buf); - if (max_userns == 0) { - fprintf(stderr, "User namespaces are not enabled in %s.\n", _max_user_namespaces); - } - } else { - fprintf(stderr, "Error reading %s: no contents, should contain a number greater than 0.\n", _max_user_namespaces); - } - fclose(fp); - } else { - fprintf(stderr, "Error reading %s: %m\n", _max_user_namespaces); - } + _check_proc_sys_file (_max_user_namespaces); + _check_proc_sys_file (_unprivileged_user_namespaces); _exit(1); } } diff --git a/vendor/github.com/containers/buildah/util.go b/vendor/github.com/containers/buildah/util.go index 7bb651bd2..697f98779 100644 --- a/vendor/github.com/containers/buildah/util.go +++ b/vendor/github.com/containers/buildah/util.go @@ -95,7 +95,7 @@ func (b *Builder) copyFileWithTar(chownOpts *idtools.IDPair, hasher io.Writer) f archiver.Untar = func(tarArchive io.Reader, dest string, options *archive.TarOptions) error { contentReader, contentWriter, err := os.Pipe() if err != nil { - return err + return errors.Wrapf(err, "error creating pipe extract data to %q", dest) } defer contentReader.Close() defer contentWriter.Close() @@ -113,10 +113,12 @@ func (b *Builder) copyFileWithTar(chownOpts *idtools.IDPair, hasher io.Writer) f } hashWorker.Done() }() - err = originalUntar(io.TeeReader(tarArchive, contentWriter), dest, options) + if err = originalUntar(io.TeeReader(tarArchive, contentWriter), dest, options); err != nil { + err = errors.Wrapf(err, "error extracting data to %q while copying", dest) + } hashWorker.Wait() if err == nil { - err = hashError + err = errors.Wrapf(hashError, "error calculating digest of data for %q while copying", dest) } return err } @@ -255,7 +257,7 @@ func isReferenceBlocked(ref types.ImageReference, sc *types.SystemContext) (bool func hasRegistry(imageName string) (bool, error) { imgRef, err := reference.Parse(imageName) if err != nil { - return false, err + return false, errors.Wrapf(err, "error parsing image name %q", imageName) } registry := reference.Domain(imgRef.(reference.Named)) if registry != "" { @@ -270,7 +272,7 @@ func ReserveSELinuxLabels(store storage.Store, id string) error { if selinux.GetEnabled() { containers, err := store.Containers() if err != nil { - return err + return errors.Wrapf(err, "error getting list of containers") } for _, c := range containers { @@ -288,7 +290,7 @@ func ReserveSELinuxLabels(store storage.Store, id string) error { } // Prevent different containers from using same MCS label if err := label.ReserveLabel(b.ProcessLabel); err != nil { - return err + return errors.Wrapf(err, "error reserving SELinux label %q", b.ProcessLabel) } } } diff --git a/vendor/github.com/containers/buildah/util/util.go b/vendor/github.com/containers/buildah/util/util.go index 93323232d..887004ba4 100644 --- a/vendor/github.com/containers/buildah/util/util.go +++ b/vendor/github.com/containers/buildah/util/util.go @@ -10,6 +10,7 @@ import ( "path/filepath" "strconv" "strings" + "syscall" "github.com/containers/image/directory" dockerarchive "github.com/containers/image/docker/archive" @@ -472,11 +473,31 @@ func UnsharedRunrootPath(uid string) (string, error) { if envRuntimeDir, haveRuntimeDir := os.LookupEnv("XDG_RUNTIME_DIR"); haveRuntimeDir { return filepath.Join(envRuntimeDir, "run"), nil } + var runtimeDir string // If $XDG_RUNTIME_DIR is not defined, but we know our UID... if uid != "" { - return filepath.Join("/var/run/user", uid, "run"), nil + tmpDir := filepath.Join("/var/run/user", uid) + os.MkdirAll(tmpDir, 0700) + st, err := os.Stat(tmpDir) + if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Getuid() && st.Mode().Perm() == 0700 { + runtimeDir = tmpDir + } + } + if runtimeDir == "" { + home := os.Getenv("HOME") + if home == "" { + return "", errors.New("neither XDG_RUNTIME_DIR nor HOME was set non-empty") + } + resolvedHome, err := filepath.EvalSymlinks(home) + if err != nil { + return "", errors.Wrapf(err, "cannot resolve %s", home) + } + runtimeDir = filepath.Join(resolvedHome, "rundir") + } + if err := os.Setenv("XDG_RUNTIME_DIR", runtimeDir); err != nil { + return "", errors.New("could not set XDG_RUNTIME_DIR") } - return "", errors.New("unable to determine a --runroot location: $XDG_RUNTIME_DIR is not set, and we don't know our UID") + return runtimeDir, nil } // GetPolicyContext sets up, initializes and returns a new context for the specified policy diff --git a/vendor/github.com/containers/buildah/vendor.conf b/vendor/github.com/containers/buildah/vendor.conf index 42389e8c6..6ab583f51 100644 --- a/vendor/github.com/containers/buildah/vendor.conf +++ b/vendor/github.com/containers/buildah/vendor.conf @@ -3,7 +3,7 @@ github.com/blang/semver master github.com/BurntSushi/toml master github.com/containerd/continuity master github.com/containernetworking/cni v0.7.0-alpha1 -github.com/containers/image 5cc7850824afe2b4fb016f8906666b358c50dc31 +github.com/containers/image 918dbb93e6e099b196b498c38d079f6bb924d0c8 github.com/containers/libpod 2afadeec6696fefac468a49c8ba24b0bc275aa75 github.com/containers/storage 41294c85d97bef688e18f710402895dbecde3308 github.com/docker/distribution 5f6282db7d65e6d72ad7c2cc66310724a57be716 |