Skip to content

feat: add the systeminfo, stats, log, backup and suggest commands - #43

Merged
marevol merged 3 commits into
fix/typer-required-argsfrom
feat/add-ops-commands
Oct 16, 2026
Merged

marevol merged 3 commits into
fix/typer-required-argsfrom
feat/add-ops-commands

Conversation

@marevol

@marevol marevol commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds five commands for the admin APIs that report on and maintain a running Fess:

Command Subcommands API
systeminfo (none; --output text|json|yaml) GET /api/admin/systeminfo
stats (none) GET /api/admin/stats
log list, download <id> --dest PATH [--force] GET /log/files, GET /log/file/{id}
backup list, download <id> --dest PATH [--force] GET /backup/files, GET /backup/file/{id}
suggest info, delete-all, delete-document, delete-query (--yes skips the confirmation) GET /suggest, DELETE /suggest/{all,document,query}
  • Text output is a key/value (or list) table; json/yaml give the full response. Every command exits non-zero on an API failure, in all output modes.
  • Downloads are streamed to the file given by --dest. An existing destination is kept unless --force is given, and a failed transfer leaves no partial file (it is written to <dest>.part and renamed).
  • log download checks the id against log list first: Fess answers an id that names no log file with an empty 200, which cannot be told from an empty log file.
  • backup download requests the id with a trailing slash (see the server oddities below).
  • Skills docs: one reference page per command, rows in the SKILL.md index, resource count 25 -> 30, and the stale "not exposed" list in workflows.md trimmed.

Versions

All five APIs exist in 14.19.2, 15.6.1, 15.7.0, 15.8.0 and 15.9.0 (checked in each tag's source; the action classes are unchanged apart from additions in 15.9: mapping files and chat_log.ndjson in backup). None of them needs the CodeLibs engine plugins, so the 15.9 404 of FessApiAdminAction.hookBefore does not apply (only the dictionary APIs override requiresEnginePlugins).

Verified

Live, 15.9.0 (Fess + OpenSearch 3.9.0): every subcommand and output mode by hand, with real data (5 crawled pages, search log entries, suggest words generated by the Suggest Indexer job): log download of .log, .log.gz, and an empty file; all 11 backup ids; unknown ids; a bad token (exit 3); an unreachable server (exit 1); suggest delete-query / delete-document / delete-all with counts before and after (delete-document keeps the query words and vice versa); confirmation abort.

Live, 14.19.2 (OpenSearch 2.19.1) and 15.8.0 (OpenSearch 3.8.0): the 17 new integration tests pass, plus a by-hand pass of all subcommands. On these two versions the suggest index was empty, so the delete assertions ran against an empty index.

Unit: 219 pass (tests/unit, including a download test against a local HTTP server). The new tests/commands files import-check (--collect-only); I did not run tests/commands through the repo fixture (a scratch conftest without Docker was used for the live runs above).

NOT verified

  • 15.6.1 and 15.7.0 live (source only). The trailing-slash behaviour is servlet-level, so the multi-version matrix run is the real check.
  • The plugin-less engine 404 path (not applicable to these APIs, so not exercised).
  • Large backups (the read timeout is 60 s per chunk).

Server oddities found (handled or documented)

  • A last path segment with an extension (/api/admin/backup/file/fess_config.bulk) gets a bare 404 Not Found. (text/plain) on 15.9 and a 302 on 14.19.2 / 15.8.0 instead of running the action. With a trailing slash it works on all three.
  • log list hands out URL-safe Base64 ids but log download decodes standard Base64, so an id containing - or _ (file names with characters such as > or ?) cannot be downloaded. Not worked around.
  • An unknown or non-.log log id answers 200 with an empty body.
  • fess.json and doc.json are listed but download as 0 bytes before 15.9.0.
  • log list returns lastModified in camelCase and without a time zone, unlike the rest of the API.
  • The error text for an unknown backup id differs in 14.x (Could not find index for backup.).
  • Pre-existing, outside this change: uv.lock pins click 8.3.0, which breaks required options with typer 0.16.0 (a missing --dest reaches the command as None; webconfig create without --name has the same problem). Click 8.2.1 behaves correctly.

Stacked PRs (merge from the bottom; each PR's base is the branch below it, so no conflicts remain):
main ← #45 theme timeout (+ CI runs for stacked PRs) ← #46 typer ← #43 ops commands ← #44 dict ← #41 general/plugin/storage ← #42 searchlist/documents.
After a PR is squash-merged GitHub retargets the next one to main.

Wrap the admin APIs that report on and maintain a running Fess:

- systeminfo / stats: show the server information and statistics
  (text tables, full data with json/yaml).
- log list|download, backup list|download: list the files and stream one to
  --dest; an existing destination is kept unless --force is given, and a
  failed transfer leaves no partial file. log download checks the id against
  the list first because Fess answers an unknown id with an empty download.
  backup download requests the id with a trailing slash because Fess does not
  run the action for a path whose last segment has an extension.
- suggest info|delete-all|delete-document|delete-query: show the word counts
  and delete words; the deletes ask for confirmation unless --yes is given.

All five APIs exist in 14.19.2, 15.6.1, 15.7.0, 15.8.0 and 15.9.0. Adds unit
tests (including a download test against a local HTTP server), integration
tests and the skills reference pages.
@marevol
marevol added this pull request to stack #47 October 16, 2026 13:50
@marevol marevol added this to the 0.4.0 milestone Oct 16, 2026
@marevol marevol self-assigned this Oct 16, 2026
@marevol
marevol merged commit 949f1fc into main Oct 16, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant