簡體   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