zaki work log

作業ログやら生活ログやらなんやら

[YAML] 複数行テキストの行頭にインデントを設定するには (Ansible/Kubernetes)

YAMLで複数行のテキストを記述しつつ、その先頭にインデントを設定するにはどうするか。

YAMLの複数行テキスト

---
data:
  sample1-1.txt: |
    this file is sample file.
    curry tabetai!

YAML| を使って、次行から複数行のテキストを書ける。
この場合、sample1-1.txtというキーに対して、以下の2行のテキストが値になる。

this file is sample file.
curry tabetai!

インデント設定

このとき、各行に一律インデントを入れたい場合、YAMLでインデントをこのように増やしても、、

data:
  sample-indent1.txt: |
          this file is sample file.
          curry tabetai!
  #^^^^^ この部分

増やしたインデントはすべてYAMLの構造として解釈されるので、sample-indent1.txtの値はインデントの量にかかわらず、

this file is sample file.
curry tabetai!

となる。

増やしたインデントをYAMLの構造として解釈せずに、文字列値の中のスペースとして認識させるには、、
多分この「8.2.3. Block Nodes」だと思うんだけど、実は書いてあることがよくわからなかった。
プログラマーのための YAML 入門 (初級編)の「複数行の文字列」の章にも少しかかれてるけど、インデント指定のところは詳しい記述がない。

ということで、試してみた結果。

f:id:zaki-hmkc:20210717215212p:plain

|の後に数字を入力することで、キー文字列のインデント位置から何文字のスペースをYAML構造のインデントとして解釈するかを指定できる。
残りのスペースはYAMLのインデントとしては解釈されず、複数行テキスト内のスペース文字列として認識されるようになる。

この内容でConfigMapを作って、

---
apiVersion: v1
data:
  sample-indent2.txt: |4
            this file is sample file.
            curry tabetai!
kind: ConfigMap
metadata:
  name: yaml-multiline-sample

-o jsonで出力すると、この通り、各行先頭に6文字のスペースが入っていることを確認できる。

    "data": {
        "sample-indent2.txt": "      this file is sample file.\n      curry tabetai!\n",
    }

複数行表記で使用する記号の種類と効果

まずは前フリ

---
apiVersion: v1
data:
  sample1-1.txt: |
    this file is sample file.
    curry tabetai!

  sample1-2.txt: |+
    this file is sample file.
    curry tabetai!

  sample1-3.txt: |-
    this file is sample file.
    curry tabetai!

  sample2-1.txt: >
    this file is sample file.
    curry tabetai!

  sample2-2.txt: >+
    this file is sample file.
    curry tabetai!

  sample2-3.txt: >-
    this file is sample file.
    curry tabetai!

kind: ConfigMap
metadata:
  name: yaml-multiline-sample

この内容で定義したConfigMapをファイルとしてマウントすると、参照できるファイルは以下の通り。

|を使ったファイル

root@configmap-app-68f8ddc68f-n4f2k:/var/tmp/configmap# cat sample1-1.txt 
this file is sample file.
curry tabetai!
root@configmap-app-68f8ddc68f-n4f2k:/var/tmp/configmap# cat sample1-2.txt 
this file is sample file.
curry tabetai!

root@configmap-app-68f8ddc68f-n4f2k:/var/tmp/configmap# cat sample1-3.txt 
this file is sample file.
curry tabetai!root@configmap-app-68f8ddc68f-n4f2k:/var/tmp/configmap# 

>を使ったファイル

root@configmap-app-68f8ddc68f-n4f2k:/var/tmp/configmap# cat sample2-1.txt 
this file is sample file. curry tabetai!
root@configmap-app-68f8ddc68f-n4f2k:/var/tmp/configmap# cat sample2-2.txt 
this file is sample file. curry tabetai!

