-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Henrik Andersson <henrik.andersson@octopus.com>
- Loading branch information
1 parent
88d0588
commit 43d5f2c
Showing
4 changed files
with
222 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
package list | ||
|
||
import ( | ||
"errors" | ||
"github.com/MakeNowJust/heredoc/v2" | ||
"github.com/OctopusDeploy/cli/pkg/apiclient" | ||
"github.com/OctopusDeploy/cli/pkg/constants" | ||
"github.com/OctopusDeploy/cli/pkg/factory" | ||
"github.com/OctopusDeploy/cli/pkg/output" | ||
"github.com/OctopusDeploy/cli/pkg/question/selectors" | ||
"github.com/OctopusDeploy/cli/pkg/util/flag" | ||
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" | ||
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/runbooks" | ||
"github.com/spf13/cobra" | ||
"math" | ||
"time" | ||
) | ||
|
||
const ( | ||
FlagProject = "project" | ||
FlagRunbook = "runbook" | ||
FlagLimit = "limit" | ||
) | ||
|
||
type ListFlags struct { | ||
Project *flag.Flag[string] | ||
Runbook *flag.Flag[string] | ||
Limit *flag.Flag[int32] | ||
} | ||
|
||
func NewListFlags() *ListFlags { | ||
return &ListFlags{ | ||
Project: flag.New[string](FlagProject, false), | ||
Runbook: flag.New[string](FlagRunbook, false), | ||
Limit: flag.New[int32](FlagLimit, false), | ||
} | ||
} | ||
|
||
type SnapshotsAsJson struct { | ||
Id string `json:"Id"` | ||
Name string `json:"Name"` | ||
Assembled *time.Time `json:"Assembled"` | ||
} | ||
|
||
func NewCmdList(f factory.Factory) *cobra.Command { | ||
listFlags := NewListFlags() | ||
cmd := &cobra.Command{ | ||
Use: "list", | ||
Short: "List runbook snapshots", | ||
Long: "List runbook snapshots in Octopus Deploy", | ||
Example: heredoc.Docf(` | ||
$ %[1]s runbook snapshot list --project "Deploy Web App" --runbook "Run maintenance" | ||
$ %[1]s runbook snapshot ls | ||
`, constants.ExecutableName), | ||
Aliases: []string{"ls"}, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return listRun(cmd, f, listFlags) | ||
}, | ||
} | ||
|
||
flags := cmd.Flags() | ||
flags.StringVarP(&listFlags.Project.Value, listFlags.Project.Name, "p", "", "Name or ID of the project to list runbook snapshots for") | ||
flags.StringVarP(&listFlags.Runbook.Value, listFlags.Runbook.Name, "r", "", "Name or ID of the runbook to list snapshots for") | ||
flags.Int32Var(&listFlags.Limit.Value, listFlags.Limit.Name, math.MaxInt32, "Limit the maximum number of results that will be returned") | ||
|
||
return cmd | ||
} | ||
|
||
func listRun(cmd *cobra.Command, f factory.Factory, flags *ListFlags) error { | ||
client, err := f.GetSpacedClient(apiclient.NewRequester(cmd)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
outputFormat, err := cmd.Flags().GetString(constants.FlagOutputFormat) | ||
if err != nil { // should never happen, but fallback if it does | ||
outputFormat = constants.OutputFormatTable | ||
} | ||
|
||
projectNameOrID := flags.Project.Value | ||
runbookNameOrID := flags.Runbook.Value | ||
|
||
var selectedProject *projects.Project | ||
var selectedRunbook *runbooks.Runbook | ||
if f.IsPromptEnabled() { // this would be AskQuestions if it were bigger | ||
if projectNameOrID == "" { | ||
selectedProject, err = selectors.Project("Select the project to list runbook snapshots for", client, f.Ask) | ||
if err != nil { | ||
return err | ||
} | ||
} else { // project name is already provided, fetch the object because it's needed for further questions | ||
selectedProject, err = selectors.FindProject(client, projectNameOrID) | ||
if err != nil { | ||
return err | ||
} | ||
if !constants.IsProgrammaticOutputFormat(outputFormat) { | ||
cmd.Printf("Project %s\n", output.Cyan(selectedProject.Name)) | ||
} | ||
} | ||
|
||
if runbookNameOrID == "" { | ||
selectedRunbook, err = selectors.Runbook("Select the runbook to list snapshots for", client, f.Ask, selectedProject.GetID()) | ||
if err != nil { | ||
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()) | ||
if err != nil { | ||
return err | ||
} | ||
if !constants.IsProgrammaticOutputFormat(outputFormat) { | ||
cmd.Printf("Runbook %s\n", output.Cyan(selectedRunbook.Name)) | ||
} | ||
} | ||
} else { // we don't have the executions API backing us and allowing NameOrID; we need to do the lookup ourselves | ||
if projectNameOrID == "" { | ||
return errors.New("project must be specified") | ||
} | ||
selectedProject, err = selectors.FindProject(client, projectNameOrID) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if runbookNameOrID == "" { | ||
return errors.New("runbook must be specified") | ||
} | ||
selectedRunbook, err = selectors.FindRunbook(client, runbookNameOrID, selectedProject.GetID()) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
allSnapshots, err := runbooks.ListSnapshots(client, client.GetSpaceID(), selectedProject.GetID(), selectedRunbook.GetID(), int(flags.Limit.Value)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return output.PrintArray(allSnapshots.Items, cmd, output.Mappers[*runbooks.RunbookSnapshot]{ | ||
Json: func(s *runbooks.RunbookSnapshot) any { | ||
return SnapshotsAsJson{ | ||
Id: s.GetID(), | ||
Name: s.Name, | ||
Assembled: s.Assembled, | ||
} | ||
}, | ||
Table: output.TableDefinition[*runbooks.RunbookSnapshot]{ | ||
Header: []string{"ID", "NAME", "ASSEMBLED"}, | ||
Row: func(s *runbooks.RunbookSnapshot) []string { | ||
return []string{s.GetID(), output.Bold(s.Name), s.Assembled.Format(time.RFC1123Z)} | ||
}, | ||
}, | ||
Basic: func(s *runbooks.RunbookSnapshot) string { | ||
return s.Name | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package snapshot | ||
|
||
import ( | ||
"github.com/MakeNowJust/heredoc/v2" | ||
cmdList "github.com/OctopusDeploy/cli/pkg/cmd/runbook/snapshot/list" | ||
"github.com/OctopusDeploy/cli/pkg/constants" | ||
"github.com/OctopusDeploy/cli/pkg/factory" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func NewCmdSnapshot(f factory.Factory) *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "snapshot <command>", | ||
Short: "Manage runbook snapshots", | ||
Long: "Manage runbook snapshots in Octopus Deploy", | ||
Example: heredoc.Docf(` | ||
$ %[1]s runbook snapshot create | ||
$ %[1]s runbook snapshot list | ||
`, constants.ExecutableName), | ||
} | ||
|
||
cmd.AddCommand(cmdList.NewCmdList(f)) | ||
return cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package selectors | ||
|
||
import ( | ||
"errors" | ||
"github.com/OctopusDeploy/cli/pkg/question" | ||
octopusApiClient "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" | ||
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/runbooks" | ||
"math" | ||
) | ||
|
||
func Runbook(questionText string, client *octopusApiClient.Client, ask question.Asker, projectID string) (*runbooks.Runbook, error) { | ||
existingRunbooks, err := runbooks.List(client, client.GetSpaceID(), projectID, "", math.MaxInt32) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if len(existingRunbooks.Items) == 0 { | ||
return nil, errors.New("no runbooks found") | ||
} | ||
|
||
if len(existingRunbooks.Items) == 1 { | ||
return existingRunbooks.Items[0], nil | ||
} | ||
|
||
return question.SelectMap(ask, questionText, existingRunbooks.Items, func(r *runbooks.Runbook) string { | ||
return r.Name | ||
}) | ||
} | ||
|
||
func FindRunbook(client *octopusApiClient.Client, runbookIdentifier string, projectID string) (*runbooks.Runbook, error) { | ||
runbook, err := runbooks.GetByID(client, client.GetSpaceID(), runbookIdentifier) | ||
if err != nil { | ||
runbook, err = runbooks.GetByName(client, client.GetSpaceID(), projectID, runbookIdentifier) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
return runbook, nil | ||
} |