让我们设想一个像这样的库存文件:
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]
在我的剧本中,我现在想要创建一些包含组mainnodes
的IP地址的变量:
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部分,它没有。 :/
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,')}}"
答案 0 :(得分:50)
我找到了神奇的map extract
here。
main_nodes_ips: "{{ groups['mainnodes'] | map('extract', hostvars, ['ansible_host']) | join(',') }}"
main_nodes_ips_with_port: "{{ groups['mainnodes'] | map('extract', hostvars, ['ansible_host']) | join(':3000,') }}:3000"
另一种选择(想法来自here):
main_nodes_ips: "{{ groups['mainnodes'] | map('extract', hostvars, ['ansible_eth0', 'ipv4', 'address']) | join(',') }}"
(假设界面为eth0
)
答案 1 :(得分:7)
我曾经遇到过这个问题,这就是我提出的问题(不是最优的,但是有效)
---
# 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 %}
答案 2 :(得分:2)
我现在自己开始工作了。我对解决方案不太满意,但它会做:
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,')}
答案 3 :(得分:2)
这可以帮我。不依赖接口名称
- main_nodes_ips: "{{ groups['mainnodes'] | map('extract', hostvars, ['ansible_default_ipv4', 'address']) | join(',') }}"
答案 4 :(得分:1)
我找到了#34;唯一的方法"当以下任何一种情况属实时,加入其他小组的错误:
如下:
{% set ips=[] %}{% for host in groups['othergroup'] %}{% if ips.append(lookup('dig', host)) %}{% endif %}{% endfor %}{{ ips }}
在运行ansible的机器上需要dnspython,通过
安装sudo apt-get install python-dnspython
如果有人知道一个更好的方法,我会喜欢摆脱这种可憎的行为。
答案 5 :(得分:1)
我是通过在剧本中使用安莎事实来做到这一点的。 该playbook采用ansible_all_ipv4_addresses列表和ansible_nodename(实际上是完全限定的域名),遍历所有主机并将数据保存在localhost上的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
答案 6 :(得分:0)
- name: Create List of nodes to be added into Cluster
set_fact: nodelist={%for host in groups['mygroup']%}"{{hostvars[host].ansible_eth0.ipv4.address}}"{% if not loop.last %},{% endif %}{% endfor %}
- debug: msg=[{{nodelist}}]
- name: Set Cluster node list in config file
lineinfile:
path: "/etc/myfonfig.cfg"
line: "hosts: [{{ nodelist }}]"
作为结果,您将在配置文件中包含以下行:
hosts: ["192.168.126.38","192.168.126.39","192.168.126.40"]
答案 7 :(得分:0)
这是我为了不依赖eth0
而做的事情(感谢ADV-IT的回答):
- name: gathering facts
hosts: mainnodes
gather_facts: true
- hosts: mainnodes
tasks:
- name: Create List of nodes
set_fact: nodelist={%for host in groups['mainnodes']%}"{{hostvars[host]['ansible_env'].SSH_CONNECTION.split(' ')[2]}}"{% if not loop.last %},{% endif %}{% endfor %}