0
votes

Using Terraform v0.12.9, azurerm provider v1.36.1

Scenario:

  • You have created an image based on a third-party marketplace image.
  • You have published this image to a shared image gallery.
  • You have been able to do so in an automated fashion using Terraform and Azure Devops pipelines. (ex. CIS hardened images)
  • For each of these previous steps you have provided plan information data. if not, you would not be able to create a VM from this image, because there is an extra cost associated with using the marketplace image.

  • Now you want other teams be able to use your image from the Shared Image Gallery through Terraform Automation.

How to get the plan information from the shared image without hard-coding it?

Well, I thought to just retreive the data using a data source using:

data "azurerm_shared_image" "image" {
  name                = var.image_name
  gallery_name        = var.gallery_name
  resource_group_name = var.rsg_name
}

and using the necessary blocks inside the virtual_machine resource like so:

  storage_image_reference {
    id = data.azurerm_shared_image.image.id
  }

  plan {
    name      = data.azurerm_shared_image.image.sku
    publisher = data.azurerm_shared_image.image.publisher
    product   = data.azurerm_shared_image.image.offer
  }

However, I get an error stating:

Error: Unsupported attribute
This object has no argument, nested block, or exported attribute named "sku".

for each sku, publisher and offer.

1

1 Answers

0
votes

We can get a better picture of what we are dealing with to add an output for testing purposes, like so:

output "imagedata" {
  value = data.azurerm_shared_image.image
}

We get an important insight:

imagedata = {
  "description" = ""
  "eula" = ""
  "gallery_name" = [removed]
  "id" = [removed]
  "identifier" = [
    {
      "offer" = "cis-centos-7-l1"
      "publisher" = "center-for-internet-security-inc"
      "sku" = "cis-centos75-l1"
    },
  ]
  "location" = [removed]
  "name" = [removed]
  "os_type" = "Linux"
  "privacy_statement_uri" = ""
  "release_note_uri" = ""
  "resource_group_name" = [removed]
  "tags" = {}
}

Ah now using data.azurerm_shared_image.image.identifier.sku won't just work here either. As far as Terraform is concerned, the identifier block is only one element in an array.

Solution:

We retrieve the data still the same way:

data "azurerm_shared_image" "image" {
  name                = var.image_name
  gallery_name        = var.gallery_name
  resource_group_name = var.rsg_name
}

And we reference it in our virtual_machine resource like so:

  storage_image_reference {
    id = data.azurerm_shared_image.image.id
  }

  plan {
    name      = data.azurerm_shared_image.image.identifier[0].sku
    publisher = data.azurerm_shared_image.image.identifier[0].publisher
    product   = data.azurerm_shared_image.image.identifier[0].offer
  }