在列表中获取特定的事实
Getting specific ansible facts in a list
我目前正在尝试自动创建反亲和性规则以在 VMware 中部署各种应用程序。我一直在像这样使用 drs_rule 模块:
- name: Create DRS Anti-Affinity Rule for appX
vmware_vm_vm_drs_rule:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
cluster_name: '{{ vsphere_cluster }}'
enabled: True
vms:
-appXa
-appXb
-appXc
drs_rule_name: appX_rule
mandatory: True
affinity_rule: False
delegate_to: localhost
run_once: True
但是,VM 的确切数量可能因部署而异。因此,我需要能够动态地提取这些信息。这是我能找到的最接近我需要的东西:
- name: Create DRS Anti-Affinity Rule for appX
vmware_vm_vm_drs_rule:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
cluster_name: '{{ vsphere_cluster }}'
enabled: True
vms: "{{ item }}"
drs_rule_name: appX_rule
mandatory: True
affinity_rule: False
loop: "{{ groups['appX'] }}"
delegate_to: localhost
run_once: True
虽然这确实会从我的清单文件中为该组提取 IP 地址,但我需要提取 VM 名称(即主机名)才能与此模块一起使用。有没有办法在剧本中制作这样的作品?基本上是让它 return 主机名字符串列表,这样我就可以将它插入到这个模块中。
# ansible appX-i inventory -m setup -a "filter=ansible_hostname"
xxx.xxx.xxx.xxx | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "appXa"
},
"changed": false
}
xxx.xxx.xxx.xxx | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "appXb"
},
"changed": false
}
xxx.xxx.xxx.xxx | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "appXc"
},
"changed": false
}
非常感谢:-)
编辑:我能够提取主机名。这归功于 mdaniel
- name: Create DRS Anti-Affinity Rule for appX
vmware_vm_vm_drs_rule:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
cluster_name: '{{ vsphere_cluster }}'
enabled: True
vms: "{{ item }}"
drs_rule_name: appX_rule
mandatory: True
affinity_rule: False
loop: "{{ groups['appX'] | map('extract', hostvars, 'ansible_hostname') }}"
delegate_to: localhost
run_once: True
然而,我们实际上需要格式为“hostname_IP”的项目,例如“appXa_192.168.1.100”。有没有办法提取 IP 地址并将它们之间的下划线连接在同一行上?
此外,使用 map/extract 提取 IP 时遇到一些问题,因为 ansible facts 以字典格式提供。即
"ansible_default_ipv4": {
"address": "192.169.1.100",
我可以使用列表中的 ansible_all_ipv4_addresses,但如果我们将多个 IP 附加到同一台机器,这可能会带来复杂性。
However, we actually need the items in the format of "hostname_IP" e.g. "appXa_192.168.1.100". Is there a way to pull the IP address and concatenate an underscore in between them all on the same line?
是也不是;一次完成会有些愚蠢,因为在 jinja2 中没有 lambda:
等价物,但是使用 with_together:
lookup 可能会做你想做的,因为它会给任务访问主机名,匹配 ip,然后允许您根据需要廉价地将它们一起加入。 together
查找应该可以安全地用于将它们配对,因为(据我所知)groups["appX"]
是确定性排序的,因此每个 map
应用程序将发生在同一个列表
- debug:
msg: |
the hostname is '{{ item.0 }}'
its IP is '{{ item.1 }}'
composite key is '{{ item.0 ~ "_" ~ item.1 }}'
with_together:
- '{{ groups["appX"] | map("extract", hostvars, "ansible_hostname") | list }}'
- '{{ groups["appX"] | map("extract", hostvars, ["ansible_default_ipv4", "address"]) | list }}'
我目前正在尝试自动创建反亲和性规则以在 VMware 中部署各种应用程序。我一直在像这样使用 drs_rule 模块:
- name: Create DRS Anti-Affinity Rule for appX
vmware_vm_vm_drs_rule:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
cluster_name: '{{ vsphere_cluster }}'
enabled: True
vms:
-appXa
-appXb
-appXc
drs_rule_name: appX_rule
mandatory: True
affinity_rule: False
delegate_to: localhost
run_once: True
但是,VM 的确切数量可能因部署而异。因此,我需要能够动态地提取这些信息。这是我能找到的最接近我需要的东西:
- name: Create DRS Anti-Affinity Rule for appX
vmware_vm_vm_drs_rule:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
cluster_name: '{{ vsphere_cluster }}'
enabled: True
vms: "{{ item }}"
drs_rule_name: appX_rule
mandatory: True
affinity_rule: False
loop: "{{ groups['appX'] }}"
delegate_to: localhost
run_once: True
虽然这确实会从我的清单文件中为该组提取 IP 地址,但我需要提取 VM 名称(即主机名)才能与此模块一起使用。有没有办法在剧本中制作这样的作品?基本上是让它 return 主机名字符串列表,这样我就可以将它插入到这个模块中。
# ansible appX-i inventory -m setup -a "filter=ansible_hostname"
xxx.xxx.xxx.xxx | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "appXa"
},
"changed": false
}
xxx.xxx.xxx.xxx | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "appXb"
},
"changed": false
}
xxx.xxx.xxx.xxx | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "appXc"
},
"changed": false
}
非常感谢:-)
编辑:我能够提取主机名。这归功于 mdaniel
- name: Create DRS Anti-Affinity Rule for appX
vmware_vm_vm_drs_rule:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
cluster_name: '{{ vsphere_cluster }}'
enabled: True
vms: "{{ item }}"
drs_rule_name: appX_rule
mandatory: True
affinity_rule: False
loop: "{{ groups['appX'] | map('extract', hostvars, 'ansible_hostname') }}"
delegate_to: localhost
run_once: True
然而,我们实际上需要格式为“hostname_IP”的项目,例如“appXa_192.168.1.100”。有没有办法提取 IP 地址并将它们之间的下划线连接在同一行上?
此外,使用 map/extract 提取 IP 时遇到一些问题,因为 ansible facts 以字典格式提供。即
"ansible_default_ipv4": {
"address": "192.169.1.100",
我可以使用列表中的 ansible_all_ipv4_addresses,但如果我们将多个 IP 附加到同一台机器,这可能会带来复杂性。
However, we actually need the items in the format of "hostname_IP" e.g. "appXa_192.168.1.100". Is there a way to pull the IP address and concatenate an underscore in between them all on the same line?
是也不是;一次完成会有些愚蠢,因为在 jinja2 中没有 lambda:
等价物,但是使用 with_together:
lookup 可能会做你想做的,因为它会给任务访问主机名,匹配 ip,然后允许您根据需要廉价地将它们一起加入。 together
查找应该可以安全地用于将它们配对,因为(据我所知)groups["appX"]
是确定性排序的,因此每个 map
应用程序将发生在同一个列表
- debug:
msg: |
the hostname is '{{ item.0 }}'
its IP is '{{ item.1 }}'
composite key is '{{ item.0 ~ "_" ~ item.1 }}'
with_together:
- '{{ groups["appX"] | map("extract", hostvars, "ansible_hostname") | list }}'
- '{{ groups["appX"] | map("extract", hostvars, ["ansible_default_ipv4", "address"]) | list }}'