func()

in internal/pkg/term/progress/ecs.go [203:291]


func (c *rollingUpdateComponent) renderStoppedTasks(out io.Writer) (numLines int, err error) {
	if len(c.stoppedTasks) == 0 {
		return 0, nil
	}
	header := []string{"TaskId", "CurrentStatus", "DesiredStatus"}
	var rows [][]string
	title := fmt.Sprintf("Latest %d %s stopped reason", len(c.stoppedTasks), english.PluralWord(len(c.stoppedTasks), "task", "tasks"))
	title = fmt.Sprintf("%s%s", color.DullRed.Sprintf("✘ "), color.Faint.Sprintf(title))
	childComponents := []Renderer{
		&singleLineComponent{}, // Add an empty line before rendering task stopped events.
		&singleLineComponent{
			Text:    title,
			Padding: c.padding,
		},
	}
	type stoppedTasksInfo struct {
		ids              []string
		latestStoppingAt time.Time
	}
	stopReason2Tasks := make(map[string]*stoppedTasksInfo, len(c.stoppedTasks))
	for _, st := range c.stoppedTasks {
		id, err := ecs.TaskID(aws.StringValue(st.TaskArn))
		if err != nil {
			return 0, err
		}
		tasks, ok := stopReason2Tasks[aws.StringValue(st.StoppedReason)]
		if ok {
			tasks.ids = append(tasks.ids, ecs.ShortTaskID(id))
			tasks.latestStoppingAt = aws.TimeValue(st.StoppingAt)
			stopReason2Tasks[aws.StringValue(st.StoppedReason)] = tasks
		} else {
			stopReason2Tasks[aws.StringValue(st.StoppedReason)] = &stoppedTasksInfo{
				ids:              []string{ecs.ShortTaskID(id)},
				latestStoppingAt: aws.TimeValue(st.StoppingAt),
			}
		}
		rows = append(rows, []string{
			ecs.ShortTaskID(id),
			aws.StringValue(st.LastStatus),
			aws.StringValue(st.DesiredStatus),
		})
	}
	var sortedReasons []string
	for reason := range stopReason2Tasks {
		sortedReasons = append(sortedReasons, reason)
	}
	sort.SliceStable(sortedReasons, func(i, j int) bool {
		return stopReason2Tasks[sortedReasons[i]].latestStoppingAt.After(stopReason2Tasks[sortedReasons[j]].latestStoppingAt)
	})
	for _, reason := range sortedReasons {
		for i, truncatedReason := range splitByLength(fmt.Sprintf("[%s]: %s", strings.Join(stopReason2Tasks[reason].ids, ","), reason), maxCellLength) {
			pretty := fmt.Sprintf("  %s", truncatedReason)
			if i == 0 {
				pretty = fmt.Sprintf("- %s", truncatedReason)
			}
			childComponents = append(childComponents, &singleLineComponent{
				Text:    pretty,
				Padding: c.padding + nestedComponentPadding,
			})
		}
	}
	table := newTableComponent(color.Faint.Sprintf("Latest %d stopped %s", len(c.stoppedTasks), english.PluralWord(len(c.stoppedTasks), "task", "tasks")), header, rows)
	table.Padding = c.padding
	childComponents = append(childComponents,
		&singleLineComponent{},
		&singleLineComponent{
			Text:    color.Faint.Sprintf("Troubleshoot task stopped reason"),
			Padding: c.padding,
		},
		&singleLineComponent{
			Text: fmt.Sprintf("1. You can run %s to see the logs of the last stopped task.",
				color.HighlightCode("copilot svc logs --previous")),
			Padding: c.padding + nestedComponentPadding,
		},
		&singleLineComponent{
			Text: fmt.Sprintf("2. You can visit this article: %s.",
				color.Emphasize("https://repost.aws/knowledge-center/ecs-task-stopped")),
			Padding: c.padding + nestedComponentPadding,
		})
	treeComponent := treeComponent{
		Root:     table,
		Children: childComponents,
	}
	nl, err := treeComponent.Render(out)
	if err != nil {
		return 0, fmt.Errorf("render deployments table: %w", err)
	}
	return nl, err
}