2018-05-22 21:43:36 +02:00
|
|
|
// Copyright 2016-2018, Pulumi Corporation.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
2017-10-19 00:37:18 +02:00
|
|
|
|
2017-10-03 01:37:12 +02:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
2018-05-04 21:59:48 +02:00
|
|
|
"bytes"
|
2018-04-20 03:59:14 +02:00
|
|
|
"context"
|
2018-09-29 18:57:58 +02:00
|
|
|
"encoding/json"
|
2017-10-05 23:08:46 +02:00
|
|
|
"fmt"
|
2017-10-03 01:37:12 +02:00
|
|
|
"os"
|
2018-05-04 21:59:48 +02:00
|
|
|
"os/exec"
|
2018-04-20 03:59:14 +02:00
|
|
|
"os/signal"
|
2017-10-25 19:20:08 +02:00
|
|
|
"path/filepath"
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
"sort"
|
2018-10-02 19:49:41 +02:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
2017-10-25 19:20:08 +02:00
|
|
|
|
2018-08-03 01:15:57 +02:00
|
|
|
"github.com/golang/glog"
|
|
|
|
multierror "github.com/hashicorp/go-multierror"
|
2018-05-08 03:23:03 +02:00
|
|
|
"github.com/opentracing/opentracing-go"
|
2017-10-08 16:18:53 +02:00
|
|
|
"github.com/pkg/errors"
|
2018-04-11 19:08:32 +02:00
|
|
|
survey "gopkg.in/AlecAivazis/survey.v1"
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
surveycore "gopkg.in/AlecAivazis/survey.v1/core"
|
2018-08-03 01:15:57 +02:00
|
|
|
git "gopkg.in/src-d/go-git.v4"
|
2017-10-08 16:18:53 +02:00
|
|
|
|
Improve the overall cloud CLI experience
This improves the overall cloud CLI experience workflow.
Now whether a stack is local or cloud is inherent to the stack
itself. If you interact with a cloud stack, we transparently talk
to the cloud; if you interact with a local stack, we just do the
right thing, and perform all operations locally. Aside from sometimes
seeing a cloud emoji pop-up ☁️, the experience is quite similar.
For example, to initialize a new cloud stack, simply:
$ pulumi login
Logging into Pulumi Cloud: https://pulumi.com/
Enter Pulumi access token: <enter your token>
$ pulumi stack init my-cloud-stack
Note that you may log into a specific cloud if you'd like. For
now, this is just for our own testing purposes, but someday when we
support custom clouds (e.g., Enterprise), you can just say:
$ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873
The cloud is now the default. If you instead prefer a "fire and
forget" style of stack, you can skip the login and pass `--local`:
$ pulumi stack init my-faf-stack --local
If you are logged in and run `pulumi`, we tell you as much:
$ pulumi
Usage:
pulumi [command]
// as before...
Currently logged into the Pulumi Cloud ☁️
https://pulumi.com/
And if you list your stacks, we tell you which one is local or not:
$ pulumi stack ls
NAME LAST UPDATE RESOURCE COUNT CLOUD URL
my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/
my-faf-stack n/a 0 n/a
And `pulumi stack` by itself prints information like your cloud org,
PPC name, and so on, in addition to the usuals.
I shall write up more details and make sure to document these changes.
This change also fairly significantly refactors the layout of cloud
versus local logic, so that the cmd/ package is resonsible for CLI
things, and the new pkg/backend/ package is responsible for the
backends. The following is the overall resulting package architecture:
* The backend.Backend interface can be implemented to substitute
a new backend. This has operations to get and list stacks,
perform updates, and so on.
* The backend.Stack struct is a wrapper around a stack that has
or is being manipulated by a Backend. It resembles our existing
Stack notions in the engine, but carries additional metadata
about its source. Notably, it offers functions that allow
operations like updating and deleting on the Backend from which
it came.
* There is very little else in the pkg/backend/ package.
* A new package, pkg/backend/local/, encapsulates all local state
management for "fire and forget" scenarios. It simply implements
the above logic and contains anything specific to the local
experience.
* A peer package, pkg/backend/cloud/, encapsulates all logic
required for the cloud experience. This includes its subpackage
apitype/ which contains JSON schema descriptions required for
REST calls against the cloud backend. It also contains handy
functions to list which clouds we have authenticated with.
* A subpackage here, pkg/backend/state/, is not a provider at all.
Instead, it contains all of the state management functions that
are currently shared between local and cloud backends. This
includes configuration logic -- including encryption -- as well
as logic pertaining to which stacks are known to the workspace.
This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 16:29:46 +01:00
|
|
|
"github.com/pulumi/pulumi/pkg/backend"
|
2018-09-05 00:40:15 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/backend/display"
|
2018-09-04 21:38:58 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/backend/filestate"
|
|
|
|
"github.com/pulumi/pulumi/pkg/backend/httpstate"
|
Improve the overall cloud CLI experience
This improves the overall cloud CLI experience workflow.
Now whether a stack is local or cloud is inherent to the stack
itself. If you interact with a cloud stack, we transparently talk
to the cloud; if you interact with a local stack, we just do the
right thing, and perform all operations locally. Aside from sometimes
seeing a cloud emoji pop-up ☁️, the experience is quite similar.
For example, to initialize a new cloud stack, simply:
$ pulumi login
Logging into Pulumi Cloud: https://pulumi.com/
Enter Pulumi access token: <enter your token>
$ pulumi stack init my-cloud-stack
Note that you may log into a specific cloud if you'd like. For
now, this is just for our own testing purposes, but someday when we
support custom clouds (e.g., Enterprise), you can just say:
$ pulumi login --cloud-url https://corp.acme.my-ppc.net:9873
The cloud is now the default. If you instead prefer a "fire and
forget" style of stack, you can skip the login and pass `--local`:
$ pulumi stack init my-faf-stack --local
If you are logged in and run `pulumi`, we tell you as much:
$ pulumi
Usage:
pulumi [command]
// as before...
Currently logged into the Pulumi Cloud ☁️
https://pulumi.com/
And if you list your stacks, we tell you which one is local or not:
$ pulumi stack ls
NAME LAST UPDATE RESOURCE COUNT CLOUD URL
my-cloud-stack 2017-12-01 ... 3 https://pulumi.com/
my-faf-stack n/a 0 n/a
And `pulumi stack` by itself prints information like your cloud org,
PPC name, and so on, in addition to the usuals.
I shall write up more details and make sure to document these changes.
This change also fairly significantly refactors the layout of cloud
versus local logic, so that the cmd/ package is resonsible for CLI
things, and the new pkg/backend/ package is responsible for the
backends. The following is the overall resulting package architecture:
* The backend.Backend interface can be implemented to substitute
a new backend. This has operations to get and list stacks,
perform updates, and so on.
* The backend.Stack struct is a wrapper around a stack that has
or is being manipulated by a Backend. It resembles our existing
Stack notions in the engine, but carries additional metadata
about its source. Notably, it offers functions that allow
operations like updating and deleting on the Backend from which
it came.
* There is very little else in the pkg/backend/ package.
* A new package, pkg/backend/local/, encapsulates all local state
management for "fire and forget" scenarios. It simply implements
the above logic and contains anything specific to the local
experience.
* A peer package, pkg/backend/cloud/, encapsulates all logic
required for the cloud experience. This includes its subpackage
apitype/ which contains JSON schema descriptions required for
REST calls against the cloud backend. It also contains handy
functions to list which clouds we have authenticated with.
* A subpackage here, pkg/backend/state/, is not a provider at all.
Instead, it contains all of the state management functions that
are currently shared between local and cloud backends. This
includes configuration logic -- including encryption -- as well
as logic pertaining to which stacks are known to the workspace.
This addresses pulumi/pulumi#629 and pulumi/pulumi#494.
2017-12-02 16:29:46 +01:00
|
|
|
"github.com/pulumi/pulumi/pkg/backend/state"
|
2017-12-18 20:42:32 +01:00
|
|
|
"github.com/pulumi/pulumi/pkg/diag/colors"
|
2018-04-20 03:59:14 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/engine"
|
|
|
|
"github.com/pulumi/pulumi/pkg/util/cancel"
|
2018-10-03 01:08:03 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/util/ciutil"
|
2017-12-13 19:46:54 +01:00
|
|
|
"github.com/pulumi/pulumi/pkg/util/cmdutil"
|
2017-10-05 23:08:46 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/util/contract"
|
2018-05-22 01:17:12 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/util/gitutil"
|
2019-04-26 20:43:16 +02:00
|
|
|
"github.com/pulumi/pulumi/pkg/util/tracing"
|
2018-01-08 22:01:40 +01:00
|
|
|
"github.com/pulumi/pulumi/pkg/workspace"
|
2017-10-03 01:37:12 +02:00
|
|
|
)
|
|
|
|
|
2018-05-23 02:02:45 +02:00
|
|
|
func hasDebugCommands() bool {
|
|
|
|
return cmdutil.IsTruthy(os.Getenv("PULUMI_DEBUG_COMMANDS"))
|
|
|
|
}
|
|
|
|
|
2018-09-05 00:40:15 +02:00
|
|
|
func currentBackend(opts display.Options) (backend.Backend, error) {
|
2018-04-05 00:31:01 +02:00
|
|
|
creds, err := workspace.GetStoredCredentials()
|
2017-10-03 01:37:12 +02:00
|
|
|
if err != nil {
|
2018-04-05 00:31:01 +02:00
|
|
|
return nil, err
|
|
|
|
}
|
2019-04-25 05:55:39 +02:00
|
|
|
if filestate.IsFileStateBackendURL(creds.Current) {
|
2019-04-19 02:43:23 +02:00
|
|
|
return filestate.New(cmdutil.Diag(), creds.Current)
|
2017-10-03 01:37:12 +02:00
|
|
|
}
|
2019-04-19 02:43:23 +02:00
|
|
|
return httpstate.Login(commandContext(), cmdutil.Diag(), creds.Current, opts)
|
2018-05-08 03:23:03 +02:00
|
|
|
}
|
|
|
|
|
2018-05-14 22:44:44 +02:00
|
|
|
// This is used to control the contents of the tracing header.
|
|
|
|
var tracingHeader = os.Getenv("PULUMI_TRACING_HEADER")
|
|
|
|
|
2018-05-08 03:23:03 +02:00
|
|
|
func commandContext() context.Context {
|
|
|
|
ctx := context.Background()
|
2018-05-07 20:49:15 +02:00
|
|
|
if cmdutil.IsTracingEnabled() {
|
|
|
|
if cmdutil.TracingRootSpan != nil {
|
|
|
|
ctx = opentracing.ContextWithSpan(ctx, cmdutil.TracingRootSpan)
|
|
|
|
}
|
2018-05-14 22:44:44 +02:00
|
|
|
|
2019-04-26 20:43:16 +02:00
|
|
|
tracingOptions := tracing.Options{
|
2018-05-14 22:44:44 +02:00
|
|
|
PropagateSpans: true,
|
|
|
|
TracingHeader: tracingHeader,
|
|
|
|
}
|
2019-04-26 20:43:16 +02:00
|
|
|
ctx = tracing.ContextWithOptions(ctx, tracingOptions)
|
2018-05-08 03:23:03 +02:00
|
|
|
}
|
|
|
|
return ctx
|
2018-04-05 00:31:01 +02:00
|
|
|
}
|
|
|
|
|
Initial support for passing URLs to `new` and `up` (#1727)
* Initial support for passing URLs to `new` and `up`
This PR adds initial support for `pulumi new` using Git under the covers
to manage Pulumi templates, providing the same experience as before.
You can now also optionally pass a URL to a Git repository, e.g.
`pulumi new [<url>]`, including subdirectories within the repository,
and arbitrary branches, tags, or commits.
The following commands result in the same behavior from the user's
perspective:
- `pulumi new javascript`
- `pulumi new https://github.com/pulumi/templates/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates/javascript`
To specify an arbitrary branch, tag, or commit:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates/javascript`
Branches and tags can include '/' separators, and `pulumi` will still
find the right subdirectory.
URLs to Gists are also supported, e.g.:
`pulumi new https://gist.github.com/justinvp/6673959ceb9d2ac5a14c6d536cb871a6`
If the specified subdirectory in the repository does not contain a
`Pulumi.yaml`, it will look for subdirectories within containing
`Pulumi.yaml` files, and prompt the user to choose a template, along the
lines of how `pulumi new` behaves when no template is specified.
The following commands result in the CLI prompting to choose a template:
- `pulumi new`
- `pulumi new https://github.com/pulumi/templates/templates`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates`
Of course, arbitrary branches, tags, or commits can be specified as well:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates`
This PR also includes initial support for passing URLs to `pulumi up`,
providing a streamlined way to deploy installable cloud applications
with Pulumi, without having to manage source code locally before doing
a deployment.
For example, `pulumi up https://github.com/justinvp/aws` can be used to
deploy a sample AWS app. The stack can be updated with different
versions, e.g.
`pulumi up https://github.com/justinvp/aws/tree/v2 -s <stack-to-update>`
Config values can optionally be passed via command line flags, e.g.
`pulumi up https://github.com/justinvp/aws -c aws:region=us-west-2 -c foo:bar=blah`
Gists can also be used, e.g.
`pulumi up https://gist.github.com/justinvp/62fde0463f243fcb49f5a7222e51bc76`
* Fix panic when hitting ^C from "choose template" prompt
* Add description to templates
When running `pulumi new` without specifying a template, include the template description along with the name in the "choose template" display.
```
$ pulumi new
Please choose a template:
aws-go A minimal AWS Go program
aws-javascript A minimal AWS JavaScript program
aws-python A minimal AWS Python program
aws-typescript A minimal AWS TypeScript program
> go A minimal Go program
hello-aws-javascript A simple AWS serverless JavaScript program
javascript A minimal JavaScript program
python A minimal Python program
typescript A minimal TypeScript program
```
* React to changes to the pulumi/templates repo.
We restructured the `pulumi/templates` repo to have all the templates in the root instead of in a `templates` subdirectory, so make the change here to no longer look for templates in `templates`.
This also fixes an issue around using `Depth: 1` that I found while testing this. When a named template is used, we attempt to clone or pull from the `pulumi/templates` repo to `~/.pulumi/templates`. Having it go in this well-known directory allows us to maintain previous behavior around allowing offline use of templates. If we use `Depth: 1` for the initial clone, it will fail when attempting to pull when there are updates to the remote repository. Unfortunately, there's no built-in `--unshallow` support in `go-git` and setting a larger `Depth` doesn't appear to help. There may be a workaround, but for now, if we're cloning the pulumi templates directory to `~/.pulumi/templates`, we won't use `Depth: 1`. For template URLs, we will continue to use `Depth: 1` as we clone those to a temp directory (which gets deleted) that we'll never try to update.
* List available templates in help text
* Address PR Feedback
* Don't show "Installing dependencies" message for `up`
* Fix secrets handling
When prompting for config, if the existing stack value is a secret, keep it a secret and mask the prompt. If the template says it should be secret, make it a secret.
* Fix ${PROJECT} and ${DESCRIPTION} handling for `up`
Templates used with `up` should already have a filled-in project name and description, but if it's a `new`-style template, that has `${PROJECT}` and/or `${DESCRIPTION}`, be helpful and just replace these with better values.
* Fix stack handling
Add a bool `setCurrent` param to `requireStack` to control whether the current stack should be saved in workspace settings. For the `up <url>` case, we don't want to save. Also, split the `up` code into two separate functions: one for the `up <url>` case and another for the normal `up` case where you have workspace in your current directory. While we may be able to combine them back into a single function, right now it's a bit cleaner being separate, even with some small amount of duplication.
* Fix panic due to nil crypter
Lazily get the crypter only if needed inside `promptForConfig`.
* Embellish comment
* Harden isPreconfiguredEmptyStack check
Fix the code to check to make sure the URL specified on the command line matches the URL stored in the `pulumi:template` config value, and that the rest of the config from the stack satisfies the config requirements of the template.
2018-08-11 03:08:16 +02:00
|
|
|
// createStack creates a stack with the given name, and optionally selects it as the current.
|
|
|
|
func createStack(
|
2019-05-07 01:01:47 +02:00
|
|
|
b backend.Backend, stackRef backend.StackReference, opts interface{}, setCurrent bool,
|
|
|
|
secretsProvider string) (backend.Stack, error) {
|
|
|
|
|
|
|
|
if secretsProvider != "" && secretsProvider != "passphrase" {
|
|
|
|
return nil, errors.Errorf("unknown secrets provider type '%s'", secretsProvider)
|
|
|
|
}
|
|
|
|
|
|
|
|
// As part of creating the stack, we also need to configure the secrets provider for the stack. Today, we only
|
|
|
|
// have to do this configuration step when you are using the passpharse provider (which is used for all filestate,
|
|
|
|
// stacks and well as httpstate stacks that opted into this by passing --secrets-provider passphrase
|
|
|
|
// while initialing a stack). The only other supported provider today (the provider that uses the pulumi service
|
|
|
|
// does not need to be initialized explicitly, as creating the stack inside the Pulumi service does this).
|
|
|
|
if _, ok := b.(filestate.Backend); ok || secretsProvider == "passphrase" {
|
|
|
|
if _, pharseErr := newPassphraseSecretsManager(stackRef.Name(), stackConfigFile); pharseErr != nil {
|
|
|
|
return nil, pharseErr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-08 03:23:03 +02:00
|
|
|
stack, err := b.CreateStack(commandContext(), stackRef, opts)
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
if err != nil {
|
2018-05-08 00:31:27 +02:00
|
|
|
// If it's a StackAlreadyExistsError, don't wrap it.
|
|
|
|
if _, ok := err.(*backend.StackAlreadyExistsError); ok {
|
|
|
|
return nil, err
|
|
|
|
}
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
return nil, errors.Wrapf(err, "could not create stack")
|
|
|
|
}
|
|
|
|
|
Initial support for passing URLs to `new` and `up` (#1727)
* Initial support for passing URLs to `new` and `up`
This PR adds initial support for `pulumi new` using Git under the covers
to manage Pulumi templates, providing the same experience as before.
You can now also optionally pass a URL to a Git repository, e.g.
`pulumi new [<url>]`, including subdirectories within the repository,
and arbitrary branches, tags, or commits.
The following commands result in the same behavior from the user's
perspective:
- `pulumi new javascript`
- `pulumi new https://github.com/pulumi/templates/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates/javascript`
To specify an arbitrary branch, tag, or commit:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates/javascript`
Branches and tags can include '/' separators, and `pulumi` will still
find the right subdirectory.
URLs to Gists are also supported, e.g.:
`pulumi new https://gist.github.com/justinvp/6673959ceb9d2ac5a14c6d536cb871a6`
If the specified subdirectory in the repository does not contain a
`Pulumi.yaml`, it will look for subdirectories within containing
`Pulumi.yaml` files, and prompt the user to choose a template, along the
lines of how `pulumi new` behaves when no template is specified.
The following commands result in the CLI prompting to choose a template:
- `pulumi new`
- `pulumi new https://github.com/pulumi/templates/templates`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates`
Of course, arbitrary branches, tags, or commits can be specified as well:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates`
This PR also includes initial support for passing URLs to `pulumi up`,
providing a streamlined way to deploy installable cloud applications
with Pulumi, without having to manage source code locally before doing
a deployment.
For example, `pulumi up https://github.com/justinvp/aws` can be used to
deploy a sample AWS app. The stack can be updated with different
versions, e.g.
`pulumi up https://github.com/justinvp/aws/tree/v2 -s <stack-to-update>`
Config values can optionally be passed via command line flags, e.g.
`pulumi up https://github.com/justinvp/aws -c aws:region=us-west-2 -c foo:bar=blah`
Gists can also be used, e.g.
`pulumi up https://gist.github.com/justinvp/62fde0463f243fcb49f5a7222e51bc76`
* Fix panic when hitting ^C from "choose template" prompt
* Add description to templates
When running `pulumi new` without specifying a template, include the template description along with the name in the "choose template" display.
```
$ pulumi new
Please choose a template:
aws-go A minimal AWS Go program
aws-javascript A minimal AWS JavaScript program
aws-python A minimal AWS Python program
aws-typescript A minimal AWS TypeScript program
> go A minimal Go program
hello-aws-javascript A simple AWS serverless JavaScript program
javascript A minimal JavaScript program
python A minimal Python program
typescript A minimal TypeScript program
```
* React to changes to the pulumi/templates repo.
We restructured the `pulumi/templates` repo to have all the templates in the root instead of in a `templates` subdirectory, so make the change here to no longer look for templates in `templates`.
This also fixes an issue around using `Depth: 1` that I found while testing this. When a named template is used, we attempt to clone or pull from the `pulumi/templates` repo to `~/.pulumi/templates`. Having it go in this well-known directory allows us to maintain previous behavior around allowing offline use of templates. If we use `Depth: 1` for the initial clone, it will fail when attempting to pull when there are updates to the remote repository. Unfortunately, there's no built-in `--unshallow` support in `go-git` and setting a larger `Depth` doesn't appear to help. There may be a workaround, but for now, if we're cloning the pulumi templates directory to `~/.pulumi/templates`, we won't use `Depth: 1`. For template URLs, we will continue to use `Depth: 1` as we clone those to a temp directory (which gets deleted) that we'll never try to update.
* List available templates in help text
* Address PR Feedback
* Don't show "Installing dependencies" message for `up`
* Fix secrets handling
When prompting for config, if the existing stack value is a secret, keep it a secret and mask the prompt. If the template says it should be secret, make it a secret.
* Fix ${PROJECT} and ${DESCRIPTION} handling for `up`
Templates used with `up` should already have a filled-in project name and description, but if it's a `new`-style template, that has `${PROJECT}` and/or `${DESCRIPTION}`, be helpful and just replace these with better values.
* Fix stack handling
Add a bool `setCurrent` param to `requireStack` to control whether the current stack should be saved in workspace settings. For the `up <url>` case, we don't want to save. Also, split the `up` code into two separate functions: one for the `up <url>` case and another for the normal `up` case where you have workspace in your current directory. While we may be able to combine them back into a single function, right now it's a bit cleaner being separate, even with some small amount of duplication.
* Fix panic due to nil crypter
Lazily get the crypter only if needed inside `promptForConfig`.
* Embellish comment
* Harden isPreconfiguredEmptyStack check
Fix the code to check to make sure the URL specified on the command line matches the URL stored in the `pulumi:template` config value, and that the rest of the config from the stack satisfies the config requirements of the template.
2018-08-11 03:08:16 +02:00
|
|
|
if setCurrent {
|
2018-09-05 16:20:25 +02:00
|
|
|
if err = state.SetCurrentStack(stack.Ref().String()); err != nil {
|
Initial support for passing URLs to `new` and `up` (#1727)
* Initial support for passing URLs to `new` and `up`
This PR adds initial support for `pulumi new` using Git under the covers
to manage Pulumi templates, providing the same experience as before.
You can now also optionally pass a URL to a Git repository, e.g.
`pulumi new [<url>]`, including subdirectories within the repository,
and arbitrary branches, tags, or commits.
The following commands result in the same behavior from the user's
perspective:
- `pulumi new javascript`
- `pulumi new https://github.com/pulumi/templates/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates/javascript`
To specify an arbitrary branch, tag, or commit:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates/javascript`
Branches and tags can include '/' separators, and `pulumi` will still
find the right subdirectory.
URLs to Gists are also supported, e.g.:
`pulumi new https://gist.github.com/justinvp/6673959ceb9d2ac5a14c6d536cb871a6`
If the specified subdirectory in the repository does not contain a
`Pulumi.yaml`, it will look for subdirectories within containing
`Pulumi.yaml` files, and prompt the user to choose a template, along the
lines of how `pulumi new` behaves when no template is specified.
The following commands result in the CLI prompting to choose a template:
- `pulumi new`
- `pulumi new https://github.com/pulumi/templates/templates`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates`
Of course, arbitrary branches, tags, or commits can be specified as well:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates`
This PR also includes initial support for passing URLs to `pulumi up`,
providing a streamlined way to deploy installable cloud applications
with Pulumi, without having to manage source code locally before doing
a deployment.
For example, `pulumi up https://github.com/justinvp/aws` can be used to
deploy a sample AWS app. The stack can be updated with different
versions, e.g.
`pulumi up https://github.com/justinvp/aws/tree/v2 -s <stack-to-update>`
Config values can optionally be passed via command line flags, e.g.
`pulumi up https://github.com/justinvp/aws -c aws:region=us-west-2 -c foo:bar=blah`
Gists can also be used, e.g.
`pulumi up https://gist.github.com/justinvp/62fde0463f243fcb49f5a7222e51bc76`
* Fix panic when hitting ^C from "choose template" prompt
* Add description to templates
When running `pulumi new` without specifying a template, include the template description along with the name in the "choose template" display.
```
$ pulumi new
Please choose a template:
aws-go A minimal AWS Go program
aws-javascript A minimal AWS JavaScript program
aws-python A minimal AWS Python program
aws-typescript A minimal AWS TypeScript program
> go A minimal Go program
hello-aws-javascript A simple AWS serverless JavaScript program
javascript A minimal JavaScript program
python A minimal Python program
typescript A minimal TypeScript program
```
* React to changes to the pulumi/templates repo.
We restructured the `pulumi/templates` repo to have all the templates in the root instead of in a `templates` subdirectory, so make the change here to no longer look for templates in `templates`.
This also fixes an issue around using `Depth: 1` that I found while testing this. When a named template is used, we attempt to clone or pull from the `pulumi/templates` repo to `~/.pulumi/templates`. Having it go in this well-known directory allows us to maintain previous behavior around allowing offline use of templates. If we use `Depth: 1` for the initial clone, it will fail when attempting to pull when there are updates to the remote repository. Unfortunately, there's no built-in `--unshallow` support in `go-git` and setting a larger `Depth` doesn't appear to help. There may be a workaround, but for now, if we're cloning the pulumi templates directory to `~/.pulumi/templates`, we won't use `Depth: 1`. For template URLs, we will continue to use `Depth: 1` as we clone those to a temp directory (which gets deleted) that we'll never try to update.
* List available templates in help text
* Address PR Feedback
* Don't show "Installing dependencies" message for `up`
* Fix secrets handling
When prompting for config, if the existing stack value is a secret, keep it a secret and mask the prompt. If the template says it should be secret, make it a secret.
* Fix ${PROJECT} and ${DESCRIPTION} handling for `up`
Templates used with `up` should already have a filled-in project name and description, but if it's a `new`-style template, that has `${PROJECT}` and/or `${DESCRIPTION}`, be helpful and just replace these with better values.
* Fix stack handling
Add a bool `setCurrent` param to `requireStack` to control whether the current stack should be saved in workspace settings. For the `up <url>` case, we don't want to save. Also, split the `up` code into two separate functions: one for the `up <url>` case and another for the normal `up` case where you have workspace in your current directory. While we may be able to combine them back into a single function, right now it's a bit cleaner being separate, even with some small amount of duplication.
* Fix panic due to nil crypter
Lazily get the crypter only if needed inside `promptForConfig`.
* Embellish comment
* Harden isPreconfiguredEmptyStack check
Fix the code to check to make sure the URL specified on the command line matches the URL stored in the `pulumi:template` config value, and that the rest of the config from the stack satisfies the config requirements of the template.
2018-08-11 03:08:16 +02:00
|
|
|
return nil, err
|
|
|
|
}
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return stack, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// requireStack will require that a stack exists. If stackName is blank, the currently selected stack from
|
|
|
|
// the workspace is returned. If no stack with either the given name, or a currently selected stack, exists,
|
|
|
|
// and we are in an interactive terminal, the user will be prompted to create a new stack.
|
Initial support for passing URLs to `new` and `up` (#1727)
* Initial support for passing URLs to `new` and `up`
This PR adds initial support for `pulumi new` using Git under the covers
to manage Pulumi templates, providing the same experience as before.
You can now also optionally pass a URL to a Git repository, e.g.
`pulumi new [<url>]`, including subdirectories within the repository,
and arbitrary branches, tags, or commits.
The following commands result in the same behavior from the user's
perspective:
- `pulumi new javascript`
- `pulumi new https://github.com/pulumi/templates/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates/javascript`
To specify an arbitrary branch, tag, or commit:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates/javascript`
Branches and tags can include '/' separators, and `pulumi` will still
find the right subdirectory.
URLs to Gists are also supported, e.g.:
`pulumi new https://gist.github.com/justinvp/6673959ceb9d2ac5a14c6d536cb871a6`
If the specified subdirectory in the repository does not contain a
`Pulumi.yaml`, it will look for subdirectories within containing
`Pulumi.yaml` files, and prompt the user to choose a template, along the
lines of how `pulumi new` behaves when no template is specified.
The following commands result in the CLI prompting to choose a template:
- `pulumi new`
- `pulumi new https://github.com/pulumi/templates/templates`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates`
Of course, arbitrary branches, tags, or commits can be specified as well:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates`
This PR also includes initial support for passing URLs to `pulumi up`,
providing a streamlined way to deploy installable cloud applications
with Pulumi, without having to manage source code locally before doing
a deployment.
For example, `pulumi up https://github.com/justinvp/aws` can be used to
deploy a sample AWS app. The stack can be updated with different
versions, e.g.
`pulumi up https://github.com/justinvp/aws/tree/v2 -s <stack-to-update>`
Config values can optionally be passed via command line flags, e.g.
`pulumi up https://github.com/justinvp/aws -c aws:region=us-west-2 -c foo:bar=blah`
Gists can also be used, e.g.
`pulumi up https://gist.github.com/justinvp/62fde0463f243fcb49f5a7222e51bc76`
* Fix panic when hitting ^C from "choose template" prompt
* Add description to templates
When running `pulumi new` without specifying a template, include the template description along with the name in the "choose template" display.
```
$ pulumi new
Please choose a template:
aws-go A minimal AWS Go program
aws-javascript A minimal AWS JavaScript program
aws-python A minimal AWS Python program
aws-typescript A minimal AWS TypeScript program
> go A minimal Go program
hello-aws-javascript A simple AWS serverless JavaScript program
javascript A minimal JavaScript program
python A minimal Python program
typescript A minimal TypeScript program
```
* React to changes to the pulumi/templates repo.
We restructured the `pulumi/templates` repo to have all the templates in the root instead of in a `templates` subdirectory, so make the change here to no longer look for templates in `templates`.
This also fixes an issue around using `Depth: 1` that I found while testing this. When a named template is used, we attempt to clone or pull from the `pulumi/templates` repo to `~/.pulumi/templates`. Having it go in this well-known directory allows us to maintain previous behavior around allowing offline use of templates. If we use `Depth: 1` for the initial clone, it will fail when attempting to pull when there are updates to the remote repository. Unfortunately, there's no built-in `--unshallow` support in `go-git` and setting a larger `Depth` doesn't appear to help. There may be a workaround, but for now, if we're cloning the pulumi templates directory to `~/.pulumi/templates`, we won't use `Depth: 1`. For template URLs, we will continue to use `Depth: 1` as we clone those to a temp directory (which gets deleted) that we'll never try to update.
* List available templates in help text
* Address PR Feedback
* Don't show "Installing dependencies" message for `up`
* Fix secrets handling
When prompting for config, if the existing stack value is a secret, keep it a secret and mask the prompt. If the template says it should be secret, make it a secret.
* Fix ${PROJECT} and ${DESCRIPTION} handling for `up`
Templates used with `up` should already have a filled-in project name and description, but if it's a `new`-style template, that has `${PROJECT}` and/or `${DESCRIPTION}`, be helpful and just replace these with better values.
* Fix stack handling
Add a bool `setCurrent` param to `requireStack` to control whether the current stack should be saved in workspace settings. For the `up <url>` case, we don't want to save. Also, split the `up` code into two separate functions: one for the `up <url>` case and another for the normal `up` case where you have workspace in your current directory. While we may be able to combine them back into a single function, right now it's a bit cleaner being separate, even with some small amount of duplication.
* Fix panic due to nil crypter
Lazily get the crypter only if needed inside `promptForConfig`.
* Embellish comment
* Harden isPreconfiguredEmptyStack check
Fix the code to check to make sure the URL specified on the command line matches the URL stored in the `pulumi:template` config value, and that the rest of the config from the stack satisfies the config requirements of the template.
2018-08-11 03:08:16 +02:00
|
|
|
func requireStack(
|
2018-09-05 00:40:15 +02:00
|
|
|
stackName string, offerNew bool, opts display.Options, setCurrent bool) (backend.Stack, error) {
|
2017-11-01 22:55:16 +01:00
|
|
|
if stackName == "" {
|
Initial support for passing URLs to `new` and `up` (#1727)
* Initial support for passing URLs to `new` and `up`
This PR adds initial support for `pulumi new` using Git under the covers
to manage Pulumi templates, providing the same experience as before.
You can now also optionally pass a URL to a Git repository, e.g.
`pulumi new [<url>]`, including subdirectories within the repository,
and arbitrary branches, tags, or commits.
The following commands result in the same behavior from the user's
perspective:
- `pulumi new javascript`
- `pulumi new https://github.com/pulumi/templates/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates/javascript`
To specify an arbitrary branch, tag, or commit:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates/javascript`
Branches and tags can include '/' separators, and `pulumi` will still
find the right subdirectory.
URLs to Gists are also supported, e.g.:
`pulumi new https://gist.github.com/justinvp/6673959ceb9d2ac5a14c6d536cb871a6`
If the specified subdirectory in the repository does not contain a
`Pulumi.yaml`, it will look for subdirectories within containing
`Pulumi.yaml` files, and prompt the user to choose a template, along the
lines of how `pulumi new` behaves when no template is specified.
The following commands result in the CLI prompting to choose a template:
- `pulumi new`
- `pulumi new https://github.com/pulumi/templates/templates`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates`
Of course, arbitrary branches, tags, or commits can be specified as well:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates`
This PR also includes initial support for passing URLs to `pulumi up`,
providing a streamlined way to deploy installable cloud applications
with Pulumi, without having to manage source code locally before doing
a deployment.
For example, `pulumi up https://github.com/justinvp/aws` can be used to
deploy a sample AWS app. The stack can be updated with different
versions, e.g.
`pulumi up https://github.com/justinvp/aws/tree/v2 -s <stack-to-update>`
Config values can optionally be passed via command line flags, e.g.
`pulumi up https://github.com/justinvp/aws -c aws:region=us-west-2 -c foo:bar=blah`
Gists can also be used, e.g.
`pulumi up https://gist.github.com/justinvp/62fde0463f243fcb49f5a7222e51bc76`
* Fix panic when hitting ^C from "choose template" prompt
* Add description to templates
When running `pulumi new` without specifying a template, include the template description along with the name in the "choose template" display.
```
$ pulumi new
Please choose a template:
aws-go A minimal AWS Go program
aws-javascript A minimal AWS JavaScript program
aws-python A minimal AWS Python program
aws-typescript A minimal AWS TypeScript program
> go A minimal Go program
hello-aws-javascript A simple AWS serverless JavaScript program
javascript A minimal JavaScript program
python A minimal Python program
typescript A minimal TypeScript program
```
* React to changes to the pulumi/templates repo.
We restructured the `pulumi/templates` repo to have all the templates in the root instead of in a `templates` subdirectory, so make the change here to no longer look for templates in `templates`.
This also fixes an issue around using `Depth: 1` that I found while testing this. When a named template is used, we attempt to clone or pull from the `pulumi/templates` repo to `~/.pulumi/templates`. Having it go in this well-known directory allows us to maintain previous behavior around allowing offline use of templates. If we use `Depth: 1` for the initial clone, it will fail when attempting to pull when there are updates to the remote repository. Unfortunately, there's no built-in `--unshallow` support in `go-git` and setting a larger `Depth` doesn't appear to help. There may be a workaround, but for now, if we're cloning the pulumi templates directory to `~/.pulumi/templates`, we won't use `Depth: 1`. For template URLs, we will continue to use `Depth: 1` as we clone those to a temp directory (which gets deleted) that we'll never try to update.
* List available templates in help text
* Address PR Feedback
* Don't show "Installing dependencies" message for `up`
* Fix secrets handling
When prompting for config, if the existing stack value is a secret, keep it a secret and mask the prompt. If the template says it should be secret, make it a secret.
* Fix ${PROJECT} and ${DESCRIPTION} handling for `up`
Templates used with `up` should already have a filled-in project name and description, but if it's a `new`-style template, that has `${PROJECT}` and/or `${DESCRIPTION}`, be helpful and just replace these with better values.
* Fix stack handling
Add a bool `setCurrent` param to `requireStack` to control whether the current stack should be saved in workspace settings. For the `up <url>` case, we don't want to save. Also, split the `up` code into two separate functions: one for the `up <url>` case and another for the normal `up` case where you have workspace in your current directory. While we may be able to combine them back into a single function, right now it's a bit cleaner being separate, even with some small amount of duplication.
* Fix panic due to nil crypter
Lazily get the crypter only if needed inside `promptForConfig`.
* Embellish comment
* Harden isPreconfiguredEmptyStack check
Fix the code to check to make sure the URL specified on the command line matches the URL stored in the `pulumi:template` config value, and that the rest of the config from the stack satisfies the config requirements of the template.
2018-08-11 03:08:16 +02:00
|
|
|
return requireCurrentStack(offerNew, opts, setCurrent)
|
2017-11-01 22:55:16 +01:00
|
|
|
}
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
|
2018-07-07 06:30:00 +02:00
|
|
|
b, err := currentBackend(opts)
|
2018-04-05 00:31:01 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2018-04-18 01:37:52 +02:00
|
|
|
|
2018-04-20 08:16:07 +02:00
|
|
|
stackRef, err := b.ParseStackReference(stackName)
|
2018-04-18 01:37:52 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-05-08 03:23:03 +02:00
|
|
|
stack, err := b.GetStack(commandContext(), stackRef)
|
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
|
|
|
}
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
if stack != nil {
|
|
|
|
return stack, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// No stack was found. If we're in a terminal, prompt to create one.
|
2018-04-14 19:01:39 +02:00
|
|
|
if offerNew && cmdutil.Interactive() {
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
fmt.Printf("The stack '%s' does not exist.\n", stackName)
|
|
|
|
fmt.Printf("\n")
|
2018-04-05 00:31:01 +02:00
|
|
|
_, err = cmdutil.ReadConsole("If you would like to create this stack now, please press <ENTER>, otherwise " +
|
|
|
|
"press ^C")
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-05-07 01:01:47 +02:00
|
|
|
return createStack(b, stackRef, nil, setCurrent, "")
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
}
|
|
|
|
|
2018-04-14 19:01:39 +02:00
|
|
|
return nil, errors.Errorf("no stack named '%s' found", stackName)
|
2017-10-19 00:37:18 +02:00
|
|
|
}
|
|
|
|
|
2018-09-05 00:40:15 +02:00
|
|
|
func requireCurrentStack(offerNew bool, opts display.Options, setCurrent bool) (backend.Stack, error) {
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
// Search for the current stack.
|
2018-07-07 06:30:00 +02:00
|
|
|
b, err := currentBackend(opts)
|
2018-04-05 00:31:01 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2018-05-08 03:23:03 +02:00
|
|
|
stack, err := state.CurrentStack(commandContext(), b)
|
2017-10-19 00:37:18 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
} else if stack != nil {
|
|
|
|
return stack, nil
|
2017-10-19 00:37:18 +02:00
|
|
|
}
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
|
|
|
|
// If no current stack exists, and we are interactive, prompt to select or create one.
|
Initial support for passing URLs to `new` and `up` (#1727)
* Initial support for passing URLs to `new` and `up`
This PR adds initial support for `pulumi new` using Git under the covers
to manage Pulumi templates, providing the same experience as before.
You can now also optionally pass a URL to a Git repository, e.g.
`pulumi new [<url>]`, including subdirectories within the repository,
and arbitrary branches, tags, or commits.
The following commands result in the same behavior from the user's
perspective:
- `pulumi new javascript`
- `pulumi new https://github.com/pulumi/templates/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates/javascript`
To specify an arbitrary branch, tag, or commit:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates/javascript`
Branches and tags can include '/' separators, and `pulumi` will still
find the right subdirectory.
URLs to Gists are also supported, e.g.:
`pulumi new https://gist.github.com/justinvp/6673959ceb9d2ac5a14c6d536cb871a6`
If the specified subdirectory in the repository does not contain a
`Pulumi.yaml`, it will look for subdirectories within containing
`Pulumi.yaml` files, and prompt the user to choose a template, along the
lines of how `pulumi new` behaves when no template is specified.
The following commands result in the CLI prompting to choose a template:
- `pulumi new`
- `pulumi new https://github.com/pulumi/templates/templates`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates`
Of course, arbitrary branches, tags, or commits can be specified as well:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates`
This PR also includes initial support for passing URLs to `pulumi up`,
providing a streamlined way to deploy installable cloud applications
with Pulumi, without having to manage source code locally before doing
a deployment.
For example, `pulumi up https://github.com/justinvp/aws` can be used to
deploy a sample AWS app. The stack can be updated with different
versions, e.g.
`pulumi up https://github.com/justinvp/aws/tree/v2 -s <stack-to-update>`
Config values can optionally be passed via command line flags, e.g.
`pulumi up https://github.com/justinvp/aws -c aws:region=us-west-2 -c foo:bar=blah`
Gists can also be used, e.g.
`pulumi up https://gist.github.com/justinvp/62fde0463f243fcb49f5a7222e51bc76`
* Fix panic when hitting ^C from "choose template" prompt
* Add description to templates
When running `pulumi new` without specifying a template, include the template description along with the name in the "choose template" display.
```
$ pulumi new
Please choose a template:
aws-go A minimal AWS Go program
aws-javascript A minimal AWS JavaScript program
aws-python A minimal AWS Python program
aws-typescript A minimal AWS TypeScript program
> go A minimal Go program
hello-aws-javascript A simple AWS serverless JavaScript program
javascript A minimal JavaScript program
python A minimal Python program
typescript A minimal TypeScript program
```
* React to changes to the pulumi/templates repo.
We restructured the `pulumi/templates` repo to have all the templates in the root instead of in a `templates` subdirectory, so make the change here to no longer look for templates in `templates`.
This also fixes an issue around using `Depth: 1` that I found while testing this. When a named template is used, we attempt to clone or pull from the `pulumi/templates` repo to `~/.pulumi/templates`. Having it go in this well-known directory allows us to maintain previous behavior around allowing offline use of templates. If we use `Depth: 1` for the initial clone, it will fail when attempting to pull when there are updates to the remote repository. Unfortunately, there's no built-in `--unshallow` support in `go-git` and setting a larger `Depth` doesn't appear to help. There may be a workaround, but for now, if we're cloning the pulumi templates directory to `~/.pulumi/templates`, we won't use `Depth: 1`. For template URLs, we will continue to use `Depth: 1` as we clone those to a temp directory (which gets deleted) that we'll never try to update.
* List available templates in help text
* Address PR Feedback
* Don't show "Installing dependencies" message for `up`
* Fix secrets handling
When prompting for config, if the existing stack value is a secret, keep it a secret and mask the prompt. If the template says it should be secret, make it a secret.
* Fix ${PROJECT} and ${DESCRIPTION} handling for `up`
Templates used with `up` should already have a filled-in project name and description, but if it's a `new`-style template, that has `${PROJECT}` and/or `${DESCRIPTION}`, be helpful and just replace these with better values.
* Fix stack handling
Add a bool `setCurrent` param to `requireStack` to control whether the current stack should be saved in workspace settings. For the `up <url>` case, we don't want to save. Also, split the `up` code into two separate functions: one for the `up <url>` case and another for the normal `up` case where you have workspace in your current directory. While we may be able to combine them back into a single function, right now it's a bit cleaner being separate, even with some small amount of duplication.
* Fix panic due to nil crypter
Lazily get the crypter only if needed inside `promptForConfig`.
* Embellish comment
* Harden isPreconfiguredEmptyStack check
Fix the code to check to make sure the URL specified on the command line matches the URL stored in the `pulumi:template` config value, and that the rest of the config from the stack satisfies the config requirements of the template.
2018-08-11 03:08:16 +02:00
|
|
|
return chooseStack(b, offerNew, opts, setCurrent)
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
}
|
|
|
|
|
2018-09-14 05:54:42 +02:00
|
|
|
// chooseStack will prompt the user to choose amongst the full set of stacks in the given backend. If offerNew is
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
// true, then the option to create an entirely new stack is provided and will create one as desired.
|
Initial support for passing URLs to `new` and `up` (#1727)
* Initial support for passing URLs to `new` and `up`
This PR adds initial support for `pulumi new` using Git under the covers
to manage Pulumi templates, providing the same experience as before.
You can now also optionally pass a URL to a Git repository, e.g.
`pulumi new [<url>]`, including subdirectories within the repository,
and arbitrary branches, tags, or commits.
The following commands result in the same behavior from the user's
perspective:
- `pulumi new javascript`
- `pulumi new https://github.com/pulumi/templates/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates/javascript`
To specify an arbitrary branch, tag, or commit:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates/javascript`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates/javascript`
Branches and tags can include '/' separators, and `pulumi` will still
find the right subdirectory.
URLs to Gists are also supported, e.g.:
`pulumi new https://gist.github.com/justinvp/6673959ceb9d2ac5a14c6d536cb871a6`
If the specified subdirectory in the repository does not contain a
`Pulumi.yaml`, it will look for subdirectories within containing
`Pulumi.yaml` files, and prompt the user to choose a template, along the
lines of how `pulumi new` behaves when no template is specified.
The following commands result in the CLI prompting to choose a template:
- `pulumi new`
- `pulumi new https://github.com/pulumi/templates/templates`
- `pulumi new https://github.com/pulumi/templates/tree/master/templates`
- `pulumi new https://github.com/pulumi/templates/tree/HEAD/templates`
Of course, arbitrary branches, tags, or commits can be specified as well:
- `pulumi new https://github.com/pulumi/templates/tree/<branch>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<tag>/templates`
- `pulumi new https://github.com/pulumi/templates/tree/<commit>/templates`
This PR also includes initial support for passing URLs to `pulumi up`,
providing a streamlined way to deploy installable cloud applications
with Pulumi, without having to manage source code locally before doing
a deployment.
For example, `pulumi up https://github.com/justinvp/aws` can be used to
deploy a sample AWS app. The stack can be updated with different
versions, e.g.
`pulumi up https://github.com/justinvp/aws/tree/v2 -s <stack-to-update>`
Config values can optionally be passed via command line flags, e.g.
`pulumi up https://github.com/justinvp/aws -c aws:region=us-west-2 -c foo:bar=blah`
Gists can also be used, e.g.
`pulumi up https://gist.github.com/justinvp/62fde0463f243fcb49f5a7222e51bc76`
* Fix panic when hitting ^C from "choose template" prompt
* Add description to templates
When running `pulumi new` without specifying a template, include the template description along with the name in the "choose template" display.
```
$ pulumi new
Please choose a template:
aws-go A minimal AWS Go program
aws-javascript A minimal AWS JavaScript program
aws-python A minimal AWS Python program
aws-typescript A minimal AWS TypeScript program
> go A minimal Go program
hello-aws-javascript A simple AWS serverless JavaScript program
javascript A minimal JavaScript program
python A minimal Python program
typescript A minimal TypeScript program
```
* React to changes to the pulumi/templates repo.
We restructured the `pulumi/templates` repo to have all the templates in the root instead of in a `templates` subdirectory, so make the change here to no longer look for templates in `templates`.
This also fixes an issue around using `Depth: 1` that I found while testing this. When a named template is used, we attempt to clone or pull from the `pulumi/templates` repo to `~/.pulumi/templates`. Having it go in this well-known directory allows us to maintain previous behavior around allowing offline use of templates. If we use `Depth: 1` for the initial clone, it will fail when attempting to pull when there are updates to the remote repository. Unfortunately, there's no built-in `--unshallow` support in `go-git` and setting a larger `Depth` doesn't appear to help. There may be a workaround, but for now, if we're cloning the pulumi templates directory to `~/.pulumi/templates`, we won't use `Depth: 1`. For template URLs, we will continue to use `Depth: 1` as we clone those to a temp directory (which gets deleted) that we'll never try to update.
* List available templates in help text
* Address PR Feedback
* Don't show "Installing dependencies" message for `up`
* Fix secrets handling
When prompting for config, if the existing stack value is a secret, keep it a secret and mask the prompt. If the template says it should be secret, make it a secret.
* Fix ${PROJECT} and ${DESCRIPTION} handling for `up`
Templates used with `up` should already have a filled-in project name and description, but if it's a `new`-style template, that has `${PROJECT}` and/or `${DESCRIPTION}`, be helpful and just replace these with better values.
* Fix stack handling
Add a bool `setCurrent` param to `requireStack` to control whether the current stack should be saved in workspace settings. For the `up <url>` case, we don't want to save. Also, split the `up` code into two separate functions: one for the `up <url>` case and another for the normal `up` case where you have workspace in your current directory. While we may be able to combine them back into a single function, right now it's a bit cleaner being separate, even with some small amount of duplication.
* Fix panic due to nil crypter
Lazily get the crypter only if needed inside `promptForConfig`.
* Embellish comment
* Harden isPreconfiguredEmptyStack check
Fix the code to check to make sure the URL specified on the command line matches the URL stored in the `pulumi:template` config value, and that the rest of the config from the stack satisfies the config requirements of the template.
2018-08-11 03:08:16 +02:00
|
|
|
func chooseStack(
|
2018-09-05 00:40:15 +02:00
|
|
|
b backend.Backend, offerNew bool, opts display.Options, setCurrent bool) (backend.Stack, error) {
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
// Prepare our error in case we need to issue it. Bail early if we're not interactive.
|
|
|
|
var chooseStackErr string
|
|
|
|
if offerNew {
|
|
|
|
chooseStackErr = "no stack selected; please use `pulumi stack select` or `pulumi stack init` to choose one"
|
|
|
|
} else {
|
|
|
|
chooseStackErr = "no stack selected; please use `pulumi stack select` to choose one"
|
|
|
|
}
|
|
|
|
if !cmdutil.Interactive() {
|
|
|
|
return nil, errors.New(chooseStackErr)
|
|
|
|
}
|
|
|
|
|
2018-04-18 12:19:13 +02:00
|
|
|
proj, err := workspace.DetectProject()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-09-14 05:54:42 +02:00
|
|
|
// List stacks as available options.
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
var options []string
|
2018-09-14 05:54:42 +02:00
|
|
|
summaries, err := b.ListStacks(commandContext(), &proj.Name)
|
2018-04-05 00:31:01 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "could not query backend for stacks")
|
|
|
|
}
|
2018-09-14 05:54:42 +02:00
|
|
|
for _, summary := range summaries {
|
|
|
|
name := summary.Name().String()
|
2018-04-05 00:31:01 +02:00
|
|
|
options = append(options, name)
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
}
|
|
|
|
sort.Strings(options)
|
|
|
|
|
|
|
|
// If we are offering to create a new stack, add that to the end of the list.
|
2018-09-14 05:54:42 +02:00
|
|
|
const newOption = "<create a new stack>"
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
if offerNew {
|
|
|
|
options = append(options, newOption)
|
|
|
|
} else if len(options) == 0 {
|
|
|
|
// If no options are available, we can't offer a choice!
|
2018-04-14 19:01:39 +02:00
|
|
|
return nil, errors.New("this command requires a stack, but there are none")
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// If a stack is already selected, make that the default.
|
|
|
|
var current string
|
2018-05-08 03:23:03 +02:00
|
|
|
currStack, currErr := state.CurrentStack(commandContext(), b)
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
contract.IgnoreError(currErr)
|
|
|
|
if currStack != nil {
|
2018-09-05 16:20:25 +02:00
|
|
|
current = currStack.Ref().String()
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Customize the prompt a little bit (and disable color since it doesn't match our scheme).
|
|
|
|
surveycore.DisableColor = true
|
|
|
|
surveycore.QuestionIcon = ""
|
2018-07-07 06:30:00 +02:00
|
|
|
surveycore.SelectFocusIcon = opts.Color.Colorize(colors.BrightGreen + ">" + colors.Reset)
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
message := "\rPlease choose a stack"
|
|
|
|
if offerNew {
|
|
|
|
message += ", or create a new one:"
|
|
|
|
} else {
|
|
|
|
message += ":"
|
|
|
|
}
|
2018-09-19 10:40:03 +02:00
|
|
|
message = opts.Color.Colorize(colors.SpecPrompt + message + colors.Reset)
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
|
|
|
|
var option string
|
2018-09-14 05:54:42 +02:00
|
|
|
if err = survey.AskOne(&survey.Select{
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
Message: message,
|
|
|
|
Options: options,
|
|
|
|
Default: current,
|
|
|
|
}, &option, nil); err != nil {
|
|
|
|
return nil, errors.New(chooseStackErr)
|
|
|
|
}
|
|
|
|
|
|
|
|
if option == newOption {
|
2019-02-13 07:53:05 +01:00
|
|
|
stackName, readErr := cmdutil.ReadConsole(
|
|
|
|
"Please enter your desired stack name.\n" +
|
|
|
|
"To create a stack in an organization, " +
|
|
|
|
"use the format <org-name>/<stack-name> (e.g. `acmecorp/dev`)")
|
2018-09-14 05:54:42 +02:00
|
|
|
if readErr != nil {
|
|
|
|
return nil, readErr
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
}
|
|
|
|
|
2018-09-14 05:54:42 +02:00
|
|
|
stackRef, parseErr := b.ParseStackReference(stackName)
|
|
|
|
if parseErr != nil {
|
|
|
|
return nil, parseErr
|
2018-04-18 01:37:52 +02:00
|
|
|
}
|
|
|
|
|
2019-05-07 01:01:47 +02:00
|
|
|
return createStack(b, stackRef, nil, setCurrent, "")
|
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.
This includes:
* If `pulumi stack select` is run by itself, use an interactive
CLI menu to let the user select an existing stack, or choose to
create a new one. This looks as follows
$ pulumi stack select
Please choose a stack, or choose to create a new one:
abcdef
babblabblabble
> currentlyselected
defcon
<create a new stack>
and is navigated in the usual way (key up, down, enter).
* If a stack name is passed that does not exist, prompt the user
to ask whether s/he wants to create one on-demand. This hooks
interesting moments in time, like `pulumi stack select foo`,
and cuts down on the need to run additional commands.
* If a current stack is required, but none is currently selected,
then pop the same interactive menu shown above to select one.
Depending on the command being run, we may or may not show the
option to create a new stack (e.g., that doesn't make much sense
when you're running `pulumi destroy`, but might when you're
running `pulumi stack`). This again lets you do with a single
command what would have otherwise entailed an error with multiple
commands to recover from it.
* If you run `pulumi stack init` without any additional arguments,
we interactively prompt for the stack name. Before, we would
error and you'd then need to run `pulumi stack init <name>`.
* Colorize some things nicely; for example, now all prompts will
by default become bright white.
2018-02-17 00:03:54 +01:00
|
|
|
}
|
|
|
|
|
2018-09-14 05:54:42 +02:00
|
|
|
// With the stack name selected, look it up from the backend.
|
|
|
|
stackRef, err := b.ParseStackReference(option)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "parsing selected stack")
|
|
|
|
}
|
|
|
|
stack, err := b.GetStack(commandContext(), stackRef)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "getting selected stack")
|
|
|
|
}
|
|
|
|
|
2018-09-21 16:45:23 +02:00
|
|
|
// If setCurrent is true, we'll persist this choice so it'll be used for future CLI operations.
|
|
|
|
if setCurrent {
|
|
|
|
if err = state.SetCurrentStack(stackRef.String()); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-14 05:54:42 +02:00
|
|
|
return stack, nil
|
2017-10-19 00:37:18 +02:00
|
|
|
}
|
2017-10-25 19:20:08 +02:00
|
|
|
|
2018-02-14 22:56:16 +01:00
|
|
|
// readProject attempts to detect and read the project for the current workspace. If an error occurs, it will be
|
|
|
|
// printed to Stderr, and the returned value will be nil. If the project is successfully detected and read, it
|
|
|
|
// is returned along with the path to its containing directory, which will be used as the root of the project's
|
2018-01-08 22:01:40 +01:00
|
|
|
// Pulumi program.
|
2018-02-14 22:56:16 +01:00
|
|
|
func readProject() (*workspace.Project, string, error) {
|
2018-01-08 22:01:40 +01:00
|
|
|
pwd, err := os.Getwd()
|
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now that we got here, we have a path, so we will try to load it.
|
2018-02-14 22:56:16 +01:00
|
|
|
path, err := workspace.DetectProjectPathFrom(pwd)
|
2018-01-08 22:01:40 +01:00
|
|
|
if err != nil {
|
2018-02-14 22:56:16 +01:00
|
|
|
return nil, "", errors.Wrapf(err,
|
|
|
|
"could not locate Pulumi.yaml project file (searching upwards from %s)", pwd)
|
|
|
|
} else if path == "" {
|
|
|
|
return nil, "", errors.Errorf(
|
2018-12-05 23:00:14 +01:00
|
|
|
"no Pulumi.yaml project file found (searching upwards from %s). If you have not "+
|
|
|
|
"created a project yet, use `pulumi new` to do so", pwd)
|
2018-01-08 22:01:40 +01:00
|
|
|
}
|
2018-02-14 22:56:16 +01:00
|
|
|
proj, err := workspace.LoadProject(path)
|
2018-01-08 22:01:40 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
|
|
|
|
2018-02-14 22:56:16 +01:00
|
|
|
return proj, filepath.Dir(path), nil
|
2018-01-08 22:01:40 +01:00
|
|
|
}
|
2018-01-18 20:10:15 +01:00
|
|
|
|
2018-05-04 21:59:48 +02:00
|
|
|
// anyWriter is an io.Writer that will set itself to `true` iff any call to `anyWriter.Write` is made with a
|
|
|
|
// non-zero-length slice. This can be used to determine whether or not any data was ever written to the writer.
|
|
|
|
type anyWriter bool
|
|
|
|
|
|
|
|
func (w *anyWriter) Write(d []byte) (int, error) {
|
|
|
|
if len(d) > 0 {
|
|
|
|
*w = true
|
|
|
|
}
|
|
|
|
return len(d), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// isGitWorkTreeDirty returns true if the work tree for the current directory's repository is dirty.
|
2018-10-08 19:05:06 +02:00
|
|
|
func isGitWorkTreeDirty(repoRoot string) (bool, error) {
|
2018-05-04 21:59:48 +02:00
|
|
|
gitBin, err := exec.LookPath("git")
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
gitStatusCmd := exec.Command(gitBin, "status", "--porcelain", "-z")
|
|
|
|
var anyOutput anyWriter
|
|
|
|
var stderr bytes.Buffer
|
2018-10-08 19:05:06 +02:00
|
|
|
gitStatusCmd.Dir = repoRoot
|
2018-05-04 21:59:48 +02:00
|
|
|
gitStatusCmd.Stdout = &anyOutput
|
|
|
|
gitStatusCmd.Stderr = &stderr
|
|
|
|
if err = gitStatusCmd.Run(); err != nil {
|
|
|
|
if ee, ok := err.(*exec.ExitError); ok {
|
|
|
|
ee.Stderr = stderr.Bytes()
|
|
|
|
}
|
|
|
|
return false, errors.Wrapf(err, "'git status' failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
return bool(anyOutput), nil
|
|
|
|
}
|
|
|
|
|
2018-01-25 03:22:41 +01:00
|
|
|
// getUpdateMetadata returns an UpdateMetadata object, with optional data about the environment
|
|
|
|
// performing the update.
|
2018-10-02 19:49:41 +02:00
|
|
|
func getUpdateMetadata(msg, root string) (*backend.UpdateMetadata, error) {
|
|
|
|
m := &backend.UpdateMetadata{
|
2018-01-25 03:22:41 +01:00
|
|
|
Message: msg,
|
|
|
|
Environment: make(map[string]string),
|
|
|
|
}
|
|
|
|
|
2018-10-02 19:49:41 +02:00
|
|
|
if err := addGitMetadata(root, m); err != nil {
|
2018-08-03 01:15:57 +02:00
|
|
|
glog.V(3).Infof("errors detecting git metadata: %s", err)
|
2018-08-01 06:38:07 +02:00
|
|
|
}
|
2018-10-02 19:49:41 +02:00
|
|
|
|
2018-08-01 06:38:07 +02:00
|
|
|
addCIMetadataToEnvironment(m.Environment)
|
|
|
|
|
|
|
|
return m, nil
|
|
|
|
}
|
|
|
|
|
2018-10-02 19:49:41 +02:00
|
|
|
// addGitMetadata populate's the environment metadata bag with Git-related values.
|
|
|
|
func addGitMetadata(repoRoot string, m *backend.UpdateMetadata) error {
|
2018-08-03 01:15:57 +02:00
|
|
|
var allErrors *multierror.Error
|
|
|
|
|
2018-01-25 03:22:41 +01:00
|
|
|
// Gather git-related data as appropriate. (Returns nil, nil if no repo found.)
|
2018-08-01 06:38:07 +02:00
|
|
|
repo, err := gitutil.GetGitRepository(repoRoot)
|
2018-01-25 03:22:41 +01:00
|
|
|
if err != nil {
|
2018-08-01 06:38:07 +02:00
|
|
|
return errors.Wrapf(err, "detecting Git repository")
|
2018-05-04 21:59:48 +02:00
|
|
|
}
|
|
|
|
if repo == nil {
|
2018-08-01 06:38:07 +02:00
|
|
|
return nil
|
2018-05-04 21:59:48 +02:00
|
|
|
}
|
2018-01-25 03:22:41 +01:00
|
|
|
|
2018-10-23 23:53:52 +02:00
|
|
|
if err := AddGitRemoteMetadataToMap(repo, m.Environment); err != nil {
|
2018-08-03 01:15:57 +02:00
|
|
|
allErrors = multierror.Append(allErrors, err)
|
|
|
|
}
|
|
|
|
|
2018-10-08 19:05:06 +02:00
|
|
|
if err := addGitCommitMetadata(repo, repoRoot, m); err != nil {
|
2018-08-03 01:15:57 +02:00
|
|
|
allErrors = multierror.Append(allErrors, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return allErrors.ErrorOrNil()
|
|
|
|
}
|
|
|
|
|
2018-10-23 23:53:52 +02:00
|
|
|
// AddGitRemoteMetadataToMap reads the given git repo and adds its metadata to the given map bag.
|
|
|
|
func AddGitRemoteMetadataToMap(repo *git.Repository, env map[string]string) error {
|
|
|
|
var allErrors *multierror.Error
|
|
|
|
|
|
|
|
// Get the remote URL for this repo.
|
|
|
|
remoteURL, err := gitutil.GetGitRemoteURL(repo, "origin")
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "detecting Git remote URL")
|
|
|
|
}
|
|
|
|
if remoteURL == "" {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the remote URL is a GitHub or a GitLab URL.
|
|
|
|
if err := addVCSMetadataToEnvironment(remoteURL, env); err != nil {
|
|
|
|
allErrors = multierror.Append(allErrors, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the environment map contains the vcs kind and if it is GitHub,
|
|
|
|
// then let's set the old metadata keys as well, so that the UI can continue to read those.
|
|
|
|
// As of this writing, none of the other VCS were detected _previously_ and only the `github` keys were set
|
|
|
|
// when the origin remote was truly a github remote.
|
|
|
|
// TODO [pulumi/pulumi-service#2306] Once the UI is updated and we no longer need these keys, we can remove this block.
|
|
|
|
if env[backend.VCSRepoKind] == gitutil.GitHubHostName && env[backend.VCSRepoOwner] != "" {
|
|
|
|
env[backend.GitHubLogin] = env[backend.VCSRepoOwner]
|
|
|
|
env[backend.GitHubRepo] = env[backend.VCSRepoName]
|
|
|
|
}
|
|
|
|
|
|
|
|
return allErrors.ErrorOrNil()
|
|
|
|
}
|
|
|
|
|
|
|
|
func addVCSMetadataToEnvironment(remoteURL string, env map[string]string) error {
|
|
|
|
// GitLab, Bitbucket, Azure DevOps etc. repo slug if applicable.
|
|
|
|
// We don't require a cloud-hosted VCS, so swallow errors.
|
|
|
|
vcsInfo, err := gitutil.TryGetVCSInfo(remoteURL)
|
2018-05-04 21:59:48 +02:00
|
|
|
if err != nil {
|
2018-10-23 23:53:52 +02:00
|
|
|
return errors.Wrap(err, "detecting VCS project information")
|
2018-05-04 21:59:48 +02:00
|
|
|
}
|
2018-10-23 23:53:52 +02:00
|
|
|
env[backend.VCSRepoOwner] = vcsInfo.Owner
|
|
|
|
env[backend.VCSRepoName] = vcsInfo.Repo
|
|
|
|
env[backend.VCSRepoKind] = vcsInfo.Kind
|
2018-05-04 21:59:48 +02:00
|
|
|
|
2018-08-03 01:15:57 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-10-08 19:05:06 +02:00
|
|
|
func addGitCommitMetadata(repo *git.Repository, repoRoot string, m *backend.UpdateMetadata) error {
|
2018-10-17 00:37:02 +02:00
|
|
|
// When running in a CI/CD environment, the current git repo may be running from a
|
|
|
|
// detached HEAD and may not have have the latest commit message. We fall back to
|
|
|
|
// CI-system specific environment variables when possible.
|
|
|
|
ciVars := ciutil.DetectVars()
|
|
|
|
|
2018-05-04 21:59:48 +02:00
|
|
|
// Commit at HEAD
|
|
|
|
head, err := repo.Head()
|
|
|
|
if err != nil {
|
2018-08-01 06:38:07 +02:00
|
|
|
return errors.Wrap(err, "getting repository HEAD")
|
|
|
|
}
|
|
|
|
|
|
|
|
hash := head.Hash()
|
2018-10-02 19:49:41 +02:00
|
|
|
m.Environment[backend.GitHead] = hash.String()
|
2018-08-01 06:38:07 +02:00
|
|
|
commit, commitErr := repo.CommitObject(hash)
|
|
|
|
if commitErr != nil {
|
|
|
|
return errors.Wrap(commitErr, "getting HEAD commit info")
|
2018-05-04 21:59:48 +02:00
|
|
|
}
|
|
|
|
|
2018-10-17 00:37:02 +02:00
|
|
|
// If in detached head, will be "HEAD", and fallback to use value from CI/CD system if possible.
|
|
|
|
// Otherwise, the value will be like "refs/heads/master".
|
2018-10-08 20:13:21 +02:00
|
|
|
headName := head.Name().String()
|
2018-10-17 00:37:02 +02:00
|
|
|
if headName == "HEAD" && ciVars.BranchName != "" {
|
|
|
|
headName = ciVars.BranchName
|
|
|
|
}
|
2018-10-08 20:13:21 +02:00
|
|
|
if headName != "HEAD" {
|
2018-10-17 00:37:02 +02:00
|
|
|
m.Environment[backend.GitHeadName] = headName
|
2018-10-08 20:13:21 +02:00
|
|
|
}
|
|
|
|
|
2018-10-17 00:37:02 +02:00
|
|
|
// If there is no message set manually, default to the Git commit's title.
|
2018-10-18 20:10:36 +02:00
|
|
|
msg := strings.TrimSpace(commit.Message)
|
2018-10-17 00:37:02 +02:00
|
|
|
if msg == "" && ciVars.CommitMessage != "" {
|
|
|
|
msg = ciVars.CommitMessage
|
|
|
|
}
|
2018-10-02 19:49:41 +02:00
|
|
|
if m.Message == "" {
|
2018-10-17 00:37:02 +02:00
|
|
|
m.Message = gitCommitTitle(msg)
|
2018-10-02 19:49:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Store committer and author information.
|
|
|
|
m.Environment[backend.GitCommitter] = commit.Committer.Name
|
|
|
|
m.Environment[backend.GitCommitterEmail] = commit.Committer.Email
|
|
|
|
m.Environment[backend.GitAuthor] = commit.Author.Name
|
|
|
|
m.Environment[backend.GitAuthorEmail] = commit.Author.Email
|
|
|
|
|
|
|
|
// If the worktree is dirty, set a bit, as this could be a mistake.
|
2018-10-08 19:05:06 +02:00
|
|
|
isDirty, err := isGitWorkTreeDirty(repoRoot)
|
2018-05-04 21:59:48 +02:00
|
|
|
if err != nil {
|
2018-08-01 06:38:07 +02:00
|
|
|
return errors.Wrapf(err, "checking git worktree dirty state")
|
2018-01-25 03:22:41 +01:00
|
|
|
}
|
2018-10-02 19:49:41 +02:00
|
|
|
m.Environment[backend.GitDirty] = strconv.FormatBool(isDirty)
|
2018-01-25 03:22:41 +01:00
|
|
|
|
2018-08-01 06:38:07 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-10-02 19:49:41 +02:00
|
|
|
// gitCommitTitle turns a commit message into its title, simply by taking the first line.
|
|
|
|
func gitCommitTitle(s string) string {
|
|
|
|
if ixCR := strings.Index(s, "\r"); ixCR != -1 {
|
|
|
|
s = s[:ixCR]
|
|
|
|
}
|
|
|
|
if ixLF := strings.Index(s, "\n"); ixLF != -1 {
|
|
|
|
s = s[:ixLF]
|
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2018-09-18 18:50:29 +02:00
|
|
|
// addCIMetadataToEnvironment populates the environment metadata bag with CI/CD-related values.
|
2018-08-01 06:38:07 +02:00
|
|
|
func addCIMetadataToEnvironment(env map[string]string) {
|
2018-11-01 19:20:31 +01:00
|
|
|
// Add the key/value pair to env, if there actually is a value.
|
|
|
|
addIfSet := func(key, val string) {
|
|
|
|
if val != "" {
|
|
|
|
env[key] = val
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use our built-in CI/CD detection logic.
|
2018-10-03 01:08:03 +02:00
|
|
|
vars := ciutil.DetectVars()
|
2019-05-07 20:49:13 +02:00
|
|
|
if vars.Name == "" {
|
|
|
|
return
|
2018-08-01 06:38:07 +02:00
|
|
|
}
|
2019-05-07 20:49:13 +02:00
|
|
|
env[backend.CISystem] = string(vars.Name)
|
|
|
|
addIfSet(backend.CIBuildID, vars.BuildID)
|
|
|
|
addIfSet(backend.CIBuildType, vars.BuildType)
|
|
|
|
addIfSet(backend.CIBuildURL, vars.BuildURL)
|
|
|
|
addIfSet(backend.CIPRHeadSHA, vars.SHA)
|
|
|
|
addIfSet(backend.CIPRNumber, vars.PRNumber)
|
2018-01-25 03:22:41 +01:00
|
|
|
}
|
2018-04-05 00:31:01 +02:00
|
|
|
|
2018-04-20 03:59:14 +02:00
|
|
|
type cancellationScope struct {
|
|
|
|
context *cancel.Context
|
|
|
|
sigint chan os.Signal
|
2018-09-11 01:42:22 +02:00
|
|
|
done chan bool
|
2018-04-20 03:59:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *cancellationScope) Context() *cancel.Context {
|
|
|
|
return s.context
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *cancellationScope) Close() {
|
|
|
|
signal.Stop(s.sigint)
|
|
|
|
close(s.sigint)
|
2018-09-11 01:42:22 +02:00
|
|
|
<-s.done
|
2018-04-20 03:59:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type cancellationScopeSource int
|
|
|
|
|
|
|
|
var cancellationScopes = backend.CancellationScopeSource(cancellationScopeSource(0))
|
|
|
|
|
|
|
|
func (cancellationScopeSource) NewScope(events chan<- engine.Event, isPreview bool) backend.CancellationScope {
|
|
|
|
cancelContext, cancelSource := cancel.NewContext(context.Background())
|
|
|
|
|
|
|
|
c := &cancellationScope{
|
|
|
|
context: cancelContext,
|
|
|
|
sigint: make(chan os.Signal),
|
2018-09-11 01:42:22 +02:00
|
|
|
done: make(chan bool),
|
2018-04-20 03:59:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for range c.sigint {
|
|
|
|
// If we haven't yet received a SIGINT, call the cancellation func. Otherwise call the termination
|
|
|
|
// func.
|
|
|
|
if cancelContext.CancelErr() == nil {
|
|
|
|
message := "^C received; cancelling. If you would like to terminate immediately, press ^C again.\n"
|
|
|
|
if !isPreview {
|
|
|
|
message += colors.BrightRed + "Note that terminating immediately may lead to orphaned resources " +
|
|
|
|
"and other inconsistencies.\n" + colors.Reset
|
|
|
|
}
|
|
|
|
events <- engine.Event{
|
|
|
|
Type: engine.StdoutColorEvent,
|
|
|
|
Payload: engine.StdoutEventPayload{
|
|
|
|
Message: message,
|
|
|
|
Color: colors.Always,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
cancelSource.Cancel()
|
|
|
|
} else {
|
|
|
|
message := colors.BrightRed + "^C received; terminating" + colors.Reset
|
|
|
|
events <- engine.Event{
|
|
|
|
Type: engine.StdoutColorEvent,
|
|
|
|
Payload: engine.StdoutEventPayload{
|
|
|
|
Message: message,
|
|
|
|
Color: colors.Always,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
cancelSource.Terminate()
|
|
|
|
}
|
|
|
|
}
|
2018-09-11 01:42:22 +02:00
|
|
|
close(c.done)
|
2018-04-20 03:59:14 +02:00
|
|
|
}()
|
|
|
|
signal.Notify(c.sigint, os.Interrupt)
|
|
|
|
|
|
|
|
return c
|
|
|
|
}
|
2018-05-01 00:27:53 +02:00
|
|
|
|
2018-09-29 18:57:58 +02:00
|
|
|
// printJSON simply prints out some object, formatted as JSON, using standard indentation.
|
|
|
|
func printJSON(v interface{}) error {
|
2018-10-25 22:56:30 +02:00
|
|
|
out, err := json.MarshalIndent(v, "", " ")
|
2018-09-29 18:57:58 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
fmt.Println(string(out))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-05-05 20:57:09 +02:00
|
|
|
// updateFlagsToOptions ensures that the given update flags represent a valid combination. If so, an UpdateOptions
|
|
|
|
// is returned with a nil-error; otherwise, the non-nil error contains information about why the combination is invalid.
|
|
|
|
func updateFlagsToOptions(interactive, skipPreview, yes bool) (backend.UpdateOptions, error) {
|
|
|
|
if !interactive && !yes {
|
|
|
|
return backend.UpdateOptions{},
|
|
|
|
errors.New("--yes must be passed in non-interactive mode")
|
Revise the way previews are controlled
I found the flag --force to be a strange name for skipping a preview,
since that name is usually reserved for operations that might be harmful
and yet you're coercing a tool to do it anyway, knowing there's a chance
you're going to shoot yourself in the foot.
I also found that what I almost always want in the situation where
--force was being used is to actually just run a preview and have the
confirmation auto-accepted. Going straight to --force isn't the right
thing in a CI scenario, where you actually want to run a preview first,
just to ensure there aren't any issues, before doing the update.
In a sense, there are four options here:
1. Run a preview, ask for confirmation, then do an update (the default).
2. Run a preview, auto-accept, and then do an update (the CI scenario).
3. Just run a preview with neither a confirmation nor an update (dry run).
4. Just do an update, without performing a preview beforehand (rare).
This change enables all four workflows in our CLI.
Rather than have an explosion of flags, we have a single flag,
--preview, which can specify the mode that we're operating in. The
following are the values which correlate to the above four modes:
1. "": default (no --preview specified)
2. "auto": auto-accept preview confirmation
3. "only": only run a preview, don't confirm or update
4. "skip": skip the preview altogether
As part of this change, I redid a bit of how the preview modes
were specified. Rather than booleans, which had some illegal
combinations, this change introduces a new enum type. Furthermore,
because the engine is wholly ignorant of these flags -- and only the
backend understands them -- it was confusing to me that
engine.UpdateOptions stored this flag, especially given that all
interesting engine options _also_ accepted a dryRun boolean. As of
this change, the backend.PreviewBehavior controls the preview options.
2018-04-28 23:50:17 +02:00
|
|
|
}
|
|
|
|
|
2018-05-05 20:57:09 +02:00
|
|
|
return backend.UpdateOptions{
|
|
|
|
AutoApprove: yes,
|
|
|
|
SkipPreview: skipPreview,
|
|
|
|
}, nil
|
Revise the way previews are controlled
I found the flag --force to be a strange name for skipping a preview,
since that name is usually reserved for operations that might be harmful
and yet you're coercing a tool to do it anyway, knowing there's a chance
you're going to shoot yourself in the foot.
I also found that what I almost always want in the situation where
--force was being used is to actually just run a preview and have the
confirmation auto-accepted. Going straight to --force isn't the right
thing in a CI scenario, where you actually want to run a preview first,
just to ensure there aren't any issues, before doing the update.
In a sense, there are four options here:
1. Run a preview, ask for confirmation, then do an update (the default).
2. Run a preview, auto-accept, and then do an update (the CI scenario).
3. Just run a preview with neither a confirmation nor an update (dry run).
4. Just do an update, without performing a preview beforehand (rare).
This change enables all four workflows in our CLI.
Rather than have an explosion of flags, we have a single flag,
--preview, which can specify the mode that we're operating in. The
following are the values which correlate to the above four modes:
1. "": default (no --preview specified)
2. "auto": auto-accept preview confirmation
3. "only": only run a preview, don't confirm or update
4. "skip": skip the preview altogether
As part of this change, I redid a bit of how the preview modes
were specified. Rather than booleans, which had some illegal
combinations, this change introduces a new enum type. Furthermore,
because the engine is wholly ignorant of these flags -- and only the
backend understands them -- it was confusing to me that
engine.UpdateOptions stored this flag, especially given that all
interesting engine options _also_ accepted a dryRun boolean. As of
this change, the backend.PreviewBehavior controls the preview options.
2018-04-28 23:50:17 +02:00
|
|
|
}
|