wait.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package amazon
  2. import (
  3. "context"
  4. "fmt"
  5. "sort"
  6. "time"
  7. "github.com/aws/aws-sdk-go/aws"
  8. "github.com/aws/aws-sdk-go/service/cloudformation"
  9. "github.com/docker/ecs-plugin/pkg/console"
  10. )
  11. func (c *client) WaitStackCompletion(ctx context.Context, name string, operation int) error {
  12. w := console.NewProgressWriter()
  13. knownEvents := map[string]struct{}{}
  14. // Get the unique Stack ID so we can collect events without getting some from previous deployments with same name
  15. stackID, err := c.api.GetStackID(ctx, name)
  16. if err != nil {
  17. return err
  18. }
  19. ticker := time.NewTicker(1 * time.Second)
  20. done := make(chan error)
  21. go func() {
  22. err := c.api.WaitStackComplete(ctx, name, operation)
  23. ticker.Stop()
  24. done <- err
  25. }()
  26. var completed bool
  27. var waitErr error
  28. for !completed {
  29. select {
  30. case err := <-done:
  31. completed = true
  32. waitErr = err
  33. case <-ticker.C:
  34. }
  35. events, err := c.api.DescribeStackEvents(ctx, stackID)
  36. if err != nil {
  37. return err
  38. }
  39. sort.Slice(events, func(i, j int) bool {
  40. return events[i].Timestamp.Before(*events[j].Timestamp)
  41. })
  42. for _, event := range events {
  43. if _, ok := knownEvents[*event.EventId]; ok {
  44. continue
  45. }
  46. knownEvents[*event.EventId] = struct{}{}
  47. resource := fmt.Sprintf("%s %q", aws.StringValue(event.ResourceType), aws.StringValue(event.LogicalResourceId))
  48. w.ResourceEvent(resource, aws.StringValue(event.ResourceStatus), aws.StringValue(event.ResourceStatusReason))
  49. }
  50. }
  51. return waitErr
  52. }
  53. type waitAPI interface {
  54. GetStackID(ctx context.Context, name string) (string, error)
  55. WaitStackComplete(ctx context.Context, name string, operation int) error
  56. DescribeStackEvents(ctx context.Context, stackID string) ([]*cloudformation.StackEvent, error)
  57. }
  58. const (
  59. StackCreate = iota
  60. StackDelete
  61. )