LocalStack – AWS Lambda Function with Python

To make development with the AWS service Lambda function, need access of AWS console and it include costing while executing for the testing purpose. It also include some security because you are providing the access of AWS i know you will do with IAM policy but it is tedious job for the developer specific one.

If we have solution where developer can do the testing on local machine with similar environment of AWS lambda then it become magic, is’nt it?

Yes, Localstack provide the solution of it. I would like to introduce step wise how to run the Lambda function from your local machine.

Step 1: Set up the docker yaml file for the localstack services. I defined the step in my previous blog named Localstack-S3

Step 2: Need some modification with the docker-compose.yaml file

version: "3.8"
 
services:
  localstack-s3:
    image: localstack/localstack:latest
    container_name: localstack-aws
    environment:
      - SERVICES=s3, lambda
      - EDGE_PORT=4566
      - DEFAULT_REGION=us-west-2
      - DATA_DIR=/tmp/localstack/data
    ports:
      - "4566-4583:4566-4583"
      - "8055:8080"
    volumes:
      - './.localstack:/tmp/localstack'
      - '/var/run/docker.sock:/var/run/docker.sock'

Step 3: Just execute the docker-compose.yaml with the below command

# docker-compose up

Step 4: configure the AWS with the below command and profile the fake access-key and secret key with default region is us-west-2

# aws configure –profile localstack

Step 5: Create the file name as lambda.py

import logging

LOGGER = logging.getLogger()
LOGGER.setLevel(logging.INFO)


def handler(event, context):
    logging.info('Hands-on-cloud')
    return {
        "message": "Hello User!"
    }

Step 6: Create the main.py file to create/delete/invoke the lambda function

import os
import logging
import json
from zipfile import ZipFile

import boto3

AWS_REGION = 'us-west-2'
AWS_PROFILE = 'localstack'
ENDPOINT_URL = 'http://localhost:4566'
LAMBDA_ZIP = './function.zip'

boto3.setup_default_session(profile_name=AWS_PROFILE)

# logger config
logger = logging.getLogger()
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s: %(levelname)s: %(message)s')


def get_boto3_client(service):
    """
    Initialize Boto3 Lambda client.
    """
    try:
        lambda_client = boto3.client(
            service,
            region_name=AWS_REGION,
            endpoint_url=ENDPOINT_URL
        )
    except Exception as e:
        logger.exception('Error while connecting to LocalStack.')
        raise e
    else:
        return lambda_client


def create_lambda_zip(function_name):
    """
    Generate ZIP file for lambda function.
    """
    try:
        with ZipFile(LAMBDA_ZIP, 'w') as zip:
            zip.write(function_name + '.py')
    except Exception as e:
        logger.exception('Error while creating ZIP file.')
        raise e


def create_lambda(function_name):
    """
    Creates a Lambda function in LocalStack.
    """
    try:
        lambda_client = get_boto3_client('lambda')
        _ = create_lambda_zip(function_name)

        # create zip file for lambda function.
        with open(LAMBDA_ZIP, 'rb') as f:
            zipped_code = f.read()

        lambda_client.create_function(
            FunctionName=function_name,
            Runtime='python3.8',
            Role='role',
            Handler=function_name + '.handler',
            Code=dict(ZipFile=zipped_code)
        )
    except Exception as e:
        logger.exception('Error while creating function.')
        raise e


def delete_lambda(function_name):
    """
    Deletes the specified lambda function.
    """
    try:
        lambda_client = get_boto3_client('lambda')
        lambda_client.delete_function(
            FunctionName=function_name
        )
        # remove the lambda function zip file
        os.remove(LAMBDA_ZIP)
    except Exception as e:
        logger.exception('Error while deleting lambda function')
        raise e


def invoke_function(function_name):
    """
    Invokes the specified function and returns the result.
    """
    try:
        lambda_client = get_boto3_client('lambda')
        response = lambda_client.invoke(
            FunctionName=function_name)
        # print(response)    
        return json.loads(
            response['Payload']
            .read()
            .decode('utf-8')
        )
    except Exception as e:
        logger.exception('Error while invoking function')
        raise e

create_lambda('lambda') # to create the lambda function
resp = invoke_function('lambda') 
print(resp)  

Step 7: Execute the main.py file with the below command to see the lambda.py output.

# python main.py

Step 8: To verify the lambda function created or not, Run the below command to get the list of lambda function from the localstack:

# aws –endpoint-url=http://localhost:4566 lambda list-functions

{
    "Functions": [
        {
            "FunctionName": "lambda",
            "FunctionArn": "arn:aws:lambda:us-west-2:000000000000:function:lambda",
            "Runtime": "python3.8",
            "Role": "role",
            "Handler": "lambda.handler",
            "CodeSize": 309,
            "Description": "",
            "Timeout": 3,
            "LastModified": "2022-03-19T12:53:23.534+0000",
            "CodeSha256": "yBwA+WRL5iF7mQWX+m1MXrL0tsgzDAmzBQaUHNCh3mA=",
            "Version": "$LATEST",
            "VpcConfig": {},
            "TracingConfig": {
                "Mode": "PassThrough"
            },
            "RevisionId": "26d31821-c1f3-4462-acd4-a8545026a19b",
            "State": "Active",
            "LastUpdateStatus": "Successful",
            "PackageType": "Zip",
            "Architectures": [
                "x86_64"
            ]
        }
    ]
}

That’s it. Enjoy with the lambda function creation on local and test it.

  • 23
    Shares