如何用Ansible模板结合CSV为Bind9生成区域配置文件
解决方案
1. 修正数据处理逻辑
原脚本循环CSV的每一行记录,导致生成了大量对应单行数据的文件。我们需要先将CSV数据按network1/network2/network3维度整理,得到每个网络对应的主机-IP映射列表:
- name: 整理各网络的主机记录 set_fact: network_records: network1: "{{ OUTPUT_CSV.list | map(attribute='hostname') | zip(OUTPUT_CSV.list | map(attribute='network1')) | list }}" network2: "{{ OUTPUT_CSV.list | map(attribute='hostname') | zip(OUTPUT_CSV.list | map(attribute='network2')) | list }}" network3: "{{ OUTPUT_CSV.list | map(attribute='hostname') | zip(OUTPUT_CSV.list | map(attribute='network3')) | list }}" delegate_to: localhost
这段代码通过map提取每个网络的主机名和对应IP,再用zip配对,最终生成以网络名为键、主机-IP列表为值的字典。
2. 修正区域文件生成任务
现在循环整理好的网络名称,而非CSV的每一行,同时修正拼写错误并调整目标文件名:
- name: 生成Bind9区域配置文件 template: src: zones.rfc.j2 dest: "/path/to/create/files/{{ item.key }}.zone.conf" delegate_to: dns_server loop: "{{ network_records | dict2items }}" loop_control: label: "{{ item.key }}"
dict2items将字典转为键值对列表,循环时item.key对应network1/network2/network3,直接用它命名目标文件,符合需求。
3. 调整Jinja2模板(zones.rfc.j2)
模板需要渲染对应网络的所有主机记录,示例如下:
$TTL 86400 @ IN SOA ns1.{{ item.key }}. root.{{ item.key }}. ( 2024052001 ; 序列号 3600 ; 刷新时间 1800 ; 重试时间 604800 ; 过期时间 86400 ; 最小TTL ) IN NS ns1.{{ item.key }}. IN A 192.168.1.10 ; 替换为你的NS服务器IP {% for hostname, ip in item.value %} {{ hostname }} IN A {{ ip }} {% endfor %}
模板中通过item.key获取当前网络名称,遍历item.value生成对应的A记录。
原脚本错误点
- 循环对象错误:原脚本循环
OUTPUT_CSV.list(CSV每一行),导致每行生成一个文件,而非按网络生成3个文件。 - 语法错误:
delegate to应为delegate_to。 - 文件名错误:原用
{{ item }}.txt,item是整行CSV数据,导致文件名包含冗余内容。
内容的提问来源于stack exchange,提问作者Alireza Haji Esmaeeli
相关产品推荐
相关产品推荐

