pulumi/cmd/pulumi.go
Joe Duffy 16ade183d8
Add a manifest to checkpoint files (#630)
This change adds a new manifest section to the checkpoint files.
The existing time moves into it, and we add to it the version of
the Pulumi CLI that created it, along with the names, types, and
versions of all plugins used to generate the file.  There is a
magic cookie that we also use during verification.

This is to help keep us sane when debugging problems "in the wild,"
and I'm sure we will add more to it over time (checksum, etc).

For example, after an up, you can now see this in `pulumi stack`:

```
Current stack is demo:
    Last updated at 2017-12-01 13:48:49.815740523 -0800 PST
    Pulumi version v0.8.3-79-g1ab99ad
    Plugin pulumi-provider-aws [resource] version v0.8.3-22-g4363e77
    Plugin pulumi-langhost-nodejs [language] version v0.8.3-79-g77bb6b6
    Checkpoint file is /Users/joeduffy/dev/code/src/github.com/pulumi/pulumi-aws/.pulumi/stacks/webserver/demo.json
```

This addresses pulumi/pulumi#628.
2017-12-01 13:50:32 -08:00

107 lines
3.4 KiB
Go

// Copyright 2016-2017, Pulumi Corporation. All rights reserved.
package cmd
import (
"bufio"
"flag"
"fmt"
"os"
"strings"
"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/pulumi/pulumi/pkg/diag/colors"
"github.com/pulumi/pulumi/pkg/util/cmdutil"
)
// 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).
var backend pulumiBackend
func init() {
if usePulumiCloudCommands() {
backend = &pulumiCloudPulumiBackend{}
} else {
backend = &localPulumiBackend{}
}
}
// NewPulumiCmd creates a new Pulumi Cmd instance.
func NewPulumiCmd() *cobra.Command {
var logFlow bool
var logToStderr bool
var tracing string
var verbose int
var cwd string
cmd := &cobra.Command{
Use: "pulumi",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
if cwd != "" {
err := os.Chdir(cwd)
if err != nil {
cmdutil.ExitError(err.Error())
}
}
cmdutil.InitLogging(logToStderr, verbose, logFlow)
cmdutil.InitTracing("pulumi-cli", tracing)
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
glog.Flush()
cmdutil.CloseTracing()
},
}
cmd.PersistentFlags().StringVarP(&cwd, "cwd", "C", "", "Run pulumi as if it had been started in another directory")
cmd.PersistentFlags().BoolVar(&disableIntegrityChecking, "disable-integrity-checking", false,
"Disable integrity checking of checkpoint files")
cmd.PersistentFlags().BoolVar(&logFlow, "logflow", false, "Flow log settings to child processes (like plugins)")
cmd.PersistentFlags().BoolVar(&logToStderr, "logtostderr", false, "Log to stderr instead of to files")
cmd.PersistentFlags().StringVar(&tracing, "tracing", "", "Emit tracing to a Zipkin-compatible tracing endpoint")
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())
cmd.AddCommand(newStackCmd())
cmd.AddCommand(newPreviewCmd())
cmd.AddCommand(newUpdateCmd())
cmd.AddCommand(newVersionCmd())
cmd.AddCommand(newInitCmd())
cmd.AddCommand(newLogsCmd())
// Commands specific to the Pulumi Cloud Management Console.
cmd.AddCommand(newLoginCmd())
cmd.AddCommand(newLogoutCmd())
// 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())
}
// Tell flag about -C, so someone can do pulumi -C <working-directory> stack and the call to cmdutil.InitLogging
// 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")
return cmd
}
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)
if line, _ := reader.ReadString('\n'); strings.TrimSpace(line) != name {
fmt.Fprintf(os.Stderr, "Confirmation declined -- exiting without doing anything\n")
return false
}
return true
}