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

[Bug]: Impossible to update traffic policy #27767

Open huats opened 2 years ago

huats commented 2 years ago

Terraform Core Version

1.3.4, 1.2.9

AWS Provider Version

4.39.0

Affected Resource(s)

Expected Behavior

We should be able to modify a traffic policy and that it creates a new version, enabling to choose the version to use in the traffic policy instance.

Actual Behavior

When a change is done to a traffic policy, the AWS API rejects it. It is the consequence that modifying a traffic policy never creates a new version which could be used by the aws_route53_traffic_policy_instance. Thus it is not possible to "change" the policy because it is still used by the traffic policy instance

Relevant Error/Panic Output Snippet

`TrafficPolicyInUse: Policy is in use for at least one instance`

Terraform Configuration Files

data "aws_region" "current" {}

data "aws_route53_traffic_policy_document" "example" {
  record_type = "A"
  start_endpoint  = "endpoint-start-YYYY"

  endpoint {
    id     = "endpoint-start-YYYY"
    type   = "cloudfront"
    region = data.aws_region.current.name
    value  = "ZZZZZZZZZ.cloudfront.net"
  }
}

resource "aws_route53_traffic_policy" "test-policy" {
    name     = "playground-policy"

    document = data.aws_route53_traffic_policy_document.example.json
}

resource "aws_route53_traffic_policy_instance" "test-instance" {
  name                   = "my.playground.com"
  traffic_policy_id      = aws_route53_traffic_policy.test-policy.id
  traffic_policy_version = aws_route53_traffic_policy.test-policy.version
  hosted_zone_id         = "XXXXXXXXXXXXXX"
  ttl                    = 360
}

Steps to Reproduce

terraform apply

Debug Output

No response

Panic Output

No response

Important Factoids

No response

References

No response

Would you like to implement a fix?

No response

github-actions[bot] commented 2 years ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

grampajoe commented 1 year ago

Another case is when a Traffic Policy isn't in use. Changing the document makes Terraform delete the policy and recreate, starting back at version 1.

It looks like that's configured in the code here.

Based on the documentation, I'd expect Terraform to update rather than recreate when document is changed.

IamEnTm commented 1 year ago

I was facing the same issue, so I've created a fork with support for document update by creating a new policy version. I have not written any tests, just added the functionality itself - but I've tested it a lot on my environments. The functionality added is:

The fork can be found here: https://github.com/IamEnTm/terraform-provider-aws All of the changes are currently just in 1 file - traffic_policy.go

To build the provider you can clone the repo and use the following: https://developer.hashicorp.com/terraform/tutorials/providers/provider-setup

To use the created binary in your terraform, you can create/edit your ~/.terraformrc file to look something like that:

provider_installation {
  dev_overrides {
    "hashicorp/aws" = "<PATH_TO_BINARY_FOLDER>" # e.g. "/Users/IamEnTm/go/bin"
 }

  direct {}
}

I'm not experienced with writing code for terraform providers, so I would appreciate any help to complete this feature with tests or any other code I've missed and create a pull request :)

Luis-3M commented 1 year ago

Also experiencing the same issues described above.

jmorsecode commented 1 year ago

Same issue on 5.x. Why is this still open after almost a year? It makes the module nearly useless without the fixes described above. Why is a policy "rules" change set to force replace? ~ Rules = { ... changes... } # forces replacement

bdhobare commented 1 year ago

Can we upstream the changes by @IamEnTm to the main repo? As stated, this is just making the module unusable. Incrementing the policy version for document changes is the expected behavior. Meanwhile if someone has a quick fix, it would be helpful.

jmorsecode commented 1 year ago

It's not ideal but we seem to be have a slight workaround by adding:

lifecycle {
    create_before_destroy = true
  }

With the sacrifice of essentially not having any version history.

Luis-3M commented 11 months ago

Any idea on to when is this going to fixed ?

lauren-hinge commented 7 months ago

It's not ideal but we seem to be have a slight workaround by adding:

lifecycle {
    create_before_destroy = true
  }

With the sacrifice of essentially not having any version history.

Ran into this and tried the same, but it seems like because the create_before_destroy's destroy fails (or for another reason I'm not aware of), the incoming changes don't actually hit the current (or any new) version of the policy.

Plus, it leaves a deposed object in state, which blocks any further update attempts.

Anyway, would really love to see a fix for this, this resource type basically cannot be terraformed for us as-is.

pwilczynskiclearcode commented 4 months ago

My ugly solution is to have sth like blue/green deployment:

locals {
  traffic_policy = ...
}

resource "aws_route53_traffic_policy" "policy-blue" {
  name     = "blue"
  document = jsonencode(local.traffic_policy)
}

resource "aws_route53_traffic_policy" "policy-green" {
  lifecycle {
    ignore_changes = [document]
  }
  name     = "green"
  document = jsonencode(local.traffic_policy)
}

resource "aws_route53_traffic_policy_instance" "record" {
  hosted_zone_id         = "some-zone-id"
  name                   = "entry.dot.com"
  traffic_policy_id      = aws_route53_traffic_policy.policy-blue.id
  traffic_policy_version = aws_route53_traffic_policy.policy-blue.version
}

and if doing updates to local.traffic_policy we'd change the code to:

resource "aws_route53_traffic_policy" "policy-blue" {
  lifecycle {
    ignore_changes = [document]
  }
  name     = "blue"
  document = jsonencode(local.traffic_policy)
}

resource "aws_route53_traffic_policy" "policy-green" {
  name     = "green"
  document = jsonencode(local.traffic_policy)
}

resource "aws_route53_traffic_policy_instance" "record" {
  ...
  traffic_policy_id      = aws_route53_traffic_policy.policy-green.id
  traffic_policy_version = aws_route53_traffic_policy.policy-green.version
}

I actually use terramate on top of terraform so it's slightly easier as I can do blue/green change with one variable.