El presente artículo es un taller, vas a aprender como loco porque vamos a tomar un API que lo tengo en mi repo y lo vamos a subir a la nube de Azure mediante Azure CLI.
No se si les ha pasado a ustedes pero a mi sí, y varias veces, subir tu proyecto a Azure desde Visual Studio puede ser tedioso y agotador, además hay cosas que a veces no funcionan y uno no sabe bien porqué, eso hace perder tiempo y frustra, además como somos desarrolladores nos llevamos mejor con el código y los comandos de consola que con ventanas y asistentes, además eso de estar amarrado a VS obligatoriamente no me fascina, qué pasa si desarrollaste tu proyecto dotnet con VS Code?
Así que me puse manos a la obra y quise automatizar este proceso de publicar un proyecto API REST en la nube mediante el CLI que nos proporciona el mismo Azure, esto hace que con una línea yo pueda crear y configurar cualquier recurso de Azure desde mi ordenador sin importar el sistema operativo que tenga, ni el IDE que esté usando. Genial 🐿️
Esto quiere decir que vamos a publicar nuestro API REST mediante la línea de comandos que nos proporciona Azure, esta herramienta llamada Azure CLI la tendrás que instalar desde aquí en tu ordenador, vamos dale, instálalo.
Se sobreentiende que ya debes contar con una cuenta y suscripción activa a Azure, si no la tienes corre hazte una si quieres aprender e infórmate bien para que no metas la pataza.
Explicación de lo que vamos a hacer
Tengo un API REST hecho con .NET la cual tiene las siguientes funcionalidades:
- Autenticación y autorización con JWT Bearer Token e Identity
- Entity Framework Core Code First con SQL Server
- Logging mediante Applications Insights
- API Versioning
- Swagger
- Automapper
Al ejecutarla luce así:
No es en extremo compleja pero tiene funcionalidades muy comunes y utilizadas hoy en día.
Clona mi repo
Tendrás algo así
El proyecto luce así:
Vas a la carpeta LibraryNetCoreAPI donde está el .csproj del proyecto del API y debes añadir un archivo con extensión .bat y lo llamarás publish (o como prefieras)
Este archivo no debes subirlo a tu repositorio porque va a contener información sensible.
A estas alturas deberás haber instalado el Azure CLI, así que antes de copiar y pegar el batch, abre una consola en la misma carpeta y comprueba que lo tienes correctamente instalado, ejecuta:
az version
Genial, por lo visto el CLI de Azure está instalado correctamente.
Ahora inicia sesión con:
az login
Si tu cuenta de Azure tiene activado un inicio de sesión con MFA usarías az login --use-device-code
Una vez con la sesión inciada en el Azure CLI, esta herramienta pone a tu disposición una serie de comandos que te van a permitir crear y configurar todos tus servicios en la nube de Azure, podrías ejecutarlo uno a uno, o juntarlos todos en un sólo script como el que te mostraré más adelante.
Primero vamos a enumerar los distintos servicios en la nube de Azure que necesitaremos crear:
- Resource group
- App Service Plan
- App Service
- SQL Server
- SQL Database
- Application Insights
Para crear por ejemplo un Resource Group el comando tiene el siguiente formato:
az group create --name NombreDelGrupoDeRecursos --location NombreDeLaUbicación
Por supuesto, puedes añadirles cuantos parámetros necesites, esos son los mínimos básicos, aquí te dejo la documentación de Azure CLI.
Automatizando
Entonces ahora tu puedes decidir publicar tu proyecto ejecutando los comandos uno a uno, los podrías obtener del script a continuación, o configurar las variables del script según tus necesidades y ejecutarlo en lote.
El script está escrito en BATCH que es un lenguaje de scripting de Windows, si tu utilizas Linux/MacOS puedes cambiarlo a BASH, sólo requiere unos pocos ajustes de tuerca y como podrás notar en la parte inicial están definidas las variables que utilicé para usuarios, contraseñas y nombres de los recursos, tú puedes cambiarlos a otros valores válidos.
Si ejecutas las líneas de Azure CLI directamente en la consola pondrías los comandos del script despues de cada llamada call y al ser multiplataforma se ejecutan igual sin importar el sistema operativo subyacente.
En la primera vez que ejecutes el script es posible que te pida seleccionar tu suscripción de Azure, selecciona la tuya o pulsa enter.
@echo off
setlocal enabledelayedexpansion
::Batch para subir proyecto API REST a la nube de Azure
::Al definir las variables tener en cuenta que algunos nombres de recursos de Azure deben ser unicos a nivel mundial
::Se recomienda añadir el nombre del proyecto antes del nombre del recurso para identificarlo y evitar que ya exista
::Si ocurre algun error, detener el proceso en la consola con CTRL+C varias veces, ir al portal de Azure y eliminar todo el grupo de recursos, corregir y reintentar
::Aunque puedes añadir az-login al script, como no es necesario logarse cada vez que corras el script, ejecutalo antes
::El parametro de az login use-device-code se usa cuando usas MFA o authenticator.
::By Gerson Azabache - bravedeveloper.com
:: Obtener el tiempo de inicio
for /f "tokens=1-2 delims=: " %%a in ('time /t') do (
set startHour=%%a
set startMinute=%%b
)
:: DEFINICION DE variables // No usar espacios ni caracteres especiales
set dbAdminUser=usuariodb
set dbAdminPassword="Admin123"
set resourceGroup=libraryBraveDevRG
set appServicePlan=libraryBraveDevSP
set appServiceWebApp=libraryBraveDevWA
set dbServer=librarybravedevdbserver
set dbName=librarydb
set applicationInsightsApp=librarybravedevAI
::set IP_PUBLICA=x.x.x.x
call az version
:: call az login
:: call az login --use-device-code
:: Obteniendo automaticamente tu IP Publica y asignandola a la variable IP_PUBLICA
for /f "delims=" %%i in ('powershell -Command "(Invoke-WebRequest -uri http://ifconfig.me).Content"') do set IP_PUBLICA=%%i
echo 1/12: ========== Creando grupo de recursos ==========
call az group create --name %resourceGroup% --location eastus
echo 2/12: ========== Creando plan de App Service ==========
call az appservice plan create --name %appServicePlan% --resource-group %resourceGroup% --sku FREE
echo 3/12: ========== Creando aplicacion web ==========
call az webapp create --resource-group %resourceGroup% --plan %appServicePlan% --name %appServiceWebApp% --runtime "dotnet:8"
echo 4/12: ========== Creando servidor SQL ==========
call az sql server create --name %dbServer% --resource-group %resourceGroup% --location eastus --admin-user %dbAdminUser% --admin-password %dbAdminPassword%
echo 5/12: ========== Creando bd SQL ==========
call az sql db create --resource-group %resourceGroup% --server %dbServer% --name %dbName% --service-objective Basic --backup-storage-redundancy Local
echo 6/12: ========== Creando regla firewall para IP especifica y de accesos Azure ==========
call az sql server firewall-rule create --resource-group %resourceGroup% --server %dbServer% --name AllowMyPublicIP --start-ip-address %IP_PUBLICA% --end-ip-address %IP_PUBLICA%
call az sql server firewall-rule create --resource-group %resourceGroup% --server %dbServer% --name AllowAzureIps --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0
echo 7/12: ========== Creando Application insights y configurando ==========
call az extension add --name application-insights
call az monitor app-insights component create --app %applicationInsightsApp% --location eastus --resource-group %resourceGroup%
for /f "tokens=*" %%i in ('az monitor app-insights component show --app %applicationInsightsApp% --resource-group %resourceGroup% --query "connectionString" --output tsv') do set insightsConnection=%%i
echo !insightsConnection!
call az webapp config appsettings set --resource-group %resourceGroup% --name %appServiceWebApp% --settings "ApplicationInsights:ConnectionString"="!insightsConnection!"
echo 8/12: ========== Configurando cadena de conexion bd en webapp ==========
for /f "tokens=*" %%i in ('az sql db show-connection-string --server %dbServer% --name %dbName% --client ado.net --output tsv') do set defaultConnection=%%i
echo !defaultConnection!
:: Reemplazo valores <user> y <password> en la cadena de conexion
set "defaultConnection=!defaultConnection:<username>=%dbAdminUser%!"
set "defaultConnection=!defaultConnection:<password>=%dbAdminPassword%!"
call az webapp config connection-string set --resource-group %resourceGroup% --name %appServiceWebApp% --settings defaultConnection="!defaultConnection!" --connection-string-type SQLAzure
echo 9/12: ========== Configurando appsettings JWTKEY y ASPNETCORE_ENVIRONMENT ==========
call az webapp config appsettings set --resource-group %resourceGroup% --name %appServiceWebApp% --settings "JWTKey"=1VGSDF8VHDFBN88P7INGILDFY8U7KNMFHBVRWCGEW78WE0GC820CWG2FVC8VG80WE48G4W8EC4W1FV
call az webapp config appsettings set --resource-group %resourceGroup% --name %appServiceWebApp% --settings ASPNETCORE_ENVIRONMENT=Production
echo 10/12: ========== Publicando aplicacion ==========
call dotnet publish -c Release -o ./publish
echo 11/12: ========== Comprimiendo archivos de publicacion ==========
call powershell Compress-Archive -Path .\publish\* -DestinationPath .\publish.zip -Update
echo 12/12: ========== Desplegando aplicacion a Azure App Service ==========
call az webapp deployment source config-zip --resource-group %resourceGroup% --name %appServiceWebApp% --src ./publish.zip
echo Despliegue completado.
:: Obtener el tiempo de finalizacion
for /f "tokens=1-2 delims=: " %%a in ('time /t') do (
set endHour=%%a
set endMinute=%%b
)
:: Calculando la diferencia en minutos
set /a startTotalMinutes=startHour*60 + startMinute
set /a endTotalMinutes=endHour*60 + endMinute
set /a duration=endTotalMinutes - startTotalMinutes
:: Mostrar el tiempo total de ejecución
echo El script tuvo una duracion de %duration% minutos.
pause
endlocal
Si en algún punto de la ejecución tienes errores, cancela la operación con CTRL+C corrige y vuelve a intentar, normalmente debería funcionar, pero ya sabes como es esto, hay muchos factores involucrados, desde un nombre mal elegido configurado en las variables del script hasta un error local en tu ordenador o un comando deprecado...
Mientras se ejecuta el script he añadido comentarios e información relevante y un contador de minutos, mira todo el log que va mostrando para que sepas si algo falló y tengas que corregir o cambiar ✌️
Resultados
Si la ejecución fue exitosa al final verás algo así:
Ahora comprueba en tu portal de Azure y si no hubo errores en los pasos del script, tendrás todo publicado y operativo 💪😎 Quiere decir que haciendo unos pequeños ajustes a unos comandos, en cuestión de minutos tienes a tu aplicación en la nube?! 😉 así es mi crack 😎 y ya te olvidas de asistentes y ventanitas.
Y por supuesto, ahora prueba tu API
Registrando usuario:
Todo está funcionando correctamente, también puedes ver en tu portal de Azure que Applications Insights también estará trabajando al igual que tu base de datos.
Verifica también que en el script he añadido tu IP pública de forma dinámica, así puedes entrar a tu base de datos sin problemas.
No olvides cerrar el caño! 🚰
No te olvides de borrar todos tus servicios creados en la nube, recuerda que no es gratis todo y dejar instancias corriendo es potencialmente caro 🤑😶.
Para hacerlo de forma rápida elimina todo el Resource Group
Todos los comandos aquí ejecutados han sido elegidos con la configuración más austera posible, usando la capa gratuita siempre que sea posible como en el caso de AppServices, o la capa básica para la base de datos porque no tiene opción gratuita, tú puedes cambiar eso leyendo un poco la documentación de Azure CLI y modificando el script a tu gusto y necesidad. Disfrútalo y ya sabes la mejor forma de agradecer es compartir este artículo con todos tus colegas 🐿️💪🦊
Si esta entrada te ha gustado crack, y espero que así sea, compártela 🦊💪