1
votes

I am having some trouble writing the cloudformation script for cloudwatch event trigger to kick off my lambda script, I know I can do it through the console but my requirement is that I need to provision everything in cloudformation. I followed the documentation and it still haven't worked for me and I kept getting the error:

Template contains errors.: Invalid template property or properties [rPermissionForEventsToInvokeLambda, rLambdaScheduledRule]

can someone point out what is the issue with this part of my cloudformation script? I followed the document almost to the letter and still having error, even the example in the documentation have the same error when I tried to validate it. my cloudformation code is below, any help is appreciated!

rLambdaScheduledRule:
  Type: AWS::Events::Rule
  Properties:
    ScheduleExpression: rate(1 hour)
    State: ENABLED
    Targets:
      Ref: 
        Fn::ImportValue:
          Fn::Sub: rUploadLambda
    Action: lambda:InvokeFunction
rPermissionForEventsToInvokeLambda: 
  Type: AWS::Lambda::Permission
  Properties: 
    FunctionName: 
      Ref: 
        Fn::ImportValue:
        Fn::Sub: rUploadLambda
    Action: lambda:InvokeFunction
    Principal: events.amazonaws.com
    SourceArn: 
      Fn::GetAtt: 
        - rLambdaScheduledRule
        - Arn
1
Is this your complete cloudformation template? Since it is complaining about rLambdaScheduledRule and rPermissionForEventsToInvokeLambda, maybe they are not put under 'Resources' ? Just a guess...niekname

1 Answers

3
votes

1) You must export the Lambda function ARN in the CloudFormation template in which you create the lambda function. You need to pass the Lambda function ARN as input to the cloudwatch event (The AWS::Events::Rule Targets attribute requires a resource ARN).

See a sample script below:

Resources:
  # Create Controlled Lambda Function
  myLambda:
    Type: "AWS::Lambda::Function"
    Properties: 
      Code:
        S3Bucket: "lambda-bucket"
        S3Key: "myhandler.zip"
      Description: "Lambda handler"
      FunctionName: "myhandler"
      Handler: myhandler.myhandler
      MemorySize: 128
      Role: "arn:aws:iam::xxxxxxxxxxx:role/myLambdaExecutionRole-NC7FA7TUSZ5B"
      Runtime: "python3.6"
      Timeout: 10

# Output of the cf template
Outputs:
  myLambdaArn:
    Description: Arn of the my_lambda_function
    Value: !GetAtt myLambda.Arn
    Export: 
      Name: !Sub "${AWS::StackName}-LambdaArn"

2) When you create the CloudWatch Event, you need to pass the ARN of the lambda function created in Step1 as the Target.

See a sample script below:

Resources:
  # Cloudwatch event to trigger lambda periodically
  rLambdaScheduledRule:
    Type: "AWS::Events::Rule"
    Properties: 
      Description: "CloudWatch Event to trigger lambda fn"
      ScheduleExpression: "rate(1 hour)"
      State: "ENABLED"
      Targets:
        - 
          Arn: 
            Fn::ImportValue:
              !Sub "${NetworkStackName}-LambdaArn"
          Id: "targetevent_v1"

  PermissionForEventsToInvokeLambda: 
    Type: "AWS::Lambda::Permission"
    Properties: 
      FunctionName: 
        Fn::ImportValue:
          !Sub "${NetworkStackName}-LambdaArn"
      Action: "lambda:InvokeFunction"
      Principal: "events.amazonaws.com"
      SourceArn: 
        Fn::GetAtt: 
          - rLambdaScheduledRule
          - Arn

The value of ${NetworkStackName} should be the StackName from Step1. Some of the issues you need to correct in your template:

  • correct the Targets property of resource rLambdaScheduledRule.
  • remove Action property from resource rLambdaScheduledRule.
  • correct the FunctionName property of resource rPermissionForEventsToInvokeLambda.

Keeping above sample as reference, correct your template and try again.