I'm trying to read from a list of CSV files (fileglob) and the files have a standard naming convention. Just wanted to read the CSV files using read_csv
and register
/set_fact
them to the filename, which should be the variable name.
The files are
apples.csv
pears.csv
grapes.csv
What I've tried, (its close but not correct)
- name: "Read into dynamic variables"
read_csv:
path: "{{ item }}"
with_fileglob:
- "/tmp/fruits/*.csv"
fruit_name: "{{ item | basename | regex_replace('.csv') }}"
register: "fruit_{{ fruit_name }}"
So ideally want to get the contents of each CSV to be part of variable, e.g. fruit_apples
which can be later re-used in other plays.
CodePudding user response:
This will not be possible. According Registering variables
" When you register a variable in a task with a loop, the registered variable contains a value for each item in the loop. The data structure placed in the variable during the loop will contain a
results
attribute, that is a list of all responses from the module."
Therefore you need to extract the parts which you are interested in within the next tasks.
To get a better understanding in the behavior I've created a small test
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Create multiple results and register them
debug:
msg: "{{ item }}"
loop: [A, B, C]
register: result
- name: Show result
debug:
msg: "{{ result }}"
which is showing an equivalent behavior since with_fileglob
is a with_X
style loop.
TASK [Create multiple results and register them] ***
ok: [localhost] => (item=A) =>
msg: A
ok: [localhost] => (item=B) =>
msg: B
ok: [localhost] => (item=C) =>
msg: C
TASK [Show result] *********************************
ok: [localhost] =>
msg:
changed: false
msg: All items completed
results:
- ansible_loop_var: item
changed: false
failed: false
item: A
msg: A
- ansible_loop_var: item
changed: false
failed: false
item: B
msg: B
- ansible_loop_var: item
changed: false
failed: false
item: C
msg: C
Further Q&A
- Ansible: How to register multiple variables within a single task?
- Registering multiple variables in a loop
CodePudding user response:
For example, given the files
shell> tree fruits/
fruits/
├── apples.csv
├── grapes.csv
└── pears.csv
0 directories, 3 files
shell> cat fruits/apples.csv
red,big,20
green,small,10
shell> cat fruits/grapes.csv
red,big,20
black,small,10
shell> cat fruits/pears.csv
green,big,30
yellow,small,20
Read the files
- read_csv:
fieldnames: color,size,price
path: "{{ item }}"
with_fileglob: "fruits/*.csv"
register: fruit
Instead of creating the variables fruit_*, it's simpler to create a dictionary of the fruits. For example, put the declarations below as appropriate
fruits: "{{ dict(f_keys|zip(f_vals)) }}"
f_vals: "{{ fruit.results|map(attribute='list')|list }}"
f_keys: "{{ fruit.results|map(attribute='item')|
map('basename')|
map('splitext')|
map('first')|list }}"
gives
fruits:
apples:
- {color: red, price: '20', size: big}
- {color: green, price: '10', size: small}
grapes:
- {color: red, price: '20', size: big}
- {color: black, price: '10', size: small}
pears:
- {color: green, price: '30', size: big}
- {color: yellow, price: '20', size: small}
Example of a complete playbook
- hosts: localhost
vars:
fruits: "{{ dict(f_keys|zip(f_vals)) }}"
f_vals: "{{ fruit.results|map(attribute='list')|list }}"
f_keys: "{{ fruit.results|map(attribute='item')|
map('basename')|
map('splitext')|
map('first')|list }}"
tasks:
- read_csv:
fieldnames: color,size,price
path: "{{ item }}"
with_fileglob: "fruits/*.csv"
register: fruit
- debug:
var: fruits
- debug:
var: fruits.apples