terraform-provider-aws
terraform-provider-aws copied to clipboard
[Bug]: aws_amplify_app.custom_header always reports changes
Terraform Core Version
1.5.5
AWS Provider Version
5.24.0
Affected Resource(s)
aws_amplify_app
Expected Behavior
When using custom_headers in aws_amplify_app, running terraform plan when nothing has changed should not result in any actions.
e.g.
resource "aws_amplify_app" "amplify" {
# ...
custom_headers = <<EOT
customHeaders:
- pattern: '**/*.jpg'
headers:
- key: Cache-Control
value: 'public, max-age=605800, s-maxage=3600'
EOT
}
running terraform apply followed by terraform plan should not result in any changes reported.
Actual Behavior
In actuality no matter what content is stored in custom_headers, it is always deemed changed.
Relevant Error/Panic Output Snippet
Terraform will perform the following actions:
# module.frontend.aws_amplify_app.amplify will be updated in-place
~ resource "aws_amplify_app" "amplify" {
~ custom_headers = jsonencode(
[
- {
- headers = [
- {
- key = "Cache-Control"
- value = "public, max-age=605800, s-maxage=3600"
},
]
- pattern = "**/*.jpg"
},
- {
- headers = [
- {
- key = "Cache-Control"
- value = "public, max-age=605800, s-maxage=3600"
},
]
- pattern = "**/*.svg"
},
- {
- headers = [
- {
- key = "Cache-Control"
- value = "public, max-age=605800, s-maxage=3600"
},
]
- pattern = "**/*.js"
},
- {
- headers = [
- {
- key = "Cache-Control"
- value = "public, max-age=605800, s-maxage=3600"
},
]
- pattern = "**/*.css"
},
- {
- headers = [
- {
- key = "Cache-Control"
- value = "public, max-age=600, s-maxage=600"
},
]
- pattern = "**/*.html"
},
]
) -> <<-EOT
# https://docs.aws.amazon.com/amplify/latest/userguide/custom-headers.html
# https://docs.aws.amazon.com/amplify/latest/userguide/ttl.html
# max-age controls caching on user browser's side
# s-maxage controls cloudfront caching (how often the CDN can be refreshed)
customHeaders:
# Setting image, js, css caching to 7 days, because we hash the names of images
- pattern: '**/*.jpg'
headers:
- key: Cache-Control
value: 'public, max-age=605800, s-maxage=3600'
- pattern: '**/*.svg'
headers:
- key: Cache-Control
value: 'public, max-age=605800, s-maxage=3600'
- pattern: '**/*.js'
headers:
- key: Cache-Control
value: 'public, max-age=605800, s-maxage=3600'
- pattern: '**/*.css'
headers:
- key: Cache-Control
value: 'public, max-age=605800, s-maxage=3600'
# html pages should be cached less, since their names are not hashed
- pattern: '**/*.html'
headers:
- key: Cache-Control
value: 'public, max-age=600, s-maxage=600'
EOT
id = "REDACTED"
name = "REDACTED"
tags = {}
# (14 unchanged attributes hidden)
# (3 unchanged blocks hidden)
}
Terraform Configuration Files
N/A
Steps to Reproduce
- Create an
aws_amplify_appresource withcustom_headers - run `terraform apply``
- run
terraform plan
Debug Output
No response
Panic Output
No response
Important Factoids
The custom_header capability was introduced in this PR: https://github.com/hashicorp/terraform-provider-aws/pull/31561 . I suspect that the AWS API does not return exactly what was originally set on the custom_headers. Specifically you will notice below that the reported current value by AWS is missing the root customHeaders key. It looks like AWS normalizes the string that is sent through the custom header api.
Perhaps the solution is to normalize the user-provided string on the provider side (e.g. through jsonencode(yamldecode(...))), but also taking care of the fact that AWS reports the value without the root customHeaders key. Attempting to set a value without that root key results in an error from the AWS PI.
References
No response
Would you like to implement a fix?
None
Community Note
Voting for Prioritization
- Please vote on this issue by adding a 👍 reaction to the original post to help the community and maintainers prioritize this request.
- Please see our prioritization guide for information on how we prioritize.
- Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request.
Volunteering to Work on This Issue
- If you are interested in working on this issue, please leave a comment.
- If this would be your first contribution, please review the contribution guide.
Hi @ewbankkit @Maddog2050! Just pinging if you saw this. The changes merged recently here https://github.com/hashicorp/terraform-provider-aws/issues/31560 have a bug.
@justinretzolk @ewbankkit @Maddog2050 Pinging again, since this prevents us from using the custom_header functionality through terraform.
@justinretzolk @ewbankkit @Maddog2050 Pinging again - It has been several months.
This would be great if this could be fixed.
This would be great if this could be fixed. This issue makes it difficult to read the Terraform plan by adding the message each time. This error does not allow us to determine if there are changes to custom headers or not.
@justinretzolk @ewbankkit @Maddog2050 Pinging again :) It has been 9 months of this issue.
Hey amazing folks, I'm supporting @KholdStare on this request. Any idea when this could be fixed? :)
hi, any news about fixing this bug?
Got really tired of trying to remember to manually toggle this on and off. So I used the AWS CLI to manage changed headers:
locals {
custom_headers = templatefile(
"${path.module}/custom-headers.yaml",
{ script_sri = var.script_sri, style_sri = var.style_sri }
)
}
# Manually update the headers on change
resource "terraform_data" "amplify_custom_headrs" {
triggers_replace = {
headers_hash = sha256(local.custom_headers)
}
provisioner "local-exec" {
command = <<EOF
aws --profile ${var.aws_profile} --region ${var.region} \
amplify update-app \
--app-id ${module.amplify_website.amplify_site.id} \
--custom-headers '${jsonencode(yamldecode(local.custom_headers))}'
EOF
}
}
Full code if someone is interested: https://github.com/rgant/rob.gant.ninja/blob/66448ef6c3c25ba4e5725bf089ab26923c4c2699/infrastructure/amplify.tf#L115
feels like terraform is managing the string as json in state as you can see in the first part of plan and aws api wants yaml (https://docs.aws.amazon.com/amplify/latest/userguide/custom-header-YAML-format.html), so feels like the provider is reserializing the yaml into json to compare with tfstate causing perpetual diff because difference in quotes, breaks and sorting but keeping YAML for apply.
this validates to me as if you add jsonencode to the terraform, plan shows just whitespace changes but apply fails because aws api wants yaml
~ resource "aws_amplify_app" "this" {
~ custom_headers = jsonencode( # whitespace changes
[
{
headers = [
{
key = "Cache-Control"
value = "public, max-age=2592000, stale-while-revalidate=2592000"
},
]
pattern = "**/*.js"
},
{
headers = [
{
key = "Cache-Control"
value = "public, max-age=2592000, stale-while-revalidate=2592000"
},
]
pattern = "**/*.css"
},
so the fix has to be in that direction