Ansible Tips: copyモジュールで(Chef cookbook_fileリソースの様に)ファイル配布元を自動的に選択させる例
目的1: copy元を自動的に選択
Ansibleのcopyモジュールに相当するChefのcookbook_fileリソースでは、copy元は、COOKBOOK_NAME/files/下で以下に最初にマッチしたファイルが使用される。
- /host-\$fqdn/\$source
- /\$platform-\$platform_version/\$source
- /\$platform/\$source
- /default/\$source
- /\$source
https://docs.chef.io/resources/cookbook_file/
https://docs.chef.io/resources/cookbook_file/#cookbook_file_specificity
しかしansibleのcopyモジュールには、その様なcopy元自動選択機能はない。
その様な機能を実装するにはどうするか。
目的2 ファイル配布元をinventory_dir/files下とする
Ansible copyモジュールのファイル配布元は、相対パス指定の場合、playbook_dir/files, playbook_dir 下から探される様子。
しかし、playbookはロジック、inventoryはデータと切り分けをしたい場合、配布元はplaybook_dir下よりinventory_dir下が望ましい。
追記/訂正
ansible-playbookコマンドの-iオプションで指定可能なインベントリーには、-i inventory_dir の様にディレクトリーを指定することも可能。
インベントリーファイルそのものやinventory_dir/host_varsやinventory_dir/group_varsを配置して利用可能。
しかし、inventory_dir/filesの様に本来のインベントリー情報以外のファイルが含まれると、エラーとなってしまう。その為、ディレクトリー指定を考慮するならば、inventory_dirの外部にに置いたほうが良い。
最終目的
Chefのcookbook_fileリソースの様に、以下の順序でcopy元を探索し、最初に見つかったファイルを配布したい。
- "{{ inventory_dir }}/files/{{ inventory_hostname }}" 下
- "{{ inventory_dir }}/files/{{ ansible_distribution }}-{{ ansible_distribution_version }}" 下
- "{{ inventory_dir }}/files/{{ ansible_distribution }}" 下
- "{{ inventory_dir }}/files/default" 下
- "{{ inventory_dir }}/files" 下
検証環境
- ansible 2.9.4
inventory_dirイメージ
inventory_dir
│
├── hosts # inventory file
│
├── host_vars # host_varsはinventory_dir下を使用している
│ ├── host01
│ │ └── main.yml
│ └── host02
│ └── main.yml
│
├── group_vars # group_varsもinventory_dir下を使用している
│ └── all
│ └── main.yml
│
└── files # **** ファイル配布元もinventory_dir下に置きたい ****
├── default # 個別のノードで指定しない場合のデフォルト(Chef準拠)
│ └── etc
│ └── hosts
├── host01 # 個別のノードで指定する場合(Chef準拠)
│ └── etc
│ └── hosts
対応するtask例
- name: copy files from inventory_dir/files
copy:
src: "{{ lookup('first_found', paths|map('regex_replace','$',item)|list ) }}"
dest: "{{ item }}"
vars:
paths:
- "{{ inventory_dir }}/files/{{ inventory_hostname }}"
- "{{ inventory_dir }}/files/{{ ansible_distribution }}-{{ ansible_distribution_version }}"
- "{{ inventory_dir }}/files/{{ ansible_distribution }}"
- "{{ inventory_dir }}/files/default"
- "{{ inventory_dir }}/files"
loop:
- "/etc/hosts"
TASK [copy files from inventory_dir/files] *************************************************************************************
ok: [host01] => (item=/etc/hosts)
- lookup('first_found', ... にて、コントローラーノード上でリスト順で最初に見つかったファイルをソースとする。
- with_first_found: を用いると、ファイル名でのloopを行うには、ファイルを分けてimport_tasksなどを使用しなければいけなくなる。
- jinja2によるfor loopと組み合わせる事でも対応可能。(可読性は落ちるが、柔軟な処理が可能)
- mapフィルターにて、Arrayであるpathsの各要素に操作を行う。
- 操作を行うフィルターへのパラメーターは、map内での第2パラメーター以降で設定する。
- つまり、各要素に | regex_replace('$',item) というフィルターを掛け、各要素の最後にファイル名を付与する
- 最後にlistフィルターでArrayに戻す。
- 操作を行うフィルターへのパラメーターは、map内での第2パラメーター以降で設定する。
- pathsに探索順にパスを定義
- inventory_dir や inventory_hostname は Ansible が設定する値
- copy対象ファイルはloop:にて回す
- パス情報の管理を容易とするために絶対パス指定としている
参照
first_found – return first file found from list
https://docs.ansible.com/ansible/latest/plugins/lookup/first_found.html
ansible 1.6 > using with_first_found in a with_items loop?
https://stackoverrun.com/ja/q/6205524
map(*args, **kwargs)
https://jinja.palletsprojects.com/en/2.11.x/templates/#map
Regular Expression Filters
https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#regular-expression-filters
Ansible Jinja2 filters 正規表現で変数の文字列を置換、抽出する
https://qiita.com/tbuchi888/items/80fded8d11366e967290
Author And Source
この問題について(Ansible Tips: copyモジュールで(Chef cookbook_fileリソースの様に)ファイル配布元を自動的に選択させる例), 我々は、より多くの情報をここで見つけました https://qiita.com/hiroyuki_onodera/items/dc2ebda7d77657e77eca著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .