skip to Main Content

I am looking for a way to pass data template_cloudinit_config to another module. I am clear about how to pass variables to module for various data types including object, but I am not sure how to do this with data.

In this setup, I have a vm-basic module that will define all the virtual hardware configuration, and postgres Terraform script that will define service related information including cloud init scripts. The intention is to have vm virtual hardware configuration to be highly reusable as module, to allow me focusing only on service related info i.e. postgres, nginx etc.

This is my vm-basic vars.tf file that will accept parameters that will be used in virtual hardware configuration.

variable "prefix" {}

variable "rg" { type = object({ 
    name = string
    location = string 
}) } 

variable "vm_size" {}
variable "private_ip_address" {}
variable "subnet" { type = object({ id = string }) } 
variable "data_disk_size_gb" { type = number }

variable "service_name" { type = string }
variable "admin_username" { type = string }
variable "admin_public_key_path" { type = string }

variable "nsg_allow_tcp_ports" { type = list(string) }

locals {
  nsg_allow_tcp_ports = {for p in var.nsg_allow_tcp_ports: index(var.nsg_allow_tcp_ports, p) => p}
}


#### DOES NOT WORK ######
#### Expected an equals sign ("=") to mark the beginning of the attribute value. ######
variable "custom_data" { type = object({ data }) }

How custom data will be used in vm-basic module

resource "azurerm_linux_virtual_machine" "vm" {
    name                  = "${var.prefix}-${var.service_name}-vm"
    location              = var.rg.location
    resource_group_name   = var.rg.name
    ...
    ...
    custom_data = var.custom_data.rendered
    ...
    ...
}

How the other script will pass parameter to vm-basic module

module "vm-basic" { 
  source = "../../base/vm"
  service_name = var.service_name

  prefix = var.prefix
  rg = var.rg
  vm_size = var.vm_size
  private_ip_address = var.private_ip_address
  subnet = var.subnet
  data_disk_size_gb = var.data_disk_size_gb

  admin_username = var.admin_username
  admin_public_key_path = var.admin_public_key_path

  nsg_allow_tcp_ports = var.nsg_allow_tcp_ports
}

data "template_cloudinit_config" "config" {
  gzip = true
  base64_encode = true
  part {
      filename = "init-cloud-config"
      content_type = "text/cloud-config"
      content = file("init.yaml")
  }
  part {
      filename = "init-shellscript"
      content_type = "text/x-shellscript"
      content = templatefile("init.sh",
        { hostname = "${var.prefix}-${var.service_name}" }
      )
  }
}

How can I pass data object to another Terraform module?

2

Answers


  1. Chosen as BEST ANSWER

    In the variable vars.tf file, it's enough to just do

    variable "custom_data" {}
    

    In the vm-basic module, refer to the variable through var, similar to others.

    custom_data = var.custom_data.rendered
    

  2. The meaning of the error you saw is that Terraform is expecting the argument to the object type constraint to be name = type pairs, but you only wrote data and so Terraform is reporting that there’s a missing =.

    To make this work, you’ll need to write a valid type constraint. It’s not clear to me from your question exactly what custom_data represents, but I do see your later example includes var.custom_data.rendered and so from that I can tell that the type constraint should at least include a rendered attribute in order to make that valid, and the custom_data argument to azurerm_linux_virtual_machine expects a string so I’ll match that:

    variable "custom_data" {
      type = object({
        rendered = string
      })
    }
    

    This means that Terraform will accept any object value which has a rendered attribute that can convert to string, and thus your later reference to var.custom_data.rendered is guaranteed to work and always produce a string value.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search