Terraform: Cloudwatch Event trigger Lambda doesn't associate unless we do a manual update to cloudwatch event.

Created on 10 May 2017  ·  16Comments  ·  Source: hashicorp/terraform

Hi there,

Terraform Launches all the required resources as expected. But the Event trigger is not being associated with the lambda function. Had to update the cloudwatch event manually from the console to add it as a trigger to lambda and to invoke.

Terraform Version

Terraform v0.9.4

Affected Resource(s)

AWS Lambda
AWS Cloudwatch Event rule/target

Expected Behavior

Under lambda function triggers tab you should see the "CloudWatch Events - Schedule:*" and should be invoked by the Cloudwatch event as per the Schedule expression.

Actual Behavior

What actually happened?

Terraform Launches all the required resources as expected. But the Event trigger is not being associated with the lambda function. Had to update the cloudwatch event manually from the console to add it as a trigger to lambda and to invoke.

Steps to Reproduce

We can reproduce by running below resources by providing some meaningful zip to the function.

resource "aws_lambda_function" "waf_spam_list" {
filename = "lambda.zip"
function_name = "waf_spam_list"
role = "arn:aws:iam::xxxxxxxxxxxx:role/xxxxxxxxxxxxx"
handler = "index.handler"
source_code_hash = "${base64sha256(file("lambda.zip"))}"
runtime = "nodejs4.3"
timeout = "59"
}

resource "aws_cloudwatch_event_rule" "waf-spam-update" {
name = "waf-spam-update"
depends_on = ["aws_lambda_function.waf_spam_list"]
schedule_expression = "rate(1 minute)"
}

resource "aws_cloudwatch_event_target" "waf-spam-target" {
target_id = "waf-spam-target"
rule = "${aws_cloudwatch_event_rule.waf-spam-update.name}"
arn = "${aws_lambda_function.waf_spam_list.arn}"
input = < { some json input }
INPUT
}

bug provideaws

Most helpful comment

I was having the same problem and ultimately here is the code that worked for me in its entirety (minus the iam_role and iam_role_policy):

NOTE: I added target_id and depends_on and that was what worked for me. Not sure which of those I needed. Haven't gone through a process of elimination to see which one is necessary and I'm a novice at terraform so can't say without further experimentation.

data "archive_file" "function" {
  type = "zip"
  source_file = "${path.module}/index.js"
  output_path = "${path.module}/function.zip"
}

resource "aws_lambda_function" "demo_lambda" {
  function_name = "demo_lambda"
  handler = "index.handler"
  runtime = "nodejs6.10"
  filename = "function.zip"
  source_code_hash = "${base64sha256(file("function.zip"))}"
  role = "${aws_iam_role.lambda_exec_role.arn}"
}

resource "aws_cloudwatch_event_rule" "demo_lambda_every_one_minute" {
  name = "demo_lambda_every_one_minute"
  // Worked for me after I added `depends_on`
  depends_on = [
    "aws_lambda_function.demo_lambda"
  ]
  schedule_expression = "rate(1 minute)"
}

resource "aws_cloudwatch_event_target" "demo_lambda" {
  target_id = "demo_lambda" // Worked for me after I added `target_id`
  rule = "${aws_cloudwatch_event_rule.demo_lambda_every_one_minute.name}"
  arn = "${aws_lambda_function.demo_lambda.arn}"
}

resource "aws_lambda_permission" "demo_lambda_every_one_minute" {
  statement_id = "AllowExecutionFromCloudWatch"
  action = "lambda:InvokeFunction"
  function_name = "${aws_lambda_function.demo_lambda.function_name}"
  principal = "events.amazonaws.com"
  source_arn = "${aws_cloudwatch_event_rule.demo_lambda_every_one_minute.arn}"
}

CC: https://github.com/terraform-providers/terraform-provider-aws/issues/756

All 16 comments

I'm experiencing this issue also. Tried 0.9.5 with same result.

I have successfully set up a WAF with rules updated in a Lambda function and triggered by CloudWatch, very similar to the above example.

Have you added an aws_lambda_permission resource to allow CloudWatch to trigger the Lambda function? See https://www.terraform.io/docs/providers/aws/r/lambda_permission.html

resource "aws_lambda_permission" "waf-spam-update" {
  statement_id = "waf-spam-update"
  action = "lambda:InvokeFunction"
  function_name = "${aws_lambda_function.waf_spam_list.function_name}"
  principal = "events.amazonaws.com"
  source_arn = "${aws_cloudwatch_event_rule.waf-spam-update.arn}"
}

Yes - even with lambda permission it makes no difference.

