Skip to content

Commit

Permalink
add aws command with install and uninstall subcommands
Browse files Browse the repository at this point in the history
  • Loading branch information
ianic committed Sep 29, 2021
1 parent 5313c5c commit 6c4bb5b
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 32 deletions.
121 changes: 121 additions & 0 deletions cli/cmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,124 @@ func selectFunctionFromStage(stage *config.Stage) string {
}
return function
}

func newAwsCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "aws",
Short: "AWS account subcommand",
Args: cobra.NoArgs,
}
cmd.AddCommand(newAwsInstallCommand())
cmd.AddCommand(newAwsUninstallCommand())
return cmd
}

func newAwsInstallCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "install [account-name]",
Short: "Install Mantil into AWS account",
Long: fmt.Sprintf(`Install Mantil into AWS account
Command will install backend services into AWS account.
You must provide credentials for Mantil to access your AWS account.
%s
Argument account-name is for referencing that account in Mantil.
If not provided default name %s will be used for the first account.
There is --dry-run flag which will show you what credentials will be used
and what account will be managed by command.
`, credentialsHelp(), commands.DefaultAccountName),
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cred, err := initAwsInstall(cmd, args)
if err != nil {
return err
}
if dryRun, _ := cmd.Flags().GetBool("dry-run"); dryRun {
showDryRunInfo(cred)
return nil
}
return cred.cmd.Create()
},
}
addAwsInstallFlags(cmd)
return cmd
}

func newAwsUninstallCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "uninstall [account-name]",
Short: "Uninstall Mantil from AWS account",
Long: fmt.Sprintf(`Uninstall Mantil from AWS account
Command will remove backend services from AWS account.
You must provide credentials for Mantil to access your AWS account.
%s
Argument account-name is Mantil account reference.
There is --dry-run flag which will show you what credentials will be used
and what account will be managed by command.
`, credentialsHelp()),
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cred, err := initAwsInstall(cmd, args)
if err != nil {
return err
}
if dryRun, _ := cmd.Flags().GetBool("dry-run"); dryRun {
showDryRunInfo(cred)
return nil
}
return cred.cmd.Destroy()
},
}
addAwsInstallFlags(cmd)
return cmd
}

func credentialsHelp() string {
return `There are few ways to provide credentials:
1. specifiy access keys as arguments:
$ mantil aws install --aws-access-key-id=AKIAIOSFODNN7EXAMPLE --aws-secret-access-key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY --aws-region=us-east-1
2. read access keys from environment variables:
$ export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
$ export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
$ export AWS_DEFAULT_REGION=us-east-1
$ mantil aws install --aws-env
reference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html
3. use your named AWS profile form ~/.aws/config
$ mantil aws install --aws-profile=my-named-profile
reference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html
`
}

func addAwsInstallFlags(cmd *cobra.Command) {
cmd.Flags().String("aws-access-key-id", "", "access key ID for the AWS account, must be used with the aws-secret-access-key and aws-region flags")
cmd.Flags().String("aws-secret-access-key", "", "secret access key for the AWS account, must be used with the aws-access-key-id and aws-region flags")
cmd.Flags().String("aws-region", "", "region for the AWS account, must be used with and aws-access-key-id and aws-secret-access-key flags")
cmd.Flags().Bool("aws-env", false, "use AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_DEFAULT_REGION environment variables for AWS authentication")
cmd.Flags().String("aws-profile", "", "use the given profile for AWS authentication")
cmd.Flags().Bool("dry-run", false, "don't start install/uninstall just show what credentials will be used")
}

