Cómo importar infraestructura existente a Terraform con Terraformer

Cómo importar infraestructura existente a Terraform con Terraformer

En este artículo, te cuento sobre esta excelente herramienta para importar infraestructura existente a Terraform.

Hace un tiempo, en la serie que llamé Terraform Essentials, en el último capítulo, les mostré cómo importar infraestructura existente, pero había una limitación que tiene y es que no genera los archivos .tf sino que guarda todo en un .tfstate.

Terraform Essentials V: Cómo importar infraestructura existente a Terraform
En este artículo, que es el último de la serie Terraform Essentials, veremos como importar infraestructura existente a Terraform.

Gracias a Dios existe el Open Source y un montón de gente buena que comparte las soluciones que inventa para que las limitaciones que pueda tener una herramienta, desaparezcan.

Así que el día de hoy, les voy a hablar sobre una herramienta llamada Terraformer, la misma es capaz de importar la infraestructura existente y guardarla en archivos.tf, soporta un montón de proveedores, por supuesto es gratuita y la misma fue creada por el equipo SRE de Waze.

GoogleCloudPlatform/terraformer
CLI tool to generate terraform files from existing infrastructure (reverse Terraform). Infrastructure to Code - GoogleCloudPlatform/terraformer

Empecemos

Terraformer, básicamente lo que hace y de una manera muy sencilla es leer toda la infraestructura que tenemos en cualquier proveedor soportado y generar los archivos .tf, de esta manera, vamos a poder gestionar, no solo la nueva infraestructura, sino la existente, a través de Terraform.

Nota: Terraform debe estar instalado en la misma máquina donde correrá Terraformer.
Nota 2: Por el momento, Terraform es capaz de funcionar con Terraform 0.12.x, se están haciendo trabajos para ser compatibles con última versión.

Instalación

Vamos a instalar Terraformer. Para eso, debemos clonar el repositorio del proyecto:

$ git clone https://github.com/GoogleCloudPlatform/terraformer.git

Entramos al directorio

$ cd terraformer

Si no tenés golang instalado, debemos hacerlo, para eso ejecutaremos:

$ sudo apt install golang-go

Una vez instalado, vamos a correr...

$ go mod download

Luego tenemos que "buildear" Terraformer para todos los proveedores o para el cual queramos trabajar. Si usas varios proveedores, podes bajar todos los complementos corriendo:

$ sudo go build -v

O, si, como en este caso que les voy a mostrar solo importas infraestructura de DigitalOcean, podes correrlo así:

$ sudo go run build/main.go digitalocean

Tené en cuenta que haciéndolo así 👆, el ejecutable te va a quedar como terraform-digitalocean.

Por último movemos el ejecutable a la carpeta /usr/local/bin:

$ sudo cp terraformer-digitalocean /usr/local/bin

La instalación estaría pronta, podemos ejecutar lo siguiente para ver si ejecuta bien.

$ terraformer-digitalocean

La devolución sería algo como esto:

Usage:
   [command]

Available Commands:
  help        Help about any command
  import      Import current state to Terraform configuration
  plan        Plan to import current state to Terraform configuration
  version     Print the version number of Terraformer

Flags:
  -h, --help      help for this command
  -v, --version   version for this command

Una vez instalado, comenzamos a ajustar algunas cosillas para importar...

Importación

Como les comenté más arriba, voy a importar la infra que tengo corriendo en DigitalOcean, en este momento no es mucha más que nombres de dominio, pero tranquilamente se puede usar para importar droplets u otros recursos y no solo desde DigitalOcean.

Vamos a crear una carpeta llamada ¨do¨:

$ mkdir do && cd do

Vamos a generar un archivo llamado init.tf, en el mismo definiremos el proveedor al cual queremos conectarnos, en este caso será DigitalOcean, así que mi archivo se ve algo así:

$ vim init.tf
provider "digitalocean" {}

Pasamos nuestra API key de DigitalOcean como variable de entorno. La misma la pueden generar desde aquí:

DigitalOcean – The developer cloud
Helping millions of developers easily build, test, manage, and scale applications of any size – faster than ever before.
$ export DIGITALOCEAN_TOKEN=<api-key>

Luego debemos iniciar el plugin de DigitalOcen para Terraform, así que ejecutaremos:

$ terraform init

El output de este comando se deberá ver algo así:


