diff options
author | Valentin Rothberg <rothberg@redhat.com> | 2021-07-19 11:41:04 +0200 |
---|---|---|
committer | Valentin Rothberg <rothberg@redhat.com> | 2021-07-26 09:28:17 +0200 |
commit | 1b6423e9f172b6d2437011ef4504a8247728a73d (patch) | |
tree | 0ba7fccceb6b036ed5e49caec51ffeb9921234a8 | |
parent | ec5c7c1f6a1898dacddb6cc35802525c288b61ef (diff) | |
download | podman-1b6423e9f172b6d2437011ef4504a8247728a73d.tar.gz podman-1b6423e9f172b6d2437011ef4504a8247728a73d.tar.bz2 podman-1b6423e9f172b6d2437011ef4504a8247728a73d.zip |
refine dangling checks
By proxy by vendoring containers/common. Previously, a "dangling" image
was an untagged image; just a described in the Docker docs. The
definition of dangling has now been refined to an untagged image without
children to be compatible with Docker.
Further update a redundant image-prune test.
Fixes: #10998
Fixes: #10832
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
24 files changed, 296 insertions, 251 deletions
diff --git a/docs/source/markdown/podman-images.1.md b/docs/source/markdown/podman-images.1.md index 23cce450a..02385daec 100644 --- a/docs/source/markdown/podman-images.1.md +++ b/docs/source/markdown/podman-images.1.md @@ -36,7 +36,7 @@ Filter output based on conditions provided Filter on images created before the given IMAGE (name or tag). **dangling=true|false** - Show dangling images. Dangling images are a file system layer that was used in a previous build of an image and is no longer referenced by any active images. They are denoted with the `<none>` tag, consume disk space and serve no active purpose. + Show dangling images. Dangling images are a file system layer that was used in a previous build of an image and is no longer referenced by any image. They are denoted with the `<none>` tag, consume disk space and serve no active purpose. **label** Filter by images labels key and/or value. diff --git a/docs/source/markdown/podman-rmi.1.md b/docs/source/markdown/podman-rmi.1.md index 1f62d6133..e34b1964b 100644 --- a/docs/source/markdown/podman-rmi.1.md +++ b/docs/source/markdown/podman-rmi.1.md @@ -10,7 +10,7 @@ podman\-rmi - Removes one or more locally stored images ## DESCRIPTION Removes one or more locally stored images. -Passing an argument _image_ deletes it, along with any of its dangling (untagged) parent images. +Passing an argument _image_ deletes it, along with any of its dangling parent images. A dangling image is an image without a tag and without being referenced by another image. ## OPTIONS @@ -11,8 +11,8 @@ require ( github.com/container-orchestrated-devices/container-device-interface v0.0.0-20210325223243-f99e8b6c10b9 github.com/containernetworking/cni v0.8.1 github.com/containernetworking/plugins v0.9.1 - github.com/containers/buildah v1.21.1-0.20210707133512-2eb97b499d74 - github.com/containers/common v0.41.1-0.20210716140645-ffcfe1ff6e70 + github.com/containers/buildah v1.21.1-0.20210721171232-54cafea4c933 + github.com/containers/common v0.41.1-0.20210721172332-291287e9d060 github.com/containers/conmon v2.0.20+incompatible github.com/containers/image/v5 v5.13.2 github.com/containers/ocicrypt v1.1.2 @@ -239,11 +239,11 @@ github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHV github.com/containernetworking/plugins v0.8.7/go.mod h1:R7lXeZaBzpfqapcAbHRW8/CYwm0dHzbz0XEjofx0uB0= github.com/containernetworking/plugins v0.9.1 h1:FD1tADPls2EEi3flPc2OegIY1M9pUa9r2Quag7HMLV8= github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containers/buildah v1.21.1-0.20210707133512-2eb97b499d74 h1:u+Wk1Gv+UgOR0AHmlpbH+ZsdfZt7vkGuiKCyhbI4Ga0= -github.com/containers/buildah v1.21.1-0.20210707133512-2eb97b499d74/go.mod h1:P0rxPkI7440rWVMkbPkSHX4j1PxjOcx+cY8QrqYgdLE= -github.com/containers/common v0.40.2-0.20210707094508-0a4a1906d4b2/go.mod h1:thow5Jn7O+rP01njI9COQ16L9g/KQ1LcMcYqP2NhYCU= -github.com/containers/common v0.41.1-0.20210716140645-ffcfe1ff6e70 h1:9kKqg10PfrLQdsN4lw/n8XIuqLk43JwwAcE4klCvOsI= -github.com/containers/common v0.41.1-0.20210716140645-ffcfe1ff6e70/go.mod h1:w0CLPB8nH75msgISbE/z8TMIxK9disFsmvFNd2SDid8= +github.com/containers/buildah v1.21.1-0.20210721171232-54cafea4c933 h1:jqO3hDypBoKM5be+fVcqGHOpX2fOiQy2DFEeb/VKpsk= +github.com/containers/buildah v1.21.1-0.20210721171232-54cafea4c933/go.mod h1:9gspFNeUJxIK72n1IMIKIHmtcePEZQsv0tjo+1LqkCo= +github.com/containers/common v0.41.1-0.20210721112610-c95d2f794edf/go.mod h1:Ba5YVNCnyX6xDtg1JqEHa2EMVMW5UbHmIyEqsEwpeGE= +github.com/containers/common v0.41.1-0.20210721172332-291287e9d060 h1:HgGff2MeEKfYoKp2WQFl9xdsgP7KV8rr/1JZRIuPXmg= +github.com/containers/common v0.41.1-0.20210721172332-291287e9d060/go.mod h1:Ba5YVNCnyX6xDtg1JqEHa2EMVMW5UbHmIyEqsEwpeGE= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/image/v5 v5.13.2 h1:AgYunV/9d2fRkrmo23wH2MkqeHolFd6oQCkK+1PpuFA= @@ -259,7 +259,6 @@ github.com/containers/psgo v1.5.2 h1:3aoozst/GIwsrr/5jnFy3FrJay98uujPCu9lTuSZ/Cw github.com/containers/psgo v1.5.2/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU= github.com/containers/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3ETQAf/CeZPyM= github.com/containers/storage v1.32.2/go.mod h1:YIBxxjfXZTi04Ah49sh1uSGfmT1V89+I5i3deRobzQo= -github.com/containers/storage v1.32.5/go.mod h1:8/DVVDqniaUlUV0D0q7cEnXK6Bs2uU3FPqNZVPumwEs= github.com/containers/storage v1.32.6 h1:NqdFRewXO/PYPjgCAScoigZc5QUA21yapSEj6kqD8cw= github.com/containers/storage v1.32.6/go.mod h1:mdB+b89p+jU8zpzLTVXA0gWMmIo0WrkfGMh1R8O2IQw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -698,7 +697,6 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= -github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= @@ -709,7 +707,6 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= -github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/onsi/gomega v1.14.0 h1:ep6kpPVwmr/nTbklSx2nrLNSIO62DoYAhnPNIMhK8gI= github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index 3cc10d70f..af5878798 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -176,6 +176,11 @@ func ImageToImageSummary(l *libimage.Image) (*entities.ImageSummary, error) { } containerCount := len(containers) + isDangling, err := l.IsDangling(context.TODO()) + if err != nil { + return nil, errors.Wrapf(err, "failed to check if image %s is dangling", l.ID()) + } + is := entities.ImageSummary{ ID: l.ID(), ParentId: imageData.Parent, @@ -188,7 +193,7 @@ func ImageToImageSummary(l *libimage.Image) (*entities.ImageSummary, error) { Labels: imageData.Labels, Containers: containerCount, ReadOnly: l.IsReadOnly(), - Dangling: l.IsDangling(), + Dangling: isDangling, Names: l.Names(), Digest: string(imageData.Digest), ConfigDigest: "", // TODO: libpod/image didn't set it but libimage should diff --git a/pkg/domain/infra/abi/images_list.go b/pkg/domain/infra/abi/images_list.go index b0e947991..2ec4ad244 100644 --- a/pkg/domain/infra/abi/images_list.go +++ b/pkg/domain/infra/abi/images_list.go @@ -30,12 +30,16 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) for j, d := range img.Digests() { digests[j] = string(d) } + isDangling, err := img.IsDangling(ctx) + if err != nil { + return nil, errors.Wrapf(err, "error checking if image %q is dangling", img.ID()) + } e := entities.ImageSummary{ ID: img.ID(), // ConfigDigest: string(img.ConfigDigest), Created: img.Created().Unix(), - Dangling: img.IsDangling(), + Dangling: isDangling, Digest: string(img.Digest()), RepoDigests: digests, History: img.NamesHistory(), diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go index 68ccd0a94..ff70a8cf4 100644 --- a/test/e2e/prune_test.go +++ b/test/e2e/prune_test.go @@ -16,6 +16,11 @@ LABEL RUN podman --version RUN apk update RUN apk add bash`, ALPINE) +var emptyPruneImage = ` +FROM scratch +ENV test1=test1 +ENV test2=test2` + var _ = Describe("Podman prune", func() { var ( tempdir string @@ -110,8 +115,12 @@ var _ = Describe("Podman prune", func() { Expect(session).Should(Exit(0)) Expect(len(session.OutputToStringArray())).To(Equal(numImages)) - // Now build a new image with dangling intermediate images. + // Now build an image and untag it. The (intermediate) images + // should be removed recursively during pruning. podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true") + session = podmanTest.Podman([]string{"untag", "alpine_bash:latest"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) session = podmanTest.Podman([]string{"images", "-a"}) session.WaitWithDefaultTimeout() @@ -136,26 +145,33 @@ var _ = Describe("Podman prune", func() { Expect(len(session.OutputToStringArray())).To(Equal(numImages - numPrunedImages)) }) - It("podman image prune skip cache images", func() { - podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true") + It("podman image prune - handle empty images", func() { + // As shown in #10832, empty images were not treated correctly + // in Podman. + podmanTest.BuildImage(emptyPruneImage, "empty:scratch", "true") - none := podmanTest.Podman([]string{"images", "-a"}) - none.WaitWithDefaultTimeout() - Expect(none).Should(Exit(0)) - hasNone, _ := none.GrepString("<none>") + session := podmanTest.Podman([]string{"images", "-a"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + hasNone, _ := session.GrepString("<none>") Expect(hasNone).To(BeTrue()) - prune := podmanTest.Podman([]string{"image", "prune", "-f"}) - prune.WaitWithDefaultTimeout() - Expect(prune).Should(Exit(0)) + // Nothing will be pruned. + session = podmanTest.Podman([]string{"image", "prune", "-f"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(len(session.OutputToStringArray())).To(Equal(0)) - after := podmanTest.Podman([]string{"images", "-a"}) - after.WaitWithDefaultTimeout() - Expect(none).Should(Exit(0)) - // Check if all "dangling" images were pruned. - hasNoneAfter, _ := after.GrepString("<none>") - Expect(hasNoneAfter).To(BeFalse()) - Expect(len(after.OutputToStringArray()) > 1).To(BeTrue()) + // Now the image will be untagged, and its parent images will + // be removed recursively. + session = podmanTest.Podman([]string{"untag", "empty:scratch"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"image", "prune", "-f"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(len(session.OutputToStringArray())).To(Equal(2)) }) It("podman image prune dangling images", func() { diff --git a/vendor/github.com/containers/buildah/.cirrus.yml b/vendor/github.com/containers/buildah/.cirrus.yml index 849e45f8a..73ab4fc11 100644 --- a/vendor/github.com/containers/buildah/.cirrus.yml +++ b/vendor/github.com/containers/buildah/.cirrus.yml @@ -30,7 +30,7 @@ env: UBUNTU_NAME: "ubuntu-2104" PRIOR_UBUNTU_NAME: "ubuntu-2010" - IMAGE_SUFFIX: "c6534244118822912" + IMAGE_SUFFIX: "c6248193773010944" FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}" PRIOR_FEDORA_CACHE_IMAGE_NAME: "prior-fedora-${IMAGE_SUFFIX}" UBUNTU_CACHE_IMAGE_NAME: "ubuntu-${IMAGE_SUFFIX}" diff --git a/vendor/github.com/containers/buildah/add.go b/vendor/github.com/containers/buildah/add.go index ad178dc6b..f17e3a9c9 100644 --- a/vendor/github.com/containers/buildah/add.go +++ b/vendor/github.com/containers/buildah/add.go @@ -602,12 +602,43 @@ func (b *Builder) userForRun(mountPoint string, userspec string) (specs.User, st // userForRun() does, except for the case where we're passed a single numeric // value, where we need to use that value for both the UID and the GID. func (b *Builder) userForCopy(mountPoint string, userspec string) (uint32, uint32, error) { - if id, err := strconv.ParseUint(userspec, 10, 32); err == nil { - return uint32(id), uint32(id), nil + var ( + user, group string + uid, gid uint64 + err error + ) + + split := strings.SplitN(userspec, ":", 2) + user = split[0] + if len(split) > 1 { + group = split[1] + } + + // If userspec did not specify any values for user or group, then fail + if user == "" && group == "" { + return 0, 0, errors.Errorf("can't find uid for user %s", userspec) + } + + // If userspec specifies values for user or group, check for numeric values + // and return early. If not, then translate username/groupname + if user != "" { + uid, err = strconv.ParseUint(user, 10, 32) + } + if err == nil { + // default gid to uid + gid = uid + if group != "" { + gid, err = strconv.ParseUint(group, 10, 32) + } } - user, _, err := b.userForRun(mountPoint, userspec) + // If err != nil, then user or group not numeric, check filesystem + if err == nil { + return uint32(uid), uint32(gid), nil + } + + owner, _, err := b.userForRun(mountPoint, userspec) if err != nil { return 0xffffffff, 0xffffffff, err } - return user.UID, user.GID, nil + return owner.UID, owner.GID, nil } diff --git a/vendor/github.com/containers/buildah/chroot/run.go b/vendor/github.com/containers/buildah/chroot/run.go index 7cb1d710e..591003568 100644 --- a/vendor/github.com/containers/buildah/chroot/run.go +++ b/vendor/github.com/containers/buildah/chroot/run.go @@ -161,7 +161,7 @@ func RunUsingChroot(spec *specs.Spec, bundlePath, homeDir string, stdin io.Reade cmd := unshare.Command(runUsingChrootCommand) cmd.Stdin, cmd.Stdout, cmd.Stderr = stdin, stdout, stderr cmd.Dir = "/" - cmd.Env = append([]string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())}, os.Environ()...) + cmd.Env = []string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())} logrus.Debugf("Running %#v in %#v", cmd.Cmd, cmd) confwg.Add(1) @@ -207,7 +207,7 @@ func runUsingChrootMain() { os.Exit(1) } - if options.Spec == nil { + if options.Spec == nil || options.Spec.Process == nil { fmt.Fprintf(os.Stderr, "invalid options spec in runUsingChrootMain\n") os.Exit(1) } @@ -573,7 +573,7 @@ func runUsingChroot(spec *specs.Spec, bundlePath string, ctty *os.File, stdin io cmd := unshare.Command(append([]string{runUsingChrootExecCommand}, spec.Process.Args...)...) cmd.Stdin, cmd.Stdout, cmd.Stderr = stdin, stdout, stderr cmd.Dir = "/" - cmd.Env = append([]string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())}, os.Environ()...) + cmd.Env = []string{fmt.Sprintf("LOGLEVEL=%d", logrus.GetLevel())} cmd.UnshareFlags = syscall.CLONE_NEWUTS | syscall.CLONE_NEWNS requestedUserNS := false for _, ns := range spec.Linux.Namespaces { @@ -663,7 +663,7 @@ func runUsingChrootExecMain() { // Set the hostname. We're already in a distinct UTS namespace and are admins in the user // namespace which created it, so we shouldn't get a permissions error, but seccomp policy // might deny our attempt to call sethostname() anyway, so log a debug message for that. - if options.Spec == nil { + if options.Spec == nil || options.Spec.Process == nil { fmt.Fprintf(os.Stderr, "invalid options spec passed in\n") os.Exit(1) } @@ -819,7 +819,6 @@ func runUsingChrootExecMain() { // Output debug messages when that differs from what we're being asked to do. func logNamespaceDiagnostics(spec *specs.Spec) { sawMountNS := false - sawUserNS := false sawUTSNS := false for _, ns := range spec.Linux.Namespaces { switch ns.Type { @@ -854,9 +853,8 @@ func logNamespaceDiagnostics(spec *specs.Spec) { } case specs.UserNamespace: if ns.Path != "" { - logrus.Debugf("unable to join user namespace %q, creating a new one", ns.Path) + logrus.Debugf("unable to join user namespace, sorry about that") } - sawUserNS = true case specs.UTSNamespace: if ns.Path != "" { logrus.Debugf("unable to join UTS namespace %q, creating a new one", ns.Path) @@ -867,9 +865,6 @@ func logNamespaceDiagnostics(spec *specs.Spec) { if !sawMountNS { logrus.Debugf("mount namespace not requested, but creating a new one anyway") } - if !sawUserNS { - logrus.Debugf("user namespace not requested, but creating a new one anyway") - } if !sawUTSNS { logrus.Debugf("UTS namespace not requested, but creating a new one anyway") } diff --git a/vendor/github.com/containers/buildah/go.mod b/vendor/github.com/containers/buildah/go.mod index 494d1e211..68721b73c 100644 --- a/vendor/github.com/containers/buildah/go.mod +++ b/vendor/github.com/containers/buildah/go.mod @@ -4,10 +4,10 @@ go 1.12 require ( github.com/containernetworking/cni v0.8.1 - github.com/containers/common v0.40.2-0.20210707094508-0a4a1906d4b2 + github.com/containers/common v0.41.1-0.20210721112610-c95d2f794edf github.com/containers/image/v5 v5.13.2 github.com/containers/ocicrypt v1.1.2 - github.com/containers/storage v1.32.5 + github.com/containers/storage v1.32.6 github.com/docker/distribution v2.7.1+incompatible github.com/docker/go-units v0.4.0 github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316 @@ -18,10 +18,10 @@ require ( github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect github.com/mattn/go-shellwords v1.0.12 github.com/onsi/ginkgo v1.16.4 - github.com/onsi/gomega v1.13.0 + github.com/onsi/gomega v1.14.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6 - github.com/opencontainers/runc v1.0.0 + github.com/opencontainers/runc v1.0.1 github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 github.com/opencontainers/runtime-tools v0.9.0 github.com/opencontainers/selinux v1.8.2 diff --git a/vendor/github.com/containers/buildah/go.sum b/vendor/github.com/containers/buildah/go.sum index 5616f98b5..ce7eb6c74 100644 --- a/vendor/github.com/containers/buildah/go.sum +++ b/vendor/github.com/containers/buildah/go.sum @@ -73,8 +73,9 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3 github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.17 h1:yFHH5bghP9ij5Y34PPaMOE8g//oXZ0uJQeMENVo2zcI= github.com/Microsoft/hcsshim v0.8.17/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim v0.8.20 h1:ZTwcx3NS8n07kPf/JZ1qwU6vnjhVPMUWlXBF8r9UxrE= +github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -136,6 +137,7 @@ github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.6.1/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -223,8 +225,8 @@ github.com/containernetworking/cni v0.8.1 h1:7zpDnQ3T3s4ucOuJ/ZCLrYBxzkg0AELFfII github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containers/common v0.40.2-0.20210707094508-0a4a1906d4b2 h1:2ApmOS9jSnJXuSOkZNEAZ7j0/9i8zjoi67b/UpUjPxY= -github.com/containers/common v0.40.2-0.20210707094508-0a4a1906d4b2/go.mod h1:thow5Jn7O+rP01njI9COQ16L9g/KQ1LcMcYqP2NhYCU= +github.com/containers/common v0.41.1-0.20210721112610-c95d2f794edf h1:z0ciG0ByyJG3WCBpLYd2XLThCC7UBaH7GeSfXY4sAqc= +github.com/containers/common v0.41.1-0.20210721112610-c95d2f794edf/go.mod h1:Ba5YVNCnyX6xDtg1JqEHa2EMVMW5UbHmIyEqsEwpeGE= github.com/containers/image/v5 v5.13.2 h1:AgYunV/9d2fRkrmo23wH2MkqeHolFd6oQCkK+1PpuFA= github.com/containers/image/v5 v5.13.2/go.mod h1:GkWursKDlDcUIT7L7vZf70tADvZCk/Ga0wgS0MuF0ag= github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE= @@ -235,8 +237,8 @@ github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B github.com/containers/ocicrypt v1.1.2 h1:Ez+GAMP/4GLix5Ywo/fL7O0nY771gsBIigiqUm1aXz0= github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/containers/storage v1.32.2/go.mod h1:YIBxxjfXZTi04Ah49sh1uSGfmT1V89+I5i3deRobzQo= -github.com/containers/storage v1.32.5 h1:DXgmyA+oOs7YAzKkEqgC5O8l2UuDGJcwEFbdt49qiak= -github.com/containers/storage v1.32.5/go.mod h1:8/DVVDqniaUlUV0D0q7cEnXK6Bs2uU3FPqNZVPumwEs= +github.com/containers/storage v1.32.6 h1:NqdFRewXO/PYPjgCAScoigZc5QUA21yapSEj6kqD8cw= +github.com/containers/storage v1.32.6/go.mod h1:mdB+b89p+jU8zpzLTVXA0gWMmIo0WrkfGMh1R8O2IQw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= @@ -609,7 +611,6 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= @@ -618,8 +619,8 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= -github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/onsi/gomega v1.14.0 h1:ep6kpPVwmr/nTbklSx2nrLNSIO62DoYAhnPNIMhK8gI= +github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -636,8 +637,9 @@ github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= github.com/opencontainers/runc v1.0.0-rc95/go.mod h1:z+bZxa/+Tz/FmYVWkhUajJdzFeOqjc5vrqskhVyHGUM= -github.com/opencontainers/runc v1.0.0 h1:QOhAQAYUlKeofuyeKdR6ITvOnXLPbEAjPMjz9wCUXcU= github.com/opencontainers/runc v1.0.0/go.mod h1:MU2S3KEB2ZExnhnAQYbwjdYV6HwKtDlNbA2Z2OeNDeA= +github.com/opencontainers/runc v1.0.1 h1:G18PGckGdAm3yVQRWDVQ1rLSLntiniKJ0cNRT2Tm5gs= +github.com/opencontainers/runc v1.0.1/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= diff --git a/vendor/github.com/containers/buildah/imagebuildah/build.go b/vendor/github.com/containers/buildah/imagebuildah/build.go index a315d7f7d..954ef7f8a 100644 --- a/vendor/github.com/containers/buildah/imagebuildah/build.go +++ b/vendor/github.com/containers/buildah/imagebuildah/build.go @@ -39,7 +39,7 @@ const ( ) // Mount is a mountpoint for the build container. -type Mount specs.Mount +type Mount = specs.Mount type BuildOptions = define.BuildOptions diff --git a/vendor/github.com/containers/buildah/imagebuildah/executor.go b/vendor/github.com/containers/buildah/imagebuildah/executor.go index c754ae3c0..606015ba7 100644 --- a/vendor/github.com/containers/buildah/imagebuildah/executor.go +++ b/vendor/github.com/containers/buildah/imagebuildah/executor.go @@ -165,8 +165,7 @@ func NewExecutor(logger *logrus.Logger, store storage.Store, options define.Buil if err != nil { return nil, err } - - transientMounts = append([]Mount{Mount(mount)}, transientMounts...) + transientMounts = append([]Mount{mount}, transientMounts...) } secrets, err := parse.Secrets(options.CommonBuildOpts.Secrets) @@ -569,7 +568,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image // 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 { + for stageIndex, 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 @@ -589,7 +588,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image // FROM instruction uses argument values, // we might not record the right value here. b.baseMap[base] = true - logrus.Debugf("base: %q", base) + logrus.Debugf("base for stage %d: %q", stageIndex, base) } } case "ADD", "COPY": @@ -601,7 +600,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image // not record the right value here. rootfs := strings.TrimPrefix(flag, "--from=") b.rootfsMap[rootfs] = true - logrus.Debugf("rootfs: %q", rootfs) + logrus.Debugf("rootfs needed for COPY in stage %d: %q", stageIndex, rootfs) } } } diff --git a/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go b/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go index be105901b..d3d5cc7c4 100644 --- a/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go +++ b/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go @@ -434,7 +434,7 @@ func (s *StageExecutor) Run(run imagebuilder.Run, config docker.Config) error { Runtime: s.executor.runtime, Args: s.executor.runtimeArgs, NoPivot: os.Getenv("BUILDAH_NOPIVOT") != "", - Mounts: convertMounts(s.executor.transientMounts), + Mounts: append([]Mount{}, s.executor.transientMounts...), Env: config.Env, User: config.User, WorkingDir: config.WorkingDir, @@ -557,13 +557,6 @@ func (s *StageExecutor) prepare(ctx context.Context, from string, initializeIBCo OciDecryptConfig: s.executor.ociDecryptConfig, } - // Check and see if the image is a pseudonym for the end result of a - // previous stage, named by an AS clause in the Dockerfile. - s.executor.stagesLock.Lock() - if asImageFound, ok := s.executor.imageMap[from]; ok { - builderOptions.FromImage = asImageFound - } - s.executor.stagesLock.Unlock() builder, err = buildah.NewBuilder(ctx, s.executor.store, builderOptions) if err != nil { return nil, errors.Wrapf(err, "error creating build container") @@ -684,15 +677,20 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string, // If the base image's name corresponds to the result of an earlier // stage, make sure that stage has finished building an image, and - // substitute that image's ID for the base image's name here. If not, - // then go on assuming that it's just a regular image that's either in - // local storage, or one that we have to pull from a registry. + // substitute that image's ID for the base image's name here and force + // the pull policy to "never" to avoid triggering an error when it's + // set to "always", which doesn't make sense for image IDs. + // If not, then go on assuming that it's just a regular image that's + // either in local storage, or one that we have to pull from a + // registry, subject to the passed-in pull policy. if isStage, err := s.executor.waitForStage(ctx, base, s.stages[:s.index]); isStage && err != nil { return "", nil, err } + pullPolicy := s.executor.pullPolicy s.executor.stagesLock.Lock() if stageImage, isPreviousStage := s.executor.imageMap[base]; isPreviousStage { base = stageImage + pullPolicy = define.PullNever } s.executor.stagesLock.Unlock() @@ -723,7 +721,7 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string, // Create the (first) working container for this stage. Reinitializing // the imagebuilder configuration may alter the list of steps we have, // so take a snapshot of them *after* that. - if _, err := s.prepare(ctx, base, true, true, s.executor.pullPolicy); err != nil { + if _, err := s.prepare(ctx, base, true, true, pullPolicy); err != nil { return "", nil, err } children := stage.Node.Children diff --git a/vendor/github.com/containers/buildah/imagebuildah/util.go b/vendor/github.com/containers/buildah/imagebuildah/util.go index 7519672bf..598e407a8 100644 --- a/vendor/github.com/containers/buildah/imagebuildah/util.go +++ b/vendor/github.com/containers/buildah/imagebuildah/util.go @@ -2,26 +2,11 @@ package imagebuildah import ( "github.com/containers/buildah" - "github.com/opencontainers/runtime-spec/specs-go" ) // InitReexec is a wrapper for buildah.InitReexec(). It should be called at // the start of main(), and if it returns true, main() should return -// immediately. +// successfully immediately. func InitReexec() bool { return buildah.InitReexec() } - -func convertMounts(mounts []Mount) []specs.Mount { - specmounts := []specs.Mount{} - for _, m := range mounts { - s := specs.Mount{ - Destination: m.Destination, - Type: m.Type, - Source: m.Source, - Options: m.Options, - } - specmounts = append(specmounts, s) - } - return specmounts -} diff --git a/vendor/github.com/containers/buildah/install.md b/vendor/github.com/containers/buildah/install.md index 0cec56c75..30ec26cc3 100644 --- a/vendor/github.com/containers/buildah/install.md +++ b/vendor/github.com/containers/buildah/install.md @@ -153,9 +153,7 @@ sudo apt-get -qq -y install buildah ### Kernel Version Requirements To run Buildah on Red Hat Enterprise Linux or CentOS, version 7.4 or higher is required. -On other Linux distributions Buildah requires a kernel version of 4.0 or -higher in order to support the OverlayFS filesystem. The kernel version can be checked -with the 'uname -a' command. +On other Linux distributions Buildah requires a kernel version that supports the OverlayFS and/or fuse-overlayfs filesystem -- you'll need to consult your distribution's documentation to determine a minimum version number. ### runc Requirement diff --git a/vendor/github.com/containers/buildah/pkg/parse/parse.go b/vendor/github.com/containers/buildah/pkg/parse/parse.go index 0a09dd75a..5ba2f51d0 100644 --- a/vendor/github.com/containers/buildah/pkg/parse/parse.go +++ b/vendor/github.com/containers/buildah/pkg/parse/parse.go @@ -15,6 +15,7 @@ import ( "unicode" "github.com/containers/buildah/define" + "github.com/containers/common/pkg/parse" "github.com/containers/image/v5/types" "github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/unshare" @@ -205,13 +206,13 @@ func Volume(volume string) (specs.Mount, error) { if err := validateVolumeMountHostDir(arr[0]); err != nil { return mount, err } - if err := ValidateVolumeCtrDir(arr[1]); err != nil { + if err := parse.ValidateVolumeCtrDir(arr[1]); err != nil { return mount, err } mountOptions := "" if len(arr) > 2 { mountOptions = arr[2] - if _, err := ValidateVolumeOpts(strings.Split(arr[2], ",")); err != nil { + if _, err := parse.ValidateVolumeOpts(strings.Split(arr[2], ",")); err != nil { return mount, err } } @@ -360,7 +361,7 @@ func GetBindMount(args []string) (specs.Mount, error) { if len(kv) == 1 { return newMount, errors.Wrapf(optionArgError, kv[0]) } - if err := ValidateVolumeHostDir(kv[1]); err != nil { + if err := parse.ValidateVolumeHostDir(kv[1]); err != nil { return newMount, err } newMount.Source = kv[1] @@ -369,7 +370,7 @@ func GetBindMount(args []string) (specs.Mount, error) { if len(kv) == 1 { return newMount, errors.Wrapf(optionArgError, kv[0]) } - if err := ValidateVolumeCtrDir(kv[1]); err != nil { + if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return newMount, err } newMount.Destination = kv[1] @@ -391,7 +392,7 @@ func GetBindMount(args []string) (specs.Mount, error) { newMount.Source = newMount.Destination } - opts, err := ValidateVolumeOpts(newMount.Options) + opts, err := parse.ValidateVolumeOpts(newMount.Options) if err != nil { return newMount, err } @@ -433,7 +434,7 @@ func GetTmpfsMount(args []string) (specs.Mount, error) { if len(kv) == 1 { return newMount, errors.Wrapf(optionArgError, kv[0]) } - if err := ValidateVolumeCtrDir(kv[1]); err != nil { + if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return newMount, err } newMount.Destination = kv[1] @@ -452,17 +453,7 @@ func GetTmpfsMount(args []string) (specs.Mount, error) { // ValidateVolumeHostDir validates a volume mount's source directory func ValidateVolumeHostDir(hostDir string) error { - if len(hostDir) == 0 { - return errors.Errorf("host directory cannot be empty") - } - if filepath.IsAbs(hostDir) { - if _, err := os.Stat(hostDir); err != nil { - return errors.WithStack(err) - } - } - // If hostDir is not an absolute path, that means the user wants to create a - // named volume. This will be done later on in the code. - return nil + return parse.ValidateVolumeHostDir(hostDir) } // validates the host path of buildah --volume @@ -478,75 +469,12 @@ func validateVolumeMountHostDir(hostDir string) error { // ValidateVolumeCtrDir validates a volume mount's destination directory. func ValidateVolumeCtrDir(ctrDir string) error { - if len(ctrDir) == 0 { - return errors.Errorf("container directory cannot be empty") - } - if !filepath.IsAbs(ctrDir) { - return errors.Errorf("invalid container path %q, must be an absolute path", ctrDir) - } - return nil + return parse.ValidateVolumeCtrDir(ctrDir) } // ValidateVolumeOpts validates a volume's options func ValidateVolumeOpts(options []string) ([]string, error) { - var foundRootPropagation, foundRWRO, foundLabelChange, bindType, foundExec, foundDev, foundSuid, foundChown int - finalOpts := make([]string, 0, len(options)) - for _, opt := range options { - switch opt { - case "noexec", "exec": - foundExec++ - if foundExec > 1 { - return nil, errors.Errorf("invalid options %q, can only specify 1 'noexec' or 'exec' option", strings.Join(options, ", ")) - } - case "nodev", "dev": - foundDev++ - if foundDev > 1 { - return nil, errors.Errorf("invalid options %q, can only specify 1 'nodev' or 'dev' option", strings.Join(options, ", ")) - } - case "nosuid", "suid": - foundSuid++ - if foundSuid > 1 { - return nil, errors.Errorf("invalid options %q, can only specify 1 'nosuid' or 'suid' option", strings.Join(options, ", ")) - } - case "rw", "ro": - foundRWRO++ - if foundRWRO > 1 { - return nil, errors.Errorf("invalid options %q, can only specify 1 'rw' or 'ro' option", strings.Join(options, ", ")) - } - case "z", "Z", "O": - foundLabelChange++ - if foundLabelChange > 1 { - return nil, errors.Errorf("invalid options %q, can only specify 1 'z', 'Z', or 'O' option", strings.Join(options, ", ")) - } - case "U": - foundChown++ - if foundChown > 1 { - return nil, errors.Errorf("invalid options %q, can only specify 1 'U' option", strings.Join(options, ", ")) - } - case "private", "rprivate", "shared", "rshared", "slave", "rslave", "unbindable", "runbindable": - foundRootPropagation++ - if foundRootPropagation > 1 { - return nil, errors.Errorf("invalid options %q, can only specify 1 '[r]shared', '[r]private', '[r]slave' or '[r]unbindable' option", strings.Join(options, ", ")) - } - case "bind", "rbind": - bindType++ - if bindType > 1 { - return nil, errors.Errorf("invalid options %q, can only specify 1 '[r]bind' option", strings.Join(options, ", ")) - } - case "cached", "delegated": - // The discarded ops are OS X specific volume options - // introduced in a recent Docker version. - // They have no meaning on Linux, so here we silently - // drop them. This matches Docker's behavior (the options - // are intended to be always safe to use, even not on OS - // X). - continue - default: - return nil, errors.Errorf("invalid option type %q", opt) - } - finalOpts = append(finalOpts, opt) - } - return finalOpts, nil + return parse.ValidateVolumeOpts(options) } // validateExtraHost validates that the specified string is a valid extrahost and returns it. @@ -601,7 +529,7 @@ func SystemContextFromOptions(c *cobra.Command) (*types.SystemContext, error) { creds, err := c.Flags().GetString("creds") if err == nil && c.Flag("creds").Changed { var err error - ctx.DockerAuthConfig, err = getDockerAuth(creds) + ctx.DockerAuthConfig, err = AuthConfig(creds) if err != nil { return nil, err } @@ -734,7 +662,9 @@ func parseCreds(creds string) (string, string) { return up[0], up[1] } -func getDockerAuth(creds string) (*types.DockerAuthConfig, error) { +// AuthConfig parses the creds in format [username[:password] into an auth +// config. +func AuthConfig(creds string) (*types.DockerAuthConfig, error) { username, password := parseCreds(creds) if username == "" { fmt.Print("Username: ") diff --git a/vendor/github.com/containers/common/libimage/filters.go b/vendor/github.com/containers/common/libimage/filters.go index eae18fd9c..0cc5cc311 100644 --- a/vendor/github.com/containers/common/libimage/filters.go +++ b/vendor/github.com/containers/common/libimage/filters.go @@ -88,7 +88,7 @@ func (r *Runtime) compileImageFilters(ctx context.Context, filters []string) ([] if err != nil { return nil, errors.Wrapf(err, "non-boolean value %q for dangling filter", value) } - filterFuncs = append(filterFuncs, filterDangling(dangling)) + filterFuncs = append(filterFuncs, filterDangling(ctx, dangling)) case "id": filterFuncs = append(filterFuncs, filterID(value)) @@ -201,9 +201,13 @@ func filterContainers(value bool) filterFunc { } // filterDangling creates a dangling filter for matching the specified value. -func filterDangling(value bool) filterFunc { +func filterDangling(ctx context.Context, value bool) filterFunc { return func(img *Image) (bool, error) { - return img.IsDangling() == value, nil + isDangling, err := img.IsDangling(ctx) + if err != nil { + return false, err + } + return isDangling == value, nil } } diff --git a/vendor/github.com/containers/common/libimage/image.go b/vendor/github.com/containers/common/libimage/image.go index 19b929dc7..5b060a185 100644 --- a/vendor/github.com/containers/common/libimage/image.go +++ b/vendor/github.com/containers/common/libimage/image.go @@ -121,24 +121,29 @@ func (i *Image) IsReadOnly() bool { return i.storageImage.ReadOnly } -// IsDangling returns true if the image is dangling. An image is considered -// dangling if no names are associated with it in the containers storage. -func (i *Image) IsDangling() bool { - return len(i.Names()) == 0 +// IsDangling returns true if the image is dangling, that is an untagged image +// without children. +func (i *Image) IsDangling(ctx context.Context) (bool, error) { + if len(i.Names()) > 0 { + return false, nil + } + children, err := i.getChildren(ctx, false) + if err != nil { + return false, err + } + return len(children) == 0, nil } // IsIntermediate returns true if the image is an intermediate image, that is -// a dangling image without children. +// an untagged image with children. func (i *Image) IsIntermediate(ctx context.Context) (bool, error) { - // If the image has tags, it's not an intermediate one. - if !i.IsDangling() { + if len(i.Names()) > 0 { return false, nil } children, err := i.getChildren(ctx, false) if err != nil { return false, err } - // No tags, no children -> intermediate! return len(children) != 0, nil } @@ -271,7 +276,7 @@ type RemoveImageReport struct { // remove removes the image along with all dangling parent images that no other // image depends on. The image must not be set read-only and not be used by -// containers. +// containers. Returns IDs of removed/untagged images in order. // // If the image is used by containers return storage.ErrImageUsedByContainer. // Use force to remove these containers. @@ -282,7 +287,12 @@ type RemoveImageReport struct { // // This function is internal. Users of libimage should always use // `(*Runtime).RemoveImages()`. -func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, referencedBy string, options *RemoveImagesOptions) error { +func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, referencedBy string, options *RemoveImagesOptions) ([]string, error) { + processedIDs := []string{} + return i.removeRecursive(ctx, rmMap, processedIDs, referencedBy, options) +} + +func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveImageReport, processedIDs []string, referencedBy string, options *RemoveImagesOptions) ([]string, error) { // If referencedBy is empty, the image is considered to be removed via // `image remove --all` which alters the logic below. @@ -294,7 +304,7 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, logrus.Debugf("Removing image %s", i.ID()) if i.IsReadOnly() { - return errors.Errorf("cannot remove read-only image %q", i.ID()) + return processedIDs, errors.Errorf("cannot remove read-only image %q", i.ID()) } if i.runtime.eventChannel != nil { @@ -306,7 +316,7 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, if exists { // If the image has already been removed, we're done. if report.Removed { - return nil + return processedIDs, nil } } else { report = &RemoveImageReport{ID: i.ID()} @@ -333,7 +343,7 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, if options.WithSize { size, err := i.Size() if handleError(err) != nil { - return err + return processedIDs, err } report.Size = size } @@ -354,18 +364,18 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, byDigest := strings.HasPrefix(referencedBy, "sha256:") if !options.Force { if byID && numNames > 1 { - return errors.Errorf("unable to delete image %q by ID with more than one tag (%s): please force removal", i.ID(), i.Names()) + return processedIDs, errors.Errorf("unable to delete image %q by ID with more than one tag (%s): please force removal", i.ID(), i.Names()) } else if byDigest && numNames > 1 { // FIXME - Docker will remove the digest but containers storage // does not support that yet, so our hands are tied. - return errors.Errorf("unable to delete image %q by digest with more than one tag (%s): please force removal", i.ID(), i.Names()) + return processedIDs, errors.Errorf("unable to delete image %q by digest with more than one tag (%s): please force removal", i.ID(), i.Names()) } } // Only try to untag if we know it's not an ID or digest. if !byID && !byDigest { if err := i.Untag(referencedBy); handleError(err) != nil { - return err + return processedIDs, err } report.Untagged = append(report.Untagged, referencedBy) @@ -374,14 +384,15 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, } } + processedIDs = append(processedIDs, i.ID()) if skipRemove { - return nil + return processedIDs, nil } // Perform the actual removal. First, remove containers if needed. if options.Force { if err := i.removeContainers(options.RemoveContainerFunc); err != nil { - return err + return processedIDs, err } } @@ -407,7 +418,7 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, } if _, err := i.runtime.store.DeleteImage(i.ID(), true); handleError(err) != nil { - return err + return processedIDs, err } report.Untagged = append(report.Untagged, i.Names()...) @@ -417,27 +428,24 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, // Check if can remove the parent image. if parent == nil { - return nil + return processedIDs, nil } - if !parent.IsDangling() { - return nil - } - - // If the image has siblings, we don't remove the parent. - hasSiblings, err := parent.HasChildren(ctx) + // Only remove the parent if it's dangling, that is being untagged and + // without children. + danglingParent, err := parent.IsDangling(ctx) if err != nil { // See Podman commit fd9dd7065d44: we need to // be tolerant toward corrupted images. logrus.Warnf("error determining if an image is a parent: %v, ignoring the error", err) - hasSiblings = false + danglingParent = false } - if hasSiblings { - return nil + if !danglingParent { + return processedIDs, nil } // Recurse into removing the parent. - return parent.remove(ctx, rmMap, "", options) + return parent.removeRecursive(ctx, rmMap, processedIDs, "", options) } // Tag the image with the specified name and store it in the local containers diff --git a/vendor/github.com/containers/common/libimage/layer_tree.go b/vendor/github.com/containers/common/libimage/layer_tree.go index 4195b43c0..05f21531b 100644 --- a/vendor/github.com/containers/common/libimage/layer_tree.go +++ b/vendor/github.com/containers/common/libimage/layer_tree.go @@ -15,6 +15,9 @@ type layerTree struct { // ociCache is a cache for Image.ID -> OCI Image. Translations are done // on-demand. ociCache map[string]*ociv1.Image + // emptyImages do not have any top-layer so we cannot create a + // *layerNode for them. + emptyImages []*Image } // node returns a layerNode for the specified layerID. @@ -105,6 +108,7 @@ func (r *Runtime) layerTree() (*layerTree, error) { img := images[i] // do not leak loop variable outside the scope topLayer := img.TopLayer() if topLayer == "" { + tree.emptyImages = append(tree.emptyImages, img) continue } node, exists := tree.nodes[topLayer] @@ -126,22 +130,13 @@ func (r *Runtime) layerTree() (*layerTree, error) { // either the same top layer as parent or parent being the true parent layer. // Furthermore, the history of the parent and child images must match with the // parent having one history item less. If all is true, all images are -// returned. Otherwise, the first image is returned. +// returned. Otherwise, the first image is returned. Note that manifest lists +// do not have children. func (t *layerTree) children(ctx context.Context, parent *Image, all bool) ([]*Image, error) { if parent.TopLayer() == "" { - return nil, nil - } - - var children []*Image - - parentNode, exists := t.nodes[parent.TopLayer()] - if !exists { - // Note: erroring out in this case has turned out having been a - // mistake. Users may not be able to recover, so we're now - // throwing a warning to guide them to resolve the issue and - // turn the errors non-fatal. - logrus.Warnf("Layer %s not found in layer tree. The storage may be corrupted, consider running `podman system reset`.", parent.TopLayer()) - return children, nil + if isManifestList, _ := parent.IsManifestList(ctx); isManifestList { + return nil, nil + } } parentID := parent.ID() @@ -163,6 +158,38 @@ func (t *layerTree) children(ctx context.Context, parent *Image, all bool) ([]*I return areParentAndChild(parentOCI, childOCI), nil } + var children []*Image + + // Empty images are special in that they do not have any physical layer + // but yet can have a parent-child relation. Hence, compare the + // "parent" image to all other known empty images. + if parent.TopLayer() == "" { + for i := range t.emptyImages { + empty := t.emptyImages[i] + isParent, err := checkParent(empty) + if err != nil { + return nil, err + } + if isParent { + children = append(children, empty) + if !all { + break + } + } + } + return children, nil + } + + parentNode, exists := t.nodes[parent.TopLayer()] + if !exists { + // Note: erroring out in this case has turned out having been a + // mistake. Users may not be able to recover, so we're now + // throwing a warning to guide them to resolve the issue and + // turn the errors non-fatal. + logrus.Warnf("Layer %s not found in layer tree. The storage may be corrupted, consider running `podman system reset`.", parent.TopLayer()) + return children, nil + } + // addChildrenFrom adds child images of parent to children. Returns // true if any image is a child of parent. addChildrenFromNode := func(node *layerNode) (bool, error) { @@ -204,8 +231,37 @@ func (t *layerTree) children(ctx context.Context, parent *Image, all bool) ([]*I } // parent returns the parent image or nil if no parent image could be found. +// Note that manifest lists do not have parents. func (t *layerTree) parent(ctx context.Context, child *Image) (*Image, error) { if child.TopLayer() == "" { + if isManifestList, _ := child.IsManifestList(ctx); isManifestList { + return nil, nil + } + } + + childID := child.ID() + childOCI, err := t.toOCI(ctx, child) + if err != nil { + return nil, err + } + + // Empty images are special in that they do not have any physical layer + // but yet can have a parent-child relation. Hence, compare the + // "child" image to all other known empty images. + if child.TopLayer() == "" { + for _, empty := range t.emptyImages { + if childID == empty.ID() { + continue + } + emptyOCI, err := t.toOCI(ctx, empty) + if err != nil { + return nil, err + } + // History check. + if areParentAndChild(emptyOCI, childOCI) { + return empty, nil + } + } return nil, nil } @@ -219,14 +275,8 @@ func (t *layerTree) parent(ctx context.Context, child *Image) (*Image, error) { return nil, nil } - childOCI, err := t.toOCI(ctx, child) - if err != nil { - return nil, err - } - // Check images from the parent node (i.e., parent layer) and images // with the same layer (i.e., same top layer). - childID := child.ID() images := node.images if node.parent != nil { images = append(images, node.parent.images...) diff --git a/vendor/github.com/containers/common/libimage/pull.go b/vendor/github.com/containers/common/libimage/pull.go index 71cec021b..1a6ad1ce2 100644 --- a/vendor/github.com/containers/common/libimage/pull.go +++ b/vendor/github.com/containers/common/libimage/pull.go @@ -10,6 +10,7 @@ import ( "github.com/containers/common/pkg/config" registryTransport "github.com/containers/image/v5/docker" dockerArchiveTransport "github.com/containers/image/v5/docker/archive" + dockerDaemonTransport "github.com/containers/image/v5/docker/daemon" "github.com/containers/image/v5/docker/reference" ociArchiveTransport "github.com/containers/image/v5/oci/archive" ociTransport "github.com/containers/image/v5/oci/layout" @@ -55,6 +56,13 @@ func (r *Runtime) Pull(ctx context.Context, name string, pullPolicy config.PullP var possiblyUnqualifiedName string // used for short-name resolution ref, err := alltransports.ParseImageName(name) if err != nil { + // Check whether `name` points to a transport. If so, we + // return the error. Otherwise we assume that `name` refers to + // an image on a registry (e.g., "fedora"). + if alltransports.TransportFromImageName(name) != nil { + return nil, err + } + // If the image clearly refers to a local one, we can look it up directly. // In fact, we need to since they are not parseable. if strings.HasPrefix(name, "sha256:") || (len(name) == 64 && !strings.ContainsAny(name, "/.:@")) { @@ -169,6 +177,15 @@ func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference, var storageName, imageName string switch ref.Transport().Name() { + case dockerDaemonTransport.Transport.Name(): + // Normalize to docker.io if needed (see containers/podman/issues/10998). + named, err := reference.ParseNormalizedNamed(ref.StringWithinTransport()) + if err != nil { + return nil, err + } + imageName = named.String() + storageName = imageName + case ociTransport.Transport.Name(): split := strings.SplitN(ref.StringWithinTransport(), ":", 2) storageName = toLocalImageName(split[0]) diff --git a/vendor/github.com/containers/common/libimage/runtime.go b/vendor/github.com/containers/common/libimage/runtime.go index 1fd2973cb..26a04dad5 100644 --- a/vendor/github.com/containers/common/libimage/runtime.go +++ b/vendor/github.com/containers/common/libimage/runtime.go @@ -3,7 +3,6 @@ package libimage import ( "context" "os" - "path/filepath" "strings" "github.com/containers/image/v5/docker/reference" @@ -94,10 +93,6 @@ func RuntimeFromStore(store storage.Store, options *RuntimeOptions) (*Runtime, e setRegistriesConfPath(&systemContext) - if systemContext.BlobInfoCacheDir == "" { - systemContext.BlobInfoCacheDir = filepath.Join(store.GraphRoot(), "cache") - } - return &Runtime{ store: store, systemContext: systemContext, @@ -592,11 +587,10 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem rmErrors = append(rmErrors, err) } - orderedIDs := []string{} // determinism and relative order deleteMap := make(map[string]*deleteMe) // ID -> deleteMe - + toDelete := []string{} // Look up images in the local containers storage and fill out - // orderedIDs and the deleteMap. + // toDelete and the deleteMap. switch { case len(names) > 0: // Look up the images one-by-one. That allows for removing @@ -610,15 +604,12 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem } dm, exists := deleteMap[img.ID()] if !exists { - orderedIDs = append(orderedIDs, img.ID()) + toDelete = append(toDelete, img.ID()) dm = &deleteMe{image: img} deleteMap[img.ID()] = dm } dm.referencedBy = append(dm.referencedBy, resolvedName) } - if len(orderedIDs) == 0 { - return nil, rmErrors - } default: filteredImages, err := r.ListImages(ctx, nil, &ListImagesOptions{Filters: options.Filters}) @@ -627,14 +618,21 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem return nil, rmErrors } for _, img := range filteredImages { - orderedIDs = append(orderedIDs, img.ID()) + toDelete = append(toDelete, img.ID()) deleteMap[img.ID()] = &deleteMe{image: img} } } + // Return early if there's no image to delete. + if len(deleteMap) == 0 { + return nil, rmErrors + } + // Now remove the images in the given order. rmMap := make(map[string]*RemoveImageReport) - for _, id := range orderedIDs { + orderedIDs := []string{} + visitedIDs := make(map[string]bool) + for _, id := range toDelete { del, exists := deleteMap[id] if !exists { appendError(errors.Errorf("internal error: ID %s not in found in image-deletion map", id)) @@ -644,9 +642,17 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem del.referencedBy = []string{""} } for _, ref := range del.referencedBy { - if err := del.image.remove(ctx, rmMap, ref, options); err != nil { + processedIDs, err := del.image.remove(ctx, rmMap, ref, options) + if err != nil { appendError(err) - continue + } + // NOTE: make sure to add given ID only once to orderedIDs. + for _, id := range processedIDs { + if visited := visitedIDs[id]; visited { + continue + } + orderedIDs = append(orderedIDs, id) + visitedIDs[id] = true } } } diff --git a/vendor/modules.txt b/vendor/modules.txt index 337d85442..4ded74e36 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -77,7 +77,7 @@ github.com/containernetworking/plugins/pkg/utils/hwaddr github.com/containernetworking/plugins/pkg/utils/sysctl github.com/containernetworking/plugins/plugins/ipam/host-local/backend github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator -# github.com/containers/buildah v1.21.1-0.20210707133512-2eb97b499d74 +# github.com/containers/buildah v1.21.1-0.20210721171232-54cafea4c933 github.com/containers/buildah github.com/containers/buildah/bind github.com/containers/buildah/chroot @@ -93,7 +93,7 @@ github.com/containers/buildah/pkg/overlay github.com/containers/buildah/pkg/parse github.com/containers/buildah/pkg/rusage github.com/containers/buildah/util -# github.com/containers/common v0.41.1-0.20210716140645-ffcfe1ff6e70 +# github.com/containers/common v0.41.1-0.20210721172332-291287e9d060 github.com/containers/common/libimage github.com/containers/common/libimage/manifests github.com/containers/common/pkg/apparmor |