Compare commits
1 commit
master
...
evan/autoC
Author | SHA1 | Date | |
---|---|---|---|
448eb648dd |
|
@ -70,7 +70,7 @@ func newCancelCmd() *cobra.Command {
|
|||
// 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) {
|
||||
if cmdutil.Interactive() && (!yes && !confirmPrompt(prompt, stackName, opts)) {
|
||||
fmt.Println("confirmation declined")
|
||||
return result.Bail()
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/common/apitype"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/common/tokens"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/common/util/contract"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/common/workspace"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/pulumi"
|
||||
)
|
||||
|
@ -409,6 +411,62 @@ func (l *LocalWorkspace) SetProgram(fn pulumi.RunFunc) {
|
|||
l.program = fn
|
||||
}
|
||||
|
||||
// ExportStack exports the deployment state of the stack matching the given name.
|
||||
// This can be combined with ImportStack to edit a stack's state (such as recovery from failed deployments).
|
||||
func (l *LocalWorkspace) ExportStack(ctx context.Context, stackName string) (apitype.UntypedDeployment, error) {
|
||||
var state apitype.UntypedDeployment
|
||||
err := l.SelectStack(ctx, stackName)
|
||||
if err != nil {
|
||||
return state, errors.Wrapf(err, "could not export stack, unable to select stack %s.", stackName)
|
||||
}
|
||||
|
||||
stdout, stderr, errCode, err := l.runPulumiCmdSync(ctx, "stack", "export", "--show-secrets")
|
||||
if err != nil {
|
||||
return state, newAutoError(errors.Wrap(err, "could not export stack."), stdout, stderr, errCode)
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(stdout), &state)
|
||||
if err != nil {
|
||||
return state, newAutoError(
|
||||
errors.Wrap(err, "failed to export stack, unable to unmarshall stack state."), stdout, stderr, errCode,
|
||||
)
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// ImportStack imports the specified deployment state into a pre-existing stack.
|
||||
// This can be combined with ExportStack to edit a stack's state (such as recovery from failed deployments).
|
||||
func (l *LocalWorkspace) ImportStack(ctx context.Context, stackName string, state apitype.UntypedDeployment) error {
|
||||
err := l.SelectStack(ctx, stackName)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not import stack, failed to select stack %s.", stackName)
|
||||
}
|
||||
|
||||
f, err := ioutil.TempFile(os.TempDir(), "")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not import stack. failed to get allocate temp file.")
|
||||
}
|
||||
defer func() { contract.IgnoreError(os.Remove(f.Name())) }()
|
||||
|
||||
bytes, err := json.Marshal(state)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not import stack, failed to marshal stack state.")
|
||||
}
|
||||
|
||||
_, err = f.Write(bytes)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not import stack. failed to write out stack intermediate.")
|
||||
}
|
||||
|
||||
stdout, stderr, errCode, err := l.runPulumiCmdSync(ctx, "stack", "import", "--file", f.Name())
|
||||
if err != nil {
|
||||
return newAutoError(errors.Wrap(err, "could not import stack."), stdout, stderr, errCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LocalWorkspace) runPulumiCmdSync(
|
||||
ctx context.Context,
|
||||
args ...string,
|
||||
|
|
|
@ -930,6 +930,78 @@ func TestNestedStackFails(t *testing.T) {
|
|||
assert.Equal(t, "succeeded", dRes.Summary.Result)
|
||||
}
|
||||
|
||||
func TestImportExportStack(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
sName := fmt.Sprintf("int_test%d", rangeIn(10000000, 99999999))
|
||||
stackName := FullyQualifiedStackName(pulumiOrg, pName, sName)
|
||||
cfg := ConfigMap{
|
||||
"bar": ConfigValue{
|
||||
Value: "abc",
|
||||
},
|
||||
"buzz": ConfigValue{
|
||||
Value: "secret",
|
||||
Secret: true,
|
||||
},
|
||||
}
|
||||
|
||||
// initialize
|
||||
s, err := NewStackInlineSource(ctx, stackName, pName, func(ctx *pulumi.Context) error {
|
||||
c := config.New(ctx, "")
|
||||
ctx.Export("exp_static", pulumi.String("foo"))
|
||||
ctx.Export("exp_cfg", pulumi.String(c.Get("bar")))
|
||||
ctx.Export("exp_secret", c.GetSecret("buzz"))
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("failed to initialize stack, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// -- pulumi stack rm --
|
||||
err = s.Workspace().RemoveStack(ctx, s.Name())
|
||||
assert.Nil(t, err, "failed to remove stack. Resources have leaked.")
|
||||
}()
|
||||
|
||||
err = s.SetAllConfig(ctx, cfg)
|
||||
if err != nil {
|
||||
t.Errorf("failed to set config, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// -- pulumi up --
|
||||
_, err = s.Up(ctx)
|
||||
if err != nil {
|
||||
t.Errorf("up failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// -- pulumi stack export --
|
||||
state, err := s.Export(ctx)
|
||||
if err != nil {
|
||||
t.Errorf("export failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// -- pulumi stack import --
|
||||
err = s.Import(ctx, state)
|
||||
if err != nil {
|
||||
t.Errorf("import failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
// -- pulumi destroy --
|
||||
|
||||
dRes, err := s.Destroy(ctx)
|
||||
if err != nil {
|
||||
t.Errorf("destroy failed, err: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
assert.Equal(t, "destroy", dRes.Summary.Kind)
|
||||
assert.Equal(t, "succeeded", dRes.Summary.Result)
|
||||
}
|
||||
|
||||
func getTestOrg() string {
|
||||
testOrg := "pulumi-test"
|
||||
if _, set := os.LookupEnv("PULUMI_TEST_ORG"); set {
|
||||
|
|
|
@ -568,6 +568,36 @@ func (s *Stack) Info(ctx context.Context) (StackSummary, error) {
|
|||
return info, nil
|
||||
}
|
||||
|
||||
// Cancel stops a stack's currently running update. It returns an error if no update is currently running.
|
||||
// Note that this operation is _very dangerous_, and may leave the stack in an inconsistent state
|
||||
// if a resource operation was pending when the update was canceled.
|
||||
// This command is not supported for local backends.
|
||||
func (s *Stack) Cancel(ctx context.Context) error {
|
||||
err := s.Workspace().SelectStack(ctx, s.Name())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to cancel update")
|
||||
}
|
||||
|
||||
stdout, stderr, errCode, err := s.runPulumiCmdSync(ctx, "cancel", "--yes")
|
||||
if err != nil {
|
||||
return newAutoError(errors.Wrap(err, "failed to cancel update"), stdout, stderr, errCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Export exports the deployment state of the stack.
|
||||
// This can be combined with Stack.Import to edit a stack's state (such as recovery from failed deployments).
|
||||
func (s *Stack) Export(ctx context.Context) (apitype.UntypedDeployment, error) {
|
||||
return s.Workspace().ExportStack(ctx, s.Name())
|
||||
}
|
||||
|
||||
// Import imports the specified deployment state into the stack.
|
||||
// This can be combined with Stack.Export to edit a stack's state (such as recovery from failed deployments).
|
||||
func (s *Stack) Import(ctx context.Context, state apitype.UntypedDeployment) error {
|
||||
return s.Workspace().ImportStack(ctx, s.Name(), state)
|
||||
}
|
||||
|
||||
// UpdateSummary provides a summary of a Stack lifecycle operation (up/preview/refresh/destroy).
|
||||
type UpdateSummary struct {
|
||||
Kind string `json:"kind"`
|
||||
|
|
|
@ -17,6 +17,7 @@ package auto
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/common/apitype"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/common/workspace"
|
||||
"github.com/pulumi/pulumi/sdk/v2/go/pulumi"
|
||||
)
|
||||
|
@ -96,6 +97,12 @@ type Workspace interface {
|
|||
Program() pulumi.RunFunc
|
||||
// SetProgram sets the program associated with the Workspace to the specified `pulumi.RunFunc`.
|
||||
SetProgram(pulumi.RunFunc)
|
||||
// ExportStack exports the deployment state of the stack matching the given name.
|
||||
// This can be combined with ImportStack to edit a stack's state (such as recovery from failed deployments).
|
||||
ExportStack(context.Context, string) (apitype.UntypedDeployment, error)
|
||||
// ImportStack imports the specified deployment state into a pre-existing stack.
|
||||
// This can be combined with ExportStack to edit a stack's state (such as recovery from failed deployments).
|
||||
ImportStack(context.Context, string, apitype.UntypedDeployment) error
|
||||
}
|
||||
|
||||
// ConfigValue is a configuration value used by a Pulumi program.
|
||||
|
|
Loading…
Reference in a new issue