Skip to content

volume prune: add dry-run support#28673

Open
kyounghunJang wants to merge 1 commit into
containers:mainfrom
kyounghunJang:feat/add-volume-prune-dry-run
Open

volume prune: add dry-run support#28673
kyounghunJang wants to merge 1 commit into
containers:mainfrom
kyounghunJang:feat/add-volume-prune-dry-run

Conversation

@kyounghunJang
Copy link
Copy Markdown
Contributor

@kyounghunJang kyounghunJang commented May 10, 2026

Add a --dry-run option to show which volumes would be pruned without removing them.

Example Output (remote)

$ podman volume ls   
DRIVER      VOLUME NAME
local       vol1
local       validatepr-gocache
local       validatepr-gomodcache
local       validatepr-lintcache
local       validatepr-precommitcache

$ podman volume prune --all --dry-run
Volumes that would be pruned:
vol1
validatepr-gocache
validatepr-gomodcache
validatepr-lintcache
validatepr-precommitcache

$ podman volume ls
DRIVER      VOLUME NAME
local       vol1
local       validatepr-gocache
local       validatepr-gomodcache
local       validatepr-lintcache
local       validatepr-precommitcache

Related: #27838

Checklist

Ensure you have completed the following checklist for your pull request to be reviewed:

  • Certify you wrote the patch or otherwise have the right to pass it on as an open-source patch by signing all
    commits. (git commit -s). (If needed, use git commit -s --amend). The author email must match
    the sign-off email address. See CONTRIBUTING.md
    for more information.
  • Referenced issues using Fixes: #00000 in commit message (if applicable)
  • Tests have been added/updated (or no tests are needed)
  • Documentation has been updated (or no documentation changes are needed)
  • All commits pass make validatepr (format/lint checks)
  • Release note entered in the section below (or None if no user-facing changes)

Does this PR introduce a user-facing change?

The `podman volume prune` command now supports `--dry-run` to preview which volumes would be pruned without removing them.

@github-actions github-actions Bot added the kind/api-change Change to remote API; merits scrutiny label May 10, 2026
Add a --dry-run option to show which volumes would be pruned without removing them.

Related: containers#27838
Signed-off-by: KyounghoonJang <matkimchi_@naver.com>
@kyounghunJang kyounghunJang force-pushed the feat/add-volume-prune-dry-run branch from c89d8dd to 0b42fa2 Compare May 11, 2026 00:40
Copy link
Copy Markdown
Member

@Honny1 Honny1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I have some comments.

Comment thread libpod/runtime_volume.go
}

// PlanPruneVolumes returns a list of volumes that would be pruned by PruneVolumes
func (r *Runtime) PlanPruneVolumes(filterFuncs []VolumeFilter) ([]*reports.PruneReport, error) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function has divergent logic from PruneVolumes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it not be simpler to have a dryRun option to PruneVolumes? Keep the logic between the two shared, just gate the actual r.removeVolume bit off if it's set?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mheon
After thinking about it again, I think having PruneVolumes take a dryRun bool parameter and handling the branching logic there, as you suggested, is a much simpler approach.
Thanks for the feedback! I’ll update it accordingly.

Expect(session.OutputToStringArray()[0]).To(Equal(vol1))
})

It("podman volume prune --all --dry-run", func() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to see also other tests for example:

  • --dry-run without --all (anonymous-only volumes)
  • --dry-run combined with --force (should work but good to verify)
  • Negative test for volumes in use (should not appear in dry-run output)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Honny1
Thank you for the feedback.

Before adding the test code, I would like to share the results I observed in my remote environment.

## case 1: --dry-run without --all
$ podman volume prune --dry-run
Volumes that would be pruned:

## case 2: --dry-run combined with --force
$ podman volume prune --force --all --dry-run
Volumes that would be pruned:
vol1
validatepr-gocache
validatepr-gomodcache
validatepr-lintcache
validatepr-precommitcache

$ podman volume ls                           
DRIVER      VOLUME NAME
local       vol1
local       validatepr-gocache
local       validatepr-gomodcache
local       validatepr-lintcache
local       validatepr-precommitcache

## case 3: Negative test for volumes in use
$ podman run -d --name testctr -v vol1:/data alpine sleep 1000
$ podman volume prune --all --dry-run
Volumes that would be pruned:
validatepr-gocache
validatepr-gomodcache
validatepr-lintcache
validatepr-precommitcache

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not forget to create also anonymous volumes.

// - `until=<timestamp>` Prune volumes created before this timestamp. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine’s time.
// - `label` (`label=<key>`, `label=<key>=<value>`, `label!=<key>`, or `label!=<key>=<value>`) Prune volumes with (or without, in case `label!=...` is used) the specified labels.
// - in: query
// name: dryrun
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dryrun query parameter should include required: false and ideally a default: false.

_ = pruneCommand.RegisterFlagCompletionFunc(filterFlagName, common.AutocompleteVolumePruneFilters)
flags.BoolP("force", "f", false, "Do not prompt for confirmation")
flags.BoolP("all", "a", false, "Remove all unused volumes, both anonymous and named")
flags.Bool("dry-run", false, "Show what would be pruned without actually pruning")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should conflict with --force

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/api-change Change to remote API; merits scrutiny

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants