github.com/myhau/pulumi/pkg/v3@v3.70.2-0.20221116134521-f2775972e587/backend/display/query.go (about)

     1  // Copyright 2016-2018, Pulumi Corporation.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package display
    16  
    17  import (
    18  	"fmt"
    19  	"math"
    20  	"os"
    21  	"time"
    22  
    23  	"github.com/pulumi/pulumi/pkg/v3/engine"
    24  	"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
    25  	"github.com/pulumi/pulumi/sdk/v3/go/common/util/cmdutil"
    26  	"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
    27  )
    28  
    29  // ShowQueryEvents displays query events on the CLI.
    30  func ShowQueryEvents(op string, events <-chan engine.Event,
    31  	done chan<- bool, opts Options) {
    32  
    33  	prefix := fmt.Sprintf("%s%s...", cmdutil.EmojiOr("✨ ", "@ "), op)
    34  
    35  	var spinner cmdutil.Spinner
    36  	var ticker *time.Ticker
    37  
    38  	if opts.IsInteractive {
    39  		spinner, ticker = cmdutil.NewSpinnerAndTicker(prefix, nil, opts.Color, 8 /*timesPerSecond*/)
    40  	} else {
    41  		spinner = &nopSpinner{}
    42  		ticker = time.NewTicker(math.MaxInt64)
    43  	}
    44  
    45  	defer func() {
    46  		spinner.Reset()
    47  		ticker.Stop()
    48  		close(done)
    49  	}()
    50  
    51  	for {
    52  		select {
    53  		case <-ticker.C:
    54  			spinner.Tick()
    55  		case event := <-events:
    56  			spinner.Reset()
    57  
    58  			out := os.Stdout
    59  			if event.Type == engine.DiagEvent {
    60  				payload := event.Payload().(engine.DiagEventPayload)
    61  				if payload.Severity == diag.Error || payload.Severity == diag.Warning {
    62  					out = os.Stderr
    63  				}
    64  			}
    65  
    66  			msg := renderQueryEvent(event, opts)
    67  			if msg != "" && out != nil {
    68  				fprintIgnoreError(out, msg)
    69  			}
    70  
    71  			if event.Type == engine.CancelEvent {
    72  				return
    73  			}
    74  		}
    75  	}
    76  }
    77  
    78  func renderQueryEvent(event engine.Event, opts Options) string {
    79  	switch event.Type {
    80  	case engine.CancelEvent:
    81  		return ""
    82  
    83  	case engine.StdoutColorEvent:
    84  		return renderStdoutColorEvent(event.Payload().(engine.StdoutEventPayload), opts)
    85  
    86  	// Includes stdout of the query process.
    87  	case engine.DiagEvent:
    88  		return renderQueryDiagEvent(event.Payload().(engine.DiagEventPayload), opts)
    89  
    90  	case engine.PreludeEvent, engine.SummaryEvent, engine.ResourceOperationFailed,
    91  		engine.ResourceOutputsEvent, engine.ResourcePreEvent:
    92  
    93  		contract.Failf("query mode does not support resource operations")
    94  		return ""
    95  
    96  	default:
    97  		contract.Failf("unknown event type '%s'", event.Type)
    98  		return ""
    99  	}
   100  }
   101  
   102  func renderQueryDiagEvent(payload engine.DiagEventPayload, opts Options) string {
   103  	// Ignore debug messages unless we're in debug mode.
   104  	if payload.Severity == diag.Debug && !opts.Debug {
   105  		return ""
   106  	}
   107  
   108  	// Ignore error messages reported through diag events -- these are reported as errors later.
   109  	if payload.Severity == diag.Infoerr {
   110  		return ""
   111  	}
   112  
   113  	// For stdout messages, trim ONLY the last newline character.
   114  	if payload.Severity == diag.Info {
   115  		payload.Message = cmdutil.RemoveTrailingNewline(payload.Message)
   116  	}
   117  
   118  	return opts.Color.Colorize(payload.Prefix + payload.Message)
   119  }