Initializing the backend...

Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "digitalocean" (terraform-providers/digitalocean) 1.22.2...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.digitalocean: version = "~> 1.22"


Warning: registry.terraform.io: For users on Terraform 0.13 or greater, this provider has moved to digitalocean/digitalocean. Please update your source in required_providers.


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.

A partir de aquí, podemos comenzar a importar nuestra infraestructura.

Para hacerlo, debemos invocar el ejecutable, la acción, el provider y el recurso. Por ejemplo, en mi caso para importar los dominios y sus registros, corrí lo siguiente:

$ terraformer-digitalocean import digitalocean plan -r domain

El output de eso fue todo esto:

2020/10/02 10:59:51 digitalocean importing... domain
2020/10/02 11:00:06 Refreshing state... digitalocean_domain.tfer--cduser-002E-com
2020/10/02 11:00:06 Refreshing state... digitalocean_domain.tfer--cloudforgood-002E-xyz
2020/10/02 11:00:06 Refreshing state... digitalocean_domain.tfer--en-002E-cduser-002E-com
2020/10/02 11:00:06 Refreshing state... digitalocean_domain.tfer--incusdrive-002E-com
2020/10/02 11:00:06 Refreshing state... digitalocean_domain.tfer--xcellere-002E-com
2020/10/02 11:00:06 Refreshing state... digitalocean_domain.tfer--xcellere-002E-xyz
2020/10/02 11:00:06 Refreshing state... digitalocean_record.tfer--8423394
2020/10/02 11:00:06 Refreshing state... digitalocean_record.tfer--8423395
...
2020/10/02 11:00:10 digitalocean Connecting....
2020/10/02 11:00:10 digitalocean save domain
2020/10/02 11:00:10 digitalocean save tfstate for domain
Reduje el output porque es mucho más largo.

Lo siguiente que veremos es que generó una carpeta llamada ¨generated¨, entraremos ahí, luego habrá otra con el nombre del proveedor, en este caso DigitalOcean, el recurso que importamos y adentro los archivos .tf con su respectivo .tfstate.

drwxrwxr-x 2 ubuntu ubuntu   4096 Oct  2 11:00 ./
drwxrwxr-x 4 ubuntu ubuntu   4096 Oct  2 11:06 ../
-rwxrwxr-x 1 ubuntu ubuntu    935 Oct  2 11:00 domain.tf*
-rwxrwxr-x 1 ubuntu ubuntu  10707 Oct  2 11:00 outputs.tf*
-rwxrwxr-x 1 ubuntu ubuntu     52 Oct  2 11:00 provider.tf*
-rwxrwxr-x 1 ubuntu ubuntu  23260 Oct  2 11:00 record.tf*
-rwxrwxr-x 1 ubuntu ubuntu 132703 Oct  2 11:00 terraform.tfstate*

Si abro el archivo domain.tf, que es el que más me interesa, veo que me trajo todos los dominios:

resource "digitalocean_domain" "tfer--cduser-002E-com" {
  name = "cduser.com"
}

resource "digitalocean_domain" "tfer--cloudforgood-002E-xyz" {
  name = "cloudforgood.xyz"
}

resource "digitalocean_domain" "tfer--en-002E-cduser-002E-com" {
  name = "en.cduser.com"
}

resource "digitalocean_domain" "tfer--incusdrive-002E-com" {
  name = "incusdrive.com"
}

Ahora, vos me dirás pero importar recurso por recurso no es para nada eficiente y lo que te respondo es: tenés razón, pero Terraformer puede importar proyectos enteros. En mi caso pude importar todo un proyecto de DigitalOcean con sus dominios, spaces y droplets. Lo que si, es que debemos definir todos los recursos en la misma "orden":

terraformer-digitalocean import digitalocean -r droplet,ssh_key,volume,project <id-proyecto>

Para ir cerrando

Como ven, no es nada del otro mundo importar infra a Terraform con Terraformer.

Tengan en cuenta lo que les mencione más arriba con respecto a la versión de Terraform y también que la cantidad de proveedores es un poco más limitada, acá pueden ver la lista de los que están soportados en este momento:

GoogleCloudPlatform/terraformer
CLI tool to generate terraform files from existing infrastructure (reverse Terraform). Infrastructure to Code - GoogleCloudPlatform/terraformer

Espero que les haya servido y como siempre digo, cualquier duda o consulta, no duden en dejar un comentario.