首发于 DevNet
Jinja2: 从 Nested Loop 变量生成 CSV 文件

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