単一ファイルにある複数YAMLドキュメントのうち、1つをyqで抽出する
概要
kustomize build
の出力など、単一ファイルに複数のYAMLドキュメントが記述されていることがあります。そのYAMLドキュメントの1つを抽出したい場合、yq
を利用できます。
以下のexample.yaml
を例として、コマンドと実行結果を紹介します。
foo: bar
---
hoge: fuga
$ yq '(select(documentIndex == 0) | .)' example.yaml
foo: bar
$ yq '(select(documentIndex == 1) | .)' example.yaml
hoge: fuga
環境
筆者は macOS Monterey 12.6.1(Apple M1)を使用しています。
yq
のバージョンはこちらです。
$ yq --version
yq (https://github.com/mikefarah/yq/) version v4.30.5
目的
@hhiroshellさんに語り尽くされていました。
KustomizeのHash Suffixがあってもいい感じにdiffが見られるkubectlプラグインを作った話
筆者はkubectl
を素のまま使わない環境を利用しています。kubectl diff
相当のコマンドを利用できない、また、kubectl pluginで解決できないため、別のアプローチを取りました[1]。
まず、変更前のマニフェストを適用します。
kubectl apply -f before/app.yaml
ConfigMapGeneratorに指定する値を編集し、kustomize build
します。ここでは、サンプルリポジトリのわかりやすさを考慮し、ファイル一式をbefore
とafter
ディレクトリに配置しています。
after/app.yaml
を適用する前に、差分を確認します。
diff -upN <(kubectl apply -f after/app.yaml view-last-applied) after/app.yaml
出力結果は以下のとおりです。1行目はstderrに出力されます。
ConfigMapの名前が変更されており、期待した結果を得られません。
Error from server (NotFound): configmaps "example-configmap-1-286h7kfc5k" not found
--- /dev/fd/11 2022-12-10 12:13:10.000000000 +0900
+++ after/app.yaml 2022-12-10 11:51:08.000000000 +0900
@@ -0,0 +1,27 @@
+apiVersion: v1
+data:
+ FOO: baz
+kind: ConfigMap
+metadata:
+ annotations:
+ app: example
+ name: example-configmap-1-286h7kfc5k
+ namespace: default
+---
+apiVersion: v1
+kind: Pod
+metadata:
+ annotations:
+ app: example
+ name: example
+ namespace: default
+spec:
+ containers:
+ - env:
+ - name: FOO
+ valueFrom:
+ configMapKeyRef:
+ key: FOO
+ name: example-configmap-1-286h7kfc5k
+ image: nginx
+ name: nginx
解決策として1つずつ比較することを思いつきました。ここで、概要で紹介したコマンドを利用します。
Podの差分を確認する
diff -upN \
<(kubectl get pod example -o yaml | yq '.metadata.annotations.["kubectl.kubernetes.io/last-applied-configuration"]' | jq | yq -P .) \
<(yq '(select(documentIndex == 1) | .)' after/app.yaml)
--- /dev/fd/11 2022-12-10 12:04:25.000000000 +0900
+++ /dev/fd/14 2022-12-10 12:04:25.000000000 +0900
@@ -12,6 +12,6 @@ spec:
valueFrom:
configMapKeyRef:
key: FOO
- name: example-configmap-1-59m54fbgh2
+ name: example-configmap-1-286h7kfc5k
image: nginx
name: nginx
ConfigMapの差分を確認する
CONFIGMAP=$(kubectl get pod example -o jsonpath='{.spec.containers[?(@.name=="nginx")].env[0].valueFrom.configMapKeyRef.name}')
diff -upN \
<(kubectl get cm $CONFIGMAP -o yaml | yq '.metadata.annotations.["kubectl.kubernetes.io/last-applied-configuration"]' | jq | yq -P .) \
<(yq '(select(documentIndex == 0) | .)' after/app.yaml)
--- /dev/fd/11 2022-12-10 12:10:14.000000000 +0900
+++ /dev/fd/14 2022-12-10 12:10:14.000000000 +0900
@@ -1,9 +1,9 @@
apiVersion: v1
data:
- FOO: bar
+ FOO: baz
kind: ConfigMap
metadata:
annotations:
app: example
- name: example-configmap-1-59m54fbgh2
+ name: example-configmap-1-286h7kfc5k
namespace: default
おわりに
yq
を利用してkustomize build
の出力から得たい情報を抽出できました。考案したdiff
コマンドは柔軟性に欠けますが、私のユースケースでは十分なものとなりました。
参考
本記事で紹介したコマンドは、こちらのIssueに記載されています。
-
正確には、紹介したアプローチを試した後で@hhiroshellさんの発表、プラグインを知りました。 ↩︎
Discussion