Mil SMS desde el entorno de pruebas
Una app de comida a domicilio de Sevilla prepara una versión nueva. El equipo la prueba en un servidor aparte.
Pero el número de envío de SMS está escrito en el código. Durante las pruebas, mil clientes reales reciben "Tu pedido está en camino" sin haber pedido nada.
Esta lección enseña dónde van los ajustes para que esto no pase.
Al final de esta lección
Nota
Puedo dejar los ajustes de una aplicación fuera de su código.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Configuración | los ajustes de una aplicación | |
| Entorno | un lugar donde se ejecuta la aplicación | pruebas, producción |
| Variable de entorno | un ajuste que el sistema da al programa | PORT=5000 |
| Valor por defecto | el valor que se usa si falta el ajuste | |
| Secreto | un ajuste que nadie más debe ver | una contraseña |
| Gestor de secretos | un servicio que guarda secretos con permisos |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
El código es el mismo en cada entorno
Una aplicación suele vivir en varios entornos: el portátil, el servidor de pruebas y producción.
El código tiene que ser idéntico en todos. Es el que pasó las pruebas del pipeline.
Lo que cambia es la configuración: la base de datos, el puerto, si se envían SMS. Por eso la configuración sale del código y llega desde fuera.
Qué cambia y qué no
| Ajuste | Pruebas | Producción |
|---|---|---|
| Base de datos | bd-pruebas.interna | bd-prod.interna |
| Puerto | 5000 | 8080 |
| Avisos por SMS | No | Sí |
| Versión del código | 3.2 | 3.2 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Las variables de entorno llevan los ajustes
La forma más común de dar un ajuste es una variable de entorno. El sistema la entrega al programa cuando lo arranca.
En Python se leen con os.environ. Un ajuste obligatorio da error si falta. Uno opcional usa un valor por defecto.
Ejecuta el bloque y haz el cambio del último comentario.
Leer ajustes en Python
import os
# En el trabajo, estas dos líneas no existen: el sistema da las variables.
os.environ["SMS_ENABLED"] = "no"
os.environ["DB_HOST"] = "bd-pruebas.interna"
db_host = os.environ["DB_HOST"] # obligatoria: sin ella, error
port = os.getenv("PORT", "8000") # opcional: si falta, 8000
sms = os.environ["SMS_ENABLED"] == "si"
print("Base de datos:", db_host)
print("Puerto:", port)
print("Avisos por SMS a clientes:", sms)
# Cambia SMS_ENABLED a "si" y ejecuta otra vez.
Un guion, dos entornos
mkdir -p reparto && cd reparto
cat > arrancar.sh <<'FIN'
echo "[$APP_ENV] base: $DB_HOST, puerto: ${PORT:-8000}"
FIN
# El mismo guion, dos entornos distintos
APP_ENV=pruebas DB_HOST=bd-pruebas.interna PORT=5000 bash arrancar.sh
APP_ENV=produccion DB_HOST=bd-prod.interna bash arrancar.sh
# Añade PORT=8080 delante de la línea de producción y ejecuta.
Un secreto no entra en el repositorio
Una contraseña o una clave de un servicio de pago es un secreto. No se escribe en el código.
En el portátil se suele guardar en un archivo .env, y ese archivo se añade a .gitignore.
En producción, el secreto vive en un gestor de secretos. Ese servicio decide quién puede leerlo y anota cada lectura.
Un error frecuente
Advertencia
Mucha gente cree que un repositorio privado es un buen sitio para una contraseña. No lo es. La ve cualquiera con acceso, incluidos antiguos compañeros, y queda en cada copia y en el historial. Si una contraseña llega al repositorio, se cambia.
Dónde va cada cosa
| Elemento | Código | Variable de entorno | Gestor de secretos |
|---|---|---|---|
| Cómo se calcula el precio del envío | Sí | No | No |
| El puerto | No | Sí | No |
| La contraseña de la base de datos | No | No | Sí |
| La clave de la pasarela de pago | No | No | Sí |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.