From c929a325ff44b16aef0c28ce487632bdea8bbc12 Mon Sep 17 00:00:00 2001 From: Ben Pearce Date: Thu, 13 Oct 2022 14:07:40 +1000 Subject: [PATCH 1/6] refactored common confirmation flag --- pkg/cmd/account/delete/delete.go | 10 +++------- pkg/cmd/environment/delete/delete.go | 10 +++------- pkg/cmd/project/delete/delete.go | 1 + pkg/cmd/space/delete/delete.go | 10 +++------- pkg/question/input.go | 19 ++++++++++++++++++- 5 files changed, 28 insertions(+), 22 deletions(-) create mode 100644 pkg/cmd/project/delete/delete.go diff --git a/pkg/cmd/account/delete/delete.go b/pkg/cmd/account/delete/delete.go index 388ae8bd..0058d0f4 100644 --- a/pkg/cmd/account/delete/delete.go +++ b/pkg/cmd/account/delete/delete.go @@ -15,6 +15,7 @@ import ( ) func NewCmdDelete(f factory.Factory) *cobra.Command { + var skipConfirmation bool cmd := &cobra.Command{ Use: "delete { | }", Short: "Delete an account in an instance of Octopus Deploy", @@ -31,11 +32,6 @@ func NewCmdDelete(f factory.Factory) *cobra.Command { itemIDOrName := args[0] - skipConfirmation, err := cmd.Flags().GetBool("confirm") - if err != nil { - return err - } - client, err := f.GetSpacedClient() if err != nil { return err @@ -70,8 +66,8 @@ func NewCmdDelete(f factory.Factory) *cobra.Command { return delete(client, itemToDelete) }, } - // TODO confirm might want to be a global flag? - cmd.Flags().BoolP("confirm", "y", false, "Don't ask for confirmation before deleting the account.") + + question.RegisterDeleteFlag(&skipConfirmation, cmd, "account") return cmd } diff --git a/pkg/cmd/environment/delete/delete.go b/pkg/cmd/environment/delete/delete.go index 9eea452e..95cbe35e 100644 --- a/pkg/cmd/environment/delete/delete.go +++ b/pkg/cmd/environment/delete/delete.go @@ -15,6 +15,7 @@ import ( ) func NewCmdDelete(f factory.Factory) *cobra.Command { + var skipConfirmation bool cmd := &cobra.Command{ Use: "delete { | }", Short: "Delete an environment in an instance of Octopus Deploy", @@ -31,11 +32,6 @@ func NewCmdDelete(f factory.Factory) *cobra.Command { itemIDOrName := args[0] - skipConfirmation, err := cmd.Flags().GetBool("confirm") - if err != nil { - return err - } - client, err := f.GetSpacedClient() if err != nil { return err @@ -70,8 +66,8 @@ func NewCmdDelete(f factory.Factory) *cobra.Command { return delete(client, itemToDelete) }, } - // TODO confirm might want to be a global flag? - cmd.Flags().BoolP("confirm", "y", false, "Don't ask for confirmation before deleting the space.") + + question.RegisterDeleteFlag(&skipConfirmation, cmd, "environment") return cmd } diff --git a/pkg/cmd/project/delete/delete.go b/pkg/cmd/project/delete/delete.go new file mode 100644 index 00000000..a67e08ac --- /dev/null +++ b/pkg/cmd/project/delete/delete.go @@ -0,0 +1 @@ +package delete diff --git a/pkg/cmd/space/delete/delete.go b/pkg/cmd/space/delete/delete.go index c037c35a..827a2003 100644 --- a/pkg/cmd/space/delete/delete.go +++ b/pkg/cmd/space/delete/delete.go @@ -16,6 +16,7 @@ import ( ) func NewCmdDelete(f factory.Factory) *cobra.Command { + var alreadyConfirmed bool cmd := &cobra.Command{ Use: "delete { | }", Short: "Delete a space in an instance of Octopus Deploy", @@ -32,11 +33,6 @@ func NewCmdDelete(f factory.Factory) *cobra.Command { itemIDOrName := args[0] - alreadyConfirmed, err := cmd.Flags().GetBool("confirm") - if err != nil { - return err - } - client, err := f.GetSystemClient() if err != nil { return err @@ -59,8 +55,8 @@ func NewCmdDelete(f factory.Factory) *cobra.Command { return nil }, } - // TODO confirm might want to be a global flag? - cmd.Flags().BoolP("confirm", "y", false, "Don't ask for confirmation before deleting the space.") + + question.RegisterDeleteFlag(&alreadyConfirmed, cmd, "space") return cmd } diff --git a/pkg/question/input.go b/pkg/question/input.go index 7e981470..bc97149c 100644 --- a/pkg/question/input.go +++ b/pkg/question/input.go @@ -2,11 +2,28 @@ package question import ( "fmt" - "github.com/AlecAivazis/survey/v2" "github.com/OctopusDeploy/cli/pkg/output" + "github.com/OctopusDeploy/cli/pkg/util/flag" + "github.com/spf13/cobra" ) +const FlagConfirm = "confirm" + +type DeleteFlags struct { + Confirm *flag.Flag[bool] +} + +func NewDeleteFlags() *DeleteFlags { + return &DeleteFlags{ + Confirm: flag.New[bool](FlagConfirm, false), + } +} + +func RegisterDeleteFlag(value *bool, cmd *cobra.Command, resourceDescription string) { + cmd.Flags().BoolVarP(value, FlagConfirm, "c", false, fmt.Sprintf("Don't ask for confirmation before deleting the %s.", resourceDescription)) +} + func DeleteWithConfirmation(ask Asker, itemType string, itemName string, itemID string, doDelete func() error) error { var enteredName string if err := ask(&survey.Input{ From ef0ce8b7b7865305372d0e917c0b1d00c7c9dada Mon Sep 17 00:00:00 2001 From: Ben Pearce Date: Thu, 13 Oct 2022 14:07:54 +1000 Subject: [PATCH 2/6] added project delete --- pkg/cmd/project/delete/delete.go | 100 +++++++++++++++++++++++++++++++ pkg/cmd/project/project.go | 2 + 2 files changed, 102 insertions(+) diff --git a/pkg/cmd/project/delete/delete.go b/pkg/cmd/project/delete/delete.go index a67e08ac..b2c0e6b7 100644 --- a/pkg/cmd/project/delete/delete.go +++ b/pkg/cmd/project/delete/delete.go @@ -1 +1,101 @@ package delete + +import ( + "github.com/MakeNowJust/heredoc/v2" + "github.com/OctopusDeploy/cli/pkg/factory" + "github.com/OctopusDeploy/cli/pkg/question" + "github.com/OctopusDeploy/cli/pkg/question/selectors" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" + "github.com/spf13/cobra" + "io" +) + +type DeleteOptions struct { + Client *client.Client + Ask question.Asker + Host string + Writer io.Writer + NoPrompt bool + idOrName string + *question.DeleteFlags +} + +func NewCmdList(f factory.Factory) *cobra.Command { + deleteFlags := question.NewDeleteFlags() + cmd := &cobra.Command{ + Use: "delete { | | }", + Short: "Delete projects in Octopus Deploy", + Long: "Delete projects in Octopus Deploy", + Aliases: []string{"del", "rm", "remove"}, + Example: heredoc.Doc(` + $ octopus project delete + $ octopus project rm + `), + RunE: func(cmd *cobra.Command, args []string) error { + client, err := f.GetSystemClient() + if err != nil { + return err + } + + opts := &DeleteOptions{ + Client: client, + Ask: f.Ask, + Host: f.GetCurrentHost(), + Writer: cmd.OutOrStdout(), + NoPrompt: !f.IsPromptEnabled(), + idOrName: args[0], + DeleteFlags: deleteFlags, + } + + return deleteRun(opts) + }, + } + + question.RegisterDeleteFlag(&deleteFlags.Confirm.Value, cmd, "project") + + return cmd +} + +func deleteRun(opts *DeleteOptions) error { + if !opts.NoPrompt { + if err := PromptMissing(opts); err != nil { + return err + } + } + + itemToDelete, err := opts.Client.Projects.GetByID(opts.idOrName) + if err != nil { + return err + } + + if opts.DeleteFlags.Confirm.Value { + return delete(opts.Client, itemToDelete) + } else { + return question.DeleteWithConfirmation(opts.Ask, "project", itemToDelete.Name, itemToDelete.ID, func() error { + return delete(opts.Client, itemToDelete) + }) + } + + return nil +} + +func PromptMissing(opts *DeleteOptions) error { + if opts.idOrName == "" { + existingProjects, err := opts.Client.Projects.GetAll() + if err != nil { + return err + } + itemToDelete, err := selectors.ByNameOrID(opts.Ask, existingProjects, "Select the project you wish to delete:") + if err != nil { + return err + } + opts.idOrName = itemToDelete.GetID() + } + + return nil +} + +func delete(client *client.Client, project *projects.Project) error { + return client.Projects.DeleteByID(project.GetID()) +} diff --git a/pkg/cmd/project/project.go b/pkg/cmd/project/project.go index 4496c1ad..84f02a9d 100644 --- a/pkg/cmd/project/project.go +++ b/pkg/cmd/project/project.go @@ -3,6 +3,7 @@ package project import ( "fmt" "github.com/MakeNowJust/heredoc/v2" + cmdDelete "github.com/OctopusDeploy/cli/pkg/cmd/project/delete" cmdList "github.com/OctopusDeploy/cli/pkg/cmd/project/list" cmdView "github.com/OctopusDeploy/cli/pkg/cmd/project/view" "github.com/OctopusDeploy/cli/pkg/constants" @@ -28,6 +29,7 @@ func NewCmdProject(f factory.Factory) *cobra.Command { cmd.AddCommand(cmdList.NewCmdList(f)) cmd.AddCommand(cmdView.NewCmdView(f)) + cmd.AddCommand(cmdDelete.NewCmdList(f)) return cmd } From d7c7450e22138fc7fd6355a60fa5b2ea2900df97 Mon Sep 17 00:00:00 2001 From: Ben Pearce Date: Thu, 13 Oct 2022 17:37:03 +1000 Subject: [PATCH 3/6] fix project query and client creation update go-octopusdeploy reference --- go.mod | 2 +- go.sum | 2 ++ pkg/cmd/project/delete/delete.go | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a8659ab6..7286c706 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/AlecAivazis/survey/v2 v2.3.5 github.com/MakeNowJust/heredoc/v2 v2.0.1 - github.com/OctopusDeploy/go-octopusdeploy/v2 v2.8.1 + github.com/OctopusDeploy/go-octopusdeploy/v2 v2.9.1 github.com/briandowns/spinner v1.19.0 github.com/google/uuid v1.3.0 github.com/hashicorp/go-multierror v1.1.1 diff --git a/go.sum b/go.sum index 1173c6e9..41d51324 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,8 @@ github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63n github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w= github.com/OctopusDeploy/go-octopusdeploy/v2 v2.8.1 h1:jaMlQAeI93w/BlwUf5LNXXlm0aRneroFKuV1BH0D89s= github.com/OctopusDeploy/go-octopusdeploy/v2 v2.8.1/go.mod h1:XWqxyDUVElUlTaPqyCBblukpsHSnPcAKkAHgJgbsIAs= +github.com/OctopusDeploy/go-octopusdeploy/v2 v2.9.1 h1:rnG8B0t759J3en86aTSi9nZ/dv8VcNIz3s+iKWQxVrI= +github.com/OctopusDeploy/go-octopusdeploy/v2 v2.9.1/go.mod h1:XWqxyDUVElUlTaPqyCBblukpsHSnPcAKkAHgJgbsIAs= github.com/briandowns/spinner v1.19.0 h1:s8aq38H+Qju89yhp89b4iIiMzMm8YN3p6vGpwyh/a8E= github.com/briandowns/spinner v1.19.0/go.mod h1:mQak9GHqbspjC/5iUx3qMlIho8xBS/ppAL/hX5SmPJU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= diff --git a/pkg/cmd/project/delete/delete.go b/pkg/cmd/project/delete/delete.go index b2c0e6b7..8b8bd3f4 100644 --- a/pkg/cmd/project/delete/delete.go +++ b/pkg/cmd/project/delete/delete.go @@ -33,7 +33,7 @@ func NewCmdList(f factory.Factory) *cobra.Command { $ octopus project rm `), RunE: func(cmd *cobra.Command, args []string) error { - client, err := f.GetSystemClient() + client, err := f.GetSpacedClient() if err != nil { return err } @@ -64,7 +64,7 @@ func deleteRun(opts *DeleteOptions) error { } } - itemToDelete, err := opts.Client.Projects.GetByID(opts.idOrName) + itemToDelete, err := opts.Client.Projects.GetByIdOrName(opts.idOrName) if err != nil { return err } From 93358b93d40366bde37db156d40cce5b80bc6066 Mon Sep 17 00:00:00 2001 From: Ben Pearce Date: Thu, 13 Oct 2022 21:43:42 +1000 Subject: [PATCH 4/6] corrected short hand value for confirm --- pkg/question/input.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/question/input.go b/pkg/question/input.go index bc97149c..99baf7e6 100644 --- a/pkg/question/input.go +++ b/pkg/question/input.go @@ -21,7 +21,7 @@ func NewDeleteFlags() *DeleteFlags { } func RegisterDeleteFlag(value *bool, cmd *cobra.Command, resourceDescription string) { - cmd.Flags().BoolVarP(value, FlagConfirm, "c", false, fmt.Sprintf("Don't ask for confirmation before deleting the %s.", resourceDescription)) + cmd.Flags().BoolVarP(value, FlagConfirm, "y", false, fmt.Sprintf("Don't ask for confirmation before deleting the %s.", resourceDescription)) } func DeleteWithConfirmation(ask Asker, itemType string, itemName string, itemID string, doDelete func() error) error { From 2b1330ed338c48b9242810899c2cf410d41f5855 Mon Sep 17 00:00:00 2001 From: Ben Pearce Date: Thu, 13 Oct 2022 21:49:47 +1000 Subject: [PATCH 5/6] cleanup --- pkg/cmd/project/delete/delete.go | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/pkg/cmd/project/delete/delete.go b/pkg/cmd/project/delete/delete.go index 8b8bd3f4..dcdadc37 100644 --- a/pkg/cmd/project/delete/delete.go +++ b/pkg/cmd/project/delete/delete.go @@ -8,16 +8,13 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" "github.com/spf13/cobra" - "io" ) type DeleteOptions struct { Client *client.Client Ask question.Asker - Host string - Writer io.Writer NoPrompt bool - idOrName string + IdOrName string *question.DeleteFlags } @@ -41,10 +38,8 @@ func NewCmdList(f factory.Factory) *cobra.Command { opts := &DeleteOptions{ Client: client, Ask: f.Ask, - Host: f.GetCurrentHost(), - Writer: cmd.OutOrStdout(), NoPrompt: !f.IsPromptEnabled(), - idOrName: args[0], + IdOrName: args[0], DeleteFlags: deleteFlags, } @@ -64,7 +59,7 @@ func deleteRun(opts *DeleteOptions) error { } } - itemToDelete, err := opts.Client.Projects.GetByIdOrName(opts.idOrName) + itemToDelete, err := opts.Client.Projects.GetByIdOrName(opts.IdOrName) if err != nil { return err } @@ -76,12 +71,10 @@ func deleteRun(opts *DeleteOptions) error { return delete(opts.Client, itemToDelete) }) } - - return nil } func PromptMissing(opts *DeleteOptions) error { - if opts.idOrName == "" { + if opts.IdOrName == "" { existingProjects, err := opts.Client.Projects.GetAll() if err != nil { return err @@ -90,7 +83,7 @@ func PromptMissing(opts *DeleteOptions) error { if err != nil { return err } - opts.idOrName = itemToDelete.GetID() + opts.IdOrName = itemToDelete.GetID() } return nil From 759c6da11b8b523af859e40ed103068d69db648e Mon Sep 17 00:00:00 2001 From: Ben Pearce Date: Fri, 14 Oct 2022 11:18:47 +1000 Subject: [PATCH 6/6] reorder paramters --- pkg/cmd/account/delete/delete.go | 2 +- pkg/cmd/environment/delete/delete.go | 2 +- pkg/cmd/project/delete/delete.go | 2 +- pkg/cmd/space/delete/delete.go | 2 +- pkg/question/input.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/cmd/account/delete/delete.go b/pkg/cmd/account/delete/delete.go index 0058d0f4..6c09c218 100644 --- a/pkg/cmd/account/delete/delete.go +++ b/pkg/cmd/account/delete/delete.go @@ -67,7 +67,7 @@ func NewCmdDelete(f factory.Factory) *cobra.Command { }, } - question.RegisterDeleteFlag(&skipConfirmation, cmd, "account") + question.RegisterDeleteFlag(cmd, &skipConfirmation, "account") return cmd } diff --git a/pkg/cmd/environment/delete/delete.go b/pkg/cmd/environment/delete/delete.go index 95cbe35e..2a528fb5 100644 --- a/pkg/cmd/environment/delete/delete.go +++ b/pkg/cmd/environment/delete/delete.go @@ -67,7 +67,7 @@ func NewCmdDelete(f factory.Factory) *cobra.Command { }, } - question.RegisterDeleteFlag(&skipConfirmation, cmd, "environment") + question.RegisterDeleteFlag(cmd, &skipConfirmation, "environment") return cmd } diff --git a/pkg/cmd/project/delete/delete.go b/pkg/cmd/project/delete/delete.go index dcdadc37..2361a8fc 100644 --- a/pkg/cmd/project/delete/delete.go +++ b/pkg/cmd/project/delete/delete.go @@ -47,7 +47,7 @@ func NewCmdList(f factory.Factory) *cobra.Command { }, } - question.RegisterDeleteFlag(&deleteFlags.Confirm.Value, cmd, "project") + question.RegisterDeleteFlag(cmd, &deleteFlags.Confirm.Value, "project") return cmd } diff --git a/pkg/cmd/space/delete/delete.go b/pkg/cmd/space/delete/delete.go index 827a2003..ca7ee41b 100644 --- a/pkg/cmd/space/delete/delete.go +++ b/pkg/cmd/space/delete/delete.go @@ -56,7 +56,7 @@ func NewCmdDelete(f factory.Factory) *cobra.Command { }, } - question.RegisterDeleteFlag(&alreadyConfirmed, cmd, "space") + question.RegisterDeleteFlag(cmd, &alreadyConfirmed, "space") return cmd } diff --git a/pkg/question/input.go b/pkg/question/input.go index 99baf7e6..b0d44f45 100644 --- a/pkg/question/input.go +++ b/pkg/question/input.go @@ -20,7 +20,7 @@ func NewDeleteFlags() *DeleteFlags { } } -func RegisterDeleteFlag(value *bool, cmd *cobra.Command, resourceDescription string) { +func RegisterDeleteFlag(cmd *cobra.Command, value *bool, resourceDescription string) { cmd.Flags().BoolVarP(value, FlagConfirm, "y", false, fmt.Sprintf("Don't ask for confirmation before deleting the %s.", resourceDescription)) }