繁体   English   中英

Terraform - /usr/local/bin/jq:参数列表太长

[英]Terraform - /usr/local/bin/jq: Argument list too long

这是之前提出的问题的变体。

我在 Terraform 中使用外部数据源来请求它提供 AWS Dublin 中的卷快照列表,并在模板文件中使用 JQ 来提取快照 ID。

data "external" "volsnapshot_ids" {

  program    = [

    "bash",

    "-c",

    templatefile("cli.tftpl", {input_string = "aws ec2 describe-snapshots --region=eu-west-1", top = "Snapshots", next = "| .SnapshotId"})]

}

它使用这个模板文件:

#!/bin/bash

set -e

OUTPUT=$(${input_string} | jq  -r -c '.${top}[] ${next}' | jq -R -s -c 'split("\n")' | jq '.[:-1]')

jq -n -c --arg output "$OUTPUT" '{"output":$output}'

JQ 的基本 CLI 命令可以正常工作,如下所示:

aws ec2 describe-snapshots --region=eu-west-1 | jq  -r -c '.Snapshots[] | .SnapshotId' | jq -R -s -c 'split("\n")' | jq '.[:-1]' | wc -l

它返回很多快照 ID。

但是,当我通过 Terraform 运行它时,它会出错:

Error: External Program Execution Failed

│ 

│   with data.external.volsnapshot_ids,

│   on data.tf line 304, in data "external" "volsnapshot_ids":

│  304:   program    = [

│  305:     "bash",

│  306:     "-c", 

│  307:     templatefile("cli.tftpl", {input_string = "aws ec2 describe-snapshots --region=eu-west-1", top = "Snapshots", next = "| .SnapshotId"})]

│ 

│ The data source received an unexpected error while attempting to execute

│ the program.

│ 

│ Program: /bin/bash

│ Error Message: bash: line 6: /usr/local/bin/jq: Argument list too long

│ 

│ State: exit status 1

我认为这是返回的数据集的大小,因为它适用于快照 ID 较少的地区——伦敦适用。

从规模上看,这里是伦敦:

aws ec2 describe-snapshots --region=eu-west-2 | jq  -r -c '.Snapshots[] | .SnapshotId' | jq -R -s -c 'split("\n")' | jq '.[:-1]' | wc -l
20000

这里是都柏林:

aws ec2 describe-snapshots --region=eu-west-1 | jq  -r -c '.Snapshots[] | .SnapshotId' | jq -R -s -c 'split("\n")' | jq '.[:-1]' | wc -l
42500

有没有办法修复我的模板文件中的 JQ,以便它可以处理 JSON 大文件?

我不建议在 TF 数据源中使用命令。 可能很难调试。 EBS 快照有一个data_source

至于模板中的命令,为了调试它,您需要模拟相同的环境。 例如,不要按原样运行,而是尝试重复模板中的内容,例如bash -c等。 也可以加output查看渲染出来的模板,看看有没有问题。

滚动到答案底部。

不要提供值作为参数,而是通过直接标准输入:
 aws... \ | jq -rc '.${top}[] ${next}' \ | jq -Rsc './"\n"' \ | jq -c '.[:-1]' | jq -Rc '{output:.}'

请注意,您可能可以将大部分单独的 jq 调用组合到一个 jq 程序中。


这个jq调用管道是一个非常非常复杂的非解决方案。 为什么在字符串和 JSON 对象之间来回转换,再次解析这些字符串,而 jq 已经可以直接处理数据了?

{"output":"[\"snap-cafebabe\",\"snap-deadbeef\",\"snap-0123abcd\"]"}

示例 output:

top=Snapshots
next=SnapshotId
aws ... | jq --arg top "$top" --arg next "$next" -c '{ output: .[$top] | map(.[$next]) | tostring }'

如果必须使用变量:

 top=Snapshots next=SnapshotId aws... | jq --arg top "$top" --arg next "$next" -c '{ output: .[$top] | map(.[$next]) | tostring }'

.[$top] | map(.[$next]) | tostring | { output: . } .[$top] | map(.[$next]) | tostring | { output: . } .[$top] | map(.[$next]) | tostring | { output: . }.[$top] | map(.[$next]) | { output: tostring } .[$top] | map(.[$next]) | { output: tostring } .[$top] | map(.[$next]) | { output: tostring }

即使您想要或需要将多个jq调用串在一起,如果您已经以 stream 形式完美地构造了 JSON 项,那么使用原始输入 ( -R ) 并尝试解析它也没有什么意义。

如果您想通过多个步骤完成它,但始终停留在 JSON 区域(而不是在结构化文本 881569990078588 和非结构化文本之间打乒乓球),这就是它的样子:

top=Snapshots
next=SnapshotId
aws ... \
  | jq --arg top "$top" --arg next "$next" '.[$top] | map(.[$next])' \
  | jq -c '{ output: tostring }'

或等效的:

 top=Snapshots next=SnapshotId aws... \ | jq --arg top "$top" --arg next "$next" '.[$top] | map(.[$next])' \ | jq -c '{ output: tostring }'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM