Ansible: récupère toutes les adresses IP d'un groupe

Imaginons un fichier d'inventaire comme ceci:

node-01 ansible_ssh_host=192.168.100.101
node-02 ansible_ssh_host=192.168.100.102
node-03 ansible_ssh_host=192.168.100.103
node-04 ansible_ssh_host=192.168.100.104
node-05 ansible_ssh_host=192.168.100.105

[mainnodes]
node-[01:04]

Dans mon playbook, je veux maintenant créer des variables contenant les adresses IP du groupe mainnodes:

vars:
  main_nodes_ips: "192.168.100.101,192.168.100.102,192.168.100.103,192.168.100.104"
  main_nodes_ips_with_port: "192.168.100.101:3000,192.168.100.102:3000,192.168.100.103:3000,192.168.100.104:3000"

C'est ce que j'ai eu jusqu'à présent:

vars:
  main_nodes_ips: "{{groups['mainnodes']|join(',')}}"
  main_nodes_ips_with_port: "{{groups['mainnodes']|join(':3000,')}}"

Mais cela utiliserait les noms d'hôte au lieu des adresses IP.

Des idées comment cela pourrait être fait?

Mise à Jour:

En regardant les documents pendant un moment, je pense que cela me permettrait de parcourir toutes les adresses ip adresses:

{% for host in groups['mainnodes'] %}
    {{hostvars[host]['ansible_ssh_host']}}
{% endfor %}

Mais je n'arrive tout simplement pas à comprendre comment créer un tableau contenant toutes ces adresses IP. Pour que je puisse utiliser la commande |join() sur eux.

Update2:
J'ai juste pensé que j'avais compris... mais il s'avère que vous ne pouvez pas utiliser la syntaxe {% %} dans le playbook... ou puis-je? Eh bien, dans la section vars, ce n'est pas le cas.: /

vars:
  {% set main_nodes_ip_arr=[] %}
  {% for host in groups['mesos-slave'] %}
     {% if main_nodes_ip_arr.insert(loop.index,hostvars[host]['ansible_ssh_host']) %} {% endif %}
  {% endfor %}
  main_nodes_ips: "{{main_nodes_ip_arr|join(',')}}"
  main_nodes_ips_with_port: "{{main_nodes_ip_arr|join(':3000,')}}"
21
demandé sur Forivin 2016-03-31 12:07:43

5 réponses

Je trouve la magie map extract ici.

main_nodes_ips: "{{ groups['mainnodes'] | map('extract', hostvars, ['ansible_ssh_host']) | join(',') }}"
main_nodes_ips_with_port: "{{ groups['mainnodes'] | map('extract', hostvars, ['ansible_ssh_host']) | join(':3000,') }}:3000"

Une alternative(l'idée vient de ici):

main_nodes_ips: "{{ groups['mainnodes'] | map('extract', hostvars, ['ansible_eth0', 'ipv4', 'address']) | join(',') }}"
32
répondu McKelvin 2016-10-08 13:08:58

Je suis tombé sur ce problème un temps, et c'est ce que j'ai trouvé (pas optimal, mais ça fonctionne)

---
# playbook.yml
  - hosts: localhost
    connection: local

    tasks:
      - name: create deploy template
        template:
          src: iplist.txt
          dest: /tmp/iplist.txt
      - include_vars: /tmp/iplist.txt

      - debug: var=ip

Et le fichier modèle est

ip:
{% for h in groups['webservers'] %}
 - {{ hostvars[h].ansible_ssh_host }}
{% endfor %}
3
répondu user2599522 2016-03-31 11:41:13

Je l'ai fait travailler tout seul maintenant. Je ne suis pas trop heureux de la solution, mais cela fera l'affaire:

main_nodes_ips: "{% set IP_ARR=[] %}{% for host in groups['mainnodes'] %}{% if IP_ARR.insert(loop.index,hostvars[host]['ansible_ssh_host']) %}{% endif %}{% endfor %}{{IP_ARR|join(',')}}"
main_nodes_ips_with_port: "{% set IP_ARR=[] %}{% for host in groups['mainnodes'] %}{% if IP_ARR.insert(loop.index,hostvars[host]['ansible_ssh_host']) %}{% endif %}{% endfor %}{{IP_ARR|join(':3000,')}
1
répondu Forivin 2016-03-31 11:09:30

J'ai trouvé le "seul moyen" d'accéder aux adresses ip d'autres groupes, lorsque l'un des éléments suivants est vrai:

  • certains membres ne sont pas encore bootstrappés par ansible
  • utilisant la série
  • Le groupe ne fait pas partie du playbook

Est comme suit:

{% set ips=[] %}{% for host in groups['othergroup'] %}{% if ips.append(lookup('dig', host)) %}{% endif %}{% endfor %}{{ ips }}

Nécessite dnspython sur la machine exécutant ansible, installer via

sudo apt-get install python-dnspython

Si quelqu'un connaît un meilleur moyen compte tenu des conditions, j'aimerais me débarrasser de cette abomination.

1
répondu Petroldrake 2017-09-06 14:32:17

Je l'ai fait en utilisant des faits ansible dans un playbook. Ce playbook prend la liste ansible_all_ipv4_addresses et ansible_nodename (qui est en fait un nom de domaine complet), parcourt tous les hôtes et enregistre les données dans le fichier localpath_to_save_ips sur votre localhost. Vous pouvez changer localpath_to_save_ips en chemin absolu sur votre localhost.

---
- hosts: all
  become: yes
  gather_facts: yes

  tasks:
  - name: get ip
    local_action: shell echo {{ ansible_all_ipv4_addresses }} {{ ansible_nodename }} >> localpath_to_save_ips
1
répondu Ilshat Karazbayev 2018-04-13 18:24:10