Simplifying progress code (#1253)
This commit is contained in:
parent
fe3d854bc5
commit
7807edc166
|
@ -86,7 +86,8 @@ type ProgressDisplay struct {
|
|||
// a status message to help indicate that things are still working.
|
||||
currentTick int
|
||||
|
||||
rows []Row
|
||||
headerRow Row
|
||||
resourceRows []ResourceRow
|
||||
|
||||
// A mapping from each resource URN we are told about to its current status.
|
||||
eventUrnToResourceRow map[resource.URN]ResourceRow
|
||||
|
@ -238,20 +239,30 @@ func DisplayProgressEvents(
|
|||
|
||||
// Gets the padding necessary to prepend to a message in order to keep it aligned in the
|
||||
// terminal.
|
||||
func (display *ProgressDisplay) getMessagePadding(uncolorizedColumns []string, columnIndex int) string {
|
||||
func (display *ProgressDisplay) getMessagePadding(
|
||||
id string, maxIDLength int, uncolorizedColumns []string, columnIndex int) string {
|
||||
|
||||
extraWhitespace := 1
|
||||
|
||||
// In the terminal we try to align the status messages for each resource.
|
||||
// do not bother with this in the non-terminal case.
|
||||
if display.isTerminal {
|
||||
column := uncolorizedColumns[columnIndex]
|
||||
maxIDLength := display.maxColumnLengths[columnIndex]
|
||||
extraWhitespace = maxIDLength - len(column)
|
||||
var column string
|
||||
var maxLength int
|
||||
if columnIndex == -1 {
|
||||
column = id
|
||||
maxLength = maxIDLength
|
||||
} else {
|
||||
column = uncolorizedColumns[columnIndex]
|
||||
maxLength = display.maxColumnLengths[columnIndex]
|
||||
}
|
||||
|
||||
extraWhitespace = maxLength - len(column)
|
||||
contract.Assertf(extraWhitespace >= 0, "Neg whitespace. %v %s", maxIDLength, column)
|
||||
|
||||
if columnIndex > 0 {
|
||||
// Place two spaces between all columns (except after the first column). The first
|
||||
// column already has a ": " so it doesn't need the extra space.
|
||||
// Place two spaces between all columns (except after the first column). The first
|
||||
// column already has a ": " so it doesn't need the extra space.
|
||||
if columnIndex >= 0 {
|
||||
extraWhitespace += 2
|
||||
}
|
||||
}
|
||||
|
@ -264,12 +275,12 @@ func (display *ProgressDisplay) getMessagePadding(uncolorizedColumns []string, c
|
|||
// suffix. Importantly, if there isn't enough room to display all of that on the terminal, then
|
||||
// the msg will be truncated to try to make it fit.
|
||||
func (display *ProgressDisplay) getPaddedMessage(
|
||||
colorizedColumns, uncolorizedColumns []string) string {
|
||||
id string, maxIDLength int, colorizedColumns, uncolorizedColumns []string) string {
|
||||
|
||||
colorizedMessage := ""
|
||||
|
||||
for i := 1; i < len(colorizedColumns); i++ {
|
||||
padding := display.getMessagePadding(uncolorizedColumns, i-1)
|
||||
for i := 0; i < len(colorizedColumns); i++ {
|
||||
padding := display.getMessagePadding(id, maxIDLength, uncolorizedColumns, i-1)
|
||||
colorizedMessage += padding + colorizedColumns[i]
|
||||
}
|
||||
|
||||
|
@ -278,7 +289,6 @@ func (display *ProgressDisplay) getPaddedMessage(
|
|||
// msgWithColors having the color code information embedded with it. So we need to get
|
||||
// the right substring of it, assuming that embedded colors are just markup and do not
|
||||
// actually contribute to the length
|
||||
id := uncolorizedColumns[0]
|
||||
maxMsgLength := display.terminalWidth - len(id) - len(": ") - 1
|
||||
if maxMsgLength < 0 {
|
||||
maxMsgLength = 0
|
||||
|
@ -310,23 +320,25 @@ func (display *ProgressDisplay) uncolorizeColumns(columns []string) []string {
|
|||
return uncolorizedColumns
|
||||
}
|
||||
|
||||
func (display *ProgressDisplay) refreshSingleRow(row Row) {
|
||||
func (display *ProgressDisplay) refreshSingleRow(id string, maxIDLength int, row Row) {
|
||||
colorizedColumns := row.ColorizedColumns()
|
||||
colorizedColumns[display.suffixColumn] += row.ColorizedSuffix()
|
||||
|
||||
uncolorizedColumns := display.uncolorizeColumns(colorizedColumns)
|
||||
|
||||
msg := display.getPaddedMessage(colorizedColumns, uncolorizedColumns)
|
||||
msg := display.getPaddedMessage(id, maxIDLength, colorizedColumns, uncolorizedColumns)
|
||||
|
||||
display.colorizeAndWriteProgress(makeActionProgress(
|
||||
uncolorizedColumns[0], msg, true /*showID*/))
|
||||
if display.isTerminal {
|
||||
display.colorizeAndWriteProgress(makeActionProgress(
|
||||
id, msg, true /*showID*/))
|
||||
} else {
|
||||
display.writeSimpleMessage(msg)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure our stored dimension info is up to date. Returns 'true' if the stored dimension info is
|
||||
// updated.
|
||||
func (display *ProgressDisplay) updateDimensions() bool {
|
||||
updated := false
|
||||
|
||||
func (display *ProgressDisplay) updateDimensions(rows []Row) {
|
||||
// don't do any refreshing if we're not in a terminal
|
||||
if display.isTerminal {
|
||||
currentTerminalWidth, _, err := terminal.GetSize(int(os.Stdout.Fd()))
|
||||
|
@ -335,10 +347,9 @@ func (display *ProgressDisplay) updateDimensions() bool {
|
|||
if currentTerminalWidth != display.terminalWidth {
|
||||
// terminal width changed. Refresh everything
|
||||
display.terminalWidth = currentTerminalWidth
|
||||
updated = true
|
||||
}
|
||||
|
||||
for _, row := range display.rows {
|
||||
for _, row := range rows {
|
||||
colorizedColumns := row.ColorizedColumns()
|
||||
uncolorizedColumns := display.uncolorizeColumns(colorizedColumns)
|
||||
|
||||
|
@ -354,25 +365,47 @@ func (display *ProgressDisplay) updateDimensions() bool {
|
|||
|
||||
if columnLength > display.maxColumnLengths[i] {
|
||||
display.maxColumnLengths[i] = columnLength
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updated
|
||||
func (display *ProgressDisplay) allRows() []Row {
|
||||
result := []Row{}
|
||||
if display.headerRow != nil {
|
||||
result = append(result, display.headerRow)
|
||||
}
|
||||
|
||||
for _, row := range display.resourceRows {
|
||||
result = append(result, row)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (display *ProgressDisplay) refreshAllRowsIfInTerminal() {
|
||||
if display.isTerminal {
|
||||
if display.isTerminal && display.headerRow != nil {
|
||||
// make sure our stored dimension info is up to date
|
||||
display.updateDimensions()
|
||||
|
||||
for _, row := range display.rows {
|
||||
display.refreshSingleRow(row)
|
||||
rows := display.allRows()
|
||||
display.updateDimensions(rows)
|
||||
|
||||
// tree := display.generateTree()
|
||||
|
||||
maxIDLength := len(fmt.Sprintf("%v", len(rows)-1))
|
||||
for i, row := range rows {
|
||||
var id string
|
||||
if i == 0 {
|
||||
id = "#"
|
||||
} else {
|
||||
id = fmt.Sprintf("%v", i)
|
||||
}
|
||||
|
||||
display.refreshSingleRow(id, maxIDLength, row)
|
||||
}
|
||||
|
||||
systemID := len(display.rows)
|
||||
systemID := len(rows)
|
||||
|
||||
printedHeader := false
|
||||
for _, payload := range display.systemEventPayloads {
|
||||
|
@ -421,7 +454,7 @@ func (display *ProgressDisplay) processEndSteps() {
|
|||
v.SetDone()
|
||||
|
||||
if !display.isTerminal {
|
||||
display.refreshSingleRow(v)
|
||||
display.refreshSingleRow("", 0, v)
|
||||
}
|
||||
} else {
|
||||
// Explicitly transition the status so that we clear out any cached data for it.
|
||||
|
@ -461,7 +494,7 @@ func (display *ProgressDisplay) processEndSteps() {
|
|||
wroteResourceHeader = true
|
||||
columns := row.ColorizedColumns()
|
||||
display.writeSimpleMessage(" " +
|
||||
columns[idColumn] + ": " +
|
||||
// columns[idColumn] + ": " +
|
||||
columns[typeColumn] + ": " +
|
||||
columns[nameColumn])
|
||||
}
|
||||
|
@ -561,13 +594,10 @@ func (display *ProgressDisplay) processNormalEvent(event engine.Event) {
|
|||
|
||||
row, has := display.eventUrnToResourceRow[eventUrn]
|
||||
if !has {
|
||||
id := fmt.Sprintf("%v", len(display.eventUrnToResourceRow)+1)
|
||||
|
||||
// first time we're hearing about this resource. Create an initial nearly-empty
|
||||
// status for it, assigning it a nice short ID.
|
||||
row = &resourceRowData{
|
||||
display: display,
|
||||
id: id,
|
||||
tick: display.currentTick,
|
||||
diagInfo: &DiagInfo{},
|
||||
step: engine.StepEventMetadata{Op: deploy.OpSame},
|
||||
|
@ -575,7 +605,7 @@ func (display *ProgressDisplay) processNormalEvent(event engine.Event) {
|
|||
|
||||
display.eventUrnToResourceRow[eventUrn] = row
|
||||
display.ensureHeaderRow()
|
||||
display.rows = append(display.rows, row)
|
||||
display.resourceRows = append(display.resourceRows, row)
|
||||
}
|
||||
|
||||
if event.Type == engine.ResourcePreEvent {
|
||||
|
@ -605,7 +635,7 @@ func (display *ProgressDisplay) processNormalEvent(event engine.Event) {
|
|||
display.refreshAllRowsIfInTerminal()
|
||||
} else {
|
||||
// otherwise, just print out this single row.
|
||||
display.refreshSingleRow(row)
|
||||
display.refreshSingleRow("", 0, row)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,9 +656,9 @@ func (display *ProgressDisplay) handleSystemEvent(payload engine.StdoutEventPayl
|
|||
}
|
||||
|
||||
func (display *ProgressDisplay) ensureHeaderRow() {
|
||||
if len(display.rows) == 0 {
|
||||
if display.headerRow == nil {
|
||||
// about to make our first status message. make sure we present the header line first.
|
||||
display.rows = append(display.rows, &headerRowData{display: display})
|
||||
display.headerRow = &headerRowData{display: display}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/pulumi/pulumi/pkg/engine"
|
||||
"github.com/pulumi/pulumi/pkg/resource"
|
||||
"github.com/pulumi/pulumi/pkg/resource/deploy"
|
||||
"github.com/pulumi/pulumi/pkg/util/contract"
|
||||
)
|
||||
|
||||
type Row interface {
|
||||
|
@ -61,7 +60,7 @@ func (data *headerRowData) ColorizedColumns() []string {
|
|||
} else {
|
||||
statusColumn = header("Status")
|
||||
}
|
||||
data.columns = []string{"#", header("Resource Type"), header("Name"), statusColumn, header("Extra Info")}
|
||||
data.columns = []string{header("Resource Type"), header("Name"), statusColumn, header("Extra Info")}
|
||||
}
|
||||
|
||||
return data.columns
|
||||
|
@ -75,10 +74,6 @@ func (data *headerRowData) ColorizedSuffix() string {
|
|||
type resourceRowData struct {
|
||||
display *ProgressDisplay
|
||||
|
||||
// The simple short ID we have generated for the resource to present it to the user.
|
||||
// Usually similar to the form: aws.Function("name")
|
||||
id string
|
||||
|
||||
// The change that the engine wants apply to that resource.
|
||||
step engine.StepEventMetadata
|
||||
|
||||
|
@ -151,11 +146,10 @@ func (data *resourceRowData) RecordDiagEvent(event engine.Event) {
|
|||
type column int
|
||||
|
||||
const (
|
||||
idColumn column = 0
|
||||
typeColumn column = 1
|
||||
nameColumn column = 2
|
||||
statusColumn column = 3
|
||||
infoColumn column = 4
|
||||
typeColumn column = 0
|
||||
nameColumn column = 1
|
||||
statusColumn column = 2
|
||||
infoColumn column = 3
|
||||
)
|
||||
|
||||
func (data *resourceRowData) ColorizedSuffix() string {
|
||||
|
@ -171,9 +165,6 @@ func (data *resourceRowData) ColorizedSuffix() string {
|
|||
|
||||
func (data *resourceRowData) ColorizedColumns() []string {
|
||||
step := data.step
|
||||
if step.Op == "" {
|
||||
contract.Failf("Finishing a resource we never heard about: '%s'", data.id)
|
||||
}
|
||||
|
||||
var name string
|
||||
var typ string
|
||||
|
@ -185,8 +176,7 @@ func (data *resourceRowData) ColorizedColumns() []string {
|
|||
typ = simplifyTypeName(data.step.URN.Type())
|
||||
}
|
||||
|
||||
columns := make([]string, 5)
|
||||
columns[idColumn] = data.id
|
||||
columns := make([]string, 4)
|
||||
columns[typeColumn] = typ
|
||||
columns[nameColumn] = name
|
||||
|
||||
|
|
Loading…
Reference in a new issue