特定のプロパティを持つオブジェクトを検索した後、他のプロパティを更新しようとします。次の入力が与えられた場合:
[
{
"replacements": [
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.abc.image.tag"
},
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.def.image.tag"
},
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.ghi.image.tag"
}
],
"yamlFilePath": "k8s/helm/Dev/us-east-1/values.yaml"
}
]
そして、プレースホルダ(abc-image-tag
for k8s-helm-templates.deployment.containers.abc.image.tag
)を次のように使用します。
[
{"name":"abc-image-tag","value":"123"},
{"name":"def-image-tag","value":"456"}
]
あなたが得る必要があるのは、与えられた値が正しく置き換えられ、ゼロ値が次のようにフィルタリングされることです。
[
{
"replacements": [
{
"newValue": "123",
"yamlPath": "k8s-helm-templates.deployment.containers.abc.image.tag"
},
{
"newValue": "456",
"yamlPath": "k8s-helm-templates.deployment.containers.def.image.tag"
}
],
"yamlFilePath": "k8s/helm/Dev/us-east-1/values.yaml"
}
]
いくつかのトリックを試して文書を調べましたが、うまく動作しないようです。 jqで可能ですか?他の手順を実行するには、bashを使用してください。
答え1
この試み:
jq \
--null-input \
--rawfile replacements replacements.json \
--rawfile placeholders placeholders.json \
'
def placeholder_index: .name | gsub("-"; ".") ;
def replacement_index: .yamlPath | sub("^k8s-helm-templates\\.deployment\\.containers\\."; "") ;
def replace($placeholders):
[
JOIN(INDEX(.[]; replacement_index); $placeholders[]; placeholder_index) |
{newvalue: .[0].value, yamlPath: .[1].yamlPath}
]
;
$replacements | fromjson as $replacements |
$placeholders | fromjson as $placeholders |
$replacements | .[0].replacements |= replace($placeholders)
'
この目標を達成するために、私が作成したプロトタイプを示すことでこれを説明できます。
各入力がファイルにあるとします。
cat > replacements.json <<"EOF"
[
{
"replacements": [
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.abc.image.tag"
},
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.def.image.tag"
},
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.ghi.image.tag"
}
],
"yamlFilePath": "k8s/helm/Dev/us-east-1/values.yaml"
}
]
EOF
cat > placeholders.json <<"EOF"
[
{"name":"abc-image-tag","value":"123"},
{"name":"def-image-tag","value":"456"}
]
EOF
最初の秘密は、各入力のハンドルを取得することです。入力が1つしかない場合、通常は標準入力からそれを読み込み、.
パイプの先頭で参照します。複数の入力がある場合は、--rawfile
各JSONテキストを名前付き変数にロードするために使用できます。明らかな「デフォルト」入力がない場合は、--null-input
jqを使用して標準入力から読み取ることができません。
--rawfile
文字列を読み取るので、それを使用してfromjson
JSONオブジェクトを解析する必要があります。を使用してJSONオブジェクトの配列を読み取ることもできますが、--slurpfile
最初の要素を選択する必要があるため、それでも追加の手順です。
jq \
--null-input \
--rawfile replacements replacements.json \
--rawfile placeholders placeholders.json \
'
$replacements | fromjson as $replacements |
$placeholders | fromjson as $placeholders |
$replacements, $placeholders
'
必要な結果は、2つのSQLデータベーステーブル間の内部結合のように見えます。 jqには、同様のことを行うことができる「SQLスタイル演算子」があるので、こう言うのです。文書化がうまくいかなかったので、ここで試行錯誤を経て調べました。
INDEX
入力ストリームの各オブジェクトをキーにマッピングし、両方のインデックスJOIN
に対して内部結合を実行するオブジェクトを作成するために使用されます。
インデックスは$replacements
こんな感じです。ここのキー式は共通のプレフィックスを削除し、yamlPath
変更可能なイメージタグを残します。
jq \
--null-input \
--rawfile replacements replacements.json \
--rawfile placeholders placeholders.json \
'
$replacements | fromjson as $replacements |
$placeholders | fromjson as $placeholders |
INDEX(
$replacements[0].replacements[];
.yamlPath | sub("^k8s-helm-templates\\.deployment\\.containers\\."; "")
)
'
{
"abc.image.tag": {
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.abc.image.tag"
},
"def.image.tag": {
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.def.image.tag"
},
"ghi.image.tag": {
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.ghi.image.tag"
}
}
インデックスは$placeholders
こんな感じです。キー式は、可変イメージラベルがラベルのように見えるようにダッシュをドットに置き換えます$replacements
。
jq \
--null-input \
--rawfile replacements replacements.json \
--rawfile placeholders placeholders.json \
'
$replacements | fromjson as $replacements |
$placeholders | fromjson as $placeholders |
INDEX($placeholders[]; .name | gsub("-"; "."))
'
{
"abc.image.tag": {
"name": "abc-image-tag",
"value": "123"
},
"def.image.tag": {
"name": "def-image-tag",
"value": "456"
}
}
2つのインデックスオブジェクトの一部のキーが一致することがわかります。これが私たちがJOIN
これらのオブジェクトの内部接続を実行する機能を取得する方法です。
実際、この関数はとにかく2番目のインデックスを効果的に生成するので、一度だけINDEX
呼び出すだけです。JOIN
JOIN
最初のオブジェクトはストリーム入力から取得され、2 番目のオブジェクトはインデックス入力から取得されるペアリストのストリームを返します。
jq \
--null-input \
--rawfile replacements replacements.json \
--rawfile placeholders placeholders.json \
'
$replacements | fromjson as $replacements |
$placeholders | fromjson as $placeholders |
JOIN(
INDEX(
$replacements[0].replacements[];
.yamlPath | sub("^k8s-helm-templates\\.deployment\\.containers\\."; "")
);
$placeholders[];
.name | gsub("-"; ".")
)
'
[
{
"name": "abc-image-tag",
"value": "123"
},
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.abc.image.tag"
}
]
[
{
"name": "def-image-tag",
"value": "456"
},
{
"newValue": "0",
"yamlPath": "k8s-helm-templates.deployment.containers.def.image.tag"
}
]
次のステップは、関連付けられた各オブジェクトの正しいプロパティを「選択」して新しいオブジェクトを作成し、出力を配列にラップする新しいオブジェクトを作成することJOIN
です。
jq \
--null-input \
--rawfile replacements replacements.json \
--rawfile placeholders placeholders.json \
'
$replacements | fromjson as $replacements |
$placeholders | fromjson as $placeholders |
[
JOIN(
INDEX(
$replacements[0].replacements[];
.yamlPath | sub("^k8s-helm-templates\\.deployment\\.containers\\."; "")
);
$placeholders[];
.name | gsub("-"; ".")
) |
{newvalue: .[0].value, yamlPath: .[1].yamlPath}
]
'
[
{
"newvalue": "123",
"yamlPath": "k8s-helm-templates.deployment.containers.abc.image.tag"
},
{
"newvalue": "456",
"yamlPath": "k8s-helm-templates.deployment.containers.def.image.tag"
}
]
最終的な解決策では、各式の名前を指定するいくつかの関数を定義しました。更新割り当て演算子を使用して|=
元の構造をコピーし$replacements
、結合の結果として内部リストを更新します。