Fix renaming a freshly created stack using the local backend

Attempting to `pulumi stack rename` a stack which had been created but
never updated, when using the local backend, was broken because
code-paths were not hardened against the snapshot being `nil` (which
is the case for a stack before the initial deployment had been done).

Fixes #2654
This commit is contained in:
Matt Ellis 2019-08-13 11:21:00 -07:00
parent 82903927f1
commit 342f8311a1
4 changed files with 36 additions and 7 deletions

View file

@ -8,6 +8,9 @@ CHANGELOG
- Allow resource IDs to be changed during `pulumi refresh` operations
- Do not crash when renaming a stack that has never been updated, when using the local backend. (fixes
[#2654](https://github.com/pulumi/pulumi/issues/2654))
## 1.0.0-beta.2 (2019-08-13)
- Fix the package version compatibility checks in the NodeJS language host.

View file

@ -312,12 +312,15 @@ func (b *localBackend) RenameStack(ctx context.Context, stackRef backend.StackRe
return err
}
// Rewrite the checkpoint and save it with the new name.
if err = edit.RenameStack(snap, newName); err != nil {
return err
// If we have a snapshot, we need to rename the URNs inside it to use the new stack name.
if snap != nil {
if err = edit.RenameStack(snap, newName); err != nil {
return err
}
}
if _, err = b.saveStack(newName, snap, snap.SecretsManager); err != nil {
// Now save the snapshot with a new name (we pass nil to re-use the existing secrets manager from the snapshot)
if _, err = b.saveStack(newName, snap, nil); err != nil {
return err
}
@ -325,11 +328,16 @@ func (b *localBackend) RenameStack(ctx context.Context, stackRef backend.StackRe
file := b.stackPath(stackName)
backupTarget(b.bucket, file)
// And move the history over as well.
// And move the history over as well, if it exists.
oldHistoryDir := b.historyDirectory(stackName)
newHistoryDir := b.historyDirectory(newName)
if _, err := os.Stat(oldHistoryDir); err == nil {
newHistoryDir := b.historyDirectory(newName)
if err := os.Rename(oldHistoryDir, newHistoryDir); err != nil {
return errors.Wrap(err, "renaming history")
}
}
return os.Rename(oldHistoryDir, newHistoryDir)
return nil
}
func (b *localBackend) GetLatestConfiguration(ctx context.Context,

View file

@ -96,6 +96,8 @@ func LocateResource(snap *deploy.Snapshot, urn resource.URN) []*resource.State {
// RenameStack changes the `stackName` component of every URN in a snapshot. In addition, it rewrites the name of
// the root Stack resource itself.
func RenameStack(snap *deploy.Snapshot, newName tokens.QName) error {
contract.Require(snap != nil, "snap")
rewriteUrn := func(u resource.URN) resource.URN {
// The pulumi:pulumi:Stack resource's name component is of the form `<project>-<stack>` so we want
// to rename the name portion as well.

View file

@ -348,6 +348,22 @@ func TestStackBackups(t *testing.T) {
})
}
func TestStackRenameAfterCreate(t *testing.T) {
e := ptesting.NewEnvironment(t)
defer func() {
if !t.Failed() {
e.DeleteEnvironment()
}
}()
stackName := addRandomSuffix("stack-rename")
integration.CreateBasicPulumiRepo(e)
e.RunCommand("pulumi", "login", "--cloud-url", e.LocalURL())
e.RunCommand("pulumi", "stack", "init", stackName)
newName := addRandomSuffix("renamed-stack")
e.RunCommand("pulumi", "stack", "rename", newName)
}
func getFileNames(infos []os.FileInfo) []string {
var result []string
for _, i := range infos {