Ansible Csv Vars Plugin
Introduction
When rolling out network configs I kept address assignments in spreadsheets because they are easy to edit. Translating those tables into Ansible host vars manually grew painful, so this plugin lets each CSV row feed host-specific variables automatically. During template rendering every device pulls its unique addresses from the sheet, keeping the workflow spreadsheet-friendly while delivering correct per-host values in playbooks.
Requirements
Parse data from CSV into host variables.
CSV file example:
hostname,gateway,vlan30,vlan40,vlan50,vlan60,vlan70
localhost,192.168.30.254,192.168.30.31,192.168.40.31,192.168.50.31,192.168.60.31,192.168.70.31
- Place the CSV file in the
csv_vars
directory underinventory
orplaybook
, and it will be automatically parsed. - The
hostname
field in the CSV must match the host name in the inventory. - It is recommended to name the CSV as GROUP_OR_HOST_NAME.csv. Multiple CSV files are supported, and variable overriding is also supported.
Write the Plugin
File path: vars_plugins/csv_vars.py
1
...existing code...
Code from https://github.com/guozijn/csv_vars
CSV File
Place the CSV file in the csv_vars
directory under inventory or playbook.
1
2
3
4
5
mdkir csv_vars
cat << EOF >> csv_vars/nodes.csv
hostname,gateway,vlan30,vlan40,vlan50,vlan60,vlan70
192.168.77.130,192.168.30.254,192.168.30.31,192.168.40.31,192.168.50.31,192.168.60.31,192.168.70.31
EOF
Run Playbook
1
2
3
4
5
6
7
8
9
# cat test_vars.yml
- hosts: 192.168.77.130
gather_facts: no
tasks:
- debug:
msg: "{{ lookup('vars', item) }}"
loop: "{{ hostvars[inventory_hostname].keys() | select('match', '^vlan.*$|gateway') | list }}"
Execution result:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# ansible-playbook test_vars.yml
PLAY [192.168.77.130] ************************************************************************************************
TASK [debug] *********************************************************************************************************
ok: [192.168.77.130] => (item=gateway) => {
"msg": "192.168.30.254"
}
ok: [192.168.77.130] => (item=vlan60) => {
"msg": "192.168.60.31"
}
ok: [192.168.77.130] => (item=vlan30) => {
"msg": "192.168.30.31"
}
ok: [192.168.77.130] => (item=vlan40) => {
"msg": "192.168.40.31"
}
ok: [192.168.77.130] => (item=vlan70) => {
"msg": "192.168.70.31"
}
ok: [192.168.77.130] => (item=vlan50) => {
"msg": "192.168.50.31"
}
PLAY RECAP ***********************************************************************************************************
192.168.77.130 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Run ad-hoc
Configure ansible.cfg
to set the custom plugin directory:
1
2
[defaults]
vars_plugins = /etc/ansible/vars_plugins
1
2
3
4
5
6
7
8
9
# ansible 192.168.77.130 -m debug -a 'var=gateway'
192.168.77.130 | SUCCESS => {
"gateway": "192.168.30.254"
}
# ansible 192.168.77.130 -m debug -a 'var=vlan30'
192.168.77.130 | SUCCESS => {
"vlan30": "192.168.30.31"
}