Skip to content

refactor(cluster): migrate module from server - #2495

Open
shikanime wants to merge 29 commits into
mainfrom
pr/cluster-migration
Open

shikanime wants to merge 29 commits into
mainfrom
pr/cluster-migration

Conversation

@shikanime

@shikanime shikanime commented Aug 13, 2026 •

Copy link
Copy Markdown
Member

Issues liées

Refs #2492


Quel est le comportement actuel ?

Le module cluster (clusters, usage, environnements) est servi par l'ancienne application Fastify apps/server.

Quel est le nouveau comportement ?

Migration du module cluster vers apps/server-nestjs :

  • ClusterController : routes GET /, GET /:clusterId, GET /usage/:clusterId, GET /:clusterId/environments, POST /, PUT /:clusterId, DELETE /:clusterId.
  • ClusterService : CRUD + calcul d'usage et liste des environnements rattachés.
  • ClusterModule : enregistrement dans main.module.ts.
  • Parité des contrats et codes HTTP contre apps/server/src/resources/cluster/.

État lors de la bascule

Cette PR migre le module côté server-nestjs mais ne bascule pas encore le trafic : le routage reste porté par l'ancienne application, ce qui rend le point de routage non bloquant ici mais à traiter dans la vague de bascule.

  • Routage : apps/nginx-strangler/conf.d/routing.conf ne contient aucune location /api/v1/clusters sur cette branche ; /api/v1/clusters retombe donc dans location /api/ → server-legacy. Les routes migrées ne sont pas encore servies par server-nestjs.
  • Hooks : ClusterService émet cluster.upsert / cluster.delete via EventEmitter2, et server-nestjs porte les listeners correspondants (argocd.service.ts : @OnEvent('cluster.upsert') → syncCluster, @OnEvent('cluster.delete') → cleanupCluster, résultats argocd centralisés via capturePluginResult) ; l'écouteur historique reste dans l'ancienne application (apps/server/src/utils/hook-wrapper.ts, câblé par apps/server/src/resources/cluster/business.ts). À la bascule du routage, l'émission côté server-nestjs déclenchera donc le provisionnement — aucun risque de no-op ; la vague de bascule n'a plus que le bloc location /api/v1/clusters à porter.

Cette PR introduit-elle un breaking change ?

Non.

Autres informations

@shikanime

Copy link
Copy Markdown
Member Author

Réouverte : couverture des familles restantes pour #1889 — le fermeture précédente était un tri, pas un rejet du travail.

@shikanime
shikanime restored the pr/cluster-migration branch September 17, 2026 09:51
@shikanime

Copy link
Copy Markdown
Member Author

Réouverte : famille requise pour #1889. Branche recréée depuis le SHA d'origine (l'ancienne ref avait été supprimée).

@shikanime shikanime reopened this Sep 17, 2026
@shikanime shikanime self-assigned this Sep 17, 2026
@shikanime shikanime added this to the 9.27.0 milestone Sep 17, 2026
Comment thread apps/server-nestjs/src/modules/cluster/cluster.controller.ts
Comment thread apps/server-nestjs/src/modules/cluster/cluster.controller.ts
Comment thread apps/server-nestjs/src/modules/cluster/cluster.service.ts Outdated
Comment thread apps/server-nestjs/src/modules/cluster/cluster.service.ts Outdated
Comment thread apps/server-nestjs/src/modules/cluster/cluster.service.ts Outdated
Comment thread apps/server-nestjs/src/modules/cluster/cluster.service.ts Outdated
Comment thread apps/server-nestjs/src/modules/cluster/cluster.service.ts Outdated
Comment thread apps/server-nestjs/src/modules/cluster/cluster.service.ts Outdated
Comment thread apps/server-nestjs/src/modules/cluster/cluster-queries.utils.ts Outdated
Comment thread apps/server-nestjs/src/modules/cluster/cluster-testing.utils.ts Outdated
@shikanime

Copy link
Copy Markdown
Member Author

