如何通过Terraform仅基于CSV中maxview字段值为1的条目创建虚拟机?
实现仅创建CSV中maxview为1的虚拟机
当然可以实现这个需求!你只需要先对CSV读取的数据进行过滤,仅保留maxview字段值为"1"的条目,再基于过滤后的列表创建虚拟机即可。下面是具体的修改方案:
1. 过滤CSV数据
首先修改locals块,先读取原始CSV数据,再添加过滤逻辑筛选出符合条件的实例:
locals { # 读取原始CSV数据(保留原始数据,方便后续扩展) raw_instances = csvdecode(file("./data/sys-${local.environment}.csv")) # 过滤出maxview字段为"1"的条目 # 注意:csvdecode会把所有CSV字段解析为字符串,所以要匹配字符串"1"而非数字1 instances = [for inst in local.raw_instances : inst if inst.maxview == "1"] # 原有的vsphere_hn配置保持不变 vsphere_hn = { domain = "hn" dev1 = { app_datastores = ["sata_ssd_storage_140-1"] } eu1 = { app_datastores = ["sata_ssd_storage_140-1"] } } }
2. 基于过滤后的列表创建虚拟机
推荐使用for_each替代count来创建虚拟机(count依赖列表索引,当CSV条目顺序变化时可能导致不必要的VM销毁重建,for_each使用唯一键更稳定):
// VMs module "vm-hn-maxview-maxview_vm" { # 使用for_each遍历过滤后的实例,以node字段作为唯一标识键 for_each = { for inst in local.instances : inst.node => inst } providers = { vsphere = vsphere.vcadmin } # 注意:将原有的local.instances[count.index]替换为each.value name = "${each.value.node}.${local.vsphere_hn.domain}.${var.dns_local_name[local.environment]}" annotation = "Managed by Terraform" dc = var.vsphere_core_datacenter_name[local.environment] # 这里注意:原代码用count.index取datastore可能会因过滤后列表长度变化导致越界,这里先取第一个datastore,可根据实际需求调整 datastore = local.vsphere_hn[local.environment].app_datastores[0] template = var.centos7_vsphere_template[local.environment].template resource_pool_vapp = vsphere_vapp_container.vm-hn-maxview-vapp.id customize_name = "maxview" customize_domain = "${each.value.node}.${local.vsphere_hn.domain}.${var.dns_local_name[local.environment]}" cpu_number = 2 num_cores_per_socket = 1 ram_size = 2048 network = { "${var.network_vlan_maxview_name[local.environment]}" = ["${var.network_address_prefix[local.environment]}.8.${each.value.node_id}"] } network_gateway = "${var.network_address_prefix[local.environment]}.9.254" network_submask = ["${var.network_address_submask_maxview[local.environment]}"] data_disk = { disk1 = { size_gb = 10, thin_provisioned = false, data_disk_scsi_controller = 0, } } }
关键说明
- 你之前尝试的
for_each写法有误:{ for inst in local.instances : inst.node => inst } ? 1:0不符合Terraform语法,正确的过滤逻辑是在for表达式中添加if条件,直接生成仅包含目标实例的map/列表。 csvdecode会将CSV中所有字段解析为字符串类型,所以判断时要使用inst.maxview == "1"而非inst.maxview == 1。- 如果坚持使用
count,只需将count = length(local.instances)即可(因为local.instances已经是过滤后的列表),但依然推荐for_each以避免不必要的资源变动。
内容的提问来源于stack exchange,提问作者onev
相关产品推荐
相关产品推荐

