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

     1  package test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/gruntwork-io/terratest/modules/aws"
     8  	"github.com/gruntwork-io/terratest/modules/random"
     9  	"github.com/gruntwork-io/terratest/modules/terraform"
    10  	test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  // An example of how to test the Terraform module in examples/terraform-aws-lambda-example using Terratest.
    16  func TestTerraformAwsLambdaExample(t *testing.T) {
    17  	t.Parallel()
    18  
    19  	// Make a copy of the terraform module to a temporary directory. This allows running multiple tests in parallel
    20  	// against the same terraform module.
    21  	exampleFolder := test_structure.CopyTerraformFolderToTemp(t, "../", "examples/terraform-aws-lambda-example")
    22  
    23  	// Give this lambda function a unique ID for a name so we can distinguish it from any other lambdas
    24  	// in your AWS account
    25  	functionName := fmt.Sprintf("terratest-aws-lambda-example-%s", random.UniqueId())
    26  
    27  	// Pick a random AWS region to test in. This helps ensure your code works in all regions.
    28  	awsRegion := aws.GetRandomStableRegion(t, nil, nil)
    29  
    30  	// Construct the terraform options with default retryable errors to handle the most common retryable errors in
    31  	// terraform testing.
    32  	terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
    33  		// The path to where our Terraform code is located
    34  		TerraformDir: exampleFolder,
    35  
    36  		// Variables to pass to our Terraform code using -var options
    37  		Vars: map[string]interface{}{
    38  			"function_name": functionName,
    39  		},
    40  
    41  		// Environment variables to set when running Terraform
    42  		EnvVars: map[string]string{
    43  			"AWS_DEFAULT_REGION": awsRegion,
    44  		},
    45  	})
    46  
    47  	// At the end of the test, run `terraform destroy` to clean up any resources that were created
    48  	defer terraform.Destroy(t, terraformOptions)
    49  
    50  	// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
    51  	terraform.InitAndApply(t, terraformOptions)
    52  
    53  	// Invoke the function, so we can test its output
    54  	response := aws.InvokeFunction(t, awsRegion, functionName, ExampleFunctionPayload{ShouldFail: false, Echo: "hi!"})
    55  
    56  	// This function just echos it's input as a JSON string when `ShouldFail` is `false``
    57  	assert.Equal(t, `"hi!"`, string(response))
    58  
    59  	// Invoke the function, this time causing it to error and capturing the error
    60  	_, err := aws.InvokeFunctionE(t, awsRegion, functionName, ExampleFunctionPayload{ShouldFail: true, Echo: "hi!"})
    61  
    62  	// Function-specific errors have their own special return
    63  	functionError, ok := err.(*aws.FunctionError)
    64  	require.True(t, ok)
    65  
    66  	// Make sure the function-specific error comes back
    67  	assert.Contains(t, string(functionError.Payload), "Failed to handle")
    68  }
    69  
    70  // Annother example of how to test the Terraform module in
    71  // examples/terraform-aws-lambda-example using Terratest, this time with
    72  // the aws.InvokeFunctionWithParams.
    73  func TestTerraformAwsLambdaWithParamsExample(t *testing.T) {
    74  	t.Parallel()
    75  
    76  	// Make a copy of the terraform module to a temporary directory. This allows running multiple tests in parallel
    77  	// against the same terraform module.
    78  	exampleFolder := test_structure.CopyTerraformFolderToTemp(t, "../", "examples/terraform-aws-lambda-example")
    79  
    80  	// Give this lambda function a unique ID for a name so we can distinguish it from any other lambdas
    81  	// in your AWS account
    82  	functionName := fmt.Sprintf("terratest-aws-lambda-withparams-example-%s", random.UniqueId())
    83  
    84  	// Pick a random AWS region to test in. This helps ensure your code works in all regions.
    85  	awsRegion := aws.GetRandomStableRegion(t, nil, nil)
    86  
    87  	// Construct the terraform options with default retryable errors to handle the most common retryable errors in
    88  	// terraform testing.
    89  	terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
    90  		// The path to where our Terraform code is located
    91  		TerraformDir: exampleFolder,
    92  
    93  		// Variables to pass to our Terraform code using -var options
    94  		Vars: map[string]interface{}{
    95  			"function_name": functionName,
    96  		},
    97  
    98  		// Environment variables to set when running Terraform
    99  		EnvVars: map[string]string{
   100  			"AWS_DEFAULT_REGION": awsRegion,
   101  		},
   102  	})
   103  
   104  	// At the end of the test, run `terraform destroy` to clean up any resources that were created
   105  	defer terraform.Destroy(t, terraformOptions)
   106  
   107  	// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
   108  	terraform.InitAndApply(t, terraformOptions)
   109  
   110  	// Call InvokeFunctionWithParms with an InvocationType of "DryRun".
   111  	// A "DryRun" invocation does not execute the function, so the example
   112  	// test function will not be checking the payload.
   113  	var invocationType aws.InvocationTypeOption = aws.InvocationTypeDryRun
   114  	input := &aws.LambdaOptions{InvocationType: &invocationType}
   115  	out := aws.InvokeFunctionWithParams(t, awsRegion, functionName, input)
   116  
   117  	// With "DryRun", there's no message in the output, but there is
   118  	// a status code which will have a value of 204 for a successful
   119  	// invocation.
   120  	assert.Equal(t, int(*out.StatusCode), 204)
   121  
   122  	// Invoke the function, this time causing the Lambda to error and
   123  	// capturing the error.
   124  	invocationType = aws.InvocationTypeRequestResponse
   125  	input = &aws.LambdaOptions{
   126  		InvocationType: &invocationType,
   127  		Payload:        ExampleFunctionPayload{ShouldFail: true, Echo: "hi!"},
   128  	}
   129  	out, err := aws.InvokeFunctionWithParamsE(t, awsRegion, functionName, input)
   130  
   131  	// The Lambda executed, but should have failed.
   132  	assert.Error(t, err, "Unhandled")
   133  
   134  	// Make sure the function-specific error comes back
   135  	assert.Contains(t, string(out.Payload), "Failed to handle")
   136  
   137  	// Call InvokeFunctionWithParamsE with a LambdaOptions struct that has
   138  	// an unsupported InvocationType.  The function should fail.
   139  	invocationType = "Event"
   140  	input = &aws.LambdaOptions{
   141  		InvocationType: &invocationType,
   142  		Payload:        ExampleFunctionPayload{ShouldFail: false, Echo: "hi!"},
   143  	}
   144  	out, err = aws.InvokeFunctionWithParamsE(t, awsRegion, functionName, input)
   145  	require.NotNil(t, err)
   146  	assert.Contains(t, err.Error(), "LambdaOptions.InvocationType, if specified, must either be \"RequestResponse\" or \"DryRun\"")
   147  }
   148  
   149  type ExampleFunctionPayload struct {
   150  	Echo       string
   151  	ShouldFail bool
   152  }