hashicorp / terraform-provider-awscc

Terraform AWS Cloud Control provider
https://registry.terraform.io/providers/hashicorp/awscc/latest/docs
Mozilla Public License 2.0
244 stars 112 forks source link

awscc_route53resolver_resolver_rule : terraform plan detect unexpected drift #1282

Open wellsiau-aws opened 9 months ago

wellsiau-aws commented 9 months ago

Community Note

Terraform CLI and Terraform AWS Cloud Control Provider Version

Affected Resource(s)

Terraform Configuration Files

Please include all Terraform configurations required to reproduce the bug. Bug reports without a functional reproduction may be closed without investigation.

resource "awscc_route53resolver_resolver_rule" "example" {
  domain_name          = "example.com"
  name                 = "MyRule"
  resolver_endpoint_id = "rslvr-out-3483213a88fd40db8"
  rule_type            = "FORWARD"

  tags = [{
    "key"   = "LineOfBusiness",
    "value" = "Engineering"
  }]

  target_ips = [
    {
      ip   = "192.0.2.6"
      port = "53"
    },
    {
      ip   = "192.0.2.99"
      port = "53"
    }
  ]
}

Expected Behavior

terraform plan should return no-resource changes

Actual Behavior

terraform plan detects that domain_name changed despite there are no modification.

awscc_route53resolver_resolver_rule.example: Refreshing state... [id=rslvr-rr-2995758e0ca74e719]
awscc_route53resolver_resolver_rule_association.example: Refreshing state... [id=rslvr-rrassoc-e6748af5c9934f2fb]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # awscc_route53resolver_resolver_rule.example will be updated in-place
  ~ resource "awscc_route53resolver_resolver_rule" "example" {
      ~ domain_name          = "example.com." -> "example.com"
        id                   = "rslvr-rr-2995758e0ca74e719"
        name                 = "MyRule"
        tags                 = [
            {
                key   = "LineOfBusiness"
                value = "Engineering"
            },
        ]
      ~ target_ips           = [
          ~ {
              + ipv_6 = (known after apply)
                # (2 unchanged attributes hidden)
            },
          ~ {
              + ipv_6 = (known after apply)
                # (2 unchanged attributes hidden)
            },
        ]
        # (4 unchanged attributes hidden)
    }

Steps to Reproduce

  1. terraform apply
  2. terraform plan
wellsiau-aws commented 9 months ago

CCAPI raw output as comparison below, notice that the DomainName includes extra . at the end : example.com.

aws cloudcontrol get-resource --type-name AWS::Route53Resolver::ResolverRule --identifier rslvr-rr-2995758e0ca74e719 | jq -r ".ResourceDescription.Properties" | jq "."
{
  "ResolverEndpointId": "rslvr-out-3483213a88fd40db8",
  "DomainName": "example.com.",
  "RuleType": "FORWARD",
  "ResolverRuleId": "rslvr-rr-2995758e0ca74e719",
  "Arn": "arn:aws:route53resolver:us-east-1:204034886740:resolver-rule/rslvr-rr-2995758e0ca74e719",
  "Tags": [
    {
      "Value": "Engineering",
      "Key": "LineOfBusiness"
    }
  ],
  "TargetIps": [
    {
      "Ip": "192.0.2.6",
      "Port": "53"
    },
    {
      "Ip": "192.0.2.99",
      "Port": "53"
    }
  ],
  "Name": "MyRule"
}
wellsiau-aws commented 9 months ago

Another problem, the target_ips attribute also detected unnecessary changes because the ipv_6 was stored in the Terraform state as null

Terraform state output (redacted):

{
  "version": 4,
  "terraform_version": "1.4.2",
  . . .
  "resources": [
    {
      "mode": "managed",
      "type": "awscc_route53resolver_resolver_rule",
      . . . 
      "instances": [
        {
          "schema_version": 1,
          "attributes": {
            . . . 
            "target_ips": [
              {
                "ip": "192.0.2.6",
                "ipv_6": null,
                "port": "53"
              },
              {
                "ip": "192.0.2.99",
                "ipv_6": null,
                "port": "53"
              }
            ]
          },
. . .
}
kadrach commented 9 months ago

@wellsiau-aws R53Resolver silently appends the trailing dot to input domain names. Your HCL configuration will store "example.com" in state, but read calls (CCAPI/R53Resolver API) return "example.com." (trailing dot). This is visible in your sample plan.

Using domain_name = "example.com." in your configuration leads to a no-op plan.

kadrach commented 9 months ago

This is annotated in the resource schema via this propertyTransform (explained here), but I believe not currently implemented in this provider.

https://github.com/hashicorp/terraform-provider-awscc/blob/main/internal/service/cloudformation/schemas/AWS_Route53Resolver_ResolverRule.json#L129-L131