Don't print error
prefix when a confirmation prompt is declined
Use `result.Result` in more places, so when a confirmation prompt is declined, we just return `result.Bail()` after printing a message without the `error: ` prefix. Fixes #2070
This commit is contained in:
parent
f34aef2f4d
commit
ccd958777c
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,9 +1,10 @@
|
|||
## 0.17.4 (Unreleased)
|
||||
|
||||
## 0.17.3 (Released March 26, 2019)
|
||||
## Improvements
|
||||
|
||||
- Add support for serializing JavaScript function that capture [BigInts](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
|
||||
- Support serializing arrow-functions with deconstructed parameters.
|
||||
- Don't print the `error:` prefix when Pulumi exists because of a declined confirmation prompt (fixes [pulumi/pulumi#458](https://github.com/pulumi/pulumi/issues/2070))
|
||||
|
||||
## 0.17.3 (Released March 26, 2019)
|
||||
|
||||
### Improvements
|
||||
|
||||
|
@ -12,7 +13,8 @@
|
|||
- A bug in the previous version of the Pulumi CLI occasionally caused the Pulumi Engine to load the incorrect resource
|
||||
plugin when processing an update. This bug has been fixed in 0.17.3 by performing a deterministic selection of the
|
||||
best set of plugins available to the engine before starting up. See
|
||||
[pulumi/pulumi#2579](https://github.com/pulumi/pulumi/issues/2579) for discussion on this issue.
|
||||
- Add support for serializing JavaScript function that capture [BigInts](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
|
||||
- Support serializing arrow-functions with deconstructed parameters.
|
||||
|
||||
## 0.17.2 (Released March 15, 2019)
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@ package cmd
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/util/result"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/backend/display"
|
||||
|
@ -41,11 +42,11 @@ func newCancelCmd() *cobra.Command {
|
|||
"\n" +
|
||||
"After this command completes successfully, the stack will be ready for further\n" +
|
||||
"updates.",
|
||||
Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error {
|
||||
Run: cmdutil.RunResultFunc(func(cmd *cobra.Command, args []string) result.Result {
|
||||
// Use the stack provided or, if missing, default to the current one.
|
||||
if len(args) > 0 {
|
||||
if stack != "" {
|
||||
return errors.New("only one of --stack or argument stack name may be specified, not both")
|
||||
return result.Error("only one of --stack or argument stack name may be specified, not both")
|
||||
}
|
||||
|
||||
stack = args[0]
|
||||
|
@ -57,25 +58,26 @@ func newCancelCmd() *cobra.Command {
|
|||
|
||||
s, err := requireStack(stack, false, opts, true /*setCurrent*/)
|
||||
if err != nil {
|
||||
return err
|
||||
return result.FromError(err)
|
||||
}
|
||||
|
||||
// Ensure that we are targeting the Pulumi cloud.
|
||||
backend, ok := s.Backend().(httpstate.Backend)
|
||||
if !ok {
|
||||
return errors.New("the `cancel` command is not supported for local stacks")
|
||||
return result.Error("the `cancel` command is not supported for local stacks")
|
||||
}
|
||||
|
||||
// Ensure the user really wants to do this.
|
||||
stackName := string(s.Ref().Name())
|
||||
prompt := fmt.Sprintf("This will irreversibly cancel the currently running update for '%s'!", stackName)
|
||||
if !yes && !confirmPrompt(prompt, stackName, opts) {
|
||||
return errors.New("confirmation declined")
|
||||
fmt.Println("confirmation declined")
|
||||
return result.Bail()
|
||||
}
|
||||
|
||||
// Cancel the update.
|
||||
if err := backend.CancelCurrentUpdate(commandContext(), s.Ref()); err != nil {
|
||||
return err
|
||||
return result.FromError(err)
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf(
|
||||
|
|
|
@ -18,7 +18,8 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/util/result"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/backend/display"
|
||||
|
@ -44,11 +45,11 @@ func newStackRmCmd() *cobra.Command {
|
|||
"`destroy` command for removing a resources, as this is a distinct operation.\n" +
|
||||
"\n" +
|
||||
"After this command completes, the stack will no longer be available for updates.",
|
||||
Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error {
|
||||
Run: cmdutil.RunResultFunc(func(cmd *cobra.Command, args []string) result.Result {
|
||||
// Use the stack provided or, if missing, default to the current one.
|
||||
if len(args) > 0 {
|
||||
if stack != "" {
|
||||
return errors.New("only one of --stack or argument stack name may be specified, not both")
|
||||
return result.Error("only one of --stack or argument stack name may be specified, not both")
|
||||
}
|
||||
stack = args[0]
|
||||
}
|
||||
|
@ -59,29 +60,30 @@ func newStackRmCmd() *cobra.Command {
|
|||
|
||||
s, err := requireStack(stack, false, opts, true /*setCurrent*/)
|
||||
if err != nil {
|
||||
return err
|
||||
return result.FromError(err)
|
||||
}
|
||||
|
||||
// Ensure the user really wants to do this.
|
||||
prompt := fmt.Sprintf("This will permanently remove the '%s' stack!", s.Ref())
|
||||
if !yes && !confirmPrompt(prompt, s.Ref().String(), opts) {
|
||||
return errors.New("confirmation declined")
|
||||
fmt.Println("confirmation declined")
|
||||
return result.Bail()
|
||||
}
|
||||
|
||||
hasResources, err := s.Remove(commandContext(), force)
|
||||
if err != nil {
|
||||
if hasResources {
|
||||
return errors.Errorf(
|
||||
return result.Errorf(
|
||||
"'%s' still has resources; removal rejected; pass --force to override", s.Ref())
|
||||
}
|
||||
return err
|
||||
return result.FromError(err)
|
||||
}
|
||||
|
||||
if !preserveConfig {
|
||||
// Blow away stack specific settings if they exist. If we get an ENOENT error, ignore it.
|
||||
if path, err := workspace.DetectProjectStackPath(s.Ref().Name()); err == nil {
|
||||
if err = os.Remove(path); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
return result.FromError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
20
cmd/state.go
20
cmd/state.go
|
@ -18,6 +18,8 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/util/result"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/util/contract"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
@ -109,7 +111,7 @@ func locateStackResource(opts display.Options, snap *deploy.Snapshot, urn resour
|
|||
}
|
||||
|
||||
// runStateEdit runs the given state edit function on a resource with the given URN in a given stack.
|
||||
func runStateEdit(stackName string, urn resource.URN, operation edit.OperationFunc) error {
|
||||
func runStateEdit(stackName string, urn resource.URN, operation edit.OperationFunc) result.Result {
|
||||
return runTotalStateEdit(stackName, func(opts display.Options, snap *deploy.Snapshot) error {
|
||||
res, err := locateStackResource(opts, snap, urn)
|
||||
if err != nil {
|
||||
|
@ -122,17 +124,18 @@ func runStateEdit(stackName string, urn resource.URN, operation edit.OperationFu
|
|||
|
||||
// runTotalStateEdit runs a snapshot-mutating function on the entirity of the given stack's snapshot. Before mutating
|
||||
// the snapshot, the user is prompted for confirmation if the current session is interactive.
|
||||
func runTotalStateEdit(stackName string, operation func(opts display.Options, snap *deploy.Snapshot) error) error {
|
||||
func runTotalStateEdit(stackName string,
|
||||
operation func(opts display.Options, snap *deploy.Snapshot) error) result.Result {
|
||||
opts := display.Options{
|
||||
Color: cmdutil.GetGlobalColorization(),
|
||||
}
|
||||
s, err := requireStack(stackName, true, opts, true /*setCurrent*/)
|
||||
if err != nil {
|
||||
return err
|
||||
return result.FromError(err)
|
||||
}
|
||||
snap, err := s.Snapshot(commandContext())
|
||||
if err != nil {
|
||||
return err
|
||||
return result.FromError(err)
|
||||
}
|
||||
|
||||
if cmdutil.Interactive() {
|
||||
|
@ -145,7 +148,8 @@ func runTotalStateEdit(stackName string, operation func(opts display.Options, sn
|
|||
if err = survey.AskOne(&survey.Confirm{
|
||||
Message: prompt,
|
||||
}, &confirm, nil); err != nil || !confirm {
|
||||
return errors.New("confirmation declined")
|
||||
fmt.Println("confirmation declined")
|
||||
return result.Bail()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,7 +158,7 @@ func runTotalStateEdit(stackName string, operation func(opts display.Options, sn
|
|||
// before we mutated it, we'll assert that we didn't make it invalid by mutating it.
|
||||
stackIsAlreadyHosed := snap.VerifyIntegrity() != nil
|
||||
if err = operation(opts, snap); err != nil {
|
||||
return err
|
||||
return result.FromError(err)
|
||||
}
|
||||
|
||||
// If the stack is already broken, don't bother verifying the integrity here.
|
||||
|
@ -165,11 +169,11 @@ func runTotalStateEdit(stackName string, operation func(opts display.Options, sn
|
|||
// Once we've mutated the snapshot, import it back into the backend so that it can be persisted.
|
||||
bytes, err := json.Marshal(stack.SerializeDeployment(snap))
|
||||
if err != nil {
|
||||
return err
|
||||
return result.FromError(err)
|
||||
}
|
||||
dep := apitype.UntypedDeployment{
|
||||
Version: apitype.DeploymentSchemaVersionCurrent,
|
||||
Deployment: bytes,
|
||||
}
|
||||
return s.ImportDeployment(commandContext(), &dep)
|
||||
return result.WrapIfNonNil(s.ImportDeployment(commandContext(), &dep))
|
||||
}
|
||||
|
|
|
@ -17,13 +17,14 @@ package cmd
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/util/result"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/diag"
|
||||
"github.com/pulumi/pulumi/pkg/resource"
|
||||
"github.com/pulumi/pulumi/pkg/resource/deploy"
|
||||
"github.com/pulumi/pulumi/pkg/resource/edit"
|
||||
"github.com/pulumi/pulumi/pkg/util/cmdutil"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -42,9 +43,9 @@ by its Pulumi URN (use 'pulumi stack --show-urns' to get it).
|
|||
Resources can't be deleted if there exist other resources that depend on it or are parented to it. Protected resources
|
||||
will not be deleted unless it is specifically requested using the --force flag.`,
|
||||
Args: cmdutil.ExactArgs(1),
|
||||
Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error {
|
||||
Run: cmdutil.RunResultFunc(func(cmd *cobra.Command, args []string) result.Result {
|
||||
urn := resource.URN(args[0])
|
||||
err := runStateEdit(stack, urn, func(snap *deploy.Snapshot, res *resource.State) error {
|
||||
res := runStateEdit(stack, urn, func(snap *deploy.Snapshot, res *resource.State) error {
|
||||
if !force {
|
||||
return edit.DeleteResource(snap, res)
|
||||
}
|
||||
|
@ -56,8 +57,8 @@ will not be deleted unless it is specifically requested using the --force flag.`
|
|||
|
||||
return edit.DeleteResource(snap, res)
|
||||
})
|
||||
if err != nil {
|
||||
switch e := err.(type) {
|
||||
if res != nil {
|
||||
switch e := res.Error().(type) {
|
||||
case edit.ResourceHasDependenciesError:
|
||||
message := "This resource can't be safely deleted because the following resources depend on it:\n"
|
||||
for _, dependentResource := range e.Dependencies {
|
||||
|
@ -66,13 +67,13 @@ will not be deleted unless it is specifically requested using the --force flag.`
|
|||
}
|
||||
|
||||
message += "\nDelete those resources first before deleting this one."
|
||||
return errors.New(message)
|
||||
return result.Error(message)
|
||||
case edit.ResourceProtectedError:
|
||||
return errors.New(
|
||||
return result.Error(
|
||||
"This resource can't be safely deleted because it is protected. " +
|
||||
"Re-run this command with --force to force deletion")
|
||||
default:
|
||||
return err
|
||||
return res
|
||||
}
|
||||
}
|
||||
fmt.Println("Resource deleted successfully")
|
||||
|
|
|
@ -17,9 +17,10 @@ package cmd
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/util/result"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/util/contract"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/pkg/backend/display"
|
||||
"github.com/pulumi/pulumi/pkg/resource/deploy"
|
||||
|
||||
|
@ -41,13 +42,13 @@ func newStateUnprotectCommand() *cobra.Command {
|
|||
|
||||
This command clears the 'protect' bit on one or more resources, allowing those resources to be deleted.`,
|
||||
Args: cmdutil.MaximumNArgs(1),
|
||||
Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error {
|
||||
Run: cmdutil.RunResultFunc(func(cmd *cobra.Command, args []string) result.Result {
|
||||
if unprotectAll {
|
||||
return unprotectAllResources(stack)
|
||||
}
|
||||
|
||||
if len(args) != 1 {
|
||||
return errors.New("must provide a URN corresponding to a resource")
|
||||
return result.Error("must provide a URN corresponding to a resource")
|
||||
}
|
||||
|
||||
urn := resource.URN(args[0])
|
||||
|
@ -62,8 +63,8 @@ This command clears the 'protect' bit on one or more resources, allowing those r
|
|||
return cmd
|
||||
}
|
||||
|
||||
func unprotectAllResources(stackName string) error {
|
||||
err := runTotalStateEdit(stackName, func(_ display.Options, snap *deploy.Snapshot) error {
|
||||
func unprotectAllResources(stackName string) result.Result {
|
||||
res := runTotalStateEdit(stackName, func(_ display.Options, snap *deploy.Snapshot) error {
|
||||
for _, res := range snap.Resources {
|
||||
err := edit.UnprotectResource(snap, res)
|
||||
contract.AssertNoError(err)
|
||||
|
@ -72,17 +73,17 @@ func unprotectAllResources(stackName string) error {
|
|||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
if res != nil {
|
||||
return res
|
||||
}
|
||||
fmt.Println("All resources successfully unprotected")
|
||||
return nil
|
||||
}
|
||||
|
||||
func unprotectResource(stackName string, urn resource.URN) error {
|
||||
err := runStateEdit(stackName, urn, edit.UnprotectResource)
|
||||
if err != nil {
|
||||
return err
|
||||
func unprotectResource(stackName string, urn resource.URN) result.Result {
|
||||
res := runStateEdit(stackName, urn, edit.UnprotectResource)
|
||||
if res != nil {
|
||||
return res
|
||||
}
|
||||
fmt.Println("Resource successfully unprotected")
|
||||
return nil
|
||||
|
|
|
@ -123,14 +123,14 @@ func PreviewThenPrompt(ctx context.Context, kind apitype.UpdateKind, stack Stack
|
|||
}
|
||||
|
||||
// Otherwise, ensure the user wants to proceed.
|
||||
err := confirmBeforeUpdating(kind, stack, events, op.Opts)
|
||||
res = confirmBeforeUpdating(kind, stack, events, op.Opts)
|
||||
close(eventsChannel)
|
||||
return changes, result.WrapIfNonNil(err)
|
||||
return changes, res
|
||||
}
|
||||
|
||||
// confirmBeforeUpdating asks the user whether to proceed. A nil error means yes.
|
||||
func confirmBeforeUpdating(kind apitype.UpdateKind, stack Stack,
|
||||
events []engine.Event, opts UpdateOptions) error {
|
||||
events []engine.Event, opts UpdateOptions) result.Result {
|
||||
for {
|
||||
var response string
|
||||
|
||||
|
@ -167,11 +167,12 @@ func confirmBeforeUpdating(kind apitype.UpdateKind, stack Stack,
|
|||
Options: choices,
|
||||
Default: string(no),
|
||||
}, &response, nil); err != nil {
|
||||
return errors.Wrapf(err, "confirmation cancelled, not proceeding with the %s", kind)
|
||||
return result.FromError(errors.Wrapf(err, "confirmation cancelled, not proceeding with the %s", kind))
|
||||
}
|
||||
|
||||
if response == string(no) {
|
||||
return errors.Errorf("confirmation declined, not proceeding with the %s", kind)
|
||||
fmt.Printf("confirmation declined, not proceeding with the %s\n", kind)
|
||||
return result.Bail()
|
||||
}
|
||||
|
||||
if response == string(yes) {
|
||||
|
|
Loading…
Reference in a new issue