Skip to content

Commit

Permalink
feat: runbook delete (#341)
Browse files Browse the repository at this point in the history
  • Loading branch information
benPearce1 authored Mar 13, 2024
1 parent 43d5f2c commit 2bbb1ff
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 4 deletions.
140 changes: 140 additions & 0 deletions pkg/cmd/runbook/delete/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package delete

import (
"errors"
"github.com/MakeNowJust/heredoc/v2"
"github.com/OctopusDeploy/cli/pkg/cmd"
"github.com/OctopusDeploy/cli/pkg/cmd/runbook/shared"
"github.com/OctopusDeploy/cli/pkg/constants"
"github.com/OctopusDeploy/cli/pkg/factory"
"github.com/OctopusDeploy/cli/pkg/question"
"github.com/OctopusDeploy/cli/pkg/question/selectors"
"github.com/OctopusDeploy/cli/pkg/util/flag"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/runbooks"
"github.com/spf13/cobra"
)

const resourceDescription = "runbook"

const (
FlagProject = "project"
FlagRunbook = "runbook"
)

type DeleteFlags struct {
Project *flag.Flag[string]
Runbook *flag.Flag[string]
SkipConfirmation bool
}

func NewDeleteFlags() *DeleteFlags {
return &DeleteFlags{
Project: flag.New[string](FlagProject, false),
Runbook: flag.New[string](FlagRunbook, false),
}
}

type DeleteOptions struct {
*DeleteFlags
*cmd.Dependencies
*shared.RunbooksOptions
GetAllProjectsCallback shared.GetAllProjectsCallback
}

func NewDeleteOptions(dependencies *cmd.Dependencies, flags *DeleteFlags) *DeleteOptions {
return &DeleteOptions{
DeleteFlags: flags,
Dependencies: dependencies,
RunbooksOptions: shared.NewGetRunbooksOptions(dependencies),
GetAllProjectsCallback: func() ([]*projects.Project, error) { return shared.GetAllProjects(dependencies.Client) },
}
}

func NewCmdDelete(f factory.Factory) *cobra.Command {
deleteFlags := NewDeleteFlags()
cmd := &cobra.Command{
Use: "delete {<name> | <id>}",
Short: "Delete a runbook",
Long: "Delete a runbook in Octopus Deploy",
Aliases: []string{"del", "rm", "remove"},
Example: heredoc.Docf(`
$ %[1]s runbook delete
$ %[1]s runbook rm
`, constants.ExecutableName),
RunE: func(c *cobra.Command, args []string) error {
deps := cmd.NewDependencies(f, c)

opts := NewDeleteOptions(deps, deleteFlags)
if deleteFlags.Runbook.Value == "" && len(args) > 0 {
deleteFlags.Runbook.Value = args[0]
}

return deleteRun(opts)
},
}

flags := cmd.Flags()
flags.StringVarP(&deleteFlags.Project.Value, deleteFlags.Project.Name, "p", "", "Name or ID of the project to delete a runbook from")
flags.StringVarP(&deleteFlags.Runbook.Value, deleteFlags.Runbook.Name, "r", "", "Name or ID of the runbook to delete")
question.RegisterConfirmDeletionFlag(cmd, &deleteFlags.SkipConfirmation, resourceDescription)

return cmd
}

func deleteRun(opts *DeleteOptions) error {
project, err := getProject(opts)
if err != nil {
return err
}

runbook, err := getRunbook(opts, project)
if err != nil {
return err
}

if opts.SkipConfirmation {
return delete(opts.Client, runbook)
} else {
return question.DeleteWithConfirmation(opts.Ask, resourceDescription, runbook.Name, runbook.GetID(), func() error {
return delete(opts.Client, runbook)
})
}
}

func getRunbook(opts *DeleteOptions, project *projects.Project) (*runbooks.Runbook, error) {
var runbook *runbooks.Runbook
var err error
if opts.Runbook.Value == "" {
runbook, err = selectors.Select(opts.Ask, "Select the runbook you wish to delete:", func() ([]*runbooks.Runbook, error) { return opts.GetRunbooksCallback(project.GetID()) }, func(runbook *runbooks.Runbook) string { return runbook.Name })
} else {
runbook, err = selectors.FindRunbook(opts.Client, project, opts.Runbook.Value)
}

if runbook == nil {
return nil, errors.New("unable to find runbook")
}

return runbook, err
}

func getProject(opts *DeleteOptions) (*projects.Project, error) {
var project *projects.Project
var err error
if opts.Project.Value == "" {
project, err = selectors.Select(opts.Ask, "Select the project containing the runbook you wish to delete:", opts.GetAllProjectsCallback, func(project *projects.Project) string { return project.GetName() })
} else {
project, err = selectors.FindProject(opts.Client, opts.Project.Value)
}

if project == nil {
return nil, errors.New("unable to find project")
}

return project, err
}

func delete(client *client.Client, itemToDelete *runbooks.Runbook) error {
return client.Runbooks.DeleteByID(itemToDelete.GetID())
}
2 changes: 2 additions & 0 deletions pkg/cmd/runbook/runbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package runbook

import (
"github.com/MakeNowJust/heredoc/v2"
cmdDelete "github.com/OctopusDeploy/cli/pkg/cmd/runbook/delete"
cmdList "github.com/OctopusDeploy/cli/pkg/cmd/runbook/list"
cmdRun "github.com/OctopusDeploy/cli/pkg/cmd/runbook/run"
cmdSnapshot "github.com/OctopusDeploy/cli/pkg/cmd/runbook/snapshot"
Expand All @@ -27,6 +28,7 @@ func NewCmdRunbook(f factory.Factory) *cobra.Command {

cmd.AddCommand(cmdList.NewCmdList(f))
cmd.AddCommand(cmdRun.NewCmdRun(f))
cmd.AddCommand(cmdDelete.NewCmdDelete(f))
cmd.AddCommand(cmdSnapshot.NewCmdSnapshot(f))
return cmd
}
43 changes: 43 additions & 0 deletions pkg/cmd/runbook/shared/shared.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package shared

import (
"github.com/OctopusDeploy/cli/pkg/cmd"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/newclient"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/runbooks"
"math"
)

type GetRunbooksCallback func(projectID string) ([]*runbooks.Runbook, error)
type GetAllProjectsCallback func() ([]*projects.Project, error)

type RunbooksOptions struct {
GetRunbooksCallback
GetAllProjectsCallback
}

func NewGetRunbooksOptions(dependencies *cmd.Dependencies) *RunbooksOptions {
return &RunbooksOptions{
GetRunbooksCallback: func(projectID string) ([]*runbooks.Runbook, error) {
return GetAllRunbooks(dependencies.Client, projectID)
},
}
}

func GetAllRunbooks(client newclient.Client, projectID string) ([]*runbooks.Runbook, error) {
res, err := runbooks.List(client, client.GetSpaceID(), projectID, "", math.MaxInt32)
if err != nil {
return nil, err
}
return res.Items, nil
}

func GetAllProjects(client *client.Client) ([]*projects.Project, error) {
res, err := client.Projects.GetAll()
if err != nil {
return nil, err
}

return res, nil
}
4 changes: 2 additions & 2 deletions pkg/cmd/runbook/snapshot/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func listRun(cmd *cobra.Command, f factory.Factory, flags *ListFlags) error {
return err
}
} else { // project name is already provided, fetch the object because it's needed for further questions
selectedRunbook, err = selectors.FindRunbook(client, runbookNameOrID, selectedProject.GetID())
selectedRunbook, err = selectors.FindRunbook(client, selectedProject, runbookNameOrID)
if err != nil {
return err
}
Expand All @@ -124,7 +124,7 @@ func listRun(cmd *cobra.Command, f factory.Factory, flags *ListFlags) error {
if runbookNameOrID == "" {
return errors.New("runbook must be specified")
}
selectedRunbook, err = selectors.FindRunbook(client, runbookNameOrID, selectedProject.GetID())
selectedRunbook, err = selectors.FindRunbook(client, selectedProject, runbookNameOrID)
if err != nil {
return err
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/question/selectors/runbooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"github.com/OctopusDeploy/cli/pkg/question"
octopusApiClient "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/runbooks"
"math"
)
Expand All @@ -27,10 +28,10 @@ func Runbook(questionText string, client *octopusApiClient.Client, ask question.
})
}

func FindRunbook(client *octopusApiClient.Client, runbookIdentifier string, projectID string) (*runbooks.Runbook, error) {
func FindRunbook(client *octopusApiClient.Client, project *projects.Project, runbookIdentifier string) (*runbooks.Runbook, error) {
runbook, err := runbooks.GetByID(client, client.GetSpaceID(), runbookIdentifier)
if err != nil {
runbook, err = runbooks.GetByName(client, client.GetSpaceID(), projectID, runbookIdentifier)
runbook, err = runbooks.GetByName(client, client.GetSpaceID(), project.GetID(), runbookIdentifier)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 2bbb1ff

Please sign in to comment.