[GH-ISSUE #3048] Deleting a site doesn't cascade to its site-resources; alias stays reserved → 409 on recreate #27920

Closed
opened 2026-06-10 23:30:34 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @maisim on GitHub (May 11, 2026).
Original GitHub issue: https://github.com/fosrl/pangolin/issues/3048

Describe the Bug

DELETE /site/{id} leaves the child site-resource in DB with its alias still globally reserved. The orphan has no parent site, so it doesn't show up in site-scoped listings, and there's no GET /site-resource?alias=… endpoint to discover the conflicting id. State is unrecoverable through normal flows.

Root cause is in the data model: siteResources.networkId uses onDelete: "set null" instead of onDelete: "cascade", and orphaned networks (no longer referenced by any siteNetworks row after a site deletion) are never cleaned up. The fix seems requires both a schema migration (change onDelete on siteResources.networkId) and cleanup logic in deleteSite to remove networks that become unreferenced.

Environment

  • OS Type & Version: docker stack
  • Pangolin Version: 1.18.3
  • Gerbil Version: 1.3.1
  • Traefik Version: v3.6
  • Newt Version: /
  • Olm Version: /

To Reproduce

PUT  /org/{org}/site                         → siteId A
PUT  /org/{org}/site-resource alias=foo,siteId=A
DELETE /site/A
PUT  /org/{org}/site                         → siteId B
PUT  /org/{org}/site-resource alias=foo,siteId=B
   → 409 "Alias already in use by another site resource"

Expected Behavior

Either cascade-delete child site-resources, or refuse DELETE /site/{id} with 409 while children exist. In both cases, the alias should be released when its resource is gone.

Originally created by @maisim on GitHub (May 11, 2026). Original GitHub issue: https://github.com/fosrl/pangolin/issues/3048 ### Describe the Bug DELETE /site/{id} leaves the child site-resource in DB with its alias still globally reserved. The orphan has no parent site, so it doesn't show up in site-scoped listings, and there's no GET /site-resource?alias=… endpoint to discover the conflicting id. State is unrecoverable through normal flows. Root cause is in the data model: siteResources.networkId uses onDelete: "set null" instead of onDelete: "cascade", and orphaned networks (no longer referenced by any siteNetworks row after a site deletion) are never cleaned up. The fix seems requires both a schema migration (change onDelete on siteResources.networkId) and cleanup logic in deleteSite to remove networks that become unreferenced. ### Environment - OS Type & Version: docker stack - Pangolin Version: 1.18.3 - Gerbil Version: 1.3.1 - Traefik Version: v3.6 - Newt Version: / - Olm Version: / ### To Reproduce ``` PUT /org/{org}/site → siteId A PUT /org/{org}/site-resource alias=foo,siteId=A DELETE /site/A PUT /org/{org}/site → siteId B PUT /org/{org}/site-resource alias=foo,siteId=B → 409 "Alias already in use by another site resource" ``` ### Expected Behavior Either cascade-delete child site-resources, or refuse DELETE /site/{id} with 409 while children exist. In both cases, the alias should be released when its resource is gone.
Author
Owner

@maisim commented on GitHub (May 11, 2026):

Here a script to reproduce the problem:
https://gist.github.com/maisim/6e6f12ad274f909fb6855df71c5faea6

<!-- gh-comment-id:4419412558 --> @maisim commented on GitHub (May 11, 2026): Here a script to reproduce the problem: https://gist.github.com/maisim/6e6f12ad274f909fb6855df71c5faea6
Author
Owner

@maisim commented on GitHub (May 11, 2026):

Fisrt, big thank you for this awesome tool :)

I can try to propose a fix for this, but I would appreciate some feedback first, since I do not have a global view of the project and I may be missing some design constraints.

From what I understand, there are at least two possible approaches:

  1. Cascade-delete siteResources when their parent network/site is deleted.
  2. Prevent DELETE /site/{id} while related resources still exist, and return a 409 instead.

My current assumption is that cascading the deletion is the expected behavior, because after the site is deleted the resource is no longer reachable through normal API flows, while its alias remains globally reserved.

If that direction sounds correct, I can try to open a PR with:

  • a schema migration changing the relevant onDelete behavior;
  • cleanup logic in deleteSite for networks that become unreferenced;
  • a regression test covering the alias reuse scenario described above.

Please let me know if there is a preferred approach or any project-specific constraint I should take into account before working on it.

<!-- gh-comment-id:4419463380 --> @maisim commented on GitHub (May 11, 2026): Fisrt, big thank you for this awesome tool :) I can try to propose a fix for this, but I would appreciate some feedback first, since I do not have a global view of the project and I may be missing some design constraints. From what I understand, there are at least two possible approaches: 1. Cascade-delete `siteResources` when their parent network/site is deleted. 2. Prevent `DELETE /site/{id}` while related resources still exist, and return a `409` instead. My current assumption is that cascading the deletion is the expected behavior, because after the site is deleted the resource is no longer reachable through normal API flows, while its alias remains globally reserved. If that direction sounds correct, I can try to open a PR with: - a schema migration changing the relevant `onDelete` behavior; - cleanup logic in `deleteSite` for networks that become unreferenced; - a regression test covering the alias reuse scenario described above. Please let me know if there is a preferred approach or any project-specific constraint I should take into account before working on it.
Author
Owner

@AstralDestiny commented on GitHub (May 11, 2026):

Well deletion of site shouldn't delete resources as they can be moved to different sites and whatnot

<!-- gh-comment-id:4419517569 --> @AstralDestiny commented on GitHub (May 11, 2026): Well deletion of site shouldn't delete resources as they can be moved to different sites and whatnot
Author
Owner

@oschwartz10612 commented on GitHub (May 11, 2026):

Agreed with @AstralDestiny. This was a change in 1.18 when we introduced HA - we wanted to decouple the private resources from the sites in the same way the public resources are. When you delete a site it just deletes the target on the public resource not the resource itself. Similarly when deleting a site it just unregisters it from the private resource so you can choose other ones.

<!-- gh-comment-id:4423032758 --> @oschwartz10612 commented on GitHub (May 11, 2026): Agreed with @AstralDestiny. This was a change in 1.18 when we introduced HA - we wanted to decouple the private resources from the sites in the same way the public resources are. When you delete a site it just deletes the target on the public resource not the resource itself. Similarly when deleting a site it just unregisters it from the private resource so you can choose other ones.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/pangolin#27920