Use block variables

Hi everyone!

I’ve a tiny question about syntax:

My variables.tf:

variable "bucket_website" {
  description = "Bucket website configuration"
  default = {
    main_page_suffix = "index.html"
    not_found_page   = "404.html"
  }
}

My main.tf:

resource "google_storage_bucket" "default" {
  website = var.bucket_website
}

The error:

Error: Unsupported argument

  on XXX line YY, in resource "google_storage_bucket" "default":
  13:   website = var.bucket_website

An argument named "website" is not expected here. Did you mean to define a
block of type "website"?

The question: What’s the right syntax? Must use a dynamic? Lookup?

1 Like

I don’t think it’s possible to supply an object to a resource ‘block’ attribute.

Hi @JulienBreux,

If you will always have exactly one website block then you can just write it out directly with individual references to your object:

resource "google_storage_bucket" "default" {
  website {
    main_page_suffix = var.bucket_website.main_page_suffix
    not_found_page   = var.bucket_website.not_found_page
  }
}

A dynamic block would only be necessary here if the decision about whether or not to include the website block must be made dynamically. For example, you might allow var.bucket_website to be null in order to disable the website functionality altogether:

variable "bucket_website" {
  description = "Bucket website configuration"
  type = object({
    main_page_suffix = string
    not_found_page   = string
  })
  default = null
}

resource "google_storage_bucket" "default" {
  dynamic "website" {
    for_each = var.bucket_website[*]
    content {
      main_page_suffix = website.value.main_page_suffix
      not_found_page   = website.value.not_found_page
    }
  }
}

The var.bucket_website[*] syntax is a special mode of the splat operator [*] when applied to a non-list value: if var.bucket_website is null then it will produce an empty list, and otherwise it will produce a single-element list containing the value. We can use that to concisely adapt a variable that is either null or not into what the dynamic block expects: a list with zero or more elements.

1 Like

hello, @apparentlymart.

I also long to write my code with syntax @JulienBreux suggests.
Although I understand these syntax that you recommend, I think that is lengthy…
could you tell me whether you are considering to equip JulienBreux’s syntax to Terraform?

There are no plans to support treating a nested block type as if it were an argument, if that’s what you mean.

What is likely to improve in future is that a next-generation provider SDK to allow provider authors to make better use of the new data types and associated syntax that Terraform 0.12 introduced, so that they can for example define an argument as being a list of objects as can be done by module authors with variables of type list(object), in which case the syntax for using such things would be the same as passing a list of objects to a module. It’ll be up to each provider to decide which of the models is most appropriate for the underlying system they are writing a provider for, which includes whether the concept in question is modelled as a value of some other object or whether it’s a distinct object in its own right.

I’m not working directly on that project so I don’t have more details to share about that right now, but the technical research is underway right now.

2 Likes

A post was split to a new topic: A use-case: dynamically-generating actions blocks in the CloudFlare provider