pulumi/pkg/backend/state/stacks.go
joeduffy 2eb86b24c2 Make some updates based on CR feedback
This change implements some feedback from @ellismg.

* Make backend.Stack an interface and let backends implement it,
  enabling dynamic type testing/casting to access information
  specific to that backend.  For instance, the cloud.Stack conveys
  the cloud URL, org name, and PPC name, for each stack.

* Similarly expose specialized backend.Backend interfaces,
  local.Backend and cloud.Backend, to convey specific information.

* Redo a bunch of the commands in terms of these.

* Keeping with this theme, turn the CreateStack options into an
  opaque interface{}, and let the specific backends expose their
  own structures with their own settings (like PPC name in cloud).

* Show both the org and PPC names in the cloud column printed in
  the stack ls command, in addition to the Pulumi Cloud URL.

Unrelated, but useful:

* Special case the 401 HTTP response and make a friendly error,
  to tell the developer they must use `pulumi login`.  This is
  better than tossing raw "401: Unauthorized" errors in their face.

* Change the "Updating stack '..' in the Pulumi Cloud" message to
  use the correct action verb ("Previewing", "Destroying", etc).
2017-12-03 08:10:50 -08:00

61 lines
1.4 KiB
Go

// Copyright 2016-2017, Pulumi Corporation. All rights reserved.
package state
import (
"github.com/pulumi/pulumi/pkg/backend"
"github.com/pulumi/pulumi/pkg/tokens"
"github.com/pulumi/pulumi/pkg/workspace"
)
// Stack returns an stack name after ensuring the stack exists. When an empty stack name is passed, the
// "current" ambient stack is returned.
func Stack(name tokens.QName, backends []backend.Backend) (backend.Stack, error) {
if name == "" {
return CurrentStack(backends)
}
// If not using the current stack, check all of the known backends to see if they know about it.
for _, be := range backends {
stacks, err := be.ListStacks()
if err != nil {
return nil, err
}
for _, stack := range stacks {
if stack.Name() == name {
return stack, nil
}
}
}
return nil, nil
}
// CurrentStack reads the current stack and returns an instance connected to its backend provider.
func CurrentStack(backends []backend.Backend) (backend.Stack, error) {
w, err := workspace.New()
if err != nil {
return nil, err
}
stackName := w.Settings().Stack
if stackName == "" {
return nil, nil
}
return Stack(stackName, backends)
}
// SetCurrentStack changes the current stack to the given stack name.
func SetCurrentStack(name tokens.QName) error {
// Switch the current workspace to that stack.
w, err := workspace.New()
if err != nil {
return err
}
w.Settings().Stack = name
return w.Save()
}