root@configmap-app-68f8ddc68f-n4f2k:/var/tmp/configmap# cat sample2-3.txt 
this file is sample file. curry tabetai!root@configmap-app-68f8ddc68f-n4f2k:/var/tmp/configmap# 
$ kubectl get cm -n sample yaml-multiline-sample -o json
{
    "apiVersion": "v1",
    "data": {
        "sample1-1.txt": "this file is sample file.\ncurry tabetai!\n",
        "sample1-2.txt": "this file is sample file.\ncurry tabetai!\n\n",
        "sample1-3.txt": "this file is sample file.\ncurry tabetai!",
        "sample2-1.txt": "this file is sample file. curry tabetai!\n",
        "sample2-2.txt": "this file is sample file. curry tabetai!\n\n",
        "sample2-3.txt": "this file is sample file. curry tabetai!"
    },
    ...

+を指定した場合は、末尾に余計な改行が入っている。
対して-を指定した場合は、末尾に改行が無い。(そのためプロンプトが同じ行に表示される)

記号まとめ

  • 書き出し
    • |: 記述そのまま。ただし末尾に改行が複数ある場合は1つにまとめられる
    • >: 各行の末尾は改行でなくスペースに変換される
  • オプション
    • +: デフォルトの「末尾の複数改行を1つにする」機能がオフになる (書いたままになる)
    • -: 末尾の改行が削除される

ここも図にした方が分かりやすいと思うけど力尽きた()

インデント量の指定

---
apiVersion: v1
data:
  sample1-1.txt: |2
      this file is sample file.
      curry tabetai!

  sample1-2.txt: |+2
        this file is sample file.
        curry tabetai!

  sample1-3.txt: |-2
          this file is sample file.
          curry tabetai!

  sample2-1.txt: >2
      this file is sample file.
      curry tabetai!

  sample2-2.txt: >+2
        this file is sample file.
        curry tabetai!

  sample2-3.txt: >-2
          this file is sample file.
          curry tabetai!

kind: ConfigMap
metadata:
  name: yaml-multiline-sample

こうすると

    "data": {
        "sample1-1.txt": "  this file is sample file.\n  curry tabetai!\n",
        "sample1-2.txt": "    this file is sample file.\n    curry tabetai!\n\n",
        "sample1-3.txt": "      this file is sample file.\n      curry tabetai!",
        "sample2-1.txt": "  this file is sample file.\n  curry tabetai!\n",
        "sample2-2.txt": "    this file is sample file.\n    curry tabetai!\n\n",
        "sample2-3.txt": "      this file is sample file.\n      curry tabetai!"
    },

>との併用時は、>の機能である改行をスペースに変換する機能がオフになるっぽい?

Ansibleの場合は

---
- hosts: localhost
  gather_facts: false
  vars:
    data:
      sample1-1.txt: |2
          this file is sample file.
          curry tabetai!

      sample1-2.txt: |+2
            this file is sample file.
            curry tabetai!

      sample1-3.txt: |-2
              this file is sample file.
              curry tabetai!

      sample2-1.txt: >2
          this file is sample file.
          curry tabetai!

      sample2-2.txt: >+2
            this file is sample file.
            curry tabetai!

      sample2-3.txt: >-2
              this file is sample file.
              curry tabetai!

  tasks:
    - name: print data
      ansible.builtin.debug:
        msg: "{{ data }}"

このplaybookをJSON形式で出力すると

$ ANSIBLE_STDOUT_CALLBACK=json ansible-playbook yaml-multiline.yml
:
:
    "msg": {
        "sample1-1.txt": "  this file is sample file.\n  curry tabetai!\n",
        "sample1-2.txt": "    this file is sample file.\n    curry tabetai!\n\n",
        "sample1-3.txt": "      this file is sample file.\n      curry tabetai!",
        "sample2-1.txt": "  this file is sample file.\n  curry tabetai!\n",
        "sample2-2.txt": "    this file is sample file.\n    curry tabetai!\n\n",
        "sample2-3.txt": "      this file is sample file.\n      curry tabetai!"
    }

Kubernetes(のConfigMap)の場合と同じ結果になる。