Catalog en serio: kinds, relaciones y providers
|
Objetivos del capítulo
|
De una entidad a un catálogo
En el :cap-03 cargamos una entidad. Pero una IDP vive o muere según su catálogo: si tiene 5 componentes suecos, no es una IDP, es un monolito. La salsa está en modelar correctamente un conjunto de servicios, sus relaciones y cómo se sincronizan desde las fuentes de verdad.
Ahora poblamos el catálogo con los cinco componentes base de Sazón Foods, definimos cómo se relacionan y los importamos desde GitHub.
Los cinco componentes semilla
Una SaaS B2B de restaurantes tiene, en su forma más simple:
-
Una web (panel para cocineros).
-
Una API que sirve la lógica de negocio.
-
Un worker que ejecuta tareas async (notificaciones, informes).
-
Una base de datos Postgres donde vive el estado.
-
Un System que agrupa los anteriores como una unidad lógica.
El System es la mise-en-place agrupada: la bandeja con los cinco ingredientes que componen el plato sazon-restaurant. Sin esa bandeja, el cocinero tiene que ir al mercado cada vez.
El catálogo semilla:
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: sazon-web
description: Frontend público
tags: [frontend, customer-facing]
spec:
type: website
lifecycle: production
owner: team-cocina
system: sazon-restaurant
---
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: sazon-api
description: API REST del menú
tags: [backend, nodejs]
spec:
type: service
lifecycle: production
owner: team-cocina
system: sazon-restaurant
providesApis: [sazon-menu-api]
---
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: sazon-worker
description: Worker de pedidos
tags: [backend, worker]
spec:
type: service
lifecycle: production
owner: team-cocina
system: sazon-restaurant
---
apiVersion: backstage.io/v1alpha1
kind: Resource
metadata:
name: sazon-postgres-prod
description: Postgres de producción
spec:
type: database
lifecycle: production
owner: team-cocina
system: sazon-restaurant
---
apiVersion: backstage.io/v1alpha1
kind: System
metadata:
name: sazon-restaurant
description: Sistema SaaS B2B de Sazón Foods
spec:
owner: team-cocina
domain: restaurant
|
Qué acabas de hacer
|
La entidad System
El System agrupa componentes que comparten dominio. En Backstage se modela como una entidad con kind System. Sus relaciones hasPart lo enlazan con cada componente.
apiVersion: backstage.io/v1alpha1
kind: System
metadata:
name: sazon-restaurant
title: Sazón Foods — Restaurante SaaS
description: Plataforma SaaS B2B para gestión de pedidos en restaurantes.
spec:
owner: guests
domain: sazon-foods
type: saas
Tras guardar el archivo y reiniciar el backend, refresca el catalog: sazon-restaurant aparece como padre de los cinco componentes.
Relaciones: cómo se habla el catálogo
Backstage soporta relaciones entre entidades. Tres relaciones nos llevan lejos:
-
dependsOn: A depende de B (ej. la API depende de la DB).
-
providesApi: A expone una API llamada X (ej. la API provee
sazon-orders). -
consumesApi: A consume una API llamada X (ej. la web consume
sazon-orders).
|
Por qué importan las relaciones
Las relaciones permiten a los plugins renderizar grafos de dependencias (Tech Insights, Catalog Graph) y al Scaffolder razonar sobre qué generar. Una entidad sin relaciones es un nodo aislado en un grafo. |
Definimos las relaciones como un YAML de relaciones:
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: sazon-frontend
description: SPA React del portal
tags: [frontend]
spec:
type: website
lifecycle: production
owner: team-cocina
system: sazon-restaurant
consumesApis: [sazon-menu-api]
---
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: sazon-menu-api
description: API pública del menú
tags: [rest]
spec:
type: openapi
lifecycle: production
owner: team-cocina
system: sazon-restaurant
definition: |
openapi: 3.0.0
info: { title: sazon-menu-api, version: 1.0.0 }
paths:
/menu: { get: { summary: Lista el menú } }
---
# sazon-api depende de sazon-postgres-prod
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: sazon-api
description: API REST del menú
tags: [backend, nodejs]
spec:
type: service
lifecycle: production
owner: team-cocina
system: sazon-restaurant
providesApis: [sazon-menu-api]
dependsOn: [resource:sazon-restaurant/sazon-postgres-prod]
---
# sazon-worker consume sazon-api y depende de la misma DB
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: sazon-worker
description: Worker de pedidos
tags: [backend, worker]
spec:
type: service
lifecycle: production
owner: team-cocina
system: sazon-restaurant
consumesApis: [sazon-menu-api]
dependsOn: [resource:sazon-restaurant/sazon-postgres-prod]
Cada relación tiene un source, type y target. La entidad API definida aparte (con metadata.name: sazon-orders-api y spec.type: openapi) es referenciada por las relaciones providesApi/consumesApi.
Providers: discovery automático desde GitHub
Mantener entidades a mano es tedioso. Backstage soporta providers que descubren repos en GitHub y los ingieren como entidades automáticamente.
| ¿Cómo funciona? |
El GithubDiscoveryProcessor escanea una org o un equipo, busca catalog-info.yaml en cada repo, y los ingesta como entidades. Se ejecuta en cada tick configurable.
Activamos el provider desde app-config.addons.yaml:
catalog:
providers:
github:
providerId:
- id: provider-discovery
github: https://github.com
orgs: ['sazon-foods']
schedule:
initialDelay: { seconds: 30 }
frequency: { minutes: 30 }
filters:
repository: ^sazon-.*$
producer:
getCodeowners: true
|
Política de filtros
El |
Importar proyectos existentes en bloque
Si tienes decenas de repos ya creados y quieres migrarlos de golpe, hay un script de bulk-import. Backstage lo publica como ejemplo y lo hemos adaptado para Sazón Foods:
set -euo pipefail
# Configura el token en app-config.local.yaml o via GITHUB_TOKEN.
GITHUB_TOKEN="${GITHUB_TOKEN:-}"
ORG="${CATALOG_ORG:-sazon-foods}"
# Endpoint exacto del bulk import (cap-04, RQ-A22-bulk-import-endpoint).
ENDPOINT="http://localhost:7007/api/catalog/import-many"
curl -X POST "$ENDPOINT" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"items\": [
{ \"type\": \"repository\", \"target\": \"$ORG/sazon-web\" },
{ \"type\": \"repository\", \"target\": \"$ORG/sazon-api\" },
{ \"type\": \"repository\", \"target\": \"$ORG/sazon-worker\" }
]
}"
echo "==> PRs creadas en github.com/$ORG. Revisa y mergea."
|
El flujo del script
Útil cuando arrancas con muchos servicios ya en producción. |
-
Crea los cinco
Componenty unSystem. -
Añade relaciones
dependsOn,providesApiyconsumesApi. -
Activa el
GithubDiscoveryProcessorcon un filtro razonable. -
Si tienes repos legacy, ejecuta el bulk-import y revisa los PRs.
Resumen
-
Modelar System + Component + relaciones es la base del catalog.
-
Las relaciones permiten grafos, dependencias y razonamiento sobre la topología.
-
El
GithubDiscoveryProcessorsincroniza el catalog desde GitHub con filtros. -
El bulk-import acelera la adopción en empresas con muchos servicios.
Glosario del capítulo
- kind
-
Categoría de entidad (Component, API, Resource, System, Domain, Group, User).
- relación
-
Edge del grafo: dependsOn, providesApi, consumesApi, hasPart, ownerOf.
- provider
-
Componente que descubre entidades en una fuente externa (GitHub, GitLab, etc.).
- processor
-
Pieza que procesa una entidad: enriquece, valida, transforma.
Próximo capítulo
El backend: en qué cocina se cocina —pasamos del catalog al backend: arquitectura, configuración y cómo extenderlo con plugins.
Parte II: Parte 2 — Backend: la cocina por dentro
La New Backend System, los services del core, y nuestro primer plugin backend completo. Aquí es donde la cocina pasa de hobby a restaurante.