github.com/containerd/nerdctl@v1.7.7/cmd/nerdctl/system_prune.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "fmt" 21 "strings" 22 23 "github.com/containerd/log" 24 "github.com/containerd/nerdctl/pkg/api/types" 25 "github.com/containerd/nerdctl/pkg/clientutil" 26 "github.com/containerd/nerdctl/pkg/cmd/system" 27 "github.com/spf13/cobra" 28 ) 29 30 func newSystemPruneCommand() *cobra.Command { 31 systemPruneCommand := &cobra.Command{ 32 Use: "prune [flags]", 33 Short: "Remove unused data", 34 Args: cobra.NoArgs, 35 RunE: systemPruneAction, 36 SilenceUsage: true, 37 SilenceErrors: true, 38 } 39 systemPruneCommand.Flags().BoolP("all", "a", false, "Remove all unused images, not just dangling ones") 40 systemPruneCommand.Flags().BoolP("force", "f", false, "Do not prompt for confirmation") 41 systemPruneCommand.Flags().Bool("volumes", false, "Prune volumes") 42 return systemPruneCommand 43 } 44 45 func processSystemPruneOptions(cmd *cobra.Command) (types.SystemPruneOptions, error) { 46 globalOptions, err := processRootCmdFlags(cmd) 47 if err != nil { 48 return types.SystemPruneOptions{}, err 49 } 50 51 all, err := cmd.Flags().GetBool("all") 52 if err != nil { 53 return types.SystemPruneOptions{}, err 54 } 55 56 vFlag, err := cmd.Flags().GetBool("volumes") 57 if err != nil { 58 return types.SystemPruneOptions{}, err 59 } 60 61 buildkitHost, err := getBuildkitHost(cmd, globalOptions.Namespace) 62 if err != nil { 63 log.L.WithError(err).Warn("BuildKit is not running. Build caches will not be pruned.") 64 buildkitHost = "" 65 } 66 67 return types.SystemPruneOptions{ 68 Stdout: cmd.OutOrStdout(), 69 Stderr: cmd.ErrOrStderr(), 70 GOptions: globalOptions, 71 All: all, 72 Volumes: vFlag, 73 BuildKitHost: buildkitHost, 74 NetworkDriversToKeep: networkDriversToKeep, 75 }, nil 76 } 77 78 func grantSystemPrunePermission(cmd *cobra.Command, options types.SystemPruneOptions) (bool, error) { 79 force, err := cmd.Flags().GetBool("force") 80 if err != nil { 81 return false, err 82 } 83 84 if !force { 85 var confirm string 86 msg := `This will remove: 87 - all stopped containers 88 - all networks not used by at least one container` 89 if options.Volumes { 90 msg += ` 91 - all volumes not used by at least one container` 92 } 93 if options.All { 94 msg += ` 95 - all images without at least one container associated to them 96 - all build cache` 97 } else { 98 msg += ` 99 - all dangling images 100 - all dangling build cache` 101 } 102 103 msg += "\nAre you sure you want to continue? [y/N] " 104 fmt.Fprintf(options.Stdout, "WARNING! %s", msg) 105 fmt.Fscanf(cmd.InOrStdin(), "%s", &confirm) 106 107 if strings.ToLower(confirm) != "y" { 108 return false, nil 109 } 110 } 111 112 return true, nil 113 } 114 115 func systemPruneAction(cmd *cobra.Command, _ []string) error { 116 options, err := processSystemPruneOptions(cmd) 117 if err != nil { 118 return err 119 } 120 121 if ok, err := grantSystemPrunePermission(cmd, options); err != nil { 122 return err 123 } else if !ok { 124 return nil 125 } 126 127 client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), options.GOptions.Namespace, options.GOptions.Address) 128 if err != nil { 129 return err 130 } 131 defer cancel() 132 133 return system.Prune(ctx, client, options) 134 }