On Tue 6 Jun 2017 at 22:49, Dave Long notifications@github.com wrote:

I have successfully set up a WAF with rules updated in a Lambda function
and triggered by CloudWatch, very similar to the above example.

Have you added an aws_lambda_permission resource to allow CloudWatch to
trigger the Lambda function? See
https://www.terraform.io/docs/providers/aws/r/lambda_permission.html

resource "aws_lambda_permission" "waf-spam-update" {
statement_id = "waf-spam-update"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.waf_spam_list.function_name}"
principal = "events.amazonaws.com"
source_arn = "${aws_cloudwatch_event_rule.waf-spam-update.arn}"
}


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/hashicorp/terraform/issues/14342#issuecomment-306627574,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AJunpC7kTVIxoz7ZSdI-HzOJd-fdbvo9ks5sBcligaJpZM4NWLA_
.

@byrneo I disagree, the workaround suggested by @longwave worked for me

I am facing the same issue, terraform is giving "created successful" but it is not reflecting actually on aws console. @sandyfox did it work for you?

There is one more strange thing, as the permission didn't reflect through terraform, then I applied the different permission manually through aws console and then tried to execute the terraform state again. Ideally it should show change but terraform gave "No changes" output. It clearly signifies that permissions are not being managed by terraform appropriately.

@SanchitBansal I didn't get a chance to test it later since my job accomplished by the manual change for now ;) . I will let you know if there is any progress from my end.

Note: please make sure the "source_arn" is defined, use count/similar if you need multiple.
It didn't work for me without being defined, even though it's optional; beware!

@jlsjonas yes I even tried with "source_arn" parameter but no luck.

I was having the same problem and ultimately here is the code that worked for me in its entirety (minus the iam_role and iam_role_policy):

NOTE: I added target_id and depends_on and that was what worked for me. Not sure which of those I needed. Haven't gone through a process of elimination to see which one is necessary and I'm a novice at terraform so can't say without further experimentation.

data "archive_file" "function" {
  type = "zip"
  source_file = "${path.module}/index.js"
  output_path = "${path.module}/function.zip"
}

resource "aws_lambda_function" "demo_lambda" {
  function_name = "demo_lambda"
  handler = "index.handler"
  runtime = "nodejs6.10"
  filename = "function.zip"
  source_code_hash = "${base64sha256(file("function.zip"))}"
  role = "${aws_iam_role.lambda_exec_role.arn}"
}

resource "aws_cloudwatch_event_rule" "demo_lambda_every_one_minute" {
  name = "demo_lambda_every_one_minute"
  // Worked for me after I added `depends_on`
  depends_on = [
    "aws_lambda_function.demo_lambda"
  ]
  schedule_expression = "rate(1 minute)"
}

resource "aws_cloudwatch_event_target" "demo_lambda" {
  target_id = "demo_lambda" // Worked for me after I added `target_id`
  rule = "${aws_cloudwatch_event_rule.demo_lambda_every_one_minute.name}"
  arn = "${aws_lambda_function.demo_lambda.arn}"
}

resource "aws_lambda_permission" "demo_lambda_every_one_minute" {
  statement_id = "AllowExecutionFromCloudWatch"
  action = "lambda:InvokeFunction"
  function_name = "${aws_lambda_function.demo_lambda.function_name}"
  principal = "events.amazonaws.com"
  source_arn = "${aws_cloudwatch_event_rule.demo_lambda_every_one_minute.arn}"
}

CC: https://github.com/terraform-providers/terraform-provider-aws/issues/756

resource "aws_lambda_permission" "demo_lambda_every_one_minute" {
  statement_id = "AllowExecutionFromCloudWatch"
  action = "lambda:InvokeFunction"
  function_name = "${aws_lambda_function.demo_lambda.function_name}"
  principal = "events.amazonaws.com"
  source_arn = "${aws_cloudwatch_event_rule.demo_lambda_every_one_minute.arn}"
}

this part does the trick. I dont need additions on aws_cloudwatch_event_rule and aws_cloudwatch_event_target

Worked as @snasirca, although I didnt have to include the depends_on and target_id.
Basically target_id is automatically computed if not provided. But if you provide it, it shouldnt be longer than 64 characters, else it throws an error.

@exNewbie Thanks, this is what I was missing!

@jlsjonas How to use the similar grammar with terraform you Mentioned?

Worked when I put target_id in aws_cloudwatch_event_target with the same value from name in aws_cloudwatch_event_rule. When Terraform put the random value in target_id this don't work.

I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

Was this page helpful?
0 / 5 - 0 ratings