From ee3741ed9d46dec41a255d0f5310512a0b404d58 Mon Sep 17 00:00:00 2001 From: Vaishak Dinesh Date: Fri, 1 May 2026 11:46:22 -0700 Subject: [PATCH] fix(zone): rewrite cross-file .zone references to .name The cloudflare_zone resource renamed its 'zone' attribute to 'name' in v5, but tf-migrate only updated it within the resource block. Cross-file references like cloudflare_zone.example.zone were left unchanged, breaking any resource that referenced the zone's domain. Add ComputedAttributeMapper to the zone migrator so that all cross-file references to .zone are rewritten to .name during global postprocessing. Fixes references in string interpolations, locals, and other resources. Found via review of cloudflare/ops/terraform-cfaccounts MR !9482. --- .../testdata/zone/expected/zone_cross_refs.tf | 37 +++++++++++++++++++ .../testdata/zone/input/zone_cross_refs.tf | 23 ++++++++++++ internal/resources/zone/v4_to_v5.go | 16 +++++++- 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 integration/v4_to_v5/testdata/zone/expected/zone_cross_refs.tf create mode 100644 integration/v4_to_v5/testdata/zone/input/zone_cross_refs.tf diff --git a/integration/v4_to_v5/testdata/zone/expected/zone_cross_refs.tf b/integration/v4_to_v5/testdata/zone/expected/zone_cross_refs.tf new file mode 100644 index 00000000..95a3ac76 --- /dev/null +++ b/integration/v4_to_v5/testdata/zone/expected/zone_cross_refs.tf @@ -0,0 +1,37 @@ +# Cross-file references to cloudflare_zone.*.zone +# These should be rewritten to .name after migration + + + +# Pattern: .zone reference in a local +locals { + cftftest_zone_domain = cloudflare_zone.minimal.name +} + +# Pattern: Direct .zone reference in another resource +resource "cloudflare_dns_record" "cftftest_zone_ref" { + zone_id = cloudflare_zone.minimal.id + name = cloudflare_zone.minimal.name + type = "CNAME" + content = "example.com" + ttl = 1 +} + +moved { + from = cloudflare_record.cftftest_zone_ref + to = cloudflare_dns_record.cftftest_zone_ref +} + +# Pattern: .zone reference in string interpolation +resource "cloudflare_dns_record" "cftftest_zone_interpolation" { + zone_id = cloudflare_zone.minimal.id + name = "cftftest-sub.${cloudflare_zone.minimal.name}" + type = "CNAME" + content = "example.com" + ttl = 1 +} + +moved { + from = cloudflare_record.cftftest_zone_interpolation + to = cloudflare_dns_record.cftftest_zone_interpolation +} diff --git a/integration/v4_to_v5/testdata/zone/input/zone_cross_refs.tf b/integration/v4_to_v5/testdata/zone/input/zone_cross_refs.tf new file mode 100644 index 00000000..5c172d9a --- /dev/null +++ b/integration/v4_to_v5/testdata/zone/input/zone_cross_refs.tf @@ -0,0 +1,23 @@ +# Cross-file references to cloudflare_zone.*.zone +# These should be rewritten to .name after migration + +# Pattern: Direct .zone reference in another resource +resource "cloudflare_record" "cftftest_zone_ref" { + zone_id = cloudflare_zone.minimal.id + name = cloudflare_zone.minimal.zone + type = "CNAME" + content = "example.com" +} + +# Pattern: .zone reference in string interpolation +resource "cloudflare_record" "cftftest_zone_interpolation" { + zone_id = cloudflare_zone.minimal.id + name = "cftftest-sub.${cloudflare_zone.minimal.zone}" + type = "CNAME" + content = "example.com" +} + +# Pattern: .zone reference in a local +locals { + cftftest_zone_domain = cloudflare_zone.minimal.zone +} diff --git a/internal/resources/zone/v4_to_v5.go b/internal/resources/zone/v4_to_v5.go index a6ae0d0e..b42906d1 100644 --- a/internal/resources/zone/v4_to_v5.go +++ b/internal/resources/zone/v4_to_v5.go @@ -47,6 +47,21 @@ func (m *V4ToV5Migrator) GetResourceRename() ([]string, string) { return []string{"cloudflare_zone"}, "cloudflare_zone" } +// GetComputedAttributeMappings implements the ComputedAttributeMapper interface. +// In v4, the zone's domain was accessed as cloudflare_zone.example.zone. +// In v5, it's cloudflare_zone.example.name. This enables cross-file reference +// rewriting so that any resource referencing .zone gets updated to .name. +func (m *V4ToV5Migrator) GetComputedAttributeMappings() []transform.ComputedAttributeMapping { + return []transform.ComputedAttributeMapping{ + { + OldResourceType: "cloudflare_zone", + OldAttribute: "zone", + NewResourceType: "cloudflare_zone", + NewAttribute: "name", + }, + } +} + // TransformConfig handles configuration file transformations. // Transformations: // 1. zone → name @@ -103,4 +118,3 @@ func (m *V4ToV5Migrator) setAccountNestedAttribute(body *hclwrite.Body, accountI // Set the account attribute with the nested object body.SetAttributeRaw("account", tokens) } -