func showDryRunInfo(cred *credentials) {
accountID, _ := cred.cli.AccountID()
if cred.profile != "" {
fmt.Printf(`command will use AWS profile %s defined in you AWS configuration file (~/.aws/config)
to manage AWS account ID: %s in region %s
`, cred.profile, accountID, cred.cli.Region())
} else {
fmt.Printf(`command will use AWS credentials:
aws-access-key-id: %s
aws-secret-access-key: %s
aws-region: %s
to manage AWS account ID: %s in region %s
`, cred.accessKeyID, cred.secretAccessKey, cred.region, accountID, cred.cli.Region())
}
fmt.Printf("account name in Mantil is %s\n", cred.accountName)
}
1 change: 1 addition & 0 deletions cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func Execute(ctx context.Context, version string) error {
cmd.AddCommand(newSetupCommand())
cmd.AddCommand(newDeployCommand())
cmd.AddCommand(newGenerateCommand())
cmd.AddCommand(newAwsCommand())

// register global flags
var verbose, noColor bool
Expand Down
84 changes: 56 additions & 28 deletions cli/cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,14 @@ func newSetupCommand() *cobra.Command {
if err != nil {
return err
}
accountName := commands.DefaultAccountName
if len(args) > 0 {
accountName = args[0]
}

awsClient, err := createAwsClient(cmd)
cred, err := initAwsInstall(cmd, args)
if err != nil {
return err
}

v, ok := setup.GetVersion(cmd.Context())
if !ok {
return fmt.Errorf("version not found in context")
}
b := setup.New(awsClient, v, accountName)
if destroy {
err = b.Destroy()
err = cred.cmd.Destroy()
} else {
err = b.Create()
err = cred.cmd.Create()
}
return err
},
Expand All @@ -56,22 +45,61 @@ func newSetupCommand() *cobra.Command {
return cmd
}

func createAwsClient(cmd *cobra.Command) (*aws.AWS, error) {
var c credentials
if err := c.read(cmd); err != nil {
return nil, err
}
if c.profile != "" {
return aws.NewFromProfile(c.profile)
}
return aws.NewWithCredentials(c.accessKeyID, c.secretAccessKey, "", c.region)
}

type credentials struct {
accessKeyID string
secretAccessKey string
region string
profile string
accountName string
cli *aws.AWS
version *setup.VersionInfo
cmd *setup.Cmd
}

func initAwsInstall(cmd *cobra.Command, args []string) (*credentials, error) {
c := credentials{
accountName: commands.DefaultAccountName,
}
if len(args) > 0 {
c.accountName = args[0]
}

if err := c.createAwsClient(cmd); err != nil {
return nil, err
}

v, ok := setup.GetVersion(cmd.Context())
if !ok {
return nil, fmt.Errorf("version not found in context")
}
c.version = v

if err := c.cli.Try(); err != nil {
return nil, err
}

c.cmd = setup.New(c.cli, c.version, c.accountName)
return &c, nil
}

func (c *credentials) createAwsClient(cmd *cobra.Command) error {
if err := c.read(cmd); err != nil {
return err
}
if c.profile != "" {
cli, err := aws.NewFromProfile(c.profile)
if err != nil {
return err
}
c.cli = cli
return nil
}
cli, err := aws.NewWithCredentials(c.accessKeyID, c.secretAccessKey, "", c.region)
if err != nil {
return err
}
c.cli = cli
return nil
}

func (c *credentials) read(cmd *cobra.Command) error {
Expand All @@ -98,21 +126,21 @@ func (c *credentials) awsFromAccessKeys(cmd *cobra.Command) error {
return err
}
if c.accessKeyID == "" {
return fmt.Errorf("access key id not provided")
return fmt.Errorf("access key id not provided, must be used with the aws-secret-access-key and aws-region")
}
c.secretAccessKey, err = cmd.Flags().GetString("aws-secret-access-key")
if err != nil {
return err
}
if c.secretAccessKey == "" {
return fmt.Errorf("secret access key not provided")
return fmt.Errorf("secret access key not provided, must be used with the aws-access-key-id and aws-region flags")
}
c.region, err = cmd.Flags().GetString("aws-region")
if err != nil {
return err
}
if c.region == "" {
return fmt.Errorf("region not provided")
return fmt.Errorf("region not provided, must be used with and aws-access-key-id and aws-secret-access-key flags")
}
return nil
}
Expand Down
Loading

0 comments on commit 6c4bb5b

Please sign in to comment.