diff options
-rw-r--r-- | .cirrus.yml | 12 | ||||
-rwxr-xr-x | API.md | 4 | ||||
-rw-r--r-- | cmd/podman/images_prune.go | 29 | ||||
-rw-r--r-- | cmd/podman/varlink/io.podman.varlink | 2 | ||||
-rw-r--r-- | completions/bash/podman | 2 | ||||
-rwxr-xr-x | contrib/cirrus/integration_test.sh | 6 | ||||
-rw-r--r-- | contrib/cirrus/lib.sh | 2 | ||||
-rwxr-xr-x | contrib/cirrus/setup_environment.sh | 3 | ||||
-rwxr-xr-x | contrib/cirrus/system_test.sh | 7 | ||||
-rwxr-xr-x | contrib/cirrus/unit_test.sh | 8 | ||||
-rw-r--r-- | docs/podman-image-prune.1.md | 21 | ||||
-rw-r--r-- | docs/tutorials/podman_tutorial.md | 11 | ||||
-rw-r--r-- | libpod/adapter/runtime.go | 5 | ||||
-rw-r--r-- | libpod/adapter/runtime_remote.go | 3 | ||||
-rw-r--r-- | libpod/image/prune.go | 39 | ||||
-rw-r--r-- | pkg/apparmor/apparmor_linux.go | 13 | ||||
-rw-r--r-- | pkg/varlinkapi/images.go | 17 | ||||
-rw-r--r-- | test/e2e/prune_test.go | 7 |
18 files changed, 120 insertions, 71 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 3192d15ae..d3a9eea40 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -27,12 +27,12 @@ env: #### #### Cache-image names to test with ### - FEDORA_CACHE_IMAGE_NAME: "fedora-29-libpod-9afa57a9" - PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-28-libpod-9afa57a9" - UBUNTU_CACHE_IMAGE_NAME: "ubuntu-18-libpod-9afa57a9" - RHEL_CACHE_IMAGE_NAME: "rhel-8-notready" - PRIOR_RHEL_CACHE_IMAGE_NAME: "rhel-7-notready" - CENTOS_CACHE_IMAGE_NAME: "centos-7-notready" + FEDORA_CACHE_IMAGE_NAME: "fedora-29-libpod-7f4cd1f7" + PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-28-libpod-7f4cd1f7" + UBUNTU_CACHE_IMAGE_NAME: "ubuntu-18-libpod-7f4cd1f7" + # RHEL_CACHE_IMAGE_NAME: "rhel-8-notready" + # PRIOR_RHEL_CACHE_IMAGE_NAME: "rhel-7-libpod-7f4cd1f7" + # CENTOS_CACHE_IMAGE_NAME: "centos-7-notready" #### #### Variables for composing new cache-images (used in PR testing) from @@ -65,7 +65,7 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in [func ImageExists(name: string) int](#ImageExists) -[func ImagesPrune() []string](#ImagesPrune) +[func ImagesPrune(all: bool) []string](#ImagesPrune) [func ImportImage(source: string, reference: string, message: string, changes: []string) string](#ImportImage) @@ -580,7 +580,7 @@ $ varlink call -m unix:/run/podman/io.podman/io.podman.ImageExists '{"name": "im ### <a name="ImagesPrune"></a>func ImagesPrune <div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> -method ImagesPrune() [[]string](#[]string)</div> +method ImagesPrune(all: [bool](https://godoc.org/builtin#bool)) [[]string](#[]string)</div> ImagesPrune removes all unused images from the local store. Upon successful pruning, the IDs of the removed images are returned. ### <a name="ImportImage"></a>func ImportImage diff --git a/cmd/podman/images_prune.go b/cmd/podman/images_prune.go index 06879e02d..aef387732 100644 --- a/cmd/podman/images_prune.go +++ b/cmd/podman/images_prune.go @@ -2,7 +2,7 @@ package main import ( "fmt" - "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/libpod/adapter" "github.com/pkg/errors" "github.com/urfave/cli" ) @@ -13,33 +13,36 @@ var ( Removes all unnamed images from local storage ` - + pruneImageFlags = []cli.Flag{ + cli.BoolFlag{ + Name: "all, a", + Usage: "remove all unused images, not just dangling ones", + }, + } pruneImagesCommand = cli.Command{ Name: "prune", Usage: "Remove unused images", Description: pruneImagesDescription, Action: pruneImagesCmd, OnUsageError: usageErrorHandler, + Flags: pruneImageFlags, } ) func pruneImagesCmd(c *cli.Context) error { - runtime, err := libpodruntime.GetRuntime(c) + runtime, err := adapter.GetRuntime(c) if err != nil { return errors.Wrapf(err, "could not get runtime") } defer runtime.Shutdown(false) - pruneImages, err := runtime.ImageRuntime().GetPruneImages() - if err != nil { - return err - } - - for _, i := range pruneImages { - if err := i.Remove(true); err != nil { - return errors.Wrapf(err, "failed to remove %s", i.ID()) + // Call prune; if any cids are returned, print them and then + // return err in case an error also came up + pruneCids, err := runtime.PruneImages(c.Bool("all")) + if len(pruneCids) > 0 { + for _, cid := range pruneCids { + fmt.Println(cid) } - fmt.Println(i.ID()) } - return nil + return err } diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index 86c3eb7ff..80f0bbdfe 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -1019,7 +1019,7 @@ method UnmountContainer(name: string, force: bool) -> () # ImagesPrune removes all unused images from the local store. Upon successful pruning, # the IDs of the removed images are returned. -method ImagesPrune() -> (pruned: []string) +method ImagesPrune(all: bool) -> (pruned: []string) # This function is not implemented yet. method ListContainerPorts(name: string) -> (notimplemented: NotImplemented) diff --git a/completions/bash/podman b/completions/bash/podman index 08891563c..9ef1d1a0d 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -2459,6 +2459,8 @@ _podman_images_prune() { " local boolean_options=" + -a + --all -h --help " diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh index 627864f47..58c8af289 100755 --- a/contrib/cirrus/integration_test.sh +++ b/contrib/cirrus/integration_test.sh @@ -17,9 +17,9 @@ set -x cd "$GOSRC" case "${OS_RELEASE_ID}-${OS_RELEASE_VER}" in ubuntu-18) - make install PREFIX=/usr ETCDIR=/etc "BUILDTAGS=$BUILDTAGS" - make test-binaries "BUILDTAGS=$BUILDTAGS" - SKIP_USERNS=1 make localintegration "BUILDTAGS=$BUILDTAGS" + make install PREFIX=/usr ETCDIR=/etc + make test-binaries + SKIP_USERNS=1 make localintegration ;; fedora-29) ;& # Continue to the next item fedora-28) ;& diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh index 32b2c91a5..39e6c7699 100644 --- a/contrib/cirrus/lib.sh +++ b/contrib/cirrus/lib.sh @@ -199,7 +199,7 @@ install_runc_from_git(){ cd "$DEST" ooe.sh git fetch origin --tags ooe.sh git checkout -q "$RUNC_COMMIT" - ooe.sh make static BUILDTAGS="seccomp selinux" + ooe.sh make static BUILDTAGS="seccomp apparmor selinux" sudo install -m 755 runc /usr/bin/runc cd $wd } diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index bcfe7e396..838f3c3f3 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -57,7 +57,6 @@ then ubuntu-18) # Always install runc on Ubuntu install_runc_from_git - envstr='export BUILDTAGS="seccomp $($GOSRC/hack/btrfs_tag.sh) $($GOSRC/hack/btrfs_installed_tag.sh) $($GOSRC/hack/ostree_tag.sh) varlink exclude_graphdriver_devicemapper"' ;; fedora-29) ;& # Continue to the next item fedora-28) @@ -67,11 +66,9 @@ then ;& # Continue to the next item centos-7) ;& rhel-7) - envstr='unset BUILDTAGS' # Use default from Makefile ;; *) bad_os_id_ver ;; esac - X=$(echo "$envstr" | tee -a "$HOME/$ENVLIB") && eval "$X" && echo "$X" # Do the same for golang env. vars go env | while read envline diff --git a/contrib/cirrus/system_test.sh b/contrib/cirrus/system_test.sh index 66974f8c6..cb179407a 100755 --- a/contrib/cirrus/system_test.sh +++ b/contrib/cirrus/system_test.sh @@ -15,12 +15,9 @@ set -x cd "$GOSRC" case "${OS_RELEASE_ID}-${OS_RELEASE_VER}" in - ubuntu-18) - make install.tools "BUILDTAGS=$BUILDTAGS" - make "BUILDTAGS=$BUILDTAGS" - make test-binaries "BUILDTAGS=$BUILDTAGS" - ;; + ubuntu-18) ;& # Continue to the next item fedora-28) ;& + fedora-29) ;& centos-7) ;& rhel-7) make install.tools diff --git a/contrib/cirrus/unit_test.sh b/contrib/cirrus/unit_test.sh index 15403b7a7..fd9e82509 100755 --- a/contrib/cirrus/unit_test.sh +++ b/contrib/cirrus/unit_test.sh @@ -16,12 +16,8 @@ clean_env set -x cd "$GOSRC" case "${OS_RELEASE_ID}-${OS_RELEASE_VER}" in - ubuntu-18) - make install.tools "BUILDTAGS=$BUILDTAGS" - make localunit "BUILDTAGS=$BUILDTAGS" - make "BUILDTAGS=$BUILDTAGS" - ;; - fedora-29) ;& # Continue to the next item + ubuntu-18) ;& # Continue to the next item + fedora-29) ;& fedora-28) ;& centos-7) ;& rhel-7) diff --git a/docs/podman-image-prune.1.md b/docs/podman-image-prune.1.md index db76b26e0..df912c380 100644 --- a/docs/podman-image-prune.1.md +++ b/docs/podman-image-prune.1.md @@ -6,23 +6,38 @@ podman-image-prune - Remove all unused images # SYNOPSIS **podman image prune** +[**-a**|**--all**] [**-h**|**--help**] # DESCRIPTION -**podman image prune** removes all unused images from local storage. An unused image -is defined as an image that does not have any containers based on it. +**podman image prune** removes all dangling images from local storage. With the `all` option, +you can delete all unused images. Unused images are dangling images as well as any image that +does not have any containers based on it. + +## OPTIONS +**--all, -a** + +Remove dangling images and images that have no associated containers. ## Examples ## -Remove all unused images from local storage +Remove all dangling images from local storage ``` $ sudo podman image prune f3e20dc537fb04cb51672a5cb6fdf2292e61d411315549391a0d1f64e4e3097e 324a7a3b2e0135f4226ffdd473e4099fd9e477a74230cdc35de69e84c0f9d907 +``` + +Remove all unused images from local storage +``` +$ sudo podman image prune -a +f3e20dc537fb04cb51672a5cb6fdf2292e61d411315549391a0d1f64e4e3097e +324a7a3b2e0135f4226ffdd473e4099fd9e477a74230cdc35de69e84c0f9d907 6125002719feb1ddf3030acab1df6156da7ce0e78e571e9b6e9c250424d6220c 91e732da5657264c6f4641b8d0c4001c218ae6c1adb9dcef33ad00cafd37d8b6 e4e5109420323221f170627c138817770fb64832da7d8fe2babd863148287fca 77a57fa8285e9656dbb7b23d9efa837a106957409ddd702f995605af27a45ebe + ``` ## SEE ALSO diff --git a/docs/tutorials/podman_tutorial.md b/docs/tutorials/podman_tutorial.md index 2b938319f..5017e61cd 100644 --- a/docs/tutorials/podman_tutorial.md +++ b/docs/tutorials/podman_tutorial.md @@ -14,6 +14,17 @@ Fedora 27 and later provide Podman via the package manager. sudo dnf install -y podman ``` +*Optional*: If you've already installed podman on Fedora and you're feeling +adventerous, you can test the very latest podman in Fedora's `updates-testing` +repository before it goes out to all Fedora users. +```console +sudo yum distro-sync --enablerepo=updates-testing podman +``` + +If you use a newer podman package from Fedora's `updates-testing`, we would +appreciate your `+1` feedback in [Bodhi, Fedora's update management +system](https://bodhi.fedoraproject.org/updates/?packages=podman). + ## Install Podman on Fedora from Source Many of the basic components to run Podman are readily available from the Fedora RPM repositories. In this section, we will help you install all the runtime and build dependencies for Podman, diff --git a/libpod/adapter/runtime.go b/libpod/adapter/runtime.go index 1f3599082..f4961437e 100644 --- a/libpod/adapter/runtime.go +++ b/libpod/adapter/runtime.go @@ -99,3 +99,8 @@ func (r *LocalRuntime) LookupContainer(idOrName string) (*Container, error) { } return &Container{ctr}, nil } + +// PruneImages is wrapper into PruneImages within the image pkg +func (r *LocalRuntime) PruneImages(all bool) ([]string, error) { + return r.ImageRuntime().PruneImages(all) +} diff --git a/libpod/adapter/runtime_remote.go b/libpod/adapter/runtime_remote.go index 7189348bc..f184ce0a9 100644 --- a/libpod/adapter/runtime_remote.go +++ b/libpod/adapter/runtime_remote.go @@ -320,3 +320,6 @@ func (r *LocalRuntime) Config(name string) *libpod.ContainerConfig { return &data } +func (r *LocalRuntime) PruneImages(all bool) ([]string, error) { + return iopodman.ImagesPrune().Call(r.Conn, all) +} diff --git a/libpod/image/prune.go b/libpod/image/prune.go index 6a1f160d5..8602c222c 100644 --- a/libpod/image/prune.go +++ b/libpod/image/prune.go @@ -1,9 +1,11 @@ package image +import "github.com/pkg/errors" + // GetPruneImages returns a slice of images that have no names/unused -func (ir *Runtime) GetPruneImages() ([]*Image, error) { +func (ir *Runtime) GetPruneImages(all bool) ([]*Image, error) { var ( - unamedImages []*Image + pruneImages []*Image ) allImages, err := ir.GetImages() if err != nil { @@ -11,16 +13,35 @@ func (ir *Runtime) GetPruneImages() ([]*Image, error) { } for _, i := range allImages { if len(i.Names()) == 0 { - unamedImages = append(unamedImages, i) + pruneImages = append(pruneImages, i) continue } - containers, err := i.Containers() - if err != nil { - return nil, err + if all { + containers, err := i.Containers() + if err != nil { + return nil, err + } + if len(containers) < 1 { + pruneImages = append(pruneImages, i) + } } - if len(containers) < 1 { - unamedImages = append(unamedImages, i) + } + return pruneImages, nil +} + +// PruneImages prunes dangling and optionally all unused images from the local +// image store +func (ir *Runtime) PruneImages(all bool) ([]string, error) { + var prunedCids []string + pruneImages, err := ir.GetPruneImages(all) + if err != nil { + return nil, errors.Wrap(err, "unable to get images to prune") + } + for _, p := range pruneImages { + if err := p.Remove(true); err != nil { + return nil, errors.Wrap(err, "failed to prune image") } + prunedCids = append(prunedCids, p.ID()) } - return unamedImages, nil + return prunedCids, nil } diff --git a/pkg/apparmor/apparmor_linux.go b/pkg/apparmor/apparmor_linux.go index 0787b3fa5..2c5022c1f 100644 --- a/pkg/apparmor/apparmor_linux.go +++ b/pkg/apparmor/apparmor_linux.go @@ -214,8 +214,15 @@ func CheckProfileAndLoadDefault(name string) (string, error) { return name, nil } - if name != "" && rootless.IsRootless() { - return "", errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name) + // AppArmor is not supported in rootless mode as it requires root + // privileges. Return an error in case a specific profile is specified. + if rootless.IsRootless() { + if name != "" { + return "", errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name) + } else { + logrus.Debug("skipping loading default AppArmor profile (rootless mode)") + return "", nil + } } if name != "" && !runcaa.IsEnabled() { @@ -230,7 +237,7 @@ func CheckProfileAndLoadDefault(name string) (string, error) { return "", err } if !isLoaded { - return "", fmt.Errorf("AppArmor profile %q specified but not loaded") + return "", fmt.Errorf("AppArmor profile %q specified but not loaded", name) } return name, nil } diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go index 744f031c0..d6a9b7301 100644 --- a/pkg/varlinkapi/images.go +++ b/pkg/varlinkapi/images.go @@ -627,19 +627,10 @@ func (i *LibpodAPI) ContainerRunlabel(call iopodman.VarlinkCall, input iopodman. } // ImagesPrune .... -func (i *LibpodAPI) ImagesPrune(call iopodman.VarlinkCall) error { - var ( - pruned []string - ) - pruneImages, err := i.Runtime.ImageRuntime().GetPruneImages() +func (i *LibpodAPI) ImagesPrune(call iopodman.VarlinkCall, all bool) error { + prunedImages, err := i.Runtime.ImageRuntime().PruneImages(all) if err != nil { - return err - } - for _, i := range pruneImages { - if err := i.Remove(true); err != nil { - return call.ReplyErrorOccurred(err.Error()) - } - pruned = append(pruned, i.ID()) + return call.ReplyErrorOccurred(err.Error()) } - return call.ReplyImagesPrune(pruned) + return call.ReplyImagesPrune(prunedImages) } diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go index 50a279232..81fb82b20 100644 --- a/test/e2e/prune_test.go +++ b/test/e2e/prune_test.go @@ -1,5 +1,3 @@ -// +build !remoteclient - package integration import ( @@ -41,6 +39,7 @@ var _ = Describe("Podman rm", func() { }) It("podman container prune containers", func() { + SkipIfRemote() top := podmanTest.RunTopContainer("") top.WaitWithDefaultTimeout() Expect(top.ExitCode()).To(Equal(0)) @@ -57,6 +56,7 @@ var _ = Describe("Podman rm", func() { }) It("podman image prune none images", func() { + SkipIfRemote() podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true") none := podmanTest.Podman([]string{"images", "-a"}) @@ -74,10 +74,11 @@ var _ = Describe("Podman rm", func() { Expect(none.ExitCode()).To(Equal(0)) hasNoneAfter, _ := after.GrepString("<none>") Expect(hasNoneAfter).To(BeFalse()) + Expect(len(after.OutputToStringArray()) > 1).To(BeTrue()) }) It("podman image prune unused images", func() { - prune := podmanTest.Podman([]string{"image", "prune"}) + prune := podmanTest.Podman([]string{"image", "prune", "-a"}) prune.WaitWithDefaultTimeout() Expect(prune.ExitCode()).To(Equal(0)) |