Terraform 参数必须是地图或对象,得到“字符串”

Posted

技术标签:

【中文标题】Terraform 参数必须是地图或对象,得到“字符串”【英文标题】:Terraform arguments must be maps or objects, got "string" 【发布时间】:2021-05-07 03:45:10 【问题描述】:

预期行为

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

实际行为

抛出错误(见错误输出)

错误输出

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 提供程序)版本

受影响的资源

azurerm_v2.25.0 terraform v0.13.0

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

【问题讨论】:

【参考方案1】:

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

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)

【讨论】:

以上是关于Terraform 参数必须是地图或对象,得到“字符串”的主要内容,如果未能解决你的问题,请参考以下文章

Terraform:“inputMap”参数的值无效:lookup() 需要地图作为第一个参数

Terraform - 迭代嵌套地图

如何在 terraform 中创建地图

为啥我得到错误count():参数必须是在laravel中实现Countable的数组或对象?

terraform 显示返回 4 个 json 对象

Terraform - 如何将列表转换为地图(如何使用 terraform 获取 AMI 标签)