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