【问题标题】:Exclude list of numbers from Range function in Terraform从 Terraform 中的 Range 函数中排除数字列表
【发布时间】:2021-12-03 20:11:55
【问题描述】:

我正在尝试使用 for_each 循环在 Azure 中创建多个 VM。假设 VM 1-100。但是,会有删除请求,即 VM 编号 50。

我有两个问题:

terraform_azure> terraform state list
module.edit_vms.azurerm_linux_virtual_machine.test_seat["test-vm-1"]

terraform state rm module.edit_vms.azurerm_linux_virtual_machine.test_seat["test-vm-1"]
zsh: no matches found: module.edit_vms.azurerm_linux_virtual_machine.test_seat[test-vm-1]
  1. 当我尝试从 Terraform 状态删除 VM 50 时,出现上述错误。我不明白为什么在 terraform state list 命令下列出资源时没有找到匹配项

  2. 有没有办法删除 50 号 VM 并将 VM 计数设置为 1 -> 101 并防止 terraform 重新创建 50 号 VM?如果从状态文件中删除虚拟机不是一个好习惯,那么如果我可以在代码中指定我希望它被销毁并且在将来应用时不重新创建会更好。

这是我的变量.tf

variable "edit_seat_spec" {
    description = "VM details"
    type = list
    default = [{
        resource_group_name = "my_rg"
        server_name = "test-vm"
        server_size = "Standard_B2s"
        location = "East US"
        vnet = "test_vnet"
        subnet_name = "default"
        username = "username"
        password = "password"
        vm_count = "4"
    }]
}

还有main.tf

locals{
      edit_seat = [
        for edit in var.edit_seat_spec : [
          for i in range(1, edit.vm_count) : {
            name = "${edit.server_name}-${i}"
            resource_group = edit.resource_group_name
            vnet = edit.vnet
            nic = "${edit.server_name}-${i}-nic"
            location            = edit.location
            subnet_name = edit.subnet_name
            size                = edit.server_size
            admin_username      = edit.username
            admin_password = edit.password
            }
        ]
      ]
    }
    
locals {
    edit_vm = flatten(local.edit_seat)
  }

    resource "azurerm_linux_virtual_machine" "vm" {
    for_each = {for edit in local.edit_vm: edit.name => edit}
            name = each.value.name
            resource_group_name = each.value.resource_group
            location            = each.value.location
            size                = each.value.size
            admin_username      = each.value.admin_username
            admin_password = each.value.admin_password
            disable_password_authentication = false
            network_interface_ids = [azurerm_network_interface.edit_seat_nic[each.key].id]
    os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
    }
    
      source_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "16.04-LTS"
        version   = "latest"
      }
    }

【问题讨论】:

    标签: azure foreach terraform


    【解决方案1】:

    您可以过滤forwith the help of if statement 中的元素。

    另外请注意,range 不会包含上限:

    limit的解释取决于step的方向:对于一个正步,当下一个数字大于或等于limit时序列完成。

    因此,如果您想要从 1 到 100 的范围,则需要 range(1, var.variable_that_contains_100 + 1)
    因此,如果您想在从 1 到 100 的步进中跳过一个元素,则需要将上限设为 102。


    这里是一个例子,请求 5 个元素,跳过 3 个,为简洁起见:

    variable "vm_count" {
      default = 5 
    }
    
    output "test" {
      value = [for i in range(1, var.vm_count + 2) : {
        name = "some-server-${i}"
      } if i != 3]
    }
    

    这会产生:

    Changes to Outputs:
      + test = [
          + {
              + name = "some-server-1"
            },
          + {
              + name = "some-server-2"
            },
          + {
              + name = "some-server-4"
            },
          + {
              + name = "some-server-5"
            },
          + {
              + name = "some-server-6"
            },
        ]
    

    如果你想排除一个列表,正如问题的标题所说,你可以在条件中使用contains,然后在排除列表的length加一的基础上增加上限。

    variable "vm_count" {
      default = 5 
    }
    
    variable "exclusion" {
      default = [2,4,5]
    }
    
    output "test" {
      value = [for i in range(1, var.vm_count + length(var.exclusion) + 1) : {
        name = "some-server-${i}"
      } if !contains(var.exclusion, i)]
    }
    

    这给出了:

    Changes to Outputs:
      + test = [
          + {
              + name = "some-server-1"
            },
          + {
              + name = "some-server-3"
            },
          + {
              + name = "some-server-6"
            },
          + {
              + name = "some-server-7"
            },
          + {
              + name = "some-server-8"
            },
        ]
    

    当然,在这里,您开始遇到边缘情况,如果排除列表包含超出范围的数字,您可能会拥有过多的虚拟机,但这一切都取决于您的用例的复杂性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-12
      • 2012-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-14
      • 2020-01-11
      相关资源
      最近更新 更多