Add config editing and service restart to the web UI #69
No reviewers
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
keyop-go/nfq_forwarder!69
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "issue25_webui_config_edit"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #25
Background
Issue #22 added a read-only view of the running configuration to the web UI. Issue #25 (split out from #22's own hedge) adds the ability to actually edit that configuration and restart the service to apply it.
Fix
internal/config: extractedLoadFromBytes(the same defaults-merging/queue-number-assignment/validation pipelineLoadFromFileruns, minus the file read) and addedParseRawBytes(a bare unmarshal - no defaults, no validation), plus a newConfiguration.ConfigPathfield (yaml:"-", set byLoadFromFile) so the web UI knows which file to write an edit back to. Addedjson:"..."tags matching every existingyaml:"..."tag acrossConfiguration/ConnectionDefaults/NetworkDefaults/Connection/WebUI, soconfig.Configurationcan be reused directly as the edit feature's wire format instead of a separate DTO.internal/nfq_forwarder/webui_config_edit.go(new): four new routes, all behind the existing session/CSRF middleware -GET /api/config/raw- the actual on-disk config, unresolved (viaParseRawBytes), unlike the resolved viewGET /api/config(issue #22) shows.POST /api/config/validate- accepts either{"yaml": "..."}or{"config": {...}}(whichever edit mode the client currently holds) and always echoes back both representations, computed server-side (yaml.Marshal/ParseRawBytes) - there's no in-browser YAML parser to do this client-side, so this is what lets the UI's raw/structured toggle stay in sync.POST /api/config/save- same validation, then an atomic write (temp file in the same directory +os.Rename, preserving the existing file's permissions) of exactly the submitted, validated YAML - never the resolved/expanded form, and never at all if invalid. Does not hot-swap the runningappConfig- this project has no live-reload path (seedocs/nfq_forwarder.service'sExecReload), so a save alone has no effect until a restart.POST /api/config/restart- runssystemctl --user restart --no-block nfq_forwarder.servicebehind a newrestartServiceFuncpackage-level variable (matching the existingsshDialFunc/addDNATRulesFuncindirection pattern) for testability.--no-blockmatters: this process is asking systemd's separate manager daemon to restart it, so the call must return before that teardown happens, letting the HTTP response actually reach the browser.internal/nfq_forwarder/webui/templates/config_edit.html+webui/static/config_edit.js(new): a toggle between a raw YAML<textarea>and a structured per-field form (global settings, web UI settings, defaults incl. dynamicby_networkrows, and a dynamic connections list) - switching modes round-trips through/api/config/validate. Separate "Validate", "Save" and "Restart service" actions, with explicit messaging that saving alone doesn't apply the change.Testing
internal/config: new tests forLoadFromBytes,ParseRawBytes, andLoadFromFilesettingConfigPath- package stays at 100% coverage.internal/nfq_forwarder/webui_config_edit_test.go(new): every new route's session/CSRF requirements;GET /api/config/rawreturning the unresolved shape and failing cleanly on a missing/malformed file;POST /api/config/validatefor both submission modes, including that a semantically-invalid-but-parseable config still echoes backConfig(for the structured form to display) while a YAML syntax error omits it;POST /api/config/saveconfirming a valid submission is written byte-for-byte with permissions preserved, and an invalid one leaves the file untouched;POST /api/config/restartvia a stubbedrestartServiceFunccovering both success and a surfaced failure - no realsystemctlever invoked.make lint(golangci-lint + yamllint + gitleaks) andmake test(go test -race -cover ./...) both clean.httptestserver and a real temp config file; restart correctly surfaced a realsystemctl"unit not found" error in this sandbox (no such unit installed here) rather than hanging or crashing.Docs
Updated
README.md,docs/README.md, andCLAUDE.md(new Design-notes bullet + Testing section additions, plus a new real-host verification checklist item for the restart flow, matching the project's existing untested-in-sandbox web UI items).mentioned in issue #25
added 1 commit
2824beaa- Default to structured editing and add compact per-connection saveCompare with previous version
added 1 commit
c7edfbee- Fix compact table header alignment, compact by_network, add connection reorderingCompare with previous version
added 1 commit
3ab6a387- Compact global/web UI/defaults fields, drag-and-drop connection reorderingCompare with previous version
UI refinements added after initial review feedback:
max-contentaction-button column widths independently, since they were separate CSS grids - fixed by sharing one grid across header + rows viadisplay: contents). Applied the same compact one-row-per-rule treatment to thedefaults.by_networktable. Made the Global settings / Web UI / Defaults field cards more compact too (tighter spacing, smaller inputs).All changes are on the same branch/MR (!69), lint and the full test suite stay clean throughout. Currently awaiting review.
assigned to @danny
requested review from @danny
This seems to work and meet the specifications given.
Approving and merging, will become v1.1.0.
approved this merge request
mentioned in commit
551f561100