Skip to content

Commit

Permalink
feat: create account links and automation cmd generation
Browse files Browse the repository at this point in the history
  • Loading branch information
domenicsim1 authored Aug 22, 2022
1 parent fff48d3 commit 9aa6f12
Show file tree
Hide file tree
Showing 12 changed files with 603 additions and 295 deletions.
7 changes: 7 additions & 0 deletions pkg/apiclient/client_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ type ClientFactory interface {
// someone calls GetSpacedClient we will have to query the Octopus Server to look up spaceNameOrId,
// and any calls to GetActiveSpace before that will return nil
SetSpaceNameOrId(spaceNameOrId string)

// GetHostUrl returns the current set API URL as a string
GetHostUrl() string
}

type Client struct {
Expand Down Expand Up @@ -148,6 +151,10 @@ func (c *Client) GetActiveSpace() *spaces.Space {
return c.ActiveSpace
}

func (c *Client) GetHostUrl() string {
return c.ApiUrl.String()
}

func (c *Client) SetSpaceNameOrId(spaceNameOrId string) {
// technically don't need to nil out the SystemClient, but it's cleaner that way
// because a SpaceScopedClient can also be a SystemClient
Expand Down
102 changes: 64 additions & 38 deletions pkg/cmd/account/aws/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,49 @@ import (
"github.com/OctopusDeploy/cli/pkg/question"
"github.com/OctopusDeploy/cli/pkg/question/selectors"
"github.com/OctopusDeploy/cli/pkg/surveyext"
"github.com/OctopusDeploy/cli/pkg/util/flag"
"github.com/OctopusDeploy/cli/pkg/validation"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/accounts"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/core"
"github.com/spf13/cobra"
)

type CreateOptions struct {
Writer io.Writer
Octopus *client.Client
Ask question.Asker
Spinner factory.Spinner

Name string
Description string
AccessKey string
SecretKey string
Environments []string
type CreateFlags struct {
Name *flag.Flag[string]
Description *flag.Flag[string]
AccessKey *flag.Flag[string]
SecretKey *flag.Flag[string]
Environments *flag.Flag[[]string]
}

type CreateOptions struct {
*CreateFlags
Writer io.Writer
Octopus *client.Client
Ask question.Asker
Spinner factory.Spinner
Space string
Host string
NoPrompt bool
CmdPath string
}

func NewCreateFlags() *CreateFlags {
return &CreateFlags{
Name: flag.New[string]("name", false),
Description: flag.New[string]("description", false),
AccessKey: flag.New[string]("access-key", false),
SecretKey: flag.New[string]("secret-key", true),
Environments: flag.New[[]string]("environment", false),
}
}

func NewCmdCreate(f factory.Factory) *cobra.Command {
opts := &CreateOptions{
Ask: f.Ask,
Spinner: f.Spinner(),
CreateFlags: NewCreateFlags(),
Ask: f.Ask,
Spinner: f.Spinner(),
}
descriptionFilePath := ""

Expand All @@ -50,39 +67,41 @@ func NewCmdCreate(f factory.Factory) *cobra.Command {
Example: fmt.Sprintf(heredoc.Doc(`
$ %s account aws create"
`), constants.ExecutableName),
RunE: func(cmd *cobra.Command, args []string) error {
RunE: func(cmd *cobra.Command, _ []string) error {
client, err := f.GetSpacedClient()
if err != nil {
return err
}
opts.CmdPath = cmd.CommandPath()
opts.Octopus = client
opts.Host = f.GetCurrentHost()
opts.Space = f.GetCurrentSpace().GetID()
opts.Writer = cmd.OutOrStdout()
if descriptionFilePath != "" {
if err := validation.IsExistingFile(descriptionFilePath); err != nil {
if err = validation.IsExistingFile(descriptionFilePath); err != nil {
return err
}
data, err := os.ReadFile(descriptionFilePath)
if err != nil {
return err
}
opts.Description = string(data)
opts.Description.Value = string(data)
}
opts.NoPrompt = !f.IsPromptEnabled()
if opts.Environments != nil {
opts.Environments, err = helper.ResolveEnvironmentNames(opts.Environments, opts.Octopus, opts.Spinner)
if opts.Environments.Value != nil {
opts.Environments.Value, err = helper.ResolveEnvironmentNames(opts.Environments.Value, opts.Octopus, opts.Spinner)
if err != nil {
return err
}
}
return CreateRun(opts)
},
}

cmd.Flags().StringVarP(&opts.Name, "name", "n", "", "A short, memorable, unique name for this account.")
cmd.Flags().StringVarP(&opts.Description, "description", "d", "", "A summary explaining the use of the account to other users.")
cmd.Flags().StringVar(&opts.AccessKey, "access-key", "", "The AWS access key to use when authenticating against Amazon Web Services.")
cmd.Flags().StringVar(&opts.SecretKey, "secret-key", "", "The AWS secret key to use when authenticating against Amazon Web Services.")
cmd.Flags().StringArrayVarP(&opts.Environments, "environments", "e", nil, "The environments that are allowed to use this account")
cmd.Flags().StringVarP(&opts.Name.Value, opts.Name.Name, "n", "", "A short, memorable, unique name for this account.")
cmd.Flags().StringVarP(&opts.Description.Value, opts.Description.Name, "d", "", "A summary explaining the use of the account to other users.")
cmd.Flags().StringVar(&opts.AccessKey.Value, opts.AccessKey.Name, "", "The AWS access key to use when authenticating against Amazon Web Services.")
cmd.Flags().StringVar(&opts.SecretKey.Value, opts.SecretKey.Name, "", "The AWS secret key to use when authenticating against Amazon Web Services.")
cmd.Flags().StringArrayVarP(&opts.Environments.Value, opts.Environments.Name, "e", nil, "The environments that are allowed to use this account")
cmd.Flags().StringVarP(&descriptionFilePath, "description-file", "D", "", "Read the description from `file`")

return cmd
Expand All @@ -94,12 +113,12 @@ func CreateRun(opts *CreateOptions) error {
return err
}
}
awsAccount, err := accounts.NewAmazonWebServicesAccount(opts.Name, opts.AccessKey, core.NewSensitiveValue(opts.SecretKey))
awsAccount, err := accounts.NewAmazonWebServicesAccount(opts.Name.Value, opts.AccessKey.Value, core.NewSensitiveValue(opts.SecretKey.Value))
if err != nil {
return err
}
awsAccount.Description = opts.Description
awsAccount.EnvironmentIDs = opts.Environments
awsAccount.Description = opts.Description.Value
awsAccount.EnvironmentIDs = opts.Environments.Value

opts.Spinner.Start()
createdAccount, err := opts.Octopus.Accounts.Add(awsAccount)
Expand All @@ -109,19 +128,26 @@ func CreateRun(opts *CreateOptions) error {
}
opts.Spinner.Stop()

_, err = fmt.Fprintf(opts.Writer, "Successfully created AWS Account %s %s.\n", createdAccount.GetName(), output.Dimf("(%s)", createdAccount.GetID()))
_, err = fmt.Fprintf(opts.Writer, "Successfully created AWS account %s %s.\n", createdAccount.GetName(), output.Dimf("(%s)", createdAccount.GetID()))
if err != nil {
return err
}
link := output.Bluef("%s/app#/%s/infrastructure/accounts/%s", opts.Host, opts.Space, createdAccount.GetID())
fmt.Fprintf(opts.Writer, "\nView this account on Octopus Deploy: %s\n", link)
if !opts.NoPrompt {
autoCmd := flag.GenerateAutomationCmd(opts.CmdPath, opts.Name, opts.AccessKey, opts.SecretKey, opts.Description, opts.Environments)
fmt.Fprintf(opts.Writer, "\nAutomation Command: %s\n", autoCmd)
}

return nil
}

func promptMissing(opts *CreateOptions) error {
if opts.Name == "" {
if opts.Name.Value == "" {
if err := opts.Ask(&survey.Input{
Message: "Name",
Help: "A short, memorable, unique name for this account.",
}, &opts.Name, survey.WithValidator(survey.ComposeValidators(
}, &opts.Name.Value, survey.WithValidator(survey.ComposeValidators(
survey.MaxLength(200),
survey.MinLength(1),
survey.Required,
Expand All @@ -130,49 +156,49 @@ func promptMissing(opts *CreateOptions) error {
}
}

if opts.Description == "" {
if opts.Description.Value == "" {
if err := opts.Ask(&surveyext.OctoEditor{
Editor: &survey.Editor{
Message: "Description",
Help: "A summary explaining the use of the account to other users.",
FileName: "*.md",
},
Optional: true,
}, &opts.Description); err != nil {
}, &opts.Description.Value); err != nil {
return err
}
}

if opts.AccessKey == "" {
if opts.AccessKey.Value == "" {
if err := opts.Ask(&survey.Input{
Message: "Access Key",
Help: "The AWS access key to use when authenticating against Amazon Web Services.",
}, &opts.AccessKey, survey.WithValidator(survey.ComposeValidators(
}, &opts.AccessKey.Value, survey.WithValidator(survey.ComposeValidators(
survey.Required,
))); err != nil {
return err
}
}

if opts.SecretKey == "" {
if opts.SecretKey.Value == "" {
if err := opts.Ask(&survey.Password{
Message: "Secret Key",
Help: "The AWS secret key to use when authenticating against Amazon Web Services.",
}, &opts.SecretKey, survey.WithValidator(survey.ComposeValidators(
}, &opts.SecretKey.Value, survey.WithValidator(survey.ComposeValidators(
survey.Required,
))); err != nil {
return err
}
}

if opts.Environments == nil {
if opts.Environments.Value == nil {
environmentIDs, err := selectors.EnvironmentsMultiSelect(opts.Ask, opts.Octopus, opts.Spinner,
"Choose the environments that are allowed to use this account.\n"+
output.Dim("If nothing is selected, the account can be used for deployments to any environment."))
if err != nil {
return err
}
opts.Environments = environmentIDs
opts.Environments.Value = environmentIDs
}
return nil
}
Loading

0 comments on commit 9aa6f12

Please sign in to comment.