Skip to content
This repository has been archived by the owner on Oct 21, 2024. It is now read-only.

Commit

Permalink
add detailed failed task logging
Browse files Browse the repository at this point in the history
  • Loading branch information
chilledornaments committed Nov 4, 2021
1 parent ad4419d commit 6e9995e
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 0 deletions.
29 changes: 29 additions & 0 deletions pkg/deploy/mock_ecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,32 @@ func (c MockECSClient) UpdateService(ctx context.Context, params *ecs.UpdateServ

return &out, nil
}

func (c MockECSClient) ListTasks(ctx context.Context, params *ecs.ListTasksInput, optFns ...func(*ecs.Options)) (*ecs.ListTasksOutput, error) {
output := &ecs.ListTasksOutput{
NextToken: aws.String("FOO"),
TaskArns: []string{
"arn-1",
"arn-2",
},
}

return output, nil
}

func (c MockECSClient) DescribeTasks(ctx context.Context, params *ecs.DescribeTasksInput, optFns ...func(*ecs.Options)) (*ecs.DescribeTasksOutput, error) {
output := &ecs.DescribeTasksOutput{
Tasks: []ecstypes.Task{
{
StoppedReason: aws.String("Error pulling image"),
TaskArn: aws.String("arn-1"),
},
{
StoppedReason: aws.String("Essential container in task exited"),
TaskArn: aws.String("arn-2"),
},
},
}

return output, nil
}
39 changes: 39 additions & 0 deletions pkg/deploy/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ func CheckDeploymentStatus(ctx context.Context, c types.ECSClient, service strin

if out.Services[0].Deployments[0].FailedTasks > 0 {
log.Printf("Deployment %d has failed tasks\n", out.Services[0].Deployments[0].FailedTasks)
// This is helpful for debugging
// ECS will clear all stopped tasks after a deployment finishes
showFailedTasks(c, service, cluster, deploymentID)
return true, errors.New("deployment failed")
}

Expand All @@ -101,6 +104,42 @@ func CheckDeploymentStatus(ctx context.Context, c types.ECSClient, service strin
// The only other status is FAILED
return true, errors.New("deployment failed")
}
}

func showFailedTasks(c types.ECSClient, service string, cluster string, deploymentID string) {
input := ecs.ListTasksInput{
Cluster: &cluster,
DesiredStatus: "STOPPED",
StartedBy: &deploymentID,
ServiceName: &service,
}

resp, err := c.ListTasks(context.TODO(), &input)

if err != nil {
log.Printf("Error listing tasks: %s", err.Error())
return
}

tasks, err := c.DescribeTasks(
context.TODO(),
&ecs.DescribeTasksInput{
Tasks: resp.TaskArns,
Cluster: &cluster,
},
)

if err != nil {
log.Printf("Error describing tasks: %s", err.Error())
return
}

for _, task := range tasks.Tasks {
stoppedReason := task.StoppedReason
taskARN := task.TaskArn

log.Printf("Task '%s' failure reason: %s", *taskARN, *stoppedReason)
}

}

Expand Down
28 changes: 28 additions & 0 deletions pkg/deploy/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,31 @@ func TestGetServiceDesiredCount(t *testing.T) {
})
}
}

func Test_showFailedTasks(t *testing.T) {
type args struct {
c types.ECSClient
service string
cluster string
deploymentID string
}
tests := []struct {
name string
args args
}{
{
name: "test-failed-task-logging",
args: args{
c: MockECSClient{WantError: false, TestingT: t},
service: "test-service",
cluster: "test-cluster",
deploymentID: "ecs/deploy-foo",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
showFailedTasks(tt.args.c, tt.args.service, tt.args.cluster, tt.args.deploymentID)
})
}
}
2 changes: 2 additions & 0 deletions pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ type ECSClient interface {
RegisterTaskDefinition(ctx context.Context, params *ecs.RegisterTaskDefinitionInput, optFns ...func(*ecs.Options)) (*ecs.RegisterTaskDefinitionOutput, error)
DescribeServices(ctx context.Context, params *ecs.DescribeServicesInput, optFns ...func(*ecs.Options)) (*ecs.DescribeServicesOutput, error)
UpdateService(ctx context.Context, params *ecs.UpdateServiceInput, optFns ...func(*ecs.Options)) (*ecs.UpdateServiceOutput, error)
ListTasks(ctx context.Context, params *ecs.ListTasksInput, optFns ...func(*ecs.Options)) (*ecs.ListTasksOutput, error)
DescribeTasks(ctx context.Context, params *ecs.DescribeTasksInput, optFns ...func(*ecs.Options)) (*ecs.DescribeTasksOutput, error)
}

type AppAutoscalingClient interface {
Expand Down

0 comments on commit 6e9995e

Please sign in to comment.