Test your cloud infrastructure locally using localstack

Tim Rosenblüh
28. November 2022
Reading time: 6 min
Test your cloud infrastructure locally using localstack

Introduction

In order to test a cloud infrastructure and ensure the communication and functionality of individual components, a dedicated environment is often necessary. Normally, a development environment exists for exactly this purpose. Here, new infrastructure iterations or new services/functionalities can be tested before they are deployed in the production environment.
The disadvantages of this are, on the one hand, waiting for resources to be made available (which can take alot of time depending on the component used) and, on the other hand, the costs incurred for these resources.
So in addition to production, costs will be incurred for the development environment as well.
And this is where localstack comes into play. With it’s help, testing of AWS resources no longer has to be done purely in a dedicated account, but can be performed locally by the developers. Of course localstack does not replace a development account, but it can accelerate the infrastructure development significantly.

What is localstack?

Localstack allows developers to build and fully test their applications locally. To do this, it simulates the cloud environment on the respective computer without requiring a connection to the remote cloud provider. Common tools such as the AWS CLI, CDK or Terraform can then be used to create and test the desired resources. In addition, it is not necessary to wait for the lengthy provisioning of services, but tests can usually be run immediately after the deployment. This saves a lot of time, which in turn can be used to find errors or achieve faster development cycles.

Advantages

  • No connection to AWS required
  • Supports various IaC tools (CDK, Terraform, etc.)
  • Faster development cycle (You don’t have to wait for the provisioning of cloud resources)
  • Use of the same APIs as in the AWS Cloud
  • Price advantages compared to testing in the cloud (based on the version used e.g. Community, Pro, Team, Enterprise)

To learn more visit: localstack.cloud

Getting started with localstack

Let’s take a look on how we can start using localstack to create a cloud infrastructure.

Prerequisites for localstack

<ul> <li>python installed + pip (package manager)</li> <li>Docker installed</li> </ul> Localstack can be installed with the following command: <pre><code class=”lang-cmd”>pip <span class=”hljs-keyword”>install</span> localstack </code></pre>

Trying out localstack

After a successful installation localstack can be started: <pre><code class=”lang-cmd”>localstack start <span class=”hljs-_”>-d</span> </code></pre> With localstack running we could now already test aws-cli commands and create local resources. For example, take a look at all S3 buckets: <pre><code class=”lang-cmd”>aws –endpoint-url <span class=”hljs-string”>http:</span><span class=”hljs-comment”>//localhost:4566 s3api list-buckets</span> </code></pre> <strong>Note:</strong> When using localstack via aws-cli, the <em>endoint-url</em> must be specified so that localstack can process the requests. If this is not present, the CLI will try to connect to the AWS cloud (e.g. based on your profile credentials).

Defining the infrastructure with CDK

Next, we want to create a small application consisting of API Gateway, AWS Lambda and DynamoDB and test it locally. For this we will not use the aws-cli but deploy the microservice using CDK.

Prerequisites for CDK

Run the following command to verify the installation:

cdklocal <span class="hljs-comment">--version</span>

Note: In the following project TypeScript is used.

Create the infrastructure

First, a project folder must be created. In this folder you can execute the command (see below) to initialize the CDK project.

cdk init app --language=typescript

After that, the corresponding resources can be defined.

    // DynamoDB Table
    const dynamoTable = new dynamodb.Table(this, 'test-table', {
        partitionKey: { name: 'name', type: dynamodb.AttributeType.STRING }
    })
    // Lambda Function
    const lambdaFunc = new Function(this, 'lambdaFunc', {
      runtime: Runtime.NODEJS_14_X,
      code: Code.fromAsset('./lambda'),
      handler: 'index.handler',
      environment: {
        TABLE_NAME: dynamoTable.tableName
      }
    })
    // REST-API with Lambda-Function-Integration
    const api = new RestApi(this, 'myapi', {});
    const lambdaIntegration = new LambdaIntegration(lambdaFunc);
    const sendResource = api.root.addResource('send');
    sendResource.addMethod('POST', lambdaIntegration);
// Output for local API endpoint
new CfnOutput(this, 'endpoint', { value: `http://localhost:4566/restapis/${api.restApiId}/dev/_user_request_${sendResource.path}` })

To deploy the infrastructure locally, the environment must first be bootstrapped so that all the necessary resources for using CDK are available in the localstack environment.

cdklocal bootstrap

Note: After successfully bootstrapping the environment, you can see the bucket used for the CDK deployment:

aws --endpoint-url http://localhost:4566 s3api list-buckets

After that, we can deploy our infrastructure. To do this, run:

cdklocal deploy

And with that, our infrastructure got deployed.
We can now send a POST request via curl or Postman to one of the endpoints:

API Endpoints
API Endpoints

(Make sure to append ‘send’ to the second one)

The body should look like this:

{
    "name": "Tester"
}

Finally, we can verify the content of the local DynamoDB table using the aws-cli:

aws --endpoint-url=http://localhost:4566 dynamodb scan --table-name YOUR_TABLE_NAME

All created names should then be available in the table:

{
    "Items": [
        {
            "name": {
                "S": "Tester"
            }
        },
        {
            "name": {
                "S": "Peter"
            }
        },
        {
            "name": {
                "S": "Tim"
            }
        }
    ],
    "Count": 3,
    "ScannedCount": 3,
    "ConsumedCapacity": null
}

To remove the infrastructure from the local environment, cdklocal destroy can be run.

Note:

In order for the Lambda-Function to access the local AWS services, the associated endpoint must be specified when initializing the respective SDKs.

Example with the DynamoDB DocumentClient:

const documentClient = new AWS.DynamoDB.DocumentClient({endpoint: `http://${process.env.LOCALSTACK_HOSTNAME}:4566`})

If this is not explicitly defined, the DocumentClient/aws-sdk will attempt to connect to the remote cloud provider, which of course will result in an error.

To get more info visit the localstack documentation:

Summary

Localstack allows developers to test their cloud infrastructure locally, without having to wait for provisioning of resources or being billed for the resources used. This can be done using standard technologies for creating and managing resources. These include the AWS CLI, CDK or Terraform. With this developers can test their infrastructure faster and thus shorten the development cycles significantly.

To learn more about localstack visit:

Thank you for reading my blogpost about AWS development with localstack. Feel free to provide me with any feedback!