AWS Lambda Powertools are awesome

At FourCo we make heavy use of Lambda Functions. I recently stumbled upon the AWS Lambda Powertools project, a suite of utilities for AWS Lambda Functions written in Python. They have made the development process for Lambda Functions a lot easier. In this blog I’ll go over a few of the utilities with examples.

Parameters Utility

Getting a value from the SSM Parameter store, Secrets Manager or a DynamoDB Table usually means diving into the boto3 documentation to check the request and response syntax and then writing quite a few lines of code to retrieve the actual value. Here is how it looks with AWS Lambda Powertools:

from aws_lambda_powertools.utilities import parameters

def handler(event, context):
    value = parameters.get_parameter("/my/parameter")

    # get_parameters returns a dict with the parameter name as key
    values = parameters.get_parameters("/my/path/prefix")
    for k, v in values.items():
        print(f"{k}: {v}")

Besides getting a single parameter, you can also easily get all the parameters for a given path.

Getting a secret from Secrets Manager works exactly the same:

from aws_lambda_powertools.utilities import parameters

def handler(event, context):
    value = parameters.get_secret("secret-name")

To get a value from DynamoDB we need a bit more info about our table, but it’s still a lot easier than making custom boto3 calls:

from aws_lambda_powertools.utilities import parameters

dynamodb_provider = parameters.DynamoDBProvider(
    table_name="my-table",
    key_attr="MyKeyAttr",
    value_attr="MyvalueAttr"
)

def handler(event, context):
    value = dynamodb_provider.get("my-parameter")

Event Source Data Classes Utility

You can trigger your Lambda Function in many ways, for example by an S3 bucket upload event or from an API Gateway. These events are passed to the Lambda Function as a nested json to the ‘event’ parameter. An example of how this looks for a Lambda Function triggered by an S3 notification event:

{
  "Records": [
    {
      "eventVersion": "2.1",
      "eventSource": "aws:s3",
      "awsRegion": "us-east-2",
      "eventTime": "2019-09-03T19:37:27.192Z",
      "eventName": "ObjectCreated:Put",
      "userIdentity": {
        "principalId": "AWS:AIDAINPONIXQXHT3IKHL2"
      },
      "requestParameters": {
        "sourceIPAddress": "205.255.255.255"
      },
      "responseElements": {
        "x-amz-request-id": "D82B88E5F771F645",
        "x-amz-id-2": "vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo="
      },
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "828aa6fc-f7b5-4305-8584-487c791949c1",
        "bucket": {
          "name": "DOC-EXAMPLE-BUCKET",
          "ownerIdentity": {
            "principalId": "A3I5XTEXAMAI3E"
          },
          "arn": "arn:aws:s3:::lambda-artifacts-deafc19498e3f2df"
        },
        "object": {
          "key": "b21b84d653bb07b05b1e6b33684dc11b",
          "size": 1305107,
          "eTag": "b21b84d653bb07b05b1e6b33684dc11b",
          "sequencer": "0C0F6F405D6ED209E1"
        }
      }
    }
  ]
}

The Event Source Data Classes utility of Powertools provides data classes for most commonly used Lambda event sources. It provides easy to use decorators for the Lambda handler, an example for the same S3 notification event:

from aws_lambda_powertools.utilities.data_classes import event_source, S3Event

@event_source(data_class=S3Event)
def lambda_handler(event: S3Event, context):
    bucket_name = event.bucket_name

    for record in event.records:
        object_key = record.s3.get_object.key

        do_something_with(f"{bucket_name}/{object_key}")

Besides making your code a lot shorter and easier to read, it also allows for autocomplete in your IDE. This saves a lot of going back and forth between your code and the boto3 documentation.

image 1
Autocomplete example from Visual Studio Code

Typing Utility

I’d like to end with a short and sweet one: the Typing utility. I like to use type hints for my Python code, but would often end up with everything neatly typed except for the Lambda Context! Finally these days are over:

from typing import Any, Dict
from aws_lambda_powertools.utilities.typing import LambdaContext

def handler(event: Dict[str, Any], context: LambdaContext) -> Dict[str, Any]:
    pass

This makes it much easier to use the context object in your IDE, as it gives the same autocomplete feature as before. But let’s be honest: even if you don’t use the context object at all in your handler code, you can sleep safe and sound knowing that all your variables are typed.

Installation

AWS Lambda Powertools is not bundled with the Lambda runtime, but is available via a Lambda Layer at arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPython:20 (or you can just use old-fashioned pip install aws-lambda-powertools).

These are just some examples of the functionality of AWS Lambda Powertools. You can find everything about it on their official site. It has great examples and a tutorial for their bigger utilities. Highly recommended!

Link: awslabs.github.io/aws-lambda-powertools-python/latest/