Somebody asked me if it was possible to parse a CSV file into an Ansible vars_file. A little casual googling didn’t yield good results, so I wrote up a little hack.
The context was wanting to feed a big CSV file of data (presumably exported from an Excel spreadsheet) to Ansible’s network automation. So first we gin up a bit of CSV:
name,description,vlanid,state,mtu,inet spam,spam,1,up,1500,192.168.1.1 eggs,eggs,2,up,1500,192.168.1.2 sausage,sausage,3,up,9000,192.168.1.3
Parsing this with Python is very easy. In fact, it even has a built-in module for CSV, which can produce a nice dict with labels based on the column titles.
#!/usr/bin/env python
import csv
import sys
import yaml
csv_data = []
with open(sys.argv[1]) as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
csv_data.append(row)
with open(sys.argv[1] + '.yml', 'w') as outfile:
outfile.write(yaml.dump({'csv_data': csv_data}))
Now using this bit of Python, we can make an Ansible playbook that first parses the CSV into a YAML vars_file, and then imports that vars_file in the playbook.
---
- hosts: localhost
connection: local
become: false
gather_facts: false
tasks:
- name: parse csv and make vars file
command: "python csv_to_yaml.py example.csv"
- hosts: localhost
connection: local
become: false
gather_facts: false
vars_files:
- example.csv.yml
tasks:
- debug: var=csv_data
Now lets run it and look at the debug output.
[jason@w550s redhat]$ ansible-playbook csv_vars_playbook.yml
[WARNING]: Could not match supplied host pattern, ignoring: all
[WARNING]: provided hosts list is empty, only localhost is available
PLAY [localhost] **********************************************************
TASK [parse csv and make vars file] ***************************************
changed: [localhost]
PLAY [localhost] **********************************************************
TASK [debug] **************************************************************
ok: [localhost] => {
"csv_data": [
{
"description": "spam",
"inet": "192.168.1.1",
"mtu": "1500",
"name": "spam",
"state": "up",
"vlanid": "1"
},
{
"description": "eggs",
"inet": "192.168.1.2",
"mtu": "1500",
"name": "eggs",
"state": "up",
"vlanid": "2"
},
{
"description": "sausage",
"inet": "192.168.1.3",
"mtu": "9000",
"name": "sausage",
"state": "up",
"vlanid": "3"
}
]
}
PLAY RECAP ****************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0
There may be better ways for Ansible to parse CSV, but this was quick and easy. Hit me up if you’ve got a more elegant approach!