我正在编写的剧本可以在多个环境中运行,并且每个环境都在不同的子网上。
我正在编写一个条件块,只有当主机 IP 处于我在条件中指定的范围内时,该块才会运行
例如
如果ansible_default_ipv4.address
位于以下 IP 之一
- 192.168.4.41 或 192.168.4.42 或 192.168.4.81 或 192.168.4.82
- 192.168.5.41 或 192.168.5.42 或 192.168.5.81 或 192.168.5.82
- 192.168.6.41 或 192.168.6.42 或 192.168.6.81 或 192.168.6.82
- ... 等等
我可以逐个添加每个 IP,但这似乎效率低下、重复性强,并且会使剧本冗长。有没有办法在条件中添加范围?
此外,如果可能的话,我如何强制仅在 GroupA 或 GroupB 或 GroupC 服务器上运行?
答案1
从技术上讲,您的示例中没有 IP 范围,只有不同子网上的离散 IP 地址。
在这种情况下,我会列出我想要使用的前缀和后缀,并使用product
筛选和映射这join
筛选。
prefixes:
- 192.168.4
- 192.168.5
- 192.168.6
suffixes:
- 41
- 42
- 82
all_ips: "{{ prefixes | product(suffixes) | map('join', '.') }}"
当展开时
"all_ips": [
"192.168.4.41",
"192.168.4.42",
"192.168.4.82",
"192.168.5.41",
"192.168.5.42",
"192.168.5.82",
"192.168.6.41",
"192.168.6.42",
"192.168.6.82"
]
然后您可以在条件中使用该表达式:
when: ansible_default_ipv4.address in all_ips
现在,如果我理解正确的话,您希望特定子网上的每组 IP 都成为特定组的标记。您可以在剧本中动态地执行此操作。下面是一个例子,让您了解全局概念。我只对其进行了部分测试,因此可能会有一些遗留的拼写错误(如果很明显,请告诉我或编辑答案)。请注意,该prefixes
变量与上面的变量略有不同,以适应所需的组声明。
- name: gather facts from all host and create dynamic groups
hosts: all
vars:
prefixes:
192.168.4: dyn_group_A
192.168.5: dyn_group_B
192.168.6: dyn_group_C
suffixes:
- 41
- 42
- 82
all_ips: "{{ prefixes.keys() | product(suffixes) | map('join', '.') }}"
tasks:
- name: tag needed targets with a fact
vars:
host_prefix: "{{ (ansible_default_ipv4.address | split('.'))[:3] | join('.') }}"
ansible.builtin.set_fact:
my_dyn_group: "{{ prefixes[host_prefix] }}"
when: ansible_default_ipv4.address in all_ips
- name: create overall and specific dynamic groups from tagged targets
ansible.builtin.add_host:
name: "{{ item.inventory_hostname }}"
groups:
- dyn_group_overall
- "{{ item.my_dyn_group }}"
loop: "{{ ansible_play_hosts | map('extract', hostvars) | selectattr('my_dyn_group', 'defined') }}"
loop_control:
label: "{{ item.inventory_hostname }}"
- name: a single task that would play on all valid hosts and skip on others
ansible.builtin.debug:
msg: "I would run on {{ inventory_hostname }}"
when: inventory_hostname in groups['dyn_group_overall']
- name: a single task that would run only on group B hosts and skip on others
ansible.builtin.debug:
msg: "I would run on {{ inventory_hostname }}"
when: inventory_hostname in groups['dyn_group_B']
# Note that limiting a task by condition to a group
# in a wider targeted play as above is usually not a good practice.
# It is much more efficient on most occasion to target
# the needed group in a specific play
- name: tasks to be played on all matched hosts
hosts: dyn_group_overall
# Facts are already gathered above so skip it
gather_facts: false
tasks:
- ansible.builtin.debug:
msg: This will only play on targeted host
- name: tasks to be played on hosts in group C
hosts: dyn_group_C
gather_facts: false
tasks:
- ansible.builtin.debug:
msg: This will only play on hosts in group C