ぴよ丸水産

週末ファゴッティストによる技術ブログ

【Ansible】指定のディレクトリ配下にあるファイルをすべてコピーする

はじめに

指定のディレクトリ配下にあるすべてのファイルを、
指定のディレクトリにコピーするPlaybook書きました。

registerを駆使したパワープレイbookです。

動作確認環境

  • Ansible:2.8.5

要件

  • /tmp/hoge/target_dir/配下のすべてのファイルを、/root/fishing/dest/にコピーしたい
  • /tmp/hoge/target_dir/直下にファイルがあったり、サブディレクトリがあったりする想定

状況

コピー先のファイルパスが定義できない想定です。
とにかく、target_dirより下の階層に存在するファイルはすべて取ってくる!という仕様です。

こんな感じで仕込みました。

/tmp/hoge/
└ target_dir
    ├ subdir
    │ └ test03.txt
    ├ test01.txt
    └ test02.txt

Playbook

流れとしては、以下の通りです。
1. 対象のディレクトリがあるか確認する
2. 対象のディレクトリ内のファイルを再帰的に検索
3. 2.の検索の返り値(ファイルパス)をコピー元として、/root/fishing/dest/にコピー

- hosts: all
  tasks:
  - name: find directory
    find:
      paths: /tmp/hoge/
      file_type: directory
      patterns: "target_dir"
    register: find_dir_result

  - name: find file in target directory
    find:
      paths: /tmp/hoge/target_dir/
      recurse: yes
    when: find_dir_result.matched != 0
    register: find_file_result

  - name: copy the file to another directory
    copy:
      src: "{{ item.path }}"
      dest: /root/fishing/dest
    with_items: "{{ find_file_result.files }}"
    when: find_dir_result.matched != 0

実行ログ

# ansible-playbook -i "localhost," -c local site.yml

PLAY [all] *********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [find directory] **********************************************************
ok: [localhost]

TASK [find file in target directory] *******************************************
ok: [localhost]

TASK [copy the file to another directory] **************************************
changed: [localhost] => (item={'path': '/tmp/hoge/target_dir/test02.txt', 'mode': '0644', 'isdir': False, 'ischr': False, 'isblk': False, 'isreg': True, 'isfifo': False, 'islnk': False, 'issock': False, 'uid': 0, 'gid': 0, 'size': 7, 'inode': 271483, 'dev': 64770, 'nlink': 1, 'atime': 1574214578.7024505, 'mtime': 1574214578.7024505, 'ctime': 1574214578.7024505, 'gr_name': 'root', 'pw_name': 'root', 'wusr': True, 'rusr': True, 'xusr': False, 'wgrp': False, 'rgrp': True, 'xgrp': False, 'woth': False, 'roth': True, 'xoth': False, 'isuid': False, 'isgid': False})
changed: [localhost] => (item={'path': '/tmp/hoge/target_dir/test01.txt', 'mode': '0644', 'isdir': False, 'ischr': False, 'isblk': False, 'isreg': True, 'isfifo': False, 'islnk': False, 'issock': False, 'uid': 0, 'gid': 0, 'size': 5, 'inode': 264556, 'dev': 64770, 'nlink': 1, 'atime': 1574214468.7718232, 'mtime': 1574214053.4072368, 'ctime': 1574214602.3138, 'gr_name': 'root', 'pw_name': 'root', 'wusr': True, 'rusr': True, 'xusr': False, 'wgrp': False, 'rgrp': True, 'xgrp': False, 'woth': False, 'roth': True, 'xoth': False, 'isuid': False, 'isgid': False})
changed: [localhost] => (item={'path': '/tmp/hoge/target_dir/subdir/test03.txt', 'mode': '0644', 'isdir': False, 'ischr': False, 'isblk': False, 'isreg': True, 'isfifo': False, 'islnk': False, 'issock': False, 'uid': 0, 'gid': 0, 'size': 0, 'inode': 271486, 'dev': 64770, 'nlink': 1, 'atime': 1574214635.5332918, 'mtime': 1574214635.5332918, 'ctime': 1574214635.5332918, 'gr_name': 'root', 'pw_name': 'root', 'wusr': True, 'rusr': True, 'xusr': False, 'wgrp': False, 'rgrp': True, 'xgrp': False, 'woth': False, 'roth': True, 'xoth': False, 'isuid': False, 'isgid': False})

PLAY RECAP *********************************************************************
localhost                  : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

結果

ちゃんとコピーされてます。

# ls /root/fishing/dest/
test01.txt  test02.txt  test03.txt

まとめ

工夫した点、学んだ点は以下の通り。

  • (find結果のregister変数).matchedでfindのヒット数を処理に使える
  • findモジュールのrecurse: yes再帰的検索ができる
  • with_items: (find結果のregister変数).filesで、findでヒットしたファイル分の処理をループできる

registerを駆使してごにょごにょするのが得意になってきた気がします。
もっとスマートな方法があるのかもしれないけども。。

補足(経緯など)

Windowsホストからfetchした痕跡で、
後々Git管理したいディレクトリに、C:というディレクトリが含まれてました。
WindowsクライアントでPullするとエラーになるため、
C:配下のファイルを上の階層に引き上げるために作ったPlaybookです。
fetchしているPlaybookはいじれない状況だったので、
別のPlaybookでごにょごにょした次第です。
実際はlocal_actionでやりました。

つまるところ、
Ansibleを取り巻くJenkinsやGitの動作を改善するために、
仕掛けた小細工なので、
果たして有用な情報なのかは置いておきます。

参考

docs.ansible.com