DEV Community

Randika Madhushan Perera
Randika Madhushan Perera

Posted on

Developing AWS Lambda Functions In Locally

1. Introduction

In this article, we are going to learn about Lambda function creating, building, updating, and testing locally.

We can use AWS SAM to achieve this.

1.1 What is SAM

the AWS Serverless Application Model (SAM) is an open-source framework for building serverless applications. It provides shorthand syntax to express functions, APIs, databases, and event source mappings. With just a few lines per resource, you can define the application you want and model it using YAML.

During deployment, SAM transforms and expands the SAM syntax into AWS CloudFormation syntax, enabling you to build serverless applications faster.

2. Setup the environment

2.1 Install AWS SAM CLI

You need to follow the below steps to install the AWS SAM.

2.2 Install Docker Desktop

Follow, and install the docker application on your desktop.

2.3 Authenticate AWS using AWS CLI

Follow AWS CLI, to authenticate your AWS account.

3. Create a project

Step 01: Create a folder and go inside of that folder. Here I'm using "sam-projects".

Inside of the folder run the below command to make sure your SAM installation is successful.

sam -h 
Enter fullscreen mode Exit fullscreen mode

Step 02: To create a new project run the sam init command.

I'm using AWS Quick start template.

PS C:\sam_projects\sam init You can preselect a particular runtime or package type when using the `sam init` experience. Call `sam init --help` to learn more. Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 Choose an AWS Quick Start application template 1 - Hello World Example 2 - Data processing 3 - Hello World Example with Powertools for AWS Lambda 4 - Multi-step workflow 5 - Scheduled task 6 - Standalone function 7 - Serverless API 8 - Infrastructure event management 9 - Lambda Response Streaming 10 - Serverless Connector Hello World Example 11 - Multi-step workflow with Connectors 12 - GraphQLApi Hello World Example 13 - Full Stack 14 - Lambda EFS example 15 - Hello World Example With Powertools for AWS Lambda 16 - DynamoDB Example 17 - Machine Learning Template: 1 Use the most popular runtime and package type? (Python and zip) [y/N]: y Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: N Would you like to enable monitoring using CloudWatch Application Insights? For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html [y/N]: N Would you like to set Structured Logging in JSON format on your Lambda functions? [y/N]: y Structured Logging in JSON format might incur an additional cost. View https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-pricing for more details Project name [sam-app]: sam-app2 Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment) ----------------------- Generating application: ----------------------- Name: sam-app2 Runtime: python3.9 Architectures: x86_64 Dependency Manager: pip Application Template: hello-world Output Directory: . Configuration file: sam-app2\samconfig.toml Next steps can be found in the README file at sam-app2\README.md Commands you can use next ========================= [*] Create pipeline: cd sam-app2 && sam pipeline init --bootstrap [*] Validate SAM template: cd sam-app2 && sam validate [*] Test Function in the Cloud: cd sam-app2 && sam sync --stack-name {stack-name} --watch 
Enter fullscreen mode Exit fullscreen mode

Now you see your project has been created.

sam-app2

Step 03: Explaining project structure

** I have deleted "tests" folder. We do not need that for this lesson.

Let's start with template.yaml file.

SAM is that it deploys and maintains all of your resources, this is very similar to CloudFormation, actually this uses CloudFormation to deploy your resources and create a change set to update your resources.

template.yaml

AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > sam-app2 Sample SAM Template for sam-app2 # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst Globals: Function: Timeout: 3 MemorySize: 128 # You can add LoggingConfig parameters such as the Logformat, Log Group, and SystemLogLevel or ApplicationLogLevel. Learn more here https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-loggingconfig. LoggingConfig: LogFormat: JSON Resources: HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.9 Architectures: - x86_64 Events: HelloWorld: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: Path: /hello Method: get Outputs: # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function # Find out more about other implicit resources you can reference within SAM # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api HelloWorldApi: Description: API Gateway endpoint URL for Prod stage for Hello World function Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" HelloWorldFunction: Description: Hello World Lambda Function ARN Value: !GetAtt HelloWorldFunction.Arn HelloWorldFunctionIamRole: Description: Implicit IAM Role created for Hello World function Value: !GetAtt HelloWorldFunctionRole.Arn 
Enter fullscreen mode Exit fullscreen mode

