github.com/kevinklinger/open_terraform@v1.3.6/noninternal/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/kevinklinger/open_terraform/noninternal/e2e" 16 tfversion "github.com/kevinklinger/open_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 := t.TempDir() 91 92 tf := e2e.NewBinary(t, terraformBin, tmpDir) 93 tfEnvFlags = append(tfEnvFlags, "TF_LOG=INFO") 94 tfEnvFlags = append(tfEnvFlags, cliConfigFileEnv) 95 for _, env := range tfEnvFlags { 96 tf.AddEnv(env) 97 } 98 99 var orgName string 100 for index, op := range tc.operations { 101 switch orgCount { 102 case 0: 103 orgName = "" 104 case 1: 105 orgName = orgNames[0] 106 default: 107 orgName = orgNames[index] 108 } 109 110 op.prep(t, orgName, tf.WorkDir()) 111 for _, tfCmd := range op.commands { 112 cmd := tf.Cmd(tfCmd.command...) 113 cmd.Stdin = exp.Tty() 114 cmd.Stdout = exp.Tty() 115 cmd.Stderr = exp.Tty() 116 117 err = cmd.Start() 118 if err != nil { 119 subtest.Fatal(err) 120 } 121 122 if tfCmd.expectedCmdOutput != "" { 123 got, err := exp.ExpectString(tfCmd.expectedCmdOutput) 124 if err != nil { 125 subtest.Fatalf("error while waiting for output\nwant: %s\nerror: %s\noutput\n%s", tfCmd.expectedCmdOutput, err, got) 126 } 127 } 128 129 lenInput := len(tfCmd.userInput) 130 lenInputOutput := len(tfCmd.postInputOutput) 131 if lenInput > 0 { 132 for i := 0; i < lenInput; i++ { 133 input := tfCmd.userInput[i] 134 exp.SendLine(input) 135 // use the index to find the corresponding 136 // output that matches the input. 137 if lenInputOutput-1 >= i { 138 output := tfCmd.postInputOutput[i] 139 _, err := exp.ExpectString(output) 140 if err != nil { 141 subtest.Fatal(err) 142 } 143 } 144 } 145 } 146 147 err = cmd.Wait() 148 if err != nil && !tfCmd.expectError { 149 subtest.Fatal(err) 150 } 151 } 152 } 153 154 if tc.validations != nil { 155 tc.validations(t, orgName) 156 } 157 }) 158 } 159 } 160 161 func setTfeClient() { 162 tfeHostname = os.Getenv("TFE_HOSTNAME") 163 tfeToken = os.Getenv("TFE_TOKEN") 164 165 cfg := &tfe.Config{ 166 Address: fmt.Sprintf("https://%s", tfeHostname), 167 Token: tfeToken, 168 } 169 170 if tfeHostname != "" && tfeToken != "" { 171 // Create a new TFE client. 172 client, err := tfe.NewClient(cfg) 173 if err != nil { 174 fmt.Printf("Could not create new tfe client: %v\n", err) 175 os.Exit(1) 176 } 177 tfeClient = client 178 } 179 } 180 181 func setupBinary() func() { 182 log.Println("Setting up terraform binary") 183 tmpTerraformBinaryDir, err := ioutil.TempDir("", "terraform-test") 184 if err != nil { 185 fmt.Printf("Could not create temp directory: %v\n", err) 186 os.Exit(1) 187 } 188 log.Println(tmpTerraformBinaryDir) 189 currentDir, err := os.Getwd() 190 defer os.Chdir(currentDir) 191 if err != nil { 192 fmt.Printf("Could not change directories: %v\n", err) 193 os.Exit(1) 194 } 195 // Getting top level dir 196 dirPaths := strings.Split(currentDir, "/") 197 log.Println(currentDir) 198 topLevel := len(dirPaths) - 3 199 topDir := strings.Join(dirPaths[0:topLevel], "/") 200 201 if err := os.Chdir(topDir); err != nil { 202 fmt.Printf("Could not change directories: %v\n", err) 203 os.Exit(1) 204 } 205 206 cmd := exec.Command( 207 "go", 208 "build", 209 "-o", tmpTerraformBinaryDir, 210 "-ldflags", fmt.Sprintf("-X \"github.com/kevinklinger/open_terraform/version.Prerelease=%s\"", tfversion.Prerelease), 211 ) 212 err = cmd.Run() 213 if err != nil { 214 fmt.Printf("Could not run exec command: %v\n", err) 215 os.Exit(1) 216 } 217 218 credFile := fmt.Sprintf("%s/dev.tfrc", tmpTerraformBinaryDir) 219 writeCredRC(credFile) 220 221 terraformBin = fmt.Sprintf("%s/terraform", tmpTerraformBinaryDir) 222 cliConfigFileEnv = fmt.Sprintf("TF_CLI_CONFIG_FILE=%s", credFile) 223 224 return func() { 225 os.RemoveAll(tmpTerraformBinaryDir) 226 } 227 } 228 229 func writeCredRC(file string) { 230 creds := credentialBlock() 231 f, err := os.Create(file) 232 if err != nil { 233 fmt.Printf("Could not create file: %v\n", err) 234 os.Exit(1) 235 } 236 _, err = f.WriteString(creds) 237 if err != nil { 238 fmt.Printf("Could not write credentials: %v\n", err) 239 os.Exit(1) 240 } 241 f.Close() 242 } 243 244 func credentialBlock() string { 245 return fmt.Sprintf(` 246 credentials "%s" { 247 token = "%s" 248 }`, tfeHostname, tfeToken) 249 }