Intercambio del metadata sin sesión#
El intercambio del metadata sin sesión deja que un script o la integración continua exporten el metadata de una conexión como paquete, lo analicen en otra y lo importen, sin cookies ni contraseñas. Sirve para automatizar el paso de desarrollo a pruebas y a producción, y para guardar el metadata en un repositorio de código.
Antes de empezar#
- La credencial la crea quien tiene Administración del Sistema, a nombre de un usuario que tenga Administración del Metadata (véase Credenciales de servicio). Su ámbito es Intercambio del metadata y va sola.
- Lo que se hace es lo mismo que Exportar e importar del editor del metadata, con las mismas reglas y el mismo informe. Conviene conocer antes ese proceso en la aplicación (véase el capítulo del metadata).
- En cada petición se vuelven a leer los privilegios del titular: si pierde Administración del metadata, la credencial deja de servir (
403 NOT_ALLOWED).
Funciona también en una instalación que solo entra con el inicio de sesión único, donde no hay contraseñas que poner en un script.
Crear la credencial#
- Vaya a Administración › Credenciales y pulse Nueva credencial….
- En Ámbito, elija Intercambio del metadata.
- Elija el Titular: un usuario con Administración del metadata. Los demás aparecen sin poder elegirse.
- Escriba el Nombre del cliente («Integración continua del metadata») y la caducidad: 90 días por defecto, como mucho 365.
- Pulse Crear credencial y guarde el secreto en el almacén de secretos de la integración continua.
Consejo
Cree un usuario dedicado, con Administración del metadata y nada más, como titular de la credencial del script. Así la auditoría distingue lo que hace el script de lo que hacen las personas, y puede quitarle el privilegio sin afectar a nadie.
Rutas#
Todas van bajo /api/metadata-exchange/v1, con Authorization: Bearer ect_…. La cookie de sesión no sirve.
| Ruta | Qué hace |
|---|---|
GET /connections |
Las conexiones que puede usar el titular: [{ id, name, engine, hasMetadata }]. Si la credencial se limita a unas, solo esas. |
GET /connections/{c}/export?rowFilters=&diagram=&groupings= |
El paquete, un .zip. La cabecera X-ECenter-Export-Summary resume lo que lleva. |
POST /connections/{c}/imports[?preview=true][&confirmed=true] |
Sube el paquete y lanza el análisis (preview=true) o la importación: 202 { job, status } con Location. |
GET /connections/{c}/imports/{job}[?wait=30s][&format=csv] |
El informe del trabajo cuando termina, o 202 si sigue tras esperar wait (10 s si no se dice; como mucho 30 s). Con format=csv, el informe en CSV. |
Opciones de la exportación:
| Parámetro | Por defecto | Qué hace |
|---|---|---|
rowFilters |
false |
Lleva también los universos. |
diagram |
true |
Lleva la disposición del diagrama de relaciones. |
groupings |
true |
Lleva las agrupaciones con sus valores. |
El paquete no lleva nada de la instalación (ni la URL de la conexión, ni su usuario, ni logins), y dos exportaciones del mismo metadata dan el mismo fichero: se puede versionar en Git y comparar.
El recorrido#
1. Exportar#
export ECENTER_URL=https://desarrollo.ecenter.example.org
export ECENTER_METADATA_TOKEN=ect_…
curl -s "$ECENTER_URL/api/metadata-exchange/v1/connections/$ORIGEN/export" \
-H "Authorization: Bearer $ECENTER_METADATA_TOKEN" -o metadata.zip
2. Analizar en el destino#
Se sube el paquete como multipart/form-data con dos partes: package (el zip) y, opcionalmente, options (JSON).
curl -s -X POST "$ECENTER_URL/api/metadata-exchange/v1/connections/$DESTINO/imports?preview=true" \
-H "Authorization: Bearer $ECENTER_METADATA_TOKEN" \
-F "package=@metadata.zip;type=application/zip" \
-F 'options={"missing":"KEEP"};type=application/json'
| Opción | Qué hace |
|---|---|
schemas |
Empareja el nombre lógico de un esquema del paquete con un esquema del destino: { "COMERCIAL": "PROD_COMERCIAL" }. |
privileges |
Empareja a mano la clave de un privilegio del paquete con un privilegio del destino. |
createPrivileges |
true crea, sin asignarlos a ningún rol, los privilegios del paquete que falten. |
missing |
KEEP (por defecto) conserva lo que está en el destino y no en el paquete; REMOVE lo elimina. |
diagram |
IF_EMPTY (solo si el destino no tiene disposición), REPLACE o KEEP. |
basis |
La base de un análisis anterior (abajo). |
3. Leer el informe#
curl -s "$ECENTER_URL/api/metadata-exchange/v1/connections/$DESTINO/imports/4b1d…?wait=30s" \
-H "Authorization: Bearer $ECENTER_METADATA_TOKEN"
Mientras el trabajo sigue, responde 202; repita la petición. Al terminar, 200 con el informe:
{
"outcome": "ANALYZED",
"basis": "sha256:9f2c…",
"tallies": [
{ "kind": "FACT_TABLE", "inPackage": 8, "created": 1, "changed": 2, "unchanged": 5,
"onlyInTarget": 0, "removed": 0, "pairedByName": 0 } ],
"issues": [ { "severity": "WARNING", "code": "NOT_IN_CATALOG", "kind": "FACT_TABLE",
"element": "Devoluciones",
"message": "La tabla PROD_COMERCIAL.DEVOLUCIONES no existe en la base de datos" } ],
"impact": { },
"requiresConfirmation": true
}
outcome:ANALYZED,IMPORTED,REJECTED(hay errores),METADATA_IN_USE,METADATA_IMPACT(el cambio afecta a documentos que lo usan) oMETADATA_CHANGED(el destino cambió desde el análisis).issues[].severity:ERRORimpide importar;WARNINGhay que confirmarlo;INFOes para saberlo.requiresConfirmation: hay avisos o un impacto que una persona debería revisar.- El informe nunca trae condiciones de universos ni fragmentos de SQL.
4. Importar#
Con la base del análisis, para que la importación no entre si el destino ha cambiado entre medias:
curl -s -X POST "$ECENTER_URL/api/metadata-exchange/v1/connections/$DESTINO/imports" \
-H "Authorization: Bearer $ECENTER_METADATA_TOKEN" \
-F "package=@metadata.zip;type=application/zip" \
-F 'options={"missing":"KEEP","basis":"sha256:9f2c…"};type=application/json'
El paquete viaja en cada petición: el servidor no lo guarda entre el análisis y la importación. Si el análisis pedía confirmación, la importación necesita además confirmed=true; antes de añadirlo en un script, piense si de verdad quiere aceptar sin revisar lo que ha cambiado.
El script de ejemplo#
El repositorio trae tools/demo-data/metadata_promote.py, en Python y sin dependencias, que hace todo el recorrido como lo haría la integración continua y solo importa si no hay nada que confirmar:
export ECENTER_URL=https://ecenter.example.org
export ECENTER_METADATA_TOKEN=ect_…
python3 tools/demo-data/metadata_promote.py --source "Desarrollo" --target "Producción" --analyze-only
| Opción | Qué hace |
|---|---|
--source, --target |
La conexión de origen y la de destino, por su nombre o su identificador. |
--analyze-only |
Solo analiza; nunca importa. |
--package, --save |
Promociona un paquete guardado en lugar de exportar el origen; guarda el exportado en un fichero. |
--row-filters, --no-diagram, --no-groupings |
Las opciones de la exportación. |
--remove-missing |
Elimina del destino lo que no está en el paquete. |
--create-privileges |
Crea sin asignar los privilegios que falten. |
Sus códigos de salida sirven para decidir en la integración continua:
| Código | Significado |
|---|---|
| 0 | Promocionado (o, con --analyze-only, analizado sin nada que confirmar). |
| 2 | Hay algo que confirmar: decídalo una persona en el asistente de importación de la aplicación. No se ha aplicado nada. |
| 3 | Errores o algo que lo impide. No se ha aplicado nada. |
| 4 | El destino ha cambiado desde el análisis: vuelva a lanzarlo. |
| 1 | Ha fallado la API o la red. |
Errores#
| HTTP | code |
Cuándo |
|---|---|---|
| 400 | INVALID_PACKAGE |
No es un zip, falta el manifiesto o un fichero no se lee. |
| 400 | UNSUPPORTED_FORMAT |
El paquete es de una versión más nueva de ECenter. |
| 400 | INVALID_REQUEST |
Las opciones no son válidas. |
| 403 | NOT_ALLOWED |
El titular ya no tiene Administración del metadata, o la credencial no incluye la conexión. |
| 404 | NOT_FOUND |
La conexión o el trabajo no existen, o el trabajo no es de esta credencial. |
| 409 | IMPORT_IN_PROGRESS |
Hay otra importación o restauración en curso en esa conexión. |
| 409 | JOB_CANCELED |
El trabajo se canceló (por ejemplo, al revocar la credencial). No dejó nada. |
| 410 | RESULT_EXPIRED |
El informe ya no se conserva. |
| 413 | PACKAGE_TOO_LARGE |
El paquete pasa de los topes. |
| 500 | JOB_FAILED |
El trabajo ha fallado. |
Seguridad y auditoría#
- El trabajo corre con la identidad del titular y solo lo ve esa misma credencial: desde una sesión del mismo usuario,
404. - Revocar la credencial, o inhabilitar, bloquear o borrar al titular, corta en la petición siguiente y cancela sus análisis e importaciones en curso. Un trabajo cancelado no deja nada: un análisis se deshace siempre, y una importación se deshace entera.
- Las copias del metadata y restaurarlas no van por esta superficie: se hacen en la aplicación.
- La auditoría anota cada exportación e importación con el canal
APIy la referencia de la credencial; los análisis no se anotan.