この投稿はAnsible 3 Advent Calendar 2019の1日目の記事です。
一先ず空いていたので、古い日付から思いついたフィルター芸を投稿していってみようと思います。
特定の条件にマッチしたファイルの一覧から保存されているディレクトリパスを抜き出したい時があったりなかったりあったりします。
その時の簡単なフィルターです。
ディレクトリ構成
こんな感じでtxtファイルが保存されています。
(venv) [root@localhost ansible]# tree tmp/
tmp/
├── dirA
│ └── testA.txt
├── dirB
│ └── testB.txt
├── dirC
│ └── dirD
│ └── testC.txt
└── testD.txt
このtxtファイルが保存されているディレクトリ情報を抜き出してみたいと思います。
Playbook
Playbookはこんな感じです。
---
- name: iti no kata playbook
hosts: localhost
gather_facts: no
tasks:
- name: find files
find:
paths: tmp/
recurse: yes
register: find_result
- debug:
msg: >-
{{ item.path.split('/') | difference(data) | join('/') }}
vars:
data: >-
{{ [-1]
| map('extract', item.path.split('/'))
| map('regex_search', '^.*txt$')
| list
}}
loop: "{{ find_result.files }}"
loop_control:
label: "{{ item.path }}"
when:
- item.mode == "0644"
findで tmp
ディレクトリ配下のファイル情報を取得して loop
で結果を回します。
ここでは、条件としてファイルのパーミッションが 0644
になっていているものが対象で、マッチしたものは data
変数の処理に移ります。
data
では path
キーの値を /
でsplitして正規表現でマッチしたものをリスト化して最後の要素を抜き出し data
変数に格納します。
最後に path
を /
でsplitした者に対して difference
フィルターを使って data
情報とマッチしている値を削除し /
でjoinしています。
これを実行してみます。
playbook実行
(venv) [root@localhost ansible]# ansible-playbook main.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [iti no kata playbook] *****************************************************************************************************************************************
TASK [find files] ***************************************************************************************************************************************************
ok: [localhost]
TASK [debug] ********************************************************************************************************************************************************
ok: [localhost] => (item=tmp/testD.txt) => {
"msg": "tmp"
}
ok: [localhost] => (item=tmp/dirA/testA.txt) => {
"msg": "tmp/dirA"
}
ok: [localhost] => (item=tmp/dirB/testB.txt) => {
"msg": "tmp/dirB"
}
ok: [localhost] => (item=tmp/dirC/dirD/testC.txt) => {
"msg": "tmp/dirC/dirD"
}
PLAY RECAP **********************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
各ファイルが保存されているディレクトリがmsgで表示されました :)