Test your Ballerina Function written for AWS Lambda

Hemika Kodikara
Ballerina Swan Lake Tech Blog
4 min readFeb 21, 2020

This article explains how we can locally test AWS Lambda function written in Ballerina.

Implementing your Lambda function in Ballerina

Lets create a Ballerina file named hello_world.bal. In that create a function with @awslambda:Function annotations that returns “Hello World!” as follows:

hello_world.bal

Now lets build our Ballerina file using the ballerina build command. I am using Ballerina version 1.1.3 here. You should get an output like this when building with the @awslambda:Function annotation.

$> ballerina build hello_world.bal
Compiling source
hello_world.bal
Generating executables
hello_world.jar
@awslambda:Function: sayHello
Run the following commands to deploy each Ballerina AWS Lambda function: aws lambda create-function --function-name <FUNCTION_NAME> --zip-file fileb://aws-ballerina-lambda-functions.zip --handler hello_world.<FUNCTION_NAME> --runtime provided --role <LAMBDA_ROLE_ARN> --timeout 10 --memory-size 1024 aws lambda update-function-configuration --function-name <FUNCTION_NAME> --layers arn:aws:lambda:<REGION_ID>:141896495686:layer:ballerina:2Run the following command to re-deploy an updated Ballerina AWS Lambda function:
aws lambda update-function-code --function-name <FUNCTION_NAME> --zip-file fileb://aws-ballerina-lambda-functions.zip

You should see a zip file generated having the name “aws-ballerina-lambda-functions.zip”. Make note of the layer name arn:aws:lambda:<REGION_ID>:141896495686:layer:ballerina:2 mentioned in the output logs as well.

We have now generated the artifacts to deploy the function in AWS Lambda. But we going to test it locally first.

Testing your Lambda Function Locally

Following tasks/requirements are needed to test our AWS Lambda function locally.

  1. AWS CLI command configured to an account. This is to download the layers locally.
  2. Docker is up and running.
  3. Install sam command.
  4. Write a AWS SAM specification yaml file.

Installing sam command

sam is a CLI command used in creating and managing serverless applications. You can refer the official documentation on how to install it at https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html.

I used Homebrew since I am on MacOS.

$> brew tap aws/tap
$> brew install aws-sam-cli
$> sam --version
SAM CLI, version 0.41.0

Write a AWS SAM specification yaml file.

The AWS SAM specification file defines resources types, resource properties and etc for our serverless application.

You can find the official documentation of the specification yaml file at https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification.html.

Now lets write a template.yml specification file to specify where our function code can be found and the necessary runtime and layers to execute the function.

In the template.yml we’ll define an AWS::Serverless::Function resource with name “HelloWorldFunction”. In that resource specify the following properties:

  1. Set Runtime field as provided because we will be using a layer which has the runtime dependencies.
  2. Set CodeUri to the aws-ballerina-lambda-functions.zip file which was generated from the ballerina build command.
  3. Set Handler as hello_world.sayHello . hello_world is the name of the Ballerina file and sayHello is the name of the Ballerina function in the Ballerina file.
  4. Set Layer as arn:aws:lambda:us-east-1:141896495686:layer:ballerina:2 . This is the same layer that was shown from ballerina build command. Here we use us-east-1 as the <REGION_ID>.
template.yml

Now lets test function with debug logs enabled by executing the following command. HelloWorldFunction is the resource name we provided in the template.yml.

$> sam local invoke “HelloWorldFunction” --debug

Telemetry endpoint configured to be https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics
local invoke command is called
No Parameters detected in the template
1 resources found in the template
Found Serverless function with name='HelloWorldFunction' and CodeUri='aws-ballerina-lambda-functions.zip'
Found one Lambda function with name 'HelloWorldFunction'
Invoking hello_world.sayHello (provided)
No environment variables found for function 'HelloWorldFunction'
Environment variables overrides data is standard format
Loading AWS credentials from session with profile 'None'
Resolving code path. Cwd=/private/tmp/hello_world_lambda, CodeUri=aws-ballerina-lambda-functions.zip
Resolved absolute path to code is /private/tmp/hello_world_lambda/aws-ballerina-lambda-functions.zip
Decompressing /private/tmp/hello_world_lambda/aws-ballerina-lambda-functions.zip
File hello_world.jar in zipfile does not have permission information
File functions.jar in zipfile does not have permission information
arn:aws:lambda:us-east-1:141896495686:layer:ballerina:2 is already cached. Skipping download
Image was not found.
Building image...
Requested to skip pulling images ...
Mounting /private/var/folders/0j/kf99jpqj0zs_26zw7vygjgc00000gn/T/tmp04blut77 as /var/task:ro,delegated inside runtime container
Starting a timer for 10 seconds for function 'HelloWorldFunction'
START Ballerina
START RequestId: c04371a4-da9d-1359-31b7-448940edce98 Version: $LATEST
END RequestId: c04371a4-da9d-1359-31b7-448940edce98
REPORT RequestId: c04371a4-da9d-1359-31b7-448940edce98 Init Duration: 3070.89 ms Duration: 126.78 ms Billed Duration: 200 ms Memory Size: 128 MB Max Memory Used: 76 MB
Sending Telemetry: {'metrics': [{'commandRun': {'awsProfileProvided': False, 'debugFlagProvided': True, 'region': '', 'commandName': 'sam local invoke', 'duration': 15941, 'exitReason': 'success', 'exitCode': 0, 'requestId': 'fc2eb900-21b4-471c-9c82-396a7e187999', 'installationId': 'cea54d15-ca1e-429d-a9f1-e801086e0349', 'sessionId': 'b5b1b6bc-a206-4094-af98-1ede605618d1', 'executionEnvironment': 'CLI', 'pyversion': '3.7.6', 'samcliVersion': '0.41.0'}}]}
HTTPSConnectionPool(host='aws-serverless-tools-telemetry.us-west-2.amazonaws.com', port=443): Read timed out. (read timeout=0.1)
"Hello World!"

From the output we can see that “Hello World” has been logged. So our function has successfully run locally!.

In the above logs it can be seen that it says “Building image…”. This is a docker image that has been pulled by the CLI to to run the lambda function locally. You can see this image by running docker images.

By default the SAM CLI collects telemetry. More information on this behaviour can be found at https://github.com/awslabs/aws-sam-cli/issues/1525. You can disable telemetry by setting the following environment variable.

export SAM_CLI_TELEMETRY=0

--

--