lunes, 20 de marzo de 2023

Gestionando la configuración de nuestras aplicaciones (2/x)

A raíz de la entrada anterior, surgió una interesante conversación en twitter (algo que me resultó muy satisfactorio, pues es uno de mis objetivos al escribir es generar debate):

 

Javier Campos @javiercampos • 7 mar. 
En respuesta a @javiercampos y @snavarropino 
En mi caso, estamos migrando a un proveedor de "configuración de 
aplicación" que lee de un datastore común a todos los procesos, y lo que 
se configura en "el proceso" (appsettings/entorno) es ese proveedor de 
configuración 
11,1 19 
Javier Campos @javiercampos • 7 mar. 
En respuesta a @javiercampos y @snavarropino 
Y si, se puede implementar ese proveedor fácilmente para IConfiguration, 
pero no hay una forma fácil para tener un IConfiguration que configure 
ese proveedor (se puede hacer de otros modos) 
11,1 22 
Javier Campos @javiercampos • 7 mar. 
En respuesta a @javiercampos y @snavarropino 
Es decir, si tu haces un proveedor que lea (un key/valor, sencillo) desde 
una BD y Io meta en IConfiguration (igual que se leen los appsettings o el 
entorno), donde configuras la cadena de conexión -a ese- proveedor? Se 
puede hacer, pero no es amigable (en .NET al menos) 
Javier Campos @javiercampos • 7 mar. 
En respuesta a @javiercampos y @snavarropino 
(básicamente, el método es hacer un proveedor de 'Configuration para 
leer esa cadena de conexión -puede ser appsettings/entorno-, crear la 
configuración, leer la conexión [un IOptions o similar], y luego crear -otro 
'Configuration con tu proveedor metido)

 

Javier exponía que en uno de sus proyectos, estaban tratando de hacer lo siguiente:

 

Configurar tu proceso, mediante mecanismos tipos fichero json o variable de entorno, para indicar de donde tiene que leer la configuración necesaria para ejecutarse.

 

Si he entendido bien, Javier pretende definir, en tienpo de ejecución, el proveedor del que se van a leer los valores de configuración que tu aplicación necesita.

 

Me sorprende, porque realmente no es necesario en .NET, que dispone de un mecanismo de configuración en el que configuramos uno o más proveedores para que resuelvan la configuración. Estos proveedores están priorizados, de modo que si se resuelven varios, uno de ellos "mandará".

 

Por lo tanto, no es necesario configurar en tiempo de ejecución el proveedor que quieres, solo has de dejar todos preparados, y en cada entorno configurar como quieres. Por ejemplo, puedes preparar la siguiente configuración:

 

  1. Fichero json appSettings.json
  2. Fichero json específico de un entorno: appSettings.Production.json o appSettings.Staging.json por ejemplo
  3. Variables de entorno

 

Esto se hace así:

 

 

 

En el fichero appSettings.json estarán los valores comunes, y por ejemplo, puedo poner en el entorno de staging un fichero appSettings.Staging.json que los sobrescriba, prevaleciendo estos (si te fijas en el código, cuanto más abajo el proveedor tendrá más "peso").


Y finalmente, para producción (imaginad que esto se ejecuta en un kubernetes) podría setearía variables de entorno por cada par clave/valor del fichero json, y estas variables de entorno prevalecerían sobre los valores del fichero.

 

¿Cómo le decimos a la aplicación en que entorno está?

 

Por defecto estará en Producción, y setearemos otros entorno mediante una variable de entorno (valga la redundancia), que tradicionalmente ha sido ASPNETCORE_ENVIRONMENT.

 

Sin embargo hay otros modos, como la variable DOTNET_ENVIRONMENT o el parámetro en line de comandos que podemos pasar a dotnet run:

 

dotnet run --environment <entorno>

 

Todo lo tenéis aquí detallado.


Sin duda algo se me escapa... espero que Javier me lo aclare. Mientras tanto seguiré preparando la siguiente entrada del blog. Os dejo una pregunta para abrir boca:


Si tenemos microservicios o simplemente un sistema distribuido, ¿cómo configuramos valores que deben estar presentes en varios servicios (por ejemplo la url del proveedor de identidad)? ¿Repetimos la configuración en cada servicio?


Veremos como evitarlo en la siguiente entrada sobre configuración centralizada