🔴 Bloquant pour la bascule : emitAsync('cluster.upsert'/'cluster.delete') n'a aucun consommateur @OnEvent dans server-nestjs. Les abonnés legacy du hook cluster sont argocd, gitlab et vault — le pont reste à écrire (même pattern que #2749 pour adminRole.*). Rien de cassé tant qu'apps/server sert la route.

shikanime and others added 29 commits October 21, 2026 17:36
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ib545fd310384d7847a47cd007d36a8526a6a6964

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I603381219713d5fcda1e1e6bf9b7a7496a6a6964

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I078ab8b313d60cccd67993443c14cf3c6a6a6964
rebases cleanly.

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Id763439e79b52a6af29fdef6bf8c1d826a6a6964
Co-authored-by: Automata <automata@shikanime.studio>

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I7f5dd540e89d54187ba0881d1af533ad6a6a6964
…ked admin-token PR

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ib00d7b390b49a646f18899caf9d879fb6a6a6964

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ic223ae4950476c208ab605fb31899b236a6a6964
- name CreateClusterBodySchema/UpdateClusterBodySchema in shared, derive type aliases from them, validate at controller pipe
- propagate cluster.upsert hook failure as 422 with regression test
- dedupe test factories to canonical modules, drop divider comments

Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ia5abe56ef859df38cc46c7491b8c07096a6a6964

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I74a8bf02a144ac92603ed7b89a4c395d6a6a6964

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I35a88616852aa448b001cd99d0f23bbf6a6a6964
Co-authored-by: Automata <automata@shikanime.studio>

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ieca62cb2edf5d3366570fb60b0e24ed86a6a6964
ClusterService injects LogService and the controller guard requires auth and user-permission providers that ClusterModule never imported; the backend crashed at boot.

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I4a060cde917ff9c62ac4779f2810f05c6a6a6964

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I05cc45bf006e1e7eaaae7d595a11a02b6a6a6964
ClusterService injects EventEmitter2; import EventsModule so the provider resolves and the backend stops crashing at boot.

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ie806f5daeff91530e9e916d23dbe070b6a6a6964
Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I75ea6fd82315a9c9c67f63ad414957936a6a6964
ClusterService injects LogService and EventEmitter2 and the controller guard requires auth and user-permission providers that ClusterModule never imported; the backend crashed at boot.

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: If466a357f2692be40e3de4170cd37a8d6a6a6964
Reflect-based guard metadata assertions pass whether or not the guard is
enforced and add no behavioural coverage; the guard spec and the controller
delegation tests are untouched.

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Id551b411ab24291da518f2599ae1edd66a6a6964

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I610c3537602b9b15b472e5fd69a408696a6a6964
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ie239c572870d655ca697a5ad53e487496a6a6964

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I8f0a537fd3f724c1bcd283997171a9a76a6a6964

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Iea5eabc6a0b5ff15d0b32365897ec56a6a6a6964
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Id86ef6af532de064301d2586c163a7326a6a6964

Co-authored-by: Automata <automata@shikanime.studio>

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I94b7b2df3d455f9791f0385aab46532b6a6a6964
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I5cafffa7f7e9786916555e0e69894d6b6a6a6964

Co-authored-by: Automata <automata@shikanime.studio>

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I0719ab0da6e2d14f052da99641f0980c6a6a6964
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I9681a6be979533285c8ea54ae6f9b9956a6a6964

Co-authored-by: Automata <automata@shikanime.studio>

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Iec8008c8736fa5e3f04fb661568a0ca86a6a6964
Co-authored-by: Automata <automata@shikanime.studio>

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I5094e976da1ceb3b103bfd6632a1c3256a6a6964
Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ic0c77b63ed86e4d744e584c7b4ed2d346a6a6964

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ia7d6c7881f1d0154f865469a29753a496a6a6964
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I425f9664368d246076e7d5891de423606a6a6964

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I3b10511f56e3fec439d8911849e7d7cb6a6a6964
- generateClusterTlsClientConfig now nests tlsClientConfig under username,
  password and bearerToken, matching the legacy convertConfig shape; secrets
  stay out of the tlsClientConfig block
- split create/update failure messages to their legacy-exact wording
- stop mutating the typed update body before destructuring it

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I3327b416d19ce00fa7be415daf162af16a6a6964

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Id2bdb99c4b0e568d2375759fb67631a56a6a6964
…eries.utils

