Problema

Exportar la definición de un Azure Resource Group a archivos Terraform (.tf) parece una tarea de pocos minutos: apuntar aztfexport al grupo, generar los archivos y listo. En la práctica, la operación se vuelve una lucha contra errores de arquitectura, límites de tiempo y memoria, y diferencias entre tipos de recursos (por ejemplo, Logic Apps Consumption vs Standard). El patrón recurrente es que la herramienta funciona en un entorno controlado, pero falla cuando se ejecuta en Cloud Shell o en máquinas con políticas restrictivas.

Causa

  1. Arquitectura incorrecta del binario
    aztfexport, terraform y la CLI de Azure se distribuyen en paquetes linux_amd64, linux_arm64, windows_amd64, etc. Ejecutar una versión ARM o 32‑bit en un contenedor Linux x86‑64 genera un error silencioso al intentar iniciar el proceso.

  2. Límites de Cloud Shell

    • Timeout de inactividad: la sesión se cierra después de 20 min sin interacción, aunque el proceso siga generando salida.
    • Memoria fija: cada trabajador de --parallelism consume RAM. Un valor alto provoca OOM rápidamente, terminando la exportación.
  3. Políticas de grupo en entornos corporativos
    Instaladores MSI o gestores de paquetes como winget pueden estar bloqueados. Solo los archivos zip “portables” que se extraen en el perfil del usuario pueden ejecutarse.

  4. Recursos que no aparecen en ARM
    Los Logic Apps Standard almacenan sus flujos (workflow.json) en un share de Files, no en la plantilla ARM. aztfexport no los detecta, generando recursos vacíos.

Solución

1. Verificar arquitectura antes de ejecutar

Descargar siempre el binario que coincida con la arquitectura del entorno donde se ejecutará. En Linux, comprobar con:

uname -m   # debe devolver x86_64 para linux_amd64

En PowerShell, validar $env:PROCESSOR_ARCHITECTURE antes de descargar.

2. Usar curl + unzip en Cloud Shell

El cliente .NET de PowerShell (Invoke-WebRequest + Expand-Archive) pierde el bit ejecutable. En Cloud Shell:

curl -L -o aztfexport.zip https://github.com/Azure/aztfexport/releases/download/vX.Y.Z/aztfexport_linux_amd64.zip
unzip aztfexport.zip -d $HOME/bin
chmod +x $HOME/bin/aztfexport
export PATH=$HOME/bin:$PATH

Repetir lo mismo para terraform y la CLI de Azure.

3. Ajustar paralelismo y limitar salida

Para la mayoría de los grupos, --parallelism 3 ofrece equilibrio entre velocidad y consumo de memoria. Añadir --hcl-only si solo se necesita la configuración y no el estado.

aztfexport export \
  --resource-group MyRG \
  --output ./tf \
  --parallelism 3 \
  --hcl-only

4. Ejecutar fuera de Cloud Shell cuando sea posible

En máquinas con restricciones, usar zip portable:

  1. Descargar Azure CLI, terraform y aztfexport como zip.
  2. Extraer en $HOME\.local\bin (Linux) o %USERPROFILE%\bin (Windows).
  3. Añadir la ruta al User PATH para que nuevas terminales la reconozcan.

En Windows PowerShell:

$zip = "C:\Temp\aztfexport_windows_amd64.zip"
Expand-Archive $zip -DestinationPath "$env:USERPROFILE\bin"
$env:Path += ";$env:USERPROFILE\bin"

5. Manejar Logic Apps Standard

Exportar el recurso ARM como siempre, pero luego descargar el contenido del share de Files:

  1. En el portal, abrir la cuenta de Storage vinculada.
  2. Navegar a fileShares/<app-name>/workflow.json.
  3. Descargar y versionar junto a los archivos .tf.

Para Logic Apps Consumption, el flujo está dentro del recurso ARM y se exporta sin pasos extra.

Cuándo aplicar esta solución

  • Síntomas: proceso de exportación se cuelga, muestra “Killed” o “error occurred trying to start process”.
  • Entorno: Cloud Shell, contenedores Linux, o VDI con políticas de instalación restrictivas.
  • Recurso: grupos que incluyen Logic Apps Standard, o cualquier recurso con artefactos externos no representados en ARM.

No aplicar cuando se dispone de una máquina de CI/CD con recursos ilimitados y sin restricciones de política; en esos casos, la configuración por defecto de aztfexport suele ser suficiente.

Código

# 1. Verificar arquitectura
if [[ "$(uname -m)" != "x86_64" ]]; then
  echo "Arquitectura no soportada: $(uname -m)"
  exit 1
fi

# 2. Descargar herramientas (ejemplo linux_amd64)
mkdir -p $HOME/bin
curl -L -o $HOME/bin/aztfexport.zip \
  https://github.com/Azure/aztfexport/releases/download/v0.5.0/aztfexport_linux_amd64.zip
unzip -o $HOME/bin/aztfexport.zip -d $HOME/bin
chmod +x $HOME/bin/aztfexport

curl -L -o $HOME/bin/terraform.zip \
  https://releases.hashicorp.com/terraform/1.9.0/terraform_1.9.0_linux_amd64.zip
unzip -o $HOME/bin/terraform.zip -d $HOME/bin
chmod +x $HOME/bin/terraform

export PATH=$HOME/bin:$PATH

# 3. Exportar con paralelismo bajo y solo HCL
aztfexport export \
  --resource-group MyResourceGroup \
  --output ./tf \
  --parallelism 3 \
  --hcl-only

Verificación

  1. Binarios correctos: ejecutar file $(which aztfexport) y file $(which terraform); la salida debe contener x86-64.
  2. Exportación completa: el directorio ./tf debe contener al menos un archivo .tf por recurso y un terraform.tfstate (si no usaste --hcl-only).
  3. Logic Apps Standard: abrir el directorio del share descargado y confirmar que workflow.json está presente y contiene el flujo esperado.
  4. Memoria: observar el uso de RAM con htop o top; el proceso no debe superar el límite de Cloud Shell (≈ 2 GB). Si supera, reducir --parallelism.

Notas adicionales

  • En Cloud Shell, cualquier salida escrita a la consola “resetea” el temporizador de inactividad. Mantener una interacción ligera (por ejemplo, echo .) cada 5 min evita el timeout.
  • Los nombres genéricos (res-0, res-1) que genera aztfexport son esperados; renombrar manualmente o usar terraform state rename facilita el mantenimiento.
  • Para entornos CI, montar un contenedor Docker con los binarios pre‑instalados elimina la necesidad de descargar en cada ejecución.
  • Cuando se trabaja con VDI bloqueado, siempre verifica que la política de ejecución de scripts (Set-ExecutionPolicy) permita scripts locales; de lo contrario, los binarios portables pueden ser marcados como no confiables.