Clarify refresh text

The wording for refresh doesn't accurately convey that the operations
aren't actually mutating your resources, but instead are simply changing
your checkpoint state. This change (hopefully) helps in two ways:

First, put text just before the prompt:

Do you want to perform this refresh?
No resources will be modified as part of this refresh; just your stack's state will be.

Second, alter the summary ever-so-slightly, from:

info: 2 changes performed:
    ~ 2 resources updated
      3 resources unchanged

to:

info: 2 changes refreshed:
    ~ 2 resources updated
      3 resources unchanged

This reads just slightly better, and removes any sense of panic I might
have otherwise had that my refresh just did something wrong.

As I was in here, since I had to pass UpdateKind information to new
places, I cleaned up the situation where we had three mostly-similar
enums (but which actually diverged) and several areas where we were
using untyped strings for this same information. Now there's just one.

This fixes pulumi/pulumi#1551.
This commit is contained in:
joeduffy 2018-08-29 17:06:48 -07:00
parent 6883d08796
commit cd5707f483
10 changed files with 93 additions and 97 deletions

View file

@ -23,14 +23,16 @@ import "encoding/json"
type UpdateKind string
const (
// DeployUpdate is the prototypical Pulumi program update.
DeployUpdate UpdateKind = "update"
// UpdateUpdate is the prototypical Pulumi program update.
UpdateUpdate UpdateKind = "update"
// PreviewUpdate is a preview of an update, without impacting resources.
PreviewUpdate UpdateKind = "preview"
// RefreshUpdate is an update that came from a refresh operation.
RefreshUpdate UpdateKind = "refresh"
// DestroyUpdate is an update which removes all resources.
DestroyUpdate UpdateKind = "destroy"
// ImportUpdate is an update that entails importing a raw checkpoint file.
ImportUpdate UpdateKind = "import"
)
// UpdateResult is an enum for the result of the update.

View file

