I'm trying to iterate through var.vm_settings but doesn't seem to cooperate. The error doesn't make sense because the required type for the input variable is "string"
throws error (see Error output)
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".
azurerm_v2.25.0
terraform v0.13.0
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
}
Usually if you have a default map and you want to combine it with user provided map, the following is enough:
merge(var.vm_defaults, var.vm_settings)
The above will use values from var.vm_settings
, and everything else will be from var.vm_defaults
.
So your local.vm_settings
would be:
locals {
vm_settings = merge(var.vm_defaults, var.vm_settings)
}