Referring to function resource from custom resources

I see that Serverless appends LambdaFunction to the names of function resources when it creates the Cloudformation template. When I refer to these functions in the custom resources section of my serverless.yml I have been doing the same:

functions:
  sendEmail: # I want to refer to this resource later
    ...
resources:
  Resources:
    EmailerSchedule:
      Type: AWS::Events::Rule
      Properties:
        Targets:
          - Arn:
              Fn:Get:Att: 
                - sendEmailLambdaFunction # I have to append `LambdaFunction` to the name specified under `functions`
                - Arn
    EmailerPermission:
      Type: AWS::Lambda::Permission
      Properties:
        FunctionName:
          Ref: sendEmailLambdaFunction # I have to append `LambdaFunction` to the name specified under `functions`

Is there a better way to do this, that doesn’t require implicit knowledge about how Serverless compiles the yaml file?

Update: I see in the documentation that this is a standard pattern, so presumably it will always be safe to hard-code the function name with LambdaFunction appended. I would still be interested to know whether there is another way to get the same string, such as through a variable.

5 Likes

You’re doing it the right way.

The only improvement to this system (i.e. having a standardised naming convention) would be to add helper functions (probably as part of the variables system?) to convert serverless.yml references to CFN Logical IDs, but I doubt it’s worth the extra complexity at this stage.

Note to future readers that if your function name key contains ‘-’, you would have to replace them by Dash.

For instance: hello-world -> HelloDashworldLambdaFunction`. (note the leading capitalized letter)

This is not working for me. I’m getting the following error:

The CloudFormation template is invalid: Template error: instance of Fn::GetAtt references undefined resource createAuthChallengeLambdaFunction

Here’s my custom resource:

# resources/cognito-user-pool.yml
Resources:
  CognitoUserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      LambdaConfig:
        CreateAuthChallenge:
          !GetAtt createAuthChallengeLambdaFunction.Arn

Could it be that this custom resource definition is in a separate yml file that is loaded into serverless.yml?

# serverless.yml
functions:
  createAuthChallenge:
    handler: createAuthChallenge.handler

resources:
  - ${file(resources/cognito-user-pool.yml)}

From peeking into .serverless/serverless-state.json I think perhaps my function reference name should be:

${self:service}-${self:provider.stage}-myFunctionNameLambdaFunction

Will try this and report back.

Figured it out. The function name is capitalized, so createAuthChallenge becomes CreateAuthChallengeLambdaFunction

6 Likes

Same problem here. Your solution works for me. Thanx

@disbelief I literally just signed up to thank you, your solution worked :smiley: