diff --git a/ecs/pkg/amazon/down.go b/ecs/pkg/amazon/down.go index ab708d21..616d6659 100644 --- a/ecs/pkg/amazon/down.go +++ b/ecs/pkg/amazon/down.go @@ -12,6 +12,11 @@ func (c *client) ComposeDown(ctx context.Context, projectName string, deleteClus } fmt.Printf("Delete stack ") + err = c.WaitStackCompletion(ctx, projectName) + if err != nil { + return err + } + if !deleteCluster { return nil } diff --git a/ecs/pkg/amazon/down_test.go b/ecs/pkg/amazon/down_test.go index 3bfc1e40..49e5fe2a 100644 --- a/ecs/pkg/amazon/down_test.go +++ b/ecs/pkg/amazon/down_test.go @@ -20,6 +20,7 @@ func TestDownDontDeleteCluster(t *testing.T) { ctx := context.TODO() recorder := m.EXPECT() recorder.DeleteStack(ctx, "test_project").Return(nil).Times(1) + recorder.WaitStackComplete(ctx, "test_project", gomock.Any()).Return(nil).Times(1) c.ComposeDown(ctx, "test_project", false) } @@ -37,6 +38,7 @@ func TestDownDeleteCluster(t *testing.T) { ctx := context.TODO() recorder := m.EXPECT() recorder.DeleteStack(ctx, "test_project").Return(nil).Times(1) + recorder.WaitStackComplete(ctx, "test_project", gomock.Any()).Return(nil).Times(1) recorder.DeleteCluster(ctx, "test_cluster").Return(nil).Times(1) c.ComposeDown(ctx, "test_project", true) diff --git a/ecs/pkg/amazon/up.go b/ecs/pkg/amazon/up.go index c7a50409..0ee37e5f 100644 --- a/ecs/pkg/amazon/up.go +++ b/ecs/pkg/amazon/up.go @@ -3,13 +3,9 @@ package amazon import ( "context" "fmt" - "sort" - "github.com/aws/aws-sdk-go/aws" - cf "github.com/aws/aws-sdk-go/service/cloudformation" "github.com/awslabs/goformation/v4/cloudformation" "github.com/docker/ecs-plugin/pkg/compose" - "github.com/docker/ecs-plugin/pkg/console" ) func (c *client) ComposeUp(ctx context.Context, project *compose.Project) error { @@ -38,42 +34,13 @@ func (c *client) ComposeUp(ctx context.Context, project *compose.Project) error return err } - w := console.NewProgressWriter() - known := map[string]struct{}{} - err = c.api.WaitStackComplete(ctx, project.Name, func() error { - events, err := c.api.DescribeStackEvents(ctx, project.Name) - if err != nil { - return err - } - - sort.Slice(events, func(i, j int) bool { - return events[i].Timestamp.Before(*events[j].Timestamp) - }) - - for _, event := range events { - if _, ok := known[*event.EventId]; ok { - continue - } - known[*event.EventId] = struct{}{} - - resource := fmt.Sprintf("%s %q", aws.StringValue(event.ResourceType), aws.StringValue(event.LogicalResourceId)) - w.ResourceEvent(resource, aws.StringValue(event.ResourceStatus), aws.StringValue(event.ResourceStatusReason)) - } - return nil - }) - if err != nil { - return err - } - - // TODO monitor progress - return nil + return c.WaitStackCompletion(ctx, project.Name) } type upAPI interface { + waitAPI ClusterExists(ctx context.Context, name string) (bool, error) CreateCluster(ctx context.Context, name string) (string, error) StackExists(ctx context.Context, name string) (bool, error) CreateStack(ctx context.Context, name string, template *cloudformation.Template) error - WaitStackComplete(ctx context.Context, name string, fn func() error) error - DescribeStackEvents(ctx context.Context, stack string) ([]*cf.StackEvent, error) } diff --git a/ecs/pkg/amazon/wait.go b/ecs/pkg/amazon/wait.go new file mode 100644 index 00000000..f3a25c89 --- /dev/null +++ b/ecs/pkg/amazon/wait.go @@ -0,0 +1,46 @@ +package amazon + +import ( + "context" + "fmt" + "sort" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cloudformation" + "github.com/docker/ecs-plugin/pkg/console" +) + +func (c *client) WaitStackCompletion(ctx context.Context, name string) error { + w := console.NewProgressWriter() + known := map[string]struct{}{} + err := c.api.WaitStackComplete(ctx, name, func() error { + events, err := c.api.DescribeStackEvents(ctx, name) + if err != nil { + return err + } + + sort.Slice(events, func(i, j int) bool { + return events[i].Timestamp.Before(*events[j].Timestamp) + }) + + for _, event := range events { + if _, ok := known[*event.EventId]; ok { + continue + } + known[*event.EventId] = struct{}{} + + resource := fmt.Sprintf("%s %q", aws.StringValue(event.ResourceType), aws.StringValue(event.LogicalResourceId)) + w.ResourceEvent(resource, aws.StringValue(event.ResourceStatus), aws.StringValue(event.ResourceStatusReason)) + } + return nil + }) + if err != nil { + return err + } + return nil +} + +type waitAPI interface { + WaitStackComplete(ctx context.Context, name string, fn func() error) error + DescribeStackEvents(ctx context.Context, stack string) ([]*cloudformation.StackEvent, error) +} diff --git a/ecs/pkg/console/progress.go b/ecs/pkg/console/progress.go index 8ada4df8..157ee813 100644 --- a/ecs/pkg/console/progress.go +++ b/ecs/pkg/console/progress.go @@ -21,7 +21,11 @@ type progress struct { resources []*resource } -func NewProgressWriter() *progress { +type ProgressWriter interface { + ResourceEvent(name string, status string, details string) +} + +func NewProgressWriter() ProgressWriter { return &progress{ console: ansiConsole{os.Stdout}, }