Skip to main content

NTC Route53 Migration (v1 → v2)

This guide covers the migration of terraform-aws-ntc-route53 from v1.x to v2.x.

Overview of Changes

v2.0.0 introduces significant architectural improvements to simplify multi-region configurations:

Key Changes

Featurev1.xv2.x
Provider ArchitectureAWS Provider v5AWS Provider v6 with region attribute
DNSSEC ConfigurationSeparate moduleIntegrated into root module
Query Logs ConfigurationSeparate moduleIntegrated into root module
Multi-Region SupportMultiple provider aliases + module callsSingle module with regions configuration
Module Complexity3+ module calls neededSingle module call

Before & After Comparison

Previous approach required 3 separate module configurations:

# Main hosted zone module
module "ntc_route53" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-route53?ref=1.3.0"
# ... configuration
}

# Separate DNSSEC module
module "ntc_route53_dnssec" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-route53//modules/dnssec?ref=1.3.0"
zone_id = module.ntc_route53.zone_id
# ... configuration
providers = {
aws.us_east_1 = aws.use1
}
}

# Separate Query Logs module
module "ntc_route53_query_logging" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-route53//modules/query-logs?ref=1.3.0"
zone_id = module.ntc_route53.zone_id
# ... configuration
providers = {
aws.us_east_1 = aws.use1
}
}

Migration Steps

Step 1: Update Provider Configuration

Update the terraform.required_providers to use AWS Provider v6:

main.tf
terraform {
required_version = ">= 1.3.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

provider "aws" {
region = "eu-central-1"
}

provider "aws" {
alias = "euc1"
region = "eu-central-1"
}

provider "aws" {
alias = "euc2"
region = "eu-central-2"
}

provider "aws" {
alias = "use1"
region = "us-east-1"
}

Step 2: Consolidate Module Configuration

Extract DNSSEC and Query Log Configuration

If you have separate DNSSEC and Query Log modules, consolidate them:

# ---------------------------------------------------------------------------------------------------------------------
# ¦ NTC ROUTE53 - PUBLIC HOSTED ZONE
# ---------------------------------------------------------------------------------------------------------------------
module "ntc_route53" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-route53?ref=1.3.0"

zone_name = "mydomain.com"
zone_description = "Managed by Terraform"
zone_type = "public"
}

# ---------------------------------------------------------------------------------------------------------------------
# ¦ NTC ROUTE53 - DNSSEC (Separate Module)
# ---------------------------------------------------------------------------------------------------------------------
module "ntc_route53_dnssec" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-route53//modules/dnssec?ref=1.3.0"

zone_id = module.ntc_route53.zone_id

key_signing_keys = [
{
ksk_name = "ksk-1"
ksk_status = "active"
}
]

providers = {
aws.us_east_1 = aws.use1
}
}

# ---------------------------------------------------------------------------------------------------------------------
# ¦ NTC ROUTE53 - QUERY LOGGING (Separate Module)
# ---------------------------------------------------------------------------------------------------------------------
module "ntc_route53_query_logging" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-route53//modules/query-logs?ref=1.3.0"

zone_id = module.ntc_route53.zone_id

providers = {
aws.us_east_1 = aws.use1
}
}

Step 3: Add State Migration Blocks

Create a state_migrations.tf file to migrate resources without recreating them:

state_migrations.tf
# ---------------------------------------------------------------------------------------------------------------------
# ¦ STATE MIGRATIONS - v1.x to v2.x
# ---------------------------------------------------------------------------------------------------------------------
# These moved blocks ensure Terraform state is updated without recreating resources
# Run: terraform plan - should show only "moved" operations (no creates/destroys)
# After successful migration, this file can be deleted

# -------------------------------------------------------------------------------------------------------------------
# DNSSEC
# -------------------------------------------------------------------------------------------------------------------
moved {
from = module.ntc_route53_dnssec.aws_kms_alias.ntc_dnssec["ksk-1"]
to = module.ntc_route53.module.dnssec[0].aws_kms_alias.ntc_dnssec["ksk-1"]
}

