diff --git a/cli/templatecreate_test.go b/cli/templatecreate_test.go index 3f1904e5fd6c9..c034b62eeaff3 100644 --- a/cli/templatecreate_test.go +++ b/cli/templatecreate_test.go @@ -229,6 +229,7 @@ func TestTemplateCreate(t *testing.T) { "templates", "delete", "my-template", + "--yes", } cmd, root := clitest.New(t, args...) clitest.SetupConfig(t, client, root) diff --git a/cli/templatedelete.go b/cli/templatedelete.go index 0ca9929daa0c4..9eecda2b29bd9 100644 --- a/cli/templatedelete.go +++ b/cli/templatedelete.go @@ -2,6 +2,7 @@ package cli import ( "fmt" + "strings" "time" "github.com/spf13/cobra" @@ -12,7 +13,7 @@ import ( ) func templateDelete() *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Use: "delete [name...]", Short: "Delete templates", RunE: func(cmd *cobra.Command, args []string) error { @@ -33,6 +34,14 @@ func templateDelete() *cobra.Command { if len(args) > 0 { templateNames = args + + for _, templateName := range templateNames { + template, err := client.TemplateByName(ctx, organization.ID, templateName) + if err != nil { + return xerrors.Errorf("get template by name: %w", err) + } + templates = append(templates, template) + } } else { allTemplates, err := client.TemplatesByOrganization(ctx, organization.ID) if err != nil { @@ -58,17 +67,19 @@ func templateDelete() *cobra.Command { for _, template := range allTemplates { if template.Name == selection { templates = append(templates, template) + templateNames = append(templateNames, template.Name) } } } - for _, templateName := range templateNames { - template, err := client.TemplateByName(ctx, organization.ID, templateName) - if err != nil { - return xerrors.Errorf("get template by name: %w", err) - } - - templates = append(templates, template) + // Confirm deletion of the template. + _, err = cliui.Prompt(cmd, cliui.PromptOptions{ + Text: fmt.Sprintf("Delete these templates: %s?", cliui.Styles.Code.Render(strings.Join(templateNames, ", "))), + IsConfirm: true, + Default: "no", + }) + if err != nil { + return err } for _, template := range templates { @@ -83,4 +94,7 @@ func templateDelete() *cobra.Command { return nil }, } + + cliui.AllowSkipPrompt(cmd) + return cmd } diff --git a/cli/templatedelete_test.go b/cli/templatedelete_test.go index 92fb0b2932fa0..14364d673f012 100644 --- a/cli/templatedelete_test.go +++ b/cli/templatedelete_test.go @@ -2,11 +2,14 @@ package cli_test import ( "context" + "fmt" + "strings" "testing" "github.com/stretchr/testify/require" "github.com/coder/coder/cli/clitest" + "github.com/coder/coder/cli/cliui" "github.com/coder/coder/coderd/coderdtest" "github.com/coder/coder/codersdk" "github.com/coder/coder/pty/ptytest" @@ -25,14 +28,27 @@ func TestTemplateDelete(t *testing.T) { template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) cmd, root := clitest.New(t, "templates", "delete", template.Name) + clitest.SetupConfig(t, client, root) - require.NoError(t, cmd.Execute()) + pty := ptytest.New(t) + cmd.SetIn(pty.Input()) + cmd.SetOut(pty.Output()) + + execDone := make(chan error) + go func() { + execDone <- cmd.Execute() + }() + + pty.ExpectMatch(fmt.Sprintf("Delete these templates: %s?", cliui.Styles.Code.Render(template.Name))) + pty.WriteLine("yes") + + require.NoError(t, <-execDone) _, err := client.Template(context.Background(), template.ID) require.Error(t, err, "template should not exist") }) - t.Run("Multiple", func(t *testing.T) { + t.Run("Multiple --yes", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) @@ -49,7 +65,7 @@ func TestTemplateDelete(t *testing.T) { templateNames = append(templateNames, template.Name) } - cmd, root := clitest.New(t, append([]string{"templates", "delete"}, templateNames...)...) + cmd, root := clitest.New(t, append([]string{"templates", "delete", "--yes"}, templateNames...)...) clitest.SetupConfig(t, client, root) require.NoError(t, cmd.Execute()) @@ -59,6 +75,45 @@ func TestTemplateDelete(t *testing.T) { } }) + t.Run("Multiple prompted", func(t *testing.T) { + t.Parallel() + + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) + user := coderdtest.CreateFirstUser(t, client) + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) + _ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) + templates := []codersdk.Template{ + coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID), + coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID), + coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID), + } + templateNames := []string{} + for _, template := range templates { + templateNames = append(templateNames, template.Name) + } + + cmd, root := clitest.New(t, append([]string{"templates", "delete"}, templateNames...)...) + clitest.SetupConfig(t, client, root) + pty := ptytest.New(t) + cmd.SetIn(pty.Input()) + cmd.SetOut(pty.Output()) + + execDone := make(chan error) + go func() { + execDone <- cmd.Execute() + }() + + pty.ExpectMatch(fmt.Sprintf("Delete these templates: %s?", cliui.Styles.Code.Render(strings.Join(templateNames, ", ")))) + pty.WriteLine("yes") + + require.NoError(t, <-execDone) + + for _, template := range templates { + _, err := client.Template(context.Background(), template.ID) + require.Error(t, err, "template should not exist") + } + }) + t.Run("Selector", func(t *testing.T) { t.Parallel() @@ -80,7 +135,7 @@ func TestTemplateDelete(t *testing.T) { execDone <- cmd.Execute() }() - pty.WriteLine("docker-local") + pty.WriteLine("yes") require.NoError(t, <-execDone) _, err := client.Template(context.Background(), template.ID)