-
Notifications
You must be signed in to change notification settings - Fork 9.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix aws_ram_resource_share_accepter eventual consistency problems
- Loading branch information
1 parent
6034deb
commit 559e521
Showing
5 changed files
with
338 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
package finder | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/ram" | ||
"github.com/hashicorp/aws-sdk-go-base/tfawserr" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" | ||
) | ||
|
||
// ResourceShareOwnerOtherAccountsByArn returns the resource share owned by other accounts corresponding to the specified ARN. | ||
// Returns nil if no configuration is found. | ||
func ResourceShareOwnerOtherAccountsByArn(conn *ram.RAM, arn string) (*ram.ResourceShare, error) { | ||
listResourceSharesInput := &ram.GetResourceSharesInput{ | ||
ResourceOwner: aws.String(ram.ResourceOwnerOtherAccounts), | ||
ResourceShareArns: aws.StringSlice([]string{arn}), | ||
} | ||
|
||
return resourceShare(conn, listResourceSharesInput) | ||
} | ||
|
||
// ResourceShareOwnerSelfByArn returns the resource share owned by own account corresponding to the specified ARN. | ||
// Returns nil if no configuration is found. | ||
func ResourceShareOwnerSelfByArn(conn *ram.RAM, arn string) (*ram.ResourceShare, error) { | ||
listResourceSharesInput := &ram.GetResourceSharesInput{ | ||
ResourceOwner: aws.String(ram.ResourceOwnerSelf), | ||
ResourceShareArns: aws.StringSlice([]string{arn}), | ||
} | ||
|
||
return resourceShare(conn, listResourceSharesInput) | ||
} | ||
|
||
// ResourceShareInvitationByResourceShareArnAndStatus returns the resource share invitation corresponding to the specified resource share ARN. | ||
// Returns nil if no configuration is found. | ||
func ResourceShareInvitationByResourceShareArnAndStatus(conn *ram.RAM, resourceShareArn, status string) (*ram.ResourceShareInvitation, error) { | ||
var invitation *ram.ResourceShareInvitation | ||
|
||
// Retry for Ram resource share invitation eventual consistency | ||
err := resource.Retry(30*time.Second, func() *resource.RetryError { | ||
i, err := resourceShareInvitationByResourceShareArnAndStatus(conn, resourceShareArn, status) | ||
invitation = i | ||
|
||
if err != nil { | ||
return resource.NonRetryableError(err) | ||
} | ||
|
||
if invitation == nil { | ||
return resource.RetryableError(&resource.NotFoundError{}) | ||
} | ||
|
||
return nil | ||
}) | ||
|
||
if tfresource.TimedOut(err) { | ||
invitation, err = resourceShareInvitationByResourceShareArnAndStatus(conn, resourceShareArn, status) | ||
} | ||
|
||
if invitation == nil { | ||
return nil, nil | ||
} | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return invitation, nil | ||
} | ||
|
||
// ResourceShareInvitationByArn returns the resource share invitation corresponding to the specified ARN. | ||
// Returns nil if no configuration is found. | ||
func ResourceShareInvitationByArn(conn *ram.RAM, arn string) (*ram.ResourceShareInvitation, error) { | ||
var invitation *ram.ResourceShareInvitation | ||
|
||
// Retry for Ram resource share invitation eventual consistency | ||
err := resource.Retry(30*time.Second, func() *resource.RetryError { | ||
i, err := resourceShareInvitationByArn(conn, arn) | ||
invitation = i | ||
|
||
if err != nil { | ||
return resource.NonRetryableError(err) | ||
} | ||
|
||
if invitation == nil { | ||
resource.RetryableError(&resource.NotFoundError{}) | ||
} | ||
|
||
return nil | ||
}) | ||
|
||
if tfresource.TimedOut(err) { | ||
invitation, err = resourceShareInvitationByArn(conn, arn) | ||
} | ||
|
||
if invitation == nil { | ||
return nil, nil | ||
} | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return invitation, nil | ||
} | ||
|
||
func resourceShare(conn *ram.RAM, input *ram.GetResourceSharesInput) (*ram.ResourceShare, error) { | ||
var shares *ram.GetResourceSharesOutput | ||
|
||
// Retry for Ram resource share eventual consistency | ||
err := resource.Retry(30*time.Second, func() *resource.RetryError { | ||
ss, err := conn.GetResourceShares(input) | ||
shares = ss | ||
|
||
if tfawserr.ErrCodeEquals(err, ram.ErrCodeUnknownResourceException) { | ||
return resource.RetryableError(err) | ||
} | ||
|
||
if err != nil { | ||
return resource.NonRetryableError(err) | ||
} | ||
|
||
if len(shares.ResourceShares) == 0 { | ||
return resource.RetryableError(&resource.NotFoundError{}) | ||
} | ||
|
||
return nil | ||
}) | ||
|
||
if tfresource.TimedOut(err) { | ||
shares, err = conn.GetResourceShares(input) | ||
} | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if shares == nil || len(shares.ResourceShares) == 0 { | ||
return nil, nil | ||
} | ||
|
||
return shares.ResourceShares[0], nil | ||
} | ||
|
||
func resourceShareInvitationByResourceShareArnAndStatus(conn *ram.RAM, resourceShareArn, status string) (*ram.ResourceShareInvitation, error) { | ||
var invitation *ram.ResourceShareInvitation | ||
|
||
input := &ram.GetResourceShareInvitationsInput{ | ||
ResourceShareArns: []*string{aws.String(resourceShareArn)}, | ||
} | ||
|
||
err := conn.GetResourceShareInvitationsPages(input, func(page *ram.GetResourceShareInvitationsOutput, lastPage bool) bool { | ||
for _, rsi := range page.ResourceShareInvitations { | ||
if aws.StringValue(rsi.Status) == status { | ||
invitation = rsi | ||
return false | ||
} | ||
} | ||
|
||
return !lastPage | ||
}) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return invitation, nil | ||
} | ||
|
||
func resourceShareInvitationByArn(conn *ram.RAM, arn string) (*ram.ResourceShareInvitation, error) { | ||
input := &ram.GetResourceShareInvitationsInput{ | ||
ResourceShareInvitationArns: []*string{aws.String(arn)}, | ||
} | ||
|
||
output, err := conn.GetResourceShareInvitations(input) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if len(output.ResourceShareInvitations) == 0 { | ||
return nil, nil | ||
} | ||
|
||
return output.ResourceShareInvitations[0], nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package waiter | ||
|
||
import ( | ||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/ram" | ||
"github.com/hashicorp/aws-sdk-go-base/tfawserr" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/ram/finder" | ||
) | ||
|
||
const ( | ||
resourceShareInvitationStatusNotFound = "NotFound" | ||
resourceShareInvitationStatusUnknown = "Unknown" | ||
|
||
resourceShareStatusNotFound = "NotFound" | ||
resourceShareStatusUnknown = "Unknown" | ||
) | ||
|
||
// ResourceShareInvitationStatus fetches the ResourceShareInvitation and its Status | ||
func ResourceShareInvitationStatus(conn *ram.RAM, arn string) resource.StateRefreshFunc { | ||
return func() (interface{}, string, error) { | ||
invitation, err := finder.ResourceShareInvitationByArn(conn, arn) | ||
|
||
if err != nil { | ||
return nil, resourceShareInvitationStatusUnknown, err | ||
} | ||
|
||
if invitation == nil { | ||
return nil, resourceShareInvitationStatusNotFound, nil | ||
} | ||
|
||
return invitation, aws.StringValue(invitation.Status), nil | ||
} | ||
} | ||
|
||
// ResourceShareOwnerSelfStatus fetches the ResourceShare and its Status | ||
func ResourceShareOwnerSelfStatus(conn *ram.RAM, arn string) resource.StateRefreshFunc { | ||
return func() (interface{}, string, error) { | ||
share, err := finder.ResourceShareOwnerSelfByArn(conn, arn) | ||
|
||
if err != nil { | ||
if tfawserr.ErrCodeEquals(err, ram.ErrCodeUnknownResourceException) { | ||
return nil, resourceShareStatusNotFound, nil | ||
} | ||
|
||
return nil, resourceShareStatusUnknown, err | ||
} | ||
|
||
if share == nil { | ||
return nil, resourceShareStatusNotFound, nil | ||
} | ||
|
||
return share, aws.StringValue(share.Status), nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package waiter | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/aws/aws-sdk-go/service/ram" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
) | ||
|
||
// ResourceShareInvitationAccepted waits for a ResourceShareInvitation to return ACCEPTED | ||
func ResourceShareInvitationAccepted(conn *ram.RAM, arn string, timeout time.Duration) (*ram.ResourceShareInvitation, error) { | ||
stateConf := &resource.StateChangeConf{ | ||
Pending: []string{ram.ResourceShareInvitationStatusPending}, | ||
Target: []string{ram.ResourceShareInvitationStatusAccepted}, | ||
Refresh: ResourceShareInvitationStatus(conn, arn), | ||
Timeout: timeout, | ||
} | ||
|
||
outputRaw, err := stateConf.WaitForState() | ||
|
||
if v, ok := outputRaw.(*ram.ResourceShareInvitation); ok { | ||
return v, err | ||
} | ||
|
||
return nil, err | ||
} | ||
|
||
// ResourceShareOwnedBySelfDisassociated waits for a ResourceShare owned by own account to be disassociated | ||
func ResourceShareOwnedBySelfDisassociated(conn *ram.RAM, arn string, timeout time.Duration) (*ram.ResourceShare, error) { | ||
stateConf := &resource.StateChangeConf{ | ||
Pending: []string{ram.ResourceShareAssociationStatusAssociated}, | ||
Target: []string{}, | ||
Refresh: ResourceShareOwnerSelfStatus(conn, arn), | ||
Timeout: timeout, | ||
} | ||
|
||
outputRaw, err := stateConf.WaitForState() | ||
|
||
if v, ok := outputRaw.(*ram.ResourceShare); ok { | ||
return v, err | ||
} | ||
|
||
return nil, err | ||
} | ||
|
||
// ResourceShareOwnedBySelfActive waits for a ResourceShare owned by own account to return ACTIVE | ||
func ResourceShareOwnedBySelfActive(conn *ram.RAM, arn string, timeout time.Duration) (*ram.ResourceShare, error) { | ||
stateConf := &resource.StateChangeConf{ | ||
Pending: []string{ram.ResourceShareStatusPending}, | ||
Target: []string{ram.ResourceShareStatusActive}, | ||
Refresh: ResourceShareOwnerSelfStatus(conn, arn), | ||
Timeout: timeout, | ||
} | ||
|
||
outputRaw, err := stateConf.WaitForState() | ||
|
||
if v, ok := outputRaw.(*ram.ResourceShare); ok { | ||
return v, err | ||
} | ||
|
||
return nil, err | ||
} | ||
|
||
// ResourceShareOwnedBySelfDeleted waits for a ResourceShare owned by own account to return DELETED | ||
func ResourceShareOwnedBySelfDeleted(conn *ram.RAM, arn string, timeout time.Duration) (*ram.ResourceShare, error) { | ||
stateConf := &resource.StateChangeConf{ | ||
Pending: []string{ram.ResourceShareStatusDeleting}, | ||
Target: []string{ram.ResourceShareStatusDeleted}, | ||
Refresh: ResourceShareOwnerSelfStatus(conn, arn), | ||
Timeout: timeout, | ||
} | ||
|
||
outputRaw, err := stateConf.WaitForState() | ||
|
||
if v, ok := outputRaw.(*ram.ResourceShare); ok { | ||
return v, err | ||
} | ||
|
||
return nil, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.