我可以在Ansible游戏中使用Jinja2`map`过滤器从一组对象中获取值吗?

时间:2016-12-22 15:08:14

标签: ansible jinja2

我有一个用于创建一些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可能会有所帮助,但我认为这预示着我有一系列键/索引/无论如何。

2 个答案:

答案 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的列表。

因此,这已经过测试并且可以正常工作。

相关问题