hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.84k stars 9.19k forks source link

cloudfront custom_header fails on multiple defs - docs say multiple OK. #9944

Open tburt11 opened 5 years ago

tburt11 commented 5 years ago

Community Note

Terraform Version

Terraform v0.12.7

Affected Resource(s)

aws_cloudfront_distribution

Terraform Configuration Files

    custom_header      = { name = "X-CF-Masscache-Host"
                           value = "${var.spo_env}-masscache-ext.qa.sp.com"
                         }
    custom_header      = { name = "X-CF-Pesto-Host"
                           value = "${var.spo_env}-pesto-ext.qa.sp.com"
                         }
    custom_header      = { name = "X-CF-Location-Replacement-String"
                           value = "${var.spo_env}"
                         }

Debug Output

terraform validate:

Error: Attribute redefined

on main.tf line 28, in resource "aws_cloudfront_distribution" "primary": 28: custom_header = { name = "X-CF-Pesto-Host"

The argument "custom_header" was already set at main.tf:25,5-18. Each argument may be set only once.

Expected Behavior

Multiple Headers defined (docs say multiple is OK) From the Docs: custom_header (Optional) - One or more sub-resources with name and value parameters that specify header data that will be sent to the origin (multiples allowed).

Actual Behavior

Error that custom_header is already defined

Steps to Reproduce

  1. terraform validate
ofhouse commented 4 years ago

Hi Tim, maybe the syntax with custom_header = here is just wrong, using it without = should work:


origin {
  ...
  custom_header {
      name  = "X-CF-Masscache-Host"
      value = "${var.spo_env}-masscache-ext.qa.sp.com"
  }

  custom_header {
      name  = "X-CF-Pesto-Host"
      value = "${var.spo_env}-pesto-ext.qa.sp.com"
  }

  custom_header {
      name  = "X-CF-Location-Replacement-String"
      value = "${var.spo_env}"
  }
}
carbonrobot commented 4 years ago

Using provider version 3.5 throws an error when using the following syntax

    custom_header {
      name = "X-Frame-Options"
      value = "DENY"
    }

The following syntax will validate and plan correctly, but will not allow multiple

    custom_header = {
      name = "X-Frame-Options"
      value = "DENY"
    }

Perhaps the issue is with the type definition. Should the following be TypeList? https://github.com/terraform-providers/terraform-provider-aws/blob/3b002dfdfaa672c7e2527c1dfd322723b394e624/aws/resource_aws_cloudfront_distribution.go#L463

justinretzolk commented 2 years ago

Hey y'all :wave: Thank you for taking the time to file this issue and for the additional discussion! Given that there's been a number of AWS provider releases since this was initially filed, can anyone confirm whether you're still experiencing this behavior?

mariussofron commented 2 years ago

@justinretzolk Hi! I am trying to add a custom_header using a list of objects containing name and value, for example:

custom_header = [
  {
    name = "the-name"
    value = "the-value"
  }
]

and it throws:

│ Error: Unsupported argument
|  21:         custom_header = [
│ 
│ An argument named "custom_header" is not expected here. Did you mean to define a block of type "custom_header"?

It works if I define it as a block instead:

custom_header ={
  name = "the-name"
  value = "the-value"
}

I am using Terraform version 4.4.0

justinretzolk commented 2 years ago

Hey @mariussofron 👋 Notably (and perhaps this is something that's important for the original issue), this resource is not configured to use Attributes as blocks, so I believe the correct syntax would actually be what was mentioned above:

custom_header {
  name = "name0"
  value = "value0"
}

custom_header {
  name = "name1"
  value = "value1"
}

This has been mentioned above, and it was mentioned that this syntax didn't work in version 3.5 of the provider, so there's a chance this will not work. In that case, I'd like to mark this as a bug, as that is how I'd expect this resource to behave.

majormoses commented 2 years ago

I will need to check if any of our envs are on 3.5 but I can confirm you can set multiple custom_header blocks.

Here are some snippets from our internal module where I know we do support setting multiple headers:

# static or dynamically generated inputs
custom_origin_headers = [
    {
      "name": "X-Some-Header-Name",
      "value": "SOME_HEADER_VALUE"
    }
]

# in a resource or module declaration
resource "aws_cloudfront_distribution" "this" {
  # ... stuff
  origin {
    # ... stuff
    dynamic "custom_header" {
      for_each = var.custom_origin_headers
      content {
        name  = custom_header.value.name
        value = custom_header.value.value
      }
  }
}
andyp22 commented 1 year ago

I'm running aws provider version 3.76.1 and am seeing these errors when I try to modularize my code. As @majormoses states above, a dynamic custom_header block works if the resource is part of the root module, but, trying to create a dynamic custom_header block in a re-usable module using the same syntax produces the same types of errors seen above. And every dynamic block within the modularized aws_cloudfront_distribution resource throws a similar error, not just the custom_header block. Using the iterator config does not help.


│
│   on modules\cloudfront\cloudfront.tf line 52, in resource "aws_cloudfront_distribution" "this":
│   52:       for_each = local.origin_test.custom_header == null ? [] : [for i in local.origin_test.custom_header : {
│
│ There is no variable named "local".```