Merge pull request #29863 from hashicorp/barrettclark/migrate-empty-default-workspace

Cloud: Migrate empty default workspace prompt
This commit is contained in:
Barrett Clark 2021-11-16 13:27:39 -06:00 committed by GitHub
commit 02aacb09e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 94 additions and 7 deletions

View File

@ -157,6 +157,77 @@ func Test_migrate_multi_to_tfc_cloud_name_strategy(t *testing.T) {
}
},
},
"migrating multiple workspaces to cloud using name strategy; 'default' workspace is empty": {
operations: []operationSets{
{
prep: func(t *testing.T, orgName, dir string) {
tfBlock := terraformConfigLocalBackend()
writeMainTF(t, tfBlock, dir)
},
commands: []tfCommand{
{
command: []string{"init"},
expectedCmdOutput: `Successfully configured the backend "local"!`,
},
{
command: []string{"workspace", "new", "workspace1"},
expectedCmdOutput: `Created and switched to workspace "workspace1"!`,
},
{
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
{
command: []string{"workspace", "new", "workspace2"},
expectedCmdOutput: `Created and switched to workspace "workspace2"!`,
},
{
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
},
{
prep: func(t *testing.T, orgName, dir string) {
wsName := "new-workspace"
tfBlock := terraformConfigCloudBackendName(orgName, wsName)
writeMainTF(t, tfBlock, dir)
},
commands: []tfCommand{
{
command: []string{"init", "-migrate-state"},
expectedCmdOutput: `Do you want to copy only your current workspace?`,
userInput: []string{"yes", "yes"},
postInputOutput: []string{
`Do you want to copy existing state to Terraform Cloud?`,
`Terraform Cloud has been successfully initialized!`},
},
{
command: []string{"workspace", "select", "default"},
expectError: true,
},
{
command: []string{"output"},
expectedCmdOutput: `val = "workspace2"`, // this was the output of the current workspace selected before migration
},
},
},
},
validations: func(t *testing.T, orgName string) {
wsList, err := tfeClient.Workspaces.List(ctx, orgName, tfe.WorkspaceListOptions{})
if err != nil {
t.Fatal(err)
}
if len(wsList.Items) != 1 {
t.Fatalf("Expected the number of workspaces to be 1, but got %d", len(wsList.Items))
}
ws := wsList.Items[0]
// this workspace name is what exists in the cloud backend configuration block
if ws.Name != "new-workspace" {
t.Fatalf("Expected workspace to be `new-workspace`, but is %s", ws.Name)
}
},
},
}
for name, tc := range cases {
@ -220,7 +291,7 @@ func Test_migrate_multi_to_tfc_cloud_name_strategy(t *testing.T) {
}
err = cmd.Wait()
if err != nil {
if err != nil && !tfCmd.expectError {
t.Fatal(err)
}
}

View File

@ -622,18 +622,34 @@ func (m *Meta) backendMigrateState_S_TFC(opts *backendMigrateOpts, sourceWorkspa
newCurrentWorkspace := ""
// This map is used later when doing the migration per source/destination.
// If a source has 'default', then we ask what the new name should be.
// If a source has 'default' and has state, then we ask what the new name should be.
// And further down when we actually run state migration for each
// sourc/destination workspce, we use this new name (where source is 'default')
// and set as destinationWorkspace.
// source/destination workspace, we use this new name (where source is 'default')
// and set as destinationWorkspace. If the default workspace does not have
// state we will not prompt the user for a new name because empty workspaces
// do not get migrated.
defaultNewName := map[string]string{}
for i := 0; i < len(sourceWorkspaces); i++ {
if sourceWorkspaces[i] == backend.DefaultStateName {
newName, err := m.promptNewWorkspaceName(opts.DestinationType)
// For the default workspace we want to look to see if there is any state
// before we ask for a workspace name to migrate the default workspace into.
sourceState, err := opts.Source.StateMgr(backend.DefaultStateName)
if err != nil {
return err
return fmt.Errorf(strings.TrimSpace(
errMigrateSingleLoadDefault), opts.SourceType, err)
}
// RefreshState is what actually pulls the state to be evaluated.
if err := sourceState.RefreshState(); err != nil {
return fmt.Errorf(strings.TrimSpace(
errMigrateSingleLoadDefault), opts.SourceType, err)
}
if !sourceState.State().Empty() {
newName, err := m.promptNewWorkspaceName(opts.DestinationType)
if err != nil {
return err
}
defaultNewName[sourceWorkspaces[i]] = newName
}
defaultNewName[sourceWorkspaces[i]] = newName
}
}