Jinja2: 从 Nested Loop 变量生成 CSV 文件
今天我遇到了一个特殊的需求,我在自动发送设备报告的时候需要使用 jinja2 来生成邮件 CSV 附件, 但是我的 数据 input 比较特殊, 其中包含了双层循环 (Nested Loop)。
数据 input
我的数据 input 变量如下, 我们可以看到下面的 input 信息中有两个循环
- machine 的循环
- vlan 的循环
device_overall_status:
- machine: CISCOIOS001
overall_status: Fail
upgraded: 'True'
vlan_information:
- vlan_id: 'vlan100'
vlan_description: this vlan is used for management
vlan_status: up
- vlan_id: 'vlan200'
vlan_description: this vlan is used for data
vlan_status: down
- machine: CISCOIOS002
overall_status: Fail
upgraded: 'True'
vlan_information:
- vlan_id: 'vlan100'
vlan_description: this vlan is used for management
vlan_status: down
- vlan_id: 'vlan200'
description: this vlan is used for data
vlan_status: down
- machine: CISCOIOS003
overall_status: Pass
upgraded: 'True'
vlan_information:
- vlan_id: 'vlan100'
vlan_description: this vlan is used for management
vlan_status: up
- vlan_id: 'vlan200'
vlan_description: this vlan is used for data
vlan_status: up
定义 jinja2 模版
我们定义的规则是:
- 如果 overall_status 是 Fail,那么我们就将数据导入到 CSV
- 每一行数据需要包含全部的信息
{% if device_overall_status is defined and device_overall_status.machine[0] is defined %}
MachineName,upgraded,{% for title in device_overall_status[0].vlan_information %}vlan_id_{{loop.index}},vlan_description_{{loop.index}},vlan_status_{{loop.index}},{% endfor %}{{ '\n' }}{% for machine in device_overall_status %}{% if machine.overall_status == 'Fail' %}{{ machine.machine }},{{ machine.upgraded }},{% for sub in machine.vlan_information %}{{ sub.vlan_id }},{{ sub.vlan_description }},{{ sub.vlan_status }},{% endfor %}{{ '\n' }}{% endif %}{% endfor %}
{% endif %}
关于换行的问题
在上面的 jinja2 代码中,我们看到可读性并不是很高,那是因为我们常常会遇到换行的问题。
如果我们需要换行规范化,我们使用 {{ '\n' }} 来规范换行。
我们可以看到如下生成的 CSV 文件已经正确换行。
MachineName,upgraded,vlan_id_1,vlan_description_1,vlan_status_1,vlan_id_2,vlan_description_2,vlan_status_2
CISCOIOS001,TRUE,vlan100,this vlan is used for management,up,vlan200,this vlan is used for data,down
CISCOIOS002,TRUE,vlan100,this vlan is used for management,down,vlan200,this vlan is used for data,down
生成 CSV
下面 playbook 的信息描述的是生成 CSV 文件 然后显示出来
其中的 变量 {{ TEMP_FOLDER_LOCAL }} 为缓存文件夹
---
- name: Generate email attachment - csv file
template:
src: "generate_email_attachement.j2"
dest: "{{ TEMP_FOLDER_LOCAL }}/{{ csv_name }}.csv"
mode: '0644'
run_once: true