From 2943a1c978137a75edbcbda2c9c1121c5219bbe2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 7 Jul 2016 13:24:17 -0700 Subject: [PATCH] Retry creation of IAM role depending on new IAM user (#7324) --- builtin/providers/aws/awserr.go | 14 +++++++++ .../providers/aws/resource_aws_iam_role.go | 13 +++++++- .../providers/aws/resource_aws_instance.go | 31 +++++++++---------- 3 files changed, 40 insertions(+), 18 deletions(-) create mode 100644 builtin/providers/aws/awserr.go diff --git a/builtin/providers/aws/awserr.go b/builtin/providers/aws/awserr.go new file mode 100644 index 000000000000..8fc056801b4e --- /dev/null +++ b/builtin/providers/aws/awserr.go @@ -0,0 +1,14 @@ +package aws + +import ( + "strings" + + "github.com/aws/aws-sdk-go/aws/awserr" +) + +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/builtin/providers/aws/resource_aws_iam_role.go b/builtin/providers/aws/resource_aws_iam_role.go index effb95c36daa..43d292b0d5df 100644 --- a/builtin/providers/aws/resource_aws_iam_role.go +++ b/builtin/providers/aws/resource_aws_iam_role.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "regexp" + "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" @@ -103,7 +104,17 @@ func resourceAwsIamRoleCreate(d *schema.ResourceData, meta interface{}) error { AssumeRolePolicyDocument: aws.String(d.Get("assume_role_policy").(string)), } - createResp, err := iamconn.CreateRole(request) + var createResp *iam.CreateRoleOutput + err := resource.Retry(10*time.Second, func() *resource.RetryError { + var err error + createResp, err = iamconn.CreateRole(request) + // IAM roles can take ~10 seconds to propagate in AWS: + // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console + if isAWSErr(err, "MalformedPolicyDocument", "Invalid principal in policy") { + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + }) if err != nil { return fmt.Errorf("Error creating IAM Role %s: %s", name, err) } diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index e43a20b1042b..7681d6ed21e7 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -361,25 +361,22 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { log.Printf("[DEBUG] Run configuration: %s", runOpts) var runResp *ec2.Reservation - for i := 0; i < 5; i++ { + err = resource.Retry(10*time.Second, func() *resource.RetryError { + var err error runResp, err = conn.RunInstances(runOpts) - if awsErr, ok := err.(awserr.Error); ok { - // IAM profiles can take ~10 seconds to propagate in AWS: - // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console - if awsErr.Code() == "InvalidParameterValue" && strings.Contains(awsErr.Message(), "Invalid IAM Instance Profile") { - log.Printf("[DEBUG] Invalid IAM Instance Profile referenced, retrying...") - time.Sleep(2 * time.Second) - continue - } - - // Warn if the AWS Error involves group ids, to help identify situation - // where a user uses group ids in security_groups for the Default VPC. - // See https://github.com/hashicorp/terraform/issues/3798 - if awsErr.Code() == "InvalidParameterValue" && strings.Contains(awsErr.Message(), "groupId is invalid") { - return fmt.Errorf("Error launching instance, possible mismatch of Security Group IDs and Names. See AWS Instance docs here: %s.\n\n\tAWS Error: %s", "https://terraform.io/docs/providers/aws/r/instance.html", awsErr.Message()) - } + // IAM profiles can take ~10 seconds to propagate in AWS: + // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console + if isAWSErr(err, "InvalidParameterValue", "Invalid IAM Instance Profile") { + log.Printf("[DEBUG] Invalid IAM Instance Profile referenced, retrying...") + return resource.RetryableError(err) } - break + return resource.NonRetryableError(err) + }) + // Warn if the AWS Error involves group ids, to help identify situation + // where a user uses group ids in security_groups for the Default VPC. + // See https://github.com/hashicorp/terraform/issues/3798 + if isAWSErr(err, "InvalidParameterValue", "groupId is invalid") { + return fmt.Errorf("Error launching instance, possible mismatch of Security Group IDs and Names. See AWS Instance docs here: %s.\n\n\tAWS Error: %s", "https://terraform.io/docs/providers/aws/r/instance.html", err.(awserr.Error).Message()) } if err != nil { return fmt.Errorf("Error launching source instance: %s", err)