// Copyright 2016-2018, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package display import ( "fmt" "io" "github.com/pulumi/pulumi/pkg/apitype" "github.com/pulumi/pulumi/pkg/engine" "github.com/pulumi/pulumi/pkg/resource" "github.com/pulumi/pulumi/pkg/resource/deploy" "github.com/pulumi/pulumi/pkg/tokens" "github.com/pulumi/pulumi/pkg/util/contract" ) // ShowEvents reads events from the `events` channel until it is closed, displaying each event as // 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 ShowEvents( op string, action apitype.UpdateKind, stack tokens.QName, proj tokens.PackageName, events <-chan engine.Event, done chan<- bool, opts Options, isPreview bool) { if opts.JSONDisplay { // TODO[pulumi/pulumi#2390]: enable JSON display for real deployments. contract.Assertf(isPreview, "JSON display only available in preview mode") ShowJSONEvents(op, action, events, done, opts) return } switch opts.Type { case DisplayDiff: ShowDiffEvents(op, action, events, done, opts) case DisplayProgress: ShowProgressEvents(op, action, stack, proj, events, done, opts, isPreview) case DisplayQuery: contract.Failf("DisplayQuery can only be used in query mode, which should be invoked " + "directly instead of through ShowEvents") default: contract.Failf("Unknown display type %d", opts.Type) } } type nopSpinner struct { } func (s *nopSpinner) Tick() { } func (s *nopSpinner) Reset() { } // isRootStack returns true if the step pertains to the rootmost stack component. func isRootStack(step engine.StepEventMetadata) bool { return isRootURN(step.URN) } func isRootURN(urn resource.URN) bool { return urn != "" && urn.Type() == resource.RootStackType } // shouldShow returns true if a step should show in the output. func shouldShow(step engine.StepEventMetadata, opts Options) bool { // For certain operations, whether they are tracked is controlled by flags (to cut down on superfluous output). if step.Op == deploy.OpSame { // If the op is the same, it is possible that the resource's metadata changed. In that case, still show it. if step.Old.Protect != step.New.Protect { return true } return opts.ShowSameResources } // For logical replacement operations, only show them during progress-style updates (since this is integrated // into the resource status update), or if it is requested explicitly (for diffs and JSON outputs). if (opts.Type == DisplayDiff || opts.JSONDisplay) && !step.Logical && !opts.ShowReplacementSteps { return false } // Otherwise, default to showing the operation. return true } func fprintfIgnoreError(w io.Writer, format string, a ...interface{}) { _, err := fmt.Fprintf(w, format, a...) contract.IgnoreError(err) } func fprintIgnoreError(w io.Writer, a ...interface{}) { _, err := fmt.Fprint(w, a...) contract.IgnoreError(err) }