首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用引用其他资源的for_each定义资源块

如何使用引用其他资源的for_each定义资源块
EN

Stack Overflow用户
提问于 2022-10-11 23:18:41
回答 2查看 23关注 0票数 0

我在陆地上创造了很少的资源-

代码语言:javascript
复制
resource "aws_dms_replication_instance" "foobar_instance_1" {

}

resource "aws_dms_replication_instance" "foobar_instance_2" {

}

resource "aws_dms_endpoint" "foobar_source_1" {

}

resource "aws_dms_endpoint" "foobar_source_2" {

}

然后定义一个依赖于上述两种资源的复制任务-

代码语言:javascript
复制
resource "aws_dms_replication_task" "foobar_task_1" {

replication_instance_arn = aws_dms_replication_instance.foobar_instance_1.replication_instance_arn
source_endpoint_arn       = aws_dms_endpoint.foobar_source_1.endpoint_arn
.
.
.
}

我想使用tf变量来使用for_each自动化类似的for_each创建。我在variables.tf中创建了一个映射变量,如下所示-

代码语言:javascript
复制
variable "task_map" {
  type        = map(object({
    source_endpoint     = string
    repl_instance     = string
  }))
  default = {
    "dms_attr_map" = {
      source_ep     = "foobar_source_1"
      repl_instance = "foobar_instance_1"
    },
    "dms_attr_map2" = {
      source_ep     = "foobar_source_2"
      repl_instance = "foobar_instance_2"
    }

  }
}

现在,我继续创建一个资源块,在task_map上循环并创建replication_task

代码语言:javascript
复制
resource "aws_dms_replication_task" "for_each_task_1" {
    for_each                  = var.task_map
    replication_instance_arn  =  aws_dms_replication_instance.${each.value["repl_instance"]}.replication_instance_arn
    source_endpoint_arn       = aws_dms_endpoint.${each.value["source_ep"]}.endpoint_arn
    .   
    .
    .
}

在我执行我的计划时,terrraform计划会引发一个错误,即引用replication_instance使用${each.value["repl_instance"]}是错误的。

错误信息-

│错误:./││/cdc/main.tf第236行上的无效字符││:该字符不在│语言中使用。╵

╷│错误:./│/cdc/main.tf第233行上的无效属性名││:在│点之后需要一个属性名。╵

错误消息指向我使用for_each引用replication_instance和source_endpoint的特定行

代码语言:javascript
复制
aws_dms_endpoint.${each.value["source_ep"]}.endpoint_arn
aws_dms_replication_instance.${each.value["repl_instance"]}.replication_instance_arn

如何引用使用for_each使用其名称创建的资源。

谢谢。

EN

回答 2

Stack Overflow用户

发布于 2022-10-11 23:35:45

如何引用使用名称使用for_each创建的资源。

你不能这么做。换句话说,您不能以以下形式创建对资源的动态引用:

代码语言:javascript
复制
aws_dms_endpoint.${each.value["source_ep"]}.endpoint_arn

相反,您必须使用映射或列表来创建aws_dms_replication_instanceaws_dms_endpoint。例如:

代码语言:javascript
复制
resource "aws_dms_replication_instance" "foobar_instance" {
  for_each = toset(["foobar_instance_1", "foobar_instance_2"])
}

resource "aws_dms_endpoint" "foobar_source" {
  for_each = toset(["foobar_source_1", "foobar_source_2"])
}

结束时,请参阅以下内容:

代码语言:javascript
复制
resource "aws_dms_replication_task" "for_each_task_1" {
    for_each                  = var.task_map
    replication_instance_arn  = aws_dms_replication_instance.foobar_instance[each.value["repl_instance"]].replication_instance_arn
    source_endpoint_arn       = aws_dms_endpoint.foobar_source[each.value["source_ep"]].endpoint_arn
    .   
    .
    .
}
票数 1
EN

Stack Overflow用户

发布于 2022-10-12 02:08:26

在考虑这样的问题时,重要的是要认识到,像aws_dms_replication_instance.foobar_instance_1这样的引用表达式是一个不可分割的单元:aws_dms_replication_instance本身并不是一个独立的数据结构,您可以动态地查询它,因为Terraform需要能够准确地确定特定表达式所依赖的资源,以便在计算任何表达式之前生成依赖关系图。

但是,您可以构建自己的映射数据结构,其中包含您感兴趣的一组资源:

代码语言:javascript
复制
locals {
  source_endpoints = {
    "foobar_1" = aws_dms_endpoint.foobar_source_1
    "foobar_2" = aws_dms_endpoint.foobar_source_2
  }
  replication_instances = {
    "foobar_1" = aws_dms_replication_instance.foobar_instance_1
    "foobar_2" = aws_dms_replication_instance.foobar_instance_2
  }
}

然后,您可以使用local.source_endpointslocal.replication_instances作为映射来查找模块调用方指定的键:

代码语言:javascript
复制
resource "aws_dms_replication_task" "for_each_task_1" {
  for_each = var.task_map

  replication_instance_arn = local.replication_instances[each.value.repl_instance].replication_instance_arn
  source_endpoint_arn      = local.source_endpoints[each.value.source_ep].endpoint_arn

  # ...
}

这可以工作,因为本地值也是参与依赖关系图的对象。Terraform可以看到local.source_endpoints同时依赖于aws_dms_endpoint.foobar_source_1aws_dms_endpoint.foobar_source_2,因此间接地依赖于local.source_endpoints的任何东西都必须有效地依赖于这些资源。

虽然这对您的问题并不重要,但我想指出的是,这种设计意味着您的模块将声明完整的aws_dms_endpointaws_dms_replication_instance对象集,即使其中有些对象没有引用它们的任何var.task_map元素。

如果模块的唯一实际使用涉及到所有这些内容,我不会担心,但是如果这不是真的,那么这个设计的一个变体就是允许调用者通过输入变量指定他们需要的端点和复制实例,并在所有这三个资源上使用for_each

如果这样做,就可以避免构造中间数据结构,因为for_each资源已经是支持相同类型动态查找的自然映射:

代码语言:javascript
复制
resource "aws_dms_replication_instance" "example" {
  for_each = var.replication_instances

  # ...
}

resource "aws_dms_endpoint" "example" {
  for_each = var.source_endpoints

  # ...
}

resource "aws_dms_replication_task" "for_each_task_1" {
  for_each = var.task_map

  replication_instance_arn = aws_dms_replication_instance.example[each.value.repl_instance].replication_instance_arn
  source_endpoint_arn      = aws_dms_endpoint.example[each.value.source_ep].endpoint_arn

  # ...
}

在此变体中,模块的调用方控制存在哪些复制实例和端点,以及每个任务使用哪一个,因此模块的用户负担更大,但他们也可以灵活地不声明他们不实际使用的对象,以防这些对象的开销很大。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74034959

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档