wait.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package backend
  2. import (
  3. "context"
  4. "fmt"
  5. "sort"
  6. "strings"
  7. "time"
  8. "github.com/aws/aws-sdk-go/aws"
  9. "github.com/docker/ecs-plugin/pkg/console"
  10. )
  11. func (b *Backend) WaitStackCompletion(ctx context.Context, name string, operation int, w console.ProgressWriter) error {
  12. knownEvents := map[string]struct{}{}
  13. // Get the unique Stack ID so we can collect events without getting some from previous deployments with same name
  14. stackID, err := b.api.GetStackID(ctx, name)
  15. if err != nil {
  16. return err
  17. }
  18. ticker := time.NewTicker(1 * time.Second)
  19. done := make(chan bool)
  20. go func() {
  21. b.api.WaitStackComplete(ctx, stackID, operation) //nolint:errcheck
  22. ticker.Stop()
  23. done <- true
  24. }()
  25. var completed bool
  26. var stackErr error
  27. for !completed {
  28. select {
  29. case <-done:
  30. completed = true
  31. case <-ticker.C:
  32. }
  33. events, err := b.api.DescribeStackEvents(ctx, stackID)
  34. if err != nil {
  35. return err
  36. }
  37. sort.Slice(events, func(i, j int) bool {
  38. return events[i].Timestamp.Before(*events[j].Timestamp)
  39. })
  40. for _, event := range events {
  41. if _, ok := knownEvents[*event.EventId]; ok {
  42. continue
  43. }
  44. knownEvents[*event.EventId] = struct{}{}
  45. resource := aws.StringValue(event.LogicalResourceId)
  46. reason := aws.StringValue(event.ResourceStatusReason)
  47. status := aws.StringValue(event.ResourceStatus)
  48. w.ResourceEvent(resource, status, reason)
  49. if stackErr == nil && strings.HasSuffix(status, "_FAILED") {
  50. stackErr = fmt.Errorf(reason)
  51. }
  52. }
  53. }
  54. return stackErr
  55. }