// Copyright 2016-2017, Pulumi Corporation. All rights reserved. package cmd import ( "fmt" "github.com/blang/semver" "github.com/hashicorp/go-multierror" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/pulumi/pulumi/pkg/diag/colors" "github.com/pulumi/pulumi/pkg/util/cmdutil" "github.com/pulumi/pulumi/pkg/workspace" ) func newPluginRmCmd() *cobra.Command { var all bool var yes bool var cmd = &cobra.Command{ Use: "rm [KIND [NAME [VERSION]]]", Args: cmdutil.MaximumNArgs(3), Short: "Remove one or more plugins from the download cache", Long: "Remove one or more plugins from the download cache.\n" + "\n" + "Specify KIND, NAME, and/or VERSION to narrow down what will be removed.\n" + "If none are specified, the entire cache will be cleared. If only KIND and\n" + "NAME are specified, but not VERSION, all versions of the plugin with the\n" + "given KIND and NAME will be removed. VERSION may be a range.\n" + "\n" + "This cannot be undone. If a deleted plugin is subsequently required in order\n" + "to execute a Pulumi program, it must be re-downloaded and installed using the\n" + "`pulumi plugin install` command.", Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error { // Parse the filters. var kind workspace.PluginKind var name string var version *semver.Range if len(args) > 0 { if !workspace.IsPluginKind(args[0]) { return errors.Errorf("unrecognized plugin kind: %s", kind) } kind = workspace.PluginKind(args[0]) } else if !all { return errors.Errorf("please pass --all if you'd like to remove all plugins") } if len(args) > 1 { name = args[1] } if len(args) > 2 { r, err := semver.ParseRange(args[2]) if err != nil { return errors.Wrap(err, "invalid plugin semver") } version = &r } // Now build a list of plugins that match. var deletes []workspace.PluginInfo plugins, err := workspace.GetPlugins() if err != nil { return errors.Wrap(err, "loading plugins") } for _, plugin := range plugins { if (kind == "" || plugin.Kind == kind) && (name == "" || plugin.Name == name) && (version == nil || (plugin.Version != nil && (*version)(*plugin.Version))) { deletes = append(deletes, plugin) } } if len(deletes) == 0 { return errors.New("no plugins found") } // Confirm that the user wants to do this (unless --yes was passed), and do the deletes. var suffix string if len(deletes) != 1 { suffix = "s" } fmt.Print( colors.ColorizeText( fmt.Sprintf("%sThis will remove %d plugin%s from the cache:%s\n", colors.SpecAttention, len(deletes), suffix, colors.Reset))) for _, del := range deletes { fmt.Printf(" %s %s\n", del.Kind, del.String()) } if yes || confirmPrompt("", "yes") { var result error for _, plugin := range deletes { if err := plugin.Delete(); err != nil { result = multierror.Append( result, errors.Wrapf(err, "failed to delete plugin %s", plugin.Path)) } } if result != nil { return result } } return nil }), } cmd.PersistentFlags().BoolVarP(&all, "all", "a", false, "Remove all plugins") cmd.PersistentFlags().BoolVar(&yes, "yes", false, "Skip confirmation prompts, and proceed with removal anyway") return cmd }