【问题标题】:给定的键未标识此集合值中的元素:terraform
【发布时间】:2022-01-23 16:40:27
【问题描述】:

我正在尝试使用 terraform 部署 lambda 函数,代码是用 python 编写的。这是执行该操作的 terraform 代码。

data archive_file UpdateSeqNumInLedgerSummary {
  count       = (var.environment_id == var.prd_environment) ? 1 : 0
  ..
  ..
  ..
  #
}

resource aws_lambda_function update_seqnum_in_indexedledgersummary {
  count            = (var.environment_id == var.prd_environment) ? 1 : 0
  ..
  ..
  ..
  #
}

在部署期间,我还尝试使用 aws_lambda_invocation 调用 lambda 函数。这就是我正在做的事情

data aws_lambda_invocation update_seqnum_invocation {
  count         = (var.environment_id == var.prd_environment) ? 1 : 0
  function_name = aws_lambda_function.update_seqnum_in_indexedledgersummary[count.index].function_name
  input = <<JSON
  {}
  JSON
}

但在部署期间我收到以下错误

Error: Invalid index

  on seqnum-update.tf line 124, in data "aws_lambda_invocation" "update_seqnum_invocation":
 124:   function_name = aws_lambda_function.update_seqnum_in_indexedledgersummary[count.index].function_name
    |----------------
    | aws_lambda_function.update_seqnum_in_indexedledgersummary is empty tuple
    | count.index is 0

The given key does not identify an element in this collection value.

(第 124 行 sn-p 的 count.index 部分带有下划线作为相关子表达式。)

有人可以帮我解决这个问题吗?

【问题讨论】:

  • var.environment_idvar.prd_environment 的值是什么?
  • 请从输出中去除颜色代码,否则难以理解。在运行诸如 plan 或 apply 之类的 terraform 命令时,您可以使用-no-color 参数。 doc
  • @MarkoE 都是“prd3”

标签: python terraform terraform-provider-aws


【解决方案1】:

这里的问题似乎是,Terraform 无法从您描述这些关系的方式推断出 data.aws_lambda_invocation.update_seqnum_invocation 数据资源必须在对 aws_lambda_function.update_seqnum_in_indexedledgersummary 进行更改后才能读取。

您似乎使用的是旧版本的 Terraform,并且某些旧版本的 Terraform 对数据资源和托管资源之间的关系的依赖关系推断不太精确,这可能会导致这样的问题。因此,升级到最新版本的 Terraform 可能会使这项工作更加可靠,因为现代 Terraform 包含一个附加规则,即当数据资源引用托管资源并且对托管资源进行计划更改时,因此不得读取数据资源直到应用步骤。

要在较旧的 Terraform 版本中获得这种效果,您可以向 Terraform 提供更多信息,以便它更好地理解您的意图。

首先,我建议将count 更改为data.aws_lambda_invocation.update_seqnum_invocation,以便它从aws_lambda_function.update_seqnum_in_indexedledgersummary 的计数派生而来,因此Terraform 可以清楚地看到这两个计数必须始终一起更改:

data "aws_lambda_invocation" "update_seqnum_invocation" {
  count = length(aws_lambda_function.update_seqnum_in_indexedledgersummary)

  # ...
}

另一个更改有点困难,因为它涉及到找到某种方法来使数据资源的配置包含(known after apply) 值,只要相应的函数还不存在。然后,Terraform 将使用它作为数据资源读取必须等到应用步骤的信号。但是,由于这些资源类型的设计,其中aws_lambda_invocation 通过其名称引用函数并且名称直接在您的配置中指定,似乎没有包含 natural 值在会产生这种效果的数据资源配置中。

但是,我们可以通过引入额外的 null_resource 类型的中间资源(属于 the hashicorp/null provider)来强制执行此操作,保证在等待创建时产生未知的 id 值:

resource "null_resource" "example" {
  count = length(aws_lambda_function.update_seqnum_in_indexedledgersummary)
}

data "aws_lambda_invocation" "update_seqnum_invocation" {
  count = length(aws_lambda_function.update_seqnum_in_indexedledgersummary)

  # ...
  input = jsonencode({
    irrelevant = null_resource.example.id
  })
}

不幸的是,它需要在调用的input 中添加一个无用的额外参数,因为我们需要在该配置中包含未知的 ID 值somewhere。以上将使input成为(known after apply),因此仅在应用步骤期间强制读取data.aws_lambda_invocation.update_seqnum_invocation数据资源。


上面我重点介绍了如何使这些部分协同工作的细节,但我还想指出,您在这里所做的有点滥用 aws_lambda_invocation 数据资源,这是为什么这么尴尬:

与 Terraform 中的所有数据源一样,data "aws_lambda_invocation" 旨在收集数据以在您的配置中的其他地方使用,而不是描述要对您的基础架构进行的更改。因此,它通常应与在当前 Terraform 配置之外定义的函数一起使用,该函数提供当前 Terraform 配置所需的一些数据。

虽然可以让 Terraform 在应用步骤期间读取数据资源,从而获得数据资源更改基础设施的效果,但这种方法本质上是脆弱的,并且容易被破坏提供者随着 Terraform Core 本身的发展而发展,因为在这两种情况下,目标通常是在规划阶段收集尽可能多的数据,因此它被认为是一种改进,以便能够在期间读取更多数据源计划阶段而不是应用阶段。

此函数的确切作用不在您的问题范围内,因此我无法提出具体的替代方案,但 Terraform 的一般期望是基础设施的所有 更改 都将被表示通过resource 块而不是data 块,因此如果您需要修改某些内容作为应用此配置的一个步骤,最好找到一个现有的托管资源类型(使用resource 块),它可以采取该行动,或开发提供您所需资源类型的自定义 Terraform 提供程序。这将按照其设计方式使用 Terraform,因此不应在未来版本的提供程序或 Terraform Core 中中断。

【讨论】:

  • 通过如上所述更改 lambda 调用中的计数,它开始工作。谢谢
猜你喜欢
  • 2022-07-12
  • 2021-05-15
  • 2021-08-20
  • 2021-08-25
  • 2021-08-26
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多