0

I'm a terraform novice. I've written a module for cloudfront. I want to pass my origin config as an object. When I run terragrunt, I get this error:

Error: Invalid default value for variable

  on variables.tf line 9, in variable "origin_config":
   9:   default = {
  10:      protocol_policy = "https-only"
  11:      ssl_protocol = ["TLSv1.2"]
  12:      http_port = 80
  13:      https_port = 443
  14:   }

This default value is not compatible with the variable's type constraint:
attribute "domain_name" is required.

Here is my module code:

resource "aws_cloudfront_distribution" "this" {
  # origin config
  origin {
    domain_name = var.origin_config.domain_name
    origin_id   = local.origin_id
    custom_origin_config  {
        origin_protocol_policy = var.origin_config.protocol_policy
        origin_ssl_protocols = var.origin_config.ssl_protocol
        http_port = var.origin_config.http_port
        https_port = var.origin_config.https_port
    }
  }

Here is my variables.tf

variable "origin_config" {
  type = object({
    domain_name = string
    protocol_policy = string
    ssl_protocol = list(string)
    http_port = number
    https_port = number
    })
  default = {
     protocol_policy = "https-only"
     ssl_protocol = ["TLSv1.2"]
     http_port = 80
     https_port = 443
  }
}

Here is my terraform.tfvars:

origin_config = {
    domain_name = "test.example.com"
}

If I add the variable domain_name as a default, then it works. It seems like it's somehow not reading my input from terraform.tvars?

yossarian2004
  • 299
  • 1
  • 3
  • 11

2 Answers2

0

Your type includes domain_name = string which makes it compulsory. Thus, if you don't want to set fixed value, you have to set an empty string, e.g.:

variable "origin_config" {
  type = object({
    domain_name = string
    protocol_policy = string
    ssl_protocol = list(string)
    http_port = number
    https_port = number
    })
  default = {
     domain_name = ""
     protocol_policy = "https-only"
     ssl_protocol = ["TLSv1.2"]
     http_port = "80"
     https_port = "443"
  }
}

Otherwise, remove domain_name from your type. There is also experimental optional keyword:

terraform {
  experiments = [module_variable_optional_attrs]
}


variable "origin_config" {
  type = object({
    domain_name = optional(string)
    protocol_policy = string
    ssl_protocol = list(string)
    http_port = number
    https_port = number
    })
  default = {
     protocol_policy = "https-only"
     ssl_protocol = ["TLSv1.2"]
     http_port = "80"
     https_port = "443"
  }
}
Marcin
  • 215,873
  • 14
  • 235
  • 294
0

My issue turned out to be that by trying to specify a single value in my tfvars, I was overwriting the object containing my defaults.

The solution was to merge the two objects so my single key:value input would be merged with the default object into a new object.

Here is a good explanation: https://binx.io/blog/2020/01/02/module-parameter-defaults-with-the-terraform-object-type/

yossarian2004
  • 299
  • 1
  • 3
  • 11