1

i need to convert the custom output variable to convert into dictionary then to generate csv file using jinja2 template

below is the code

- name: Executing the cmd (multipath -ll | grep dm- | awk -F' dm' '{print $1}') to get the device name
   shell: multipath -ll | grep dm- | awk -F' dm' '{print $1}' | awk -F ' ' '{print $1}'
   register: multipath_device_name  
      
- name: Executing the cmd (multipath -ll | grep -E status='(active|inactive)' | awk -F ' ' '{print $5}' | cut -c 8-16) to get the device active or inactive 
  shell: multipath -ll | grep -E status='(active|inactive)' | awk -F ' ' '{print $5}' | cut -c 8-16
  register: multipath_device_status
                  
- name: Executing the cmd (multipath -ll | grep dm- | awk -F' dm' '{print $1}' | awk -F ' ' '{print $2}' | cut -d "(" -f2 | cut -d ")" -f1) to get the device active or inactive 
  shell: multipath -ll | grep dm- | awk -F' dm' '{print $1}' | awk -F ' ' '{print $2}' | cut -d "(" -f2 | cut -d ")" -f1
  register: multipath_device_id

- set_fact:
        multipath_devices:
          device_name: "{{ multipath_device_name.stdout_lines }}"
          device_id: "{{ multipath_device_id.stdout_lines }}"
          device_id_status: "{{ multipath_device_status.stdout_lines  }}"
          server_name: "{{ ansible_hostname }}"
          server_ip: "{{ ansible_default_ipv4.address }}"
- debug:
    msg: "{{ multipath_devices }}"

I got the below output for the above variable "multipath_devices"

"msg": {
        "device_id": [
            "3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2",
            "3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3",
            "3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4",
            "3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx5",
            "3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx6",
            "3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7",
            
        ],
        "device_id_status": [
            "active",
            "active",
            "active",
            "active",
            "active",
            "active"
            
        ],
        "device_name": [
            "name1",
            "name2",
            "name3",
            "name4",
            "name5",
            "name6"
        ],
        "server_ip": "192.168.56.120",
        "server_name": "node-01"

I tried the above to convert that variable into csv using jinja2 template like below, its not giving the exact output what i need. please help me to get out this done with csv

{% for key, value in multipath_devices.items() %}
    {{key}}
    {{value}}
{% endfor %}

I need the CSV file output like below

"device_name","device_id","device_id_status","server_name","server_ip"
name1, 3xxxxxxx3, active, server1, 192.168.56.201

below is the command output

name1 (3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2)
name2 (3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3)
name3 (3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4)
name4 (3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx5)
name5 (3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx6)
name6 (3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7)
Suganthan Raj
  • 2,330
  • 6
  • 31
  • 42
  • Your data structure is a bit awfull for such a task. Moreover you don't have the same number of entries from your custom commands so how do you intend to match your names, status and ids for one entry? I have the feeling you're in an [x/y problem](https://xyproblem.info) here regarding the way you get your data. You should probably edit your question and give a bit more background because there might be better ways to gather that info which could make processing it into csv a breeze. – Zeitounator Sep 02 '22 at 15:19
  • Now i have changed the number of entries.. number of entries mostly same for names, status and ids @Zeitounator – Suganthan Raj Sep 02 '22 at 15:27
  • This is still not ideal to process. Can you show how you get those custom info in your question ? – Zeitounator Sep 02 '22 at 15:35
  • i have updated code where i got those info by executing command – Suganthan Raj Sep 02 '22 at 15:49
  • It looks like you can (with some work of course) combine your 3 commands into one to get all information at once. You would then have all the custom information on one line for each device which would make it way easier to process. Can you show an example output of `multipath -ll | grep dm- | awk -F' dm' '{print $1}'`? – Zeitounator Sep 02 '22 at 15:57
  • i have updated the command output in the question section @Zeitounator – Suganthan Raj Sep 02 '22 at 16:05

1 Answers1

1

create a csv.j2 file in files folder: (you create folder files in same place than your playbook)

{{ multipath_devices.keys()|list }}
{% for i in range(0, (maxnb|max|int)) %}
{%- for k in multipath_devices -%}
{{multipath_devices[k][i] if multipath_devices[k][i] is defined else multipath_devices[k][0]}}{{'' if loop.last else ', '}} 
{%- endfor -%}
{{'\n'}}
{%- endfor %}
{%- endfor %}

if you write your task like this:

- set_fact:
        multipath_devices:
          device_name: "{{ multipath_device_name.stdout_lines }}"
          device_id: "{{ multipath_device_id.stdout_lines }}"
          device_id_status: "{{ multipath_device_status.stdout_lines  }}"
          server_name: "{{ [ansible_hostname] }}"
          server_ip: "{{ [ansible_default_ipv4.address] }}"

(i simulate your result)

- name: "tips1"
  hosts: localhost
  vars:
    multipath_devices:
      device_name:
          - name1
          - name2
          - name3
          - name4
          - name5
          - name6
      device_id:
          - 3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2
          - 3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3
          - 3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4
          - 3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx5
          - 3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx6
          - 3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7
      device_id_status:
          - active
          - active
          - active
          - active
          - active
          - active
      server_name: [node-01]          
      server_ip: [192.168.56.120]
  
  tasks:
    - name: trap max length of all lists
      set_fact:
        maxnb: "{{ maxnb | d([]) + [item.1|length]}}"
      loop: "{{multipath_devices.items()}}"
  
    - name: create csv
      template:
        src: csv.j2 
        dest: result.csv
    

result in result.csv:

device_name, device_id, device_id_status, server_name, server_ip
name1, 3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2, active, node-01, 192.168.56.120
name2, 3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3, active, node-01, 192.168.56.120
name3, 3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4, active, node-01, 192.168.56.120
name4, 3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx5, active, node-01, 192.168.56.120
name5, 3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx6, active, node-01, 192.168.56.120
name6, 3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx7, active, node-01, 192.168.56.120
Frenchy
  • 16,386
  • 3
  • 16
  • 39
  • I need the header "device_name","device_id","device_id_status","server_name","server_ip" this should be dynamically get from the variables multipath_devices, can you help me on this? @Frenchy – Suganthan Raj Sep 03 '22 at 08:16
  • ok but you cant force the position, so the position will be the position found in the variable – Frenchy Sep 03 '22 at 10:14
  • @SuganthanRaj i have modified the playbook and the j2 file to generalize the result – Frenchy Sep 03 '22 at 15:55
  • i got the error "FAILED! => {"changed": false, "msg": "AnsibleUndefinedVariable: 'keysvar' is undefined"} " – Suganthan Raj Sep 04 '22 at 14:51
  • @SuganthanRaj, i have not this error.. this error means the var keysvar doesnt exist. are you sure to not have typo error? show your playbook and your j2...have you play exactly my playbook? – Frenchy Sep 04 '22 at 15:33
  • what is the task which gives error template or set_fact module ? – Frenchy Sep 04 '22 at 15:54
  • waht is our version of ansible? – Frenchy Sep 04 '22 at 15:58
  • TASK [transform all values of dict to list] fatal: Hint: If you passed a list/dict of just one element, try adding wantlist=True to your lookup invocation or use q/query instead of lookup."} – Suganthan Raj Sep 04 '22 at 15:58
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/247776/discussion-between-suganthan-raj-and-frenchy). – Suganthan Raj Sep 04 '22 at 15:59