What happened?
VPCEndpointSubnetAssociation (and VPCEndpointRouteTableAssociation) managed resources flip their crossplane.io/external-name annotation between two formats on every reconciliation, causing perpetual updates (and, on affected setups, delete/recreate churn and AWS 429 throttling).
Observed live across reconciles for a single subnet association MR:
ext=vpce-079f2245bf1ec40be/subnet-012d3109ebb773a1c <-- import format
ext=a-vpce-079f2245bf1ec40be1284373945 <-- internal-id format
The resource's resourceVersion increments continuously while it sits in the vpce/subnet state; a sibling association that happens to settle on the a-<hash> form is stable.
Root cause
aws_vpc_endpoint_subnet_association and aws_vpc_endpoint_route_table_association are configured with FormattedIdentifierFromProvider("/", ...) in config/externalname.go. That helper leaves GetExternalNameFn as the IdentifierFromProvider default (reads tfstate["id"]) while GetIDFn joins the parameters with /.
But the Terraform AWS provider sets the id to a prefixed, hashcode-based value, not the slash-joined import id (internal/service/ec2/id.go):
func vpcEndpointSubnetAssociationCreateID(vpcEndpointID, subnetID string) string {
return fmt.Sprintf("a-%s%d", vpcEndpointID, create.StringHashcode(subnetID))
}
So GetExternalNameFn yields a-<vpc_endpoint_id><hashcode(subnet_id)> while GetIDFn yields vpc_endpoint_id/subnet_id — the two disagree and the external name oscillates. This is the same class of bug fixed for the API Gateway v1 resources in #1974 / #1975.
(aws_vpc_endpoint_security_group_association uses config.IdentifierFromProvider — both sides are the a-<hash> id, so it is consistent and unaffected.)
How can we reproduce it?
Create a VPCEndpointSubnetAssociation and watch kubectl get vpcendpointsubnetassociations -o yaml — the crossplane.io/external-name annotation alternates between <vpc_endpoint_id>/<subnet_id> and a-<vpc_endpoint_id><number>, and resourceVersion climbs continuously.
Fix
Make GetExternalNameFn and GetIDFn both deterministic from the named fields (same approach as #1975): external name = vpc_endpoint_id/child_id, Terraform id = a-<vpc_endpoint_id><hashcode(child_id)>. PR to follow.
What happened?
VPCEndpointSubnetAssociation(andVPCEndpointRouteTableAssociation) managed resources flip theircrossplane.io/external-nameannotation between two formats on every reconciliation, causing perpetual updates (and, on affected setups, delete/recreate churn and AWS429throttling).Observed live across reconciles for a single subnet association MR:
The resource's
resourceVersionincrements continuously while it sits in thevpce/subnetstate; a sibling association that happens to settle on thea-<hash>form is stable.Root cause
aws_vpc_endpoint_subnet_associationandaws_vpc_endpoint_route_table_associationare configured withFormattedIdentifierFromProvider("/", ...)inconfig/externalname.go. That helper leavesGetExternalNameFnas theIdentifierFromProviderdefault (readstfstate["id"]) whileGetIDFnjoins the parameters with/.But the Terraform AWS provider sets the id to a prefixed, hashcode-based value, not the slash-joined import id (
internal/service/ec2/id.go):So
GetExternalNameFnyieldsa-<vpc_endpoint_id><hashcode(subnet_id)>whileGetIDFnyieldsvpc_endpoint_id/subnet_id— the two disagree and the external name oscillates. This is the same class of bug fixed for the API Gateway v1 resources in #1974 / #1975.(
aws_vpc_endpoint_security_group_associationusesconfig.IdentifierFromProvider— both sides are thea-<hash>id, so it is consistent and unaffected.)How can we reproduce it?
Create a
VPCEndpointSubnetAssociationand watchkubectl get vpcendpointsubnetassociations -o yaml— thecrossplane.io/external-nameannotation alternates between<vpc_endpoint_id>/<subnet_id>anda-<vpc_endpoint_id><number>, andresourceVersionclimbs continuously.Fix
Make
GetExternalNameFnandGetIDFnboth deterministic from the named fields (same approach as #1975): external name =vpc_endpoint_id/child_id, Terraform id =a-<vpc_endpoint_id><hashcode(child_id)>. PR to follow.