0
votes

I'm creating Azure VM extension resources azurerm_virtual_machine_extension using terraform. However, I'm stuck with below use-case whether I can dynamically create settings block?

variable "test_string" {
  description = "boolean var to attach VM nics to lb"
  type        = string
  default     = ""
}

variable "test_script" {
  description = "script locally"
  type        = string
  default     = ""
}

variable "file_uri" {
  description = "script to download"
  type        = string
  default     = "https://example.com/azure-tests/custom_script.sh"
}


resource "azurerm_virtual_machine_extension" "ama_vm_extension" {

  name                 = "tst-vm-extension"
  virtual_machine_id   = "xxxxx-xxxx-xxxxx"
  publisher            = "Microsoft.Azure.Extensions"
  type                 = "CustomScript"
  type_handler_version = "2.0"

  dynamic settings = <<SETTINGS
  {
    count = var.file_uri != "" ? 1: 0
    "commandToExecute": "sh ${basename(var.file_uri)}",
    "fileUris": ["${var.file_uri}"]
  }
  SETTINGS

  dynamic settings = <<SETTINGS
  {
     count = var.test_string != "" ? 1: 0
     content {
       "commandToExecute": "${var.test_string}"
     }
  }
  SETTINGS

  dynamic settings = <<SETTINGS
  {
     count = var.test_script != "" ? 1: 0
     content {
       "script": "${base64encode(var.test_string)}"
     }
  }
  SETTINGS

}

In the above code, I would like to control the resource behavior with test_string, test_script, file_uri vars. However, terraform allows only one settings block in the resource and I don't know how I can use dynamic block feature here. As we have SETTINGS string in the end.

Your help is much appreciated here.

Thanks, Harsha

1
If the three settings are mutually exclusive, then have three azurerm_virtual_machine_extension eliminate the dynamic block and move the count to the resource itself. If they are not mutually exclusive, then use an object variable and convert it to json. I don't have time to test this, but that is where I would start.Christian Pearce

1 Answers

2
votes

Terraform's dynamic blocks are meant to be used with nested blocks in resources. Since setting is just a string, you can just use regular conditionals to set the value of setting.

I would probably do something like this:

locals {
  file_uri_settings = jsonencode({
    "commandToExecute" = "sh ${basename(var.file_uri)}",
    "fileUris"         = [var.file_uri]
  })
  test_string_settings = jsonencode({
    "commandToExecute" = var.test_string
  })
  test_script_settings = jsonencode({
    "script" = base64encode(var.test_script)
  })
}

resource "azurerm_virtual_machine_extension" "example" {
  // ...
  settings = var.test_string != "" ? local.test_string_settings : (var.test_script != "" ? local.test_script_settings : local.file_uri_settings)
  // ...
}

Just to clean it up, I pull the different options into a local block. Then you can chain ternary operators to select the correct string to use.