■ はじめに
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 の一覧からご確認ください。