我有一个用于创建一些EC2实例的剧本,然后用它们做一些事情。相关部分大致如下:
- name: create ec2 instances
ec2:
id: '{{ item.name }}'
instance_type: '{{ item.type }}'
register: ec2
with_items: '{{ my_instance_defs }}'
- name: wait for SSH
wait_for:
host: '{{ item.instances[0].private_ip }}'
port: 22
with_items: '{{ ec2.results }}'
这是按预期工作的,但我对item.instances[0].private_ip
表达式并不特别满意,部分原因是它在播放摘要中显示了非常大的对象。我希望with_items
部分只是一个IP地址数组,而不是一个包含对象数组的对象数组。在Python中,我会做类似的事情:
ips = [r['instances'][0]['private_ip'] for r in ec2['results']]
然后我会在第二项任务中使用with_items: '{{ ips }}'
。
有没有办法在剧本的YAML中使用J2过滤器做同样的事情?似乎http://docs.ansible.com/ansible/playbooks_filters.html#extracting-values-from-containers可能会有所帮助,但我认为这预示着我有一系列键/索引/无论如何。
答案 0 :(得分:11)
map在这里过滤你的朋友。
这样的事情:
with_items: "{{ ec2.results | map(attribute='instances') | map('first') | map(attribute='private_ip') | list }}"
上述代码未经过测试。
您可能需要先尝试debug
,然后逐渐添加map
以获得所需的结果
不要忘记将| list
放在最后,以使您的地图可读。
答案 1 :(得分:0)
我的示例从我的剧本中取出,删除了自动缩放的ecs集群。我修改了上面的答案以使我的工作正常。
- name: get list of instances in ASG
ec2_instance_facts:
filters:
"tag:aws:autoscaling:groupName": "{{item.name}}-{{stack}}-scalinggroup"
register: asg_host_list
- name: list ecs info
debug:
msg: "{{asg_host_list}}"
- name: get just hosts id's
set_fact:
hostlist: "{{ asg_host_list.instances | map(attribute='instance_id') | list }}"
对于我来说,主机列表可以直接输入ecs_instance,因为它需要处理实例ID的列表。
因此,这已经过测试并且可以正常工作。