csvansible

Ansible: How to 'read_csv' into a dynamic variable name?


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.


Solution

  • 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_*, creating a dictionary of the fruits is simpler. 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