Terraform 参数必须是地图或对象,得到 "string"

Terraform arguments must be maps or objects, got "string"

预期行为

我正在尝试遍历 var.vm_settings 但似乎不合作。 该错误没有意义,因为输入变量所需的类型是“string”

实际行为

抛出错误(参见错误输出)

错误输出

Error: Error in function call

  on ..\main.tf line 4, in locals:
   4:   vm_settings = zipmap(keys(var.vm_settings), [for vm_setting in values(var.vm_settings) : merge(var.vm_defaults, vm_setting)])
    |----------------
    | var.vm_defaults is object with 12 attributes

Call to function "merge" failed: arguments must be maps or objects, got
"string".

Terraform(和 AzureRM 提供程序)版本

受影响的资源

Terraform 配置文件

Main.tf

locals {
  vm_settings = zipmap(keys(var.vm_settings), [for vm_setting in values(var.vm_settings) : merge(var.vm_defaults, vm_setting)])
}

resource "azurerm_linux_virtual_machine" "oracle_db" {
  for_each = local.vm_settings

  name                            = each.key
  resource_group_name             = var.resource_group_name
  location                        = var.location
  size                            = each.value.size
  admin_username                  = each.value.admin_username
  admin_password                  = local.admin_password
  disable_password_authentication = each.value.disable_password_authentication
  priority                        = each.value.priority
  eviction_policy                 = each.value.eviction_policy
  zone                            = each.value.zone
  network_interface_ids           = [azurerm_network_interface.nic.id, ]

  admin_ssh_key {
    username   = each.value.admin_ssh_key.username
    public_key = each.value.admin_ssh_key.public_key
  }

  identity {
    type = each.value.identity.type
  }

  os_disk {
    caching              = each.value.os_disk.caching
    storage_account_type = each.value.os_disk.storage_account_type
  }

  source_image_reference {
    publisher = each.value.source_image_reference.publisher
    offer     = each.value.source_image_reference.offer
    sku       = each.value.source_image_reference.sku
    version   = each.value.source_image_reference.version
  }

  boot_diagnostics {
    storage_account_uri = each.value.boot_diagnostics.storage_account_uri
  }
}


Variables.tf

variable "vm_settings" {
  description = "Map of vm's to create (keys are vm names). Allowed values are the same as for vm_defaults."
  type        = any
  default     = {}
}

variable "vm_defaults" {
  type = object({
    name                            = string
    size                            = string
    admin_username                  = string
    admin_password                  = string
    disable_password_authentication = string
    priority                        = string
    eviction_policy                 = string
    identity = object({
      type = string
    })
    admin_ssh_key = object({
      username   = string
      public_key = string
    })
    os_disk = object({
      name                 = string
      caching              = string
      storage_account_type = string
    })
    source_image_reference = object({
      publisher = string
      offer     = string
      sku       = string
      version   = string
    })
    boot_diagnostics = object({
      storage_account_uri = string
    })
  })
  default = {
    name                            = null
    size                            = null
    admin_username                  = null
    admin_password                  = ""
    disable_password_authentication = null
    priority                        = null
    eviction_policy                 = null
    identity = {
      type = null
    }
    admin_ssh_key = {
      username   = ""
      public_key = null
    }
    os_disk = {
      name                 = null
      caching              = null
      storage_account_type = null
    }
    # Image used to create the virtual machines.
    source_image_reference = {
      publisher = ""
      offer     = ""
      sku       = ""
      version   = ""
    }
    boot_diagnostics = {
      storage_account_uri = ""
    }
  }
  description = <<EOT
virtual machine default settings (only applied to virtual machine settings managed within this module)
    vm_settings = {
    size                            = (Required) The SKU which should be used for this Virtual Machine, such as Standard_F2.
    admin_username                  = (Required) The username of the local administrator used for the Virtual Machine. Changing this forces a new resource to be created.ring
    admin_password                  = (Optional) The Password which should be used for the local-administrator on this Virtual Machine. Changing this forces a new resource to be created.
    disable_password_authentication = (Optional) Should Password Authentication be disabled on this Virtual Machine? Defaults to true. Changing this forces a new resource to be created.

    # Spot VM to save money
    priority        = (Optional) Specifies the priority of this Virtual Machine. Possible values are Regular and Spot. Defaults to Regular. Changing this forces a new resource to be created.
    eviction_policy = (Optional) Specifies what should happen when the Virtual Machine is evicted for price reasons when using a Spot instance. At this time the only supported value is Deallocate. Changing this forces a new resource to be created. This can only be configured when priority is set to Spot.

    # type of Managed Identity which should be assigned to the Linux Virtual Machine
    identity = {
      type = (Required) The type of Managed Identity which should be assigned to the Linux Virtual Machine. Possible values are SystemAssigned, UserAssigned and SystemAssigned, UserAssigned.
    }

    # SSH key
    admin_ssh_key = {
      username   = (Required) The Public Key which should be used for authentication, which needs to be at least 2048-bit and in ssh-rsa format. Changing this forces a new resource to be created.
      public_key = (Required) The Username for which this Public SSH Key should be configured. Changing this forces a new resource to be created.
    }

    # Internal OS disk
    os_disk = {
      name                 = (Required) The Type of Caching which should be used for the Internal OS Disk. Possible values are None, ReadOnly and ReadWrite.
      caching              = (Required) The Type of Caching which should be used for the Internal OS Disk. Possible values are None, ReadOnly and ReadWrite.
      storage_account_type = (Required) The Type of Storage Account which should back this the Internal OS Disk. Possible values are Standard_LRS, StandardSSD_LRS and Premium_LRS. Changing this forces a new resource to be created.
    }

    # Image used to create the virtual machines.
    source_image_reference = {
      publisher = (Optional) Specifies the publisher of the image used to create the virtual machines.
      offer     = (Optional) Specifies the offer of the image used to create the virtual machines.
      sku       = (Optional) Specifies the SKU of the image used to create the virtual machines.
      version   = (Optional) Specifies the version of the image used to create the virtual machines.
    }

    boot_diagnostics = {
      storage_account_uri = (Optional) The Primary/Secondary Endpoint for the Azure Storage Account which should be used to store Boot Diagnostics, including Console Output and Screenshots from the Hypervisor. Passing a null value will utilize a Managed Storage Account to store Boot Diagnostics.
    }
  }
EOT
}

通常如果你有一个默认地图并且你想将它与用户提供的地图结合起来,以下就足够了:

merge(var.vm_defaults, var.vm_settings)

以上将使用来自 var.vm_settings 的值,其他所有内容将来自 var.vm_defaults.

所以你的 local.vm_settings 将是:

locals {
  vm_settings = merge(var.vm_defaults, var.vm_settings)
}