Skip to content

Migration Guides

Chris Buckley edited this page Feb 13, 2025 · 2 revisions

This page provides details for migrating between major versions.

v4 to v5 (Cloudflare DNS module)

Version 5 is a major rewrite of the Cloudflare provider. The biggest impact on this module is the rename of the cloudflare_record resource to cloudflare_dns_record. Cloudflare's migration guide provides some advice for migrating from v4 to v5, but their Grit scripts do not work with modules. We provide further advice below.

First, take a copy of your terraform state, which will be used to loop over the resources and can also be used to restore the previous state in case of any serious problems. You should do this before upgrading the module/provider:

terraform state pull > backup.tfstate

Loop through resources in the state file and remove them. This removes any cloudflare_zone and cloudflare_record resources in any module, so you may need to alter the filter to select specific modules:

jq -r '.resources[]
    | select(.module and (.type | IN("cloudflare_record", "cloudflare_zone")))
    | {module: .module, type, name, instance: .instances[]}
    | (.module + "," + .type + "," + .name + "," + .instance.index_key)
' backup.tfstate | while IFS=, read module type name ix; do
    echo terraform state rm "$module.$type.$name[\"$ix\"]"
    terraform state rm "$module.$type.$name[\"$ix\"]"
done

Update the module source to use ?ref=v5 and run terraform init -upgrade.

Then, import the new records using the appropriate IDs (you may need to alter the filter again per above):

jq -r '.resources[]
    | select(.module and (.type == "cloudflare_zone"))
    | {module: .module, type, name, instance: .instances[]}
    | (.module + "," + .type + "," + .name + "," + .instance.index_key + "," + .instance.attributes.id)
' backup.tfstate | while IFS=, read module type name ix id; do
    echo terraform import "$module.$type.$name[\"$ix\"]" "$id"
    terraform import "$module.$type.$name[\"$ix\"]" "$id"
done

jq -r '.resources[]
    | select(.module and (.type == "cloudflare_record"))
    | {module: .module, name, instance: .instances[]}
    | (.module + "," + .name + "," + .instance.index_key + "," + .instance.attributes.zone_id + "/" + .instance.attributes.id)
' backup.tfstate | while IFS=, read module name ix id; do
    echo terraform import "$module.cloudflare_dns_record.$name[\"$ix\"]" "$id"
    terraform import "$module.cloudflare_dns_record.$name[\"$ix\"]" "$id"
done

Run a terraform apply and review the changes. All resources will show that they need to be updated in-place - this is to be expected and should not impact the DNS configuration. No resources should be forced to be replaced.

If you run into any issues part way through the apply, you can restore the old state with terraform state push -force backup.tfstate.

Clone this wiki locally