terraformterraform-provider-azure

azurerm_virtual_machine does not have attribute identity.0.principal_id


tf 0.11.11 and azurerm 0.31.0

I have been having a go at this for some time now but I am missing something.

I spun up a handful of azurerm_virtual_machine resources without the identity{} block. After the machines are up, I wanted to add one:

./modules/linux/main.tf

resource "azurerm_virtual_machine" "instance" {
  count                 = "${length(compact(var.hosts))}"

  name                  = "${var.hosts[count.index]}"
  location              = "${data.azurerm_resource_group.instance.location}"
  resource_group_name   = "${data.azurerm_resource_group.instance.name}"

  identity {
    type  = "SystemAssigned"
  }
}

output "system_assigned_identity_principal_ids" {
  value       = "${azurerm_virtual_machine.instance.*.identity.0.principal_id}"
  depends_on  = [ "azurerm_virtual_machine.instance" ]
}

./main.tf

module "linuxvm" {
  source = "./modules/linux"

  hosts = [ "${var.hostnames}" ]
  resource_group_name = "${module.sample_resource_group.name}"
  resource_tags = "${var.resource_tags}"
}

During terraform plan, I am getting this error: Error: Error running plan: 1 error(s) occurred:

* module.linuxvm.output.system_assigned_identity_principal_ids: Resource
'azurerm_virtual_machine.instance' does not have attribute 
'identity.0.principal_id' for variable 
'azurerm_virtual_machine.instance.*.identity.0.principal_id'

in the state file, there are no other identity attributes (which is expected). The vm's were first created without the identity block.

[user@host test]$ terraform show | grep iden
  identity.# = 0
  identity.# = 0
  identity.# = 0

If I create vms from scratch, I don't see this issue at all If I comment out the output block, terraform plan goes through. I ran out of things to try at this point.

edit: I have another observation. If I change the output from:

azurerm_virtual_machine.instance.*.identity.0.principal_id

to:

azurerm_virtual_machine.instance.0.identity.0.principal_id

terraform plan goes through. I have 3 hosts, 0-2 goes through, but using splat wouldn't.


Solution

  • Actually, when you create the VMs through Terraform with identity enabled, you cannot output the identity Ids if the VMs. Terraform only exports the VM ID, so you just can output the VM ID. See the VM Attributes.

    The command terraform plan simply check the grammar of your terraform file. So you cannot output the VM identity Id through Terraform. But you can use the help of Azure CLI or Azure PowerShell. For example, you can use the Azure CLI command like this:

    resource "null_resource" "output" {
        provisioner "local-exec" {
            command = "az vm show --ids  ${azurerm_virtual_machine.main.id} --query identity.principalId"
        }
    }
    

    Then the output like this:

    enter image description here

    Hope it helps!

    Update:

    The null_resource only can output the result but cannot pass the result to other resources as a variable. But you can use the Terraform Data Source to pass the result of the script to other resources as a variable. Here is the example:

    script.sh

    #!/bin/bash
    
    eval "$(jq -r '@sh "ids=\(.ids)"')"
    identity_id=$(az vm show --ids $ids --query identity.principalId -o tsv)
    echo -e "{\"identity\":\"$identity_id\"}"
    

    main.tf

    data "azurerm_virtual_machine" "vm" {
        name = "vmName"
        resource_group_name = "groupName"
    }
    
    data "external" "exmaple" {
        program = ["bash", "script.sh"]
    
        query = {
            ids = "${data.azurerm_virtual_machine.vm.id}"
        }
    }
    
    output "identity_id" {
        value = "${data.external.exmaple.result}"
    }