■ はじめに
2019年5月リリース予定の Ansible 2.8 では、CSV ファイルをリストやディクショナリとして読み込む read_csv
モジュール が導入されます。カンマ区切りのファイルだけでなく、別のデリミタ(;
など)を指定することもできます。
この記事では、 read_csv
モジュールの公式ドキュメントに記載されている使用例をベースにして、使い方を説明します。
なお、公式ドキュメントの使用例は、Playbook 単位ではなくtask 単位で記載されています。この記事では Playbook 単位で例示します。
似たものとして、csvfile lookup
プラグインがあります。csvfile lookup プラグインが「ローカルのCSVファイル」の「指定条件の値を取得」するのに対して、read_csv モジュールは、「リモート(またはローカル)のCSVファイル」の「全体をリストまたはディクショナリとして取得」します。
動作確認環境
- Ansible devel バージョン (2019/03/29時点)
pip install git+https://github.com/ansible/ansible.git@devel
でインストール- 参考: https://tekunabe.hatenablog.jp/entry/2018/05/09/ansible_install_devel
- CentOS 7.6 (Ansible 側、管理対象ホスト側とも)
目次
■ 単純にCSVファイルを読み込んでリストにする
CSV ファイル
以下のヘッダー付き CSV ファイルを利用します。
name,uid,gid dag,500,500 jeroen,501,500
Playbook
単純にCSVファイルを読み込んでリストにするシンプルな Playbook です。
- hosts: testsv gather_facts: no tasks: - name: Read users from CSV file and return a list read_csv: path: users.csv register: users delegate_to: localhost # ここを省略するとリモートのファイルを参照 - name: debug csv debug: msg: "{{ users }}"
read_csv
タスクpath
オプション- 読み込む CSV ファイルのパスを指定します。(必須)
delegate_to
ディレクティブdelegate_to: localhost
という指定で、リモートではなくローカル(ansible-playbook
コマンド自体を実行しているマシン)上のpath
を参照します。省略すると、リモートのpath
を参照します。
debug
タスクmsg
オプション- リストとして取得した CSV ファイルの内容を単純に全部出力します。
実行ログ
Playbook を実行します。
$ ansible-playbook -i ../inventory csv_simple.yml PLAY [testsv] ******************************************************************************************* TASK [Read users from CSV file and return a list] ******************************************************* ok: [testsv] TASK [debug csv] **************************************************************************************** ok: [testsv] => { "msg": { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "dict": {}, "failed": false, "list": [ { "gid": "500", "name": "dag", "uid": "500" }, { "gid": "500", "name": "jeroen", "uid": "501" } ] } } PLAY RECAP ********************************************************************************************** testsv : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
debug
タスクの出力により、CSV ファイルの内容がリストとして、users.list
に格納されていることが分かります。各リスト内の要素は CSV ファイルの1行目のヘッダー gid,name,uid
が、キーとなるディクショナリの構造になります。
特定の値を取得する場合、例えば、1番目(0オリジン)の name
であれば、"{{ users.list.1.name }}"
と指定すすると、jeroen
という値を取得できます。
他、SQL の where 句のような条件で抽出するには selectattrを使用します。例えば、gid
が 500
以上の name
のリストであれば、
"{{ `users.list | selectattr('gid', '==', '500') | map(attribute='name') | list }}"
と指定すると ["dag", "jeroen"]
という値を取得できます。
■ CSV ファイルを読み込んでディクショナリにする
CSV ファイル
先ほどと同じく、以下のヘッダー付き CSV ファイルを利用します。
name,uid,gid dag,500,500 jeroen,501,500
Playbook
CSV ファイルを読み込んでディクショナリにする Playbook です。
- hosts: testsv gather_facts: no tasks: - name: Read users from CSV file and return a list read_csv: path: users.csv key: name register: users delegate_to: localhost # ここを省略するとリモートのファイルを参照 - name: debug csv debug: msg: "{{ users }}"
read_csv
タスクkey
オプション- ディクショナリとして取得する際のキーを指定します。
debug
タスクmsg
オプション- ディクショナリとして取得した CSV ファイルの内容を単純に全部出力します。
実行ログ
Playbook を実行します。
$ ansible-playbook -i ../inventory csv_dict.yml PLAY [testsv] ******************************************************************************************* TASK [Read users from CSV file and return a list] ******************************************************* ok: [testsv] TASK [debug csv] **************************************************************************************** ok: [testsv] => { "msg": { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "dict": { "dag": { "gid": "500", "name": "dag", "uid": "500" }, "jeroen": { "gid": "500", "name": "jeroen", "uid": "501" } }, "failed": false, "list": [] } } PLAY RECAP ********************************************************************************************** testsv : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
debug
タスクの出力により、CSV ファイルの内容がディクショナリとして、users.dict
に格納されていることが分かります。key
オプションで指定した name
にあたる値がキーとなる構造になります。
特定の値を取得する場合、例えば name
が dag
の uid
の場合、"{{ users.dict.dag.uid }}"
と指定すると、500
という値を取得できます。
■ ヘッダーのないセミコロン区切りのファイルを読み込んでリストにする
カンマでなく、別のデリミタの場合です。
ファイル
以下のヘッダーのないセミコロン区切りのファイルを利用します。
dag;500;500 jeroen;501;500
Playbook
ヘッダーのないセミコロン区切りのファイルを読み込んでリストにする Playbook です。
- hosts: testsv gather_facts: no tasks: - name: Read users from CSV file and return a list read_csv: path: users_wo_headers.csv fieldnames: name,uid,gid delimiter: ';' register: users delegate_to: localhost # ここを省略するとリモートのファイルを参照 - name: debug csv debug: msg: "{{ users }}"
read_csv
タスクfieldnames
オプション- ヘッダーのないファイルの場合にそれぞれのカラムにつけヘッダー名です。
delimiter
オプション- 区切り文字となるデリミタを指定します。今回の読み込みファイルは
;
区切りなので、delimiter: ';'
を指定します。
- 区切り文字となるデリミタを指定します。今回の読み込みファイルは
debug
タスクmsg
オプション- リストとして取得したファイルの内容を単純に全部出力します。
実行ログ
Playbook を実行します。
$ ansible-playbook -i ../inventory csv_3.yml PLAY [testsv] ******************************************************************************************* TASK [Read users from CSV file and return a list] ******************************************************* ok: [testsv] TASK [debug csv] **************************************************************************************** ok: [testsv] => { "msg": { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "dict": {}, "failed": false, "list": [ { "gid": "500", "name": "dag", "uid": "500" }, { "gid": "500", "name": "jeroen", "uid": "501" } ] } } PLAY RECAP ********************************************************************************************** testsv : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
debug
タスクの出力により、ヘッダーのない ;
区切りのファイルの内容がリストとして、users.list
に格納されていることが分かります。各リスト内の要素は fieldnames
オプションで指定した、gid,name,uid
が、キーとなるディクショナリの構造になります。
■ まとめ
公式ドキュメントの使用例をベースにしてread_csv
モジュール の使い方を説明しました。
他に「こんなことできるかな?」と気になる事がありましたら、公式ドキュメントで詳細をご確認ください。
また、read_csv モジュールは Files modules
に分類されています。Files modules
には、他にも、指定した正規表現にマッチするすべての文字列を置換する replace
や、行ではなくブロック単位で編集する blockinfile
などのモジュールがあります。詳細は Files modules
の一覧からご確認ください。