问题描述
我有一个有趣的剧本,其中有多个参数要传递,有时足够长,使游戏看起来很胖,因此我正在考虑创建一个变量文件并在该文件中保留所有可能的值以便调用它们从那里可以使游戏变得苗条,同时避免更改剧本,我们可以对变量文件进行调整,例如cloud_vars.yml
。
下面是我的变量文件:
$ cat azure_vars.yml
---
azure_subnet_name: "infra"
azure_os_disk_type: Standard_LRS
azure_nprod_vnet: "/subscriptions/XXXXXXXX-XXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg001/providers/Microsoft.Network/virtualNetworks/vnet"
azure_prod03_vnet: "/subscriptions/XXXXXXXX-XXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg002/providers/Microsoft.Network/virtualNetworks/vnet"
azure_prod02_vnet: "/subscriptions/XXXXXXXX-XXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/rg003/providers/Microsoft.Network/virtualNetworks/vnet"
public_key: "ssh-rsa:XXXX "
azure_image_id: "/subscriptions/XXXXXXXX-XXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/mgt01-rg001/providers/Microsoft.Compute/galleries/imagegallery/images/myimage/versions/0.0.3"
# Azure domains
azure_domains:
- "eu-azrc1"
- "us-azrc2"
- "us-sea01"
# Resource group
azure_res_group:
- "rg001"
- "rg002"
- "rg003"
# Azure locations
azure_location:
- "westus2"
- "westeurope"
- "southcentralus"
...
下方的游戏书
下面是将facts
设置为稍后在剧本中使用的剧本,我很想知道如何使用azure_domains
azure_res_group
和azure_location
变量在那里定义的可变文件,到现在为止,我已经硬编码了名称和位置等。
$ cat new_vm_Creation.yml
---
- name: create azure vm
hosts: localhost
connection: local
tasks:
- include_vars: azure_vars.yml
- set_fact:
host: "{{ azure_vm_name.split('.') }}"
- set_fact:
azure_domain: "{{ host.1 }}.{{ host.2 }}"
- name: azure_domain
debug:
msg: "{{ azure_domain }}"
- set_fact:
azure_location: "westus2"
when: azure_domain == "us-sea01"
- set_fact:
azure_location: "westeurope"
when: azure_domain == "eu-azrc1"
- set_fact:
azure_location: "southcentralus"
when: azure_domain == "us-azrc2"
- name: azure_location
debug:
msg: "{{ azure_location }}"
- set_fact:
res_group: "rg001"
when: azure_domain == "us-sea01"
- set_fact:
res_group: "rg002"
when: azure_domain == "eu-azrc1"
- set_fact:
res_group: "rg003"
when: azure_domain == "us-azrc2"
- name: Resource Group
debug:
msg: "{{ res_group }}"
- set_fact:
vnet: "{{ azure_nprod_vnet }}"
when: azure_domain == "us-sea01"
- set_fact:
vnet: "{{ azure_prod03_vnet }}"
when: azure_domain == "eu-azrc1"
- set_fact:
vnet: "{{ azure_prod02_vnet }}"
when: azure_domain == "us-azrc2"
- name: Vnet
debug:
msg: "{{ vnet }}"
- name: create network security group that allows ssh
azure_rm_securitygroup:
resource_group: "{{ res_group }}"
location: "{{ location }}"
name: "{{ azure_vm_name }}-nsg"
rules:
- name: ssh
protocol: Tcp
destination_port_range: 22
access: Allow
priority: 100
direction: Inbound
- name: create virtual network interface card
azure_rm_networkinterface:
resource_group: "{{ res_group }}"
location: "{{ location }}"
name: "{{ azure_vm_name }}-nic1"
subnet: "{{ azure_subnet_name }}"
virtual_network: "{{ vnet }}"
security_group: "{{ azure_vm_name }}-nsg"
enable_accelerated_networking: true
public_ip: no
state: present
- name: create vm
azure_rm_virtualmachine:
resource_group: "{{ res_group }}"
location: "{{ location }}"
name: "{{ azure_vm_name }}"
vm_size: Standard_D4s_v3
admin_username: some_id
ssh_password_enabled: false
ssh_public_keys:
- path: /home/some_id/.ssh/authorized_keys
key_data: "{{ public_key }}"
network_interfaces: "{{ azure_vm_name }}-nic1"
os_disk_name: "{{ azure_vm_name }}-osdisk"
managed_disk_type: "{{ azure_os_disk_type }}"
os_disk_caching: ReadWrite
os_type: Linux
image:
id: "{{ azure_image_id }}"
publisher: redhat
plan:
name: rhel-lvm78
product: rhel-byos
publisher: redhat
...
解决方法
您可以在azure_vars.yml
文件中定义那些结构,包括jinja2模板,但要知道将它们放在vars文件中不能解决它们-jinja2模板评估在ansible中是递归的,因此第一次使用它们时,您将看到成功或可怕的"VARIABLE IS NOT DEFINED!"
给出{p的azure_vars.yml
azure_nprod_vnet: "/subscriptions/alpha-nprod/resourceGroups/rg001/providers/Microsoft.Network/virtualNetworks/vnet"
azure_prod03_vnet: "/subscriptions/beta-prod03/resourceGroups/rg002/providers/Microsoft.Network/virtualNetworks/vnet"
azure_prod02_vnet: "/subscriptions/charlie-prod02/resourceGroups/rg003/providers/Microsoft.Network/virtualNetworks/vnet"
things_by_azure_domain:
"us-sea01":
azure_location: "westus2"
res_group: "rg001"
vnet: "{{ azure_nprod_vnet }}"
"eu-azrc1":
azure_location: "westeurope"
res_group: "rg002"
vnet: "{{ azure_prod03_vnet }}"
"us-azrc2":
azure_location: "southcentralus"
res_group: "rg003"
vnet: "{{ azure_prod02_vnet }}"
vnet: "{{ things_by_azure_domain[azure_domain].vnet }}"
然后将azure_domain
放入范围后,使用{{ vnet }}
将递归地计算该表达式:
tasks:
# OBSERVE that we can include this,even with `azure_domain` not yet defined
# because `include_vars` DOES NOT evaluate those jinja2 expressions
- include_vars: azure_vars.yml
- set_fact:
azure_domain: us-azrc2
- debug:
var: vnet
屈服
ok: [localhost] => {
"vnet": "/subscriptions/charlie-prod02/resourceGroups/rg003/providers/Microsoft.Network/virtualNetworks/vnet"
但是,正如我所说,您将需要谨慎,因为胖手指的结局不会很好:
tasks:
- include_vars: azure_vars.yml
- set_fact:
azure_domain: us-yankee-doodle
- debug:
var: vnet
收益
ok: [localhost] => {
"vnet": "VARIABLE IS NOT DEFINED!"
}
但是至少在我的2.9.13版本中,以更高的详细度运行确实暴露了根本原因:
ok: [localhost] => {
"vnet": "VARIABLE IS NOT DEFINED!: 'dict object' has no attribute 'us-yankee-doodle'"
}