What is that Transform in SAM?

For developers getting into the world of serverless applications using AWS Serverless Application Model (SAM), the Transform section might seem a bit cryptic. Basically, the Transform section acts as a translator. It tells AWS CloudFormation how to interpret your SAM template. Remember, SAM templates are written in their own YAML or JSON formats. However, CloudFormation has its own way of defining resources and configurations. The Transform section bridges this gap.

Remember, SAM is just a way to generate CloudFormation template.

When you write a SAM template, you’ll typically see this line in the Transform section:

This line essentially tells CloudFormation this template uses the SAM syntax. In the following example, a specific version (2016-10-31 in this case) is used for transformation. With this specified, CloudFormation can take your SAM template written with functions, APIs, and other serverless resources, and translate it into a vanilla CloudFormation template that it understands perfectly.

Transform: AWS::Serverless-2016-10-31

The Transform section ensures your code is translated into the correct CloudFormation template format. One of the reasons why SAM is great for serverless developers, but it allows you to use a simplified configuration for your serverless services without being required to write a more complex CloudFormation configuration.

Here’s a simple SAM template example, along with an explanation of how it’s transformed into CloudFormation:

SAM Template (template.yaml)

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  MyLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs12.x
      CodeUri: ./my-function-code
      Events:
        MyAPIEvent:
          Type: Api 
          Properties:
            Path: /hello
            Method: get

Let’s Break Down the Parts of the Config

  • AWSTemplateFormatVersion: Standard declaration for CloudFormation templates.
  • Transform: Specifies the SAM transformation.
  • Resources: Where you define your infrastructure.
    • MyLambdaFunction:
      • Type: AWS::Serverless::Function This is a SAM-specific resource type that represents a Lambda function.
      • Properties:
        • Handler: The entry point for your function (index.handler)
        • Runtime: The programming language the function uses.
        • CodeUri: The location of your Lambda function’s code.
    • Events: MyAPIEvent
      • This links an API Gateway event source to your Lambda function.
      • Type: Api indicates an API Gateway REST API will be created.
      • Path, Method determines the API resource path and HTTP method.

Here is the CloudFormation Template Generated from SAM

AWSTemplateFormatVersion: '2010-09-09'
Description: Simple Hello World API

Resources:

  HelloWorldFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs12.x 
      CodeUri: ./hello-world-function
      Role: !GetAtt HelloWorldFunctionRole.Arn

  HelloWorldFunctionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/AWSLambdaBasicExecutionRole 

  HelloWorldAPI:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      DefinitionBody:
        swagger: '2.0'
        info:
          title: Hello World API
        paths:
          /hello:
            get:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloWorldFunction.Arn}/invocations'
                
  InvokePermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref HelloWorldFunction
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com

Outputs:
  APIURL:
    Description: Endpoint URL for the Hello World API
    Value: !Sub 'https://${HelloWorldAPI}.execute-api.${AWS::Region}.amazonaws.com/Prod' 

Let’s walk through the example above.

  1. Lambda Function (HelloWorldFunction): Contains the code that returns “Hello World!”. Key parameters are HandlerRuntime, and CodeUri.
  2. IAM Role (HelloWorldFunctionRole): Grants minimal permissions for the Lambda function to execute.
  3. API Gateway (HelloWorldAPI): Defines a REST API with:
    • A GET endpoint at /hello
    • Integrates with the Lambda function using aws_proxy.
  4. Permissions (InvokePermission): Allows API Gateway to invoke your Lambda function.
  5. Outputs: Returns the API’s endpoint URL for easy access.