with_itemsとregisterを組み合わせたAnsible playbookで苦労した

趣味と仕事にて、Ansibleを使いこなせるよう勉強中です。今回は、古いログファイルを削除するplaybookを書く際に、気づけたことがあったのでメモします。
古いログファイルを削除するplaybook
playbookで実現したい操作を簡単に書くと、「対象ディレクトリ内にある古いファイルをfindモジュールで発見してregisterしておき、次にwith_itemsのループでファイルを削除すること」となる。サンプルのplaybookは、ウェブ検索で大量に見つけられる。
しかし、対象ディレクトリを複数にしようと考えた場合に、私にとっては一気に難しくなってしまったのであった。
対象ディレクトリが1つの場合
対象ディレクトリが「~/.screen_log/
」の1つであるplaybookは、次のようになる。簡素に書けて素晴らしい。
- hosts: all tasks: - name: Find old logfiles find: path: "~/.screen_log/" age: "30d" register: files_found - name: Delete old logfiles file: path: "{{ item.path }}" state: absent with_items: "{{ files_found.files }}"
対象ディレクトリが2つ以上の場合
対象ディレクトリが2つ以上の場合、「Find old logfiles」部分を、対象ディレクトリを複数指定できるようにwith_itemsを使って書くのが普通だろう。
しかしこの状態にしたところ、「Delete old logfiles」部分が対象ディレクトリ1つの場合と同じままだと動かない。1,2時間悩んでdebug
など使いながら理解したこととして。
「Find old logfiles」部分をwith_itemsを使って書いた場合は、files_foundに登録されるデータの構造が変わり、階層が追加された内容となるのだ。そこで、「Delete old logfiles」部分のファイル情報抽出で、下記のようにmap()
やlist()
を使うようにしたら問題解決した。
- hosts: all tasks: - name: Find old logfiles find: paths={{ item.path }} age={{ item.age }} with_items: - { "path":"~/.screen_log/", "age":"30d" } - { "path":"~/.tmux_log/", "age":"30d" } register: files_found - name: Delete old logfiles file: path: "{{ item.path }}" state: absent #with_items: "{{ files_found.files }}" # エラーになる with_items: "{{ files_found.results | map(attribute='files') | list }}"