39

I already have my lambda / roles defined in cloudformation and would love to also use it to add a scheduled eventsources ... are there any docs or examples around ?

7 Answers 7

43

Use Aws::Event::Rule with a ScheduleExpression and a AWS::Lambda::Permission

// rule to periodically call the lambda
"TagWatcherRule": {
  "Type": "AWS::Events::Rule",
  "Properties": {
    "ScheduleExpression": "rate(10 minutes)",
    "Targets": [
      {
        "Id": "TagWatcherScheduler",
        "Arn": {
          "Fn::GetAtt": [
            "TagWatcherFunction",
            "Arn"
          ]
        }
      }
    ]
  }
},
// role may call the lambda
"InvokeLambdaPermission": {
  "Type": "AWS::Lambda::Permission",
  "Properties": {
    "FunctionName": {
      "Fn::GetAtt": [
        "TagWatcherFunction",
        "Arn"
      ]
    },
    "Action": "lambda:InvokeFunction",
    "Principal": "events.amazonaws.com",
    "SourceArn": {
      "Fn::GetAtt": [
        "TagWatcherRule",
        "Arn"
      ]
    }
  }
}
6
  • 1
    According to the docs, ScheduleExpression needs to be plural minutes not minute. docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/… Apr 24, 2016 at 0:43
  • @timmah.faase Not true? "Valid values: minute | minutes | hour | hours | day | days"
    – dsvensson
    Dec 20, 2016 at 15:06
  • 12
    You're allowed singular on "1", e.g. "1 minute", but must use plural otherwise, e.g. "10 minutes". Grammar is enforced!
    – helloPiers
    Dec 31, 2016 at 21:09
  • 1
    I wish I could upvote this a bunch of times. I'm certain you just saved me hours of my life. Jun 5, 2018 at 20:10
  • How can we pass custom input to lambda function through event rule?
    – nff
    Mar 8, 2019 at 9:54
11

I solved same problem.

"RoleForLambdaStopEC2Instances" : {
  "Type": "AWS::IAM::Role",
  "Properties": {
    "AssumeRolePolicyDocument": {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "",
          "Effect": "Allow",
          "Principal": {
            "Service": "lambda.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    },
    "Policies": [
      {
        "PolicyName": "LambdaStopEC2InstancesPolicy",
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "ec2:StopInstances"
              ],
              "Resource": [
                "arn:aws:logs:*:*:*",
                "arn:aws:ec2:*"
              ]
            }
          ]
        }
      }
    ],
    "Path": "/"
  }
},
"LambdaStopEC2Instances": {
  "Type": "AWS::Lambda::Function",
  "Properties": {
    "Code": {
      "S3Bucket": "XXXXXXXXXXXXXXXXX",
      "S3Key": "XXXXXXXXXXXXXXXXXX"
    },
    "Handler": "stopEC2Instances.handler",
    "Role": { "Fn::GetAtt" : ["RoleForLambdaStopEC2Instances", "Arn"] },
    "Runtime": "nodejs4.3",
    "Timeout": "5"
  }
},
"StopEC2InstancesRule": {
  "Type" : "AWS::Events::Rule",
  "Properties" : {
    "Name" : "StopEC2Instances",
    "ScheduleExpression" : "cron(0 13 ? * MON-FRI *)",
    "State": "ENABLED",
    "Targets": [{
      "Arn": { "Fn::GetAtt": ["LambdaStopEC2Instances", "Arn"] },
      "Id": "stopEC2Instances"
    }]
  }
},
"LambdaInvokePermission": {
  "Type": "AWS::Lambda::Permission",
  "Properties": {
    "FunctionName" : { "Fn::GetAtt" : ["LambdaStopEC2Instances", "Arn"] },
    "Action": "lambda:InvokeFunction",
    "Principal": "events.amazonaws.com",
    "SourceAccount": { "Ref" : "AWS::AccountId" },
    "SourceArn": { "Fn::GetAtt": ["StopEC2InstancesRule","Arn"] }
  }
}
2
  • In LambdaInvokePermission the SourceAccount property stopped it running for me
    – jhanson
    Jan 26, 2017 at 15:33
  • same as @jhanson, I had to remove the SourceArn line in LambdaInvokePermission Jul 23, 2020 at 12:38
10

The YAML Version

ScheduledRule: 
  Type: AWS::Events::Rule
  Properties: 
    Description: "ScheduledRule"
    ScheduleExpression: "rate(10 minutes)"
    State: "ENABLED"
    Targets: 
      - 
        Arn: 
          Fn::GetAtt: 
            - "LambdaFunction"
            - "Arn"
        Id: "TargetFunctionV1"
PermissionForEventsToInvokeLambda: 
  Type: AWS::Lambda::Permission
  Properties: 
    FunctionName: 
      Ref: "LambdaFunction"
    Action: "lambda:InvokeFunction"
    Principal: "events.amazonaws.com"
    SourceArn: 
      Fn::GetAtt: 
        - "ScheduledRule"
        - "Arn"
9

Unfortunately, configuring scheduled event sources for lambda functions is currently not supported by CloudFormation. You will need to deploy your lambda using CloudFormation and then manually configure your scheduled events.

CloudFormation does support an AWS::Lambda::EventSourceMapping resource type. However, this resource is limited configuring Kinesis or DynamoDB streams, so this is likely not helpful to you.

http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html


**Update - as of April 2016, this is now supported using CloudWatch Events - https://aws.amazon.com/about-aws/whats-new/2016/04/amazon-cloudwatch-events-now-supported-in-aws-cloudformation-templates/

4

As of this week (18 April 2016) it is now possible to add a scheduled CloudWatch event rule that will trigger your Lambda function.

The AWS::Event::Rule has a ScheduleExpression field for the cron-style schedule and a Targets array which can accept a Lambda function ARN.

1

AWS supports periodic run through sourcedetails.

 EventSource: "aws.config"
 MaximumExecutionFrequency: Twelve_Hours
 MessageType: "ScheduledNotification"
1

If you use function name as

"FunctionName": {
      "Fn::GetAtt": [
        "TagWatcherFunction",
        "Arn"
      ]
    }

and you not specify the function then it'll throw you "Template is not valid: Template error: instance of Fn::GetAtt references undefined resource TagWatcherFunction"

So instead of function name you can directly specify the "lambda ARN". you can see example below

"TagWatcherRule": {
  "Type": "AWS::Events::Rule",
  "Properties": {
    "ScheduleExpression": "rate(10 minutes)",
    "Targets": [
      {
        "Id": "TagWatcherScheduler",
        "Arn": {
          "Fn::GetAtt": [
            "TagWatcherFunction",
            "Arn"
          ]
        }
      }
    ]
  }
},
// role may call the lambda
"InvokeLambdaPermission": {
  "Type": "AWS::Lambda::Permission",
  "Properties": {
    "FunctionName": "arn:aws:lambda:<region>:<awsid>:function:<lambd name>",
    "Action": "lambda:InvokeFunction",
    "Principal": "events.amazonaws.com",
    "SourceArn": {
      "Fn::GetAtt": [
        "TagWatcherRule",
        "Arn"
      ]
    }
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.