2017-06-26 23:46:34 +02:00
|
|
|
// Copyright 2016-2017, Pulumi Corporation. All rights reserved.
|
2017-04-12 20:04:04 +02:00
|
|
|
|
2017-09-22 04:18:21 +02:00
|
|
|
package cmd
|
2017-04-12 20:04:04 +02:00
|
|
|
|
|
|
|
import (
|
2017-08-23 01:56:15 +02:00
|
|
|
"bufio"
|
2017-10-06 23:03:37 +02:00
|
|
|
"flag"
|
2017-08-23 01:56:15 +02:00
|
|
|
"fmt"
|
|
|
|
"os"
|
2017-11-07 22:58:56 +01:00
|
|
|
"strings"
|
2017-08-23 01:56:15 +02:00
|
|
|
|
2017-04-12 20:04:04 +02:00
|
|
|
"github.com/golang/glog"
|
|
|
|
"github.com/spf13/cobra"
|
2017-04-13 14:27:45 +02:00
|
|
|
|
2017-09-22 04:18:21 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/diag/colors"
|
|
|
|
"github.com/pulumi/pulumi/pkg/util/cmdutil"
|
2017-04-12 20:04:04 +02:00
|
|
|
)
|
|
|
|
|
Bring back component outputs
This change brings back component outputs to the overall system again.
In doing so, it generally overhauls the way we do resource RPCs a bit:
* Instead of RegisterResource and CompleteResource, we call these
BeginRegisterResource and EndRegisterResource, which begins to model
these as effectively "asynchronous" resource requests. This should also
help with parallelism (https://github.com/pulumi/pulumi/issues/106).
* Flip the CLI/engine a little on its head. Rather than it driving the
planning and deployment process, we move more to a model where it
simply observes it. This is done by implementing an event handler
interface with three events: OnResourceStepPre, OnResourceStepPost,
and OnResourceComplete. The first two are invoked immediately before
and after any step operation, and the latter is invoked whenever a
EndRegisterResource comes in. The reason for the asymmetry here is
that the checkpointing logic in the deployment engine is largely
untouched (intentionally, as this is a sensitive part of the system),
and so the "begin"/"end" nature doesn't flow through faithfully.
* Also make the engine more event-oriented in its terminology and the
way it handles the incoming BeginRegisterResource and
EndRegisterResource events from the language host. This is the first
step down a long road of incrementally refactoring the engine to work
this way, a necessary prerequisite for parallelism.
2017-11-29 16:42:14 +01:00
|
|
|
// pulumiBackend is the "backend" that we talk to. When the application launches, if the environment variable
|
|
|
|
// PULUMI_API is set, we use a backend that targets the pulumi.com API, otherwise we use the local backend (i.e.
|
|
|
|
// "fire and forget" mode).
|
2017-11-01 22:55:16 +01:00
|
|
|
var backend pulumiBackend
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
if usePulumiCloudCommands() {
|
|
|
|
backend = &pulumiCloudPulumiBackend{}
|
|
|
|
} else {
|
|
|
|
backend = &localPulumiBackend{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-22 04:18:21 +02:00
|
|
|
// NewPulumiCmd creates a new Pulumi Cmd instance.
|
2017-10-16 22:50:00 +02:00
|
|
|
func NewPulumiCmd(version string) *cobra.Command {
|
2017-05-31 18:14:49 +02:00
|
|
|
var logFlow bool
|
2017-04-12 20:04:04 +02:00
|
|
|
var logToStderr bool
|
2017-11-09 02:08:51 +01:00
|
|
|
var tracing string
|
2017-04-12 20:04:04 +02:00
|
|
|
var verbose int
|
2017-10-06 17:50:54 +02:00
|
|
|
var cwd string
|
2017-04-12 20:04:04 +02:00
|
|
|
cmd := &cobra.Command{
|
2017-09-22 04:18:21 +02:00
|
|
|
Use: "pulumi",
|
2017-04-12 20:04:04 +02:00
|
|
|
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
2017-10-06 17:50:54 +02:00
|
|
|
if cwd != "" {
|
|
|
|
err := os.Chdir(cwd)
|
|
|
|
if err != nil {
|
|
|
|
cmdutil.ExitError(err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-31 18:14:49 +02:00
|
|
|
cmdutil.InitLogging(logToStderr, verbose, logFlow)
|
2017-11-09 02:08:51 +01:00
|
|
|
cmdutil.InitTracing("pulumi-cli", tracing)
|
2017-04-12 20:04:04 +02:00
|
|
|
},
|
|
|
|
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
|
|
|
glog.Flush()
|
2017-11-09 02:08:51 +01:00
|
|
|
cmdutil.CloseTracing()
|
2017-04-12 20:04:04 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2017-10-06 17:50:54 +02:00
|
|
|
cmd.PersistentFlags().StringVarP(&cwd, "cwd", "C", "", "Run pulumi as if it had been started in another directory")
|
2017-05-31 18:14:49 +02:00
|
|
|
cmd.PersistentFlags().BoolVar(&logFlow, "logflow", false, "Flow log settings to child processes (like plugins)")
|
2017-04-12 20:04:04 +02:00
|
|
|
cmd.PersistentFlags().BoolVar(&logToStderr, "logtostderr", false, "Log to stderr instead of to files")
|
2017-11-09 02:08:51 +01:00
|
|
|
cmd.PersistentFlags().StringVar(&tracing, "tracing", "", "Emit tracing to a Zipkin-compatible tracing endpoint")
|
2017-04-12 20:04:04 +02:00
|
|
|
cmd.PersistentFlags().IntVarP(
|
|
|
|
&verbose, "verbose", "v", 0, "Enable verbose logging (e.g., v=3); anything >3 is very verbose")
|
|
|
|
|
|
|
|
cmd.AddCommand(newConfigCmd())
|
|
|
|
cmd.AddCommand(newDestroyCmd())
|
2017-10-16 21:04:35 +02:00
|
|
|
cmd.AddCommand(newStackCmd())
|
2017-09-23 00:15:42 +02:00
|
|
|
cmd.AddCommand(newPreviewCmd())
|
2017-09-23 02:23:40 +02:00
|
|
|
cmd.AddCommand(newUpdateCmd())
|
2017-10-16 22:50:00 +02:00
|
|
|
cmd.AddCommand(newVersionCmd(version))
|
2017-10-25 19:20:08 +02:00
|
|
|
cmd.AddCommand(newInitCmd())
|
2017-11-09 21:38:03 +01:00
|
|
|
cmd.AddCommand(newLogsCmd())
|
2017-04-12 20:04:04 +02:00
|
|
|
|
2017-10-20 00:22:07 +02:00
|
|
|
// Commands specific to the Pulumi Cloud Management Console.
|
|
|
|
cmd.AddCommand(newLoginCmd())
|
|
|
|
cmd.AddCommand(newLogoutCmd())
|
|
|
|
|
2017-11-21 21:11:43 +01:00
|
|
|
// We have a set of commands that are useful for developers of pulumi that we add when PULUMI_DEBUG_COMMANDS is
|
|
|
|
// set to true.
|
|
|
|
if isTruthy(os.Getenv("PULUMI_DEBUG_COMMANDS")) {
|
|
|
|
cmd.AddCommand(newArchiveCommand())
|
|
|
|
}
|
|
|
|
|
2017-10-16 21:04:35 +02:00
|
|
|
// Tell flag about -C, so someone can do pulumi -C <working-directory> stack and the call to cmdutil.InitLogging
|
2017-10-06 23:03:37 +02:00
|
|
|
// which calls flag.Parse under the hood doesn't yell at you.
|
|
|
|
//
|
|
|
|
// TODO[pulumi/pulumi#301]: when we move away from using glog, it should be safe to remove this.
|
|
|
|
flag.StringVar(&cwd, "C", "", "Run pulumi as if it had been started in another directory")
|
|
|
|
|
2017-04-12 20:04:04 +02:00
|
|
|
return cmd
|
|
|
|
}
|
2017-06-02 21:43:04 +02:00
|
|
|
|
2017-08-23 01:56:15 +02:00
|
|
|
func confirmPrompt(msg string, name string) bool {
|
|
|
|
prompt := fmt.Sprintf(msg, name)
|
|
|
|
fmt.Print(
|
|
|
|
colors.ColorizeText(fmt.Sprintf("%v%v%v\n", colors.SpecAttention, prompt, colors.Reset)))
|
|
|
|
fmt.Printf("Please confirm that this is what you'd like to do by typing (\"%v\"): ", name)
|
|
|
|
reader := bufio.NewReader(os.Stdin)
|
2017-11-07 22:58:56 +01:00
|
|
|
if line, _ := reader.ReadString('\n'); strings.TrimSpace(line) != name {
|
2017-08-23 01:56:15 +02:00
|
|
|
fmt.Fprintf(os.Stderr, "Confirmation declined -- exiting without doing anything\n")
|
|
|
|
return false
|
2017-06-02 21:43:04 +02:00
|
|
|
}
|
2017-08-23 01:56:15 +02:00
|
|
|
return true
|
2017-06-02 21:43:04 +02:00
|
|
|
}
|