So here, we do not need the below sections. I'm removing them to keep simple of the template.yaml file.

Outputs: # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function # Find out more about other implicit resources you can reference within SAM # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api HelloWorldApi: Description: API Gateway endpoint URL for Prod stage for Hello World function Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" HelloWorldFunction: Description: Hello World Lambda Function ARN Value: !GetAtt HelloWorldFunction.Arn HelloWorldFunctionIamRole: Description: Implicit IAM Role created for Hello World function Value: !GetAtt HelloWorldFunctionRole.Arn 
Enter fullscreen mode Exit fullscreen mode

and,

 Events: HelloWorld: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: Path: /hello Method: get 
Enter fullscreen mode Exit fullscreen mode

and also,

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst Globals: Function: Timeout: 3 MemorySize: 128 # You can add LoggingConfig parameters such as the Logformat, Log Group, and SystemLogLevel or ApplicationLogLevel. Learn more here https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-loggingconfig. LoggingConfig: LogFormat: JSON 
Enter fullscreen mode Exit fullscreen mode

My python runtime environment is set to Python 3.12, hence I'm changing it.

Final template.yaml

AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > sam-app2 Sample SAM Template for sam-app2 Resources: HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.12 Architectures: - x86_64 
Enter fullscreen mode Exit fullscreen mode

The resource name is "HelloWorldFunction"

So we have our actual lambda function called "app.py"

app.py

app.py

