diff --git a/cmd/podman/volumes/prune.go b/cmd/podman/volumes/prune.go index 0f3ba9ef66..78f70365ed 100644 --- a/cmd/podman/volumes/prune.go +++ b/cmd/podman/volumes/prune.go @@ -49,7 +49,9 @@ func init() { func prune(cmd *cobra.Command, args []string) error { var ( - pruneOptions = entities.VolumePruneOptions{} + pruneOptions = entities.VolumePruneOptions{} + listOptions = entities.VolumeListOptions{} + unusedOptions = entities.VolumeListOptions{} ) // Prompt for confirmation if --force is not set force, err := cmd.Flags().GetBool("force") @@ -58,7 +60,35 @@ func prune(cmd *cobra.Command, args []string) error { } if !force { reader := bufio.NewReader(os.Stdin) - fmt.Println("WARNING! This will remove all volumes not used by at least one container.") + fmt.Println("WARNING! This will remove all volumes not used by at least one container. The following volumes will be removed:") + pruneOptions.Filters, err = filters.ParseFilterArgumentsIntoFilters(filter) + listOptions.Filter, err = filters.ParseFilterArgumentsIntoFilters(filter) + if err != nil { + return err + } + // filter all the unused (unbound) volumes + unusedOptions.Filter = make(map[string][]string, 1) + unusedOptions.Filter["unused"] = []string{"true"} + if err != nil { + return err + } + unusedVolumes, err := registry.ContainerEngine().VolumeList(context.Background(), unusedOptions) + if err != nil { + return err + } + // filter volumes based on user input + filteredVolumes, err := registry.ContainerEngine().VolumeList(context.Background(), listOptions) + if err != nil { + return err + } + finalVolumes := getUnion(unusedVolumes, filteredVolumes) + if len(finalVolumes) < 1 { + fmt.Println("No unused volumes found") + return nil + } + for _, fv := range finalVolumes { + fmt.Println(fv.Name) + } fmt.Print("Are you sure you want to continue? [y/N] ") answer, err := reader.ReadString('\n') if err != nil { @@ -68,13 +98,23 @@ func prune(cmd *cobra.Command, args []string) error { return nil } } - pruneOptions.Filters, err = filters.ParseFilterArgumentsIntoFilters(filter) - if err != nil { - return err - } responses, err := registry.ContainerEngine().VolumePrune(context.Background(), pruneOptions) if err != nil { return err } return utils.PrintVolumePruneResults(responses, false) } + +func getUnion(a, b []*entities.VolumeListReport) []*entities.VolumeListReport { + var intersection []*entities.VolumeListReport + hash := make(map[string]bool, len(a)) + for _, aa := range a { + hash[aa.Name] = true + } + for _, bb := range b { + if hash[bb.Name] { + intersection = append(intersection, bb) + } + } + return intersection +} diff --git a/pkg/domain/filters/volumes.go b/pkg/domain/filters/volumes.go index 7890459f5d..87aa0f4c7d 100644 --- a/pkg/domain/filters/volumes.go +++ b/pkg/domain/filters/volumes.go @@ -85,6 +85,31 @@ func GenerateVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) { } return dangling }) + case "unused": + invert := false + unusedVal := val + switch strings.ToLower(unusedVal) { + case "true", "1": + // do nth + case "false", "0": + invert = true + + default: + return nil, errors.Errorf("%q is not a valid value for the \"unused\" filter - must be true or false", unusedVal) + } + vf = append(vf, func(v *libpod.Volume) bool { + resp, err := v.VolumeInUse() + if err != nil || len(resp) > 0 { + if !invert { + return false + } + return true + } + if !invert { + return true + } + return false + }) default: return nil, errors.Errorf("%q is in an invalid volume filter", filter) } diff --git a/test/e2e/volume_prune_test.go b/test/e2e/volume_prune_test.go index a910c47a73..09e00e5dec 100644 --- a/test/e2e/volume_prune_test.go +++ b/test/e2e/volume_prune_test.go @@ -54,6 +54,11 @@ var _ = Describe("Podman volume prune", func() { session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.Podman([]string{"volume", "prune"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(len(session.OutputToStringArray())).To(Equal(4)) + session = podmanTest.Podman([]string{"volume", "ls"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) diff --git a/test/runecho.sh b/test/runecho.sh new file mode 100755 index 0000000000..ecc7d3d47e --- /dev/null +++ b/test/runecho.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +for i in {1..9}; +do + echo "This is a new container pull ipbabble [" $i "]" +done