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 :)