Don't mention PPC unless needed in the CLI

PPCs are no longer a central concept to our model, but instead a
feature that that pulumi.com provides to some organizations. Let's
remove most mentions of PPCs except for cases where we really need to
talk about them (e.g. when a stack is actually hosted in a PPC instead
of just via the normal pulumi.com service)

Also remove some "in the Pulumi Cloud" messages from the CLI, as using
the Pulumi Cloud is now the only real way to use pulumi.

Fixes pulumi/pulumi-service#1117
This commit is contained in:
Matt Ellis 2018-04-20 02:54:33 -04:00
parent cbb7e8e862
commit fe8bad70d1
6 changed files with 116 additions and 46 deletions

View file

@ -3,8 +3,11 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"github.com/pulumi/pulumi/pkg/backend"
"github.com/pulumi/pulumi/pkg/backend/cloud"
"github.com/pulumi/pulumi/pkg/backend/local"
"github.com/pulumi/pulumi/pkg/util/cmdutil"
@ -18,13 +21,21 @@ func newLoginCmd() *cobra.Command {
Long: "Log into the Pulumi Cloud. You can script by using PULUMI_ACCESS_TOKEN environment variable.",
Args: cmdutil.NoArgs,
Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error {
var b backend.Backend
var err error
if local.IsLocalBackendURL(cloudURL) {
_, err := local.Login(cmdutil.Diag(), cloudURL)
b, err = local.Login(cmdutil.Diag(), cloudURL)
} else {
b, err = cloud.Login(cmdutil.Diag(), cloudURL)
}
if err != nil {
return err
}
_, err := cloud.Login(cmdutil.Diag(), cloudURL)
return err
fmt.Printf("Logged into %s\n", b.Name())
return nil
}),
}
cmd.PersistentFlags().StringVarP(&cloudURL, "cloud-url", "c", "", "A cloud URL to log into")

View file

@ -13,11 +13,9 @@ import (
"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/pulumi/pulumi/pkg/backend/cloud"
"github.com/pulumi/pulumi/pkg/backend/local"
"github.com/pulumi/pulumi/pkg/diag/colors"
"github.com/pulumi/pulumi/pkg/util/cmdutil"
"github.com/pulumi/pulumi/pkg/workspace"
)
// NewPulumiCmd creates a new Pulumi Cmd instance.
@ -50,17 +48,6 @@ func NewPulumiCmd() *cobra.Command {
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
defaultHelp(cmd, args)
fmt.Println("See documentation at https://docs.pulumi.com")
url, err := workspace.GetCurrentCloudURL()
if err == nil && url != "" && !local.IsLocalBackendURL(url) {
fmt.Printf("\n")
suffix := ""
if url != cloud.PulumiCloudURL {
suffix = fmt.Sprintf(" (%s)", url)
}
fmt.Printf("Currently logged into the Pulumi Cloud%s%s\n", cmdutil.EmojiOr(" ☁️", ""), suffix)
}
})
cmd.PersistentFlags().StringVarP(&cwd, "cwd", "C", "", "Run pulumi as if it had been started in another directory")

View file