import json def lambda_handler(event, context): return { "statusCode": 200, "body": json.dumps({ "message": "hello world", # "location": ip.text.replace("\n", "") }), } 
Enter fullscreen mode Exit fullscreen mode

Events: We can send test events to our function to test it locally.

Step 04: Now we want to rebuild this so, we are using sam build. This creates like a build folder of our latest lambda function.

PS C:\sam_projects\sam-app2> sam build Starting Build use cache Manifest file is changed (new hash: 3298f13ca931dd4d421) or dependency folder (.aws-sam\deps\48421c5a-c936-9d9-443b05eeae8c) is missing for (HelloWorldFunction), downloading dependencies and copying/building source Building codeuri: C:\sam_projects\sam-app2\hello_world runtime: python3.12 metadata: {} architecture: x86_64 functions: HelloWorldFunction Running PythonPipBuilder:CleanUp Running PythonPipBuilder:ResolveDependencies Running PythonPipBuilder:CopySource Running PythonPipBuilder:CopySource Build Succeeded Built Artifacts : .aws-sam\build Built Template : .aws-sam\build\template.yaml Commands you can use next ========================= [*] Validate SAM template: sam validate [*] Invoke Function: sam local invoke [*] Test Function in the Cloud: sam sync --stack-name {{stack-name}} --watch [*] Deploy: sam deploy --guided 
Enter fullscreen mode Exit fullscreen mode

So now we can see .aws-sam folder below,

aws-sam-folder

In the build folder within that in our lambda function this hello world function and see it has all of the requests dependencies so we could just right-click open it and zip it up and upload it in lambda it's it's everything you need all of your dependencies in one folder.

buiildfolder

Every time you make changes make sure to rebuild.

Step 05:

let's say this is the first iteration and we want to deploy these resources it's as simple as and you see it right here in the commands to deploy sam deploy guided guided kind of walks us through the first process of deploying it so let's type that in
sam deploy --guided

PS C:\sam_projects\sam-app2> sam deploy --guided Configuring SAM deploy ====================== Looking for config file [samconfig.toml] : Found Reading default arguments : Success Setting default arguments for 'sam deploy' ========================================= Stack Name [sam-app2]: AWS Region [us-east-1]: us-west-2 #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [Y/n]: Y #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: Y #Preserves the state of previously provisioned resources when an operation fails Disable rollback [y/N]: y Save arguments to configuration file [Y/n]: Y SAM configuration file [samconfig.toml]: SAM configuration environment [default]: Looking for resources needed for deployment: Creating the required resources... Successfully created! Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-xxxxxxxx A different default S3 bucket can be set in samconfig.toml and auto resolution of buckets turned off by setting resolve_s3=False Parameter "stack_name=sam-app2" in [default.deploy.parameters] is defined as a global parameter [default.global.parameters]. This parameter will be only saved under [default.global.parameters] in C:\sam_projects\sam-app2\samconfig.toml. Saved arguments to config file Running 'sam deploy' for future deployments will use the parameters saved above. The above parameters can be changed by modifying samconfig.toml Learn more about samconfig.toml syntax at https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html Uploading to sam-app2/c43cafb817866506 532993 / 532993 (100.00%) Deploying with following values =============================== Stack name : sam-app2 Region : us-west-2 Confirm changeset : True Disable rollback : True Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-xxxxxxx Capabilities : ["CAPABILITY_IAM"] Parameter overrides : {} Signing Profiles : {} Initiating deployment ===================== Uploading to sam-app2/86dc15e504ed4983627c.template 516 / 516 (100.00%) Waiting for changeset to be created.. CloudFormation stack changeset ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Operation LogicalResourceId ResourceType Replacement ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Add HelloWorldFunctionRole AWS::IAM::Role N/A + Add HelloWorldFunction AWS::Lambda::Function N/A ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Changeset created successfully. arn:aws:cloudformation:us-west-2:xxxxxxxx:changeSet/samcli-deploy17981/5866bc24-2 Previewing CloudFormation changeset before deployment ====================================================== Deploy this changeset? [y/N]: 
Enter fullscreen mode Exit fullscreen mode

Now if we go to cloud formation we should see two stacks if this is the first time you've deployed with SAM you'll see two stacks.

The first stack is the SAM CLI managed default and this is it creates an s3 bucket to store your artifacts so this is a one-time thing once you do this the first time you use sam then the subsequent deployments your artifacts will just be added to this.

The other stack named sam-app2 is your resource this is what we're deploying so it's a status of review in progress let's go back to our project and see that it's waiting for me to confirm it.

stack

Waiting for changeset to be created.. CloudFormation stack changeset ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Operation LogicalResourceId ResourceType Replacement ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Add HelloWorldFunctionRole AWS::IAM::Role N/A + Add HelloWorldFunction AWS::Lambda::Function N/A ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Changeset created successfully. arn:aws:cloudformation:us-west-2:xxxxxxxx:changeSet/samcli-deploy11/5866b57-08875 Previewing CloudFormation changeset before deployment ====================================================== Deploy this changeset? [y/N]: Y 
Enter fullscreen mode Exit fullscreen mode

choose Y and press enter. It should deploy the lambda function in the role.

Now you can see the below in your CMD.

Deploy this changeset? [y/N]: Y 2024-01-06 17:18:59 - Waiting for stack create/update to complete CloudFormation events from stack operations (refresh every 5.0 seconds) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ResourceStatus ResourceType LogicalResourceId ResourceStatusReason ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- CREATE_IN_PROGRESS AWS::CloudFormation::Stack sam-app2 User Initiated CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole - CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole Resource creation Initiated CREATE_COMPLETE AWS::IAM::Role HelloWorldFunctionRole - CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction - CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction Resource creation Initiated CREATE_COMPLETE AWS::Lambda::Function HelloWorldFunction - CREATE_COMPLETE AWS::CloudFormation::Stack sam-app2 - ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Successfully created/updated stack - sam-app2 in us-west-2 
Enter fullscreen mode Exit fullscreen mode

Now you can see in the CloudFormation that "sam-app2" is completed.

samapp2complete

If we go to lambda functions we should see that function.

lambda

So we learned how to create one how to build it how to, deploy it Now we need to learn how to test it and how to update it.

Step 06: Test it and Update it.

So go back to your lambda function be sure you're not working in the build folder go back to your lambda function your app.py and let's add some stuff to it.

app.py

import json def lambda_handler(event, context): first_name = event['first_name'] message = event['message'] return { "statusCode": 200, "body": json.dumps({ "message": f"{message} {first_name}", # "location": ip.text.replace("\n", "") }), } 
Enter fullscreen mode Exit fullscreen mode

So how do we test this locally well there's a folder here called events with an event.json file in it and this was created with our template it's got a ton of information. So we just delete that content and create a simple one.

event.json

{ "first_name": "Randika", "message": "Hi" } 
Enter fullscreen mode Exit fullscreen mode

Now we can test it locally.

Step 07: Npw we want to build it again.

Run the below command again.

sam build 
Enter fullscreen mode Exit fullscreen mode

You'll see it invoke the function with sam local invoke let's try that out.

sam local invoke HelloWorldFunction -e events/event.json 
Enter fullscreen mode Exit fullscreen mode

You see the below output,

PS C:\sam_projects\sam-app2> sam local invoke HelloWorldFunction -e events/event.json Invoking app.lambda_handler (python3.12) Local image is up-to-date Using local image: public.ecr.aws/lambda/python:3.12-rapid-x86_64. Mounting C:\sam_projects\sam-app2\.aws-sam\build\HelloWorldFunction as /var/task:ro,delegated, inside runtime container START RequestId: 20e25543-e2c0-4ad7-9193-9a5547529f34 Version: $LATEST END RequestId: acb97b8f-6f7d-4385-8759-740cbc67ca51 REPORT RequestId: acb97b8f-6f7d-4385-8759-740cbc67ca51 Init Duration: 0.03 ms Duration: 83.20 ms Billed Duration: 84 ms Memory Size: 128 MB Max Memory Used: 128 MB {"statusCode": 200, "body": "{\"message\": \"Hi Randika\"}"} [ERROR] [1704549897802] LAMBDA_RUNTIME Failed to get next invocation. No Response from endpoint Traceback (most recent call last): File "/var/lang/lib/python3.12/site-packages/awslambdaric/lambda_runtime_client.py", line 86, in wait_next_invocation PS C:\Users\UPERE51\Documents\Personal\Developments\sam_projects\sam-app2> 
Enter fullscreen mode Exit fullscreen mode

You can see the below message in the above output.

{"statusCode": 200, "body": "{\"message\": \"Hi Randika\"}"}

That's how we test it.

Step 08:

We want to update the lambda function in AWS, we don't need to do Ssam deploy guided again, because we have this sam config tomo file that says hey here's the stack name here's the s3 bucket here's the region.

We're just going to do sam deploy.

sam deploy 
Enter fullscreen mode Exit fullscreen mode

Output:

PS C:\sam_projects\sam-app2> sam deploy Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-xxxxxxx A different default S3 bucket can be set in samconfig.toml Or by specifying --s3-bucket explicitly. Uploading to sam-app2/61f5bc 533019 / 533019 (100.00%) Deploying with following values =============================== Stack name : sam-app2 Region : us-west-2 Confirm changeset : True Disable rollback : True Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-xxxxxxx Capabilities : ["CAPABILITY_IAM"] Parameter overrides : {} Signing Profiles : {} Initiating deployment ===================== Uploading to sam-app2/62.template 516 / 516 (100.00%) Waiting for changeset to be created.. CloudFormation stack changeset ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Operation LogicalResourceId ResourceType Replacement ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Modify HelloWorldFunction AWS::Lambda::Function False ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Previewing CloudFormation changeset before deployment ====================================================== Deploy this changeset? [y/N]: y 2024-01-06 19:40:53 - Waiting for stack create/update to complete CloudFormation events from stack operations (refresh every 5.0 seconds) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ResourceStatus ResourceType LogicalResourceId ResourceStatusReason ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- UPDATE_IN_PROGRESS AWS::CloudFormation::Stack sam-app2 User Initiated UPDATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction - UPDATE_COMPLETE AWS::Lambda::Function HelloWorldFunction - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS AWS::CloudFormation::Stack sam-app2 - UPDATE_COMPLETE AWS::CloudFormation::Stack sam-app2 - ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Successfully created/updated stack - sam-app2 in us-west-2 
Enter fullscreen mode Exit fullscreen mode

We should see in cloud formation the change set created. Let's go to the "sam-app2" and go to change sets and you can see the below

samapp2cloud

And that's it that's your workflow for developing lambda functions locally.

Top comments (2)

Collapse
 
lasanthasilva profile image
Lasantha Sanjeewa Silva

AweSome !! Keep It Bro

Collapse
 
randiakm profile image
Randika Madhushan Perera

Thank you @lasanthasilva :)