Merge pull request #29883 from hashicorp/barrettclark/cloud-e2e-tests

Cloud: Make e2e Tests Less Chatty, and More Stable
This commit is contained in:
Barrett Clark 2021-11-15 10:45:14 -06:00 committed by GitHub
commit 388c430ece
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 1619 additions and 1463 deletions

2
go.mod
View File

@ -43,7 +43,7 @@ require (
github.com/hashicorp/go-retryablehttp v0.7.0
github.com/hashicorp/go-tfe v0.20.1-0.20211110172530-c43c6b574caa
github.com/hashicorp/go-uuid v1.0.2
github.com/hashicorp/go-version v1.2.1
github.com/hashicorp/go-version v1.3.0
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f
github.com/hashicorp/hcl/v2 v2.10.1
github.com/hashicorp/terraform-config-inspect v0.0.0-20210209133302-4fd17a0faac2

3
go.sum
View File

@ -388,8 +388,9 @@ github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw=
github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=

View File

@ -0,0 +1,24 @@
# How to run tests
To run them, use:
```
TFE_TOKEN=<token> TFE_HOSTNAME=<hostname> TF_ACC=1 go test ./internal/cloud/e2e/... -ldflags "-X \"github.com/hashicorp/terraform/version.Prerelease=<PRE-RELEASE>\""
```
Required flags
* `TF_ACC=1`. This variable is used as part of terraform for tests that make
external network calls. This is needed to run these tests. Without it, the
tests do not run.
* `TFE_TOKEN=<admin token>` and `TFE_HOSTNAME=<hostname>`. The helpers
for these tests require admin access to a TFC/TFE instance.
* `-timeout=30m`. Some of these tests take longer than the default 10m timeout for `go test`.
### Flags
* Use the `-v` flag for normal verbose mode.
* Use the `-tfoutput` flag to print the terraform output to standard out.
* Use `-ldflags` to change the version Prerelease to match a version
available remotely. Some behaviors rely on the exact local version Terraform
being available in TFC/TFE, and manipulating the Prerelease during build is
often the only way to ensure this.
[(More on `-ldflags`.)](https://www.digitalocean.com/community/tutorials/using-ldflags-to-set-version-information-for-go-applications)

View File

@ -1,12 +1,8 @@
//go:build e2e
// +build e2e
package main
import (
"context"
"io/ioutil"
"log"
"os"
"testing"
@ -17,7 +13,7 @@ import (
)
func Test_terraform_apply_autoApprove(t *testing.T) {
t.Parallel()
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
@ -183,12 +179,10 @@ func Test_terraform_apply_autoApprove(t *testing.T) {
},
},
}
for name, tc := range cases {
log.Println("Test: ", name)
for _, tc := range cases {
organization, cleanup := createOrganization(t)
defer cleanup()
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -201,7 +195,6 @@ func Test_terraform_apply_autoApprove(t *testing.T) {
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv("TF_LOG=info")
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()

View File

@ -1,10 +1,6 @@
//go:build e2e
// +build e2e
package main
import (
"fmt"
"io/ioutil"
"os"
"testing"
@ -14,6 +10,7 @@ import (
)
func Test_backend_apply_before_init(t *testing.T) {
skipIfMissingEnvVar(t)
t.Parallel()
skipWithoutRemoteTerraformVersion(t)
@ -51,9 +48,7 @@ func Test_backend_apply_before_init(t *testing.T) {
expectedCmdOutput: `Successfully configured the backend "local"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
@ -77,10 +72,12 @@ func Test_backend_apply_before_init(t *testing.T) {
}
for name, tc := range cases {
fmt.Println("Test: ", name)
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
organization, cleanup := createOrganization(t)
defer cleanup()
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -93,7 +90,6 @@ func Test_backend_apply_before_init(t *testing.T) {
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv("TF_LOG=info")
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()
@ -140,5 +136,6 @@ func Test_backend_apply_before_init(t *testing.T) {
}
}
}
})
}
}

View File

@ -1,6 +1,3 @@
//go:build e2e
// +build e2e
package main
import (
@ -10,8 +7,10 @@ import (
"testing"
"time"
expect "github.com/Netflix/go-expect"
tfe "github.com/hashicorp/go-tfe"
"github.com/hashicorp/go-uuid"
goversion "github.com/hashicorp/go-version"
tfversion "github.com/hashicorp/terraform/version"
)
@ -22,7 +21,6 @@ const (
type tfCommand struct {
command []string
expectedCmdOutput string
expectedErr string
expectError bool
userInput []string
postInputOutput []string
@ -38,6 +36,16 @@ type testCases map[string]struct {
validations func(t *testing.T, orgName string)
}
func defaultOpts() []expect.ConsoleOpt {
opts := []expect.ConsoleOpt{
expect.WithDefaultTimeout(expectConsoleTimeout),
}
if verboseMode {
opts = append(opts, expect.WithStdout(os.Stdout))
}
return opts
}
func createOrganization(t *testing.T) (*tfe.Organization, func()) {
ctx := context.Background()
org, err := tfeClient.Organizations.Create(ctx, tfe.OrganizationCreateOptions{
@ -93,7 +101,7 @@ func randomString(t *testing.T) string {
}
func terraformConfigLocalBackend() string {
return fmt.Sprintf(`
return `
terraform {
backend "local" {
}
@ -102,7 +110,7 @@ terraform {
output "val" {
value = "${terraform.workspace}"
}
`)
`
}
func terraformConfigRemoteBackendName(org, name string) string {
@ -193,9 +201,16 @@ func writeMainTF(t *testing.T, block string, dir string) {
f.Close()
}
// Ensure that TFC/E has a particular terraform version.
// The e2e tests rely on the fact that the terraform version in TFC/E is able to
// run the `cloud` configuration block, which is available in 1.1 and will
// continue to be available in later versions. So this function checks that
// there is a version that is >= 1.1.
func skipWithoutRemoteTerraformVersion(t *testing.T) {
version := tfversion.String()
version := tfversion.Version
baseVersion, err := goversion.NewVersion(version)
if err != nil {
t.Fatalf(fmt.Sprintf("Error instantiating go-version for %s", version))
}
opts := tfe.AdminTerraformVersionsListOptions{
ListOptions: tfe.ListOptions{
PageNumber: 1,
@ -213,7 +228,12 @@ findTfVersion:
t.Fatalf("Could not retrieve list of terraform versions: %v", err)
}
for _, item := range tfVersionList.Items {
if item.Version == version {
availableVersion, err := goversion.NewVersion(item.Version)
if err != nil {
t.Logf("Error instantiating go-version for %s", item.Version)
continue
}
if availableVersion.Core().GreaterThanOrEqual(baseVersion.Core()) {
hasVersion = true
break findTfVersion
}

View File

@ -1,10 +1,6 @@
//go:build e2e
// +build e2e
package main
import (
"fmt"
"io/ioutil"
"os"
"testing"
@ -14,6 +10,7 @@ import (
)
func Test_init_with_empty_tags(t *testing.T) {
skipIfMissingEnvVar(t)
t.Parallel()
skipWithoutRemoteTerraformVersion(t)
@ -42,10 +39,12 @@ func Test_init_with_empty_tags(t *testing.T) {
}
for name, tc := range cases {
fmt.Println("Test: ", name)
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
organization, cleanup := createOrganization(t)
defer cleanup()
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -58,7 +57,6 @@ func Test_init_with_empty_tags(t *testing.T) {
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv("TF_LOG=info")
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()
@ -105,5 +103,6 @@ func Test_init_with_empty_tags(t *testing.T) {
}
}
}
})
}
}

View File

@ -1,9 +1,7 @@
//go:build e2e
// +build e2e
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
@ -22,13 +20,9 @@ var cliConfigFileEnv string
var tfeClient *tfe.Client
var tfeHostname string
var tfeToken string
var verboseMode bool
func TestMain(m *testing.M) {
log.SetFlags(log.LstdFlags | log.Lshortfile)
if !accTest() {
// if TF_ACC is not set, we want to skip all these tests.
return
}
teardown := setup()
code := m.Run()
teardown()
@ -42,7 +36,29 @@ func accTest() bool {
return os.Getenv("TF_ACC") != ""
}
func hasHostname() bool {
return os.Getenv("TFE_HOSTNAME") != ""
}
func hasToken() bool {
return os.Getenv("TFE_TOKEN") != ""
}
func hasRequiredEnvVars() bool {
return accTest() && hasHostname() && hasToken()
}
func skipIfMissingEnvVar(t *testing.T) {
if !hasRequiredEnvVars() {
t.Skip("Skipping test, required environment variables missing. Use `TF_ACC`, `TFE_HOSTNAME`, `TFE_TOKEN`")
}
}
func setup() func() {
tfOutput := flag.Bool("tfoutput", false, "This flag produces the terraform output from tests.")
flag.Parse()
verboseMode = *tfOutput
setTfeClient()
teardown := setupBinary()
@ -52,41 +68,38 @@ func setup() func() {
}
func setTfeClient() {
hostname := os.Getenv("TFE_HOSTNAME")
token := os.Getenv("TFE_TOKEN")
if hostname == "" {
log.Fatal("hostname cannot be empty")
}
if token == "" {
log.Fatal("token cannot be empty")
}
tfeHostname = hostname
tfeToken = token
tfeHostname = os.Getenv("TFE_HOSTNAME")
tfeToken = os.Getenv("TFE_TOKEN")
cfg := &tfe.Config{
Address: fmt.Sprintf("https://%s", hostname),
Token: token,
Address: fmt.Sprintf("https://%s", tfeHostname),
Token: tfeToken,
}
if tfeHostname != "" && tfeToken != "" {
// Create a new TFE client.
client, err := tfe.NewClient(cfg)
if err != nil {
log.Fatal(err)
fmt.Printf("Could not create new tfe client: %v\n", err)
os.Exit(1)
}
tfeClient = client
}
}
func setupBinary() func() {
log.Println("Setting up terraform binary")
tmpTerraformBinaryDir, err := ioutil.TempDir("", "terraform-test")
if err != nil {
log.Fatal(err)
fmt.Printf("Could not create temp directory: %v\n", err)
os.Exit(1)
}
log.Println(tmpTerraformBinaryDir)
currentDir, err := os.Getwd()
defer os.Chdir(currentDir)
if err != nil {
log.Fatal(err)
fmt.Printf("Could not change directories: %v\n", err)
os.Exit(1)
}
// Getting top level dir
dirPaths := strings.Split(currentDir, "/")
@ -95,7 +108,8 @@ func setupBinary() func() {
topDir := strings.Join(dirPaths[0:topLevel], "/")
if err := os.Chdir(topDir); err != nil {
log.Fatal(err)
fmt.Printf("Could not change directories: %v\n", err)
os.Exit(1)
}
cmd := exec.Command(
@ -106,7 +120,8 @@ func setupBinary() func() {
)
err = cmd.Run()
if err != nil {
log.Fatal(err)
fmt.Printf("Could not run exec command: %v\n", err)
os.Exit(1)
}
credFile := fmt.Sprintf("%s/dev.tfrc", tmpTerraformBinaryDir)
@ -124,11 +139,13 @@ func writeCredRC(file string) {
creds := credentialBlock()
f, err := os.Create(file)
if err != nil {
log.Fatal(err)
fmt.Printf("Could not create file: %v\n", err)
os.Exit(1)
}
_, err = f.WriteString(creds)
if err != nil {
log.Fatal(err)
fmt.Printf("Could not write credentials: %v\n", err)
os.Exit(1)
}
f.Close()
}

View File

@ -1,6 +1,3 @@
//go:build e2e
// +build e2e
package main
import (
@ -16,7 +13,7 @@ import (
)
func Test_migrate_multi_to_tfc_cloud_name_strategy(t *testing.T) {
t.Parallel()
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
@ -38,9 +35,7 @@ func Test_migrate_multi_to_tfc_cloud_name_strategy(t *testing.T) {
expectedCmdOutput: `Successfully configured the backend "local"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
{
@ -48,9 +43,7 @@ func Test_migrate_multi_to_tfc_cloud_name_strategy(t *testing.T) {
expectedCmdOutput: `Created and switched to workspace "prod"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
{
@ -113,9 +106,7 @@ func Test_migrate_multi_to_tfc_cloud_name_strategy(t *testing.T) {
expectedCmdOutput: `Successfully configured the backend "local"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
{
@ -123,9 +114,7 @@ func Test_migrate_multi_to_tfc_cloud_name_strategy(t *testing.T) {
expectedCmdOutput: `Created and switched to workspace "prod"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
@ -171,10 +160,12 @@ func Test_migrate_multi_to_tfc_cloud_name_strategy(t *testing.T) {
}
for name, tc := range cases {
t.Log("Test: ", name)
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
organization, cleanup := createOrganization(t)
defer cleanup()
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -188,14 +179,11 @@ func Test_migrate_multi_to_tfc_cloud_name_strategy(t *testing.T) {
tf := e2e.NewBinary(terraformBin, tmpDir)
defer tf.Close()
tf.AddEnv("TF_LOG=INFO")
tf.AddEnv(cliConfigFileEnv)
for _, op := range tc.operations {
op.prep(t, organization.Name, tf.WorkDir())
for _, tfCmd := range op.commands {
t.Log("Running commands: ", tfCmd.command)
tfCmd.command = append(tfCmd.command)
cmd := tf.Cmd(tfCmd.command...)
cmd.Stdin = exp.Tty()
cmd.Stdout = exp.Tty()
@ -241,12 +229,12 @@ func Test_migrate_multi_to_tfc_cloud_name_strategy(t *testing.T) {
if tc.validations != nil {
tc.validations(t, organization.Name)
}
})
}
}
func Test_migrate_multi_to_tfc_cloud_tags_strategy(t *testing.T) {
t.Parallel()
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
@ -268,9 +256,7 @@ func Test_migrate_multi_to_tfc_cloud_tags_strategy(t *testing.T) {
expectedCmdOutput: `Successfully configured the backend "local"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
{
@ -278,9 +264,7 @@ func Test_migrate_multi_to_tfc_cloud_tags_strategy(t *testing.T) {
expectedCmdOutput: `Created and switched to workspace "prod"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
{
@ -311,21 +295,12 @@ func Test_migrate_multi_to_tfc_cloud_tags_strategy(t *testing.T) {
{
command: []string{"init", "-migrate-state"},
expectedCmdOutput: `Terraform Cloud requires all workspaces to be given an explicit name.`,
userInput: []string{"dev", "1", "app-*", "1"},
userInput: []string{"dev", "1", "app-*"},
postInputOutput: []string{
`Would you like to rename your workspaces?`,
"What pattern would you like to add to all your workspaces?",
"The currently selected workspace (prod) does not exist.",
"How would you like to rename your workspaces?",
"Terraform Cloud has been successfully initialized!"},
},
{
command: []string{"workspace", "select", "app-prod"},
expectedCmdOutput: `Switched to workspace "app-prod".`,
},
{
command: []string{"output"},
expectedCmdOutput: `val = "prod"`,
},
{
command: []string{"workspace", "select", "app-dev"},
expectedCmdOutput: `Switched to workspace "app-dev".`,
@ -334,6 +309,14 @@ func Test_migrate_multi_to_tfc_cloud_tags_strategy(t *testing.T) {
command: []string{"output"},
expectedCmdOutput: `val = "default"`,
},
{
command: []string{"workspace", "select", "app-prod"},
expectedCmdOutput: `Switched to workspace "app-prod".`,
},
{
command: []string{"output"},
expectedCmdOutput: `val = "prod"`,
},
},
},
},
@ -417,17 +400,12 @@ func Test_migrate_multi_to_tfc_cloud_tags_strategy(t *testing.T) {
{
command: []string{"init", "-migrate-state"},
expectedCmdOutput: `Terraform Cloud requires all workspaces to be given an explicit name.`,
userInput: []string{"dev", "1", "app-*", "1"},
userInput: []string{"dev", "1", "app-*"},
postInputOutput: []string{
`Would you like to rename your workspaces?`,
"What pattern would you like to add to all your workspaces?",
"The currently selected workspace (default) does not exist.",
"How would you like to rename your workspaces?",
"Terraform Cloud has been successfully initialized!"},
},
{
command: []string{"workspace", "select", "app-dev"},
expectedCmdOutput: `Switched to workspace "app-dev".`,
},
{
command: []string{"workspace", "select", "app-billing"},
expectedCmdOutput: `Switched to workspace "app-billing".`,
@ -436,6 +414,10 @@ func Test_migrate_multi_to_tfc_cloud_tags_strategy(t *testing.T) {
command: []string{"workspace", "select", "app-identity"},
expectedCmdOutput: `Switched to workspace "app-identity".`,
},
{
command: []string{"workspace", "select", "app-dev"},
expectedCmdOutput: `Switched to workspace "app-dev".`,
},
},
},
},
@ -466,11 +448,12 @@ func Test_migrate_multi_to_tfc_cloud_tags_strategy(t *testing.T) {
}
for name, tc := range cases {
t.Log("Test: ", name)
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
organization, cleanup := createOrganization(t)
t.Log(organization.Name)
defer cleanup()
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -484,13 +467,11 @@ func Test_migrate_multi_to_tfc_cloud_tags_strategy(t *testing.T) {
tf := e2e.NewBinary(terraformBin, tmpDir)
defer tf.Close()
tf.AddEnv("TF_LOG=INFO")
tf.AddEnv(cliConfigFileEnv)
for _, op := range tc.operations {
op.prep(t, organization.Name, tf.WorkDir())
for _, tfCmd := range op.commands {
t.Log("running commands: ", tfCmd.command)
cmd := tf.Cmd(tfCmd.command...)
cmd.Stdin = exp.Tty()
cmd.Stdout = exp.Tty()
@ -539,5 +520,6 @@ func Test_migrate_multi_to_tfc_cloud_tags_strategy(t *testing.T) {
if tc.validations != nil {
tc.validations(t, organization.Name)
}
})
}
}

View File

@ -1,6 +1,3 @@
//go:build e2e
// +build e2e
package main
import (
@ -15,16 +12,11 @@ import (
)
func Test_migrate_remote_backend_name_to_tfc_name(t *testing.T) {
t.Parallel()
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
cases := map[string]struct {
operations []operationSets
validations func(t *testing.T, orgName string)
}{
"backend name strategy, to cloud with name strategy": {
operations: []operationSets{
operations := []operationSets{
{
prep: func(t *testing.T, orgName, dir string) {
remoteWorkspace := "remote-workspace"
@ -37,9 +29,7 @@ func Test_migrate_remote_backend_name_to_tfc_name(t *testing.T) {
expectedCmdOutput: `Successfully configured the backend "remote"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions in workspace "remote-workspace"?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
@ -63,8 +53,8 @@ func Test_migrate_remote_backend_name_to_tfc_name(t *testing.T) {
},
},
},
},
validations: func(t *testing.T, orgName string) {
}
validations := func(t *testing.T, orgName string) {
expectedName := "cloud-workspace"
ws, err := tfeClient.Workspaces.Read(ctx, orgName, expectedName)
if err != nil {
@ -73,63 +63,9 @@ func Test_migrate_remote_backend_name_to_tfc_name(t *testing.T) {
if ws == nil {
t.Fatalf("Expected workspace %s to be present, but is not.", expectedName)
}
},
},
"backend name strategy, to cloud name strategy, using the same name": {
operations: []operationSets{
{
prep: func(t *testing.T, orgName, dir string) {
remoteWorkspace := "remote-workspace"
tfBlock := terraformConfigRemoteBackendName(orgName, remoteWorkspace)
writeMainTF(t, tfBlock, dir)
},
commands: []tfCommand{
{
command: []string{"init"},
expectedCmdOutput: `Successfully configured the backend "remote"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions in workspace "remote-workspace"?`,
userInput: []string{"yes"},
postInputOutput: []string{`Apply complete!`},
},
},
},
{
prep: func(t *testing.T, orgName, dir string) {
wsName := "remote-workspace"
tfBlock := terraformConfigCloudBackendName(orgName, wsName)
writeMainTF(t, tfBlock, dir)
},
commands: []tfCommand{
{
command: []string{"init", "-migrate-state", "-ignore-remote-version"},
expectedCmdOutput: `Terraform Cloud has been successfully initialized!`,
},
{
command: []string{"workspace", "show"},
expectedCmdOutput: `remote-workspace`,
},
},
},
},
validations: func(t *testing.T, orgName string) {
expectedName := "remote-workspace"
ws, err := tfeClient.Workspaces.Read(ctx, orgName, expectedName)
if err != nil {
t.Fatal(err)
}
if ws == nil {
t.Fatalf("Expected workspace %s to be present, but is not.", expectedName)
}
},
},
}
for name, tc := range cases {
t.Log("Test: ", name)
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -142,13 +78,12 @@ func Test_migrate_remote_backend_name_to_tfc_name(t *testing.T) {
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv("TF_LOG=INFO")
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()
organization, cleanup := createOrganization(t)
defer cleanup()
for _, op := range tc.operations {
for _, op := range operations {
op.prep(t, organization.Name, tf.WorkDir())
for _, tfCmd := range op.commands {
cmd := tf.Cmd(tfCmd.command...)
@ -193,23 +128,16 @@ func Test_migrate_remote_backend_name_to_tfc_name(t *testing.T) {
}
}
if tc.validations != nil {
tc.validations(t, organization.Name)
}
if validations != nil {
validations(t, organization.Name)
}
}
func Test_migrate_remote_backend_name_to_tfc_name_different_org(t *testing.T) {
t.Parallel()
func Test_migrate_remote_backend_name_to_tfc_same_name(t *testing.T) {
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
cases := map[string]struct {
operations []operationSets
validations func(t *testing.T, orgName string)
}{
"backend name strategy, to cloud name strategy, using the same name, different organization": {
operations: []operationSets{
operations := []operationSets{
{
prep: func(t *testing.T, orgName, dir string) {
remoteWorkspace := "remote-workspace"
@ -222,9 +150,127 @@ func Test_migrate_remote_backend_name_to_tfc_name_different_org(t *testing.T) {
expectedCmdOutput: `Successfully configured the backend "remote"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions in workspace "remote-workspace"?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
},
{
prep: func(t *testing.T, orgName, dir string) {
wsName := "remote-workspace"
tfBlock := terraformConfigCloudBackendName(orgName, wsName)
writeMainTF(t, tfBlock, dir)
},
commands: []tfCommand{
{
command: []string{"init", "-migrate-state", "-ignore-remote-version"},
expectedCmdOutput: `Terraform Cloud has been successfully initialized!`,
},
{
command: []string{"workspace", "show"},
expectedCmdOutput: `remote-workspace`,
},
},
},
}
validations := func(t *testing.T, orgName string) {
expectedName := "remote-workspace"
ws, err := tfeClient.Workspaces.Read(ctx, orgName, expectedName)
if err != nil {
t.Fatal(err)
}
if ws == nil {
t.Fatalf("Expected workspace %s to be present, but is not.", expectedName)
}
}
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
defer exp.Close()
tmpDir, err := ioutil.TempDir("", "terraform-test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()
organization, cleanup := createOrganization(t)
defer cleanup()
for _, op := range operations {
op.prep(t, organization.Name, tf.WorkDir())
for _, tfCmd := range op.commands {
cmd := tf.Cmd(tfCmd.command...)
cmd.Stdin = exp.Tty()
cmd.Stdout = exp.Tty()
cmd.Stderr = exp.Tty()
err = cmd.Start()
if err != nil {
t.Fatal(err)
}
if tfCmd.expectedCmdOutput != "" {
_, err := exp.ExpectString(tfCmd.expectedCmdOutput)
if err != nil {
t.Fatal(err)
}
}
lenInput := len(tfCmd.userInput)
lenInputOutput := len(tfCmd.postInputOutput)
if lenInput > 0 {
for i := 0; i < lenInput; i++ {
input := tfCmd.userInput[i]
exp.SendLine(input)
// use the index to find the corresponding
// output that matches the input.
if lenInputOutput-1 >= i {
output := tfCmd.postInputOutput[i]
_, err := exp.ExpectString(output)
if err != nil {
t.Fatal(err)
}
}
}
}
err = cmd.Wait()
if err != nil {
t.Fatal(err)
}
}
}
if validations != nil {
validations(t, organization.Name)
}
}
func Test_migrate_remote_backend_name_to_tfc_name_different_org(t *testing.T) {
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
operations := []operationSets{
{
prep: func(t *testing.T, orgName, dir string) {
remoteWorkspace := "remote-workspace"
tfBlock := terraformConfigRemoteBackendName(orgName, remoteWorkspace)
writeMainTF(t, tfBlock, dir)
},
commands: []tfCommand{
{
command: []string{"init"},
expectedCmdOutput: `Successfully configured the backend "remote"!`,
},
{
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
@ -248,8 +294,8 @@ func Test_migrate_remote_backend_name_to_tfc_name_different_org(t *testing.T) {
},
},
},
},
validations: func(t *testing.T, orgName string) {
}
validations := func(t *testing.T, orgName string) {
expectedName := "remote-workspace"
ws, err := tfeClient.Workspaces.Read(ctx, orgName, expectedName)
if err != nil {
@ -258,13 +304,9 @@ func Test_migrate_remote_backend_name_to_tfc_name_different_org(t *testing.T) {
if ws == nil {
t.Fatalf("Expected workspace %s to be present, but is not.", expectedName)
}
},
},
}
for name, tc := range cases {
t.Log("Test: ", name)
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -277,7 +319,6 @@ func Test_migrate_remote_backend_name_to_tfc_name_different_org(t *testing.T) {
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv("TF_LOG=INFO")
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()
@ -287,7 +328,7 @@ func Test_migrate_remote_backend_name_to_tfc_name_different_org(t *testing.T) {
defer cleanupTwo()
orgs := []string{orgOne.Name, orgTwo.Name}
var orgName string
for index, op := range tc.operations {
for index, op := range operations {
orgName = orgs[index]
op.prep(t, orgName, tf.WorkDir())
for _, tfCmd := range op.commands {
@ -333,23 +374,17 @@ func Test_migrate_remote_backend_name_to_tfc_name_different_org(t *testing.T) {
}
}
if tc.validations != nil {
tc.validations(t, orgName)
}
if validations != nil {
validations(t, orgName)
}
}
func Test_migrate_remote_backend_name_to_tfc_tags(t *testing.T) {
t.Parallel()
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
cases := map[string]struct {
operations []operationSets
validations func(t *testing.T, orgName string)
}{
"single workspace with backend name strategy, to cloud with tags strategy": {
operations: []operationSets{
operations := []operationSets{
{
prep: func(t *testing.T, orgName, dir string) {
remoteWorkspace := "remote-workspace"
@ -362,9 +397,7 @@ func Test_migrate_remote_backend_name_to_tfc_tags(t *testing.T) {
expectedCmdOutput: `Successfully configured the backend "remote"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions in workspace "remote-workspace"?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
{
@ -394,8 +427,8 @@ func Test_migrate_remote_backend_name_to_tfc_tags(t *testing.T) {
},
},
},
},
validations: func(t *testing.T, orgName string) {
}
validations := func(t *testing.T, orgName string) {
wsList, err := tfeClient.Workspaces.List(ctx, orgName, tfe.WorkspaceListOptions{
Tags: tfe.String("app"),
})
@ -409,13 +442,9 @@ func Test_migrate_remote_backend_name_to_tfc_tags(t *testing.T) {
if ws.Name != "cloud-workspace" {
t.Fatalf("Expected workspace to be `cloud-workspace`, but is %s", ws.Name)
}
},
},
}
for name, tc := range cases {
t.Log("Test: ", name)
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -428,13 +457,12 @@ func Test_migrate_remote_backend_name_to_tfc_tags(t *testing.T) {
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv("TF_LOG=INFO")
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()
organization, cleanup := createOrganization(t)
defer cleanup()
for _, op := range tc.operations {
for _, op := range operations {
op.prep(t, organization.Name, tf.WorkDir())
for _, tfCmd := range op.commands {
cmd := tf.Cmd(tfCmd.command...)
@ -479,23 +507,17 @@ func Test_migrate_remote_backend_name_to_tfc_tags(t *testing.T) {
}
}
if tc.validations != nil {
tc.validations(t, organization.Name)
}
if validations != nil {
validations(t, organization.Name)
}
}
func Test_migrate_remote_backend_prefix_to_tfc_name(t *testing.T) {
t.Parallel()
func Test_migrate_remote_backend_prefix_to_tfc_name_strategy_single_workspace(t *testing.T) {
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
cases := map[string]struct {
operations []operationSets
validations func(t *testing.T, orgName string)
}{
"single workspace with backend prefix strategy, to cloud with name strategy": {
operations: []operationSets{
operations := []operationSets{
{
prep: func(t *testing.T, orgName, dir string) {
_ = createWorkspace(t, orgName, tfe.WorkspaceCreateOptions{Name: tfe.String("app-one")})
@ -509,9 +531,7 @@ func Test_migrate_remote_backend_prefix_to_tfc_name(t *testing.T) {
expectedCmdOutput: `Terraform has been successfully initialized!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions in workspace "app-one"?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
@ -536,8 +556,8 @@ func Test_migrate_remote_backend_prefix_to_tfc_name(t *testing.T) {
},
},
},
},
validations: func(t *testing.T, orgName string) {
}
validations := func(t *testing.T, orgName string) {
expectedName := "cloud-workspace"
ws, err := tfeClient.Workspaces.Read(ctx, orgName, expectedName)
if err != nil {
@ -546,10 +566,82 @@ func Test_migrate_remote_backend_prefix_to_tfc_name(t *testing.T) {
if ws == nil {
t.Fatalf("Expected workspace %s to be present, but is not.", expectedName)
}
},
},
"multiple workspaces with backend prefix strategy, to cloud with name strategy": {
operations: []operationSets{
}
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
defer exp.Close()
tmpDir, err := ioutil.TempDir("", "terraform-test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()
organization, cleanup := createOrganization(t)
defer cleanup()
for _, op := range operations {
op.prep(t, organization.Name, tf.WorkDir())
for _, tfCmd := range op.commands {
cmd := tf.Cmd(tfCmd.command...)
cmd.Stdin = exp.Tty()
cmd.Stdout = exp.Tty()
cmd.Stderr = exp.Tty()
err = cmd.Start()
if err != nil {
t.Fatal(err)
}
if tfCmd.expectedCmdOutput != "" {
_, err := exp.ExpectString(tfCmd.expectedCmdOutput)
if err != nil {
t.Fatal(err)
}
}
lenInput := len(tfCmd.userInput)
lenInputOutput := len(tfCmd.postInputOutput)
if lenInput > 0 {
for i := 0; i < lenInput; i++ {
input := tfCmd.userInput[i]
exp.SendLine(input)
// use the index to find the corresponding
// output that matches the input.
if lenInputOutput-1 >= i {
output := tfCmd.postInputOutput[i]
_, err := exp.ExpectString(output)
if err != nil {
t.Fatal(err)
}
}
}
}
err = cmd.Wait()
if err != nil {
t.Fatal(err)
}
}
}
if validations != nil {
validations(t, organization.Name)
}
}
func Test_migrate_remote_backend_prefix_to_tfc_name_strategy_multi_workspace(t *testing.T) {
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
operations := []operationSets{
{
prep: func(t *testing.T, orgName, dir string) {
_ = createWorkspace(t, orgName, tfe.WorkspaceCreateOptions{Name: tfe.String("app-one")})
@ -566,9 +658,7 @@ func Test_migrate_remote_backend_prefix_to_tfc_name(t *testing.T) {
postInputOutput: []string{`Terraform has been successfully initialized!`},
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions in workspace "app-one"?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
{
@ -601,8 +691,8 @@ func Test_migrate_remote_backend_prefix_to_tfc_name(t *testing.T) {
},
},
},
},
validations: func(t *testing.T, orgName string) {
}
validations := func(t *testing.T, orgName string) {
expectedName := "cloud-workspace"
ws, err := tfeClient.Workspaces.Read(ctx, orgName, expectedName)
if err != nil {
@ -618,25 +708,21 @@ func Test_migrate_remote_backend_prefix_to_tfc_name(t *testing.T) {
if len(wsList.Items) != 3 {
t.Fatalf("expected number of workspaces in this org to be 3, but got %d", len(wsList.Items))
}
ws, empty := getWorkspace(wsList.Items, "cloud-workspace")
_, empty := getWorkspace(wsList.Items, "cloud-workspace")
if empty {
t.Fatalf("expected workspaces to include 'cloud-workspace' but didn't.")
}
ws, empty = getWorkspace(wsList.Items, "app-one")
_, empty = getWorkspace(wsList.Items, "app-one")
if empty {
t.Fatalf("expected workspaces to include 'app-one' but didn't.")
}
ws, empty = getWorkspace(wsList.Items, "app-two")
_, empty = getWorkspace(wsList.Items, "app-two")
if empty {
t.Fatalf("expected workspaces to include 'app-two' but didn't.")
}
},
},
}
for name, tc := range cases {
t.Log("Test: ", name)
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -649,13 +735,12 @@ func Test_migrate_remote_backend_prefix_to_tfc_name(t *testing.T) {
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv("TF_LOG=INFO")
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()
organization, cleanup := createOrganization(t)
defer cleanup()
for _, op := range tc.operations {
for _, op := range operations {
op.prep(t, organization.Name, tf.WorkDir())
for _, tfCmd := range op.commands {
cmd := tf.Cmd(tfCmd.command...)
@ -700,23 +785,17 @@ func Test_migrate_remote_backend_prefix_to_tfc_name(t *testing.T) {
}
}
if tc.validations != nil {
tc.validations(t, organization.Name)
}
if validations != nil {
validations(t, organization.Name)
}
}
func Test_migrate_remote_backend_prefix_to_tfc_tags(t *testing.T) {
t.Parallel()
func Test_migrate_remote_backend_prefix_to_tfc_tags_strategy_single_workspace(t *testing.T) {
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
cases := map[string]struct {
operations []operationSets
validations func(t *testing.T, orgName string)
}{
"single workspace with backend prefix strategy, to cloud with tags strategy": {
operations: []operationSets{
operations := []operationSets{
{
prep: func(t *testing.T, orgName, dir string) {
_ = createWorkspace(t, orgName, tfe.WorkspaceCreateOptions{Name: tfe.String("app-one")})
@ -730,9 +809,7 @@ func Test_migrate_remote_backend_prefix_to_tfc_tags(t *testing.T) {
expectedCmdOutput: `Terraform has been successfully initialized!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions in workspace "app-one"?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
@ -758,8 +835,8 @@ func Test_migrate_remote_backend_prefix_to_tfc_tags(t *testing.T) {
},
},
},
},
validations: func(t *testing.T, orgName string) {
}
validations := func(t *testing.T, orgName string) {
expectedName := "cloud-workspace"
ws, err := tfeClient.Workspaces.Read(ctx, orgName, expectedName)
if err != nil {
@ -768,10 +845,82 @@ func Test_migrate_remote_backend_prefix_to_tfc_tags(t *testing.T) {
if ws == nil {
t.Fatalf("Expected workspace %s to be present, but is not.", expectedName)
}
},
},
"multiple workspaces with backend prefix strategy, to cloud with tags strategy": {
operations: []operationSets{
}
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
defer exp.Close()
tmpDir, err := ioutil.TempDir("", "terraform-test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()
organization, cleanup := createOrganization(t)
defer cleanup()
for _, op := range operations {
op.prep(t, organization.Name, tf.WorkDir())
for _, tfCmd := range op.commands {
cmd := tf.Cmd(tfCmd.command...)
cmd.Stdin = exp.Tty()
cmd.Stdout = exp.Tty()
cmd.Stderr = exp.Tty()
err = cmd.Start()
if err != nil {
t.Fatal(err)
}
if tfCmd.expectedCmdOutput != "" {
_, err := exp.ExpectString(tfCmd.expectedCmdOutput)
if err != nil {
t.Fatal(err)
}
}
lenInput := len(tfCmd.userInput)
lenInputOutput := len(tfCmd.postInputOutput)
if lenInput > 0 {
for i := 0; i < lenInput; i++ {
input := tfCmd.userInput[i]
exp.SendLine(input)
// use the index to find the corresponding
// output that matches the input.
if lenInputOutput-1 >= i {
output := tfCmd.postInputOutput[i]
_, err := exp.ExpectString(output)
if err != nil {
t.Fatal(err)
}
}
}
}
err = cmd.Wait()
if err != nil {
t.Fatal(err)
}
}
}
if validations != nil {
validations(t, organization.Name)
}
}
func Test_migrate_remote_backend_prefix_to_tfc_tags_strategy_multi_workspace(t *testing.T) {
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
operations := []operationSets{
{
prep: func(t *testing.T, orgName, dir string) {
_ = createWorkspace(t, orgName, tfe.WorkspaceCreateOptions{Name: tfe.String("app-one")})
@ -813,23 +962,22 @@ func Test_migrate_remote_backend_prefix_to_tfc_tags(t *testing.T) {
commands: []tfCommand{
{
command: []string{"init", "-migrate-state", "-ignore-remote-version"},
expectedCmdOutput: `Would you like to rename your workspaces?`,
userInput: []string{"1", "*"},
postInputOutput: []string{`What pattern would you like to add to all your workspaces?`,
`Terraform Cloud has been successfully initialized!`},
expectedCmdOutput: `Do you wish to proceed?`,
userInput: []string{"yes"},
postInputOutput: []string{`Terraform Cloud has been successfully initialized!`},
},
{
command: []string{"workspace", "show"},
expectedCmdOutput: "two", // this comes from the original workspace name from the previous backend.
expectedCmdOutput: "app-two",
},
{
command: []string{"workspace", "select", "one"},
expectedCmdOutput: `Switched to workspace "one".`, // this comes from the original workspace name from the previous backend.
command: []string{"workspace", "select", "app-one"},
expectedCmdOutput: `Switched to workspace "app-one".`,
},
},
},
},
validations: func(t *testing.T, orgName string) {
}
validations := func(t *testing.T, orgName string) {
wsList, err := tfeClient.Workspaces.List(ctx, orgName, tfe.WorkspaceListOptions{
Tags: tfe.String("app"),
})
@ -839,27 +987,23 @@ func Test_migrate_remote_backend_prefix_to_tfc_tags(t *testing.T) {
if len(wsList.Items) != 2 {
t.Logf("Expected the number of workspaces to be 2, but got %d", len(wsList.Items))
}
ws, empty := getWorkspace(wsList.Items, "one")
ws, empty := getWorkspace(wsList.Items, "app-one")
if empty {
t.Fatalf("expected workspaces to include 'one' but didn't.")
t.Fatalf("expected workspaces to include 'app-one' but didn't.")
}
if len(ws.TagNames) == 0 {
t.Fatalf("expected workspaces 'one' to have tags.")
}
ws, empty = getWorkspace(wsList.Items, "two")
ws, empty = getWorkspace(wsList.Items, "app-two")
if empty {
t.Fatalf("expected workspaces to include 'two' but didn't.")
t.Fatalf("expected workspaces to include 'app-two' but didn't.")
}
if len(ws.TagNames) == 0 {
t.Fatalf("expected workspaces 'two' to have tags.")
t.Fatalf("expected workspaces 'app-two' to have tags.")
}
},
},
}
for name, tc := range cases {
t.Log("Test: ", name)
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -872,13 +1016,12 @@ func Test_migrate_remote_backend_prefix_to_tfc_tags(t *testing.T) {
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv("TF_LOG=INFO")
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()
organization, cleanup := createOrganization(t)
defer cleanup()
for _, op := range tc.operations {
for _, op := range operations {
op.prep(t, organization.Name, tf.WorkDir())
for _, tfCmd := range op.commands {
cmd := tf.Cmd(tfCmd.command...)
@ -923,8 +1066,7 @@ func Test_migrate_remote_backend_prefix_to_tfc_tags(t *testing.T) {
}
}
if tc.validations != nil {
tc.validations(t, organization.Name)
}
if validations != nil {
validations(t, organization.Name)
}
}

View File

@ -1,6 +1,3 @@
//go:build e2e
// +build e2e
package main
import (
@ -15,7 +12,7 @@ import (
)
func Test_migrate_single_to_tfc(t *testing.T) {
t.Parallel()
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
@ -37,9 +34,7 @@ func Test_migrate_single_to_tfc(t *testing.T) {
expectedCmdOutput: `Successfully configured the backend "local"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
@ -88,9 +83,7 @@ func Test_migrate_single_to_tfc(t *testing.T) {
expectedCmdOutput: `Successfully configured the backend "local"!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
@ -133,10 +126,12 @@ func Test_migrate_single_to_tfc(t *testing.T) {
}
for name, tc := range cases {
t.Log("Test: ", name)
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
organization, cleanup := createOrganization(t)
defer cleanup()
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -149,7 +144,6 @@ func Test_migrate_single_to_tfc(t *testing.T) {
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv("TF_LOG=info")
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()
@ -201,5 +195,6 @@ func Test_migrate_single_to_tfc(t *testing.T) {
if tc.validations != nil {
tc.validations(t, organization.Name)
}
})
}
}

View File

@ -1,10 +1,6 @@
//go:build e2e
// +build e2e
package main
import (
"fmt"
"io/ioutil"
"os"
"testing"
@ -14,7 +10,7 @@ import (
)
func Test_migrate_tfc_to_other(t *testing.T) {
t.Parallel()
skipIfMissingEnvVar(t)
cases := map[string]struct {
operations []operationSets
}{
@ -51,10 +47,12 @@ func Test_migrate_tfc_to_other(t *testing.T) {
}
for name, tc := range cases {
fmt.Println("Test: ", name)
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
organization, cleanup := createOrganization(t)
defer cleanup()
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -67,7 +65,6 @@ func Test_migrate_tfc_to_other(t *testing.T) {
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv("TF_LOG=info")
tf.AddEnv(cliConfigFileEnv)
defer tf.Close()
@ -114,5 +111,6 @@ func Test_migrate_tfc_to_other(t *testing.T) {
}
}
}
})
}
}

View File

@ -1,6 +1,3 @@
//go:build e2e
// +build e2e
package main
import (
@ -16,7 +13,7 @@ import (
)
func Test_migrate_tfc_to_tfc_single_workspace(t *testing.T) {
t.Parallel()
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
@ -55,9 +52,7 @@ func Test_migrate_tfc_to_tfc_single_workspace(t *testing.T) {
expectedCmdOutput: `prod`, // this comes from the `prep` function
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions in workspace "prod"?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
@ -119,9 +114,7 @@ func Test_migrate_tfc_to_tfc_single_workspace(t *testing.T) {
expectedCmdOutput: `Terraform Cloud has been successfully initialized!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions in workspace "prod"?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
@ -183,9 +176,7 @@ func Test_migrate_tfc_to_tfc_single_workspace(t *testing.T) {
expectedCmdOutput: `Terraform Cloud has been successfully initialized!`,
},
{
command: []string{"apply"},
expectedCmdOutput: `Do you want to perform these actions in workspace "prod"?`,
userInput: []string{"yes"},
command: []string{"apply", "-auto-approve"},
postInputOutput: []string{`Apply complete!`},
},
},
@ -214,23 +205,22 @@ func Test_migrate_tfc_to_tfc_single_workspace(t *testing.T) {
},
},
validations: func(t *testing.T, orgName string) {
wsList, err := tfeClient.Workspaces.List(ctx, orgName, tfe.WorkspaceListOptions{
Tags: tfe.String("app"),
})
// We created the workspace, so it will be there. We could not complete the state migration,
// though, so the workspace should be empty.
ws, err := tfeClient.Workspaces.ReadWithOptions(ctx, orgName, "new-workspace", &tfe.WorkspaceReadOptions{Include: "current_run"})
if err != nil {
t.Fatal(err)
}
// The migration never occured, so we have no workspaces with this tag.
if len(wsList.Items) != 0 {
t.Fatalf("Expected number of workspaces to be 0, but got %d", len(wsList.Items))
if ws.CurrentRun != nil {
t.Fatal("Expected to workspace be empty")
}
},
},
}
for name, tc := range cases {
t.Log("Test: ", name)
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
t.Run(name, func(t *testing.T) {
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -244,7 +234,6 @@ func Test_migrate_tfc_to_tfc_single_workspace(t *testing.T) {
tf := e2e.NewBinary(terraformBin, tmpDir)
defer tf.Close()
tf.AddEnv("TF_LOG=INFO")
tf.AddEnv(cliConfigFileEnv)
orgName, cleanup := tc.setup(t)
@ -252,7 +241,6 @@ func Test_migrate_tfc_to_tfc_single_workspace(t *testing.T) {
for _, op := range tc.operations {
op.prep(t, orgName, tf.WorkDir())
for _, tfCmd := range op.commands {
t.Log("Running commands: ", tfCmd.command)
cmd := tf.Cmd(tfCmd.command...)
cmd.Stdin = exp.Tty()
cmd.Stdout = exp.Tty()
@ -298,11 +286,12 @@ func Test_migrate_tfc_to_tfc_single_workspace(t *testing.T) {
if tc.validations != nil {
tc.validations(t, orgName)
}
})
}
}
func Test_migrate_tfc_to_tfc_multiple_workspace(t *testing.T) {
t.Parallel()
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
ctx := context.Background()
@ -454,7 +443,6 @@ func Test_migrate_tfc_to_tfc_multiple_workspace(t *testing.T) {
tag := "billing"
tfBlock := terraformConfigCloudBackendTags(orgName, tag)
writeMainTF(t, tfBlock, dir)
t.Log(orgName)
},
commands: []tfCommand{
{
@ -462,8 +450,7 @@ func Test_migrate_tfc_to_tfc_multiple_workspace(t *testing.T) {
expectedCmdOutput: `Would you like to rename your workspaces?`,
userInput: []string{"1", "new-*", "1"},
postInputOutput: []string{
`What pattern would you like to add to all your workspaces?`,
`The currently selected workspace (app-staging) does not exist.`,
`How would you like to rename your workspaces?`,
`Terraform Cloud has been successfully initialized!`},
},
},
@ -492,8 +479,8 @@ func Test_migrate_tfc_to_tfc_multiple_workspace(t *testing.T) {
}
for name, tc := range cases {
t.Log("Test: ", name)
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
t.Run(name, func(t *testing.T) {
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -507,7 +494,6 @@ func Test_migrate_tfc_to_tfc_multiple_workspace(t *testing.T) {
tf := e2e.NewBinary(terraformBin, tmpDir)
defer tf.Close()
tf.AddEnv("TF_LOG=INFO")
tf.AddEnv(cliConfigFileEnv)
orgName, cleanup := tc.setup(t)
@ -515,7 +501,6 @@ func Test_migrate_tfc_to_tfc_multiple_workspace(t *testing.T) {
for _, op := range tc.operations {
op.prep(t, orgName, tf.WorkDir())
for _, tfCmd := range op.commands {
t.Log("Running commands: ", tfCmd.command)
cmd := tf.Cmd(tfCmd.command...)
cmd.Stdin = exp.Tty()
cmd.Stdout = exp.Tty()
@ -551,7 +536,6 @@ func Test_migrate_tfc_to_tfc_multiple_workspace(t *testing.T) {
}
}
t.Log(cmd.Stderr)
err = cmd.Wait()
if err != nil {
t.Fatal(err.Error())
@ -562,5 +546,6 @@ func Test_migrate_tfc_to_tfc_multiple_workspace(t *testing.T) {
if tc.validations != nil {
tc.validations(t, orgName)
}
})
}
}

View File

@ -1,6 +1,3 @@
//go:build e2e
// +build e2e
package main
import (
@ -10,7 +7,9 @@ import (
"testing"
expect "github.com/Netflix/go-expect"
tfe "github.com/hashicorp/go-tfe"
"github.com/hashicorp/terraform/internal/e2e"
tfversion "github.com/hashicorp/terraform/version"
)
func terraformConfigRequiredVariable(org, name string) string {
@ -46,7 +45,7 @@ output "test_env" {
}
func Test_cloud_run_variables(t *testing.T) {
t.Parallel()
skipIfMissingEnvVar(t)
skipWithoutRemoteTerraformVersion(t)
cases := testCases{
@ -55,6 +54,10 @@ func Test_cloud_run_variables(t *testing.T) {
{
prep: func(t *testing.T, orgName, dir string) {
wsName := "new-workspace"
_ = createWorkspace(t, orgName, tfe.WorkspaceCreateOptions{
Name: tfe.String(wsName),
TerraformVersion: tfe.String(tfversion.String()),
})
tfBlock := terraformConfigRequiredVariable(orgName, wsName)
writeMainTF(t, tfBlock, dir)
},
@ -78,10 +81,10 @@ func Test_cloud_run_variables(t *testing.T) {
}
for name, tc := range cases {
fmt.Println("Test: ", name)
t.Run(name, func(t *testing.T) {
organization, cleanup := createOrganization(t)
defer cleanup()
exp, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithDefaultTimeout(expectConsoleTimeout))
exp, err := expect.NewConsole(defaultOpts()...)
if err != nil {
t.Fatal(err)
}
@ -94,7 +97,6 @@ func Test_cloud_run_variables(t *testing.T) {
defer os.RemoveAll(tmpDir)
tf := e2e.NewBinary(terraformBin, tmpDir)
tf.AddEnv("TF_LOG=info")
tf.AddEnv("TF_CLI_ARGS=-no-color")
tf.AddEnv("TF_VAR_baz=qux")
tf.AddEnv(cliConfigFileEnv)
@ -116,7 +118,7 @@ func Test_cloud_run_variables(t *testing.T) {
if tfCmd.expectedCmdOutput != "" {
_, err := exp.ExpectString(tfCmd.expectedCmdOutput)
if err != nil {
t.Fatal(err)
t.Fatalf(`Expected command output "%s", but got %v `, tfCmd.expectedCmdOutput, err)
}
}
@ -132,7 +134,7 @@ func Test_cloud_run_variables(t *testing.T) {
output := tfCmd.postInputOutput[i]
_, err := exp.ExpectString(output)
if err != nil {
t.Fatal(err)
t.Fatalf(`Expected command output "%s", but got %v `, tfCmd.expectedCmdOutput, err)
}
}
}
@ -148,5 +150,6 @@ func Test_cloud_run_variables(t *testing.T) {
tc.validations(t, organization.Name)
}
}
})
}
}