Hi Timothy,
I thought include_vars only understood YAML & JSON ??? That’s what the docs seem to suggest. If it supports CSV, then almost certainly it would be of use to me.
(The ultimate win I suppose would be for Ansible to support pluggable data sources.)
My CSV file contains filesystem data as a proof of concept:
vg,lv,fstype,mount_point,size,owner,perms
myvg,jb,ext3,/mnt/jb,20M,root,755
myvg,jb1,ext3,/mnt/jb/jb1,12M,root,755
myvg,jb2,ext3,/mnt/jb/jb2,32M,root,755
I have a module which loads the above data into a dict and iterates over it to creates logical volumes, filesystems and mounts.
The general idea behind this…
-
My team carry out many system deployments.
-
We are fed information from other teams as spreadsheets. E.g. lists of users/groups, software, filesystems, etc.
-
If Ansible can consume data in CSV format, we can formalise the spreadsheets supplied by other teams to export CSV, to take a lot of the manual effort out of our deployments.
The organisation are currently using Puppet and could use Hiera to achieve a similar result. But they are open to suggestions, and I think Ansible might be a better fit for their way of working.
The module which uses the csv data is as follows:
roles/filesystems/tasks/main.yml
`
tasks file for filesystems roles
-
name: load csv file
load_csv: file={{csvfile}}
register: filesystems
-
name: create lvs
lvol: lv=“{{item.lv}}” vg=“{{item.vg}}” size=“{{item.size}}”
with_items: “{{filesystems.data}}”
-
name: create filesystems
filesystem: dev=“/dev/{{item.vg}}/{{item.lv}}” fstype=“{{item.fstype}}”
with_items: “{{filesystems.data}}”
-
name: create mounts
mount: src=“/dev/{{item.vg}}/{{item.lv}}” name=“{{item.mount_point}}”
fstype=“{{item.fstype}}” state=mounted
with_items: “{{filesystems.data}}”
`
The action plugin uses the header in line 1 of the CSV to create a dictionary.
action_plugins/load_csv.py
`
from future import (absolute_import, division, print_function)
metaclass = type
from ansible.plugins.action import ActionBase
import csv
import os
class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
if task_vars is None:
task_vars = dict()
super(ActionModule, self).run(tmp, task_vars)
file = self._task.args.get(‘file’)
if file is None:
return dict(failed=True, msg=“file is required”)
try:
file = os.path.expanduser(file)
fobj = open(file, ‘rb’)
reader = csv.DictReader(fobj)
data = [i for i in reader]
except Exception as err:
return dict(failed=True, msg=“failed: %s” % err)
return dict(failed=False, changed=False, data=data,)
`
The top level playbook looks like this:
`