Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resource/aws_ecs_capacity_provider: Add support for ECS capacity provider update #16942

Merged
merged 4 commits into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/16942.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_ecs_capacity_provider: Allow updates to the `auto_scaling_group_provider` argument without recreating the resource
```
31 changes: 31 additions & 0 deletions aws/internal/service/ecs/finder/finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,37 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func CapacityProviderByARN(conn *ecs.ECS, arn string) (*ecs.CapacityProvider, error) {
input := &ecs.DescribeCapacityProvidersInput{
CapacityProviders: aws.StringSlice([]string{arn}),
Include: aws.StringSlice([]string{ecs.CapacityProviderFieldTags}),
}

output, err := conn.DescribeCapacityProviders(input)

if err != nil {
return nil, err
}

if output == nil || len(output.CapacityProviders) == 0 || output.CapacityProviders[0] == nil {
return nil, &resource.NotFoundError{
Message: "Empty result",
LastRequest: input,
}
}

capacityProvider := output.CapacityProviders[0]

if status := aws.StringValue(capacityProvider.Status); status == ecs.CapacityProviderStatusInactive {
return nil, &resource.NotFoundError{
Message: status,
LastRequest: input,
}
}

return capacityProvider, nil
}

func ClusterByARN(conn *ecs.ECS, arn string) (*ecs.DescribeClustersOutput, error) {
input := &ecs.DescribeClustersInput{
Clusters: []*string{aws.String(arn)},
Expand Down
3 changes: 3 additions & 0 deletions aws/internal/service/ecs/lister/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//go:generate go run ../../../generators/listpages/main.go -function=DescribeCapacityProviders -paginator=NextToken github.com/aws/aws-sdk-go/service/ecs

package lister
31 changes: 31 additions & 0 deletions aws/internal/service/ecs/lister/list_pages_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 22 additions & 16 deletions aws/internal/service/ecs/waiter/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,10 @@ import (
"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/ecs/finder"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource"
)

const (
// EventSubscription NotFound
CapacityProviderStatusNotFound = "NotFound"

// EventSubscription Unknown
CapacityProviderStatusUnknown = "Unknown"

// AWS will likely add consts for these at some point
ServiceStatusInactive = "INACTIVE"
ServiceStatusActive = "ACTIVE"
Expand All @@ -29,24 +24,35 @@ const (
ClusterStatusNone = "NONE"
)

// CapacityProviderStatus fetches the Capacity Provider and its Status
func CapacityProviderStatus(conn *ecs.ECS, capacityProvider string) resource.StateRefreshFunc {
func CapacityProviderStatus(conn *ecs.ECS, arn string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
input := &ecs.DescribeCapacityProvidersInput{
CapacityProviders: aws.StringSlice([]string{capacityProvider}),
}
output, err := finder.CapacityProviderByARN(conn, arn)

output, err := conn.DescribeCapacityProviders(input)
if tfresource.NotFound(err) {
return nil, "", nil
}

if err != nil {
return nil, CapacityProviderStatusUnknown, err
return nil, "", err
}

return output, aws.StringValue(output.Status), nil
}
}

func CapacityProviderUpdateStatus(conn *ecs.ECS, arn string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := finder.CapacityProviderByARN(conn, arn)

if tfresource.NotFound(err) {
return nil, "", nil
}

if len(output.CapacityProviders) == 0 {
return nil, CapacityProviderStatusNotFound, nil
if err != nil {
return nil, "", err
}

return output.CapacityProviders[0], aws.StringValue(output.CapacityProviders[0].Status), nil
return output, aws.StringValue(output.UpdateStatus), nil
}
}

Expand Down
30 changes: 23 additions & 7 deletions aws/internal/service/ecs/waiter/waiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
)

const (
// Maximum amount of time to wait for a Capacity Provider to return INACTIVE
CapacityProviderInactiveTimeout = 20 * time.Minute
CapacityProviderDeleteTimeout = 20 * time.Minute
CapacityProviderUpdateTimeout = 10 * time.Minute

ServiceCreateTimeout = 2 * time.Minute
ServiceInactiveTimeout = 10 * time.Minute
Expand All @@ -23,13 +23,29 @@ const (
ClusterAvailableDelay = 10 * time.Second
)

// CapacityProviderInactive waits for a Capacity Provider to return INACTIVE
func CapacityProviderInactive(conn *ecs.ECS, capacityProvider string) (*ecs.CapacityProvider, error) {
func CapacityProviderDeleted(conn *ecs.ECS, arn string) (*ecs.CapacityProvider, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{ecs.CapacityProviderStatusActive},
Target: []string{ecs.CapacityProviderStatusInactive},
Refresh: CapacityProviderStatus(conn, capacityProvider),
Timeout: CapacityProviderInactiveTimeout,
Target: []string{},
Refresh: CapacityProviderStatus(conn, arn),
Timeout: CapacityProviderDeleteTimeout,
}

outputRaw, err := stateConf.WaitForState()

if v, ok := outputRaw.(*ecs.CapacityProvider); ok {
return v, err
}

return nil, err
}

func CapacityProviderUpdated(conn *ecs.ECS, arn string) (*ecs.CapacityProvider, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{ecs.CapacityProviderUpdateStatusUpdateInProgress},
Target: []string{ecs.CapacityProviderUpdateStatusUpdateComplete},
Refresh: CapacityProviderUpdateStatus(conn, arn),
Timeout: CapacityProviderUpdateTimeout,
}

outputRaw, err := stateConf.WaitForState()
Expand Down
Loading