Test AWS infrastructure by using LocalStack and Terraform Tests - AWS Prescriptive Guidance

Test AWS infrastructure by using LocalStack and Terraform Tests

Created by Ivan Girardi (AWS) and Ioannis Kalyvas (AWS)

Summary

This pattern helps you locally test infrastructure as code (IaC) for AWS in Terraform without the need to provision infrastructure in your AWS environment. It integrates the Terraform Tests framework with LocalStack. The LocalStack Docker container provides a local development environment that emulates various AWS services. This helps you test and iterate on infrastructure deployments without incurring costs in the AWS Cloud.

This solution provides the following benefits:

  • Cost optimization – Running tests against LocalStack eliminates the need to use AWS services. This prevents you from incurring costs that are associated with creating, operating, and modifying those AWS resources.

  • Speed and efficiency – Testing locally is also typically faster than deploying the AWS resources. This rapid feedback loop accelerates development and debugging. Because LocalStack runs locally, you can develop and test your Terraform configuration files without an internet connection. You can debug Terraform configuration files locally and receive immediate feedback, which streamlines the development process.

  • Consistency and reproducibility – LocalStack provides a consistent environment for testing. This consistency helps make sure that tests yield the same results, regardless of external AWS changes or network issues.

  • Isolation – Testing with LocalStack prevents you from accidentally affecting live AWS resources or production environments. This isolation makes it safe to experiment and test various configurations.

  • Automation – Integration with a continuous integration and continuous delivery (CI/CD) pipeline helps you automatically test Terraform configuration files. The pipeline thoroughly tests the IaC before deployment.

  • Flexibility – You can simulate different AWS Regions, AWS accounts, and service configurations to match your production environments more closely.

Prerequisites and limitations

Prerequisites

Limitations

  • This pattern provides explicit examples for testing Amazon Simple Storage Service (Amazon S3), AWS Lambda, AWS Step Functions, and Amazon DynamoDB resources. However, you can extend this solution to include additional AWS resources.

  • This pattern provides instructions to run Terraform Tests locally, but can you can integrate testing into any CI/CD pipeline.

  • This pattern provides instructions for using the LocalStack Community image. If you're using the LocalStack Pro image, see the LocalStack Pro documentation.

  • LocalStack provides emulation services for different AWS APIs. For a complete list, see AWS Service Feature Coverage. Some advanced features might require a subscription for LocalStack Pro.

Architecture

The following diagram shows the architecture for this solution. The primary components are a source code repository, a CI/CD pipeline, and a LocalStack Docker container. The LocalStack Docker Container hosts the following AWS services locally:

  • An Amazon S3 bucket for storing files

  • Amazon CloudWatch for monitoring and logging

  • An AWS Lambda function for running serverless code

  • An AWS Step Functions state machine for orchestrating multi-step workflows

  • An Amazon DynamoDB table for storing NoSQL data

A CI/CD pipeline builds and tests the LocalStack Docker container and AWS resources.

The diagram shows the following workflow:

  1. You add and commit a Terraform configuration file to the source code repository.

  2. The CI/CD pipeline detects the changes and initiates a build process for static Terraform code analysis. The pipeline builds and runs the LocalStack Docker container. Then the pipeline starts the test process.

  3. The pipeline uploads an object into an Amazon S3 bucket that is hosted in the LocalStack Docker container.

  4. Uploading the object invokes an AWS Lambda function.

  5. The Lambda function stores the Amazon S3 event notification in a CloudWatch log.

  6. The Lambda function starts an AWS Step Functions state machine.

  7. The state machine writes the name of the Amazon S3 object into a DynamoDB table.

  8. The test process in the CI/CD pipeline verifies that the name of the uploaded object matches the entry in the DynamoDB table. It also verifies that the S3 bucket is deployed with the specified name and that the AWS Lambda function has been successfully deployed.

Tools

AWS services

  • Amazon CloudWatch helps you monitor the metrics of your AWS resources and the applications you run on AWS in real time.

  • Amazon DynamoDB is a fully managed NoSQL database service that provides fast, predictable, and scalable performance.

  • AWS Lambda is a compute service that helps you run code without needing to provision or manage servers. It runs your code only when needed and scales automatically, so you pay only for the compute time that you use.

  • Amazon Simple Storage Service (Amazon S3) is a cloud-based object storage service that helps you store, protect, and retrieve any amount of data.

  • AWS Step Functions is a serverless orchestration service that helps you combine AWS Lambda functions and other AWS services to build business-critical applications.

Other tools

  • Docker is a set of platform as a service (PaaS) products that use virtualization at the operating-system level to deliver software in containers.

  • Docker Compose is a tool for defining and running multi-container applications.

  • LocalStack is a cloud service emulator that runs in a single container. By using LocalStack, you can run workloads on your local machine that use AWS services, without connecting to the AWS Cloud.

  • Terraform is an IaC tool from HashiCorp that helps you create and manage cloud and on-premises resources.

  • Terraform Tests helps you validate Terraform module configuration updates through tests that are analogous to integration or unit testing.

Code repository

The code for this pattern is available in the GitHub Test AWS infrastructure using LocalStack and Terraform Tests repository.

Best practices

Epics

TaskDescriptionSkills required

Clone the repository.

In a bash shell, enter the following command. This clones the Test AWS infrastructure using LocalStack and Terraform Tests repository from GitHub:

git clone https://github.com/aws-samples/localstack-terraform-test.git
DevOps engineer

Run the LocalStack container.

  1. Enter the following command to navigate into the cloned repository:

    cd localstack-terraform-test
  2. Enter the following command to start the LocalStack Docker container in detached mode:

    docker-compose up -d
  3. Wait until the LocalStack Docker container is operational.

DevOps engineer

Initialize Terraform.

Enter the following command to initialize Terraform:

terraform init
DevOps engineer

Run Terraform Tests.

  1. Enter the following command to run Terraform Tests:

    terraform test
  2. Verify that all tests completed successfully. The output should be similar to the following:

    Success! 3 passed, 0 failed.
DevOps engineer

Clean up resources.

Enter the following command to destroy the LocalStack container:

docker-compose down
DevOps engineer

Troubleshooting

IssueSolution

Error: reading DynamoDB Table Item (Files|README.md): empty result when running the terraform test command.

  1. Reenter the terraform test command.

  2. If that doesn't resolve the error, edit the main.tf file to increase the sleep timeout to a value greater than 15 seconds:

    resource "time_sleep" "wait" { create_duration = "15s" triggers = { s3_object = local.key_json } }

Related resources

Additional information

Integration with GitHub Actions

You can integrate LocalStack and Terraform Tests in a CI/CD pipeline by using GitHub Actions. For more information, see the GitHub Actions documentation. The following is a sample GitHub Actions configuration file:

name: LocalStack Terraform Test on: push: branches: - '**' workflow_dispatch: {} jobs: localstack-terraform-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build and Start LocalStack Container run: | docker compose up -d - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: latest - name: Run Terraform Init and Validation run: | terraform init terraform validate terraform fmt --recursive --check terraform plan terraform show - name: Run Terraform Test run: | terraform test - name: Stop and Delete LocalStack Container if: always() run: docker compose down