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
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
Install
Docker Enable access
to the default Docker socket ( /var/run/docker.sock
). For more information, see the LocalStack documentation. Install
Docker Compose Install
Terraform version 1.6.0 or later Install
Terraform CLI Configure
the Terraform AWS Provider (Optional) Install and configure the AWS Command Line Interface (AWS CLI). For an example of how to use the AWS CLI with LocalStack, see the GitHub Test AWS infrastructure using LocalStack and Terraform Tests
repository.
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
The diagram shows the following workflow:
You add and commit a Terraform configuration file to the source code repository.
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.
The pipeline uploads an object into an Amazon S3 bucket that is hosted in the LocalStack Docker container.
Uploading the object invokes an AWS Lambda function.
The Lambda function stores the Amazon S3 event notification in a CloudWatch log.
The Lambda function starts an AWS Step Functions state machine.
The state machine writes the name of the Amazon S3 object into a DynamoDB table.
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
Best practices
This solution tests AWS infrastructure that is specified in Terraform configuration files, and it does not deploy those resources in the AWS Cloud. If you want to deploy the resources, follow the principle of least-privilege (IAM documentation) and properly configure the Terraform backend
(Terraform documentation). When integrating LocalStack in a CI/CD pipeline, we recommend that you don't run the LocalStack Docker container in privilege mode. For more information, see Runtime privilege and Linux capabilities
(Docker documentation) and Security for self-managed runners (GitLab documentation).
Epics
Task | Description | Skills required |
---|---|---|
Clone the repository. | In a bash shell, enter the following command. This clones the Test AWS infrastructure using LocalStack and Terraform Tests
| DevOps engineer |
Run the LocalStack container. |
| DevOps engineer |
Initialize Terraform. | Enter the following command to initialize Terraform:
| DevOps engineer |
Run Terraform Tests. |
| DevOps engineer |
Clean up resources. | Enter the following command to destroy the LocalStack container:
| DevOps engineer |
Troubleshooting
Issue | Solution |
---|---|
|
|
Related resources
Getting started with Terraform: Guidance for AWS CDK and AWS CloudFormation experts (AWS Prescriptive Guidance)
Best practices for using the Terraform AWS Provider (AWS Prescriptive Guidance)
Terraform CI/CD and testing on AWS with the new Terraform Test Framework
(AWS blog post) Accelerating software delivery using LocalStack Cloud Emulator from AWS Marketplace
(AWS blog post)
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
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