github.com/darmach/terratest@v0.34.8-0.20210517103231-80931f95e3ff/modules/test-structure/test_structure.go (about)

     1  // Package test_structure allows to set up tests and their environment.
     2  package test_structure
     3  
     4  import (
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/gruntwork-io/terratest/modules/files"
    11  	"github.com/gruntwork-io/terratest/modules/logger"
    12  	"github.com/gruntwork-io/terratest/modules/testing"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  // SKIP_STAGE_ENV_VAR_PREFIX is the prefix used for skipping stage environment variables.
    17  const SKIP_STAGE_ENV_VAR_PREFIX = "SKIP_"
    18  
    19  // RunTestStage executes the given test stage (e.g., setup, teardown, validation) if an environment variable of the name
    20  // `SKIP_<stageName>` (e.g., SKIP_teardown) is not set.
    21  func RunTestStage(t testing.TestingT, stageName string, stage func()) {
    22  	envVarName := fmt.Sprintf("%s%s", SKIP_STAGE_ENV_VAR_PREFIX, stageName)
    23  	if os.Getenv(envVarName) == "" {
    24  		logger.Logf(t, "The '%s' environment variable is not set, so executing stage '%s'.", envVarName, stageName)
    25  		stage()
    26  	} else {
    27  		logger.Logf(t, "The '%s' environment variable is set, so skipping stage '%s'.", envVarName, stageName)
    28  	}
    29  }
    30  
    31  // SkipStageEnvVarSet returns true if an environment variable is set instructing Terratest to skip a test stage. This can be an easy way
    32  // to tell if the tests are running in a local dev environment vs a CI server.
    33  func SkipStageEnvVarSet() bool {
    34  	for _, environmentVariable := range os.Environ() {
    35  		if strings.HasPrefix(environmentVariable, SKIP_STAGE_ENV_VAR_PREFIX) {
    36  			return true
    37  		}
    38  	}
    39  
    40  	return false
    41  }
    42  
    43  // CopyTerraformFolderToTemp copies the given root folder to a randomly-named temp folder and return the path to the
    44  // given terraform modules folder within the new temp root folder. This is useful when running multiple tests in
    45  // parallel against the same set of Terraform files to ensure the tests don't overwrite each other's .terraform working
    46  // directory and terraform.tfstate files. To ensure relative paths work, we copy over the entire root folder to a temp
    47  // folder, and then return the path within that temp folder to the given terraform module dir, which is where the actual
    48  // test will be running.
    49  // For example, suppose you had the target terraform folder you want to test in "/examples/terraform-aws-example"
    50  // relative to the repo root. If your tests reside in the "/test" relative to the root, then you will use this as
    51  // follows:
    52  //
    53  //       // Root folder where terraform files should be (relative to the test folder)
    54  //       rootFolder := ".."
    55  //
    56  //       // Relative path to terraform module being tested from the root folder
    57  //       terraformFolderRelativeToRoot := "examples/terraform-aws-example"
    58  //
    59  //       // Copy the terraform folder to a temp folder
    60  //       tempTestFolder := test_structure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
    61  //
    62  //       // Make sure to use the temp test folder in the terraform options
    63  //       terraformOptions := &terraform.Options{
    64  //       		TerraformDir: tempTestFolder,
    65  //       }
    66  //
    67  // Note that if any of the SKIP_<stage> environment variables is set, we assume this is a test in the local dev where
    68  // there are no other concurrent tests running and we want to be able to cache test data between test stages, so in that
    69  // case, we do NOT copy anything to a temp folder, and return the path to the original terraform module folder instead.
    70  func CopyTerraformFolderToTemp(t testing.TestingT, rootFolder string, terraformModuleFolder string) string {
    71  	if SkipStageEnvVarSet() {
    72  		logger.Logf(t, "A SKIP_XXX environment variable is set. Using original examples folder rather than a temp folder so we can cache data between stages for faster local testing.")
    73  		return filepath.Join(rootFolder, terraformModuleFolder)
    74  	}
    75  
    76  	fullTerraformModuleFolder := filepath.Join(rootFolder, terraformModuleFolder)
    77  
    78  	exists, err := files.FileExistsE(fullTerraformModuleFolder)
    79  	require.NoError(t, err)
    80  	if !exists {
    81  		t.Fatal(files.DirNotFoundError{Directory: fullTerraformModuleFolder})
    82  	}
    83  
    84  	tmpRootFolder, err := files.CopyTerraformFolderToTemp(rootFolder, cleanName(t.Name()))
    85  	if err != nil {
    86  		t.Fatal(err)
    87  	}
    88  
    89  	tmpTestFolder := filepath.Join(tmpRootFolder, terraformModuleFolder)
    90  
    91  	// Log temp folder so we can see it
    92  	logger.Logf(t, "Copied terraform folder %s to %s", fullTerraformModuleFolder, tmpTestFolder)
    93  
    94  	return tmpTestFolder
    95  }
    96  
    97  func cleanName(originalName string) string {
    98  	parts := strings.Split(originalName, "/")
    99  	return parts[len(parts)-1]
   100  }