package context import ( "fmt" "os" "path/filepath" "github.com/pkg/errors" "github.com/urfave/cli" "github.com/smallstep/cli-utils/command" "github.com/smallstep/cli-utils/errs" "github.com/smallstep/cli-utils/fileutil" "github.com/smallstep/cli-utils/step" "github.com/smallstep/cli-utils/ui" "github.com/smallstep/cli/flags" ) func removeCommand() cli.Command { return cli.Command{ Name: "remove", Usage: "remove a context and all associated configuration", UsageText: "**step context remove** [**--force**]", Description: `**step context remove** command removes a context, along with all associated configuration, from disk. ## POSITIONAL ARGUMENTS : The name of the context to remove . ## EXAMPLES Remove a context: ''' $ step context remove alpha-one '''`, Action: command.ActionFunc(removeAction), Flags: []cli.Flag{ flags.Force, flags.HiddenNoContext, }, } } func removeAction(ctx *cli.Context) error { if err := errs.NumberOfArguments(ctx, 1); err != nil { return err } name := ctx.Args()[0] cs := step.Contexts() if !cs.Enabled() { return errors.Errorf("context '%s' not found - step path context management not enabled", name) } cur := cs.GetCurrent() target, ok := cs.Get(name) if !ok { return errors.Errorf("context '%s' not found", name) } if cur != nil && target.Name == cur.Name { return errors.Errorf("cannot remove current context") } // Check if either authority or profile should not be removed because it // is being used by another context. saveAuthority, saveProfile := false, false for _, c := range cs.List() { if target.Name == c.Name { continue } if saveAuthority && saveProfile { break } if !saveAuthority && target.Authority == c.Authority { saveAuthority = true } if !saveProfile && target.Profile == c.Profile { saveProfile = true } } if !ctx.Bool("force") && !(saveAuthority && saveProfile) { //nolint:staticcheck // TODO(hs): fix this ui.Printf("The following directories will be removed:\n") ui.Println() if !saveAuthority { ui.Printf(" - %s\n", target.Path()) } if !saveProfile { ui.Printf(" - %s\n", target.ProfilePath()) } ui.Println() if ok, err := ui.PromptYesNo(fmt.Sprintf("Are you sure you want to delete the configuration for context %s (this cannot be undone!) [y/n]", name)); err != nil { return err } else if !ok { return errors.New("context not removed") } } if !saveAuthority { if err := os.RemoveAll(target.Path()); err != nil { return err } } if !saveProfile { if err := os.RemoveAll(target.ProfilePath()); err != nil { return err } } if err := cs.Remove(name); err != nil { return err } // Attempt to remove line associated with the authority from removed context. return fileutil.RemoveLine(filepath.Join(step.BasePath(), "ssh", "includes"), target.Authority) }