New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Warn users when there are pending operations but proceed with deployment #9293
Changes from 4 commits
65b43cf
2cc4d96
fd21ab3
174750c
2d32211
b221427
79dae0b
1ce1e2a
93083fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -550,11 +550,6 @@ func TestPreviewWithPendingOperations(t *testing.T) { | |
// A preview should succeed despite the pending operations. | ||
_, res := op.Run(project, target, options, true, nil, nil) | ||
assert.Nil(t, res) | ||
|
||
// But an update should fail. | ||
_, res = op.Run(project, target, options, false, nil, nil) | ||
assertIsErrorOrBailResult(t, res) | ||
assert.EqualError(t, res.Error(), deploy.PlanPendingOperationsError{}.Error()) | ||
} | ||
|
||
// Tests that a refresh works for a stack with pending operations. | ||
|
@@ -605,11 +600,6 @@ func TestRefreshWithPendingOperations(t *testing.T) { | |
options := UpdateOptions{Host: deploytest.NewPluginHost(nil, nil, program, loaders...)} | ||
project, target := p.GetProject(), p.GetTarget(t, old) | ||
|
||
// Without refreshing, an update should fail. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above |
||
_, res := op.Run(project, target, options, false, nil, nil) | ||
assertIsErrorOrBailResult(t, res) | ||
assert.EqualError(t, res.Error(), deploy.PlanPendingOperationsError{}.Error()) | ||
|
||
// With a refresh, the update should succeed. | ||
withRefresh := options | ||
withRefresh.Refresh = true | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,6 +97,35 @@ func (ex *deploymentExecutor) checkTargets(targets []resource.URN, op StepOp) re | |
return nil | ||
} | ||
|
||
func (ex *deploymentExecutor) printPendingOperationsWarning() { | ||
pendingOperations := "" | ||
for _, op := range ex.deployment.prev.PendingOperations { | ||
pendingOperations = pendingOperations + fmt.Sprintf(" * %s, interrupted while %s\n", op.Resource.URN, op.Type) | ||
} | ||
|
||
resolutionMessage := `These resources are in an unknown state because the Pulumi CLI was interrupted while | ||
waiting for changes to these resources to complete. You should confirm whether or not the | ||
operations listed completed successfully by checking the state of the appropriate provider. | ||
For example, if you are using AWS, you can confirm using the AWS Console. | ||
|
||
Once you have confirmed the status of the interrupted operations, you can repair your stack | ||
using 'pulumi refresh' which will refresh the state from the provider you are using and | ||
clear the pending operations if there are any. | ||
|
||
Note that 'pulumi refresh' will not clear pending CREATE operations since those could have resulted in resources | ||
which are not tracked by pulumi. To repair the stack and remove pending CREATE operation, | ||
use 'pulumi stack export' which will export your stack to a file. For each operation that succeeded, | ||
remove that operation from the "pending_operations" section of the file. Once this is complete, | ||
use 'pulumi stack import' to import the repaired stack.` | ||
|
||
warning := "Attempting to deploy or update resources " + | ||
fmt.Sprintf("with %d pending operations from previous deployment.\n", len(ex.deployment.prev.PendingOperations)) + | ||
pendingOperations + | ||
resolutionMessage | ||
|
||
ex.deployment.Diag().Warningf(diag.RawMessage("" /*urn*/, warning)) | ||
} | ||
|
||
// reportExecResult issues an appropriate diagnostic depending on went wrong. | ||
func (ex *deploymentExecutor) reportExecResult(message string, preview bool) { | ||
kind := "update" | ||
|
@@ -146,8 +175,11 @@ func (ex *deploymentExecutor) Execute(callerCtx context.Context, opts Options, p | |
if opts.RefreshOnly { | ||
return nil, nil | ||
} | ||
} else if ex.deployment.prev != nil && len(ex.deployment.prev.PendingOperations) != 0 && !preview { | ||
return nil, result.FromError(PlanPendingOperationsError{ex.deployment.prev.PendingOperations}) | ||
} else if ex.deployment.prev != nil && len(ex.deployment.prev.PendingOperations) > 0 && !preview { | ||
// Print a warning for users that there are pending operations. | ||
// Explain that these operations can be cleared using pulumi refresh (except for CREATE operations) | ||
// since these require user intevention: | ||
ex.printPendingOperationsWarning() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly to what we did with refresh I think we might want to do something to ensure that after doing the update our snapshot still tracks that there were pending operations that were not resovled. |
||
} | ||
|
||
// The set of -t targets provided on the command line. 'nil' means 'update everything'. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should test we get the expected warning here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see this is now just for preview and we have tests elsewhere for updates.