Merge pull request #5543 from hashicorp/phinze/retryerror-pointers-are-evil
builtin: Refactor resource.Retry to clarify return
This commit is contained in:
commit
f8c6781982
|
@ -148,7 +148,7 @@ func resourceAwsApiGatewayApiKeyDelete(d *schema.ResourceData, meta interface{})
|
|||
conn := meta.(*AWSClient).apigateway
|
||||
log.Printf("[DEBUG] Deleting API Gateway API Key: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteApiKey(&apigateway.DeleteApiKeyInput{
|
||||
ApiKey: aws.String(d.Id()),
|
||||
})
|
||||
|
@ -161,6 +161,6 @@ func resourceAwsApiGatewayApiKeyDelete(d *schema.ResourceData, meta interface{})
|
|||
return nil
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ func resourceAwsApiGatewayDeploymentDelete(d *schema.ResourceData, meta interfac
|
|||
conn := meta.(*AWSClient).apigateway
|
||||
log.Printf("[DEBUG] Deleting API Gateway Deployment: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
log.Printf("[DEBUG] schema is %#v", d)
|
||||
if _, err := conn.DeleteStage(&apigateway.DeleteStageInput{
|
||||
StageName: aws.String(d.Get("stage_name").(string)),
|
||||
|
@ -161,9 +161,9 @@ func resourceAwsApiGatewayDeploymentDelete(d *schema.ResourceData, meta interfac
|
|||
}
|
||||
|
||||
if !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ func resourceAwsApiGatewayIntegrationDelete(d *schema.ResourceData, meta interfa
|
|||
conn := meta.(*AWSClient).apigateway
|
||||
log.Printf("[DEBUG] Deleting API Gateway Integration: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteIntegration(&apigateway.DeleteIntegrationInput{
|
||||
HttpMethod: aws.String(d.Get("http_method").(string)),
|
||||
ResourceId: aws.String(d.Get("resource_id").(string)),
|
||||
|
@ -177,9 +177,9 @@ func resourceAwsApiGatewayIntegrationDelete(d *schema.ResourceData, meta interfa
|
|||
}
|
||||
|
||||
if !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ func resourceAwsApiGatewayIntegrationResponseDelete(d *schema.ResourceData, meta
|
|||
conn := meta.(*AWSClient).apigateway
|
||||
log.Printf("[DEBUG] Deleting API Gateway Integration Response: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteIntegrationResponse(&apigateway.DeleteIntegrationResponseInput{
|
||||
HttpMethod: aws.String(d.Get("http_method").(string)),
|
||||
ResourceId: aws.String(d.Get("resource_id").(string)),
|
||||
|
@ -133,9 +133,9 @@ func resourceAwsApiGatewayIntegrationResponseDelete(d *schema.ResourceData, meta
|
|||
}
|
||||
|
||||
if !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ func resourceAwsApiGatewayMethodDelete(d *schema.ResourceData, meta interface{})
|
|||
conn := meta.(*AWSClient).apigateway
|
||||
log.Printf("[DEBUG] Deleting API Gateway Method: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteMethod(&apigateway.DeleteMethodInput{
|
||||
HttpMethod: aws.String(d.Get("http_method").(string)),
|
||||
ResourceId: aws.String(d.Get("resource_id").(string)),
|
||||
|
@ -170,9 +170,9 @@ func resourceAwsApiGatewayMethodDelete(d *schema.ResourceData, meta interface{})
|
|||
}
|
||||
|
||||
if !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ func resourceAwsApiGatewayMethodResponseDelete(d *schema.ResourceData, meta inte
|
|||
conn := meta.(*AWSClient).apigateway
|
||||
log.Printf("[DEBUG] Deleting API Gateway Method Response: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteMethodResponse(&apigateway.DeleteMethodResponseInput{
|
||||
HttpMethod: aws.String(d.Get("http_method").(string)),
|
||||
ResourceId: aws.String(d.Get("resource_id").(string)),
|
||||
|
@ -153,9 +153,9 @@ func resourceAwsApiGatewayMethodResponseDelete(d *schema.ResourceData, meta inte
|
|||
}
|
||||
|
||||
if !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ func resourceAwsApiGatewayModelDelete(d *schema.ResourceData, meta interface{})
|
|||
conn := meta.(*AWSClient).apigateway
|
||||
log.Printf("[DEBUG] Deleting API Gateway Model: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
log.Printf("[DEBUG] schema is %#v", d)
|
||||
_, err := conn.DeleteModel(&apigateway.DeleteModelInput{
|
||||
ModelName: aws.String(d.Get("name").(string)),
|
||||
|
@ -160,9 +160,9 @@ func resourceAwsApiGatewayModelDelete(d *schema.ResourceData, meta interface{})
|
|||
}
|
||||
|
||||
if !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ func resourceAwsApiGatewayResourceDelete(d *schema.ResourceData, meta interface{
|
|||
conn := meta.(*AWSClient).apigateway
|
||||
log.Printf("[DEBUG] Deleting API Gateway Resource: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
log.Printf("[DEBUG] schema is %#v", d)
|
||||
_, err := conn.DeleteResource(&apigateway.DeleteResourceInput{
|
||||
ResourceId: aws.String(d.Id()),
|
||||
|
@ -143,6 +143,6 @@ func resourceAwsApiGatewayResourceDelete(d *schema.ResourceData, meta interface{
|
|||
return nil
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ func resourceAwsApiGatewayRestApiDelete(d *schema.ResourceData, meta interface{}
|
|||
conn := meta.(*AWSClient).apigateway
|
||||
log.Printf("[DEBUG] Deleting API Gateway: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteRestApi(&apigateway.DeleteRestApiInput{
|
||||
RestApiId: aws.String(d.Id()),
|
||||
})
|
||||
|
@ -156,6 +156,6 @@ func resourceAwsApiGatewayRestApiDelete(d *schema.ResourceData, meta interface{}
|
|||
return nil
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -450,7 +450,7 @@ func resourceAwsAutoscalingGroupDelete(d *schema.ResourceData, meta interface{})
|
|||
// We retry the delete operation to handle InUse/InProgress errors coming
|
||||
// from scaling operations. We should be able to sneak in a delete in between
|
||||
// scaling operations within 5m.
|
||||
err = resource.Retry(5*time.Minute, func() error {
|
||||
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
if _, err := conn.DeleteAutoScalingGroup(&deleteopts); err != nil {
|
||||
if awserr, ok := err.(awserr.Error); ok {
|
||||
switch awserr.Code() {
|
||||
|
@ -459,11 +459,11 @@ func resourceAwsAutoscalingGroupDelete(d *schema.ResourceData, meta interface{})
|
|||
return nil
|
||||
case "ResourceInUse", "ScalingActivityInProgress":
|
||||
// These are retryable
|
||||
return awserr
|
||||
return resource.RetryableError(awserr)
|
||||
}
|
||||
}
|
||||
// Didn't recognize the error, so shouldn't retry.
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
// Successful delete
|
||||
return nil
|
||||
|
@ -472,9 +472,10 @@ func resourceAwsAutoscalingGroupDelete(d *schema.ResourceData, meta interface{})
|
|||
return err
|
||||
}
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
if g, _ = getAwsAutoscalingGroup(d.Id(), conn); g != nil {
|
||||
return fmt.Errorf("Auto Scaling Group still exists")
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Auto Scaling Group still exists"))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
@ -531,10 +532,10 @@ func resourceAwsAutoscalingGroupDrain(d *schema.ResourceData, meta interface{})
|
|||
|
||||
// Next, wait for the autoscale group to drain
|
||||
log.Printf("[DEBUG] Waiting for group to have zero instances")
|
||||
return resource.Retry(10*time.Minute, func() error {
|
||||
return resource.Retry(10*time.Minute, func() *resource.RetryError {
|
||||
g, err := getAwsAutoscalingGroup(d.Id(), conn)
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
if g == nil {
|
||||
log.Printf("[INFO] Autoscaling Group %q not found", d.Id())
|
||||
|
@ -546,7 +547,8 @@ func resourceAwsAutoscalingGroupDrain(d *schema.ResourceData, meta interface{})
|
|||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("group still has %d instances", len(g.Instances))
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("group still has %d instances", len(g.Instances)))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -32,10 +32,10 @@ func waitForASGCapacity(
|
|||
|
||||
log.Printf("[DEBUG] Waiting on %s for capacity...", d.Id())
|
||||
|
||||
return resource.Retry(wait, func() error {
|
||||
return resource.Retry(wait, func() *resource.RetryError {
|
||||
g, err := getAwsAutoscalingGroup(d.Id(), meta.(*AWSClient).autoscalingconn)
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
if g == nil {
|
||||
log.Printf("[INFO] Autoscaling Group %q not found", d.Id())
|
||||
|
@ -44,7 +44,7 @@ func waitForASGCapacity(
|
|||
}
|
||||
lbis, err := getLBInstanceStates(g, meta)
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
haveASG := 0
|
||||
|
@ -86,7 +86,8 @@ func waitForASGCapacity(
|
|||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("%q: Waiting up to %s: %s", d.Id(), wait, reason)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("%q: Waiting up to %s: %s", d.Id(), wait, reason))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -64,16 +64,16 @@ func resourceAwsAutoscalingLifecycleHookPut(d *schema.ResourceData, meta interfa
|
|||
params := getAwsAutoscalingPutLifecycleHookInput(d)
|
||||
|
||||
log.Printf("[DEBUG] AutoScaling PutLifecyleHook: %s", params)
|
||||
err := resource.Retry(5*time.Minute, func() error {
|
||||
err := resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.PutLifecycleHook(¶ms)
|
||||
|
||||
if err != nil {
|
||||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
if strings.Contains(awsErr.Message(), "Unable to publish test message to notification target") {
|
||||
return fmt.Errorf("[DEBUG] Retrying AWS AutoScaling Lifecycle Hook: %s", params)
|
||||
return resource.RetryableError(fmt.Errorf("[DEBUG] Retrying AWS AutoScaling Lifecycle Hook: %s", params))
|
||||
}
|
||||
}
|
||||
return resource.RetryError{Err: fmt.Errorf("Error putting lifecycle hook: %s", err)}
|
||||
return resource.NonRetryableError(fmt.Errorf("Error putting lifecycle hook: %s", err))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
|
@ -70,7 +70,7 @@ func resourceAwsCloudWatchEventRuleCreate(d *schema.ResourceData, meta interface
|
|||
|
||||
// IAM Roles take some time to propagate
|
||||
var out *events.PutRuleOutput
|
||||
err := resource.Retry(30*time.Second, func() error {
|
||||
err := resource.Retry(30*time.Second, func() *resource.RetryError {
|
||||
var err error
|
||||
out, err = conn.PutRule(input)
|
||||
pattern := regexp.MustCompile("cannot be assumed by principal '[a-z]+\\.amazonaws\\.com'\\.$")
|
||||
|
@ -78,12 +78,10 @@ func resourceAwsCloudWatchEventRuleCreate(d *schema.ResourceData, meta interface
|
|||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
if awsErr.Code() == "ValidationException" && pattern.MatchString(awsErr.Message()) {
|
||||
log.Printf("[DEBUG] Retrying creation of CloudWatch Event Rule %q", *input.Name)
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
}
|
||||
return resource.RetryError{
|
||||
Err: err,
|
||||
}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
@ -157,7 +155,7 @@ func resourceAwsCloudWatchEventRuleUpdate(d *schema.ResourceData, meta interface
|
|||
|
||||
// IAM Roles take some time to propagate
|
||||
var out *events.PutRuleOutput
|
||||
err := resource.Retry(30*time.Second, func() error {
|
||||
err := resource.Retry(30*time.Second, func() *resource.RetryError {
|
||||
var err error
|
||||
out, err = conn.PutRule(input)
|
||||
pattern := regexp.MustCompile("cannot be assumed by principal '[a-z]+\\.amazonaws\\.com'\\.$")
|
||||
|
@ -165,12 +163,10 @@ func resourceAwsCloudWatchEventRuleUpdate(d *schema.ResourceData, meta interface
|
|||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
if awsErr.Code() == "ValidationException" && pattern.MatchString(awsErr.Message()) {
|
||||
log.Printf("[DEBUG] Retrying update of CloudWatch Event Rule %q", *input.Name)
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
}
|
||||
return resource.RetryError{
|
||||
Err: err,
|
||||
}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
|
@ -158,20 +158,20 @@ func resourceAwsCodeDeployDeploymentGroupCreate(d *schema.ResourceData, meta int
|
|||
// Retry to handle IAM role eventual consistency.
|
||||
var resp *codedeploy.CreateDeploymentGroupOutput
|
||||
var err error
|
||||
err = resource.Retry(2*time.Minute, func() error {
|
||||
err = resource.Retry(2*time.Minute, func() *resource.RetryError {
|
||||
resp, err = conn.CreateDeploymentGroup(&input)
|
||||
if err != nil {
|
||||
codedeployErr, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
if codedeployErr.Code() == "InvalidRoleException" {
|
||||
log.Printf("[DEBUG] Trying to create deployment group again: %q",
|
||||
codedeployErr.Message())
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
|
@ -534,15 +534,15 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
|
|||
|
||||
log.Printf("[DEBUG] DB Instance create configuration: %#v", opts)
|
||||
var err error
|
||||
err = resource.Retry(5*time.Minute, func() error {
|
||||
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err = conn.CreateDBInstance(&opts)
|
||||
if err != nil {
|
||||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
if awsErr.Code() == "InvalidParameterValue" && strings.Contains(awsErr.Message(), "ENHANCED_MONITORING") {
|
||||
return awsErr
|
||||
return resource.RetryableError(awsErr)
|
||||
}
|
||||
}
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
|
@ -676,25 +676,25 @@ func resourceAwsDynamoDbTableDelete(d *schema.ResourceData, meta interface{}) er
|
|||
TableName: aws.String(d.Id()),
|
||||
}
|
||||
|
||||
err = resource.Retry(10*time.Minute, func() error {
|
||||
err = resource.Retry(10*time.Minute, func() *resource.RetryError {
|
||||
t, err := dynamodbconn.DescribeTable(params)
|
||||
if err != nil {
|
||||
if awserr, ok := err.(awserr.Error); ok && awserr.Code() == "ResourceNotFoundException" {
|
||||
return nil
|
||||
}
|
||||
// Didn't recognize the error, so shouldn't retry.
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
if t != nil {
|
||||
if t.Table.TableStatus != nil && strings.ToLower(*t.Table.TableStatus) == "deleting" {
|
||||
log.Printf("[DEBUG] AWS Dynamo DB table (%s) is still deleting", d.Id())
|
||||
return fmt.Errorf("still deleting")
|
||||
return resource.RetryableError(fmt.Errorf("still deleting"))
|
||||
}
|
||||
}
|
||||
|
||||
// we should be not found or deleting, so error here
|
||||
return resource.RetryError{Err: fmt.Errorf("[ERR] Error deleting Dynamo DB table, unexpected state: %s", t)}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
|
||||
// check error from retry
|
||||
|
|
|
@ -85,7 +85,7 @@ func resourceAwsEcsClusterDelete(d *schema.ResourceData, meta interface{}) error
|
|||
|
||||
log.Printf("[DEBUG] Deleting ECS cluster %s", d.Id())
|
||||
|
||||
err := resource.Retry(10*time.Minute, func() error {
|
||||
err := resource.Retry(10*time.Minute, func() *resource.RetryError {
|
||||
out, err := conn.DeleteCluster(&ecs.DeleteClusterInput{
|
||||
Cluster: aws.String(d.Id()),
|
||||
})
|
||||
|
@ -97,27 +97,27 @@ func resourceAwsEcsClusterDelete(d *schema.ResourceData, meta interface{}) error
|
|||
|
||||
awsErr, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
if awsErr.Code() == "ClusterContainsContainerInstancesException" {
|
||||
log.Printf("[TRACE] Retrying ECS cluster %q deletion after %q", d.Id(), awsErr.Code())
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
|
||||
if awsErr.Code() == "ClusterContainsServicesException" {
|
||||
log.Printf("[TRACE] Retrying ECS cluster %q deletion after %q", d.Id(), awsErr.Code())
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clusterName := d.Get("name").(string)
|
||||
err = resource.Retry(5*time.Minute, func() error {
|
||||
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
log.Printf("[DEBUG] Checking if ECS Cluster %q is INACTIVE", d.Id())
|
||||
out, err := conn.DescribeClusters(&ecs.DescribeClustersInput{
|
||||
Clusters: []*string{aws.String(clusterName)},
|
||||
|
@ -129,12 +129,13 @@ func resourceAwsEcsClusterDelete(d *schema.ResourceData, meta interface{}) error
|
|||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("ECS Cluster %q is still %q", clusterName, *c.Status)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("ECS Cluster %q is still %q", clusterName, *c.Status))
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -131,21 +131,21 @@ func resourceAwsEcsServiceCreate(d *schema.ResourceData, meta interface{}) error
|
|||
// See https://github.com/hashicorp/terraform/issues/2869
|
||||
var out *ecs.CreateServiceOutput
|
||||
var err error
|
||||
err = resource.Retry(2*time.Minute, func() error {
|
||||
err = resource.Retry(2*time.Minute, func() *resource.RetryError {
|
||||
out, err = conn.CreateService(&input)
|
||||
|
||||
if err != nil {
|
||||
ec2err, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
if ec2err.Code() == "InvalidParameterException" {
|
||||
log.Printf("[DEBUG] Trying to create ECS service again: %q",
|
||||
ec2err.Message())
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -308,7 +308,7 @@ func resourceAwsEcsServiceDelete(d *schema.ResourceData, meta interface{}) error
|
|||
}
|
||||
|
||||
// Wait until the ECS service is drained
|
||||
err = resource.Retry(5*time.Minute, func() error {
|
||||
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
input := ecs.DeleteServiceInput{
|
||||
Service: aws.String(d.Id()),
|
||||
Cluster: aws.String(d.Get("cluster").(string)),
|
||||
|
@ -322,16 +322,16 @@ func resourceAwsEcsServiceDelete(d *schema.ResourceData, meta interface{}) error
|
|||
|
||||
ec2err, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
if ec2err.Code() == "InvalidParameterException" {
|
||||
// Prevent "The service cannot be stopped while deployments are active."
|
||||
log.Printf("[DEBUG] Trying to delete ECS service again: %q",
|
||||
ec2err.Message())
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -243,7 +243,7 @@ func resourceAwsEipDelete(d *schema.ResourceData, meta interface{}) error {
|
|||
}
|
||||
|
||||
domain := resourceAwsEipDomain(d)
|
||||
return resource.Retry(3*time.Minute, func() error {
|
||||
return resource.Retry(3*time.Minute, func() *resource.RetryError {
|
||||
var err error
|
||||
switch domain {
|
||||
case "vpc":
|
||||
|
@ -264,10 +264,10 @@ func resourceAwsEipDelete(d *schema.ResourceData, meta interface{}) error {
|
|||
return nil
|
||||
}
|
||||
if _, ok := err.(awserr.Error); !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -109,9 +109,10 @@ func resourceAwsElasticBeanstalkApplicationDelete(d *schema.ResourceData, meta i
|
|||
ApplicationName: aws.String(d.Id()),
|
||||
})
|
||||
|
||||
return resource.Retry(10*time.Second, func() error {
|
||||
return resource.Retry(10*time.Second, func() *resource.RetryError {
|
||||
if a, _ = getBeanstalkApplication(d, meta); a != nil {
|
||||
return fmt.Errorf("Beanstalk Application still exists")
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Beanstalk Application still exists"))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
|
@ -118,24 +118,24 @@ func resourceAwsElasticacheSecurityGroupDelete(d *schema.ResourceData, meta inte
|
|||
|
||||
log.Printf("[DEBUG] Cache security group delete: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteCacheSecurityGroup(&elasticache.DeleteCacheSecurityGroupInput{
|
||||
CacheSecurityGroupName: aws.String(d.Id()),
|
||||
})
|
||||
if err != nil {
|
||||
apierr, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
log.Printf("[DEBUG] APIError.Code: %v", apierr.Code())
|
||||
switch apierr.Code() {
|
||||
case "InvalidCacheSecurityGroupState":
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
case "DependencyViolation":
|
||||
// If it is a dependency violation, we want to retry
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
default:
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -143,22 +143,22 @@ func resourceAwsElasticacheSubnetGroupDelete(d *schema.ResourceData, meta interf
|
|||
|
||||
log.Printf("[DEBUG] Cache subnet group delete: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteCacheSubnetGroup(&elasticache.DeleteCacheSubnetGroupInput{
|
||||
CacheSubnetGroupName: aws.String(d.Id()),
|
||||
})
|
||||
if err != nil {
|
||||
apierr, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
log.Printf("[DEBUG] APIError.Code: %v", apierr.Code())
|
||||
switch apierr.Code() {
|
||||
case "DependencyViolation":
|
||||
// If it is a dependency violation, we want to retry
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
default:
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -207,19 +207,20 @@ func resourceAwsElasticSearchDomainCreate(d *schema.ResourceData, meta interface
|
|||
d.SetId(*out.DomainStatus.ARN)
|
||||
|
||||
log.Printf("[DEBUG] Waiting for ElasticSearch domain %q to be created", d.Id())
|
||||
err = resource.Retry(15*time.Minute, func() error {
|
||||
err = resource.Retry(15*time.Minute, func() *resource.RetryError {
|
||||
out, err := conn.DescribeElasticsearchDomain(&elasticsearch.DescribeElasticsearchDomainInput{
|
||||
DomainName: aws.String(d.Get("domain_name").(string)),
|
||||
})
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
if !*out.DomainStatus.Processing && out.DomainStatus.Endpoint != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("%q: Timeout while waiting for the domain to be created", d.Id())
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("%q: Timeout while waiting for the domain to be created", d.Id()))
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -366,19 +367,20 @@ func resourceAwsElasticSearchDomainUpdate(d *schema.ResourceData, meta interface
|
|||
return err
|
||||
}
|
||||
|
||||
err = resource.Retry(25*time.Minute, func() error {
|
||||
err = resource.Retry(25*time.Minute, func() *resource.RetryError {
|
||||
out, err := conn.DescribeElasticsearchDomain(&elasticsearch.DescribeElasticsearchDomainInput{
|
||||
DomainName: aws.String(d.Get("domain_name").(string)),
|
||||
})
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
if *out.DomainStatus.Processing == false {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("%q: Timeout while waiting for changes to be processed", d.Id())
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("%q: Timeout while waiting for changes to be processed", d.Id()))
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -401,7 +403,7 @@ func resourceAwsElasticSearchDomainDelete(d *schema.ResourceData, meta interface
|
|||
}
|
||||
|
||||
log.Printf("[DEBUG] Waiting for ElasticSearch domain %q to be deleted", d.Get("domain_name").(string))
|
||||
err = resource.Retry(15*time.Minute, func() error {
|
||||
err = resource.Retry(15*time.Minute, func() *resource.RetryError {
|
||||
out, err := conn.DescribeElasticsearchDomain(&elasticsearch.DescribeElasticsearchDomainInput{
|
||||
DomainName: aws.String(d.Get("domain_name").(string)),
|
||||
})
|
||||
|
@ -409,21 +411,22 @@ func resourceAwsElasticSearchDomainDelete(d *schema.ResourceData, meta interface
|
|||
if err != nil {
|
||||
awsErr, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
if awsErr.Code() == "ResourceNotFoundException" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: awsErr}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
if !*out.DomainStatus.Processing {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("%q: Timeout while waiting for the domain to be deleted", d.Id())
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("%q: Timeout while waiting for the domain to be deleted", d.Id()))
|
||||
})
|
||||
|
||||
d.SetId("")
|
||||
|
|
|
@ -253,17 +253,18 @@ func resourceAwsElbCreate(d *schema.ResourceData, meta interface{}) error {
|
|||
}
|
||||
|
||||
log.Printf("[DEBUG] ELB create configuration: %#v", elbOpts)
|
||||
err = resource.Retry(1*time.Minute, func() error {
|
||||
err = resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||
_, err := elbconn.CreateLoadBalancer(elbOpts)
|
||||
|
||||
if err != nil {
|
||||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
// Check for IAM SSL Cert error, eventual consistancy issue
|
||||
if awsErr.Code() == "CertificateNotFound" {
|
||||
return fmt.Errorf("[WARN] Error creating ELB Listener with SSL Cert, retrying: %s", err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("[WARN] Error creating ELB Listener with SSL Cert, retrying: %s", err))
|
||||
}
|
||||
}
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
@ -422,22 +423,22 @@ func resourceAwsElbUpdate(d *schema.ResourceData, meta interface{}) error {
|
|||
|
||||
// Occasionally AWS will error with a 'duplicate listener', without any
|
||||
// other listeners on the ELB. Retry here to eliminate that.
|
||||
err := resource.Retry(1*time.Minute, func() error {
|
||||
err := resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||
log.Printf("[DEBUG] ELB Create Listeners opts: %s", createListenersOpts)
|
||||
if _, err := elbconn.CreateLoadBalancerListeners(createListenersOpts); err != nil {
|
||||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
if awsErr.Code() == "DuplicateListener" {
|
||||
log.Printf("[DEBUG] Duplicate listener found for ELB (%s), retrying", d.Id())
|
||||
return awsErr
|
||||
return resource.RetryableError(awsErr)
|
||||
}
|
||||
if awsErr.Code() == "CertificateNotFound" && strings.Contains(awsErr.Message(), "Server Certificate not found for the key: arn") {
|
||||
log.Printf("[DEBUG] SSL Cert not found for given ARN, retrying")
|
||||
return awsErr
|
||||
return resource.RetryableError(awsErr)
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't recognize the error, so shouldn't retry.
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
// Successful creation
|
||||
return nil
|
||||
|
|
|
@ -215,7 +215,7 @@ func attachPolicyToRoles(conn *iam.IAM, roles []*string, arn string) error {
|
|||
}
|
||||
|
||||
var attachmentErr error
|
||||
attachmentErr = resource.Retry(2*time.Minute, func() error {
|
||||
attachmentErr = resource.Retry(2*time.Minute, func() *resource.RetryError {
|
||||
|
||||
input := iam.ListRolePoliciesInput{
|
||||
RoleName: r,
|
||||
|
@ -223,7 +223,7 @@ func attachPolicyToRoles(conn *iam.IAM, roles []*string, arn string) error {
|
|||
|
||||
attachedPolicies, err := conn.ListRolePolicies(&input)
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
if len(attachedPolicies.PolicyNames) > 0 {
|
||||
|
@ -236,7 +236,7 @@ func attachPolicyToRoles(conn *iam.IAM, roles []*string, arn string) error {
|
|||
}
|
||||
|
||||
if !foundPolicy {
|
||||
return resource.RetryError{Err: fmt.Errorf("Policy (%q) not yet found", arn)}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@ func resourceAwsIAMServerCertificateRead(d *schema.ResourceData, meta interface{
|
|||
func resourceAwsIAMServerCertificateDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).iamconn
|
||||
log.Printf("[INFO] Deleting IAM Server Certificate: %s", d.Id())
|
||||
err := resource.Retry(1*time.Minute, func() error {
|
||||
err := resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteServerCertificate(&iam.DeleteServerCertificateInput{
|
||||
ServerCertificateName: aws.String(d.Get("name").(string)),
|
||||
})
|
||||
|
@ -170,10 +170,10 @@ func resourceAwsIAMServerCertificateDelete(d *schema.ResourceData, meta interfac
|
|||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
if awsErr.Code() == "DeleteConflict" && strings.Contains(awsErr.Message(), "currently in use by arn") {
|
||||
log.Printf("[WARN] Conflict deleting server certificate: %s, retrying", awsErr.Message())
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
}
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
|
@ -114,7 +114,7 @@ func resourceAwsInternetGatewayDelete(d *schema.ResourceData, meta interface{})
|
|||
|
||||
log.Printf("[INFO] Deleting Internet Gateway: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteInternetGateway(&ec2.DeleteInternetGatewayInput{
|
||||
InternetGatewayId: aws.String(d.Id()),
|
||||
})
|
||||
|
@ -124,17 +124,17 @@ func resourceAwsInternetGatewayDelete(d *schema.ResourceData, meta interface{})
|
|||
|
||||
ec2err, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
|
||||
switch ec2err.Code() {
|
||||
case "InvalidInternetGatewayID.NotFound":
|
||||
return nil
|
||||
case "DependencyViolation":
|
||||
return err // retry
|
||||
return resource.RetryableError(err) // retry
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -98,17 +98,15 @@ func resourceAwsLambdaEventSourceMappingCreate(d *schema.ResourceData, meta inte
|
|||
//
|
||||
// The role may exist, but the permissions may not have propagated, so we
|
||||
// retry
|
||||
err := resource.Retry(1*time.Minute, func() error {
|
||||
err := resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||
eventSourceMappingConfiguration, err := conn.CreateEventSourceMapping(params)
|
||||
if err != nil {
|
||||
if awserr, ok := err.(awserr.Error); ok {
|
||||
if awserr.Code() == "InvalidParameterValueException" {
|
||||
// Retryable
|
||||
return awserr
|
||||
return resource.RetryableError(awserr)
|
||||
}
|
||||
}
|
||||
// Not retryable
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
// No error
|
||||
d.Set("uuid", eventSourceMappingConfiguration.UUID)
|
||||
|
@ -186,19 +184,16 @@ func resourceAwsLambdaEventSourceMappingUpdate(d *schema.ResourceData, meta inte
|
|||
Enabled: aws.Bool(d.Get("enabled").(bool)),
|
||||
}
|
||||
|
||||
err := resource.Retry(1*time.Minute, func() error {
|
||||
err := resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.UpdateEventSourceMapping(params)
|
||||
if err != nil {
|
||||
if awserr, ok := err.(awserr.Error); ok {
|
||||
if awserr.Code() == "InvalidParameterValueException" {
|
||||
// Retryable
|
||||
return awserr
|
||||
return resource.RetryableError(awserr)
|
||||
}
|
||||
}
|
||||
// Not retryable
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
// No error
|
||||
return nil
|
||||
})
|
||||
|
||||
|
|
|
@ -199,21 +199,18 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e
|
|||
// 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
|
||||
// Error creating Lambda function: InvalidParameterValueException: The role defined for the task cannot be assumed by Lambda.
|
||||
err := resource.Retry(1*time.Minute, func() error {
|
||||
err := resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.CreateFunction(params)
|
||||
if err != nil {
|
||||
if awserr, ok := err.(awserr.Error); ok {
|
||||
if awserr.Code() == "InvalidParameterValueException" {
|
||||
log.Printf("[DEBUG] InvalidParameterValueException creating Lambda Function: %s", awserr)
|
||||
// Retryable
|
||||
return awserr
|
||||
return resource.RetryableError(awserr)
|
||||
}
|
||||
}
|
||||
log.Printf("[DEBUG] Error creating Lambda Function: %s", err)
|
||||
// Not retryable
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
// No error
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -99,7 +99,7 @@ func resourceAwsLambdaPermissionCreate(d *schema.ResourceData, meta interface{})
|
|||
|
||||
log.Printf("[DEBUG] Adding new Lambda permission: %s", input)
|
||||
var out *lambda.AddPermissionOutput
|
||||
err := resource.Retry(1*time.Minute, func() error {
|
||||
err := resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||
var err error
|
||||
out, err = conn.AddPermission(&input)
|
||||
|
||||
|
@ -107,11 +107,12 @@ func resourceAwsLambdaPermissionCreate(d *schema.ResourceData, meta interface{})
|
|||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
// IAM is eventually consistent :/
|
||||
if awsErr.Code() == "ResourceConflictException" {
|
||||
return fmt.Errorf("[WARN] Error adding new Lambda Permission for %s, retrying: %s",
|
||||
*input.FunctionName, err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("[WARN] Error adding new Lambda Permission for %s, retrying: %s",
|
||||
*input.FunctionName, err))
|
||||
}
|
||||
}
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
@ -124,21 +125,23 @@ func resourceAwsLambdaPermissionCreate(d *schema.ResourceData, meta interface{})
|
|||
|
||||
d.SetId(d.Get("statement_id").(string))
|
||||
|
||||
err = resource.Retry(5*time.Minute, func() error {
|
||||
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
// IAM is eventually cosistent :/
|
||||
err := resourceAwsLambdaPermissionRead(d, meta)
|
||||
if err != nil {
|
||||
if strings.HasPrefix(err.Error(), "Error reading Lambda policy: ResourceNotFoundException") {
|
||||
return fmt.Errorf("[WARN] Error reading newly created Lambda Permission for %s, retrying: %s",
|
||||
*input.FunctionName, err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("[WARN] Error reading newly created Lambda Permission for %s, retrying: %s",
|
||||
*input.FunctionName, err))
|
||||
}
|
||||
if strings.HasPrefix(err.Error(), "Failed to find statement \""+d.Id()) {
|
||||
return fmt.Errorf("[WARN] Error reading newly created Lambda Permission statement for %s, retrying: %s",
|
||||
*input.FunctionName, err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("[WARN] Error reading newly created Lambda Permission statement for %s, retrying: %s",
|
||||
*input.FunctionName, err))
|
||||
}
|
||||
|
||||
log.Printf("[ERROR] An actual error occured when expecting Lambda policy to be there: %s", err)
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
@ -159,28 +162,28 @@ func resourceAwsLambdaPermissionRead(d *schema.ResourceData, meta interface{}) e
|
|||
log.Printf("[DEBUG] Looking for Lambda permission: %s", input)
|
||||
var out *lambda.GetPolicyOutput
|
||||
var statement *LambdaPolicyStatement
|
||||
err := resource.Retry(1*time.Minute, func() error {
|
||||
err := resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||
// IAM is eventually cosistent :/
|
||||
var err error
|
||||
out, err = conn.GetPolicy(&input)
|
||||
if err != nil {
|
||||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
if awsErr.Code() == "ResourceNotFoundException" {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
}
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
policyInBytes := []byte(*out.Policy)
|
||||
policy := LambdaPolicy{}
|
||||
err = json.Unmarshal(policyInBytes, &policy)
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: fmt.Errorf("Error unmarshalling Lambda policy: %s", err)}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
statement, err = findLambdaPolicyStatementById(&policy, d.Id())
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -244,7 +247,7 @@ func resourceAwsLambdaPermissionDelete(d *schema.ResourceData, meta interface{})
|
|||
return err
|
||||
}
|
||||
|
||||
err = resource.Retry(5*time.Minute, func() error {
|
||||
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
log.Printf("[DEBUG] Checking if Lambda permission %q is deleted", d.Id())
|
||||
|
||||
params := &lambda.GetPolicyInput{
|
||||
|
@ -262,7 +265,7 @@ func resourceAwsLambdaPermissionDelete(d *schema.ResourceData, meta interface{})
|
|||
return nil
|
||||
}
|
||||
}
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
if resp.Policy == nil {
|
||||
|
@ -273,7 +276,8 @@ func resourceAwsLambdaPermissionDelete(d *schema.ResourceData, meta interface{})
|
|||
policy := LambdaPolicy{}
|
||||
err = json.Unmarshal(policyInBytes, &policy)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error unmarshalling Lambda policy: %s", err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Error unmarshalling Lambda policy: %s", err))
|
||||
}
|
||||
|
||||
_, err = findLambdaPolicyStatementById(&policy, d.Id())
|
||||
|
|
|
@ -329,20 +329,20 @@ func testAccCheckLambdaPermissionExists(n string, statement *LambdaPolicyStateme
|
|||
|
||||
// IAM is eventually consistent
|
||||
var foundStatement *LambdaPolicyStatement
|
||||
err := resource.Retry(5*time.Minute, func() error {
|
||||
err := resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
var err error
|
||||
foundStatement, err = lambdaPermissionExists(rs, conn)
|
||||
if err != nil {
|
||||
if strings.HasPrefix(err.Error(), "ResourceNotFoundException") {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
if strings.HasPrefix(err.Error(), "Lambda policy not found") {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
if strings.HasPrefix(err.Error(), "Failed to find statement") {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
@ -365,13 +365,13 @@ func testAccCheckAWSLambdaPermissionDestroy(s *terraform.State) error {
|
|||
}
|
||||
|
||||
// IAM is eventually consistent
|
||||
err := resource.Retry(5*time.Minute, func() error {
|
||||
err := resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
err := isLambdaPermissionGone(rs, conn)
|
||||
if err != nil {
|
||||
if !strings.HasPrefix(err.Error(), "Error unmarshalling Lambda policy") {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
|
@ -428,17 +428,15 @@ func resourceAwsLaunchConfigurationCreate(d *schema.ResourceData, meta interface
|
|||
|
||||
// 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
|
||||
err := resource.Retry(30*time.Second, func() error {
|
||||
err := resource.Retry(30*time.Second, func() *resource.RetryError {
|
||||
_, err := autoscalingconn.CreateLaunchConfiguration(&createLaunchConfigurationOpts)
|
||||
if err != nil {
|
||||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
if awsErr.Message() == "Invalid IamInstanceProfile" {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
}
|
||||
return resource.RetryError{
|
||||
Err: err,
|
||||
}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
@ -452,8 +450,12 @@ func resourceAwsLaunchConfigurationCreate(d *schema.ResourceData, meta interface
|
|||
|
||||
// We put a Retry here since sometimes eventual consistency bites
|
||||
// us and we need to retry a few times to get the LC to load properly
|
||||
return resource.Retry(30*time.Second, func() error {
|
||||
return resourceAwsLaunchConfigurationRead(d, meta)
|
||||
return resource.Retry(30*time.Second, func() *resource.RetryError {
|
||||
err := resourceAwsLaunchConfigurationRead(d, meta)
|
||||
if err != nil {
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -410,7 +410,7 @@ func resourceAwsNetworkAclDelete(d *schema.ResourceData, meta interface{}) error
|
|||
conn := meta.(*AWSClient).ec2conn
|
||||
|
||||
log.Printf("[INFO] Deleting Network Acl: %s", d.Id())
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteNetworkAcl(&ec2.DeleteNetworkAclInput{
|
||||
NetworkAclId: aws.String(d.Id()),
|
||||
})
|
||||
|
@ -427,7 +427,7 @@ func resourceAwsNetworkAclDelete(d *schema.ResourceData, meta interface{}) error
|
|||
|
||||
a, err := findNetworkAclAssociation(v.(string), conn)
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: fmt.Errorf("Dependency violation: Cannot find ACL %s: %s", d.Id(), err)}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
associations = append(associations, a)
|
||||
} else if v, ok := d.GetOk("subnet_ids"); ok {
|
||||
|
@ -435,14 +435,14 @@ func resourceAwsNetworkAclDelete(d *schema.ResourceData, meta interface{}) error
|
|||
for _, i := range ids {
|
||||
a, err := findNetworkAclAssociation(i.(string), conn)
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: fmt.Errorf("Dependency violation: Cannot delete acl %s: %s", d.Id(), err)}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
associations = append(associations, a)
|
||||
}
|
||||
}
|
||||
defaultAcl, err := getDefaultNetworkAcl(d.Get("vpc_id").(string), conn)
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: fmt.Errorf("Dependency violation: Cannot delete acl %s: %s", d.Id(), err)}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
for _, a := range associations {
|
||||
|
@ -451,10 +451,10 @@ func resourceAwsNetworkAclDelete(d *schema.ResourceData, meta interface{}) error
|
|||
NetworkAclId: defaultAcl.NetworkAclId,
|
||||
})
|
||||
}
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
default:
|
||||
// Any other error, we want to quit the retry loop immediately
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
}
|
||||
log.Printf("[Info] Deleted network ACL %s successfully", d.Id())
|
||||
|
|
|
@ -124,10 +124,10 @@ func resourceAwsNetworkAclRuleCreate(d *schema.ResourceData, meta interface{}) e
|
|||
// It appears it might be a while until the newly created rule is visible via the
|
||||
// API (see issue GH-4721). Retry the `findNetworkAclRule` function until it is
|
||||
// visible (which in most cases is likely immediately).
|
||||
err = resource.Retry(3*time.Minute, func() error {
|
||||
err = resource.Retry(3*time.Minute, func() *resource.RetryError {
|
||||
_, findErr := findNetworkAclRule(d, meta)
|
||||
if findErr != nil {
|
||||
return findErr
|
||||
return resource.RetryableError(findErr)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -324,7 +324,7 @@ func resourceAwsOpsworksStackCreate(d *schema.ResourceData, meta interface{}) er
|
|||
log.Printf("[DEBUG] Creating OpsWorks stack: %s", req)
|
||||
|
||||
var resp *opsworks.CreateStackOutput
|
||||
err = resource.Retry(20*time.Minute, func() error {
|
||||
err = resource.Retry(20*time.Minute, func() *resource.RetryError {
|
||||
var cerr error
|
||||
resp, cerr = client.CreateStack(req)
|
||||
if cerr != nil {
|
||||
|
@ -342,10 +342,10 @@ func resourceAwsOpsworksStackCreate(d *schema.ResourceData, meta interface{}) er
|
|||
trustErr := "not the necessary trust relationship"
|
||||
if opserr.Code() == "ValidationException" && (strings.Contains(opserr.Message(), trustErr) || strings.Contains(opserr.Message(), propErr)) {
|
||||
log.Printf("[INFO] Waiting for service IAM role to propagate")
|
||||
return cerr
|
||||
return resource.RetryableError(cerr)
|
||||
}
|
||||
}
|
||||
return resource.RetryError{Err: cerr}
|
||||
return resource.NonRetryableError(cerr)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
|
@ -217,18 +217,19 @@ func resourceAwsS3BucketCreate(d *schema.ResourceData, meta interface{}) error {
|
|||
}
|
||||
}
|
||||
|
||||
err := resource.Retry(5*time.Minute, func() error {
|
||||
err := resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
log.Printf("[DEBUG] Trying to create new S3 bucket: %q", bucket)
|
||||
_, err := s3conn.CreateBucket(req)
|
||||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
if awsErr.Code() == "OperationAborted" {
|
||||
log.Printf("[WARN] Got an error while trying to create S3 bucket %s: %s", bucket, err)
|
||||
return fmt.Errorf("[WARN] Error creating S3 bucket %s, retrying: %s",
|
||||
bucket, err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("[WARN] Error creating S3 bucket %s, retrying: %s",
|
||||
bucket, err))
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -565,18 +566,15 @@ func resourceAwsS3BucketPolicyUpdate(s3conn *s3.S3, d *schema.ResourceData) erro
|
|||
Policy: aws.String(policy),
|
||||
}
|
||||
|
||||
err := resource.Retry(1*time.Minute, func() error {
|
||||
err := resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||
if _, err := s3conn.PutBucketPolicy(params); err != nil {
|
||||
if awserr, ok := err.(awserr.Error); ok {
|
||||
if awserr.Code() == "MalformedPolicy" {
|
||||
// Retryable
|
||||
return awserr
|
||||
return resource.RetryableError(awserr)
|
||||
}
|
||||
}
|
||||
// Not retryable
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
// No error
|
||||
return nil
|
||||
})
|
||||
|
||||
|
|
|
@ -345,14 +345,14 @@ func resourceAwsSecurityGroupDelete(d *schema.ResourceData, meta interface{}) er
|
|||
|
||||
log.Printf("[DEBUG] Security Group destroy: %v", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteSecurityGroup(&ec2.DeleteSecurityGroupInput{
|
||||
GroupId: aws.String(d.Id()),
|
||||
})
|
||||
if err != nil {
|
||||
ec2err, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
|
||||
switch ec2err.Code() {
|
||||
|
@ -360,10 +360,10 @@ func resourceAwsSecurityGroupDelete(d *schema.ResourceData, meta interface{}) er
|
|||
return nil
|
||||
case "DependencyViolation":
|
||||
// If it is a dependency violation, we want to retry
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
default:
|
||||
// Any other error, we want to quit the retry loop immediately
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -214,7 +214,7 @@ func subscribeToSNSTopic(d *schema.ResourceData, snsconn *sns.SNS) (output *sns.
|
|||
|
||||
log.Printf("[DEBUG] SNS create topic subscription is pending so fetching the subscription list for topic : %s (%s) @ '%s'", endpoint, protocol, topic_arn)
|
||||
|
||||
err = resource.Retry(time.Duration(confirmation_timeout_in_minutes)*time.Minute, func() error {
|
||||
err = resource.Retry(time.Duration(confirmation_timeout_in_minutes)*time.Minute, func() *resource.RetryError {
|
||||
|
||||
subscription, err := findSubscriptionByNonID(d, snsconn)
|
||||
|
||||
|
@ -224,10 +224,12 @@ func subscribeToSNSTopic(d *schema.ResourceData, snsconn *sns.SNS) (output *sns.
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error fetching subscriptions for SNS topic %s: %s", topic_arn, err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Error fetching subscriptions for SNS topic %s: %s", topic_arn, err))
|
||||
}
|
||||
|
||||
return fmt.Errorf("Endpoint (%s) did not autoconfirm the subscription for topic %s", endpoint, topic_arn)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Endpoint (%s) did not autoconfirm the subscription for topic %s", endpoint, topic_arn))
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -308,7 +308,7 @@ func resourceAwsVpcDelete(d *schema.ResourceData, meta interface{}) error {
|
|||
}
|
||||
log.Printf("[INFO] Deleting VPC: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteVpc(DeleteVpcOpts)
|
||||
if err == nil {
|
||||
return nil
|
||||
|
@ -316,19 +316,17 @@ func resourceAwsVpcDelete(d *schema.ResourceData, meta interface{}) error {
|
|||
|
||||
ec2err, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
switch ec2err.Code() {
|
||||
case "InvalidVpcID.NotFound":
|
||||
return nil
|
||||
case "DependencyViolation":
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
|
||||
return resource.RetryError{
|
||||
Err: fmt.Errorf("Error deleting VPC: %s", err),
|
||||
}
|
||||
return resource.NonRetryableError(fmt.Errorf("Error deleting VPC: %s", err))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ func resourceAwsVpcDhcpOptionsUpdate(d *schema.ResourceData, meta interface{}) e
|
|||
func resourceAwsVpcDhcpOptionsDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
conn := meta.(*AWSClient).ec2conn
|
||||
|
||||
return resource.Retry(3*time.Minute, func() error {
|
||||
return resource.Retry(3*time.Minute, func() *resource.RetryError {
|
||||
log.Printf("[INFO] Deleting DHCP Options ID %s...", d.Id())
|
||||
_, err := conn.DeleteDhcpOptions(&ec2.DeleteDhcpOptionsInput{
|
||||
DhcpOptionsId: aws.String(d.Id()),
|
||||
|
@ -194,7 +194,7 @@ func resourceAwsVpcDhcpOptionsDelete(d *schema.ResourceData, meta interface{}) e
|
|||
|
||||
ec2err, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
|
||||
switch ec2err.Code() {
|
||||
|
@ -206,7 +206,7 @@ func resourceAwsVpcDhcpOptionsDelete(d *schema.ResourceData, meta interface{}) e
|
|||
vpcs, err2 := findVPCsByDHCPOptionsID(conn, d.Id())
|
||||
if err2 != nil {
|
||||
log.Printf("[ERROR] %s", err2)
|
||||
return err2
|
||||
return resource.RetryableError(err2)
|
||||
}
|
||||
|
||||
for _, vpc := range vpcs {
|
||||
|
@ -215,13 +215,12 @@ func resourceAwsVpcDhcpOptionsDelete(d *schema.ResourceData, meta interface{}) e
|
|||
DhcpOptionsId: aws.String("default"),
|
||||
VpcId: vpc.VpcId,
|
||||
}); err != nil {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
}
|
||||
return err //retry
|
||||
return resource.RetryableError(err)
|
||||
default:
|
||||
// Any other error, we want to quit the retry loop immediately
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ func resourceAwsVpnGatewayDelete(d *schema.ResourceData, meta interface{}) error
|
|||
|
||||
log.Printf("[INFO] Deleting VPN gateway: %s", d.Id())
|
||||
|
||||
return resource.Retry(5*time.Minute, func() error {
|
||||
return resource.Retry(5*time.Minute, func() *resource.RetryError {
|
||||
_, err := conn.DeleteVpnGateway(&ec2.DeleteVpnGatewayInput{
|
||||
VpnGatewayId: aws.String(d.Id()),
|
||||
})
|
||||
|
@ -139,17 +139,17 @@ func resourceAwsVpnGatewayDelete(d *schema.ResourceData, meta interface{}) error
|
|||
|
||||
ec2err, ok := err.(awserr.Error)
|
||||
if !ok {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
|
||||
switch ec2err.Code() {
|
||||
case "InvalidVpnGatewayID.NotFound":
|
||||
return nil
|
||||
case "IncorrectState":
|
||||
return err // retry
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -173,16 +173,16 @@ func resourceAwsVpnGatewayAttach(d *schema.ResourceData, meta interface{}) error
|
|||
VpcId: aws.String(d.Get("vpc_id").(string)),
|
||||
}
|
||||
|
||||
err := resource.Retry(30*time.Second, func() error {
|
||||
err := resource.Retry(30*time.Second, func() *resource.RetryError {
|
||||
_, err := conn.AttachVpnGateway(req)
|
||||
if err != nil {
|
||||
if ec2err, ok := err.(awserr.Error); ok {
|
||||
if "InvalidVpnGatewayID.NotFound" == ec2err.Code() {
|
||||
//retry
|
||||
return fmt.Errorf("Gateway not found, retry for eventual consistancy")
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Gateway not found, retry for eventual consistancy"))
|
||||
}
|
||||
}
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
|
@ -622,16 +622,17 @@ func resourceAzureInstanceDelete(d *schema.ResourceData, meta interface{}) error
|
|||
return err
|
||||
}
|
||||
|
||||
err = resource.Retry(15*time.Minute, func() error {
|
||||
err = resource.Retry(15*time.Minute, func() *resource.RetryError {
|
||||
exists, err := blobClient.BlobExists(
|
||||
storageContainterName, fmt.Sprintf(osDiskBlobNameFormat, name),
|
||||
)
|
||||
if err != nil {
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
|
||||
if exists {
|
||||
return fmt.Errorf("Instance '%s''s disk storage blob still exists.", name)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Instance '%s''s disk storage blob still exists.", name))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -117,11 +117,12 @@ func testAccAzureDatabaseServerFirewallRuleExists(name string, servers []string)
|
|||
for _, server := range servers {
|
||||
var rules sql.ListFirewallRulesResponse
|
||||
|
||||
err := resource.Retry(15*time.Minute, func() error {
|
||||
err := resource.Retry(15*time.Minute, func() *resource.RetryError {
|
||||
var erri error
|
||||
rules, erri = sqlClient.ListFirewallRules(server)
|
||||
if erri != nil {
|
||||
return fmt.Errorf("Error listing Azure Database Server Firewall Rules for Server %q: %s", server, erri)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Error listing Azure Database Server Firewall Rules for Server %q: %s", server, erri))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -49,13 +49,13 @@ func resourceHerokuDrainCreate(d *schema.ResourceData, meta interface{}) error {
|
|||
log.Printf("[DEBUG] Drain create configuration: %#v, %#v", app, url)
|
||||
|
||||
var dr *heroku.LogDrain
|
||||
err := resource.Retry(2*time.Minute, func() error {
|
||||
err := resource.Retry(2*time.Minute, func() *resource.RetryError {
|
||||
d, err := client.LogDrainCreate(app, heroku.LogDrainCreateOpts{URL: url})
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), retryableError) {
|
||||
return err
|
||||
return resource.RetryableError(err)
|
||||
}
|
||||
return resource.RetryError{Err: err}
|
||||
return resource.NonRetryableError(err)
|
||||
}
|
||||
dr = d
|
||||
return nil
|
||||
|
|
|
@ -146,11 +146,12 @@ func resourceMailgunDomainDelete(d *schema.ResourceData, meta interface{}) error
|
|||
}
|
||||
|
||||
// Give the destroy a chance to take effect
|
||||
return resource.Retry(1*time.Minute, func() error {
|
||||
return resource.Retry(1*time.Minute, func() *resource.RetryError {
|
||||
_, err = client.RetrieveDomain(d.Id())
|
||||
if err == nil {
|
||||
log.Printf("[INFO] Retrying until domain disappears...")
|
||||
return fmt.Errorf("Domain seems to still exist; will check again.")
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Domain seems to still exist; will check again."))
|
||||
}
|
||||
log.Printf("[INFO] Got error looking for domain, seems gone: %s", err)
|
||||
return nil
|
||||
|
|
|
@ -3,6 +3,7 @@ package vcd
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
|
@ -60,15 +61,16 @@ func resourceVcdDNATCreate(d *schema.ResourceData, meta interface{}) error {
|
|||
// constrained by out lock. If the edge gateway reurns with a busy error, wait
|
||||
// 3 seconds and then try again. Continue until a non-busy error or success
|
||||
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := edgeGateway.AddNATMapping("DNAT", d.Get("external_ip").(string),
|
||||
d.Get("internal_ip").(string),
|
||||
portString)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error setting DNAT rules: %#v", err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Error setting DNAT rules: %#v", err))
|
||||
}
|
||||
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
@ -119,15 +121,16 @@ func resourceVcdDNATDelete(d *schema.ResourceData, meta interface{}) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("Unable to find edge gateway: %#v", err)
|
||||
}
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := edgeGateway.RemoveNATMapping("DNAT", d.Get("external_ip").(string),
|
||||
d.Get("internal_ip").(string),
|
||||
portString)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error setting DNAT rules: %#v", err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Error setting DNAT rules: %#v", err))
|
||||
}
|
||||
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error completing tasks: %#v", err)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
types "github.com/hmrc/vmware-govcd/types/v56"
|
||||
)
|
||||
|
@ -91,16 +92,17 @@ func resourceVcdFirewallRulesCreate(d *schema.ResourceData, meta interface{}) er
|
|||
return fmt.Errorf("Unable to find edge gateway: %s", err)
|
||||
}
|
||||
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
edgeGateway.Refresh()
|
||||
firewallRules, _ := expandFirewallRules(d, edgeGateway.EdgeGateway)
|
||||
task, err := edgeGateway.CreateFirewallRules(d.Get("default_action").(string), firewallRules)
|
||||
if err != nil {
|
||||
log.Printf("[INFO] Error setting firewall rules: %s", err)
|
||||
return fmt.Errorf("Error setting firewall rules: %#v", err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Error setting firewall rules: %#v", err))
|
||||
}
|
||||
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error completing tasks: %#v", err)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/hashcode"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
types "github.com/hmrc/vmware-govcd/types/v56"
|
||||
)
|
||||
|
@ -156,8 +157,8 @@ func resourceVcdNetworkCreate(d *schema.ResourceData, meta interface{}) error {
|
|||
|
||||
log.Printf("[INFO] NETWORK: %#v", newnetwork)
|
||||
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
return vcdClient.OrgVdc.CreateOrgVDCNetwork(newnetwork)
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
return resource.RetryableError(vcdClient.OrgVdc.CreateOrgVDCNetwork(newnetwork))
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error: %#v", err)
|
||||
|
@ -174,13 +175,13 @@ func resourceVcdNetworkCreate(d *schema.ResourceData, meta interface{}) error {
|
|||
}
|
||||
|
||||
if dhcp, ok := d.GetOk("dhcp_pool"); ok {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := edgeGateway.AddDhcpPool(network.OrgVDCNetwork, dhcp.(*schema.Set).List())
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error adding DHCP pool: %#v", err)
|
||||
return resource.RetryableError(fmt.Errorf("Error adding DHCP pool: %#v", err))
|
||||
}
|
||||
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error completing tasks: %#v", err)
|
||||
|
@ -239,12 +240,13 @@ func resourceVcdNetworkDelete(d *schema.ResourceData, meta interface{}) error {
|
|||
return fmt.Errorf("Error finding network: %#v", err)
|
||||
}
|
||||
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := network.Delete()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error Deleting Network: %#v", err)
|
||||
return resource.RetryableError(
|
||||
fmt.Errorf("Error Deleting Network: %#v", err))
|
||||
}
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -3,6 +3,7 @@ package vcd
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
|
@ -51,14 +52,14 @@ func resourceVcdSNATCreate(d *schema.ResourceData, meta interface{}) error {
|
|||
return fmt.Errorf("Unable to find edge gateway: %#v", err)
|
||||
}
|
||||
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := edgeGateway.AddNATMapping("SNAT", d.Get("internal_ip").(string),
|
||||
d.Get("external_ip").(string),
|
||||
"any")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error setting SNAT rules: %#v", err)
|
||||
return resource.RetryableError(fmt.Errorf("Error setting SNAT rules: %#v", err))
|
||||
}
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -106,14 +107,14 @@ func resourceVcdSNATDelete(d *schema.ResourceData, meta interface{}) error {
|
|||
return fmt.Errorf("Unable to find edge gateway: %#v", err)
|
||||
}
|
||||
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := edgeGateway.RemoveNATMapping("SNAT", d.Get("internal_ip").(string),
|
||||
d.Get("external_ip").(string),
|
||||
"")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error setting SNAT rules: %#v", err)
|
||||
return resource.RetryableError(fmt.Errorf("Error setting SNAT rules: %#v", err))
|
||||
}
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
types "github.com/hmrc/vmware-govcd/types/v56"
|
||||
)
|
||||
|
@ -133,16 +134,16 @@ func resourceVcdVAppCreate(d *schema.ResourceData, meta interface{}) error {
|
|||
},
|
||||
}
|
||||
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
e := vcdClient.OrgVdc.InstantiateVAppTemplate(createvapp)
|
||||
|
||||
if e != nil {
|
||||
return fmt.Errorf("Error: %#v", e)
|
||||
return resource.RetryableError(fmt.Errorf("Error: %#v", e))
|
||||
}
|
||||
|
||||
e = vcdClient.OrgVdc.Refresh()
|
||||
if e != nil {
|
||||
return fmt.Errorf("Error: %#v", e)
|
||||
return resource.RetryableError(fmt.Errorf("Error: %#v", e))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
@ -152,36 +153,36 @@ func resourceVcdVAppCreate(d *schema.ResourceData, meta interface{}) error {
|
|||
|
||||
vapp, err := vcdClient.OrgVdc.FindVAppByName(d.Get("name").(string))
|
||||
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := vapp.ChangeVMName(d.Get("name").(string))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error with vm name change: %#v", err)
|
||||
return resource.RetryableError(fmt.Errorf("Error with vm name change: %#v", err))
|
||||
}
|
||||
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error changing vmname: %#v", err)
|
||||
}
|
||||
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := vapp.ChangeNetworkConfig(d.Get("network_name").(string), d.Get("ip").(string))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error with Networking change: %#v", err)
|
||||
return resource.RetryableError(fmt.Errorf("Error with Networking change: %#v", err))
|
||||
}
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error changing network: %#v", err)
|
||||
}
|
||||
|
||||
if initscript, ok := d.GetOk("initscript"); ok {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := vapp.RunCustomizationScript(d.Get("name").(string), initscript.(string))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error with setting init script: %#v", err)
|
||||
return resource.RetryableError(fmt.Errorf("Error with setting init script: %#v", err))
|
||||
}
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error completing tasks: %#v", err)
|
||||
|
@ -246,13 +247,13 @@ func resourceVcdVAppUpdate(d *schema.ResourceData, meta interface{}) error {
|
|||
}
|
||||
|
||||
if d.HasChange("memory") {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := vapp.ChangeMemorySize(d.Get("memory").(int))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error changing memory size: %#v", err)
|
||||
return resource.RetryableError(fmt.Errorf("Error changing memory size: %#v", err))
|
||||
}
|
||||
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -260,13 +261,13 @@ func resourceVcdVAppUpdate(d *schema.ResourceData, meta interface{}) error {
|
|||
}
|
||||
|
||||
if d.HasChange("cpus") {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := vapp.ChangeCPUcount(d.Get("cpus").(int))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error changing cpu count: %#v", err)
|
||||
return resource.RetryableError(fmt.Errorf("Error changing cpu count: %#v", err))
|
||||
}
|
||||
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error completing task: %#v", err)
|
||||
|
@ -317,18 +318,18 @@ func getVAppIPAddress(d *schema.ResourceData, meta interface{}) (string, error)
|
|||
vcdClient := meta.(*VCDClient)
|
||||
var ip string
|
||||
|
||||
err := retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err := retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
err := vcdClient.OrgVdc.Refresh()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error refreshing vdc: %#v", err)
|
||||
return resource.RetryableError(fmt.Errorf("Error refreshing vdc: %#v", err))
|
||||
}
|
||||
vapp, err := vcdClient.OrgVdc.FindVAppByName(d.Id())
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to find vapp.")
|
||||
return resource.RetryableError(fmt.Errorf("Unable to find vapp."))
|
||||
}
|
||||
ip = vapp.VApp.Children.VM[0].NetworkConnectionSection.NetworkConnection.IPAddress
|
||||
if ip == "" {
|
||||
return fmt.Errorf("Timeout: VM did not aquire IP address")
|
||||
return resource.RetryableError(fmt.Errorf("Timeout: VM did not aquire IP address"))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
@ -348,22 +349,22 @@ func resourceVcdVAppDelete(d *schema.ResourceData, meta interface{}) error {
|
|||
return fmt.Errorf("Error getting VApp status: %#v", err)
|
||||
}
|
||||
|
||||
_ = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
_ = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := vapp.Undeploy()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error undeploying: %#v", err)
|
||||
return resource.RetryableError(fmt.Errorf("Error undeploying: %#v", err))
|
||||
}
|
||||
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() error {
|
||||
err = retryCall(vcdClient.MaxRetryTimeout, func() *resource.RetryError {
|
||||
task, err := vapp.Delete()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error deleting: %#v", err)
|
||||
return resource.RetryableError(fmt.Errorf("Error deleting: %#v", err))
|
||||
}
|
||||
|
||||
return task.WaitTaskCompletion()
|
||||
return resource.RetryableError(task.WaitTaskCompletion())
|
||||
})
|
||||
|
||||
return err
|
||||
|
|
|
@ -5,9 +5,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// RetryFunc is the function retried until it succeeds.
|
||||
type RetryFunc func() error
|
||||
|
||||
// Retry is a basic wrapper around StateChangeConf that will just retry
|
||||
// a function until it no longer returns an error.
|
||||
func Retry(timeout time.Duration, f RetryFunc) error {
|
||||
|
@ -17,25 +14,24 @@ func Retry(timeout time.Duration, f RetryFunc) error {
|
|||
var resultErrMu sync.Mutex
|
||||
|
||||
c := &StateChangeConf{
|
||||
Pending: []string{"error"},
|
||||
Pending: []string{"retryableerror"},
|
||||
Target: []string{"success"},
|
||||
Timeout: timeout,
|
||||
MinTimeout: 500 * time.Millisecond,
|
||||
Refresh: func() (interface{}, string, error) {
|
||||
err := f()
|
||||
if err == nil {
|
||||
rerr := f()
|
||||
if rerr == nil {
|
||||
return 42, "success", nil
|
||||
}
|
||||
|
||||
resultErrMu.Lock()
|
||||
defer resultErrMu.Unlock()
|
||||
resultErr = err
|
||||
if rerr, ok := err.(RetryError); ok {
|
||||
resultErr = rerr.Err
|
||||
return nil, "quit", rerr.Err
|
||||
}
|
||||
resultErr = rerr.Err
|
||||
|
||||
return 42, "error", nil
|
||||
if rerr.Retryable {
|
||||
return 42, "retryableerror", nil
|
||||
}
|
||||
return nil, "quit", rerr.Err
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -48,12 +44,30 @@ func Retry(timeout time.Duration, f RetryFunc) error {
|
|||
return resultErr
|
||||
}
|
||||
|
||||
// RetryError, if returned, will quit the retry immediately with the
|
||||
// Err.
|
||||
// RetryFunc is the function retried until it succeeds.
|
||||
type RetryFunc func() *RetryError
|
||||
|
||||
// RetryError is the required return type of RetryFunc. It forces client code
|
||||
// to choose whether or not a given error is retryable.
|
||||
type RetryError struct {
|
||||
Err error
|
||||
Err error
|
||||
Retryable bool
|
||||
}
|
||||
|
||||
func (e RetryError) Error() string {
|
||||
return e.Err.Error()
|
||||
// RetryableError is a helper to create a RetryError that's retryable from a
|
||||
// given error.
|
||||
func RetryableError(err error) *RetryError {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &RetryError{Err: err, Retryable: true}
|
||||
}
|
||||
|
||||
// NonRetryableError is a helper to create a RetryError that's _not)_ retryable
|
||||
// from a given error.
|
||||
func NonRetryableError(err error) *RetryError {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &RetryError{Err: err, Retryable: false}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@ func TestRetry(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
tries := 0
|
||||
f := func() error {
|
||||
f := func() *RetryError {
|
||||
tries++
|
||||
if tries == 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("error")
|
||||
return RetryableError(fmt.Errorf("error"))
|
||||
}
|
||||
|
||||
err := Retry(2*time.Second, f)
|
||||
|
@ -28,8 +28,8 @@ func TestRetry(t *testing.T) {
|
|||
func TestRetry_timeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
f := func() error {
|
||||
return fmt.Errorf("always")
|
||||
f := func() *RetryError {
|
||||
return RetryableError(fmt.Errorf("always"))
|
||||
}
|
||||
|
||||
err := Retry(1*time.Second, f)
|
||||
|
@ -42,8 +42,8 @@ func TestRetry_error(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
expected := fmt.Errorf("nope")
|
||||
f := func() error {
|
||||
return RetryError{expected}
|
||||
f := func() *RetryError {
|
||||
return NonRetryableError(expected)
|
||||
}
|
||||
|
||||
errCh := make(chan error)
|
||||
|
|
Loading…
Reference in New Issue