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.8k stars 9.15k forks source link

[Bug]: DynamoDB table output has the ARN as id (instead of the name) #39635

Open gdessie opened 1 week ago

gdessie commented 1 week ago

Terraform Core Version

0.11.10

AWS Provider Version

1.57.x

Affected Resource(s)

I have a DynamoDB table created with terraform version 0.11.10 & provider 1.57.x but I have upgraded them to 0.15.5 & 4.0 a while back. Now I am trying to move the state from this repo to another one configured with the latest provider version and terraform 1.3. I'm not sure what's causing the issue but terraform is trying to recreate appautoscaling resources because the output from the table resource has unexpected values. I have also recreated the issue when I tried to remove the resource and import again in the same repository.

Expected Behavior

The id from the table output should be the name of the table (as documented here)

Actual Behavior

ARN of the table is being set on the id output.

Relevant Error/Panic Output Snippet

/+ resource "aws_appautoscaling_target" "dynamodb_table_write_target" {
      ~ arn                = "arn:aws:application-autoscaling:us-east-1:<account-id>:scalable-target/<generated-id>" -> (known after apply)
      ~ id                 = "table/<table-name>" -> (known after apply)
      ~ resource_id        = "table/<table-name>" -> "table/arn:aws:dynamodb:us-east-1:<account-id>:table/<table-name>" # forces replacement
      ~ role_arn           = "arn:aws:iam::<account-id>:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable" -> (known after apply)
        # (4 unchanged attributes hidden)
    }

Terraform Configuration Files

resource "aws_dynamodb_table" "table" {
  name                        = var.table_name
  read_capacity               = local.read_capacity
  write_capacity              = local.write_capacity
  hash_key                    = var.hash_key
  range_key                   = var.range_key
  deletion_protection_enabled = var.deletion_protection_enabled
  stream_enabled              = local.stream_enabled
  stream_view_type            = local.stream_view_type

  dynamic "attribute" {
    for_each = var.attributes
    content {
      name = attribute.value.name
      type = attribute.value.type
    }
  }

  tags         = local.tags
  billing_mode = var.billing_mode

  point_in_time_recovery {
    enabled = true
  }

  server_side_encryption {
    enabled     = var.enable_account_kms_encryption
    kms_key_arn = var.kms_key_arn
  }

  lifecycle {
    # see https://github.com/terraform-providers/terraform-provider-aws/issues/671
    ignore_changes = [
      read_capacity,
      write_capacity,
      global_secondary_index,
    ]
  }
}

resource "aws_appautoscaling_target" "dynamodb_table_read_target" {
  max_capacity       = var.read_autoscaling_capacity_max
  min_capacity       = var.read_autoscaling_capacity_min
  resource_id        = "table/${aws_dynamodb_table.table.id}"
  scalable_dimension = "dynamodb:table:ReadCapacityUnits"
  service_namespace  = "dynamodb"
}

Steps to Reproduce

# Remove the appautoscaling target from the state
terraform state rm aws_appautoscaling_target

# Import it again
terraform import aws_appautoscaling_target dynamodb/table/<table-name>/dynamodb:table:ReadCapacityUnits

Debug Output

No response

Panic Output

No response

Important Factoids

No response

References

No response

Would you like to implement a fix?

None

github-actions[bot] commented 1 week ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

justinretzolk commented 3 days ago

Hey @gdessie 👋 Thank you for taking the time to raise this! I took a quick look to verify that the aws_dynamodb_table.id was being set as documented. Depending on exactly how things are configured, that happens either here or here (where tableName is created here). I also took some time to review the changelog, and didn't see anything that would give me the indication that this has changed in the versions between 1.57.x and the current version of the provider.

Was the aws_dynamodb_table imported to the new state during the migration? I'd be curious as to what that resource looks like in the state, and what value is being set for var.table_name, since that's what is being used for aws_dynamodb_table.table.name. Are you able to provide debug logging (redacted as needed) in case that information is helpful for whoever winds up picking this up to look into it more?

gdessie commented 3 days ago

Hey @justinretzolk thanks for taking a look at this! Started seeing this issue when I tried to import the table from another repo that's configured with newer terraform and provider versions than the source repo. Here's what the state looks like (var.name is set to the name of my table). I shared the plan output under "Relevant Error/Panic Output Snippet" section but let me know if there's more I can provide.

"name": "table",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
  {
    "schema_version": 1,
    "attributes": {
      "arn": "arn:aws:dynamodb:<region>:<account-id>:table/<table-name>",
      "billing_mode": "PROVISIONED",
      "deletion_protection_enabled": true,
      "global_secondary_index": [],
      "hash_key": "pk",
      "id": "arn:aws:dynamodb:<region>:<account-id>:table/<table-name>",
      "import_table": [],
      "local_secondary_index": [],
      "name": "<table-name>",
      "point_in_time_recovery": [
        {
          "enabled": true
        }
      ],
      "range_key": "sk",
      "read_capacity": 200,
      "replica": [],
      "restore_date_time": null,
      "restore_source_name": null,
      "restore_to_latest_time": null,
      "server_side_encryption": [
        {
          "enabled": true,
          "kms_key_arn": "arn:aws:kms:<region>:<account-id>:key/<key-id>"
        }
      ],
      "stream_arn": "",
      "stream_enabled": false,
      "stream_label": "",
      "stream_view_type": "KEYS_ONLY",
      "table_class": "STANDARD",
      "timeouts": {
        "create": "10m",
        "delete": "10m",
        "update": "10m"
      },
      "ttl": [
        {
          "attribute_name": "ttl",
          "enabled": true
        }
      ],
      "write_capacity": xxx
    }
  }
]
gdessie commented 3 days ago

*yes the table was imported as well

justinretzolk commented 2 days ago

Thanks for the additional context @gdessie! Unfortunately I don't have a solid answer for what's changed there at the moment -- I'll leave that for whoever picks this up to work on it.

In the meantime, based on the state output, it looks like you should be able to update your configuration from "table/${aws_dynamodb_table.table.id}" to "table/${aws_dynamodb_table.table.name}" to workaround this and retain the implicit dependency.

gdessie commented 1 day ago

Yeah, I already did that by replacing a shared module with a local copy of it. I am trying to follow best practices at work :) Thanks for your time, @justinretzolk!