1 Commits
Author SHA1 Message Date
sneak 1a7966b97a main() is one call into internal/cli (closes #160)
check / check (push) Canceled after 0s
cmd/netwatch-server/main.go parsed the command line, ran the check-cidr
and prepare-data-dir subcommands and built the fx application itself;
the Go style guide puts all of that in internal/ or pkg/. The new
package internal/cli does it, with the same arguments, messages and
exit codes, and main() is now os.Exit(cli.Main(Appname, Version,
os.Args[1:])). Appname and Version stay in main, where the build sets
Version. Each subcommand writes its error to a writer it is given, and
prepare-data-dir also takes the volume and the user's name, so the new
unit tests give it a temporary directory and the user they run as.

Model: opus-5-5
2026-10-19 04:19:31 +00:00
6 changed files with 12 additions and 66 deletions

No files matched your search

+1 -1
View File
@@ -207,7 +207,7 @@ stops. Its routes:
It is an `fx`-wired Go application: `cmd/netwatch-server/` starts it, and its It is an `fx`-wired Go application: `cmd/netwatch-server/` starts it, and its
packages are in `internal/`: packages are in `internal/`:
- **`cli`**: Runs `netwatch-server` from its command line: the `check-cidr` and - **`cli`**: Runs netwatch-server from its command line: the `check-cidr` and
`prepare-data-dir` subcommands, which `bin/entrypoint.sh` runs before it `prepare-data-dir` subcommands, which `bin/entrypoint.sh` runs before it
starts the server, and otherwise the server, with the `fx` wiring. starts the server, and otherwise the server, with the `fx` wiring.
- **`config`**: Loads configuration from environment variables and config files - **`config`**: Loads configuration from environment variables and config files
+3 -7
View File
@@ -26,13 +26,9 @@ Run `make frontend-viewport-test` in CI as its own step; it is not part of
([#160](https://git.eeqj.de/sneak/netwatch/issues/160)). `internal/cli` runs ([#160](https://git.eeqj.de/sneak/netwatch/issues/160)). `internal/cli` runs
the `check-cidr` and `prepare-data-dir` subcommands, with the same arguments, the `check-cidr` and `prepare-data-dir` subcommands, with the same arguments,
messages and exit codes, and otherwise the server, with the `fx` wiring. messages and exit codes, and otherwise the server, with the `fx` wiring.
`Appname` and `Version` stay in `main`, where the build sets `Version`, and `Appname` and `Version` stay in `main`, where the build sets `Version`. Unit
`main` gives `cli.Main` the function that runs the server, which the tests tests give each subcommand input it takes and input it refuses, and check the
replace with one that fails them. Unit tests call `cli.Main` with `check-cidr` exit code and what it writes to stderr
and a CIDR it takes and one it refuses, and with `prepare-data-dir` and a path
outside `/data`, and check the exit code. Others give each subcommand input it
takes and input it refuses, and check the exit code and what it writes to
stderr
- 2026-10-19: report file writes no longer overlap - 2026-10-19: report file writes no longer overlap
([#150](https://git.eeqj.de/sneak/netwatch/issues/150)), so the reports of ([#150](https://git.eeqj.de/sneak/netwatch/issues/150)), so the reports of
failed writes are written in the order they arrived. Two writes that failed at failed writes are written in the order they arrived. Two writes that failed at
+1 -1
View File
@@ -15,5 +15,5 @@ var (
) )
func main() { func main() {
os.Exit(cli.Main(Appname, Version, os.Args[1:], cli.RunServer)) os.Exit(cli.Main(Appname, Version, os.Args[1:]))
} }
+6 -17
View File
@@ -24,19 +24,9 @@ import (
) )
// Main runs netwatch-server with args, its command line after the // Main runs netwatch-server with args, its command line after the
// program's name, and returns the exit code. Unless args are // program's name, and returns the exit code. appname and version are
// "check-cidr CIDR" or "prepare-data-dir DATA_DIR", Main runs the // the name and version the server logs and reports.
// server by calling serve with appname and version, the name and func Main(appname, version string, args []string) int {
// version the server logs and reports. main passes RunServer; the
// tests pass a function that fails them, so that no test starts the
// server. When serve is RunServer and the server fails to start or to
// stop, fx's Run exits the process with status 1 and Main never
// returns.
func Main(
appname, version string,
args []string,
serve func(appname, version string),
) int {
// "netwatch-server check-cidr CIDR" exits 1, with the error, if // "netwatch-server check-cidr CIDR" exits 1, with the error, if
// this server would refuse CIDR in its TRUSTED_PROXIES. // this server would refuse CIDR in its TRUSTED_PROXIES.
// bin/entrypoint.sh runs it on each entry it gives nginx. // bin/entrypoint.sh runs it on each entry it gives nginx.
@@ -52,7 +42,7 @@ func Main(
return prepareDataDir(os.Stderr, "/data", args[1], "netwatch") return prepareDataDir(os.Stderr, "/data", args[1], "netwatch")
} }
serve(appname, version) runServer(appname, version)
return 0 return 0
} }
@@ -93,11 +83,10 @@ func prepareDataDir(stderr io.Writer, volume, dataDir, username string) int {
return 0 return 0
} }
// RunServer runs the server until it is told to stop, with appname and // runServer runs the server until it is told to stop. If the server
// version as the name and version it logs and reports. If the server
// fails to start or to stop, fx's Run exits the process with status 1 // fails to start or to stop, fx's Run exits the process with status 1
// itself. // itself.
func RunServer(appname, version string) { func runServer(appname, version string) {
globals.Appname = appname globals.Appname = appname
globals.Version = version globals.Version = version
-39
View File
@@ -13,35 +13,6 @@ import (
"sneak.berlin/go/netwatch/internal/reportbuf" "sneak.berlin/go/netwatch/internal/reportbuf"
) )
// TestMainRunsCheckCIDR: Main given check-cidr returns 0 for a CIDR the
// server takes in its TRUSTED_PROXIES and 1 for one it refuses, and
// does not start the server.
func TestMainRunsCheckCIDR(t *testing.T) {
t.Parallel()
for cidr, want := range map[string]int{"10.0.0.0/8": 0, "1.2.3/32": 1} {
code := cli.Main("netwatch", "test", []string{"check-cidr", cidr},
failIfServerStarts(t))
if code != want {
t.Errorf("check-cidr %q: exit %d, want %d", cidr, code, want)
}
}
}
// TestMainRunsPrepareDataDir: Main given prepare-data-dir returns 1 for
// a DATA_DIR outside /data, and does not start the server. The test
// image has no netwatch user, so there the 1 comes from looking that
// user up; TestPrepareDataDirRefusesPathOutsideVolume checks the path.
func TestMainRunsPrepareDataDir(t *testing.T) {
t.Parallel()
code := cli.Main("netwatch", "test", []string{"prepare-data-dir", "/etc"},
failIfServerStarts(t))
if code != 1 {
t.Errorf("prepare-data-dir /etc: exit %d, want 1", code)
}
}
// TestCheckCIDRTakesCIDR: check-cidr exits 0, writing nothing, for a // TestCheckCIDRTakesCIDR: check-cidr exits 0, writing nothing, for a
// CIDR the server takes in its TRUSTED_PROXIES. // CIDR the server takes in its TRUSTED_PROXIES.
func TestCheckCIDRTakesCIDR(t *testing.T) { func TestCheckCIDRTakesCIDR(t *testing.T) {
@@ -133,13 +104,3 @@ func currentUsername(t *testing.T) string {
return current.Username return current.Username
} }
// failIfServerStarts is what the tests give Main in place of
// cli.RunServer: it fails the test instead of starting the server.
func failIfServerStarts(t *testing.T) func(appname, version string) {
t.Helper()
return func(string, string) {
t.Error("Main started the server")
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ package globals
import "go.uber.org/fx" import "go.uber.org/fx"
//nolint:gochecknoglobals // set by cli.RunServer before fx starts //nolint:gochecknoglobals // set by cli.Main before fx starts
var ( var (
// Appname is the application name. // Appname is the application name.
Appname string Appname string