From 9e27a431a1bc7e7d4f7606e6281bfba15cfb5a50 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Wed, 10 Jun 2026 20:17:40 +0000 Subject: [PATCH] Add maintained configuration examples --- README.md | 1 + cmd/weatherfeeder/config.yml | 4 ++-- cmd/weatherfeeder/main_test.go | 33 +++++++++++++++++++++++++++++++++ docs/cli.md | 2 ++ docs/config.md | 9 ++++++++- docs/operations.md | 2 ++ examples/config.minimal.yml | 19 +++++++++++++++++++ examples/config.nats.yml | 30 ++++++++++++++++++++++++++++++ examples/config.postgres.yml | 32 ++++++++++++++++++++++++++++++++ 9 files changed, 129 insertions(+), 3 deletions(-) create mode 100644 examples/config.minimal.yml create mode 100644 examples/config.nats.yml create mode 100644 examples/config.postgres.yml diff --git a/README.md b/README.md index 40e7603..2fbf676 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ current working directory. - [Configuration reference](docs/config.md) - [Operations guide](docs/operations.md) - [Troubleshooting guide](docs/troubleshooting.md) +- [Example configs](examples/) - [Event wire contract](docs/integrations/events.md) - [Postgres table contract](docs/integrations/postgres.md) - [Architecture policy](docs/policy/architecture.md) diff --git a/cmd/weatherfeeder/config.yml b/cmd/weatherfeeder/config.yml index 9539e2a..0c16594 100644 --- a/cmd/weatherfeeder/config.yml +++ b/cmd/weatherfeeder/config.yml @@ -24,7 +24,7 @@ sources: # driver: openweather_observation # every: 10m # params: -# url: "https://api.openweathermap.org/data/2.5/weather?lat=38.6239&lon=-90.3571&appid=c954f2566cb7ccb56b43737b52e88fc6&units=metric" +# url: "https://api.openweathermap.org/data/2.5/weather?lat=38.6239&lon=-90.3571&units=metric" # user_agent: "HomeOps (eric@maximumdirect.net)" # - name: NWSObservationKSUS @@ -115,7 +115,7 @@ sinks: # params: # uri: postgres://weatherdb:5432/weatherdb?sslmode=disable # username: weatherdb -# password: weatherdb +# password: # prune: 3d # # Prunes rows older than now-3d on each write transaction. diff --git a/cmd/weatherfeeder/main_test.go b/cmd/weatherfeeder/main_test.go index a978f13..d8494f3 100644 --- a/cmd/weatherfeeder/main_test.go +++ b/cmd/weatherfeeder/main_test.go @@ -2,7 +2,9 @@ package main import ( "context" + "path/filepath" "reflect" + "sort" "strings" "testing" "time" @@ -82,6 +84,33 @@ func TestExampleConfigSourcesBuildSchedulerJobs(t *testing.T) { t.Fatalf("config.Load(config.yml) unexpected error: %v", err) } + assertConfigSourcesBuildSchedulerJobs(t, cfg) +} + +func TestMaintainedConfigExamplesLoad(t *testing.T) { + paths, err := filepath.Glob("../../examples/*.yml") + if err != nil { + t.Fatalf("filepath.Glob examples: %v", err) + } + sort.Strings(paths) + if len(paths) == 0 { + t.Fatalf("expected maintained config examples") + } + + for _, path := range paths { + t.Run(filepath.Base(path), func(t *testing.T) { + cfg, err := config.Load(path) + if err != nil { + t.Fatalf("config.Load(%s) unexpected error: %v", path, err) + } + assertConfigSourcesBuildSchedulerJobs(t, cfg) + }) + } +} + +func assertConfigSourcesBuildSchedulerJobs(t *testing.T, cfg *config.Config) { + t.Helper() + reg := fksources.NewRegistry() wfsources.RegisterBuiltins(reg) @@ -91,6 +120,10 @@ func TestExampleConfigSourcesBuildSchedulerJobs(t *testing.T) { t.Fatalf("BuildInput(sources[%d]) error = %v", i, err) } + if err := fksources.ValidateExpectedKinds(sc, in); err != nil { + t.Fatalf("ValidateExpectedKinds(sources[%d]) error = %v", i, err) + } + job, err := fkscheduler.JobFromSourceConfig(in, sc) if err != nil { t.Fatalf("JobFromSourceConfig(sources[%d]) error = %v", i, err) diff --git a/docs/cli.md b/docs/cli.md index 8597d48..002761e 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -46,6 +46,8 @@ cd cmd/weatherfeeder go run . ``` +Maintained copyable configs are available under [`examples/`](../examples/). + Build and run a local binary: ```sh diff --git a/docs/config.md b/docs/config.md index 85ac9ef..a23758d 100644 --- a/docs/config.md +++ b/docs/config.md @@ -34,6 +34,7 @@ routes: `sources` and `sinks` must each contain at least one entry. `routes` is optional. When `routes` is omitted, every configured sink receives every event kind. +Maintained copyable configs are available under [`examples/`](../examples/). ## Production-Oriented Shape @@ -63,7 +64,7 @@ sinks: params: uri: postgres://weatherdb:5432/weatherdb?sslmode=disable username: weatherdb - password: "" + password: prune: 3d routes: @@ -213,3 +214,9 @@ Postgres `prune` must be a string duration. The config file is read directly from disk and has no built-in secret expansion. Keep real credentials out of repository-tracked configs. Use deployment tooling to render `config.yml` with the needed secret values before starting the daemon. + +## Maintained Examples + +- [Minimal stdout config](../examples/config.minimal.yml) +- [NATS publishing config](../examples/config.nats.yml) +- [Postgres persistence config](../examples/config.postgres.yml) diff --git a/docs/operations.md b/docs/operations.md index ab639a7..14a6017 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -16,6 +16,8 @@ CLI surface, see [CLI reference](cli.md). The daemon has no admin subcommands and no runtime reload command. Change the config file and restart the process to apply configuration changes. +Maintained copyable configs are available under [`examples/`](../examples/). + ## Runtime Lifecycle On startup, `weatherfeeder`: diff --git a/examples/config.minimal.yml b/examples/config.minimal.yml new file mode 100644 index 0000000..9ed8d4f --- /dev/null +++ b/examples/config.minimal.yml @@ -0,0 +1,19 @@ +--- +sources: + - name: NWSObservationKSTL + mode: poll + kinds: ["observation"] + driver: nws_observation + every: 10m + params: + url: "https://api.weather.gov/stations/KSTL/observations/latest" + user_agent: "weatherfeeder example (operator@example.com)" + +sinks: + - name: stdout + driver: stdout + params: {} + +routes: + - sink: stdout + kinds: ["observation"] diff --git a/examples/config.nats.yml b/examples/config.nats.yml new file mode 100644 index 0000000..0927a12 --- /dev/null +++ b/examples/config.nats.yml @@ -0,0 +1,30 @@ +--- +sources: + - name: NWSObservationKSTL + mode: poll + kinds: ["observation"] + driver: nws_observation + every: 10m + params: + url: "https://api.weather.gov/stations/KSTL/observations/latest" + user_agent: "weatherfeeder example (operator@example.com)" + + - name: NWSAlertsSTL + mode: poll + kinds: ["alert"] + driver: nws_alerts + every: 1m + params: + url: "https://api.weather.gov/alerts?point=38.6239,-90.3571&limit=20" + user_agent: "weatherfeeder example (operator@example.com)" + +sinks: + - name: nats_weather + driver: nats + params: + url: nats://localhost:4222 + subject: weatherfeeder.events + +routes: + - sink: nats_weather + kinds: ["observation", "alert"] diff --git a/examples/config.postgres.yml b/examples/config.postgres.yml new file mode 100644 index 0000000..60f9d94 --- /dev/null +++ b/examples/config.postgres.yml @@ -0,0 +1,32 @@ +--- +sources: + - name: NWSObservationKSTL + mode: poll + kinds: ["observation"] + driver: nws_observation + every: 10m + params: + url: "https://api.weather.gov/stations/KSTL/observations/latest" + user_agent: "weatherfeeder example (operator@example.com)" + + - name: OpenMeteoHourlyForecastSTL + mode: poll + kinds: ["forecast"] + driver: openmeteo_forecast + every: 1h + params: + url: "https://api.open-meteo.com/v1/forecast?latitude=38.6239&longitude=-90.3571&hourly=temperature_2m,relative_humidity_2m,dew_point_2m,apparent_temperature,precipitation_probability,precipitation,snowfall,weather_code,surface_pressure,wind_speed_10m,wind_direction_10m&forecast_days=3" + user_agent: "weatherfeeder example (operator@example.com)" + +sinks: + - name: pg_weather + driver: postgres + params: + uri: "postgres://postgres.example.invalid:5432/weatherfeeder?sslmode=disable" + username: + password: + prune: 3d + +routes: + - sink: pg_weather + kinds: ["observation", "forecast"]