El comando terraform import nos permite importar en HashiCorp Terraform recursos que ya existían previamente en el proveedor con el que estemos trabajando, es este caso AWS. Sin embargo, sólo permite importar dichos registros uno por uno, con una ejecución de terraform import cada vez. Esto, aparte de ser tremendamente tedioso, en algunas situaciones se vuelve directamente impracticable. Este es el caso de los registros de una zona DNS de Route53. La tarea puede resultar inabarcable si tenemos varias zonas DNS, y cada una tiene decenas o cientos de registros. En este artículo te ofrezco un script en bash que te permitirá importar en Terraform todos los registros de una zona DNS de Route53 en cuestión de segundos o de pocos minutos.
Requisitos previos
Para poder llevar a cabo el procedimiento descrito en este artículo necesitarás tener instalada y configurada la herramienta aws cli de Amazon y la herramienta jq disponible en la mayoría de distribuciones de Linux.
Procedimiento
Puedes llevar a cabo la importación siguiendo estos sencillos pasos. Puedes saltarte los pasos 1 y 2 e ir directamente al 3 si ya tienes tu proyecto de Terraform correctamente configurado:
1.- Crea una nueva carpeta de proyecto de Terraform y configura el proveedor a través del siguiente fichero main.tf:
provider "aws" { region = "eu-west-1" access_key = "XXXXXXXXXXXXXXXXXXXX" secret_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }
2.- Inicia el nuevo proyecto de Terraform:
$ terraform init Initializing the backend... Initializing provider plugins... - Finding latest version of hashicorp/aws... - Installing hashicorp/aws v3.74.1... - Installed hashicorp/aws v3.74.1 (signed by HashiCorp) Terraform has created a lock file .terraform.lock.hcl to record the provider selections it made above. Include this file in your version control repository so that Terraform can guarantee to make the same selections by default when you run "terraform init" in the future. Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.
3.- Ejecuta el siguiente script:
Recuerda asignar previamente el valor adecuado para las variables zone_name, zone_id, y también la aws_profile si utilizas distintos perfiles en la herramienta aws cli para manejar distintas cuentas de AWS.
#! /bin/bash # This script retrieves all DNS records from AWS Route53 DNS zone and imports all of them to Terraform zone_name='example.com' zone_id='XXXXXXXXXXXXXXXXXXXXX' aws_profile='example_com' # Get zone slug from zone name zone_slug=$(echo ${zone_name} | tr '.' '-') # Get DNS zone current data from AWS zone="$(aws --profile=${aws_profile} route53 list-hosted-zones | jq '.HostedZones[] | select (.Id | contains("'${zone_id}'"))')" # Another method to get DNS zone data searching by zone name instead of zone ID #zone="$(aws --profile=${aws_profile} route53 list-hosted-zones | jq '.HostedZones[] | select (.Name=="'${zone_name}'.")')" zone_comment="$(echo ${zone} | jq '.Comment')" if [ "${zone_comment}" == 'null' ];then zone_comment="${zone_name} zone" fi # Write aws_route53_zone resource to terraform file cat << EOF > dns-zone-${zone_name}.tf resource "aws_route53_zone" "${zone_slug}" { name = "${zone_name}" comment = "${zone_comment}" } EOF # Import DNS zone and records from file to terraform terraform import "aws_route53_zone.${zone_slug}" "${zone_id}" # Retrieve all regular records (not alias) from DNS zone and write them down to terraform file IFS=$'\n' for dns_record in $(aws --profile="${aws_profile}" route53 list-resource-record-sets --hosted-zone-id "${zone_id}" | jq -c '.ResourceRecordSets[] | select(has("AliasTarget") | not)');do name="$(echo ${dns_record} | jq -r '.Name')" type="$(echo ${dns_record} | jq -r '.Type')" name_slug="$(echo ${type}-${name} | sed -E 's/[\._\ ]+/-/g' | sed -E 's/(^-|-$)//g')" ttl="$(echo ${dns_record} | jq -r '.TTL')" records="$(echo ${dns_record} | jq -cr '.ResourceRecords' | jq '.[].Value' | sed 's/$/,/')" records="$(echo ${records} | sed 's/,$//')" cat << EOF >> dns-zone-${zone_name}.tf resource "aws_route53_record" "${name_slug}" { zone_id = aws_route53_zone.${zone_slug}.zone_id name = "${name}" type = "${type}" ttl = "${ttl}" records = [${records}] } EOF # Import DNS record to Terraform terraform import "aws_route53_record.${name_slug}" "${zone_id}_${name}_${type}" done # Retrieve all alias records from DNS zone and write them down to terraform file IFS=$'\n' for dns_record in $(aws --profile="${aws_profile}" route53 list-resource-record-sets --hosted-zone-id "${zone_id}" | jq -c '.ResourceRecordSets[] | select(has("AliasTarget"))');do name="$(echo ${dns_record} | jq -r '.Name')" type="$(echo ${dns_record} | jq -r '.Type')" name_slug="$(echo ${type}-${name} | sed -E 's/[\._\ ]+/-/g' | sed -E 's/(^-|-$)//g')" alias_name="$(echo ${dns_record} | jq -cr '.AliasTarget' | jq -r '.DNSName')" cat << EOF >> dns-zone-${zone_name}.tf resource "aws_route53_record" "${name_slug}" { zone_id = aws_route53_zone.${zone_slug}.zone_id name = "${name}" type = "${type}" alias { name = "${alias_name}" zone_id = "${zone_id}" evaluate_target_health = true } } EOF # Import DNS record to Terraform terraform import "aws_route53_record.${name_slug}" "${zone_id}_${name}_${type}" done
El script va generando en el directorio desde el que se ejecuta un fichero .tf con todos los registros DNS existentes en Route53, y al mismo tiempo los va importando en Terraform para a partir de que finalice poder empezar a gestionar estos recursos con Terraform. La ejecución del script tardará varios minutos dependiendo del número de registros que tenga la zona a importar, pero es un procesos totalmente desatendido que no requerirá ningún esfuerzo por tu parte. ¡Espero que te sea útil!
Deja una respuesta