はじめに
Ansibleのtemplateモジュールでとあるディレクトリ配下に存在する条件に一致する複数のj2ファイルをターゲットのサーバに末尾の".j2"を取り除いたファイル名で展開したいという場面がありました。
templateモジュールでのループの方法や正規表現の記載方法など備忘録的な意味も込めて記事を作成。
条件
ディレクトリ構成は下記の通りです。
roles
└── test
├── tasks
│ └── main.yml
│
├── templates
│ └── test
│ └──2021
│ ├── test1.conf.j2
│ ├── test2.conf.j2
│ ├── test3.conf.j2
│ └── sample.conf.j2
│
├── vars
| └── main.yml
│
今回はtemplates/test/2021/配下のファイル名に"test"がつくj2ファイルのみをtemplateモジュールで/tmp/test/配下に展開します。
展開する際のファイル名は".j2"を取り除いたものとします。
(test1.conf.j2であればtest1.conf)
また、srcに指定するtemplates配下のパス(test/2021/)は変数src_path
として定義されていることとします。
---
src_path: test/2021/
templateモジュールで複数ファイルを対象にループ
templateモジュールで複数ファイルをループしたい場合はwith_fileglob
を使用すればできます。
with_fileglobはワイルドカードを使用してファイルを指定できるため、特定の条件に一致するファイルのみをループしたい場合にも使えます。
Playbookは下記の通りです。
Playbook
---
- name: Set test vars
include_vars: ../vars/main.yml
- name: template test
template:
src: "{{ item }}"
dest: "/tmp/test/{{ item | regex_replace('.j2$','') }}"
with_fileglob:
- "../templates/{{ src_path }}test*.j2"
このPlaybookを実行したところ問題点がありました・・・。
問題点
with_fileglobはフルパスが戻り値となるため、上記のPlaybookのように末尾の".j2"を取り除くだけでは不完全でした。
解決策
解決策としてregex_replaceに末尾の"j2"をだけでなく余計なパスを取り除き、ファイル名のみを抽出する正規表現を記述します。
destには下記を記載しました。
dest: "/tmp/test/{{ item | regex_replace('^.*test/2021/(.*).j2$','\\1') }}"
正規表現についてはこちらを参考にしてください。
destを上記に修正しPlaybookを実行したところ上手くいきました。
regex_replaceで変数を使用
destのregex_replace内にtest/2021/を直打ちする場合は上記で大丈夫なのですが、今回は変数src_pathを使用してマッチさせる必要がありました。
変数を使用したい場合は変数部分を下記のように+変数+
の形で記載します。
dest: "/tmp/test/{{ item | regex_replace('^.*' + src_path + '(.*).j2$','\\1') }}"
最初はitemのように単純にsampla_pathと記載したり、{{ }}でくくったみたりしたのですがうまく行かず、意外とここに苦戦しました・・・。
最後に
とても単純な処理内容ですが、正規表現やregex_replace内で変数を使ってマッチさせる際の記述方法などとても勉強になりました。