2017-10-03 01:37:12 +02:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
2017-10-05 23:08:46 +02:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
2017-10-03 01:37:12 +02:00
|
|
|
"os"
|
|
|
|
|
2017-10-17 01:01:34 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/pack"
|
|
|
|
|
2017-10-08 16:18:53 +02:00
|
|
|
"github.com/pkg/errors"
|
|
|
|
|
2017-10-05 23:08:46 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/diag"
|
|
|
|
"github.com/pulumi/pulumi/pkg/diag/colors"
|
|
|
|
"github.com/pulumi/pulumi/pkg/engine"
|
2017-10-03 01:37:12 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/tokens"
|
2017-10-05 23:08:46 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/util/contract"
|
2017-10-03 01:37:12 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/workspace"
|
|
|
|
)
|
|
|
|
|
|
|
|
// newWorkspace creates a new workspace using the current working directory.
|
|
|
|
func newWorkspace() (workspace.W, error) {
|
|
|
|
pwd, err := os.Getwd()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return workspace.New(pwd)
|
|
|
|
}
|
|
|
|
|
2017-10-16 21:04:35 +02:00
|
|
|
// explicitOrCurrent returns an stack name after ensuring the stack exists. When a empty
|
|
|
|
// stack name is passed, the "current" ambient stack is returned
|
2017-10-03 01:37:12 +02:00
|
|
|
func explicitOrCurrent(name string) (tokens.QName, error) {
|
|
|
|
if name == "" {
|
2017-10-16 21:04:35 +02:00
|
|
|
return getCurrentStack()
|
2017-10-03 01:37:12 +02:00
|
|
|
}
|
|
|
|
|
2017-10-16 21:04:35 +02:00
|
|
|
_, _, err := getStack(tokens.QName(name))
|
2017-10-03 01:37:12 +02:00
|
|
|
return tokens.QName(name), err
|
|
|
|
}
|
|
|
|
|
2017-10-16 21:04:35 +02:00
|
|
|
// getCurrentStack reads the current stack.
|
|
|
|
func getCurrentStack() (tokens.QName, error) {
|
2017-10-03 01:37:12 +02:00
|
|
|
w, err := newWorkspace()
|
|
|
|
if err != nil {
|
2017-10-08 16:18:53 +02:00
|
|
|
return "", err
|
2017-10-03 01:37:12 +02:00
|
|
|
}
|
|
|
|
|
2017-10-16 21:04:35 +02:00
|
|
|
stack := w.Settings().Stack
|
|
|
|
if stack == "" {
|
|
|
|
return "", errors.New("no current stack detected; please use `pulumi stack init` to create one")
|
2017-10-08 16:18:53 +02:00
|
|
|
}
|
2017-10-16 21:04:35 +02:00
|
|
|
return stack, nil
|
2017-10-03 01:37:12 +02:00
|
|
|
}
|
|
|
|
|
2017-10-16 21:04:35 +02:00
|
|
|
// setCurrentStack changes the current stack to the given stack name, issuing an error if it doesn't exist.
|
|
|
|
func setCurrentStack(name tokens.QName, verify bool) error {
|
2017-10-03 01:37:12 +02:00
|
|
|
if verify {
|
2017-10-16 21:04:35 +02:00
|
|
|
if _, _, err := getStack(name); err != nil {
|
2017-10-03 01:37:12 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-16 21:04:35 +02:00
|
|
|
// Switch the current workspace to that stack.
|
2017-10-03 01:37:12 +02:00
|
|
|
w, err := newWorkspace()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-10-16 21:04:35 +02:00
|
|
|
w.Settings().Stack = name
|
2017-10-03 01:37:12 +02:00
|
|
|
return w.Save()
|
|
|
|
}
|
2017-10-05 23:08:46 +02:00
|
|
|
|
|
|
|
// displayEvents 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.
|
2017-10-12 23:20:01 +02:00
|
|
|
func displayEvents(events <-chan engine.Event, done chan bool, debug bool) {
|
2017-10-05 23:08:46 +02:00
|
|
|
defer close(done)
|
|
|
|
|
|
|
|
for event := range events {
|
|
|
|
switch event.Type {
|
2017-10-21 02:28:35 +02:00
|
|
|
case engine.StdoutColorEvent:
|
2017-10-05 23:08:46 +02:00
|
|
|
fmt.Print(colors.ColorizeText(event.Payload.(string)))
|
2017-10-21 02:28:35 +02:00
|
|
|
case engine.DiagEvent:
|
2017-10-05 23:08:46 +02:00
|
|
|
payload := event.Payload.(engine.DiagEventPayload)
|
|
|
|
var out io.Writer
|
|
|
|
out = os.Stdout
|
|
|
|
|
|
|
|
if payload.Severity == diag.Error || payload.Severity == diag.Warning {
|
|
|
|
out = os.Stderr
|
|
|
|
}
|
|
|
|
if payload.Severity == diag.Debug && !debug {
|
|
|
|
out = ioutil.Discard
|
|
|
|
}
|
|
|
|
msg := payload.Message
|
|
|
|
if payload.UseColor {
|
|
|
|
msg = colors.ColorizeText(msg)
|
|
|
|
}
|
|
|
|
fmt.Fprintf(out, msg)
|
|
|
|
default:
|
|
|
|
contract.Failf("unknown event type '%s'", event.Type)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-10-17 01:01:34 +02:00
|
|
|
|
2017-10-17 21:28:03 +02:00
|
|
|
func getPackage() (*pack.Package, error) {
|
|
|
|
pkgPath, err := getPackageFilePath()
|
2017-10-17 01:01:34 +02:00
|
|
|
if err != nil {
|
2017-10-17 21:28:03 +02:00
|
|
|
return nil, err
|
2017-10-17 01:01:34 +02:00
|
|
|
}
|
|
|
|
|
2017-10-17 21:28:03 +02:00
|
|
|
pkg, err := pack.Load(pkgPath)
|
2017-10-17 01:01:34 +02:00
|
|
|
|
2017-10-17 21:28:03 +02:00
|
|
|
return pkg, err
|
|
|
|
}
|
2017-10-17 01:01:34 +02:00
|
|
|
|
2017-10-17 21:28:03 +02:00
|
|
|
func savePackage(pkg *pack.Package) error {
|
|
|
|
pkgPath, err := getPackageFilePath()
|
2017-10-17 01:01:34 +02:00
|
|
|
if err != nil {
|
2017-10-17 21:28:03 +02:00
|
|
|
return err
|
2017-10-17 01:01:34 +02:00
|
|
|
}
|
|
|
|
|
2017-10-17 21:28:03 +02:00
|
|
|
return pack.Save(pkgPath, pkg)
|
|
|
|
}
|
2017-10-17 01:01:34 +02:00
|
|
|
|
2017-10-17 21:28:03 +02:00
|
|
|
func getPackageFilePath() (string, error) {
|
|
|
|
dir, err := os.Getwd()
|
2017-10-17 01:01:34 +02:00
|
|
|
if err != nil {
|
2017-10-17 21:28:03 +02:00
|
|
|
return "", err
|
2017-10-17 01:01:34 +02:00
|
|
|
}
|
|
|
|
|
2017-10-17 21:28:03 +02:00
|
|
|
pkgPath, err := workspace.DetectPackage(dir)
|
2017-10-17 01:01:34 +02:00
|
|
|
if err != nil {
|
2017-10-17 21:28:03 +02:00
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
if pkgPath == "" {
|
|
|
|
return "", errors.Errorf("could not find Pulumi.yaml, started search in %s", dir)
|
2017-10-17 01:01:34 +02:00
|
|
|
}
|
|
|
|
|
2017-10-17 21:28:03 +02:00
|
|
|
return pkgPath, nil
|
2017-10-17 01:01:34 +02:00
|
|
|
}
|