@ -20,6 +20,7 @@ import (
"fmt"
"github.com/pkg/errors"
"github.com/pulumi/pulumi/pkg/apitype"
"github.com/pulumi/pulumi/pkg/engine"
"github.com/pulumi/pulumi/pkg/operations"

View file

@ -564,11 +564,11 @@ var (
previewText string
text string
}{
string(client.UpdateKindPreview): {"update of", "Previewing"},
string(client.UpdateKindUpdate): {"update of", "Updating"},
string(client.UpdateKindRefresh): {"refresh of", "Refreshing"},
string(client.UpdateKindDestroy): {"destroy of", "Destroying"},
string(client.UpdateKindImport): {"import to", "Importing into"},
string(apitype.PreviewUpdate): {"update of", "Previewing"},
string(apitype.UpdateUpdate): {"update of", "Updating"},
string(apitype.RefreshUpdate): {"refresh of", "Refreshing"},
string(apitype.DestroyUpdate): {"destroy of", "Destroying"},
string(apitype.ImportUpdate): {"import to", "Importing into"},
}
)
@ -603,14 +603,14 @@ func getStack(ctx context.Context, b *cloudBackend, stackRef backend.StackRefere
return stack, nil
}
func createDiff(events []engine.Event, displayOpts backend.DisplayOptions) string {
func createDiff(updateKind apitype.UpdateKind, events []engine.Event, displayOpts backend.DisplayOptions) string {
buff := &bytes.Buffer{}
seen := make(map[resource.URN]engine.StepEventMetadata)
displayOpts.SummaryDiff = true
for _, e := range events {
msg := local.RenderDiffEvent(e, seen, displayOpts)
msg := local.RenderDiffEvent(updateKind, e, seen, displayOpts)
if msg != "" {
if e.Type == engine.SummaryEvent {
msg = "\n" + msg
@ -625,7 +625,7 @@ func createDiff(events []engine.Event, displayOpts backend.DisplayOptions) strin
}
func (b *cloudBackend) PreviewThenPrompt(
ctx context.Context, updateKind client.UpdateKind, stack backend.Stack, pkg *workspace.Project, root string,
ctx context.Context, updateKind apitype.UpdateKind, stack backend.Stack, pkg *workspace.Project, root string,
m backend.UpdateMetadata, opts backend.UpdateOptions,
scopes backend.CancellationScopeSource) (engine.ResourceChanges, error) {
@ -662,7 +662,7 @@ func (b *cloudBackend) PreviewThenPrompt(
}
// If there are no changes, or we're auto-approving or just previewing, we can skip the confirmation prompt.
if opts.AutoApprove || updateKind == client.UpdateKindPreview {
if opts.AutoApprove || updateKind == apitype.PreviewUpdate {
return changes, nil
}
@ -671,7 +671,7 @@ func (b *cloudBackend) PreviewThenPrompt(
}
// confirmBeforeUpdating asks the user whether to proceed. A nil error means yes.
func confirmBeforeUpdating(updateKind client.UpdateKind, stack backend.Stack,
func confirmBeforeUpdating(updateKind apitype.UpdateKind, stack backend.Stack,
events []engine.Event, opts backend.UpdateOptions) error {
for {
var response string
@ -692,10 +692,17 @@ func confirmBeforeUpdating(updateKind client.UpdateKind, stack backend.Stack,
previewWarning = colors.SpecWarning + " without a preview" + colors.BrightWhite
}
// Create a prompt. If this is a refresh, we'll add some extra text so it's clear we aren't updating resources.
prompt := "\b" + opts.Display.Color.Colorize(
colors.BrightWhite+fmt.Sprintf("Do you want to perform this %s%s?",
updateKind, previewWarning)+colors.Reset)
if updateKind == apitype.RefreshUpdate {
prompt += "\nNo resources will be modified as part of this refresh; just your stack's state will be."
}
// Now prompt the user for a yes, no, or details, and then proceed accordingly.
if err := survey.AskOne(&survey.Select{
Message: "\b" + opts.Display.Color.Colorize(
colors.BrightWhite+fmt.Sprintf("Do you want to perform this %s%s?",
updateKind, previewWarning)+colors.Reset),
Message: prompt,
Options: choices,
Default: string(no),
}, &response, nil); err != nil {
@ -711,7 +718,7 @@ func confirmBeforeUpdating(updateKind client.UpdateKind, stack backend.Stack,
}
if response == string(details) {
diff := createDiff(events, opts.Display)
diff := createDiff(updateKind, events, opts.Display)
_, err := os.Stdout.WriteString(diff + "\n\n")
contract.IgnoreError(err)
continue
@ -720,7 +727,7 @@ func confirmBeforeUpdating(updateKind client.UpdateKind, stack backend.Stack,
}
func (b *cloudBackend) PreviewThenPromptThenExecute(
ctx context.Context, updateKind client.UpdateKind, stackRef backend.StackReference, pkg *workspace.Project,
ctx context.Context, updateKind apitype.UpdateKind, stackRef backend.StackReference, pkg *workspace.Project,
root string, m backend.UpdateMetadata, opts backend.UpdateOptions,
scopes backend.CancellationScopeSource) (engine.ResourceChanges, error) {
@ -732,7 +739,7 @@ func (b *cloudBackend) PreviewThenPromptThenExecute(
// Preview the operation to the user and ask them if they want to proceed.
changes, err := b.PreviewThenPrompt(ctx, updateKind, stack, pkg, root, m, opts, scopes)
if err != nil || updateKind == client.UpdateKindPreview {
if err != nil || updateKind == apitype.PreviewUpdate {
return changes, err
}
@ -757,30 +764,30 @@ func (b *cloudBackend) Preview(ctx context.Context, stackRef backend.StackRefere
// We can skip PreviewtTenPromptThenExecute, and just go straight to Execute.
return b.updateStack(
ctx, client.UpdateKindPreview, stack, pkg, root, m, opts, nil,
ctx, apitype.PreviewUpdate, stack, pkg, root, m, opts, nil,
true /*dryRun*/, persist, scopes)
}
func (b *cloudBackend) Update(ctx context.Context, stackRef backend.StackReference, pkg *workspace.Project,
root string, m backend.UpdateMetadata, opts backend.UpdateOptions,
scopes backend.CancellationScopeSource) (engine.ResourceChanges, error) {
return b.PreviewThenPromptThenExecute(ctx, client.UpdateKindUpdate, stackRef, pkg, root, m, opts, scopes)
return b.PreviewThenPromptThenExecute(ctx, apitype.UpdateUpdate, stackRef, pkg, root, m, opts, scopes)
}
func (b *cloudBackend) Refresh(ctx context.Context, stackRef backend.StackReference, pkg *workspace.Project,
root string, m backend.UpdateMetadata, opts backend.UpdateOptions,
scopes backend.CancellationScopeSource) (engine.ResourceChanges, error) {
return b.PreviewThenPromptThenExecute(ctx, client.UpdateKindRefresh, stackRef, pkg, root, m, opts, scopes)
return b.PreviewThenPromptThenExecute(ctx, apitype.RefreshUpdate, stackRef, pkg, root, m, opts, scopes)
}
func (b *cloudBackend) Destroy(ctx context.Context, stackRef backend.StackReference, pkg *workspace.Project,
root string, m backend.UpdateMetadata, opts backend.UpdateOptions,
scopes backend.CancellationScopeSource) (engine.ResourceChanges, error) {
return b.PreviewThenPromptThenExecute(ctx, client.UpdateKindDestroy, stackRef, pkg, root, m, opts, scopes)
return b.PreviewThenPromptThenExecute(ctx, apitype.DestroyUpdate, stackRef, pkg, root, m, opts, scopes)
}
func (b *cloudBackend) createAndStartUpdate(
ctx context.Context, action client.UpdateKind, stackRef backend.StackReference,
ctx context.Context, action apitype.UpdateKind, stackRef backend.StackReference,
pkg *workspace.Project, root string, m backend.UpdateMetadata,
opts backend.UpdateOptions, dryRun bool) (client.UpdateIdentifier, int, string, error) {
@ -821,7 +828,7 @@ func (b *cloudBackend) createAndStartUpdate(
return client.UpdateIdentifier{}, 0, "", err
}
// Any non-preview update will be considered part of the stack's update history.
if action != client.UpdateKindPreview {
if action != apitype.PreviewUpdate {
logging.V(7).Infof("Stack %s being updated to version %d", stackRef, version)
}
@ -830,7 +837,7 @@ func (b *cloudBackend) createAndStartUpdate(
// updateStack performs a the provided type of update on a stack hosted in the Pulumi Cloud.
func (b *cloudBackend) updateStack(
ctx context.Context, action client.UpdateKind, stack backend.Stack, pkg *workspace.Project,
ctx context.Context, action apitype.UpdateKind, stack backend.Stack, pkg *workspace.Project,
root string, m backend.UpdateMetadata, opts backend.UpdateOptions,
callerEventsOpt chan<- engine.Event, dryRun bool, persist bool,
scopes backend.CancellationScopeSource) (engine.ResourceChanges, error) {
@ -905,7 +912,7 @@ func getUpdateContents(
}
func (b *cloudBackend) runEngineAction(
ctx context.Context, action client.UpdateKind, stackRef backend.StackReference, pkg *workspace.Project,
ctx context.Context, action apitype.UpdateKind, stackRef backend.StackReference, pkg *workspace.Project,
root string, opts backend.UpdateOptions, update client.UpdateIdentifier, token string,
callerEventsOpt chan<- engine.Event, dryRun bool, persist bool,
scopes backend.CancellationScopeSource) (engine.ResourceChanges, error) {
@ -920,7 +927,8 @@ func (b *cloudBackend) runEngineAction(
displayEvents := make(chan engine.Event)
displayDone := make(chan bool)
go u.RecordAndDisplayEvents(getActionLabel(string(action), dryRun), displayEvents, displayDone, opts.Display)
go u.RecordAndDisplayEvents(
getActionLabel(string(action), dryRun), action, displayEvents, displayDone, opts.Display)
engineEvents := make(chan engine.Event)
@ -950,13 +958,13 @@ func (b *cloudBackend) runEngineAction(
}
switch action {
case client.UpdateKindPreview:
case apitype.PreviewUpdate:
changes, err = engine.Update(u, engineCtx, opts.Engine, true)
case client.UpdateKindUpdate:
case apitype.UpdateUpdate:
changes, err = engine.Update(u, engineCtx, opts.Engine, dryRun)
case client.UpdateKindRefresh:
case apitype.RefreshUpdate:
changes, err = engine.Refresh(u, engineCtx, opts.Engine, dryRun)
case client.UpdateKindDestroy:
case apitype.DestroyUpdate:
changes, err = engine.Destroy(u, engineCtx, opts.Engine, dryRun)
default:
contract.Failf("Unrecognized action type: %s", action)
@ -1002,7 +1010,7 @@ func (b *cloudBackend) CancelCurrentUpdate(ctx context.Context, stackRef backend
// NOTE: the update kind is not relevant; the same endpoint will work for updates of all kinds.
updateID := client.UpdateIdentifier{
StackIdentifier: stackID,
UpdateKind: client.UpdateKindUpdate,
UpdateKind: apitype.UpdateUpdate,
UpdateID: stack.ActiveUpdate,
}
return b.client.CancelUpdate(ctx, updateID)
@ -1029,7 +1037,7 @@ func (b *cloudBackend) GetHistory(ctx context.Context, stackRef backend.StackRef
}
beUpdates = append(beUpdates, backend.UpdateInfo{
Kind: backend.UpdateKind(update.Kind),
Kind: update.Kind,
Message: update.Message,
Environment: update.Environment,
Config: cfg,

View file

@ -36,17 +36,6 @@ import (
"github.com/pulumi/pulumi/pkg/version"
)
// UpdateKind is an enum for describing the kinds of updates we support.
type UpdateKind string
const (
UpdateKindUpdate UpdateKind = "update"
UpdateKindPreview UpdateKind = "preview"
UpdateKindRefresh UpdateKind = "refresh"
UpdateKindDestroy UpdateKind = "destroy"
UpdateKindImport UpdateKind = "import"
)
// StackIdentifier is the set of data needed to identify a Pulumi Cloud stack.
type StackIdentifier struct {
Owner string
@ -57,7 +46,7 @@ type StackIdentifier struct {
type UpdateIdentifier struct {
StackIdentifier
UpdateKind UpdateKind
UpdateKind apitype.UpdateKind
UpdateID string
}

View file

@ -90,7 +90,7 @@ func getStackPath(stack StackIdentifier, components ...string) string {
// getUpdatePath returns the API path to for the given stack with the given components joined with path separators
// and appended to the update root.
func getUpdatePath(update UpdateIdentifier, components ...string) string {
components = append([]string{string(update.UpdateKind), update.UpdateID}, components...)
components = append([]string{string(apitype.UpdateUpdate), update.UpdateID}, components...)
return getStackPath(update.StackIdentifier, components...)
}
@ -322,7 +322,7 @@ func (pc *Client) ImportStackDeployment(ctx context.Context, stack StackIdentifi
return UpdateIdentifier{
StackIdentifier: stack,
UpdateKind: UpdateKindUpdate,
UpdateKind: apitype.UpdateUpdate,
UpdateID: resp.UpdateID,
}, nil
}
@ -331,7 +331,7 @@ func (pc *Client) ImportStackDeployment(ctx context.Context, stack StackIdentifi
// requires that the Pulumi program is uploaded, the provided getContents callback will be invoked to fetch the
// contents of the Pulumi program.
func (pc *Client) CreateUpdate(
ctx context.Context, kind UpdateKind, stack StackIdentifier, pkg *workspace.Project, cfg config.Map,
ctx context.Context, kind apitype.UpdateKind, stack StackIdentifier, pkg *workspace.Project, cfg config.Map,
main string, m apitype.UpdateMetadata, opts engine.UpdateOptions, dryRun bool,
getContents func() (io.ReadCloser, int64, error)) (UpdateIdentifier, error) {
@ -373,13 +373,13 @@ func (pc *Client) CreateUpdate(
// Create the initial update object.
var endpoint string
switch kind {
case UpdateKindUpdate:
case apitype.UpdateUpdate:
endpoint = "update"
case UpdateKindPreview:
case apitype.PreviewUpdate:
endpoint = "preview"
case UpdateKindRefresh:
case apitype.RefreshUpdate:
endpoint = "refresh"
case UpdateKindDestroy:
case apitype.DestroyUpdate:
endpoint = "destroy"
default:
contract.Failf("Unknown kind: %s", kind)
@ -392,7 +392,7 @@ func (pc *Client) CreateUpdate(
}
// Now upload the program if necessary.
if kind != UpdateKindDestroy && updateResponse.UploadURL != "" {
if kind != apitype.DestroyUpdate && updateResponse.UploadURL != "" {
uploadURL, err := url.Parse(updateResponse.UploadURL)
if err != nil {
return UpdateIdentifier{}, errors.Wrap(err, "parsing upload URL")

View file

@ -137,7 +137,7 @@ func (u *cloudUpdate) Complete(status apitype.UpdateStatus) error {
}
func (u *cloudUpdate) recordEvent(
event engine.Event, seen map[resource.URN]engine.StepEventMetadata,
action apitype.UpdateKind, event engine.Event, seen map[resource.URN]engine.StepEventMetadata,
opts backend.DisplayOptions) error {
// If we don't have a token source, we can't perform any mutations.
@ -158,7 +158,7 @@ func (u *cloudUpdate) recordEvent(
// Ensure we render events with raw colorization tags. Also, render these as 'diff' events so
// the user has a rich diff-log they can see when the look at their logs in the service.
opts.Color = colors.Raw
msg := local.RenderDiffEvent(event, seen, opts)
msg := local.RenderDiffEvent(action, event, seen, opts)
if msg == "" {
return nil
}
@ -173,13 +173,13 @@ func (u *cloudUpdate) recordEvent(
return u.backend.client.AppendUpdateLogEntry(u.context, u.update, kind, fields, token)
}
func (u *cloudUpdate) RecordAndDisplayEvents(action string,
func (u *cloudUpdate) RecordAndDisplayEvents(op string, action apitype.UpdateKind,
events <-chan engine.Event, done chan<- bool, opts backend.DisplayOptions) {
// Start the local display processor. Display things however the options have been
// set to display (i.e. diff vs progress).
displayEvents := make(chan engine.Event)
go local.DisplayEvents(action, displayEvents, done, opts)
go local.DisplayEvents(op, action, displayEvents, done, opts)
seen := make(map[resource.URN]engine.StepEventMetadata)
for e := range events {
@ -187,7 +187,7 @@ func (u *cloudUpdate) RecordAndDisplayEvents(action string,
displayEvents <- e
// Then render and record the event for posterity.
if err := u.recordEvent(e, seen, opts); err != nil {
if err := u.recordEvent(action, e, seen, opts); err != nil {
diagEvent := engine.Event{
Type: engine.DiagEvent,
Payload: engine.DiagEventPayload{

View file

@ -206,7 +206,7 @@ func (b *localBackend) GetLatestConfiguration(ctx context.Context,
func (b *localBackend) Preview(
_ context.Context, stackRef backend.StackReference, proj *workspace.Project, root string, m backend.UpdateMetadata,
opts backend.UpdateOptions, scopes backend.CancellationScopeSource) (engine.ResourceChanges, error) {
return b.performEngineOp("previewing", backend.PreviewUpdate,
return b.performEngineOp("previewing", apitype.PreviewUpdate,
stackRef.StackName(), proj, root, m, opts, scopes, engine.Update)
}
@ -225,27 +225,27 @@ func (b *localBackend) Update(
if err = backend.ValidateStackProperties(string(stackName), tags); err != nil {
return nil, errors.Wrap(err, "validating stack properties")
}
return b.performEngineOp("updating", backend.DeployUpdate,
return b.performEngineOp("updating", apitype.UpdateUpdate,
stackName, proj, root, m, opts, scopes, engine.Update)
}
func (b *localBackend) Refresh(
_ context.Context, stackRef backend.StackReference, proj *workspace.Project, root string, m backend.UpdateMetadata,
opts backend.UpdateOptions, scopes backend.CancellationScopeSource) (engine.ResourceChanges, error) {
return b.performEngineOp("refreshing", backend.RefreshUpdate,
return b.performEngineOp("refreshing", apitype.RefreshUpdate,
stackRef.StackName(), proj, root, m, opts, scopes, engine.Refresh)
}
func (b *localBackend) Destroy(
_ context.Context, stackRef backend.StackReference, proj *workspace.Project, root string, m backend.UpdateMetadata,
opts backend.UpdateOptions, scopes backend.CancellationScopeSource) (engine.ResourceChanges, error) {
return b.performEngineOp("destroying", backend.DestroyUpdate,
return b.performEngineOp("destroying", apitype.DestroyUpdate,
stackRef.StackName(), proj, root, m, opts, scopes, engine.Destroy)
}
type engineOpFunc func(engine.UpdateInfo, *engine.Context, engine.UpdateOptions, bool) (engine.ResourceChanges, error)
func (b *localBackend) performEngineOp(op string, kind backend.UpdateKind,
func (b *localBackend) performEngineOp(op string, kind apitype.UpdateKind,
stackName tokens.QName, proj *workspace.Project, root string, m backend.UpdateMetadata, opts backend.UpdateOptions,
scopes backend.CancellationScopeSource, performEngineOp engineOpFunc) (engine.ResourceChanges, error) {
@ -255,13 +255,13 @@ func (b *localBackend) performEngineOp(op string, kind backend.UpdateKind,
}
events := make(chan engine.Event)
dryRun := (kind == backend.PreviewUpdate)
dryRun := (kind == apitype.PreviewUpdate)
cancelScope := scopes.NewScope(events, dryRun)
defer cancelScope.Close()
done := make(chan bool)
go DisplayEvents(op, events, done, opts.Display)
go DisplayEvents(op, kind, events, done, opts.Display)
// Create the management machinery.
persister := b.newSnapshotPersister(stackName)

View file

@ -24,6 +24,7 @@ import (
"strconv"
"time"
"github.com/pulumi/pulumi/pkg/apitype"
"github.com/pulumi/pulumi/pkg/backend"
"github.com/pulumi/pulumi/pkg/diag"
"github.com/pulumi/pulumi/pkg/diag/colors"
@ -38,13 +39,13 @@ import (
// it comes in. Once all events have been read from the channel and displayed, it closes the `done`
// channel so the caller can await all the events being written.
func DisplayEvents(
action string, events <-chan engine.Event,
op string, action apitype.UpdateKind, events <-chan engine.Event,
done chan<- bool, opts backend.DisplayOptions) {
if opts.DiffDisplay {
DisplayDiffEvents(action, events, done, opts)
DisplayDiffEvents(op, action, events, done, opts)
} else {
DisplayProgressEvents(action, events, done, opts)
DisplayProgressEvents(op, action, events, done, opts)
}
}
@ -58,10 +59,10 @@ func (s *nopSpinner) Reset() {
}
// DisplayDiffEvents displays the engine events with the diff view.
func DisplayDiffEvents(action string,
func DisplayDiffEvents(op string, action apitype.UpdateKind,
events <-chan engine.Event, done chan<- bool, opts backend.DisplayOptions) {
prefix := fmt.Sprintf("%s%s...", cmdutil.EmojiOr("✨ ", "@ "), action)
prefix := fmt.Sprintf("%s%s...", cmdutil.EmojiOr("✨ ", "@ "), op)
var spinner cmdutil.Spinner
var ticker *time.Ticker
@ -96,7 +97,7 @@ func DisplayDiffEvents(action string,
}
}
msg := RenderDiffEvent(event, seen, opts)
msg := RenderDiffEvent(action, event, seen, opts)
if msg != "" && out != nil {
fprintIgnoreError(out, msg)
}
@ -108,8 +109,8 @@ func DisplayDiffEvents(action string,
}
}
func RenderDiffEvent(
event engine.Event, seen map[resource.URN]engine.StepEventMetadata, opts backend.DisplayOptions) string {
func RenderDiffEvent(action apitype.UpdateKind, event engine.Event,
seen map[resource.URN]engine.StepEventMetadata, opts backend.DisplayOptions) string {
switch event.Type {
case engine.CancelEvent:
@ -117,7 +118,7 @@ func RenderDiffEvent(
case engine.PreludeEvent:
return renderPreludeEvent(event.Payload.(engine.PreludeEventPayload), opts)
case engine.SummaryEvent:
return renderSummaryEvent(event.Payload.(engine.SummaryEventPayload), opts)
return renderSummaryEvent(action, event.Payload.(engine.SummaryEventPayload), opts)
case engine.ResourceOperationFailed:
return renderResourceOperationFailedEvent(event.Payload.(engine.ResourceOperationFailedPayload), opts)
case engine.ResourceOutputsEvent:
@ -147,7 +148,8 @@ func renderStdoutColorEvent(
return opts.Color.Colorize(payload.Message)
}
func renderSummaryEvent(event engine.SummaryEventPayload, opts backend.DisplayOptions) string {
func renderSummaryEvent(
action apitype.UpdateKind, event engine.SummaryEventPayload, opts backend.DisplayOptions) string {
changes := event.ResourceChanges
changeCount := 0
@ -159,6 +161,8 @@ func renderSummaryEvent(event engine.SummaryEventPayload, opts backend.DisplayOp
var kind string
if event.IsPreview {
kind = "previewed"
} else if action == apitype.RefreshUpdate {
kind = "refreshed"
} else {
kind = "performed"
}

View file

@ -25,6 +25,10 @@ import (
"unicode"
"unicode/utf8"
"github.com/docker/docker/pkg/term"
"golang.org/x/crypto/ssh/terminal"
"github.com/pulumi/pulumi/pkg/apitype"
"github.com/pulumi/pulumi/pkg/backend"
"github.com/pulumi/pulumi/pkg/diag"
"github.com/pulumi/pulumi/pkg/diag/colors"
@ -34,9 +38,6 @@ import (
"github.com/pulumi/pulumi/pkg/tokens"
"github.com/pulumi/pulumi/pkg/util/cmdutil"
"github.com/pulumi/pulumi/pkg/util/contract"
"github.com/docker/docker/pkg/term"
"golang.org/x/crypto/ssh/terminal"
)
// Progress describes a message we want to show in the display. There are two types of messages,
@ -86,6 +87,9 @@ type ProgressDisplay struct {
opts backend.DisplayOptions
progressOutput chan<- Progress
// action is the kind of action (preview, update, refresh, etc) being performed.
action apitype.UpdateKind
// Whether or not we're previewing. We don't know what we are actually doing until
// we get the initial 'prelude' event.
//
@ -223,14 +227,14 @@ func (display *ProgressDisplay) writeBlankLine() {
// DisplayProgressEvents displays the engine events with docker's progress view.
func DisplayProgressEvents(
action string, events <-chan engine.Event,
op string, action apitype.UpdateKind, events <-chan engine.Event,
done chan<- bool, opts backend.DisplayOptions) {
// Create a ticker that will update all our status messages once a second. Any
// in-flight resources will get a varying . .. ... ticker appended to them to
// let the user know what is still being worked on.
spinner, ticker := cmdutil.NewSpinnerAndTicker(
fmt.Sprintf("%s%s...", cmdutil.EmojiOr("✨ ", "@ "), action),
fmt.Sprintf("%s%s...", cmdutil.EmojiOr("✨ ", "@ "), op),
nil, 1 /*timesPerSecond*/)
// The channel we push progress messages into, and which DisplayProgressToStream pulls
@ -238,6 +242,7 @@ func DisplayProgressEvents(
progressOutput := make(chan Progress)
display := &ProgressDisplay{
action: action,
opts: opts,
progressOutput: progressOutput,
eventUrnToResourceRow: make(map[resource.URN]ResourceRow),
@ -718,7 +723,7 @@ func (display *ProgressDisplay) processEndSteps() {
// print the summary
if display.summaryEventPayload != nil {
msg := renderSummaryEvent(*display.summaryEventPayload, display.opts)
msg := renderSummaryEvent(display.action, *display.summaryEventPayload, display.opts)
if !wroteDiagnosticHeader {
display.writeBlankLine()

View file

@ -15,6 +15,7 @@
package backend
import (
"github.com/pulumi/pulumi/pkg/apitype"
"github.com/pulumi/pulumi/pkg/engine"
"github.com/pulumi/pulumi/pkg/resource/config"
)
@ -28,20 +29,6 @@ type UpdateMetadata struct {
Environment map[string]string `json:"environment"`
}
// UpdateKind is an enum for the type of update performed.
type UpdateKind string
const (
// DeployUpdate is the prototypical Pulumi program update.
DeployUpdate UpdateKind = "update"
// PreviewUpdate is a preview of an update, without impacting resources.
PreviewUpdate UpdateKind = "preview"
// RefreshUpdate is an update that adopts a cloud's existing resource state.
RefreshUpdate UpdateKind = "refresh"
// DestroyUpdate is an update which removes all resources.
DestroyUpdate UpdateKind = "destroy"
)
// UpdateResult is an enum for the result of the update.
type UpdateResult string
@ -92,8 +79,8 @@ const (
// UpdateInfo describes a previous update.
type UpdateInfo struct {
// Information known before an update is started.
Kind UpdateKind `json:"kind"`
StartTime int64 `json:"startTime"`
Kind apitype.UpdateKind `json:"kind"`
StartTime int64 `json:"startTime"`
// Message is an optional message associated with the update.
Message string `json:"message"`