Skip to content

Commit

Permalink
Merge pull request #20463 from hashicorp/t-aws_synthetics_canary-test…
Browse files Browse the repository at this point in the history
…-failures

r/aws_synthetics_canary: Correctly report creation errors
  • Loading branch information
ewbankkit authored Aug 6, 2021
2 parents 36d4ef7 + 378c849 commit f05e452
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 168 deletions.
3 changes: 3 additions & 0 deletions .changelog/20463.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
resource/aws_synthetics_canary: Correctly report any resource creation errors
```
22 changes: 19 additions & 3 deletions aws/internal/service/synthetics/finder/finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,34 @@ package finder
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/synthetics"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

// CanaryByName returns the Canary corresponding to the specified Name.
func CanaryByName(conn *synthetics.Synthetics, name string) (*synthetics.GetCanaryOutput, error) {
func CanaryByName(conn *synthetics.Synthetics, name string) (*synthetics.Canary, error) {
input := &synthetics.GetCanaryInput{
Name: aws.String(name),
}

output, err := conn.GetCanary(input)

if tfawserr.ErrCodeEquals(err, synthetics.ErrCodeResourceNotFoundException) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

return output, nil
if output == nil || output.Canary == nil || output.Canary.Status == nil {
return nil, &resource.NotFoundError{
Message: "Empty result",
LastRequest: input,
}
}

return output.Canary, nil
}
15 changes: 7 additions & 8 deletions aws/internal/service/synthetics/waiter/status.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
package waiter

import (
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/synthetics"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/synthetics/finder"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource"
)

func CanaryStatus(conn *synthetics.Synthetics, name string) resource.StateRefreshFunc {
func CanaryState(conn *synthetics.Synthetics, name string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := finder.CanaryByName(conn, name)

if err != nil {
return nil, synthetics.CanaryStateError, err
if tfresource.NotFound(err) {
return nil, "", nil
}

if aws.StringValue(output.Canary.Status.State) == synthetics.CanaryStateError {
return output, synthetics.CanaryStateError, fmt.Errorf("%s: %s", aws.StringValue(output.Canary.Status.StateReasonCode), aws.StringValue(output.Canary.Status.StateReason))
if err != nil {
return nil, "", err
}

return output, aws.StringValue(output.Canary.Status.State), nil
return output, aws.StringValue(output.Status.State), nil
}
}
73 changes: 48 additions & 25 deletions aws/internal/service/synthetics/waiter/waiter.go
Original file line number Diff line number Diff line change
@@ -1,89 +1,112 @@
package waiter

import (
"fmt"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/synthetics"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource"
)

const (
// Maximum amount of time to wait for a Canary to return Ready
CanaryCreatedTimeout = 5 * time.Minute
CanaryRunningTimeout = 5 * time.Minute
CanaryStoppedTimeout = 5 * time.Minute
CanaryDeletedTimeout = 5 * time.Minute
)

// CanaryReady waits for a Canary to return Ready
func CanaryReady(conn *synthetics.Synthetics, name string) (*synthetics.GetCanaryOutput, error) {
func CanaryReady(conn *synthetics.Synthetics, name string) (*synthetics.Canary, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{synthetics.CanaryStateCreating, synthetics.CanaryStateUpdating},
Target: []string{synthetics.CanaryStateReady},
Refresh: CanaryStatus(conn, name),
Refresh: CanaryState(conn, name),
Timeout: CanaryCreatedTimeout,
}

outputRaw, err := stateConf.WaitForState()

if v, ok := outputRaw.(*synthetics.GetCanaryOutput); ok {
return v, err
if output, ok := outputRaw.(*synthetics.Canary); ok {
if status := output.Status; aws.StringValue(status.State) == synthetics.CanaryStateError {
tfresource.SetLastError(err, fmt.Errorf("%s: %s", aws.StringValue(status.StateReasonCode), aws.StringValue(status.StateReason)))
}

return output, err
}

return nil, err
}

// CanaryReady waits for a Canary to return Stopped
func CanaryStopped(conn *synthetics.Synthetics, name string) (*synthetics.GetCanaryOutput, error) {
func CanaryStopped(conn *synthetics.Synthetics, name string) (*synthetics.Canary, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{synthetics.CanaryStateStopping, synthetics.CanaryStateUpdating,
synthetics.CanaryStateRunning, synthetics.CanaryStateReady, synthetics.CanaryStateStarting},
Pending: []string{
synthetics.CanaryStateStopping,
synthetics.CanaryStateUpdating,
synthetics.CanaryStateRunning,
synthetics.CanaryStateReady,
synthetics.CanaryStateStarting,
},
Target: []string{synthetics.CanaryStateStopped},
Refresh: CanaryStatus(conn, name),
Refresh: CanaryState(conn, name),
Timeout: CanaryStoppedTimeout,
}

outputRaw, err := stateConf.WaitForState()

if v, ok := outputRaw.(*synthetics.GetCanaryOutput); ok {
return v, err
if output, ok := outputRaw.(*synthetics.Canary); ok {
if status := output.Status; aws.StringValue(status.State) == synthetics.CanaryStateError {
tfresource.SetLastError(err, fmt.Errorf("%s: %s", aws.StringValue(status.StateReasonCode), aws.StringValue(status.StateReason)))
}

return output, err
}

return nil, err
}

// CanaryReady waits for a Canary to return Running
func CanaryRunning(conn *synthetics.Synthetics, name string) (*synthetics.GetCanaryOutput, error) {
func CanaryRunning(conn *synthetics.Synthetics, name string) (*synthetics.Canary, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{synthetics.CanaryStateStarting, synthetics.CanaryStateUpdating,
synthetics.CanaryStateStarting, synthetics.CanaryStateReady},
Pending: []string{
synthetics.CanaryStateStarting,
synthetics.CanaryStateUpdating,
synthetics.CanaryStateStarting,
synthetics.CanaryStateReady,
},
Target: []string{synthetics.CanaryStateRunning},
Refresh: CanaryStatus(conn, name),
Refresh: CanaryState(conn, name),
Timeout: CanaryRunningTimeout,
}

outputRaw, err := stateConf.WaitForState()

if v, ok := outputRaw.(*synthetics.GetCanaryOutput); ok {
return v, err
if output, ok := outputRaw.(*synthetics.Canary); ok {
if status := output.Status; aws.StringValue(status.State) == synthetics.CanaryStateError {
tfresource.SetLastError(err, fmt.Errorf("%s: %s", aws.StringValue(status.StateReasonCode), aws.StringValue(status.StateReason)))
}

return output, err
}

return nil, err
}

// CanaryReady waits for a Canary to return Ready
func CanaryDeleted(conn *synthetics.Synthetics, name string) (*synthetics.GetCanaryOutput, error) {
func CanaryDeleted(conn *synthetics.Synthetics, name string) (*synthetics.Canary, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{synthetics.CanaryStateDeleting, synthetics.CanaryStateStopped},
Target: []string{},
Refresh: CanaryStatus(conn, name),
Refresh: CanaryState(conn, name),
Timeout: CanaryDeletedTimeout,
}

outputRaw, err := stateConf.WaitForState()

if v, ok := outputRaw.(*synthetics.GetCanaryOutput); ok {
return v, err
if output, ok := outputRaw.(*synthetics.Canary); ok {
if status := output.Status; aws.StringValue(status.State) == synthetics.CanaryStateError {
tfresource.SetLastError(err, fmt.Errorf("%s: %s", aws.StringValue(status.StateReasonCode), aws.StringValue(status.StateReason)))
}

return output, err
}

return nil, err
Expand Down
Loading

0 comments on commit f05e452

Please sign in to comment.