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  }