我如何为 terraform 中的每个预定事件使用相同的 cloudwatch 日志和相同的 sns 目标?

How can i use same cloudwatch logs and same sns target for each scheduled events in terraform?

我有 2 个事件:

在event-bridge/events/event1/main.tf

module "event1" {
  source              = "../../rule"
  name                = "event1"
  description         = "event1"
  schedule_expression = "cron(0 4 * * ? *)"
  input               = jsonencode({"job-type": "event1"})
  cloudwatch_arn      = module.targets.cloudwatch_arn
}

module "targets" {
  source = "../../targets"
}

在event-bridge/events/event2/main.tf

module "event2" {
  source              = "../../rule"
  name                = "event2"
  description         = "event2"
  schedule_expression = "cron(0 5 * * ? *)"
  input               = jsonencode({"job-type": "event2"})
  cloudwatch_arn      = module.targets.cloudwatch_arn
}

module "targets" {
  source = "../../targets"
}

在 event-bridge/targets/main.tf

resource "aws_cloudwatch_log_group" "log_group_target" {
  name = "/aws/events/${local.rule_name}"
}

resource "aws_sns_topic" "sns_target" {
  name = local.rule_name
}

resource "aws_sns_topic_policy" "sns-target-policy" {
  arn    = aws_sns_topic.sns_target.arn
  policy = data.aws_iam_policy_document.events_to_sns_topic_policy.json
}

data "aws_iam_policy_document" "events_to_sns_topic_policy" {
  statement {
    effect  = "Allow"
    actions = ["SNS:Publish"]

    principals {
      type        = "Service"
      identifiers = ["events.amazonaws.com"]
    }

    resources = [aws_sns_topic.sns_target.arn]
  }
}

在event-bridge/targets/variables.tf

locals {
  rule_name = "scheduled-events"
}

在event-bridge/targets/output.tf

output "cloudwatch_arn" {
  value = aws_cloudwatch_log_group.log_group_target.arn
}

output "sns_topic_arn" {
  value = aws_sns_topic.sns_target.arn
}

在event-bridge/rule/main.tf

resource "aws_cloudwatch_event_rule" "rule" {
  name                = var.name
  description         = var.description
  schedule_expression = var.schedule_expression
}

resource "aws_cloudwatch_event_target" "cloud_watch_target" {
  rule  = local.rule_name
  arn   = var.cloudwatch_arn
}

resource "aws_cloudwatch_event_target" "sns_target" {
  rule      = local.rule_name
  arn       = var.sns_arn
  input     = var.input
}

在event-bridge/rule/variables.tf

locals {
  rule_name = "scheduled-events"
}

variable "name" {
  description = "A name of the event bridge rule to be created"
  type        = string
}

variable "description" {
  description = "A description of the event bridge rule to be created"
  type        = string
}

variable "input" {
  description = "A message for the events to be processed by this rule"
  type        = any
}

variable "schedule_expression" {
  description = "A scheduled time interval for the events to be processed"
  type        = any
}

variable "cloudwatch_arn" {
  description = "Logging cloudwatch arn for the events to be processed"
  type        = any
}

如果我 plan 像这样为每个事件创建另一个 cloudwatch 日志组和 sns 目标,并且在应用时由于同名而出现错误,但我希望他们使用相同的 cloudwatch 日志组和 sns 目标..你知道我如何实现吗?非常感谢!!

一种资源只能在该州的一个地址进行管理。您正在创建目标模块的两个实例:module.event1.module.targetsmodule.event2.module.targets.

如果您想在两个事件模块中使用在一个目标模块中创建的相同值,则必须将模块输出作为变量传入,或者使用事件模块中的数据源来引用目标。在这两种情况下,只创建一个目标模块。


应要求,我正在扩展答案以进行澄清。

考虑以下目录结构。

  • 规则/
    • main.tf
    • variables.tf
  • 目标/
    • main.tf
    • outputs.tf
    • variables.tf
  • ./main.tf

这里的 main.tf 根是状态的提供者。这是文件的内容,虽然我还没有测试过。

rule/main.tf

resource "aws_cloudwatch_event_rule" "rule" {
  name                = var.name
  description         = var.description
  schedule_expression = var.schedule_expression
}

resource "aws_cloudwatch_event_target" "cloud_watch_target" {
  rule = aws_cloudwatch_event_rule.rule.name
  arn  = var.cloudwatch_arn
}

resource "aws_cloudwatch_event_target" "sns_target" {
  rule  = aws_cloudwatch_event_rule.rule.name
  arn   = var.sns_topic_arn
  input = var.input
}

rule/variables.tf

variable "name" {
  description = "A name of the event bridge rule to be created"
  type        = string
}

variable "description" {
  description = "A description of the event bridge rule to be created"
  type        = string
}

variable "input" {
  description = "A message for the events to be processed by this rule"
  type        = any
}

variable "schedule_expression" {
  description = "A scheduled time interval for the events to be processed"
  type        = string
}

variable "cloudwatch_arn" {
  description = "Logging cloudwatch arn for the events to be processed"
  type        = string
}

variable "sns_topic_arn" {
  type = string
}

targets/main.tf

resource "aws_cloudwatch_log_group" "log_group_target" {
  name = "/aws/events/${local.rule_name}"
}

resource "aws_sns_topic" "sns_target" {
  name = local.rule_name
}

resource "aws_sns_topic_policy" "sns-target-policy" {
  arn    = aws_sns_topic.sns_target.arn
  policy = data.aws_iam_policy_document.events_to_sns_topic_policy.json
}

data "aws_iam_policy_document" "events_to_sns_topic_policy" {
  statement {
    effect  = "Allow"
    actions = ["SNS:Publish"]

    principals {
      type        = "Service"
      identifiers = ["events.amazonaws.com"]
    }

    resources = [aws_sns_topic.sns_target.arn]
  }
}

targets/outputs.tf

output "cloudwatch_arn" {
  value = aws_cloudwatch_log_group.log_group_target.arn
}

output "sns_topic_arn" {
  value = aws_sns_topic.sns_target.arn
}

targets/variables.tf

locals {
  rule_name = "scheduled-events"
}

主顶层main.tf

module "targets" {
  source = "./targets"
}

module "event1" {
  source = "./rule"

  name                = "event1"
  description         = "event1"
  schedule_expression = "cron(0 4 * * ? *)"
  input               = jsonencode({ "job-type" : "event1" })
  cloudwatch_arn      = module.targets.cloudwatch_arn
  sns_topic_arn       = module.targets.sns_topic_arn
}

module "event2" {
  source = "./rule"

  name                = "event2"
  description         = "event2"
  schedule_expression = "cron(0 5 * * ? *)"
  input               = jsonencode({ "job-type" : "event2" })
  cloudwatch_arn      = module.targets.cloudwatch_arn
  sns_topic_arn       = module.targets.sns_topic_arn
}