@ -39,15 +39,17 @@ func newStackCmd() *cobra.Command {
fmt.Printf("Current stack is %s:\n", s.Name())
be := s.Backend()
fmt.Printf(" Managed by %s", be.Name())
if _, isCloud := be.(cloud.Backend); isCloud {
fmt.Printf(" ☁️\n")
cloudBe, isCloud := be.(cloud.Backend)
if !isCloud || cloudBe.CloudURL() != cloud.PulumiCloudURL {
fmt.Printf(" Managed by %s\n", be.Name())
}
if isCloud {
if cs, ok := s.(cloud.Stack); ok {
fmt.Printf(" Organization %s\n", cs.OrgName())
fmt.Printf(" PPC %s\n", cs.CloudName())
fmt.Printf(" Owner: %s\n", cs.OrgName())
if !cs.RunLocally() {
fmt.Printf(" PPC: %s\n", cs.CloudName())
}
}
} else {
fmt.Printf("\n")
}
snap := s.Snapshot()
@ -55,7 +57,7 @@ func newStackCmd() *cobra.Command {
if t := snap.Manifest.Time; t.IsZero() {
fmt.Printf(" Last update time unknown\n")
} else {
fmt.Printf(" Last updated %s (%v)\n", humanize.Time(t), t)
fmt.Printf(" Last updated: %s (%v)\n", humanize.Time(t), t)
}
var cliver string
if snap.Manifest.Version == "" {
@ -63,7 +65,7 @@ func newStackCmd() *cobra.Command {
} else {
cliver = snap.Manifest.Version
}
fmt.Printf(" Pulumi version %s\n", cliver)
fmt.Printf(" Pulumi version: %s\n", cliver)
for _, plugin := range snap.Manifest.Plugins {
var plugver string
if plugin.Version == nil {
@ -71,7 +73,7 @@ func newStackCmd() *cobra.Command {
} else {
plugver = plugin.Version.String()
}
fmt.Printf(" Plugin %s [%s] version %s\n", plugin.Name, plugin.Kind, plugver)
fmt.Printf(" Plugin %s [%s] version: %s\n", plugin.Name, plugin.Kind, plugver)
}
} else {
fmt.Printf(" No updates yet; run 'pulumi update'\n")
@ -112,6 +114,15 @@ func newStackCmd() *cobra.Command {
printStackOutputs(outputs)
}
}
// Add a link to the pulumi.com console page for this stack, if it has one.
if cs, ok := s.(cloud.Stack); ok {
if consoleURL, err := cs.ConsoleURL(); err == nil {
fmt.Printf("\n")
fmt.Printf("More information at: %s\n", consoleURL)
}
}
fmt.Printf("\n")
fmt.Printf("Use `pulumi stack select` to change stack; `pulumi stack ls` lists known ones\n")

View file

@ -65,6 +65,8 @@ func newStackLsCmd() *cobra.Command {
if err != nil {
return err
}
showPPCColumn := hasAnyPPCStacks(bs)
for _, stack := range bs {
name := stack.Name().String()
stacks[name] = stack
@ -80,8 +82,16 @@ func newStackLsCmd() *cobra.Command {
}
}
fmt.Printf("%-"+strconv.Itoa(maxname)+"s %-24s %-18s %-25s\n",
"NAME", "LAST UPDATE", "RESOURCE COUNT", "CLOUD")
formatDirective := "%-" + strconv.Itoa(maxname) + "s %-24s %-18s"
headers := []interface{}{"NAME", "LAST UPDATE", "RESOURCE COUNT"}
if showPPCColumn {
formatDirective = formatDirective + " %-25s"
headers = append(headers, "PPC")
}
formatDirective = formatDirective + "\n"
fmt.Printf(formatDirective, headers...)
for _, name := range stackNames {
// Mark the name as current '*' if we've selected it.
stack := stacks[name]
@ -100,16 +110,19 @@ func newStackLsCmd() *cobra.Command {
resourceCount = strconv.Itoa(len(snap.Resources))
}
// Print out the cloud URL.
var cloudInfo string
if cs, ok := stack.(cloud.Stack); ok {
cloudInfo = fmt.Sprintf("%s:%s/%s", cs.CloudURL(), cs.OrgName(), cs.CloudName())
} else {
cloudInfo = none
values := []interface{}{name, lastUpdate, resourceCount}
if showPPCColumn {
// Print out the PPC name.
var cloudInfo string
if cs, ok := stack.(cloud.Stack); ok && !cs.RunLocally() {
cloudInfo = cs.CloudName()
} else {
cloudInfo = none
}
values = append(values, cloudInfo)
}
fmt.Printf("%-"+strconv.Itoa(maxname)+"s %-24s %-18s %-25s\n",
name, lastUpdate, resourceCount, cloudInfo)
fmt.Printf(formatDirective, values...)
}
return result
@ -120,3 +133,15 @@ func newStackLsCmd() *cobra.Command {
return cmd
}
func hasAnyPPCStacks(stacks []backend.Stack) bool {
for _, s := range stacks {
if cs, ok := s.(cloud.Stack); ok {
if !cs.RunLocally() {
return true
}
}
}
return false
}

View file

@ -122,6 +122,7 @@ type Backend interface {
ListTemplates() ([]workspace.Template, error)
CancelCurrentUpdate(stackRef backend.StackReference) error
StackConsoleURL(stackRef backend.StackReference) (string, error)
}
type cloudBackend struct {
@ -187,7 +188,23 @@ func Login(d diag.Sink, cloudURL string) (Backend, error) {
return New(d, cloudURL)
}
func (b *cloudBackend) Name() string { return b.url }
func (b *cloudBackend) StackConsoleURL(stackRef backend.StackReference) (string, error) {
stackID, err := b.getCloudStackIdentifier(stackRef)
if err != nil {
return "", err
}
return b.cloudConsoleStackPath(stackID), nil
}
func (b *cloudBackend) Name() string {
if b.url == PulumiCloudURL {
return "pulumi.com"
}
return b.url
}
func (b *cloudBackend) CloudURL() string { return b.url }
func (b *cloudBackend) ParseStackReference(s string) (backend.StackReference, error) {
@ -369,13 +386,19 @@ func (b *cloudBackend) CreateStack(stackRef backend.StackReference, opts interfa
return nil, errors.Wrap(err, "error determining initial tags")
}
stack, err := b.client.CreateStack(project, cloudOpts.CloudName, string(stackRef.StackName()), tags)
apistack, err := b.client.CreateStack(project, cloudOpts.CloudName, string(stackRef.StackName()), tags)
if err != nil {
return nil, err
}
fmt.Printf("Created stack '%s' hosted in Pulumi Cloud PPC %s\n", stackRef, stack.CloudName)
return newStack(stack, b), nil
stack := newStack(apistack, b)
fmt.Printf("Created stack '%s'", stack.Name())
if !stack.RunLocally() {
fmt.Printf(" in PPC %s", stack.CloudName())
}
fmt.Println()
return stack, nil
}
func (b *cloudBackend) ListStacks(projectFilter *tokens.PackageName) ([]backend.Stack, error) {
@ -697,8 +720,7 @@ func (b *cloudBackend) updateStack(
// Print a banner so it's clear this is going to the cloud.
actionLabel := getActionLabel(string(action), dryRun)
fmt.Printf(
colors.ColorizeText(
colors.BrightMagenta+"%s stack '%s' in the Pulumi Cloud"+colors.Reset+cmdutil.EmojiOr(" ☁️", "")+"\n"),
colors.ColorizeText(colors.BrightMagenta+"%s stack '%s'"+colors.Reset+"\n"),
actionLabel, stack.Name())
// Create an update object (except if this won't yield an update; i.e., doing a local preview).

View file

@ -5,6 +5,7 @@ package cloud
import (
"fmt"
"github.com/pkg/errors"
"github.com/pulumi/pulumi/pkg/apitype"
"github.com/pulumi/pulumi/pkg/backend"
"github.com/pulumi/pulumi/pkg/engine"
@ -19,10 +20,11 @@ import (
// Stack is a cloud stack. This simply adds some cloud-specific properties atop the standard backend stack interface.
type Stack interface {
backend.Stack
CloudURL() string // the URL to the cloud containing this stack.
OrgName() string // the organization that owns this stack.
CloudName() string // the PPC in which this stack is running.
RunLocally() bool // true if previews/updates/destroys targeting this stack run locally.
CloudURL() string // the URL to the cloud containing this stack.
OrgName() string // the organization that owns this stack.
CloudName() string // the PPC in which this stack is running.
RunLocally() bool // true if previews/updates/destroys targeting this stack run locally.
ConsoleURL() (string, error) // the URL to view the stack's information on Pulumi.com
}
// cloudStack is a cloud stack descriptor.
@ -141,3 +143,15 @@ func (s *cloudStack) ExportDeployment() (*apitype.UntypedDeployment, error) {
func (s *cloudStack) ImportDeployment(deployment *apitype.UntypedDeployment) error {
return backend.ImportStackDeployment(s, deployment)
}
func (s *cloudStack) ConsoleURL() (string, error) {
path, err := s.b.StackConsoleURL(s.Name())
if err != nil {
return "", nil
}
url := s.b.CloudConsoleURL(path)
if url == "" {
return "", errors.New("could not determine clould console URL")
}
return url, nil
}