mirror of https://github.com/docker/compose.git
Merge pull request #718 from docker/capacity_provider_shutdown
delete CapacityProvider before we invoke DeleteStack
This commit is contained in:
commit
10824fe7c1
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ecs
|
||||
|
||||
const (
|
||||
awsTypeCapacityProvider = "AWS::ECS::CapacityProvider"
|
||||
awsTypeAutoscalingGroup = "AWS::AutoScaling::AutoScalingGroup"
|
||||
)
|
50
ecs/down.go
50
ecs/down.go
|
@ -18,12 +18,58 @@ package ecs
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/compose-cli/progress"
|
||||
)
|
||||
|
||||
func (b *ecsAPIService) Down(ctx context.Context, project string) error {
|
||||
err := b.SDK.DeleteStack(ctx, project)
|
||||
resources, err := b.SDK.ListStackResources(ctx, project)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.WaitStackCompletion(ctx, project, stackDelete)
|
||||
|
||||
err = resources.apply(awsTypeCapacityProvider, delete(ctx, b.SDK.DeleteCapacityProvider))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = resources.apply(awsTypeAutoscalingGroup, delete(ctx, b.SDK.DeleteAutoscalingGroup))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
previousEvents, err := b.previousStackEvents(ctx, project)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = b.SDK.DeleteStack(ctx, project)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.WaitStackCompletion(ctx, project, stackDelete, previousEvents...)
|
||||
}
|
||||
|
||||
func (b *ecsAPIService) previousStackEvents(ctx context.Context, project string) ([]string, error) {
|
||||
events, err := b.SDK.DescribeStackEvents(ctx, project)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var previousEvents []string
|
||||
for _, e := range events {
|
||||
previousEvents = append(previousEvents, *e.EventId)
|
||||
}
|
||||
return previousEvents, nil
|
||||
}
|
||||
|
||||
func delete(ctx context.Context, delete func(ctx context.Context, arn string) error) func(r stackResource) error {
|
||||
return func(r stackResource) error {
|
||||
w := progress.ContextWriter(ctx)
|
||||
w.Event(progress.Event{
|
||||
ID: r.LogicalID,
|
||||
Status: progress.Working,
|
||||
StatusText: "DELETE_IN_PROGRESS",
|
||||
})
|
||||
return delete(ctx, r.ARN)
|
||||
}
|
||||
}
|
||||
|
|
41
ecs/sdk.go
41
ecs/sdk.go
|
@ -32,6 +32,8 @@ import (
|
|||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/autoscaling"
|
||||
"github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface"
|
||||
"github.com/aws/aws-sdk-go/service/cloudformation"
|
||||
"github.com/aws/aws-sdk-go/service/cloudformation/cloudformationiface"
|
||||
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
|
||||
|
@ -48,6 +50,7 @@ import (
|
|||
"github.com/aws/aws-sdk-go/service/iam/iamiface"
|
||||
"github.com/aws/aws-sdk-go/service/secretsmanager"
|
||||
"github.com/aws/aws-sdk-go/service/secretsmanager/secretsmanageriface"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -61,6 +64,7 @@ type sdk struct {
|
|||
CF cloudformationiface.CloudFormationAPI
|
||||
SM secretsmanageriface.SecretsManagerAPI
|
||||
SSM ssmiface.SSMAPI
|
||||
AG autoscalingiface.AutoScalingAPI
|
||||
}
|
||||
|
||||
func newSDK(sess *session.Session) sdk {
|
||||
|
@ -77,6 +81,7 @@ func newSDK(sess *session.Session) sdk {
|
|||
CF: cloudformation.New(sess),
|
||||
SM: secretsmanager.New(sess),
|
||||
SSM: ssm.New(sess),
|
||||
AG: autoscaling.New(sess),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,7 +369,24 @@ type stackResource struct {
|
|||
Status string
|
||||
}
|
||||
|
||||
func (s sdk) ListStackResources(ctx context.Context, name string) ([]stackResource, error) {
|
||||
type stackResourceFn func(r stackResource) error
|
||||
|
||||
type stackResources []stackResource
|
||||
|
||||
func (resources stackResources) apply(awsType string, fn stackResourceFn) error {
|
||||
var errs *multierror.Error
|
||||
for _, r := range resources {
|
||||
if r.Type == awsType {
|
||||
err := fn(r)
|
||||
if err != nil {
|
||||
errs = multierror.Append(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return errs.ErrorOrNil()
|
||||
}
|
||||
|
||||
func (s sdk) ListStackResources(ctx context.Context, name string) (stackResources, error) {
|
||||
// FIXME handle pagination
|
||||
res, err := s.CF.ListStackResourcesWithContext(ctx, &cloudformation.ListStackResourcesInput{
|
||||
StackName: aws.String(name),
|
||||
|
@ -373,7 +395,7 @@ func (s sdk) ListStackResources(ctx context.Context, name string) ([]stackResour
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resources := []stackResource{}
|
||||
resources := stackResources{}
|
||||
for _, r := range res.StackResourceSummaries {
|
||||
resources = append(resources, stackResource{
|
||||
LogicalID: aws.StringValue(r.LogicalResourceId),
|
||||
|
@ -714,3 +736,18 @@ func (s sdk) SecurityGroupExists(ctx context.Context, sg string) (bool, error) {
|
|||
}
|
||||
return len(desc.SecurityGroups) > 0, nil
|
||||
}
|
||||
|
||||
func (s sdk) DeleteCapacityProvider(ctx context.Context, arn string) error {
|
||||
_, err := s.ECS.DeleteCapacityProvider(&ecs.DeleteCapacityProviderInput{
|
||||
CapacityProvider: aws.String(arn),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (s sdk) DeleteAutoscalingGroup(ctx context.Context, arn string) error {
|
||||
_, err := s.AG.DeleteAutoScalingGroup(&autoscaling.DeleteAutoScalingGroupInput{
|
||||
AutoScalingGroupName: aws.String(arn),
|
||||
ForceDelete: aws.Bool(true),
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -28,8 +28,12 @@ import (
|
|||
"github.com/aws/aws-sdk-go/aws"
|
||||
)
|
||||
|
||||
func (b *ecsAPIService) WaitStackCompletion(ctx context.Context, name string, operation int) error { //nolint:gocyclo
|
||||
func (b *ecsAPIService) WaitStackCompletion(ctx context.Context, name string, operation int, ignored ...string) error { //nolint:gocyclo
|
||||
knownEvents := map[string]struct{}{}
|
||||
for _, id := range ignored {
|
||||
knownEvents[id] = struct{}{}
|
||||
}
|
||||
|
||||
// progress writer
|
||||
w := progress.ContextWriter(ctx)
|
||||
// Get the unique Stack ID so we can collect events without getting some from previous deployments with same name
|
||||
|
@ -78,7 +82,6 @@ func (b *ecsAPIService) WaitStackCompletion(ctx context.Context, name string, op
|
|||
case "CREATE_COMPLETE":
|
||||
if operation == stackCreate {
|
||||
progressStatus = progress.Done
|
||||
|
||||
}
|
||||
case "UPDATE_COMPLETE":
|
||||
if operation == stackUpdate {
|
||||
|
|
Loading…
Reference in New Issue