AWS recently announced the public preview of Serverless Application Model (SAM) support for CDK. SAM is an open-source framework that can be used to build, test and deploy serverless applications on AWS. It provides a Lambda-like execution environment that lets you locally build, test, and debug applications. Previously this could only be defined by SAM templates but now it is also possible through the AWS Cloud Development Kit (CDK)!
I will guide you through a small demo project to demonstrate how to build a serverless application with AWS CDK and test it locally with AWS SAM.
We will build a simple REST API which shows the current bid or ask price of a certain cryptocurrency on Binance (exchange), expressed in the value of Bitcoin.
The API expects two query parameters:
- coin: (ETH, DOG, LINK, DOT, ...)
- type: (bid or ask price)
Example of the API call:
$ curl "http://127.0.0.1:3000/crypto?type=ask&coin=ETH"
{"coin": "ETH", "price": 0.066225}
The setup in AWS will also be pretty straight forward.
We will set up a Lambda proxy integration in API Gateway
To get started, we need to install the AWS CDK CLI and create a new CDK project. I use Python as client language.
$ npm install -g aws-cdk
$ cdk init app --language python
The project structure looks like this:
.
├── README.md
├── app.py
├── cdk.json
├── requirements.txt
├── sam_cdk_demo
│ ├── __init__.py
│ └── sam_cdk_demo_stack.py
└── setup.py
The file sam_cdk_demo/sam_cdk_demo_stack.py
should contain our code to define the AWS cloud resources we need but first let's start with writing our Lambda.
Create a folder inside the root of the project called "lambda" and add a handler.py
. The ccxt library is used by our Lambda to interact with the Binance API. The Lambda itself is very basic on purpose.
import ccxt
import json
# use CCXT library to connect with Binance API
exchange = getattr(ccxt, 'binance')({
'timeout': 3000,
'enableRateLimit': True
})
def get_current_price(coin_name, price_type):
# fetch latest ticker data for coin pair xxx/BTC
ticker = exchange.fetch_ticker('{}/BTC'.format(coin_name))
# get ask/bid price from ticket data
current_price = ticker[price_type]
return current_price
def lambda_handler(event, context):
# get values from query string parameters
coin = event['queryStringParameters']['coin']
price = event['queryStringParameters']['type']
# CCXT exchange expects coin in uppercase
valid_coin = coin.upper()
# get current price based on coin name and price type (ask/bid)
current_price = get_current_price(valid_coin, price)
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json'
},
'body': json.dumps({
'coin': valid_coin,
'price': current_price,
})
}
Don't forget to add a requirements.txt
inside the folder to make the ccxt library available to the Lambda.
ccxt==1.50.13
The Lambda is ready! Now we will use AWS CDK to define our AWS infrastructure. We need to deploy the Lambda and create an API Gateway in front of it. Update the file demo/demo_stack.py
. We keep the code pretty basic again.
from aws_cdk import (
aws_lambda as _lambda,
aws_apigateway as apigw,
core,
)
class CdkLambdaSamStack(core.Stack):
def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# creating Lambda function that will be triggered by the API Gateway
get_price_handler = _lambda.Function(self,'CryptoFunction',
handler='handler.lambda_handler',
runtime=_lambda.Runtime.PYTHON_3_8,
code=_lambda.Code.asset('lambda'),
timeout=core.Duration.seconds(30),
)
# create REST API
api = apigw.RestApi(self, 'crypto-api')
# add resource /crypto
resource = api.root.add_resource('crypto')
# create Lambda integration
get_crypto_integration = apigw.LambdaIntegration(get_price_handler)
# add method which requires two query string parameteres (coin and type)
resource.add_method(
http_method='GET',
integration=get_crypto_integration,
request_parameters={
'method.request.querystring.coin': True,
'method.request.querystring.type': True
},
request_validator_options=apigw.RequestValidatorOptions(validate_request_parameters=True)
)
Update the requirements.txt
in the project root with the necessary modules.
aws-cdk.core
aws-cdk.aws_lambda
aws-cdk.aws_apigateway
Start the Python virtual environment which is created by CDK and install the modules.
$ source .venv/bin/activate
(.venv)$ pip3 install -r requirements.txt
We will use AWS SAM to test our setup locally. It's important to mention that you need to have Docker installed. We will use Docker to build our code. The Lambda will also run inside as a Lambda-like Docker container.
Prepare the deployment artifact.
(.venv)$ sam-beta-cdk build --use-container
Start the local API Gateway.
$ sam-beta-cdk local start-api
...
* Running on http://127.0.0.1:3000/
We can use a tool like Postman (or curl
or just your browser) to perform calls against our API.
It takes a few seconds to execute the function because AWS SAM is spinning up a Docker container to execute our code. After the execution the container is destroyed.
When everything looks fine we can deploy it to AWS.
(.venv)$ cdk bootstrap
(.venv)$ cdk deploy -a .aws-sam/build
Now test against the deployed API.
We were able to test our API and Lambda using the new Serverless Application Model integration with CDK! You can find all code on my GitHub. Be aware that this feature is in preview. Feel free to do more extensive testing. You can report bugs and submit feature requests to the SAM opensource repository.
Top comments (1)
This is awesome, I'll have to give it a try in TypeScript/JavaScript!