如何根据 set_facts 将多个 ansible 条件合并为一个 [英] How to Club multiple ansible condition into one based on the set_facts
问题描述
在浏览 SO post ansible
配方,我在使用 set_fact
和不同的条件检查时很有趣.但是,我根据我的方法在帖子中回答了但是,我仍然看到可以改进将多个条件用于类似任务,例如确定 location
resource group
和 <代码>vnet.
While going through one of the SO post for ansible
recipe, I got it interesting while using set_fact
with different conditional checks. However, I answered on the post based on my approach However, I still see there can be an improvement to club multiple conditions for similar task like determine the location
resource group
and vnet
.
下面是playbook
和变量文件azure_vars.yml
---
- name: create azure vm
hosts: localhost
connection: local
tasks:
- include_vars: azure_vars.yml
- set_fact:
host: "{{ azure_vm_name.split('.') }}"
- set_fact:
domain: "{{ host.1 }}.{{ host.2 }}"
- name: Domain
debug:
msg: "{{ domain }}"
- set_fact:
location: "{{ azure_location[0] }}"
when: 'domain == azure_domain[0]'
- set_fact:
location: "{{ azure_location[1] }}"
when: 'domain == azure_domain[1]'
- set_fact:
location: "{{ azure_location[2] }}"
when: 'domain == azure_domain[2]'
- name: Location
debug:
msg: "{{ location }}"
- set_fact:
res_group: "{{ azure_res_group[0] }}"
when: 'domain == azure_domain[0]'
- set_fact:
res_group: "{{ azure_res_group[1] }}"
when: 'domain == azure_domain[1]'
- set_fact:
res_group: "{{ azure_res_group[2] }}"
when: 'domain == azure_domain[2]'
- name: Resource Group
debug:
msg: "{{ res_group }}"
- set_fact:
vnet: "{{ azure_nprod_vnet }}"
when: 'domain == azure_domain[0]'
- set_fact:
vnet: "{{ azure_prod03_vnet }}"
when: 'domain == azure_domain[2]'
- set_fact:
vnet: "{{ azure_prod02_vnet }}"
when: 'domain == azure_domain[1]'
- name: Vnet
debug:
msg: "{{ vnet }}"
变量文件
此文件包含将成为 playbook
的一部分并在任务部分下作为 include_vars
导入的所有变量.
Variable Files
This file contains all the variable which will be a part of playbook
and imported as include_vars
under task section.
$ cat azure_vars.yml
---
azure_nprod_vnet: "/subscriptions/XXXXXXXX-XXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg001/providers/Microsoft.Network/virtualNetworks/vnet"
azure_prod02_vnet: "/subscriptions/XXXXXXXX-XXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg003/providers/Microsoft.Network/virtualNetworks/vnet"
azure_prod03_vnet: "/subscriptions/XXXXXXXX-XXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg002/providers/Microsoft.Network/virtualNetworks/vnet"
# Azure domain
azure_domains:
- us-sea01
- us-azrc2
- eu-azrc1
# Resource group
azure_res_group:
- rg001
- rg002
- rg003
# Azure locations
azure_location:
- westus2
- southcentralus
- westeurope
...
预计将低于三合一条件:
- set_fact:
location: "{{ azure_location[0] }}"
when: 'domain == azure_domain[0]'
- set_fact:
location: "{{ azure_location[1] }}"
when: 'domain == azure_domain[1]'
- set_fact:
location: "{{ azure_location[2] }}"
when: 'domain == azure_domain[2]'
可能是这样的:
- set_fact:
location:
- azure_location[0]
- azure_location[1]
- azure_location[2]
when:
- 'domain == azure_domain[0]
- 'domain == azure_domain[1]
- 'domain == azure_domain[2]
推荐答案
您可以使用 loop
和 zip
过滤器,或以较旧的方式,带有 with_together
— 不再推荐,如果您想以后使用 —证明你的剧本.
You can solve this using a loop
and zip
filter, or in the older fashion way, with a with_together
— not recommended anymore, if you want to future-proof your playbooks.
给定剧本:
- hosts: all
vars:
azure_vm_name: foo.bar.us-sea01.whatever.example.org
tasks:
- include_vars: azure_vars.yml
- set_fact:
host: "{{ azure_vm_name.split('.') }}"
- set_fact:
domain: "{{ host.2 }}"
- name: Domain
debug:
msg: "{{ domain }}"
- set_fact:
location: "{{ item.1 }}"
loop: "{{ azure_domains | zip(azure_location) | list }}"
when: 'domain == item.0'
- name: Location
debug:
msg: "{{ location }}"
和变量文件azure_vars.yml:
azure_domains:
- us-sea01
- us-azrc2
- eu-azrc1
azure_location:
- westus2
- southcentralus
- westeurope
总结如下:
PLAY [all] *******************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************
ok: [localhost]
TASK [include_vars] **********************************************************************************************
ok: [localhost]
TASK [set_fact] **************************************************************************************************
ok: [localhost]
TASK [set_fact] **************************************************************************************************
ok: [localhost]
TASK [Domain] ****************************************************************************************************
ok: [localhost] => {
"msg": "us-sea01"
}
TASK [set_fact] **************************************************************************************************
ok: [localhost] => (item=['us-sea01', 'westus2'])
skipping: [localhost] => (item=['us-azrc2', 'southcentralus'])
skipping: [localhost] => (item=['eu-azrc1', 'westeurope'])
TASK [Location] **************************************************************************************************
ok: [localhost] => {
"msg": "westus2"
}
PLAY RECAP *******************************************************************************************************
localhost : ok=7 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
这表示还有另一种可能性,即使用 Python 的 Ansible 能力.您可以使用 index()
列表的方法,用于定位与 azure_domains
中的 domain
相同位置的 azure_location
的元素.
例如如果domain
位于azure_domains
的2
位置,您将在 中获得位置
.2
的元素>azure_location
This said there is another possibility, using Python's capacities of Ansible. You could use the index()
method of a list to target the element of azure_location
being at the same position as domain
in azure_domains
.
e.g. if the domain
is at position 2
of azure_domains
, you'll get the element of position 2
in azure_location
.
给定剧本:
- hosts: all
vars:
azure_vm_name: foo.bar.us-sea01.whatever.example.org
tasks:
- include_vars: azure_vars.yml
- set_fact:
host: "{{ azure_vm_name.split('.') }}"
- set_fact:
domain: "{{ host.2 }}"
- name: Domain
debug:
msg: "{{ domain }}"
- set_fact:
location: "{{ azure_location[azure_domains.index(domain)] }}"
- name: Location
debug:
msg: "{{ location }}"
和相同的变量文件 azure_vars.yml,这产生了回顾:
And the same variable file azure_vars.yml, this yields the recap:
PLAY [all] ******************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************
ok: [localhost]
TASK [include_vars] *********************************************************************************************************
ok: [localhost]
TASK [set_fact] *************************************************************************************************************
ok: [localhost]
TASK [set_fact] *************************************************************************************************************
ok: [localhost]
TASK [Domain] ***************************************************************************************************************
ok: [localhost] => {
"msg": "us-sea01"
}
TASK [set_fact] *************************************************************************************************************
ok: [localhost]
TASK [Location] *************************************************************************************************************
ok: [localhost] => {
"msg": "westus2"
}
PLAY RECAP ******************************************************************************************************************
localhost : ok=7 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
没有使用循环,所以更容易回顾.
Which is not using a loop, so makes an easier recap.
这篇关于如何根据 set_facts 将多个 ansible 条件合并为一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!