Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CloudFront etags being updated even on failed apply. State file not updated with new etags #23949

Closed
frankloye opened this issue Mar 30, 2022 · 7 comments
Labels
service/cloudfront Issues and PRs that pertain to the cloudfront service.

Comments

@frankloye
Copy link

frankloye commented Mar 30, 2022

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • 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
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Affected Resource(s)

  • aws_cloudfront_distribution

Terraform Configuration Files

terraform {
  backend "azurerm" {}
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "3.53.0"
    }
  }
}

resource "aws_cloudfront_distribution" "cloudfront_distribution" {
  depends_on = [aws_cloudfront_origin_access_identity.origin_access_identity,
  aws_s3_bucket.origin_bucket]
  origin {
    domain_name = aws_s3_bucket.origin_bucket.bucket_domain_name
    origin_id   = local.origin_id
    origin_path = "/secure"
    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path
    }
  }

  is_ipv6_enabled     = true
  comment             = var.comment
  default_root_object = "index.html"

  aliases = var.aliases
  enabled = var.enabled

  dynamic "default_cache_behavior" {
    for_each = local.dynamic_default_cache_behavior[*]
    iterator = j

    content {
      allowed_methods        = j.value.allowed_methods
      cached_methods         = j.value.cached_methods
      target_origin_id       = j.value.target_origin_id
      compress               = lookup(j.value, "compress", null)
      viewer_protocol_policy = "redirect-to-https"
      #trusted_key_groups     = var.trusted_key_groups

      #cache_policy_id          = lookup(j.value, "cache_policy_id", null)
      origin_request_policy_id = lookup(j.value, "origin_request_policy_id", null)

      #min_ttl     = lookup(j.value, "min_ttl", null)
      #default_ttl = lookup(j.value, "default_ttl", null)
      #max_ttl     = lookup(j.value, "max_ttl", null)

      dynamic "forwarded_values" {
        for_each = lookup(j.value, "use_forwarded_values", true) ? [true] : []
        content {
          query_string = lookup(j.value, "query_string", null)
          headers      = lookup(j.value, "headers", null)

          cookies {
            forward = lookup(j.value, "cookies_forward", null)
          }
        }
      }

      dynamic "lambda_function_association" {
        iterator = lambda
        for_each = lookup(j.value, "lambda_function_association", [])
        content {
          event_type   = lambda.value.event_type
          lambda_arn   = lambda.value.lambda_arn
          include_body = lookup(lambda.value, "include_body", null)
        }
      }
    }
  }

  dynamic "ordered_cache_behavior" {
    for_each = local.dynamic_ordered_cache_behavior
    iterator = j
    content {
      path_pattern           = j.value.path_pattern
      allowed_methods        = j.value.allowed_methods
      cached_methods         = j.value.cached_methods
      target_origin_id       = j.value.target_origin_id
      compress               = lookup(j.value, "compress", null)
      viewer_protocol_policy = "redirect-to-https"
      trusted_key_groups     = var.trusted_key_groups

      cache_policy_id          = lookup(j.value, "cache_policy_id", null)
      origin_request_policy_id = lookup(j.value, "origin_request_policy_id", null)

      min_ttl     = lookup(j.value, "min_ttl", null)
      default_ttl = lookup(j.value, "default_ttl", null)
      max_ttl     = lookup(j.value, "max_ttl", null)

      dynamic "forwarded_values" {
        for_each = lookup(j.value, "use_forwarded_values", true) ? [true] : []
        content {
          query_string = lookup(j.value, "query_string", null)
          headers      = lookup(j.value, "headers", null)

          cookies {
            forward = lookup(j.value, "cookies_forward", null)
          }
        }
      }
      dynamic "lambda_function_association" {
        iterator = lambda
        for_each = lookup(j.value, "lambda_function_association", [])
        content {
          event_type   = lambda.value.event_type
          lambda_arn   = lambda.value.lambda_arn
          include_body = lookup(lambda.value, "include_body", null)
        }
      }
    }
  }

  price_class = "PriceClass_All"

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  dynamic "custom_error_response" {
    for_each = local.dynamic_custom_error_response

    content {
      error_code            = custom_error_response.value.error_code
      error_caching_min_ttl = lookup(custom_error_response.value, "error_caching_min_ttl", null)
      response_code         = lookup(custom_error_response.value, "response_code", null)
      response_page_path    = lookup(custom_error_response.value, "response_page_path", null)
    }
  }

  viewer_certificate {
    acm_certificate_arn      = var.certificate_arn
    minimum_protocol_version = "TLSv1.2_2018"
    ssl_support_method       = "sni-only"
  }

  tags = {
    environment = local.environment
    airid       = local.airid_val
    tf_mod      = local.tf_module_label
  }
}

Expected Behavior

CloudFront Distribution etags are not updated unless the apply is successful and state file etag values will always match the distribution etag values if updates are all made through terraform

Actual Behavior

CloudFront Distribution etags are being updated even when the apply fails and state file etag values are not being updated to reflect the new CloudFront Distribution etags

Error: error updating CloudFront Distribution (XXXXX): PreconditionFailed: The request failed because it didn't meet the preconditions in one or more request-header fields.status code: 412

Steps to Reproduce

  1. terraform apply
@github-actions github-actions bot added needs-triage Waiting for first response or review from a maintainer. service/cloudfront Issues and PRs that pertain to the cloudfront service. labels Mar 30, 2022
@justinretzolk
Copy link
Member

Hey @frankloye 👋 Thank you for taking the time to raise this! So that we have all of the necessary information in order to look into this, can you update the issue description to include the Terraform version you're running, as well as the (redacted as needed) debug logs?

I also noticed that you're using an older version of the AWS Provider. A quick check of the changelog seems to indicate that a number of bug fixes have occurred within the aws_cloudfront_distribution resource in the versions since 3.53.0, and while none of them directly call out etags, I'd be interested in seeing if using a newer version of the provider would resolve the issue.

@justinretzolk justinretzolk added waiting-response Maintainers are waiting on response from community or contributor. and removed needs-triage Waiting for first response or review from a maintainer. labels Mar 31, 2022
@frankloye
Copy link
Author

After further investigation, it seems like the issue is actually with the CloudFront Key Group Resource. When the public key value changes, the CloudFront Key Group Resource is updating the eTag on the associated CloudFront Distribution, but is not updating the distribution’s eTag in the state file. Which results in the precondition failed error when we try to update the CloudFront Distribution because our eTag in state does not match the eTag on the distribution.

Please let me know if I should open a new case or update the existing one.

@github-actions github-actions bot removed the waiting-response Maintainers are waiting on response from community or contributor. label Apr 1, 2022
@justinretzolk
Copy link
Member

Hey @frankloye -- thank you for that update. So as to prevent any possible confusion, can you open a new issue with that information in mind?

@frankloye
Copy link
Author

Created new issue: #24033

@justinretzolk
Copy link
Member

Hey @frankloye 👋 Thank you for taking the time to open that! Given that we've migrated over to that issue with the new information, is it safe to say that this one can be closed?

@frankloye
Copy link
Author

Yes. Closing this issue.

@github-actions
Copy link

github-actions bot commented May 7, 2022

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 7, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
service/cloudfront Issues and PRs that pertain to the cloudfront service.
Projects
None yet
Development

No branches or pull requests

2 participants