diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ba28ea5 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +PACKAGES = $(shell go list ./... | grep -v '/vendor/') +format: + @echo "--> Running go fmt" + @go fmt $(PACKAGES) diff --git a/command/amazon.go b/command/amazon.go new file mode 100644 index 0000000..3e9c985 --- /dev/null +++ b/command/amazon.go @@ -0,0 +1,18 @@ +package command + +import ( + "github.com/aws/aws-sdk-go/service/autoscaling" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/elb" + "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go/service/s3" +) + +type AmazonServices struct { + Iam *iam.IAM + Ec2 *ec2.EC2 + Elb *elb.ELB + Asg *autoscaling.AutoScaling + S3 *s3.S3 + S3Keys *s3.S3 +} diff --git a/command/canary.go b/command/canary.go index 9649b62..d5d6c9d 100644 --- a/command/canary.go +++ b/command/canary.go @@ -6,10 +6,10 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/autoscaling" "github.com/hello/sanders/ui" + "sort" + "strconv" "strings" "time" - "strconv" - "sort" ) const plan = ` @@ -202,12 +202,12 @@ func (c *CanaryCommand) update(service *autoscaling.AutoScaling, desiredCapacity return resp, err } -func (c *CanaryCommand) updateASGTag(service *autoscaling.AutoScaling, asgName string, tagName string, tagValue string, propagate bool) (*autoscaling.CreateOrUpdateTagsOutput, error){ +func (c *CanaryCommand) updateASGTag(service *autoscaling.AutoScaling, asgName string, tagName string, tagValue string, propagate bool) (*autoscaling.CreateOrUpdateTagsOutput, error) { //Tag the ASG so version number can be passed to instance params := &autoscaling.CreateOrUpdateTagsInput{ - Tags: []*autoscaling.Tag{// Required - {// Required + Tags: []*autoscaling.Tag{ // Required + { // Required Key: aws.String(tagName), // Required PropagateAtLaunch: aws.Bool(propagate), ResourceId: aws.String(asgName), diff --git a/command/clean.go b/command/clean.go index ea6a500..7868c2a 100644 --- a/command/clean.go +++ b/command/clean.go @@ -3,7 +3,6 @@ package command import ( "fmt" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/autoscaling" "github.com/mitchellh/cli" "sort" @@ -13,6 +12,7 @@ import ( type CleanCommand struct { Ui cli.ColoredUi Notifier BasicNotifier + Services *AmazonServices } func (c *CleanCommand) Help() string { @@ -22,12 +22,6 @@ func (c *CleanCommand) Help() string { func (c *CleanCommand) Run(args []string) int { - config := &aws.Config{ - Region: aws.String("us-east-1"), - } - - asgService := autoscaling.New(session.New(), config) - lcParams := &autoscaling.DescribeLaunchConfigurationsInput{ MaxRecords: aws.Int64(100), } @@ -35,7 +29,7 @@ func (c *CleanCommand) Run(args []string) int { pageNum := 0 allLcs := make([]*autoscaling.LaunchConfiguration, 0) - pageErr := asgService.DescribeLaunchConfigurationsPages(lcParams, func(page *autoscaling.DescribeLaunchConfigurationsOutput, lastPage bool) bool { + pageErr := c.Services.Asg.DescribeLaunchConfigurationsPages(lcParams, func(page *autoscaling.DescribeLaunchConfigurationsOutput, lastPage bool) bool { pageNum++ if len(page.LaunchConfigurations) == 0 { return false @@ -80,7 +74,7 @@ func (c *CleanCommand) Run(args []string) int { params := &autoscaling.DeleteLaunchConfigurationInput{ LaunchConfigurationName: lcName, } - _, err := asgService.DeleteLaunchConfiguration(params) + _, err := c.Services.Asg.DeleteLaunchConfiguration(params) if err != nil { // Print the error, cast err to awserr.Error to get the Code and diff --git a/command/create.go b/command/create.go index 2eab1af..a6d7301 100644 --- a/command/create.go +++ b/command/create.go @@ -2,9 +2,9 @@ package command import ( "bytes" - "encoding/base64" "crypto/sha1" - "io" + "encoding/base64" + "flag" "fmt" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" @@ -12,11 +12,11 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/s3" "github.com/mitchellh/cli" + "io" "sort" "strconv" "strings" "time" - "flag" ) type suripuApp struct { @@ -28,7 +28,7 @@ type suripuApp struct { targetDesiredCapacity int64 //This is the desired capacity of the asg targeted for deployment usesPacker bool javaVersion int - packagePath string + packagePath string } //This hash should be updated anytime default_userdata.sh is updated on S3 @@ -43,7 +43,7 @@ var suripuApps []suripuApp = []suripuApp{ targetDesiredCapacity: 2, usesPacker: false, javaVersion: 7, - packagePath: "com/hello/suripu"}, + packagePath: "com/hello/suripu"}, suripuApp{ name: "suripu-service", sg: "sg-11ac0e75", @@ -52,7 +52,7 @@ var suripuApps []suripuApp = []suripuApp{ targetDesiredCapacity: 4, usesPacker: false, javaVersion: 7, - packagePath: "com/hello/suripu"}, + packagePath: "com/hello/suripu"}, suripuApp{ name: "suripu-workers", sg: "sg-7054d714", @@ -61,7 +61,7 @@ var suripuApps []suripuApp = []suripuApp{ targetDesiredCapacity: 2, usesPacker: false, javaVersion: 7, - packagePath: "com/hello/suripu"}, + packagePath: "com/hello/suripu"}, suripuApp{ name: "suripu-admin", sg: "sg-71773a16", @@ -70,7 +70,7 @@ var suripuApps []suripuApp = []suripuApp{ targetDesiredCapacity: 1, usesPacker: false, javaVersion: 7, - packagePath: "com/hello/suripu"}, + packagePath: "com/hello/suripu"}, suripuApp{ name: "logsindexer", sg: "sg-36f95050", @@ -79,7 +79,7 @@ var suripuApps []suripuApp = []suripuApp{ targetDesiredCapacity: 1, usesPacker: false, javaVersion: 8, - packagePath: "com/hello/suripu"}, + packagePath: "com/hello/suripu"}, suripuApp{ name: "sense-firehose", sg: "sg-5296b834", @@ -88,7 +88,7 @@ var suripuApps []suripuApp = []suripuApp{ targetDesiredCapacity: 1, usesPacker: false, javaVersion: 8, - packagePath: "com/hello/suripu"}, + packagePath: "com/hello/suripu"}, suripuApp{ name: "hello-time", sg: "sg-5c371525", @@ -97,7 +97,7 @@ var suripuApps []suripuApp = []suripuApp{ targetDesiredCapacity: 2, usesPacker: false, javaVersion: 7, - packagePath: "com/hello/time"}, + packagePath: "com/hello/time"}, suripuApp{ name: "suripu-queue", sg: "sg-3e55ba46", @@ -106,7 +106,7 @@ var suripuApps []suripuApp = []suripuApp{ targetDesiredCapacity: 1, usesPacker: false, javaVersion: 7, - packagePath: "com/hello/suripu"}, + packagePath: "com/hello/suripu"}, suripuApp{ name: "messeji", sg: "sg-45c5c73c", @@ -115,7 +115,7 @@ var suripuApps []suripuApp = []suripuApp{ targetDesiredCapacity: 4, usesPacker: false, javaVersion: 8, - packagePath: "com/hello"}, + packagePath: "com/hello"}, suripuApp{ name: "taimurain", sg: "sg-b3f631c8", @@ -124,7 +124,7 @@ var suripuApps []suripuApp = []suripuApp{ targetDesiredCapacity: 3, usesPacker: true, javaVersion: 8, - packagePath: "com/hello"}, + packagePath: "com/hello"}, } var keyBucket string = "hello-keys" @@ -298,7 +298,6 @@ func (c *CreateCommand) Run(args []string) int { amiVersion = amiNameInfo[1] } - } else { canaryPath := "" @@ -427,9 +426,9 @@ func (c *CreateCommand) Run(args []string) int { key := fmt.Sprintf("/%s/%s/%s.pem", environment, selectedApp.name, *keyPairResp.KeyName) uploadResult, err := s3KeyService.PutObject(&s3.PutObjectInput{ - Body: strings.NewReader(*keyPairResp.KeyMaterial), - Bucket: aws.String(keyBucket), - Key: &key, + Body: strings.NewReader(*keyPairResp.KeyMaterial), + Bucket: aws.String(keyBucket), + Key: &key, }) if err != nil { @@ -447,8 +446,8 @@ func (c *CreateCommand) Run(args []string) int { InstanceMonitoring: &autoscaling.InstanceMonitoring{ Enabled: aws.Bool(true), }, - InstanceType: aws.String(selectedApp.instanceType), - KeyName: aws.String(keyName), + InstanceType: aws.String(selectedApp.instanceType), + KeyName: aws.String(keyName), SecurityGroups: []*string{ aws.String(selectedApp.sg), // Required }, @@ -490,7 +489,7 @@ func (c *CreateCommand) Run(args []string) int { return 0 } -func Cleanup(keyName string, objectName string, ui cli.ColoredUi ) bool { +func Cleanup(keyName string, objectName string, ui cli.ColoredUi) bool { ui.Info("") ui.Info(fmt.Sprintf("Cleaning up created KeyPair: %s", keyName)) @@ -515,8 +514,8 @@ func Cleanup(keyName string, objectName string, ui cli.ColoredUi ) bool { //Delete pem file from s3 delParams := &s3.DeleteObjectInput{ - Bucket: aws.String(keyBucket), // Required - Key: aws.String(objectName), // Required + Bucket: aws.String(keyBucket), // Required + Key: aws.String(objectName), // Required } _, objErr := s3KeyService.DeleteObject(delParams) diff --git a/command/hosts.go b/command/hosts.go index 2f678c3..103378e 100644 --- a/command/hosts.go +++ b/command/hosts.go @@ -42,11 +42,11 @@ func (c *HostsCommand) Run(args []string) int { groupnames := make([]*string, 0) for _, app := range suripuApps { - one := fmt.Sprintf("%s-prod", app.name) - two := fmt.Sprintf("%s-prod-green", app.name) - groupnames = append(groupnames, &one) - groupnames = append(groupnames, &two) - } + one := fmt.Sprintf("%s-prod", app.name) + two := fmt.Sprintf("%s-prod-green", app.name) + groupnames = append(groupnames, &one) + groupnames = append(groupnames, &two) + } req := &autoscaling.DescribeAutoScalingGroupsInput{ AutoScalingGroupNames: groupnames, diff --git a/command/monitor.go b/command/monitor.go index 7175e77..11d748c 100644 --- a/command/monitor.go +++ b/command/monitor.go @@ -1,15 +1,15 @@ package command import ( - "fmt" - "github.com/aws/aws-sdk-go/aws" + "fmt" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/elb" - "github.com/mitchellh/cli" - "strings" - "strconv" - "time" + "github.com/mitchellh/cli" + "strconv" + "strings" + "time" ) type MonitorCommand struct { @@ -28,7 +28,7 @@ func (c *MonitorCommand) Run(args []string) int { Region: aws.String("us-east-1"), } - elbs := []string{ + elbs := []string{ "suripu-service-prod", "suripu-app-prod", "suripu-app-canary", @@ -41,7 +41,7 @@ func (c *MonitorCommand) Run(args []string) int { service := elb.New(session.New(), config) ec2Service := ec2.New(session.New(), config) - for idx, elb := range elbs { + for idx, elb := range elbs { c.Ui.Output(fmt.Sprintf("[%d] %s", idx, elb)) } @@ -55,17 +55,16 @@ func (c *MonitorCommand) Run(args []string) int { selectedElb := elbs[elbIdx] - for { - status := elbStatus(selectedElb, service, ec2Service) - printStatus(c.Ui, status) - c.Ui.Output("\nSleeping for 10 seconds...\n") - time.Sleep(10000 * time.Millisecond) - } + for { + status := elbStatus(selectedElb, service, ec2Service) + printStatus(c.Ui, status) + c.Ui.Output("\nSleeping for 10 seconds...\n") + time.Sleep(10000 * time.Millisecond) + } - return 0 + return 0 } - func (c *MonitorCommand) Synopsis() string { return "Monitor ELB status" } diff --git a/command/status.go b/command/status.go index 996a39f..acd7d5c 100644 --- a/command/status.go +++ b/command/status.go @@ -2,8 +2,6 @@ package command import ( "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/elb" "github.com/mitchellh/cli" @@ -13,6 +11,7 @@ import ( type StatusCommand struct { Ui cli.ColoredUi Notifier BasicNotifier + Services *AmazonServices } func (c *StatusCommand) Help() string { @@ -43,13 +42,6 @@ func fetch(elbName string, service *elb.ELB, ec2Service *ec2.EC2, statuses chan func (c *StatusCommand) Run(args []string) int { - config := &aws.Config{ - Region: aws.String("us-east-1"), - } - - service := elb.New(session.New(), config) - ec2Service := ec2.New(session.New(), config) - elbs := []string{ "suripu-service-prod", "suripu-app-prod", @@ -63,7 +55,7 @@ func (c *StatusCommand) Run(args []string) int { statuses := make(chan *Status, 0) for _, elbName := range elbs { - go fetch(elbName, service, ec2Service, statuses) + go fetch(elbName, c.Services.Elb, c.Services.Ec2, statuses) c.Ui.Info(fmt.Sprintf("Fetching: ELB %s", elbName)) } @@ -197,27 +189,27 @@ func printStatus(ui cli.ColoredUi, status *Status) { if status.State == "InService" { ui.Info(fmt.Sprintf("\tVersion: %s", status.Version)) ui.Info(fmt.Sprintf("\tID: %s", status.InstanceId)) - ui.Info(fmt.Sprintf("\tState: %s", status.State)) ui.Info(fmt.Sprintf("\tLaunched: %s", status.Launched)) + ui.Info(fmt.Sprintf("\tState: %s", status.State)) ui.Info(fmt.Sprintf("\tHostname: %s", status.Hostname)) ui.Info(fmt.Sprintf("\tPrivate DNS: %s", status.PrivateDnsName)) } else if status.Reason == "Instance is in pending state" { ui.Warn(fmt.Sprintf("\tVersion: %s", status.Version)) ui.Warn(fmt.Sprintf("\tID: %s", status.InstanceId)) + ui.Warn(fmt.Sprintf("\tLaunched: %s", status.Launched)) ui.Warn(fmt.Sprintf("\tState: %s", status.State)) ui.Warn(fmt.Sprintf("\tReason: %s", status.Reason)) ui.Warn(fmt.Sprintf("\tDescription: %s", status.Description)) - ui.Warn(fmt.Sprintf("\tLaunched: %s", status.Launched)) ui.Warn(fmt.Sprintf("\tHostname: %s", status.Hostname)) ui.Warn(fmt.Sprintf("\tPrivate DNS: %s", status.PrivateDnsName)) } else { ui.Error(fmt.Sprintf("\tVersion: %s", status.Version)) ui.Error(fmt.Sprintf("\tID: %s", status.InstanceId)) + ui.Error(fmt.Sprintf("\tLaunched: %s", status.Launched)) ui.Error(fmt.Sprintf("\tState: %s", status.State)) ui.Error(fmt.Sprintf("\tReason: %s", status.Reason)) ui.Error(fmt.Sprintf("\tDescription: %s", status.Description)) - ui.Error(fmt.Sprintf("\tLaunched: %s", status.Launched)) ui.Error(fmt.Sprintf("\tHostname: %s", status.Hostname)) ui.Error(fmt.Sprintf("\tPrivate DNS: %s", status.PrivateDnsName)) } diff --git a/command/sunset.go b/command/sunset.go index e605baf..4e8cf14 100644 --- a/command/sunset.go +++ b/command/sunset.go @@ -1,13 +1,9 @@ package command import ( - "github.com/aws/aws-sdk-go/aws" + "fmt" "github.com/aws/aws-sdk-go/service/autoscaling" "github.com/mitchellh/cli" - // "github.com/mitchellh/packer/packer" - "fmt" - // "sort" - "github.com/aws/aws-sdk-go/aws/session" "strconv" "strings" ) @@ -15,6 +11,7 @@ import ( type SunsetCommand struct { Ui cli.ColoredUi Notifier BasicNotifier + Services *AmazonServices } func (c *SunsetCommand) Help() string { @@ -32,13 +29,6 @@ Plan: --- # of servers: %d ` - - config := &aws.Config{ - Region: aws.String("us-east-1"), - } - - service := autoscaling.New(session.New(), config) - c.Ui.Output("Which of the following apps do you want to sunset?\n") for idx, app := range suripuApps { @@ -64,7 +54,7 @@ Plan: AutoScalingGroupNames: groupnames, } - describeASGResp, err := service.DescribeAutoScalingGroups(describeASGreq) + describeASGResp, err := c.Services.Asg.DescribeAutoScalingGroups(describeASGreq) if err != nil { c.Ui.Error(fmt.Sprintf("%s", err)) return 1 @@ -155,7 +145,7 @@ Plan: c.Ui.Info("Executing plan:") c.Ui.Info(fmt.Sprintf(plan, sunsetAsg, "N/A", *updateReq.DesiredCapacity)) - _, err = service.UpdateAutoScalingGroup(updateReq) + _, err = c.Services.Asg.UpdateAutoScalingGroup(updateReq) if err != nil { c.Ui.Error(fmt.Sprintf("%s", err)) return 1 diff --git a/command/types.go b/command/types.go index e3b4950..389002a 100644 --- a/command/types.go +++ b/command/types.go @@ -64,7 +64,7 @@ func (n SlackNotifier) Notify(action *DeployAction) error { AuthorName: n.username, Fields: fields, Color: actionColors[action.CmdType], - Fallback: action.FallbackString(), + Fallback: action.FallbackString(), } payload := &Payload{ diff --git a/commands.go b/commands.go index 1be72f7..39349b0 100644 --- a/commands.go +++ b/commands.go @@ -4,7 +4,11 @@ import ( "fmt" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/autoscaling" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/elb" "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go/service/s3" "github.com/hello/sanders/command" "github.com/hello/sanders/ui" "github.com/mitchellh/cli" @@ -20,9 +24,6 @@ var ( ) func init() { - config := &aws.Config{ - Region: aws.String("us-east-1"), - } cui := cli.ColoredUi{ InfoColor: cli.UiColorGreen, ErrorColor: cli.UiColorRed, @@ -33,10 +34,26 @@ func init() { }, } - iamService := iam.New(session.New(), config) + config := &aws.Config{ + Region: aws.String("us-east-1"), + } + keyConfig := &aws.Config{ + Region: aws.String("us-west-1"), + } + + sess := session.New() + amazon := &command.AmazonServices{ + Iam: iam.New(sess, config), + Asg: autoscaling.New(sess, config), + Ec2: ec2.New(sess, config), + Elb: elb.New(sess, config), + S3: s3.New(sess, config), + S3Keys: s3.New(sess, keyConfig), + } + getUserReq := &iam.GetUserInput{} - resp, err := iamService.GetUser(getUserReq) + resp, err := amazon.Iam.GetUser(getUserReq) if err != nil { cui.Ui.Error(fmt.Sprintln(err.Error())) @@ -52,15 +69,26 @@ func init() { notifier := command.NewSlackNotifier(user) Commands = map[string]cli.CommandFactory{ - - "status": func() (cli.Command, error) { - return &command.StatusCommand{ + "canary": func() (cli.Command, error) { + return &command.CanaryCommand{ + Ui: cpui, + Notifier: notifier, + }, nil + }, + "clean": func() (cli.Command, error) { + return &command.CleanCommand{ + Ui: cui, + Services: amazon, + }, nil + }, + "confirm": func() (cli.Command, error) { + return &command.ConfirmCommand{ Ui: cui, Notifier: notifier, }, nil }, - "sunset": func() (cli.Command, error) { - return &command.SunsetCommand{ + "create": func() (cli.Command, error) { + return &command.CreateCommand{ Ui: cui, Notifier: notifier, }, nil @@ -77,41 +105,33 @@ func init() { Notifier: notifier, }, nil }, - "canary": func() (cli.Command, error) { - return &command.CanaryCommand{ - Ui: cpui, - Notifier: notifier, - }, nil - }, - "confirm": func() (cli.Command, error) { - return &command.ConfirmCommand{ + "monitor": func() (cli.Command, error) { + return &command.MonitorCommand{ Ui: cui, Notifier: notifier, }, nil }, - "create": func() (cli.Command, error) { - return &command.CreateCommand{ + "status": func() (cli.Command, error) { + return &command.StatusCommand{ Ui: cui, Notifier: notifier, + Services: amazon, }, nil }, - "monitor": func() (cli.Command, error) { - return &command.MonitorCommand{ + "sunset": func() (cli.Command, error) { + return &command.SunsetCommand{ Ui: cui, Notifier: notifier, + Services: amazon, }, nil }, + "version": func() (cli.Command, error) { return &command.VersionCommand{ Ui: cui, GitCommit: GitCommit, }, nil }, - "clean": func() (cli.Command, error) { - return &command.CleanCommand{ - Ui: cui, - }, nil - }, } } diff --git a/main.go b/main.go index 2dd7f92..0243103 100644 --- a/main.go +++ b/main.go @@ -38,7 +38,7 @@ func realMain() int { } cli := &cli.CLI{ - Name: "sanders", + Name: "sanders", Args: args, Commands: Commands, }