如何在ansible中从变量文件中调用类似值的列表

问题描述

我有一个有趣的剧本,其中有多个参数要传递,有时足够长,使游戏看起来很胖,因此我正在考虑创建一个变量文件并在该文件中保留所有可能的值以便调用它们从那里可以使游戏变得苗条,同时避免更改剧本,我们可以对变量文件进行调整,例如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_groupazure_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'"
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...