我正试图使用terraform部署一个lambda函数,代码是用python编写的。这是执行操作的地形代码。
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行摘录的count.index
部分被下划线作为相关的子表达式。(
有人能帮我吗?
这里的问题似乎是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
通过名称引用函数,并且名称是直接在配置中指定的,因此在数据资源配置中似乎没有一个自然值会产生这种效果。
然而,我们可以通过引入类型为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
})
}
上面一个不幸的部分是,它需要向调用的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中中断。