From 4811cb110accec51df168742df6a319f48ed37b6 Mon Sep 17 00:00:00 2001 From: Toshiki Sonoda Date: Tue, 14 Jun 2022 14:04:03 +0900 Subject: podman system prune support prune unused networks This is an enhancement for the podman system prune feature. In this issue, it is mentioned that 'network prune' should be wired into 'podman system prune' https://github.com/containers/podman/issues/8673 Therefore, I add the function to remove unused networks. Signed-off-by: Toshiki Sonoda --- cmd/podman/system/prune.go | 6 +++++ cmd/podman/utils/utils.go | 15 +++++++++++ docs/source/markdown/podman-system-prune.1.md | 6 ++--- docs/source/markdown/podman-system.1.md | 20 +++++++------- pkg/domain/entities/system.go | 1 + pkg/domain/infra/abi/network.go | 2 +- pkg/domain/infra/abi/system.go | 38 ++++++++++++++++++++++++--- test/e2e/prune_test.go | 23 ++++++++++++++++ 8 files changed, 93 insertions(+), 18 deletions(-) diff --git a/cmd/podman/system/prune.go b/cmd/podman/system/prune.go index ff78f93bb..1d6ba8155 100644 --- a/cmd/podman/system/prune.go +++ b/cmd/podman/system/prune.go @@ -75,6 +75,7 @@ func prune(cmd *cobra.Command, args []string) error { } } + // Remove all unused pods, containers, images, networks, and volume data. pruneOptions.Filters, err = parse.FilterArgumentsIntoFilters(filters) if err != nil { return err @@ -106,6 +107,11 @@ func prune(cmd *cobra.Command, args []string) error { if err != nil { return err } + // Print Network prune results + err = utils.PrintNetworkPruneResults(response.NetworkPruneReports, true) + if err != nil { + return err + } fmt.Printf("Total reclaimed space: %s\n", units.HumanSize((float64)(response.ReclaimedSpace))) return nil diff --git a/cmd/podman/utils/utils.go b/cmd/podman/utils/utils.go index 6fd6647d0..73bb34983 100644 --- a/cmd/podman/utils/utils.go +++ b/cmd/podman/utils/utils.go @@ -84,3 +84,18 @@ func PrintImagePruneResults(imagePruneReports []*reports.PruneReport, heading bo return nil } + +func PrintNetworkPruneResults(networkPruneReport []*reports.PruneReport, heading bool) error { + var errs OutputErrors + if heading && len(networkPruneReport) > 0 { + fmt.Println("Deleted Networks") + } + for _, r := range networkPruneReport { + if r.Err == nil { + fmt.Println(r.Id) + } else { + errs = append(errs, r.Err) + } + } + return errs.PrintErrors() +} diff --git a/docs/source/markdown/podman-system-prune.1.md b/docs/source/markdown/podman-system-prune.1.md index fb9ed44d6..c4c17fbe5 100644 --- a/docs/source/markdown/podman-system-prune.1.md +++ b/docs/source/markdown/podman-system-prune.1.md @@ -1,13 +1,13 @@ % podman-system-prune(1) ## NAME -podman\-system\-prune - Remove all unused pod, container, image and volume data +podman\-system\-prune - Remove all unused pods, containers, images, networks, and volume data ## SYNOPSIS **podman system prune** [*options*] ## DESCRIPTION -**podman system prune** removes all unused containers (both dangling and unreferenced), pods and optionally, volumes from local storage. +**podman system prune** removes all unused containers (both dangling and unreferenced), pods, networks, and optionally, volumes 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. @@ -16,7 +16,7 @@ By default, volumes are not removed to prevent important data from being deleted ## OPTIONS #### **--all**, **-a** -Recursively remove all unused pod, container, image and volume data (Maximum 50 iterations.) +Recursively remove all unused pods, containers, images, networks, and volume data. (Maximum 50 iterations.) #### **--filter**=*filters* diff --git a/docs/source/markdown/podman-system.1.md b/docs/source/markdown/podman-system.1.md index ae18aca88..7469eb79d 100644 --- a/docs/source/markdown/podman-system.1.md +++ b/docs/source/markdown/podman-system.1.md @@ -11,16 +11,16 @@ The system command allows you to manage the podman systems ## COMMANDS -| Command | Man Page | Description | -| ------- | ------------------------------------------------------------ | -------------------------------------------------------------------- | -| connection | [podman-system-connection(1)](podman-system-connection.1.md) | Manage the destination(s) for Podman service(s) | -| df | [podman-system-df(1)](podman-system-df.1.md) | Show podman disk usage. | -| info | [podman-system-info(1)](podman-info.1.md) | Displays Podman related system information. | -| migrate | [podman-system-migrate(1)](podman-system-migrate.1.md) | Migrate existing containers to a new podman version. | -| prune | [podman-system-prune(1)](podman-system-prune.1.md) | Remove all unused pod, container, image and volume data. | -| renumber | [podman-system-renumber(1)](podman-system-renumber.1.md) | Migrate lock numbers to handle a change in maximum number of locks. | -| reset | [podman-system-reset(1)](podman-system-reset.1.md) | Reset storage back to initial state. | -| service | [podman-system-service(1)](podman-system-service.1.md) | Run an API service | +| Command | Man Page | Description | +| ------- | ------------------------------------------------------------ | ------------------------------------------------------------------------ | +| connection | [podman-system-connection(1)](podman-system-connection.1.md) | Manage the destination(s) for Podman service(s) | +| df | [podman-system-df(1)](podman-system-df.1.md) | Show podman disk usage. | +| info | [podman-system-info(1)](podman-info.1.md) | Displays Podman related system information. | +| migrate | [podman-system-migrate(1)](podman-system-migrate.1.md) | Migrate existing containers to a new podman version. | +| prune | [podman-system-prune(1)](podman-system-prune.1.md) | Remove all unused pods, containers, images, networks, and volume data. | +| renumber | [podman-system-renumber(1)](podman-system-renumber.1.md) | Migrate lock numbers to handle a change in maximum number of locks. | +| reset | [podman-system-reset(1)](podman-system-reset.1.md) | Reset storage back to initial state. | +| service | [podman-system-service(1)](podman-system-service.1.md) | Run an API service | ## SEE ALSO **[podman(1)](podman.1.md)** diff --git a/pkg/domain/entities/system.go b/pkg/domain/entities/system.go index 21026477d..331d2bcdc 100644 --- a/pkg/domain/entities/system.go +++ b/pkg/domain/entities/system.go @@ -28,6 +28,7 @@ type SystemPruneReport struct { PodPruneReport []*PodPruneReport ContainerPruneReports []*reports.PruneReport ImagePruneReports []*reports.PruneReport + NetworkPruneReports []*reports.PruneReport VolumePruneReports []*reports.PruneReport ReclaimedSpace uint64 } diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go index 47f7917f4..c5f3cf8b3 100644 --- a/pkg/domain/infra/abi/network.go +++ b/pkg/domain/infra/abi/network.go @@ -142,7 +142,7 @@ func (ic *ContainerEngine) NetworkExists(ctx context.Context, networkname string }, nil } -// Network prune removes unused cni networks +// Network prune removes unused networks func (ic *ContainerEngine) NetworkPrune(ctx context.Context, options entities.NetworkPruneOptions) ([]*entities.NetworkPruneReport, error) { cons, err := ic.Libpod.GetAllContainers() if err != nil { diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index 762f0d79a..820ba529b 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -137,7 +137,7 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, noMoveProcess bool) return nil } -// SystemPrune removes unused data from the system. Pruning pods, containers, volumes and images. +// SystemPrune removes unused data from the system. Pruning pods, containers, networks, volumes and images. func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.SystemPruneOptions) (*entities.SystemPruneReport, error) { var systemPruneReport = new(entities.SystemPruneReport) filters := []string{} @@ -148,6 +148,9 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys found := true for found { found = false + + // TODO: Figure out cleaner way to handle all of the different PruneOptions + // Remove all unused pods. podPruneReport, err := ic.prunePodHelper(ctx) if err != nil { return nil, err @@ -155,9 +158,10 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys if len(podPruneReport) > 0 { found = true } + systemPruneReport.PodPruneReport = append(systemPruneReport.PodPruneReport, podPruneReport...) - // TODO: Figure out cleaner way to handle all of the different PruneOptions + // Remove all unused containers. containerPruneOptions := entities.ContainerPruneOptions{} containerPruneOptions.Filters = (url.Values)(options.Filters) @@ -165,16 +169,18 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys if err != nil { return nil, err } + reclaimedSpace += reports.PruneReportsSize(containerPruneReports) systemPruneReport.ContainerPruneReports = append(systemPruneReport.ContainerPruneReports, containerPruneReports...) + + // Remove all unused images. imagePruneOptions := entities.ImagePruneOptions{ All: options.All, Filter: filters, } + imageEngine := ImageEngine{Libpod: ic.Libpod} imagePruneReports, err := imageEngine.Prune(ctx, imagePruneOptions) - reclaimedSpace += reports.PruneReportsSize(imagePruneReports) - if err != nil { return nil, err } @@ -182,10 +188,33 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys found = true } + reclaimedSpace += reports.PruneReportsSize(imagePruneReports) systemPruneReport.ImagePruneReports = append(systemPruneReport.ImagePruneReports, imagePruneReports...) + + // Remove all unused networks. + networkPruneOptions := entities.NetworkPruneOptions{} + networkPruneOptions.Filters = options.Filters + + networkPruneReport, err := ic.NetworkPrune(ctx, networkPruneOptions) + if err != nil { + return nil, err + } + if len(networkPruneReport) > 0 { + found = true + } + for _, net := range networkPruneReport { + systemPruneReport.NetworkPruneReports = append(systemPruneReport.NetworkPruneReports, &reports.PruneReport{ + Id: net.Name, + Err: net.Error, + Size: 0, + }) + } + + // Remove unused volume data. if options.Volume { volumePruneOptions := entities.VolumePruneOptions{} volumePruneOptions.Filters = (url.Values)(options.Filters) + volumePruneReport, err := ic.VolumePrune(ctx, volumePruneOptions) if err != nil { return nil, err @@ -193,6 +222,7 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys if len(volumePruneReport) > 0 { found = true } + reclaimedSpace += reports.PruneReportsSize(volumePruneReport) systemPruneReport.VolumePruneReports = append(systemPruneReport.VolumePruneReports, volumePruneReport...) } diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go index 75adf1724..119c8d41e 100644 --- a/test/e2e/prune_test.go +++ b/test/e2e/prune_test.go @@ -258,6 +258,29 @@ var _ = Describe("Podman prune", func() { Expect(pods.OutputToStringArray()).To(HaveLen(2)) }) + It("podman system prune networks", func() { + // About netavark network backend test. + session := podmanTest.Podman([]string{"network", "create", "test"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"system", "prune", "-f"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + // Default network should exists. + session = podmanTest.Podman([]string{"network", "ls", "-q", "--filter", "name=^podman$"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToStringArray()).To(HaveLen(1)) + + // Remove all unused networks. + session = podmanTest.Podman([]string{"network", "ls", "-q", "--filter", "name=^test$"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToStringArray()).To(HaveLen(0)) + }) + It("podman system prune - pod,container stopped", func() { session := podmanTest.Podman([]string{"pod", "create"}) session.WaitWithDefaultTimeout() -- cgit v1.2.3-54-g00ecf