From 488e539f63cd9c2207b641e07fbc4ebf6be65e1e Mon Sep 17 00:00:00 2001 From: nywilken Date: Tue, 12 Nov 2019 15:27:47 -0500 Subject: [PATCH] builder/amazon: Add helper function for checking against AWSError Replace all straight forward occurrences of `if err, ok := err.(awserr.Error)` with the `isAWSErr` helper function --- builder/amazon/common/access_config.go | 19 +++++----- builder/amazon/common/helper_funcs.go | 14 ++++++++ builder/amazon/common/step_create_tags.go | 18 ++++------ builder/amazon/common/step_pre_validate.go | 3 +- .../amazon/common/step_run_source_instance.go | 35 +++++++------------ .../amazon/common/step_run_spot_instance.go | 18 ++++------ .../amazon/common/step_stop_ebs_instance.go | 18 ++++------ 7 files changed, 55 insertions(+), 70 deletions(-) diff --git a/builder/amazon/common/access_config.go b/builder/amazon/common/access_config.go index 9cee33c14..a32decf07 100644 --- a/builder/amazon/common/access_config.go +++ b/builder/amazon/common/access_config.go @@ -11,7 +11,6 @@ import ( "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" @@ -181,15 +180,17 @@ func (c *AccessConfig) Session() (*session.Session, error) { c.session = sess cp, err := c.session.Config.Credentials.Get() - if err != nil { - if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NoCredentialProviders" { - return nil, fmt.Errorf("No valid credential sources found for AWS Builder. " + - "Please see https://www.packer.io/docs/builders/amazon.html#specifying-amazon-credentials " + - "for more information on providing credentials for the AWS Builder.") - } else { - return nil, fmt.Errorf("Error loading credentials for AWS Provider: %s", err) - } + + if isAWSErr(err, "NoCredentialProviders", "") { + return nil, fmt.Errorf("No valid credential sources found for AWS Builder. " + + "Please see https://www.packer.io/docs/builders/amazon.html#specifying-amazon-credentials " + + "for more information on providing credentials for the AWS Builder.") } + + if err != nil { + return nil, fmt.Errorf("Error loading credentials for AWS Provider: %s", err) + } + log.Printf("[INFO] AWS Auth provider used: %q", cp.ProviderName) if c.DecodeAuthZMessages { diff --git a/builder/amazon/common/helper_funcs.go b/builder/amazon/common/helper_funcs.go index 8ad37c6bb..dc03c13c3 100644 --- a/builder/amazon/common/helper_funcs.go +++ b/builder/amazon/common/helper_funcs.go @@ -3,11 +3,14 @@ package common import ( "fmt" "log" + "strings" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" ) +// DestroyAMIs deregisters the AWS machine images in imageids from an active AWS account func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error { resp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ ImageIds: imageids, @@ -47,3 +50,14 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error { } return nil } + +// Returns true if the error matches all these conditions: +// * err is of type awserr.Error +// * Error.Code() matches code +// * Error.Message() contains message +func isAWSErr(err error, code string, message string) bool { + if err, ok := err.(awserr.Error); ok { + return err.Code() == code && strings.Contains(err.Message(), message) + } + return false +} diff --git a/builder/amazon/common/step_create_tags.go b/builder/amazon/common/step_create_tags.go index 68adc9878..0e785a202 100644 --- a/builder/amazon/common/step_create_tags.go +++ b/builder/amazon/common/step_create_tags.go @@ -6,7 +6,6 @@ import ( "time" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/packer/common/retry" @@ -91,17 +90,12 @@ func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) mult snapshotTags.Report(ui) // Retry creating tags for about 2.5 minutes - err = retry.Config{ - Tries: 11, - ShouldRetry: func(error) bool { - if awsErr, ok := err.(awserr.Error); ok { - switch awsErr.Code() { - case "InvalidAMIID.NotFound", "InvalidSnapshot.NotFound": - return true - } - } - return false - }, + err = retry.Config{Tries: 11, ShouldRetry: func(error) bool { + if isAWSErr(err, "InvalidAMIID.NotFound", "") || isAWSErr(err, "InvalidSnapshot.NotFound", "") { + return true + } + return false + }, RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { // Tag images and snapshots diff --git a/builder/amazon/common/step_pre_validate.go b/builder/amazon/common/step_pre_validate.go index 5aeecc2f6..8b5c46322 100644 --- a/builder/amazon/common/step_pre_validate.go +++ b/builder/amazon/common/step_pre_validate.go @@ -7,7 +7,6 @@ import ( "time" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/packer/common/retry" "github.com/hashicorp/packer/helper/multistep" @@ -36,7 +35,7 @@ func (s *StepPreValidate) Run(ctx context.Context, state multistep.StateBag) mul err := retry.Config{ Tries: 11, ShouldRetry: func(err error) bool { - if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "AuthFailure" { + if isAWSErr(err, "AuthFailure", "") { log.Printf("Waiting for Vault-generated AWS credentials" + " to pass authentication... trying again.") return true diff --git a/builder/amazon/common/step_run_source_instance.go b/builder/amazon/common/step_run_source_instance.go index 96f9700bd..f13ff3da3 100644 --- a/builder/amazon/common/step_run_source_instance.go +++ b/builder/amazon/common/step_run_source_instance.go @@ -9,7 +9,6 @@ import ( "time" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/packer/common/retry" @@ -207,17 +206,12 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa // will fail. Retry a couple of times to try to mitigate that race. var r *ec2.DescribeInstancesOutput - err = retry.Config{ - Tries: 11, - ShouldRetry: func(err error) bool { - if awsErr, ok := err.(awserr.Error); ok { - switch awsErr.Code() { - case "InvalidInstanceID.NotFound": - return true - } - } - return false - }, + err = retry.Config{Tries: 11, ShouldRetry: func(err error) bool { + if isAWSErr(err, "InvalidInstanceID.NotFound", "") { + return true + } + return false + }, RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { r, err = ec2conn.DescribeInstances(describeInstance) @@ -254,17 +248,12 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa if s.IsRestricted { ec2Tags.Report(ui) // Retry creating tags for about 2.5 minutes - err = retry.Config{ - Tries: 11, - ShouldRetry: func(error) bool { - if awsErr, ok := err.(awserr.Error); ok { - switch awsErr.Code() { - case "InvalidInstanceID.NotFound": - return true - } - } - return false - }, + err = retry.Config{Tries: 11, ShouldRetry: func(error) bool { + if isAWSErr(err, "InvalidInstanceID.NotFound", "") { + return true + } + return false + }, RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { _, err := ec2conn.CreateTags(&ec2.CreateTagsInput{ diff --git a/builder/amazon/common/step_run_spot_instance.go b/builder/amazon/common/step_run_spot_instance.go index a9756337e..8cb92baf2 100644 --- a/builder/amazon/common/step_run_spot_instance.go +++ b/builder/amazon/common/step_run_spot_instance.go @@ -9,7 +9,6 @@ import ( "time" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/packer/common/random" "github.com/hashicorp/packer/common/retry" @@ -353,17 +352,12 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } // Retry creating tags for about 2.5 minutes - err = retry.Config{ - Tries: 11, - ShouldRetry: func(error) bool { - if awsErr, ok := err.(awserr.Error); ok { - switch awsErr.Code() { - case "InvalidInstanceID.NotFound": - return true - } - } - return false - }, + err = retry.Config{Tries: 11, ShouldRetry: func(error) bool { + if isAWSErr(err, "InvalidInstanceID.NotFound", "") { + return true + } + return false + }, RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { _, err := ec2conn.CreateTags(&ec2.CreateTagsInput{ diff --git a/builder/amazon/common/step_stop_ebs_instance.go b/builder/amazon/common/step_stop_ebs_instance.go index c48bb87c0..9c90269d3 100644 --- a/builder/amazon/common/step_stop_ebs_instance.go +++ b/builder/amazon/common/step_stop_ebs_instance.go @@ -5,7 +5,6 @@ import ( "fmt" "time" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/packer/common/retry" "github.com/hashicorp/packer/helper/multistep" @@ -41,17 +40,12 @@ func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.Sta // does not exist. // Work around this by retrying a few times, up to about 5 minutes. - err := retry.Config{ - Tries: 6, - ShouldRetry: func(error) bool { - if awsErr, ok := err.(awserr.Error); ok { - switch awsErr.Code() { - case "InvalidInstanceID.NotFound": - return true - } - } - return false - }, + err := retry.Config{Tries: 6, ShouldRetry: func(error) bool { + if isAWSErr(err, "InvalidInstanceID.NotFound", "") { + return true + } + return false + }, RetryDelay: (&retry.Backoff{InitialBackoff: 10 * time.Second, MaxBackoff: 60 * time.Second, Multiplier: 2}).Linear, }.Run(ctx, func(ctx context.Context) error { ui.Message(fmt.Sprintf("Stopping instance"))