Capture first failure to report root error to user on command completion

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof 2020-04-30 16:14:36 +02:00
parent a8e963a304
commit 99b4ed0bfd
No known key found for this signature in database
GPG Key ID: 9858809D6F8F6E7E
2 changed files with 22 additions and 13 deletions

View File

@ -19,8 +19,10 @@ func TestDownDontDeleteCluster(t *testing.T) {
} }
ctx := context.TODO() ctx := context.TODO()
recorder := m.EXPECT() recorder := m.EXPECT()
recorder.DeleteStack(ctx, "test_project").Return(nil).Times(1) recorder.DeleteStack(ctx, "test_project").Return(nil)
recorder.WaitStackComplete(ctx, "test_project", gomock.Any()).Return(nil).Times(1) recorder.GetStackID(ctx, "test_project").Return("stack-123", nil)
recorder.WaitStackComplete(ctx, "stack-123", StackDelete).Return(nil)
recorder.DescribeStackEvents(ctx, "stack-123").Return(nil, nil)
c.ComposeDown(ctx, "test_project", false) c.ComposeDown(ctx, "test_project", false)
} }
@ -37,9 +39,11 @@ func TestDownDeleteCluster(t *testing.T) {
ctx := context.TODO() ctx := context.TODO()
recorder := m.EXPECT() recorder := m.EXPECT()
recorder.DeleteStack(ctx, "test_project").Return(nil).Times(1) recorder.DeleteStack(ctx, "test_project").Return(nil)
recorder.WaitStackComplete(ctx, "test_project", gomock.Any()).Return(nil).Times(1) recorder.GetStackID(ctx, "test_project").Return("stack-123", nil)
recorder.DeleteCluster(ctx, "test_cluster").Return(nil).Times(1) recorder.WaitStackComplete(ctx, "stack-123", StackDelete).Return(nil)
recorder.DescribeStackEvents(ctx, "stack-123").Return(nil, nil)
recorder.DeleteCluster(ctx, "test_cluster").Return(nil)
c.ComposeDown(ctx, "test_project", true) c.ComposeDown(ctx, "test_project", true)
} }

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"sort" "sort"
"strings"
"time" "time"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
@ -22,21 +23,20 @@ func (c *client) WaitStackCompletion(ctx context.Context, name string, operation
} }
ticker := time.NewTicker(1 * time.Second) ticker := time.NewTicker(1 * time.Second)
done := make(chan error) done := make(chan bool)
go func() { go func() {
err := c.api.WaitStackComplete(ctx, name, operation) c.api.WaitStackComplete(ctx, stackID, operation) //nolint:errcheck
ticker.Stop() ticker.Stop()
done <- err done <- true
}() }()
var completed bool var completed bool
var waitErr error var stackErr error
for !completed { for !completed {
select { select {
case err := <-done: case <-done:
completed = true completed = true
waitErr = err
case <-ticker.C: case <-ticker.C:
} }
events, err := c.api.DescribeStackEvents(ctx, stackID) events, err := c.api.DescribeStackEvents(ctx, stackID)
@ -55,10 +55,15 @@ func (c *client) WaitStackCompletion(ctx context.Context, name string, operation
knownEvents[*event.EventId] = struct{}{} knownEvents[*event.EventId] = struct{}{}
resource := fmt.Sprintf("%s %q", aws.StringValue(event.ResourceType), aws.StringValue(event.LogicalResourceId)) resource := fmt.Sprintf("%s %q", aws.StringValue(event.ResourceType), aws.StringValue(event.LogicalResourceId))
w.ResourceEvent(resource, aws.StringValue(event.ResourceStatus), aws.StringValue(event.ResourceStatusReason)) reason := aws.StringValue(event.ResourceStatusReason)
status := aws.StringValue(event.ResourceStatus)
w.ResourceEvent(resource, status, reason)
if stackErr == nil && strings.HasSuffix(status, "_FAILED") {
stackErr = fmt.Errorf(reason)
} }
} }
return waitErr }
return stackErr
} }
type waitAPI interface { type waitAPI interface {