github.com/kevinklinger/open_terraform@v1.3.6/noninternal/cloud/e2e/migrate_state_multi_to_tfc_test.go (about) 1 package main 2 3 import ( 4 "context" 5 "testing" 6 7 tfe "github.com/hashicorp/go-tfe" 8 tfversion "github.com/kevinklinger/open_terraform/version" 9 ) 10 11 func Test_migrate_multi_to_tfc_cloud_name_strategy(t *testing.T) { 12 t.Parallel() 13 skipIfMissingEnvVar(t) 14 skipWithoutRemoteTerraformVersion(t) 15 16 ctx := context.Background() 17 18 cases := testCases{ 19 "migrating multiple workspaces to cloud using name strategy; current workspace is 'default'": { 20 operations: []operationSets{ 21 { 22 prep: func(t *testing.T, orgName, dir string) { 23 tfBlock := terraformConfigLocalBackend() 24 writeMainTF(t, tfBlock, dir) 25 }, 26 commands: []tfCommand{ 27 { 28 command: []string{"init"}, 29 expectedCmdOutput: `Successfully configured the backend "local"!`, 30 }, 31 { 32 command: []string{"apply", "-auto-approve"}, 33 postInputOutput: []string{`Apply complete!`}, 34 }, 35 { 36 command: []string{"workspace", "new", "prod"}, 37 expectedCmdOutput: `Created and switched to workspace "prod"!`, 38 }, 39 { 40 command: []string{"apply", "-auto-approve"}, 41 postInputOutput: []string{`Apply complete!`}, 42 }, 43 { 44 command: []string{"workspace", "select", "default"}, 45 expectedCmdOutput: `Switched to workspace "default".`, 46 }, 47 }, 48 }, 49 { 50 prep: func(t *testing.T, orgName, dir string) { 51 wsName := "new-workspace" 52 tfBlock := terraformConfigCloudBackendName(orgName, wsName) 53 writeMainTF(t, tfBlock, dir) 54 }, 55 commands: []tfCommand{ 56 { 57 command: []string{"init"}, 58 expectedCmdOutput: `Do you want to copy only your current workspace?`, 59 userInput: []string{"yes"}, 60 postInputOutput: []string{`Terraform Cloud has been successfully initialized!`}, 61 }, 62 { 63 command: []string{"workspace", "show"}, 64 expectedCmdOutput: `new-workspace`, // this comes from the `prep` function 65 }, 66 { 67 command: []string{"output"}, 68 expectedCmdOutput: `val = "default"`, // this was the output of the current workspace selected before migration 69 }, 70 }, 71 }, 72 }, 73 validations: func(t *testing.T, orgName string) { 74 wsList, err := tfeClient.Workspaces.List(ctx, orgName, nil) 75 if err != nil { 76 t.Fatal(err) 77 } 78 if len(wsList.Items) != 1 { 79 t.Fatalf("Expected the number of workspaces to be 1, but got %d", len(wsList.Items)) 80 } 81 ws := wsList.Items[0] 82 // this workspace name is what exists in the cloud backend configuration block 83 if ws.Name != "new-workspace" { 84 t.Fatalf("Expected workspace to be `new-workspace`, but is %s", ws.Name) 85 } 86 }, 87 }, 88 "migrating multiple workspaces to cloud using name strategy; current workspace is 'prod'": { 89 operations: []operationSets{ 90 { 91 prep: func(t *testing.T, orgName, dir string) { 92 tfBlock := terraformConfigLocalBackend() 93 writeMainTF(t, tfBlock, dir) 94 }, 95 commands: []tfCommand{ 96 { 97 command: []string{"init"}, 98 expectedCmdOutput: `Successfully configured the backend "local"!`, 99 }, 100 { 101 command: []string{"apply", "-auto-approve"}, 102 postInputOutput: []string{`Apply complete!`}, 103 }, 104 { 105 command: []string{"workspace", "new", "prod"}, 106 expectedCmdOutput: `Created and switched to workspace "prod"!`, 107 }, 108 { 109 command: []string{"apply", "-auto-approve"}, 110 postInputOutput: []string{`Apply complete!`}, 111 }, 112 }, 113 }, 114 { 115 prep: func(t *testing.T, orgName, dir string) { 116 wsName := "new-workspace" 117 tfBlock := terraformConfigCloudBackendName(orgName, wsName) 118 writeMainTF(t, tfBlock, dir) 119 }, 120 commands: []tfCommand{ 121 { 122 command: []string{"init"}, 123 expectedCmdOutput: `Do you want to copy only your current workspace?`, 124 userInput: []string{"yes"}, 125 postInputOutput: []string{`Terraform Cloud has been successfully initialized!`}, 126 }, 127 { 128 command: []string{"workspace", "list"}, 129 expectedCmdOutput: `new-workspace`, // this comes from the `prep` function 130 }, 131 { 132 command: []string{"output"}, 133 expectedCmdOutput: `val = "prod"`, 134 }, 135 }, 136 }, 137 }, 138 validations: func(t *testing.T, orgName string) { 139 wsList, err := tfeClient.Workspaces.List(ctx, orgName, nil) 140 if err != nil { 141 t.Fatal(err) 142 } 143 ws := wsList.Items[0] 144 // this workspace name is what exists in the cloud backend configuration block 145 if ws.Name != "new-workspace" { 146 t.Fatalf("Expected workspace to be `new-workspace`, but is %s", ws.Name) 147 } 148 }, 149 }, 150 "migrating multiple workspaces to cloud using name strategy; 'default' workspace is empty": { 151 operations: []operationSets{ 152 { 153 prep: func(t *testing.T, orgName, dir string) { 154 tfBlock := terraformConfigLocalBackend() 155 writeMainTF(t, tfBlock, dir) 156 }, 157 commands: []tfCommand{ 158 { 159 command: []string{"init"}, 160 expectedCmdOutput: `Successfully configured the backend "local"!`, 161 }, 162 { 163 command: []string{"workspace", "new", "workspace1"}, 164 expectedCmdOutput: `Created and switched to workspace "workspace1"!`, 165 }, 166 { 167 command: []string{"apply", "-auto-approve"}, 168 postInputOutput: []string{`Apply complete!`}, 169 }, 170 { 171 command: []string{"workspace", "new", "workspace2"}, 172 expectedCmdOutput: `Created and switched to workspace "workspace2"!`, 173 }, 174 { 175 command: []string{"apply", "-auto-approve"}, 176 postInputOutput: []string{`Apply complete!`}, 177 }, 178 }, 179 }, 180 { 181 prep: func(t *testing.T, orgName, dir string) { 182 wsName := "new-workspace" 183 tfBlock := terraformConfigCloudBackendName(orgName, wsName) 184 writeMainTF(t, tfBlock, dir) 185 }, 186 commands: []tfCommand{ 187 { 188 command: []string{"init"}, 189 expectedCmdOutput: `Do you want to copy only your current workspace?`, 190 userInput: []string{"yes"}, 191 postInputOutput: []string{`Terraform Cloud has been successfully initialized!`}, 192 }, 193 { 194 command: []string{"workspace", "select", "default"}, 195 expectError: true, 196 }, 197 { 198 command: []string{"output"}, 199 expectedCmdOutput: `val = "workspace2"`, // this was the output of the current workspace selected before migration 200 }, 201 }, 202 }, 203 }, 204 validations: func(t *testing.T, orgName string) { 205 wsList, err := tfeClient.Workspaces.List(ctx, orgName, nil) 206 if err != nil { 207 t.Fatal(err) 208 } 209 if len(wsList.Items) != 1 { 210 t.Fatalf("Expected the number of workspaces to be 1, but got %d", len(wsList.Items)) 211 } 212 ws := wsList.Items[0] 213 // this workspace name is what exists in the cloud backend configuration block 214 if ws.Name != "new-workspace" { 215 t.Fatalf("Expected workspace to be `new-workspace`, but is %s", ws.Name) 216 } 217 }, 218 }, 219 } 220 221 testRunner(t, cases, 1) 222 } 223 224 func Test_migrate_multi_to_tfc_cloud_tags_strategy(t *testing.T) { 225 t.Parallel() 226 skipIfMissingEnvVar(t) 227 skipWithoutRemoteTerraformVersion(t) 228 229 ctx := context.Background() 230 231 cases := map[string]struct { 232 operations []operationSets 233 validations func(t *testing.T, orgName string) 234 }{ 235 "migrating multiple workspaces to cloud using tags strategy; pattern is using prefix `app-*`": { 236 operations: []operationSets{ 237 { 238 prep: func(t *testing.T, orgName, dir string) { 239 tfBlock := terraformConfigLocalBackend() 240 writeMainTF(t, tfBlock, dir) 241 }, 242 commands: []tfCommand{ 243 { 244 command: []string{"init"}, 245 expectedCmdOutput: `Successfully configured the backend "local"!`, 246 }, 247 { 248 command: []string{"apply", "-auto-approve"}, 249 postInputOutput: []string{`Apply complete!`}, 250 }, 251 { 252 command: []string{"workspace", "new", "prod"}, 253 expectedCmdOutput: `Created and switched to workspace "prod"!`, 254 }, 255 { 256 command: []string{"apply", "-auto-approve"}, 257 postInputOutput: []string{`Apply complete!`}, 258 }, 259 { 260 command: []string{"workspace", "select", "default"}, 261 expectedCmdOutput: `Switched to workspace "default".`, 262 }, 263 { 264 command: []string{"output"}, 265 expectedCmdOutput: `val = "default"`, 266 }, 267 { 268 command: []string{"workspace", "select", "prod"}, 269 expectedCmdOutput: `Switched to workspace "prod".`, 270 }, 271 { 272 command: []string{"output"}, 273 expectedCmdOutput: `val = "prod"`, 274 }, 275 }, 276 }, 277 { 278 prep: func(t *testing.T, orgName, dir string) { 279 tag := "app" 280 tfBlock := terraformConfigCloudBackendTags(orgName, tag) 281 writeMainTF(t, tfBlock, dir) 282 }, 283 commands: []tfCommand{ 284 { 285 command: []string{"init"}, 286 expectedCmdOutput: `Terraform Cloud requires all workspaces to be given an explicit name.`, 287 userInput: []string{"dev", "1", "app-*"}, 288 postInputOutput: []string{ 289 `Would you like to rename your workspaces?`, 290 "How would you like to rename your workspaces?", 291 "Terraform Cloud has been successfully initialized!"}, 292 }, 293 { 294 command: []string{"workspace", "select", "app-dev"}, 295 expectedCmdOutput: `Switched to workspace "app-dev".`, 296 }, 297 { 298 command: []string{"output"}, 299 expectedCmdOutput: `val = "default"`, 300 }, 301 { 302 command: []string{"workspace", "select", "app-prod"}, 303 expectedCmdOutput: `Switched to workspace "app-prod".`, 304 }, 305 { 306 command: []string{"output"}, 307 expectedCmdOutput: `val = "prod"`, 308 }, 309 }, 310 }, 311 }, 312 validations: func(t *testing.T, orgName string) { 313 wsList, err := tfeClient.Workspaces.List(ctx, orgName, &tfe.WorkspaceListOptions{ 314 Tags: "app", 315 }) 316 if err != nil { 317 t.Fatal(err) 318 } 319 if len(wsList.Items) != 2 { 320 t.Fatalf("Expected the number of workspaecs to be 2, but got %d", len(wsList.Items)) 321 } 322 expectedWorkspaceNames := []string{"app-prod", "app-dev"} 323 for _, ws := range wsList.Items { 324 hasName := false 325 for _, expectedNames := range expectedWorkspaceNames { 326 if expectedNames == ws.Name { 327 hasName = true 328 } 329 } 330 if !hasName { 331 t.Fatalf("Worksapce %s is not in the expected list of workspaces", ws.Name) 332 } 333 } 334 }, 335 }, 336 "migrating multiple workspaces to cloud using tags strategy; existing workspaces": { 337 operations: []operationSets{ 338 { 339 prep: func(t *testing.T, orgName, dir string) { 340 tfBlock := terraformConfigLocalBackend() 341 writeMainTF(t, tfBlock, dir) 342 }, 343 commands: []tfCommand{ 344 { 345 command: []string{"init"}, 346 expectedCmdOutput: `Successfully configured the backend "local"!`, 347 }, 348 { 349 command: []string{"apply", "-auto-approve"}, 350 postInputOutput: []string{`Apply complete!`}, 351 }, 352 { 353 command: []string{"workspace", "new", "identity"}, 354 expectedCmdOutput: `Created and switched to workspace "identity"!`, 355 }, 356 { 357 command: []string{"apply", "-auto-approve"}, 358 postInputOutput: []string{`Apply complete!`}, 359 }, 360 { 361 command: []string{"workspace", "new", "billing"}, 362 expectedCmdOutput: `Created and switched to workspace "billing"!`, 363 }, 364 { 365 command: []string{"apply", "-auto-approve"}, 366 postInputOutput: []string{`Apply complete!`}, 367 }, 368 { 369 command: []string{"workspace", "select", "default"}, 370 expectedCmdOutput: `Switched to workspace "default".`, 371 }, 372 }, 373 }, 374 { 375 prep: func(t *testing.T, orgName, dir string) { 376 tag := "app" 377 _ = createWorkspace(t, orgName, tfe.WorkspaceCreateOptions{ 378 Name: tfe.String("identity"), 379 TerraformVersion: tfe.String(tfversion.String()), 380 }) 381 _ = createWorkspace(t, orgName, tfe.WorkspaceCreateOptions{ 382 Name: tfe.String("billing"), 383 TerraformVersion: tfe.String(tfversion.String()), 384 }) 385 tfBlock := terraformConfigCloudBackendTags(orgName, tag) 386 writeMainTF(t, tfBlock, dir) 387 }, 388 commands: []tfCommand{ 389 { 390 command: []string{"init"}, 391 expectedCmdOutput: `Terraform Cloud requires all workspaces to be given an explicit name.`, 392 userInput: []string{"dev", "1", "app-*"}, 393 postInputOutput: []string{ 394 `Would you like to rename your workspaces?`, 395 "How would you like to rename your workspaces?", 396 "Terraform Cloud has been successfully initialized!"}, 397 }, 398 { 399 command: []string{"workspace", "select", "app-billing"}, 400 expectedCmdOutput: `Switched to workspace "app-billing".`, 401 }, 402 { 403 command: []string{"workspace", "select", "app-identity"}, 404 expectedCmdOutput: `Switched to workspace "app-identity".`, 405 }, 406 { 407 command: []string{"workspace", "select", "app-dev"}, 408 expectedCmdOutput: `Switched to workspace "app-dev".`, 409 }, 410 }, 411 }, 412 }, 413 validations: func(t *testing.T, orgName string) { 414 wsList, err := tfeClient.Workspaces.List(ctx, orgName, &tfe.WorkspaceListOptions{ 415 Tags: "app", 416 }) 417 if err != nil { 418 t.Fatal(err) 419 } 420 if len(wsList.Items) != 3 { 421 t.Fatalf("Expected the number of workspaecs to be 3, but got %d", len(wsList.Items)) 422 } 423 expectedWorkspaceNames := []string{"app-billing", "app-dev", "app-identity"} 424 for _, ws := range wsList.Items { 425 hasName := false 426 for _, expectedNames := range expectedWorkspaceNames { 427 if expectedNames == ws.Name { 428 hasName = true 429 } 430 } 431 if !hasName { 432 t.Fatalf("Worksapce %s is not in the expected list of workspaces", ws.Name) 433 } 434 } 435 }, 436 }, 437 } 438 439 testRunner(t, cases, 1) 440 }