创建主题规则不会在 lambda 上创建触发器
Creating the topic rule does not create the trigger on the lambda
这个问题看起来很像一个错误,但我相信我的 terraform 文件中一定有问题,因为我在网上找不到任何人遇到同样的问题。
这是我的 terraform 文件的一部分,它为它创建了一个 lambda 和一个主题规则:
resource "aws_lambda_function" "rds_persist" {
filename = "${local.rds_persist_file_path}"
function_name = "RdsPersist-${var.env}"
role = "${aws_iam_role.lambda_role.arn}"
handler = "package.handler"
source_code_hash = "${local.rds_persist_package_hash}"
runtime = "nodejs8.10"
memory_size = 128
timeout = 10
vpc_config = {
subnet_ids = ["${var.private_subnet_ids}"]
security_group_ids = ["${aws_security_group.all_vpc_access.id}"]
}
environment {
variables = {
DB = "${var.database_url}"
IOT_DEVICE_ARN = "${var.iot_device_v1_sns_arn}"
}
}
}
resource "aws_iot_topic_rule" "rds_push" {
name = "${var.env}_RdsPush"
description = "Pushes events to a persistence lambda (rds store)"
enabled = true
sql = "SELECT * as payload, topic() as topic, timestamp() AS timestamp FROM '#' WHERE startswith(clientid(), '${var.env}-')"
sql_version = "2016-03-23"
lambda {
function_arn = "${aws_lambda_function.rds_persist.arn}"
}
}
这是 AWS 控制台中的结果:
如果我在控制台中删除并重新添加规则,则触发器会出现在 lambda 上。
It might be the case your lambda function that your topic uses is being created before the function.
我还通过单独污染主题规则对其进行了测试,以便重新创建它(请参阅下面的日志)。不幸的是,它没有解决问题。
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
-/+ module.lambda.aws_iot_topic_rule.rds_push (tainted) (new resource required)
id: "dev_RdsPush" => <computed> (forces new resource)
arn: "arn:aws:iot:eu-west-1:827689093226:rule/dev_RdsPush" => <computed>
description: "Pushes events to a persistence lambda (rds store)" => "Pushes events to a persistence lambda (rds store)"
enabled: "true" => "true"
lambda.#: "1" => "1"
lambda.1860721139.function_arn: "arn:aws:lambda:eu-west-1:827689093226:function:RdsPersist-dev" => "arn:aws:lambda:eu-west-1:827689093226:function:RdsPersist-dev"
name: "dev_RdsPush" => "dev_RdsPush"
sql: "SELECT * as payload, topic() as topic, timestamp() AS timestamp FROM '#' WHERE startswith(clientid(), 'dev-')" => "SELECT * as payload, topic() as topic, timestamp() AS timestamp FROM '#' WHERE startswith(clientid(), 'dev-')"
sql_version: "2016-03-23" => "2016-03-23"
Plan: 1 to add, 0 to change, 1 to destroy.
更新:我刚刚在另一个地方发现了一个非常相似的问题:
另一个 lambda 和 SNS 之间应该有一个 SNS 订阅。这是地形中的相关代码:
resource "aws_sns_topic_subscription" "conference_call" {
topic_arn = "${module.sns.conference_call_arn}"
protocol = "lambda"
endpoint = "${module.lambda.messaging_arn}"
}
(显然我检查了资源,它们是正确的)
在控制台中,我没有在 lambda 中看到触发器,但我在 SNS 中看到了订阅:
更新:使用 AWS CLI 创建资源时出现完全相同的问题
# For the first issue
$ aws iot create-topic-rule --rule-name dev_RdsPush --topic-rule-payload '{"sql":"SELECT * as payload, topic() as topic, timestamp() AS timestamp FROM \'#\' WHERE startswith(clientid(), \'dev-\')","actions":[{"lambda":{"functionArn":"arn:aws:lambda:eu-west-1:xxxxxxxxx:function:RdsPersist-dev"}}]}'
# For the second issue
$ aws sns subscribe --topic-arn arn:aws:sns:eu-west-1:xxxxxxxx:conference-call-v1-dev --protocol lambda --notification-endpoint arn:aws:lambda:eu-west-1:xxxxxxxxx:function:Messaging-dev
解法:
添加这些:
物联网:
resource "aws_lambda_permission" "conference_call_sns" {
statement_id = "AllowExecutionFromSNS"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.conference_call.function_name}"
principal = "sns.amazonaws.com"
source_arn = "${var.conference_call_sns_arn}"
}
社交网络:
resource "aws_lambda_permission" "messaging_sns" {
statement_id = "AllowExecutionFromSNS"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.messaging.function_name}"
principal = "sns.amazonaws.com"
source_arn = "${var.conference_call_sns_arn}"
}
您的主题使用的 lambda 函数可能是在该函数之前创建的。尝试在您的 aws_iot_topic_rule
上添加 depends_on = ["aws_lambda_function.rds_persist"]
,看看效果如何。
您需要添加 lambda 权限以允许 IoT 调用 lambda。 Lambda 控制台使用函数的权限来显示可以调用它的对象。
https://docs.aws.amazon.com/iot/latest/developerguide/iot-rule-actions.html#lambda-rule.
在我的例子中,这是缺少的权限:
resource "aws_lambda_permission" "rds_topic_rule_permission" {
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.rds_persist.function_name
principal = "iot.amazonaws.com"
source_arn = aws_iot_topic_rule.rds_push.arn
}
参见:https://github.com/hashicorp/terraform-provider-aws/issues/24196#issuecomment-1103979956
这个问题看起来很像一个错误,但我相信我的 terraform 文件中一定有问题,因为我在网上找不到任何人遇到同样的问题。
这是我的 terraform 文件的一部分,它为它创建了一个 lambda 和一个主题规则:
resource "aws_lambda_function" "rds_persist" {
filename = "${local.rds_persist_file_path}"
function_name = "RdsPersist-${var.env}"
role = "${aws_iam_role.lambda_role.arn}"
handler = "package.handler"
source_code_hash = "${local.rds_persist_package_hash}"
runtime = "nodejs8.10"
memory_size = 128
timeout = 10
vpc_config = {
subnet_ids = ["${var.private_subnet_ids}"]
security_group_ids = ["${aws_security_group.all_vpc_access.id}"]
}
environment {
variables = {
DB = "${var.database_url}"
IOT_DEVICE_ARN = "${var.iot_device_v1_sns_arn}"
}
}
}
resource "aws_iot_topic_rule" "rds_push" {
name = "${var.env}_RdsPush"
description = "Pushes events to a persistence lambda (rds store)"
enabled = true
sql = "SELECT * as payload, topic() as topic, timestamp() AS timestamp FROM '#' WHERE startswith(clientid(), '${var.env}-')"
sql_version = "2016-03-23"
lambda {
function_arn = "${aws_lambda_function.rds_persist.arn}"
}
}
这是 AWS 控制台中的结果:
如果我在控制台中删除并重新添加规则,则触发器会出现在 lambda 上。
It might be the case your lambda function that your topic uses is being created before the function.
我还通过单独污染主题规则对其进行了测试,以便重新创建它(请参阅下面的日志)。不幸的是,它没有解决问题。
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
-/+ module.lambda.aws_iot_topic_rule.rds_push (tainted) (new resource required)
id: "dev_RdsPush" => <computed> (forces new resource)
arn: "arn:aws:iot:eu-west-1:827689093226:rule/dev_RdsPush" => <computed>
description: "Pushes events to a persistence lambda (rds store)" => "Pushes events to a persistence lambda (rds store)"
enabled: "true" => "true"
lambda.#: "1" => "1"
lambda.1860721139.function_arn: "arn:aws:lambda:eu-west-1:827689093226:function:RdsPersist-dev" => "arn:aws:lambda:eu-west-1:827689093226:function:RdsPersist-dev"
name: "dev_RdsPush" => "dev_RdsPush"
sql: "SELECT * as payload, topic() as topic, timestamp() AS timestamp FROM '#' WHERE startswith(clientid(), 'dev-')" => "SELECT * as payload, topic() as topic, timestamp() AS timestamp FROM '#' WHERE startswith(clientid(), 'dev-')"
sql_version: "2016-03-23" => "2016-03-23"
Plan: 1 to add, 0 to change, 1 to destroy.
更新:我刚刚在另一个地方发现了一个非常相似的问题:
另一个 lambda 和 SNS 之间应该有一个 SNS 订阅。这是地形中的相关代码:
resource "aws_sns_topic_subscription" "conference_call" {
topic_arn = "${module.sns.conference_call_arn}"
protocol = "lambda"
endpoint = "${module.lambda.messaging_arn}"
}
(显然我检查了资源,它们是正确的)
在控制台中,我没有在 lambda 中看到触发器,但我在 SNS 中看到了订阅:
更新:使用 AWS CLI 创建资源时出现完全相同的问题
# For the first issue
$ aws iot create-topic-rule --rule-name dev_RdsPush --topic-rule-payload '{"sql":"SELECT * as payload, topic() as topic, timestamp() AS timestamp FROM \'#\' WHERE startswith(clientid(), \'dev-\')","actions":[{"lambda":{"functionArn":"arn:aws:lambda:eu-west-1:xxxxxxxxx:function:RdsPersist-dev"}}]}'
# For the second issue
$ aws sns subscribe --topic-arn arn:aws:sns:eu-west-1:xxxxxxxx:conference-call-v1-dev --protocol lambda --notification-endpoint arn:aws:lambda:eu-west-1:xxxxxxxxx:function:Messaging-dev
解法:
添加这些:
物联网:
resource "aws_lambda_permission" "conference_call_sns" {
statement_id = "AllowExecutionFromSNS"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.conference_call.function_name}"
principal = "sns.amazonaws.com"
source_arn = "${var.conference_call_sns_arn}"
}
社交网络:
resource "aws_lambda_permission" "messaging_sns" {
statement_id = "AllowExecutionFromSNS"
action = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.messaging.function_name}"
principal = "sns.amazonaws.com"
source_arn = "${var.conference_call_sns_arn}"
}
您的主题使用的 lambda 函数可能是在该函数之前创建的。尝试在您的 aws_iot_topic_rule
上添加 depends_on = ["aws_lambda_function.rds_persist"]
,看看效果如何。
您需要添加 lambda 权限以允许 IoT 调用 lambda。 Lambda 控制台使用函数的权限来显示可以调用它的对象。
https://docs.aws.amazon.com/iot/latest/developerguide/iot-rule-actions.html#lambda-rule.
在我的例子中,这是缺少的权限:
resource "aws_lambda_permission" "rds_topic_rule_permission" {
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.rds_persist.function_name
principal = "iot.amazonaws.com"
source_arn = aws_iot_topic_rule.rds_push.arn
}
参见:https://github.com/hashicorp/terraform-provider-aws/issues/24196#issuecomment-1103979956