From d05fc51aa0a465a5824f3f06beeca1e01799156f Mon Sep 17 00:00:00 2001 From: Jake Champlin Date: Wed, 17 May 2017 08:59:47 -0400 Subject: [PATCH] provider/aws: Handle LimitExceededException for subscriber limits - Updates aws-sdk-go/request for retryer fix - Fixes dynamoDB exception handling to catch subscriber limit error When the `aws-sdk-go` dep releases the next release, we can tag the vendor with the new release version, and merge this. Until then, soft-updated the vendor solely for the `request` package to post fix. DynamoDB Fix: ``` aws_dynamodb_table.bar: Creating... arn: "" => "" attribute.#: "" => "1" attribute.4228504427.name: "" => "id" attribute.4228504427.type: "" => "S" hash_key: "" => "id" name: "" => "over-cap-test" read_capacity: "" => "5" stream_arn: "" => "" stream_enabled: "" => "" stream_view_type: "" => "" write_capacity: "" => "5" Error applying plan: 1 error(s) occurred: * aws_dynamodb_table.bar: 1 error(s) occurred: * aws_dynamodb_table.bar: AWS Error creating DynamoDB table: LimitExceededException: Subscriber limit exceeded: There is a limit of 256 tables per subscriber status code: 400, request id: J2MC7MR060VKBPHP9P6JG5B6Q3VV4KQNSO5AEMVJF66Q9ASUAAJG ``` --- builtin/providers/aws/resource_aws_dynamodb_table.go | 11 ++++++++--- .../aws-sdk-go/aws/request/connection_reset_error.go | 2 +- .../aws/request/connection_reset_error_other.go | 11 +++++++++++ .../github.com/aws/aws-sdk-go/aws/request/request.go | 4 ++-- .../aws/aws-sdk-go/aws/request/request_1_7.go | 4 ++-- .../aws/aws-sdk-go/aws/request/request_1_8.go | 8 +++++--- .../github.com/aws/aws-sdk-go/aws/request/retryer.go | 1 - vendor/vendor.json | 8 +++----- 8 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other.go diff --git a/builtin/providers/aws/resource_aws_dynamodb_table.go b/builtin/providers/aws/resource_aws_dynamodb_table.go index 155da08f95..2644f164d1 100644 --- a/builtin/providers/aws/resource_aws_dynamodb_table.go +++ b/builtin/providers/aws/resource_aws_dynamodb_table.go @@ -321,15 +321,20 @@ func resourceAwsDynamoDbTableCreate(d *schema.ResourceData, meta interface{}) er output, err := dynamodbconn.CreateTable(req) if err != nil { if awsErr, ok := err.(awserr.Error); ok { - if awsErr.Code() == "ThrottlingException" { + switch code := awsErr.Code(); code { + case "ThrottlingException": log.Printf("[DEBUG] Attempt %d/%d: Sleeping for a bit to throttle back create request", attemptCount, DYNAMODB_MAX_THROTTLE_RETRIES) time.Sleep(DYNAMODB_THROTTLE_SLEEP) attemptCount += 1 - } else if awsErr.Code() == "LimitExceededException" { + case "LimitExceededException": + // If we're at resource capacity, error out without retry + if strings.Contains(awsErr.Message(), "Subscriber limit exceeded:") { + return fmt.Errorf("AWS Error creating DynamoDB table: %s", err) + } log.Printf("[DEBUG] Limit on concurrent table creations hit, sleeping for a bit") time.Sleep(DYNAMODB_LIMIT_EXCEEDED_SLEEP) attemptCount += 1 - } else { + default: // Some other non-retryable exception occurred return fmt.Errorf("AWS Error creating DynamoDB table: %s", err) } diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go index 10fc8cb246..271da432ce 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go @@ -1,4 +1,4 @@ -// +build !appengine +// +build !appengine,!plan9 package request diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other.go b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other.go new file mode 100644 index 0000000000..daf9eca437 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other.go @@ -0,0 +1,11 @@ +// +build appengine plan9 + +package request + +import ( + "strings" +) + +func isErrConnectionReset(err error) bool { + return strings.Contains(err.Error(), "connection reset") +} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request.go index 4f4f1123aa..301f67fcf7 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/request/request.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request.go @@ -368,7 +368,7 @@ func (r *Request) ResetBody() { } if l == 0 { - r.HTTPRequest.Body = noBodyReader + r.HTTPRequest.Body = NoBody } else if l > 0 { r.HTTPRequest.Body = r.safeBody } else { @@ -382,7 +382,7 @@ func (r *Request) ResetBody() { // a io.Reader that was not also an io.Seeker. switch r.Operation.HTTPMethod { case "GET", "HEAD", "DELETE": - r.HTTPRequest.Body = noBodyReader + r.HTTPRequest.Body = NoBody default: r.HTTPRequest.Body = r.safeBody } diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go index 1323af9007..2665e81879 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go @@ -16,6 +16,6 @@ func (noBody) Read([]byte) (int, error) { return 0, io.EOF } func (noBody) Close() error { return nil } func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil } -// Is an empty reader that will trigger the Go HTTP client to not include +// NoBody is an empty reader that will trigger the Go HTTP client to not include // and body in the HTTP request. -var noBodyReader = noBody{} +var NoBody = noBody{} diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go index 8b963f4de2..8ac66b7813 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go @@ -2,8 +2,10 @@ package request -import "net/http" +import ( + "net/http" +) -// Is a http.NoBody reader instructing Go HTTP client to not include +// NoBody is a http.NoBody reader instructing Go HTTP client to not include // and body in the HTTP request. -var noBodyReader = http.NoBody +var NoBody = http.NoBody diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go b/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go index 7af81de2ae..e36aa3822d 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go @@ -38,7 +38,6 @@ var throttleCodes = map[string]struct{}{ "ThrottlingException": {}, "RequestLimitExceeded": {}, "RequestThrottled": {}, - "LimitExceededException": {}, // Deleting 10+ DynamoDb tables at once "TooManyRequestsException": {}, // Lambda functions "PriorRequestNotComplete": {}, // Route53 } diff --git a/vendor/vendor.json b/vendor/vendor.json index 09a55c3d8f..8d2def0884 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -621,12 +621,10 @@ "versionExact": "v1.8.21" }, { - "checksumSHA1": "4y3OXdVeAE/Upux6FZp/0T0gAz4=", + "checksumSHA1": "dsVwPNbrXbXMAXZY9ZkXG7vR+Oc=", "path": "github.com/aws/aws-sdk-go/aws/request", - "revision": "49c7a5e645b5eca5aabd1fd6a676dbddaf7b2a1a", - "revisionTime": "2017-05-09T17:42:03Z", - "version": "v1.8.21", - "versionExact": "v1.8.21" + "revision": "fed27f4bd16c8c63d01003b978e5bc85fe727519", + "revisionTime": "2017-05-16T23:28:54Z" }, { "checksumSHA1": "sxShwDYt1duG922FOwU0/hbu/uc=",