如何从文本文件生成YAML/JSON并按条件生成Ansible清单?
问题描述
现有input.txt文件包含以下格式的服务器信息:
it-linux1,p,a,3,3 it-test2,p,a,1,3 it-test3-dev,t,e,3,2 it-linux4,p,a,1,1 it-windows,t,e,3,4
当前使用的Ansible Playbook仅能读取文件内容并生成output.yaml(内容如下),但需要进一步处理,生成满足特定筛选条件的服务器清单,比如:
- 筛选包含
p值的服务器 - 筛选同时包含
t和3值的服务器 - 筛选包含
p且包含3值的服务器 - 筛选包含
p且包含1值的服务器
当前Playbook内容:
- name: Simple Read file and output JSON hosts: localhost connection: local become: false tasks: - name: Read Data File set_fact: data: "{{ lookup('ansible.builtin.file', '/home/checkout/myProjects/input.txt').split('\n') }}" - name: Show debug data ansible.builtin.debug: var=data - name: Create a new array set_fact: data_elements: [] - name: Loop through lines and add data elements to array set_fact: data_elements: "{{ data_elements + [item] }}" loop: "{{ data }}" - name: Show debug data ansible.builtin.debug: var=data_elements - name: Write output YAML file copy: dest: output.yaml content: "{{ {'records': data_elements} | to_nice_yaml }}"
生成的output.yaml内容:
records: - it-linux1,p,a,3,3 - it-test2,p,a,3,3 - it-test3-dev,t,e,1,2 - it-linux4,p,a,3,1 - it-windows,t,e,3,4
需求:能否读取并处理output.yaml(或直接处理原始input.txt),生成符合上述筛选条件的服务器清单?
解决方案
不需要先生成output.yaml再处理,直接在Playbook中解析原始input.txt的每行数据,拆分字段后进行条件筛选更高效。以下是实现不同筛选需求的Playbook示例:
1. 解析原始数据并拆分字段
首先将每行数据按逗号拆分为字段数组,方便后续条件判断:
- name: Generate filtered Ansible inventories hosts: localhost connection: local become: false vars: input_file_path: "/home/checkout/myProjects/input.txt" tasks: - name: Read and parse input file set_fact: parsed_servers: "{{ lookup('file', input_file_path).split('\n') | reject('equalto', '') | map('split', ',') | list }}" # 逻辑说明: # - split('\n'): 按行拆分文件内容 # - reject('equalto', ''): 移除空行 # - map('split', ','): 将每行按逗号拆分为字段数组
2. 实现不同筛选条件
筛选包含p值的服务器
- name: Filter servers with 'p' value set_fact: servers_with_p: "{{ parsed_servers | select('contains', 'p') | map('first') | list }}" # 逻辑说明: # - select('contains', 'p'): 保留包含'p'的字段数组 # - map('first'): 提取每个数组的第一个元素(服务器名称) - name: Write 'p' servers to inventory file copy: dest: inventory_p.yaml content: | [servers_with_p] {% for server in servers_with_p %} {{ server }} {% endfor %}
筛选同时包含t和3值的服务器
- name: Filter servers with 't' and '3' values set_fact: servers_with_t_and_3: "{{ parsed_servers | select('contains', 't') | select('contains', '3') | map('first') | list }}" - name: Write 't+3' servers to inventory file copy: dest: inventory_t_3.yaml content: | [servers_with_t_and_3] {% for server in servers_with_t_and_3 %} {{ server }} {% endfor %}
筛选包含p且包含3值的服务器
- name: Filter servers with 'p' and '3' values set_fact: servers_with_p_and_3: "{{ parsed_servers | select('contains', 'p') | select('contains', '3') | map('first') | list }}" - name: Write 'p+3' servers to inventory file copy: dest: inventory_p_3.yaml content: | [servers_with_p_and_3] {% for server in servers_with_p_and_3 %} {{ server }} {% endfor %}
筛选包含p且包含1值的服务器
- name: Filter servers with 'p' and '1' values set_fact: servers_with_p_and_1: "{{ parsed_servers | select('contains', 'p') | select('contains', '1') | map('first') | list }}" - name: Write 'p+1' servers to inventory file copy: dest: inventory_p_1.yaml content: | [servers_with_p_and_1] {% for server in servers_with_p_and_1 %} {{ server }} {% endfor %}
3. 基于output.yaml的处理方案(可选)
如果必须从已生成的output.yaml读取数据处理,可先读取该文件,再解析处理:
- name: Read output.yaml set_fact: output_data: "{{ lookup('file', 'output.yaml') | from_yaml }}" - name: Parse records from output.yaml set_fact: parsed_output_servers: "{{ output_data.records | reject('equalto', '') | map('split', ',') | list }}" # 后续筛选逻辑和上述一致,比如筛选含p和3的服务器: - name: Filter servers with 'p' and '3' from output.yaml set_fact: servers_p_3_from_output: "{{ parsed_output_servers | select('contains', 'p') | select('contains', '3') | map('first') | list }}"
示例生成结果
以inventory_p_3.yaml为例,最终内容会是:
[servers_with_p_and_3] it-linux1 it-test2
内容的提问来源于stack exchange,提问作者AL BADRY
相关产品推荐
相关产品推荐

