pulumi/pkg/backend/display/display.go
joeduffy 250bcb9751 Add a --json flag to the preview command
This change adds a --json flag to the preview command, enabling
basic JSON serialization of preview plans. This effectively flattens
the engine event stream into a preview structure that contains a list
of steps, diagnostics, and summary information. Each step contains
the deep serialization of resource state, in addition to metadata about
the step, such as what kind of operation it entails.

This is a partial implementation of pulumi/pulumi#2390. In particular,
we only support --json on the `preview` command itself, and not `up`,
meaning that it isn't possible to serialize the result of an actual
deployment yet (thereby limiting what you can do with outputs, etc).
2019-04-25 17:36:31 -07:00

88 lines
2.8 KiB
Go

// 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)
} else if opts.DiffDisplay {
ShowDiffEvents(op, action, events, done, opts)
} else {
ShowProgressEvents(op, action, stack, proj, events, done, opts, isPreview)
}
}
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
}
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)
}