Colocate syncClusterProjectLinks beside its exported stage twin
syncClusterStageLinks; fold the single-caller projectsToRemoveFrom
helper into a plain filter at its only call site.

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I0ef7ec192f02eac54de38aafd129d33a6a6a6964

Signed-off-by: Shikanime Deva <22115108+shikanime@users.noreply.github.com>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I1542fb0092739ab8f3f99de552b96ff16a6a6964
Isolation: cluster-testing.utils no longer imports and re-exports
environment's makeCluster; the module owns its factory again.

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I7ee65d163430af7a67e47f2519076aee6a6a6964
Main renamed VaultClientService.upsertKvData to ensureKvData and
GitlabClientService.getOrCreateInfraGroupRepo to ensureInfraGroupRepo;
the argocd handlers kept the old names and broke the docker build on
the merge ref. Also inline CLUSTER_PUBLIC into its use sites.

Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Idb33c626698fd9df3aefee2c79b877e76a6a6964
…rModule

The earlier drop (905d4c4) assumed a stacked branch would own the
admin-token registration, but that PR (#2740) merged into main before
this branch was rebuilt — merging as-is removed the /api/v1/admin/tokens
endpoints from the Nest app and its Swagger.

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ia1c33b7e4d2f49108c5e6a7d15b4d9e2f3a4b5c6
…ct links

Add ParseUUIDPipe to update so every parametrized route rejects a
malformed id with 400 before reaching Prisma, and stop
syncClusterProjectLinks from detaching projects when a PUT body omits
projectIds: removals are computed only when the field was actually sent,
an explicit [] still detaches all, and a flip to public still unlinks
everything.

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ib2d44c8f5e3a4051768d9e2f3a4b5c7a8b9c0d1e
…paths

Serialize the Vault cluster-secret config field as JSON instead of YAML
(the ArgoCD cluster secret expects a JSON string, as the legacy plugin
did), look zone clusters up by slug instead of passing the slug to a
UUID lookup, and drop the cluster being deleted from the zone values
while its row still exists — the service removes it only after this
listener succeeds.

Cover the secret shape and the zone lookup with regression tests,
including the datastore query itself, and hoist the shared cluster
factory to module scope so SonarQube's new-code analysis stops flagging
it.

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ic3d55e9a6b4c4f1839e0f2a4b5c7a8b9c1d2e3f4
Nest answered 200 on DELETE /api/v1/clusters/:clusterId while the legacy
router and clusterContract.deleteCluster announce 204, breaking the
client's extractData(response, 204) success path. Cover the status
through HTTP with and without force.

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I6502049ce6838b906c8ca5234a8d6f186a6a6964
…lable

generateZoneVaultValues swallowed role-id/secret-id errors and committed
'none' placeholders, letting a cluster upsert/delete overwrite the whole
zone's functional AppRole credentials. Let the error propagate so
capturePluginResult returns KO and ClusterService answers 422 without
rewriting argocd-values.yaml (legacy hook parity).

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ie02095fa827ca9275a50467a4dc90c586a6a6964
Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: Ic17a1d1d863599216f49082fc2a8a9fe6a6a6964
…e transactions

Move the argocd-spec-local makeClusterWithZone factory into
argocd-testing.utils. Inline ClusterPrivacySchema.enum access at the
cluster-queries call sites, dropping the CLUSTER_PUBLIC and
CLUSTER_DEDICATED aliases. Extract createClusterWithLinks and
updateClusterWithLinks into cluster-queries.utils so the service keeps
only the $transaction boundary and the emit-and-throw, matching the
admin-role pattern. Drop legacy-parity clauses from this branch's added
comments; keep the load-bearing invariants.

Co-authored-by: Automata <automata@shikanime.studio>
Signed-off-by: William Phetsinorath <william.phetsinorath-open@interieur.gouv.fr>
Change-Id: I92452f42ed4263923e6aac5d4a9f05ef6a6a6964
@cloud-pi-native-sonarqube

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

built refactor Refactor code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

💡 [REQUEST] - Migrer le module cluster vers server-nestjs

3 participants