github.com/khulnasoft/cli@v0.0.0-20240402070845-01bcad7beefa/cli/command/volume/prune.go (about)

     1  package volume
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/docker/docker/api/types/versions"
     8  	"github.com/docker/docker/errdefs"
     9  	units "github.com/khulnasoft-lab/go-units"
    10  	"github.com/khulnasoft/cli/cli"
    11  	"github.com/khulnasoft/cli/cli/command"
    12  	"github.com/khulnasoft/cli/cli/command/completion"
    13  	"github.com/khulnasoft/cli/opts"
    14  	"github.com/pkg/errors"
    15  	"github.com/spf13/cobra"
    16  )
    17  
    18  type pruneOptions struct {
    19  	all    bool
    20  	force  bool
    21  	filter opts.FilterOpt
    22  }
    23  
    24  // NewPruneCommand returns a new cobra prune command for volumes
    25  func NewPruneCommand(dockerCli command.Cli) *cobra.Command {
    26  	options := pruneOptions{filter: opts.NewFilterOpt()}
    27  
    28  	cmd := &cobra.Command{
    29  		Use:   "prune [OPTIONS]",
    30  		Short: "Remove unused local volumes",
    31  		Args:  cli.NoArgs,
    32  		RunE: func(cmd *cobra.Command, args []string) error {
    33  			spaceReclaimed, output, err := runPrune(cmd.Context(), dockerCli, options)
    34  			if err != nil {
    35  				if errdefs.IsCancelled(err) {
    36  					fmt.Fprintln(dockerCli.Out(), output)
    37  					return nil
    38  				}
    39  				return err
    40  			}
    41  			if output != "" {
    42  				fmt.Fprintln(dockerCli.Out(), output)
    43  			}
    44  			fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed)))
    45  			return nil
    46  		},
    47  		Annotations:       map[string]string{"version": "1.25"},
    48  		ValidArgsFunction: completion.NoComplete,
    49  	}
    50  
    51  	flags := cmd.Flags()
    52  	flags.BoolVarP(&options.all, "all", "a", false, "Remove all unused volumes, not just anonymous ones")
    53  	flags.SetAnnotation("all", "version", []string{"1.42"})
    54  	flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation")
    55  	flags.Var(&options.filter, "filter", `Provide filter values (e.g. "label=<label>")`)
    56  
    57  	return cmd
    58  }
    59  
    60  const (
    61  	unusedVolumesWarning = `WARNING! This will remove anonymous local volumes not used by at least one container.
    62  Are you sure you want to continue?`
    63  	allVolumesWarning = `WARNING! This will remove all local volumes not used by at least one container.
    64  Are you sure you want to continue?`
    65  )
    66  
    67  func runPrune(ctx context.Context, dockerCli command.Cli, options pruneOptions) (spaceReclaimed uint64, output string, err error) {
    68  	pruneFilters := command.PruneFilters(dockerCli, options.filter.Value())
    69  
    70  	warning := unusedVolumesWarning
    71  	if versions.GreaterThanOrEqualTo(dockerCli.CurrentVersion(), "1.42") {
    72  		if options.all {
    73  			if pruneFilters.Contains("all") {
    74  				return 0, "", errdefs.InvalidParameter(errors.New("conflicting options: cannot specify both --all and --filter all=1"))
    75  			}
    76  			pruneFilters.Add("all", "true")
    77  			warning = allVolumesWarning
    78  		}
    79  	} else {
    80  		// API < v1.42 removes all volumes (anonymous and named) by default.
    81  		warning = allVolumesWarning
    82  	}
    83  	if !options.force {
    84  		if r, err := command.PromptForConfirmation(ctx, dockerCli.In(), dockerCli.Out(), warning); !r || err != nil {
    85  			return 0, "", errdefs.Cancelled(errors.New("user cancelled operation"))
    86  		}
    87  	}
    88  
    89  	report, err := dockerCli.Client().VolumesPrune(ctx, pruneFilters)
    90  	if err != nil {
    91  		return 0, "", err
    92  	}
    93  
    94  	if len(report.VolumesDeleted) > 0 {
    95  		output = "Deleted Volumes:\n"
    96  		for _, id := range report.VolumesDeleted {
    97  			output += id + "\n"
    98  		}
    99  		spaceReclaimed = report.SpaceReclaimed
   100  	}
   101  
   102  	return spaceReclaimed, output, nil
   103  }
   104  
   105  // RunPrune calls the Volume Prune API
   106  // This returns the amount of space reclaimed and a detailed output string
   107  func RunPrune(ctx context.Context, dockerCli command.Cli, _ bool, filter opts.FilterOpt) (uint64, string, error) {
   108  	return runPrune(ctx, dockerCli, pruneOptions{force: true, filter: filter})
   109  }