web-dev-qa-db-fra.com

Puis-je utiliser le filtre `map` de Jinja2 dans une lecture Ansible pour obtenir les valeurs d'un tableau d'objets?

J'ai un livre de jeu pour créer des instances EC2 et ensuite faire des choses avec elles. Les pièces pertinentes ressemblent à peu près à:

- 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 }}'

Cela fonctionne comme prévu, mais je ne suis pas particulièrement satisfait de l'expression item.instances[0].private_ip, en partie parce qu'elle montre de très gros objets dans le résumé de la lecture. J'aimerais que la partie with_items soit simplement un tableau d'adresses IP, plutôt qu'un tableau d'objets contenant des tableaux d'objets. En Python, je voudrais juste faire quelque chose comme:

ips = [r['instances'][0]['private_ip'] for r in ec2['results']]

Et puis j'utiliserais with_items: '{{ ips }}' dans la deuxième tâche.

Est-il possible de faire la même chose en utilisant un filtre J2 dans le YAML du jeu? On dirait que http://docs.ansible.com/ansible/playbooks_filters.html#extracting-values-from-containers pourrait être utile, mais je pense que cela suppose que j'ai un tableau de clés/indices/peu importe.

6
amacleod

carte filtrez votre ami ici.

Quelque chose comme ça:

with_items: "{{ ec2.results | map(attribute='instances') | map('first') | map(attribute='private_ip') | list }}"

Le code ci-dessus n'est pas testé.
Vous voudrez peut-être essayer avec debug en premier et ajouter progressivement maps pour obtenir le résultat requis.
N'oubliez pas de mettre | list à la fin pour rendre votre carte lisible.

9
Konstantin Suvorov

Mon exemple est tiré de mon livre de jeu en supprimant un cluster ecs à mise à l'échelle automatique. J'ai modifié la réponse ci-dessus pour que le mien fonctionne.

- 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 }}"

Pour mon utilisation, hostlist peut être directement introduit dans ecs_instance car il faut une liste d'identifiants d'instances à traiter.

Donc, ceci est testé et fonctionne.

0
mpechner