github.com/cycloidio/terraform@v1.1.10-0.20220513142504-76d5c768dc63/cloud/e2e/main_test.go (about) 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 "io/ioutil" 7 "log" 8 "os" 9 "os/exec" 10 "strings" 11 "testing" 12 13 expect "github.com/Netflix/go-expect" 14 tfe "github.com/hashicorp/go-tfe" 15 "github.com/cycloidio/terraform/e2e" 16 tfversion "github.com/cycloidio/terraform/version" 17 ) 18 19 var terraformBin string 20 var cliConfigFileEnv string 21 22 var tfeClient *tfe.Client 23 var tfeHostname string 24 var tfeToken string 25 var verboseMode bool 26 27 func TestMain(m *testing.M) { 28 teardown := setup() 29 code := m.Run() 30 teardown() 31 32 os.Exit(code) 33 } 34 35 func accTest() bool { 36 // TF_ACC is set when we want to run acceptance tests, meaning it relies on 37 // network access. 38 return os.Getenv("TF_ACC") != "" 39 } 40 41 func hasHostname() bool { 42 return os.Getenv("TFE_HOSTNAME") != "" 43 } 44 45 func hasToken() bool { 46 return os.Getenv("TFE_TOKEN") != "" 47 } 48 49 func hasRequiredEnvVars() bool { 50 return accTest() && hasHostname() && hasToken() 51 } 52 53 func skipIfMissingEnvVar(t *testing.T) { 54 if !hasRequiredEnvVars() { 55 t.Skip("Skipping test, required environment variables missing. Use `TF_ACC`, `TFE_HOSTNAME`, `TFE_TOKEN`") 56 } 57 } 58 59 func setup() func() { 60 tfOutput := flag.Bool("tfoutput", false, "This flag produces the terraform output from tests.") 61 flag.Parse() 62 verboseMode = *tfOutput 63 64 setTfeClient() 65 teardown := setupBinary() 66 67 return func() { 68 teardown() 69 } 70 } 71 func testRunner(t *testing.T, cases testCases, orgCount int, tfEnvFlags ...string) { 72 for name, tc := range cases { 73 tc := tc // rebind tc into this lexical scope 74 t.Run(name, func(subtest *testing.T) { 75 subtest.Parallel() 76 77 orgNames := []string{} 78 for i := 0; i < orgCount; i++ { 79 organization, cleanup := createOrganization(t) 80 t.Cleanup(cleanup) 81 orgNames = append(orgNames, organization.Name) 82 } 83 84 exp, err := expect.NewConsole(defaultOpts()...) 85 if err != nil { 86 subtest.Fatal(err) 87 } 88 defer exp.Close() 89 90 tmpDir, err := ioutil.TempDir("", "terraform-test") 91 if err != nil { 92 subtest.Fatal(err) 93 } 94 defer os.RemoveAll(tmpDir) 95 96 tf := e2e.NewBinary(terraformBin, tmpDir) 97 tfEnvFlags = append(tfEnvFlags, "TF_LOG=INFO") 98 tfEnvFlags = append(tfEnvFlags, cliConfigFileEnv) 99 for _, env := range tfEnvFlags { 100 tf.AddEnv(env) 101 } 102 defer tf.Close() 103 104 var orgName string 105 for index, op := range tc.operations { 106 if orgCount == 1 { 107 orgName = orgNames[0] 108 } else { 109 orgName = orgNames[index] 110 } 111 op.prep(t, orgName, tf.WorkDir()) 112 for _, tfCmd := range op.commands { 113 cmd := tf.Cmd(tfCmd.command...) 114 cmd.Stdin = exp.Tty() 115 cmd.Stdout = exp.Tty() 116 cmd.Stderr = exp.Tty() 117 118 err = cmd.Start() 119 if err != nil { 120 subtest.Fatal(err) 121 } 122 123 if tfCmd.expectedCmdOutput != "" { 124 got, err := exp.ExpectString(tfCmd.expectedCmdOutput) 125 if err != nil { 126 subtest.Fatalf("error while waiting for output\nwant: %s\nerror: %s\noutput\n%s", tfCmd.expectedCmdOutput, err, got) 127 } 128 } 129 130 lenInput := len(tfCmd.userInput) 131 lenInputOutput := len(tfCmd.postInputOutput) 132 if lenInput > 0 { 133 for i := 0; i < lenInput; i++ { 134 input := tfCmd.userInput[i] 135 exp.SendLine(input) 136 // use the index to find the corresponding 137 // output that matches the input. 138 if lenInputOutput-1 >= i { 139 output := tfCmd.postInputOutput[i] 140 _, err := exp.ExpectString(output) 141 if err != nil { 142 subtest.Fatal(err) 143 } 144 } 145 } 146 } 147 148 err = cmd.Wait() 149 if err != nil && !tfCmd.expectError { 150 subtest.Fatal(err) 151 } 152 } 153 } 154 155 if tc.validations != nil { 156 tc.validations(t, orgName) 157 } 158 }) 159 } 160 } 161 162 func setTfeClient() { 163 tfeHostname = os.Getenv("TFE_HOSTNAME") 164 tfeToken = os.Getenv("TFE_TOKEN") 165 166 cfg := &tfe.Config{ 167 Address: fmt.Sprintf("https://%s", tfeHostname), 168 Token: tfeToken, 169 } 170 171 if tfeHostname != "" && tfeToken != "" { 172 // Create a new TFE client. 173 client, err := tfe.NewClient(cfg) 174 if err != nil { 175 fmt.Printf("Could not create new tfe client: %v\n", err) 176 os.Exit(1) 177 } 178 tfeClient = client 179 } 180 } 181 182 func setupBinary() func() { 183 log.Println("Setting up terraform binary") 184 tmpTerraformBinaryDir, err := ioutil.TempDir("", "terraform-test") 185 if err != nil { 186 fmt.Printf("Could not create temp directory: %v\n", err) 187 os.Exit(1) 188 } 189 log.Println(tmpTerraformBinaryDir) 190 currentDir, err := os.Getwd() 191 defer os.Chdir(currentDir) 192 if err != nil { 193 fmt.Printf("Could not change directories: %v\n", err) 194 os.Exit(1) 195 } 196 // Getting top level dir 197 dirPaths := strings.Split(currentDir, "/") 198 log.Println(currentDir) 199 topLevel := len(dirPaths) - 3 200 topDir := strings.Join(dirPaths[0:topLevel], "/") 201 202 if err := os.Chdir(topDir); err != nil { 203 fmt.Printf("Could not change directories: %v\n", err) 204 os.Exit(1) 205 } 206 207 cmd := exec.Command( 208 "go", 209 "build", 210 "-o", tmpTerraformBinaryDir, 211 "-ldflags", fmt.Sprintf("-X \"github.com/cycloidio/terraform/version.Prerelease=%s\"", tfversion.Prerelease), 212 ) 213 err = cmd.Run() 214 if err != nil { 215 fmt.Printf("Could not run exec command: %v\n", err) 216 os.Exit(1) 217 } 218 219 credFile := fmt.Sprintf("%s/dev.tfrc", tmpTerraformBinaryDir) 220 writeCredRC(credFile) 221 222 terraformBin = fmt.Sprintf("%s/terraform", tmpTerraformBinaryDir) 223 cliConfigFileEnv = fmt.Sprintf("TF_CLI_CONFIG_FILE=%s", credFile) 224 225 return func() { 226 os.RemoveAll(tmpTerraformBinaryDir) 227 } 228 } 229 230 func writeCredRC(file string) { 231 creds := credentialBlock() 232 f, err := os.Create(file) 233 if err != nil { 234 fmt.Printf("Could not create file: %v\n", err) 235 os.Exit(1) 236 } 237 _, err = f.WriteString(creds) 238 if err != nil { 239 fmt.Printf("Could not write credentials: %v\n", err) 240 os.Exit(1) 241 } 242 f.Close() 243 } 244 245 func credentialBlock() string { 246 return fmt.Sprintf(` 247 credentials "%s" { 248 token = "%s" 249 }`, tfeHostname, tfeToken) 250 }