如何从多主机的Ansible注册变量ec2_eni生成指定格式字典?
问题
我通过条件筛选(include_tasks)给Play中的部分主机执行以下任务,为其添加两个辅助私有IP:
- name: Add two secondary private IPs to WSFC hosts amazon.aws.ec2_eni: eni_id: '{{ hostvars[inventory_hostname].network_interfaces[0].network_interface_id }}' secondary_private_ip_address_count: 2 subnet_id: '{{ hostvars[inventory_hostname].network_interfaces[0].subnet_id }}' delegate_to: localhost register: ec2_eni
我需要以最高效的方式,从注册的ec2_eni变量生成如下格式的字典,按主机分类存储新增的两个IP:
some_dict: - hostname: host1 ip1: ###.###.###.### ip2: ###.###.###.### - hostname: host2 ip1: ###.###.###.### ip2: ###.###.###.###
ec2_eni的返回结构示例如下:
{ "interface": { "id": "eni-999", "subnet_id": "subnet-999", "vpc_id": "vpc-999", "description": "Primary IPv4 interface for EC2 instance", "owner_id": "999", "status": "in-use", "mac_address": "00:00:00:00:00:00", "private_ip_address": "192.168.0.1", "source_dest_check": true, "groups": { "sg-999": "security-group" }, "private_ip_addresses": [ { "private_ip_address": "192.168.0.1", "primary_address": true }, { "private_ip_address": "192.168.0.2", "primary_address": false }, { "private_ip_address": "192.168.0.3", "primary_address": false } ] } }
解决方案
可以通过set_fact结合Jinja2过滤器和循环,一次性生成目标字典,无需额外循环任务,实现高效处理:
- name: Generate target IP dictionary grouped by host set_fact: some_dict: >- {%- set ip_list = [] -%} {%- for host in ansible_play_hosts -%} {%- set secondary_ips = hostvars[host].ec2_eni.interface.private_ip_addresses | selectattr('primary_address', 'equalto', false) | map(attribute='private_ip_address') | list -%} {%- if secondary_ips | length >= 2 -%} {%- set _ = ip_list.append({ 'hostname': host, 'ip1': secondary_ips[0], 'ip2': secondary_ips[1] }) -%} {%- endif -%} {%- endfor -%} {{ ip_list }} delegate_to: localhost
说明
ansible_play_hosts:包含当前Play中所有符合条件的主机(即执行过添加IP任务的主机)selectattr('primary_address', 'equalto', false):过滤出所有非主IP的条目map(attribute='private_ip_address'):提取条目中的IP字符串,转换为列表- 最后将每个主机的信息组装为指定格式的字典,加入结果列表
内容的提问来源于stack exchange,提问作者Kimmel
相关产品推荐
相关产品推荐

