diff --git a/cmd/access.go b/cmd/access.go index 16b6988..57b5e61 100644 --- a/cmd/access.go +++ b/cmd/access.go @@ -24,6 +24,7 @@ import ( "github.com/apppackio/apppack/stacks" "github.com/apppackio/apppack/stringslice" "github.com/apppackio/apppack/ui" + "github.com/apppackio/apppack/utils" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/spf13/cobra" @@ -107,7 +108,7 @@ var accessCmd = &cobra.Command{ Short: "list users with access to the app", Args: cobra.NoArgs, DisableFlagsInUseLine: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { ui.StartSpinner() var err error sess, err := adminSession(SessionDurationSeconds) @@ -131,7 +132,7 @@ Updates the application Cloudformation stack to add access for the user.`, DisableFlagsInUseLine: true, Args: cobra.MinimumNArgs(1), Example: "apppack -a my-app access add user1@example.com user2@example.com", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { for _, email := range args { if !validateEmail(email) { checkErr(fmt.Errorf("%s does not appear to be a valid email address", email)) @@ -163,7 +164,7 @@ Updates the application Cloudformation stack to remove access for the user.`, DisableFlagsInUseLine: true, Args: cobra.MinimumNArgs(1), Example: "apppack -a my-app access remove user1@example.com user2@example.com", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { for _, email := range args { if !validateEmail(email) { checkErr(fmt.Errorf("%s does not appear to be a valid email address", email)) @@ -195,7 +196,7 @@ func init() { "account", "c", "", - "AWS account ID or alias (not needed if you are only the administrator of one account)", + utils.AccountFlagHelpText, ) accessCmd.PersistentFlags().BoolVar( &UseAWSCredentials, diff --git a/cmd/admins.go b/cmd/admins.go index 8c3d8f3..2214751 100644 --- a/cmd/admins.go +++ b/cmd/admins.go @@ -22,6 +22,7 @@ import ( "github.com/apppackio/apppack/stacks" "github.com/apppackio/apppack/stringslice" "github.com/apppackio/apppack/ui" + "github.com/apppackio/apppack/utils" "github.com/aws/aws-sdk-go/aws/session" "github.com/spf13/cobra" ) @@ -57,7 +58,7 @@ var adminsCmd = &cobra.Command{ Long: "*Requires admin permissions.*", Args: cobra.NoArgs, DisableFlagsInUseLine: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { ui.StartSpinner() sess, err := adminSession(SessionDurationSeconds) checkErr(err) @@ -78,7 +79,7 @@ var adminsAddCmd = &cobra.Command{ DisableFlagsInUseLine: true, Args: cobra.MinimumNArgs(1), Example: "apppack admins add user1@example.com user2@example.com", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { for _, email := range args { if !validateEmail(email) { checkErr(fmt.Errorf("%s does not appear to be a valid email address", email)) @@ -108,7 +109,7 @@ var adminsRemoveCmd = &cobra.Command{ Updates the application Cloudformation stack to remove an administrators.`, DisableFlagsInUseLine: true, Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { for _, email := range args { if !validateEmail(email) { checkErr(fmt.Errorf("%s does not appear to be a valid email address", email)) @@ -137,7 +138,7 @@ func init() { "account", "c", "", - "AWS account ID or alias (not needed if you are only the administrator of one account)", + utils.AccountFlagHelpText, ) adminsCmd.PersistentFlags().BoolVar( &UseAWSCredentials, diff --git a/cmd/create.go b/cmd/create.go index 08ffe28..6a3c7bd 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -22,6 +22,7 @@ import ( "github.com/apppackio/apppack/bridge" "github.com/apppackio/apppack/stacks" "github.com/apppackio/apppack/ui" + "github.com/apppackio/apppack/utils" "github.com/aws/aws-sdk-go/aws/session" "github.com/logrusorgru/aurora" "github.com/spf13/cobra" @@ -293,7 +294,7 @@ var createRegionCmd = &cobra.Command{ Short: "setup AppPack resources for an AWS region", Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) region := sess.Config.Region @@ -310,7 +311,7 @@ var createRegionCmd = &cobra.Command{ func init() { rootCmd.AddCommand(createCmd) - createCmd.PersistentFlags().StringVarP(&AccountIDorAlias, "account", "c", "", "AWS account ID or alias (not needed if you are only the administrator of one account)") + createCmd.PersistentFlags().StringVarP(&AccountIDorAlias, "account", "c", "", utils.AccountFlagHelpText) createCmd.PersistentFlags().BoolVar(&UseAWSCredentials, "aws-credentials", false, "use AWS credentials instead of AppPack.io federation") createCmd.PersistentFlags().BoolVar(&createChangeSet, "check", false, "check stack in Cloudformation before creating") createCmd.PersistentFlags().BoolVar(&nonInteractive, "non-interactive", false, "do not prompt for missing flags") diff --git a/cmd/destroy.go b/cmd/destroy.go index f85d4db..8871d65 100644 --- a/cmd/destroy.go +++ b/cmd/destroy.go @@ -20,6 +20,7 @@ import ( "github.com/apppackio/apppack/stacks" "github.com/apppackio/apppack/ui" + "github.com/apppackio/apppack/utils" "github.com/aws/aws-sdk-go/aws/session" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -80,7 +81,7 @@ var destroyAccountCmd = &cobra.Command{ Short: "destroy AWS resources used by your AppPack account", Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -94,7 +95,7 @@ var destroyRegionCmd = &cobra.Command{ Short: "destroy AWS resources used by an AppPack region", Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -109,7 +110,7 @@ var destroyRedisCmd = &cobra.Command{ Long: "*Requires admin permissions.*", Args: cobra.ExactArgs(1), DisableFlagsInUseLine: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -124,7 +125,7 @@ var destroyDatabaseCmd = &cobra.Command{ Long: "*Requires admin permissions.*", Args: cobra.ExactArgs(1), DisableFlagsInUseLine: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -139,7 +140,7 @@ var destroyClusterCmd = &cobra.Command{ Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -154,7 +155,7 @@ var destroyAppCmd = &cobra.Command{ Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -169,7 +170,7 @@ var destroyPipelineCmd = &cobra.Command{ Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -184,7 +185,7 @@ var destroyCustomDomainCmd = &cobra.Command{ Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -194,7 +195,7 @@ var destroyCustomDomainCmd = &cobra.Command{ func init() { rootCmd.AddCommand(destroyCmd) - destroyCmd.PersistentFlags().StringVarP(&AccountIDorAlias, "account", "c", "", "AWS account ID or alias (not needed if you are only the administrator of one account)") + destroyCmd.PersistentFlags().StringVarP(&AccountIDorAlias, "account", "c", "", utils.AccountFlagHelpText) destroyCmd.PersistentFlags().BoolVar(&UseAWSCredentials, "aws-credentials", false, "use AWS credentials instead of AppPack.io federation") destroyCmd.PersistentFlags().StringVar(®ion, "region", "", "AWS region to destroy resources in") diff --git a/cmd/modify.go b/cmd/modify.go index 5f04611..a6730a1 100644 --- a/cmd/modify.go +++ b/cmd/modify.go @@ -90,7 +90,7 @@ package cmd // func init() { // rootCmd.AddCommand(modifyCmd) -// modifyCmd.PersistentFlags().StringVarP(&AccountIDorAlias, "account", "c", "", "AWS account ID or alias (not needed if you are only the administrator of one account)") +// modifyCmd.PersistentFlags().StringVarP(&AccountIDorAlias, "account", "c", "", utils.AccountFlagHelpText) // modifyCmd.PersistentFlags().BoolVar(&UseAWSCredentials, "aws-credentials", false, "use AWS credentials instead of AppPack.io federation") // modifyCmd.PersistentFlags().BoolVar(&createChangeSet, "check", false, "check stack in Cloudformation before creating") // modifyCmd.PersistentFlags().BoolVar(&nonInteractive, "non-interactive", false, "do not prompt for user input") diff --git a/cmd/root.go b/cmd/root.go index 3f11394..c065119 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -50,6 +50,14 @@ var ( MaxSessionDurationSeconds = 3600 ) +func userHasMultipleAccounts() bool { + ui.StartSpinner() + admins, err := auth.AdminList() + checkErr(err) + ui.Spinner.Stop() + return len(admins) > 1 +} + // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "apppack", @@ -57,13 +65,22 @@ var rootCmd = &cobra.Command{ Long: `AppPack is a tool to manage applications deployed on AWS via AppPack.io`, DisableAutoGenTag: true, DisableFlagsInUseLine: true, - PersistentPreRun: func(cmd *cobra.Command, args []string) { + PersistentPreRun: func(_ *cobra.Command, _ []string) { if debug { logrus.SetOutput(os.Stdout) logrus.SetLevel(logrus.DebugLevel) } else { logrus.SetLevel(logrus.ErrorLevel) } + // Check for account flag or environment variable + if AccountIDorAlias == "" { + AccountIDorAlias = os.Getenv("APPPACK_ACCOUNT") + } + + // If neither is set and the user has multiple accounts, throw an error + if AccountIDorAlias == "" && userHasMultipleAccounts() { + checkErr(fmt.Errorf("you must specify an account using the -c flag or the APPPACK_ACCOUNT environment variable")) + } }, } diff --git a/cmd/stacks.go b/cmd/stacks.go index 787972f..f42a93d 100644 --- a/cmd/stacks.go +++ b/cmd/stacks.go @@ -23,6 +23,7 @@ import ( "github.com/apppackio/apppack/bridge" "github.com/apppackio/apppack/ui" + "github.com/apppackio/apppack/utils" "github.com/aws/aws-sdk-go/service/cloudformation" "github.com/juju/ansiterm/tabwriter" "github.com/logrusorgru/aurora" @@ -67,7 +68,7 @@ var stacksCmd = &cobra.Command{ Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { ui.StartSpinner() sess, err := adminSession(SessionDurationSeconds) checkErr(err) @@ -113,6 +114,6 @@ var stacksCmd = &cobra.Command{ func init() { rootCmd.AddCommand(stacksCmd) - stacksCmd.PersistentFlags().StringVarP(&AccountIDorAlias, "account", "c", "", "AWS account ID or alias (not needed if you are only the administrator of one account)") + stacksCmd.PersistentFlags().StringVarP(&AccountIDorAlias, "account", "c", "", utils.AccountFlagHelpText) stacksCmd.PersistentFlags().BoolVar(&UseAWSCredentials, "aws-credentials", false, "use AWS credentials instead of AppPack.io federation") } diff --git a/cmd/upgrade.go b/cmd/upgrade.go index 703973f..24d317a 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -20,6 +20,7 @@ import ( "github.com/apppackio/apppack/stacks" "github.com/apppackio/apppack/ui" + "github.com/apppackio/apppack/utils" "github.com/aws/aws-sdk-go/aws/session" "github.com/logrusorgru/aurora" "github.com/spf13/cobra" @@ -75,7 +76,7 @@ var upgradeAccountCmd = &cobra.Command{ Short: "upgrade your AppPack account stack", Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -89,7 +90,7 @@ var upgradeRegionCmd = &cobra.Command{ Short: "upgrade your AppPack region stack", Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -104,7 +105,7 @@ var upgradeAppCmd = &cobra.Command{ Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -119,7 +120,7 @@ var upgradePipelineCmd = &cobra.Command{ Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -134,7 +135,7 @@ var upgradeClusterCmd = &cobra.Command{ Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -149,7 +150,7 @@ var upgradeRedisCmd = &cobra.Command{ Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -164,7 +165,7 @@ var upgradeDatabaseCmd = &cobra.Command{ Long: "*Requires admin permissions.*", DisableFlagsInUseLine: true, Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { ui.StartSpinner() sess, err := adminSession(MaxSessionDurationSeconds) checkErr(err) @@ -174,7 +175,7 @@ var upgradeDatabaseCmd = &cobra.Command{ func init() { rootCmd.AddCommand(upgradeCmd) - upgradeCmd.PersistentFlags().StringVarP(&AccountIDorAlias, "account", "c", "", "AWS account ID or alias (not needed if you are only the administrator of one account)") + upgradeCmd.PersistentFlags().StringVarP(&AccountIDorAlias, "account", "c", "", utils.AccountFlagHelpText) upgradeCmd.PersistentFlags().BoolVar(&UseAWSCredentials, "aws-credentials", false, "use AWS credentials instead of AppPack.io federation") upgradeCmd.PersistentFlags().BoolVar(&createChangeSet, "check", false, "check stack in Cloudformation before creating") upgradeCmd.PersistentFlags().StringVar(®ion, "region", "", "AWS region to upgrade resources in") diff --git a/utils/utils.go b/utils/utils.go new file mode 100644 index 0000000..b0f250a --- /dev/null +++ b/utils/utils.go @@ -0,0 +1,3 @@ +package utils + +var AccountFlagHelpText string = "AWS account ID or alias. Use this flag to override the APPPACK_ACCOUNT environment variable (not needed if you are the administrator of only one account)."