给定的键不标识此集合值中的元素:terraform

Bis*_*ana 1 python terraform terraform-provider-aws

我正在尝试使用 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
  ..
  ..
  ..
  #
}
Run Code Online (Sandbox Code Playgroud)

在部署期间,我还尝试使用aws_lambda_inspiration调用 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
}
Run Code Online (Sandbox Code Playgroud)

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

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.
Run Code Online (Sandbox Code Playgroud)

count.index第 124 行代码片段的部分带有下划线,作为相关子表达式。)

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

Mar*_*ins 5

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

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

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

首先,我建议更改countfor 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)

  # ...
}
Run Code Online (Sandbox Code Playgroud)

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

但是,我们可以通过引入额外的中间资源类型null_resource(属于提供hashicorp/null)来强制执行此操作,该资源保证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
  })
}
Run Code Online (Sandbox Code Playgroud)

上面的一个不幸的部分是,它需要在input调用中添加一个无用的额外参数,因为我们需要在该配置中的某个位置包含未知的 ID 值。上述内容将使得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 的未来版本中不应中断。