add overlay file deletion support

Signed-off-by: jason yang <jasonyangshadow@gmail.com>
This commit is contained in:
jason yang
2025-07-14 04:33:58 +00:00
committed by Jonathon Anderson
parent 6b5115934b
commit e089fe0101
6 changed files with 122 additions and 12 deletions

View File

@@ -72,6 +72,7 @@ func Handler(auth *config.Authentication, allowedNets []net.IPNet) *web.Service
r.Method(http.MethodGet, "/{name}/file", nethttp.NewHandler(getOverlayFile()))
r.Method(http.MethodPut, "/{name}", nethttp.NewHandler(createOverlay()))
r.Method(http.MethodDelete, "/{name}", nethttp.NewHandler(deleteOverlay()))
r.Method(http.MethodDelete, "/{name}/file", nethttp.NewHandler(deleteOverlayFile()))
})
})

View File

@@ -256,3 +256,35 @@ func deleteOverlay() usecase.Interactor {
u.SetTags("Overlay")
return u
}
func deleteOverlayFile() usecase.Interactor {
type deleteOverlayFileInput struct {
Name string `path:"name" required:"true" description:"Name of overlay to get a file from"`
Path string `query:"path" required:"true" description:"Path to file to get from an overlay"`
Force bool `query:"force" default:"false" description:"Whether to forcely delete a overlay, default:'false'"`
Cleanup bool `query:"cleanup" default:"false" description:"Whether to cleanup empty parent directories, default:'false'"`
}
u := usecase.NewInteractor(func(ctx context.Context, input deleteOverlayFileInput, output *OverlayResponse) error {
wwlog.Debug("api.deleteOverlayFile(Name:%v, Path:%v)", input.Name, input.Path)
if input.Path == "" {
return status.Wrap(fmt.Errorf("must specify a path"), status.InvalidArgument)
}
if relPath, err := url.QueryUnescape(input.Path); err != nil {
return fmt.Errorf("failed to decode path: %v: %w", input.Path, err)
} else {
overlay_ := overlay.GetOverlay(input.Name)
err := overlay_.DeleteFile(relPath, input.Force, input.Cleanup)
if err != nil {
return fmt.Errorf("unable to delete overlay file %v: %v: %w", input.Name, relPath, err)
}
}
*output = *NewOverlayResponse(input.Name)
return nil
})
u.SetTitle("Delete a file from an overlay")
u.SetDescription("Delete a file from an overlay from the overlay name and file path")
u.SetTags("Overlay")
return u
}

View File

@@ -117,6 +117,20 @@ func TestOverlayAPI(t *testing.T) {
assert.JSONEq(t, `{"test":{"files":null, "site":true},"testoverlay":{"files":["/email.ww"], "site":false}}`, string(body))
})
t.Run("test delete overlay file", func(t *testing.T) {
req, err := http.NewRequest(http.MethodDelete, srv.URL+"/api/overlays/testoverlay/file?path=email.ww&force=true", nil)
assert.NoError(t, err)
resp, err := http.DefaultTransport.RoundTrip(req)
assert.NoError(t, err)
body, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
assert.NoError(t, resp.Body.Close())
assert.JSONEq(t, `{"files":null, "site":true}`, string(body))
})
t.Run("test delete overlays", func(t *testing.T) {
req, err := http.NewRequest(http.MethodDelete, srv.URL+"/api/overlays/test?force=true", nil)
assert.NoError(t, err)