moved {
from = module.ntc_route53_dnssec.aws_kms_key.ntc_dnssec["ksk-1"]
to = module.ntc_route53.module.dnssec[0].aws_kms_key.ntc_dnssec["ksk-1"]
}

moved {
from = module.ntc_route53_dnssec.aws_route53_hosted_zone_dnssec.ntc_dnssec["ksk-1"]
to = module.ntc_route53.module.dnssec[0].aws_route53_hosted_zone_dnssec.ntc_dnssec["ksk-1"]
}

moved {
from = module.ntc_route53_dnssec.aws_route53_key_signing_key.ntc_dnssec["ksk-1"]
to = module.ntc_route53.module.dnssec[0].aws_route53_key_signing_key.ntc_dnssec["ksk-1"]
}

# -------------------------------------------------------------------------------------------------------------------
# QUERY LOGS
# -------------------------------------------------------------------------------------------------------------------
moved {
from = module.ntc_route53_query_logging.aws_route53_query_log.ntc_query_log
to = module.ntc_route53.module.query_logs[0].aws_route53_query_log.ntc_query_log
}

moved {
from = module.ntc_route53_query_logging.aws_kms_key.ntc_query_log_encryption[0]
to = module.ntc_route53.module.query_logs[0].aws_kms_key.ntc_query_log_encryption[0]
}

moved {
from = module.ntc_route53_query_logging.aws_kms_alias.ntc_query_log_encryption[0]
to = module.ntc_route53.module.query_logs[0].aws_kms_alias.ntc_query_log_encryption[0]
}

moved {
from = module.ntc_route53_query_logging.aws_cloudwatch_log_resource_policy.ntc_query_log
to = module.ntc_route53.module.query_logs[0].aws_cloudwatch_log_resource_policy.ntc_query_log
}

moved {
from = module.ntc_route53_query_logging.aws_cloudwatch_log_group.ntc_query_log
to = module.ntc_route53.module.query_logs[0].aws_cloudwatch_log_group.ntc_query_log
}
State Migration Notes
  • These moved blocks tell Terraform to update its state without recreating resources
  • After successful migration (successful apply), you can delete state_migrations.tf
  • If you have different regions, adjust the region names accordingly

Step 4: Remove Old Definitions

After consolidating the configuration, remove the DNSSEC and Query Logs module calls.

Step 5: Initialize and Plan

# Upgrade to AWS Provider v6
terraform init -upgrade

# Review the plan
terraform plan

Expected plan output:

  • ✅ Many moved operations (state migrations)
  • ✅ Some in-place updates (configuration changes)
  • NO resource deletions or recreations

If you see deletions or recreations, do NOT apply! Review your configuration and state migration blocks carefully.

Step 6: Apply Migration

terraform apply

Monitor the output. The migration should complete without errors.

Step 7: Clean Up

After successful migration:

# Remove the state migration file (optional, but recommended)
rm state_migrations.tf

# Commit your changes
git add .
git commit -m "Migrate ntc-route53 from v1.x to v2.x"

Complete Example

See a complete before/after example in the GitHub repository:

Troubleshooting

Issue: Resources Being Recreated

Symptom: terraform plan shows deletions and recreations

Solution:

  1. Check your moved blocks match your existing state exactly
  2. Verify resource names haven't changed
  3. Use terraform state list to see current resource addresses

Issue: Provider Configuration Errors

Symptom: "provider configuration not present" errors

Solution:

  1. Ensure AWS Provider v6 is installed (terraform init -upgrade)
  2. Verify your required_providers block has version = "~> 6.0"

Issue: Region Not Supported

Symptom: "region not available" errors in ESC

Solution:

  1. For ESC, ensure you're using supported regions
  2. Check region codes match your partition (e.g., eu-central-1 vs eusc-de-east-1)

Need Help?