Ansible: Получить все IP-адреса группы

Представьте себе такой файл инвентаризации:

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]

В моей книге я теперь хочу создать некоторые переменные, содержащие IP-адреса групп 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"

Это то, что я получил до сих пор:

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

но это будет использовать имена хостов вместо IP-адресов.

Любые идеи, как это можно сделать?

Обновление:

глядя на документы некоторое время, я думаю, что это позволило бы мне перебрать все ip-адреса:

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

Но я просто не могу понять, как создать массив, содержащий все эти IP-адреса. Чтобы я мог использовать команду |join().

Update2:
Я просто подумал, что я это понял... но оказывается, что вы не можете использовать синтаксис {%%} в плейбуке... или я могу? Ну, в секции варов это не так. :/

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,')}}"

Ответы

Ответ 1

Теперь у меня это получилось. Я не очень доволен решением, но он будет делать:

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

Ответ 2

Я считаю, волшебная map extract здесь.

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"

Альтернатива (идея приходит отсюда):

main_nodes_ips: "{{ groups['mainnodes'] | map('extract', hostvars, ['ansible_eth0', 'ipv4', 'address']) | join(',') }}"

Ответ 3

я столкнулся с этой проблемой некоторое время назад, и это то, к чему я пришел (не оптимальный, но он работает)

---
# 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

и файл шаблона

ip:
{% for h in groups['webservers'] %}
 - {{ hostvars[h].ansible_ssh_host }}
{% endfor %}

Ответ 4

Я нашел "единственный способ" для доступа к другим группам ip, когда выполняется одно из следующих утверждений:

  • некоторые участники не загружаются
  • с использованием последовательного
  • группа не входит в playbook

Как следует:

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

Требуется dnspython на машине, работающей под управлением, установить через

sudo apt-get install python-dnspython

Если кто-то знает лучший способ, учитывая условия, я бы хотел избавиться от этой мерзости.

Ответ 5

Я сделал это, используя факты в книжке. Эта playbook принимает список ansible_all_ipv4_addresses и ansible_nodename (который фактически является полным доменным именем), выполняет итерацию через все хосты и сохраняет данные в файле localpath_to_save_ips на вашем локальном хосте. Вы можете изменить localpath_to_save_ips на абсолютный путь на вашем 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