Home > front end >  Ansible: How to 'read_csv' into a dynamic variable name?
Ansible: How to 'read_csv' into a dynamic variable name?

Time:06-08

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

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
  • Related