Ansibleで複数行を追加する(blockinfile)

lineinfile

Ansibleでファイルに行を追記したり置換したりした場合、lineinfileを使うことが多いと思いますが、複数行追加したい場合だと、ちょっとやりずらいところがあります。

下記のように書くと、テキスト内に指定した行の内容がなければ末尾に追加されるので、それを繰り返すことによって末尾に複数行入れられます。

  tasks:
    - name: 末尾に複数行追加
      lineinfile:
        dest=./test.txt
        line={{ item }}
      with_items:
        - '1行目'
        - '2行目'

これが特定の箇所に入れようとすると面倒になります。
たとえば、insertafterを使って指定した行の後に入れようとして、下記のように書くと、、

  tasks:
    - name: 特定の場所に追加
      lineinfile:
        dest=./test.txt
        insertafter='^# xxxx'
        line={{ item }}
      with_items:
        - '1行目'
        - '2行目'

順番が逆に並ぶことになります。

# xxxxx
2行目
1行目

これは、insertafterにマッチした箇所の後に追加するといったことを単に2回繰り返しているためなので、

# xxxxx
1行目
# xxxxx
2行目
1行目

といった形で入っていくためです。

blockinfile

そもそもlineinfileは複数行を扱うのに向いていないので、複数行を扱えるモジュールのblockinfileを使うと良さそうです。

blockinfileは、extraモジュールに現在はあるように見える(GitHubのリポジトリには存在する)のですが、Ansibleのバージョンが古いとextraにいないので、その場合には ansible-galaxy でインストールします。(1.9.4 では入ってませんでした)

ansible-galaxy install yaegashi.blockinfile

blockinfileを使うと、contentに指定した内容をそのまま入れることができます。(rolesにansible-galaxyでインストールしたblockinfileのロールを指定する必要があります)

- hosts: all
  roles:
    - yaegashi.blockinfile
  tasks:
    - name: 特定の場所に追加
      blockinfile:
        dest: ./test.txt
        insertafter: '^# xxxx'
        content: |
          1行目
          2行目

内容の前後にmarkerで指定した内容が入ります。デフォルトだと下記のような感じです。

# xxxxx
# BEGIN ANSIBLE MANAGED BLOCK
1行目
2行目
# END ANSIBLE MANAGED BLOCK

markerの範囲を一つの内容として扱うので、中身を書き換えるのも結構楽です。 たとえば、先ほどのテキスト内容から、下記を実行すると、

tasks:
  - name: 特定の場所に追加
    blockinfile:
      dest: ./test.txt
      insertafter: '^# xxxx'
      content: |
        #1行目
        2行目

markerの範囲のものを置き換えてくれます。

# xxxxx
# BEGIN ANSIBLE MANAGED BLOCK
#1行目
2行目
# END ANSIBLE MANAGED BLOCK

後から追加した行の内容が変わる可能性があるならば、1行だったとしても、blockinfileを使った方がメンテナンスしやすいだろうなぁと思いました。