[英]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.