DELETE /api/overlays/{id}?force=true can delete overlays in use

Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
Jonathon Anderson
2025-07-13 01:02:28 -06:00
parent 949dc9d46b
commit 6b5115934b
3 changed files with 19 additions and 14 deletions

View File

@@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Changed
- Restore default idempotency of `PUT /api/nodes/{id}`
- `DELETE /api/overlays/{name}?force=true` can delete overlays that are in use
### Changed

View File

@@ -223,28 +223,32 @@ func deleteOverlay() usecase.Interactor {
u := usecase.NewInteractor(func(ctx context.Context, input deleteOverlayInput, output *OverlayResponse) error {
wwlog.Debug("api.deleteOverlay(Name:%v, Force:%v)", input.Name, input.Force)
if registry, err := node.New(); err != nil {
return err
} else {
nodesCount := len(registry.ListNodesUsingOverlay(input.Name))
profilesCount := len(registry.ListProfilesUsingOverlay(input.Name))
if nodesCount > 0 || profilesCount > 0 {
return status.Wrap(fmt.Errorf(
"overlay '%s' is in use by %v nodes and %v profiles", input.Name, nodesCount, profilesCount),
status.InvalidArgument)
}
}
*output = *NewOverlayResponse(input.Name)
overlay_ := overlay.GetSiteOverlay(input.Name)
if input.Force {
if err := os.RemoveAll(overlay_.Path()); err != nil {
return err
}
} else {
if err := os.Remove(overlay_.Path()); err != nil {
if registry, err := node.New(); err != nil {
return err
} else {
nodesCount := len(registry.ListNodesUsingOverlay(input.Name))
profilesCount := len(registry.ListProfilesUsingOverlay(input.Name))
if nodesCount > 0 || profilesCount > 0 {
return status.Wrap(fmt.Errorf(
"overlay '%s' is in use by %v nodes and %v profiles", input.Name, nodesCount, profilesCount),
status.InvalidArgument)
}
}
if err := os.Remove(overlay_.Rootfs()); err != nil {
return status.Wrap(fmt.Errorf("failed to remove overlay rootfs: %v", err), status.Code(409))
} else {
if err := os.Remove(overlay_.Path()); err != nil {
return status.Wrap(fmt.Errorf("failed to remove overlay: %v", err), status.Code(409))
}
}
}
*output = *NewOverlayResponse(input.Name)
return nil
})
u.SetTitle("Delete an overlay")

View File

@@ -128,6 +128,6 @@ func TestOverlayAPI(t *testing.T) {
assert.NoError(t, err)
assert.NoError(t, resp.Body.Close())
assert.JSONEq(t, `{"files":null, "site":true}`, string(body))
assert.JSONEq(t, `{"files":[], "site":true}`, string(body))
})
}