Skip to content

Support adding events to existing functions #866

@jlhood

Description

@jlhood

Update: This top-level comment contains the finalized spec based on feedback from the community. Next step is implementation. We're looking for contributors who can help implement this feature. Thanks!

Description:

Per #349 (comment), creating a separate RFC for a SAM syntax that would allow functions provided by nested applications (AWS::Serverless::Application) to be attached to event triggers via the same Events syntax as AWS::Serverless::Function resources.

High-Level Approach: Add a new SAM resource type: AWS::Serverless::FunctionReference. It doesn't create a new AWS::Lambda::Function resource. Instead, it allows you to specify the name and ARN of an existing function and then attach event sources to it using the exact same Events syntax as AWS::Serverless::Function.

The nice thing about this approach is it's not strictly tied to nested apps. It could be used with Fn::ImportValue for example, if you want to add triggers to a function created in a separate stack in your account.

However, we will offer a simplified syntax for the nested application use case specifically.

Example 1: Nested stack with function reference

  # Example native CloudFormation nested stack that creates a function and outputs the function's name as template output variable NestedFunctionName
  NestedStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: <url>

  NestedFunctionExample:
    Type: AWS::Serverless::FunctionReference
    Properties:
      FunctionName: !GetAtt NestedStack.Outputs.NestedFunctionName
      Events: 
        GetRoot:
          Type: Api
          Properties:
            Path: /
            Method: GET

Example 2: Nested application with function reference

  # Example nested SAR application that creates a function and outputs the function's name as template output variable NestedFunctionName
  NestedApp:
    Type: AWS::Serverless::Application
    Properties:
      Location:
        ApplicationId: <app id>
        SemanticVersion: 1.0.0

  NestedFunctionExample:
    Type: AWS::Serverless::FunctionReference
    Properties:
      FunctionName: !GetAtt NestedApp.Outputs.NestedFunctionName
      Events: 
        GetRoot:
          Type: Api
          Properties:
            Path: /
            Method: GET

Example 3: More compact syntax for nested application use case

  # Example nested SAR application that creates a function and outputs the function's name as template output variable NestedFunctionName
  NestedApp:
    Type: AWS::Serverless::Application
    Properties:
      Location:
        ApplicationId: <app id>
        SemanticVersion: 1.0.0
      Events:
        NestedFunctionName: # This tells SAM to use !GetAtt NestedApp.Outputs.NestedFunctionName whenever we need the function name
          - Type: SQS
            Properties:
              Queue: !GetAtt MyQueue.Arn
              BatchSize: 10
          - Type: Api
            Properties:
              Path: /
              Method: GET

Example 4: Attaching events to function whose name is exported by a different stack

  # Assumes other stack exports function name as ExportedFunctionName
  ImportValueExample:
    Type: AWS::Serverless::FunctionReference
    Properties:
      FunctionName: !ImportValue ExportedFunctionName
      Events: 
        SQSTrigger:
          Type: SQS
          Properties:
            Queue: !GetAtt MyQueue.Arn
            BatchSize: 10

Notes/Questions:

  1. Does SAM need both name and ARN specified or is one or the other sufficient? Might be event-specific... I know API events + implicit swagger require the function name and not ARN and AWS::Lambda::Permission can take name, ARN or alias ARN so it might be safer to require both? Alternatively, we could try to parse the ARN for the function name, but that's error-prone and also the ARN could be an intrinsic function dict and not the actual value itself.
    1. Decided to go with just FunctionName and construct the ARN assuming the function is in the same account.
  2. Implementation needs to support Conditions.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions