From b4bdd2e4f12d71bfae563bf64bb9a92577377ffe Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Thu, 11 Jun 2026 14:10:27 +0000 Subject: [PATCH] Add orientation CLI and config documentation --- README.md | 51 ++++++------- docs/cli.md | 68 +++++++++++++++++ docs/config.md | 130 +++++++++++++++++++++++++++++++++ examples/config.minimal.yml | 13 ++++ examples/config.production.yml | 20 +++++ 5 files changed, 257 insertions(+), 25 deletions(-) create mode 100644 docs/cli.md create mode 100644 docs/config.md create mode 100644 examples/config.minimal.yml create mode 100644 examples/config.production.yml diff --git a/README.md b/README.md index 25f739c..0769838 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,37 @@ # weatherapi -A small HTTP API that serves a variety of weather-related endpoints. +`weatherapi` is a read-only HTTP API for weather data already stored by +`weatherfeeder` in PostgreSQL. It exposes the latest observations, current +conditions, alerts, forecasts, discussions, and weather stories as JSON, XML, +or text. -## Endpoints +## Quickstart -- `GET /observations` -- `GET /conditions/current` -- `GET /alerts/active` -- `GET /discussion` -- `GET /discussion/key-messages` -- `GET /discussion/short-term` -- `GET /discussion/long-term` -- `GET /weatherstories` -- `GET /weatherstories/latest` -- `GET /forecast/hourly` -- `GET /forecast/hourly/today` -- `GET /forecast/hourly/tomorrow` -- `GET /forecast/narrative` -- `GET /forecast/narrative/today` -- `GET /forecast/narrative/tomorrow` +The service needs a reachable Postgres database with weatherfeeder-owned tables +and the configured text template directory. -## Query Parameters +```sh +go run ./cmd/weatherapi -config config.yml +``` -Shared weather query parameters: +The checked-in `config.yml` is a local sample. For new deployments, start from +[`examples/config.minimal.yml`](examples/config.minimal.yml) or +[`examples/config.production.yml`](examples/config.production.yml) and provide +database credentials through your normal secret-management process. -- `format` (`json`, `xml`, `text`) -- `units` (`metric`, `us`) +## Endpoint Families -Forecast endpoint query parameters: +- Observations and current conditions +- Active alerts +- Hourly and narrative forecasts +- Forecast discussions +- Weather stories -- `precision` (`0`-`2`) +See [`docs/api.md`](docs/api.md) for the HTTP contract. -Forecast, discussion, and weather stories endpoint query parameters: +## Documentation -- `tz` / `TZ` (IANA timezone, US abbreviation, or UTC offset) +- [`docs/api.md`](docs/api.md): public HTTP API reference +- [`docs/cli.md`](docs/cli.md): command-line usage +- [`docs/config.md`](docs/config.md): YAML configuration reference +- [`docs/policy/architecture.md`](docs/policy/architecture.md): development architecture and invariants diff --git a/docs/cli.md b/docs/cli.md new file mode 100644 index 0000000..e94824c --- /dev/null +++ b/docs/cli.md @@ -0,0 +1,68 @@ +# weatherapi CLI + +## Shortest Useful Command + +```sh +go run ./cmd/weatherapi -config config.yml +``` + +This starts the HTTP API with the supplied YAML configuration. The configured +Postgres database must be reachable, and `templates.base_dir` must point to the +text response templates when text output is used. + +## Command Overview + +`weatherapi` is the service executable in `cmd/weatherapi`. It loads +configuration, opens configured database handles, selects the first configured +database as the primary weather data store, registers HTTP endpoints, and starts +the feedapi HTTP runtime. + +Build and run a local binary: + +```sh +go build -o ./weatherapi ./cmd/weatherapi +./weatherapi -config config.yml +``` + +Run with the default config path: + +```sh +./weatherapi +``` + +## Flag Reference + +| Flag | Default | Description | +| --- | --- | --- | +| `-config` | `WEATHERAPI_CONFIG` when set, otherwise `config.yml` | Path to the YAML config file. | + +`weatherapi` does not currently expose other CLI flags. + +## Environment Variables + +| Variable | Description | +| --- | --- | +| `WEATHERAPI_CONFIG` | Default config path used when `-config` is not provided and the value is not blank. | + +Command-line flags take precedence over environment defaults. + +## Config Path Precedence + +1. `-config /path/to/config.yml` +2. non-blank `WEATHERAPI_CONFIG` +3. `config.yml` in the current working directory + +## Startup and Shutdown + +Startup fails if configuration cannot be loaded, no database is configured, a +configured database cannot be opened, the primary database cannot be selected, +or the HTTP app cannot be constructed. + +The process listens for `SIGINT` and `SIGTERM`. When a signal is received, the +runtime context is canceled and feedapi performs graceful HTTP shutdown. Database +close errors during shutdown are logged. + +## Related Docs + +- [`docs/config.md`](config.md): YAML configuration reference +- [`docs/api.md`](api.md): public HTTP API reference diff --git a/docs/config.md b/docs/config.md new file mode 100644 index 0000000..1c8f2e3 --- /dev/null +++ b/docs/config.md @@ -0,0 +1,130 @@ +# weatherapi Configuration + +`weatherapi` uses a feedapi YAML config file. This file configures the HTTP +server, database handles, and text template directory used by the service. + +## Discovery + +The executable chooses the config path in this order: + +1. `-config /path/to/config.yml` +2. non-blank `WEATHERAPI_CONFIG` +3. `config.yml` + +See [`docs/cli.md`](cli.md) for command examples. + +## Minimal Config + +```yaml +server: + listen_addr: ":8080" + default_format: json + +databases: + - name: weatherdb + driver: postgres + uri: postgres://localhost:5432/weatherdb?sslmode=disable + username: weatherapi + password: change-me + +templates: + base_dir: templates +``` + +A maintained copy is available at +[`examples/config.minimal.yml`](../examples/config.minimal.yml). + +## Production-Oriented Config + +Use explicit server timeouts, connection pool settings, and secret placeholders +for production deployments: + +```yaml +server: + listen_addr: ":8080" + default_format: json + read_timeout: 5s + write_timeout: 10s + idle_timeout: 120s + +databases: + - name: weatherdb + driver: postgres + uri: postgres://postgres.example.internal:5432/weatherdb?sslmode=require + username: weatherapi + password: ${WEATHERAPI_DB_PASSWORD} + max_open_conns: 10 + max_idle_conns: 5 + conn_max_lifetime: 30m + conn_max_idle_time: 5m + +templates: + base_dir: templates +``` + +A maintained copy is available at +[`examples/config.production.yml`](../examples/config.production.yml). + +## Reference + +### `server` + +| Field | Required | Default | Description | +| --- | --- | --- | --- | +| `listen_addr` | No | `:8080` | Address passed to the HTTP server. | +| `default_format` | No | `json` | Response format used when neither `format` nor `Accept` selects one. Supported values are `json`, `xml`, and `text`. | +| `read_timeout` | No | feedapi default | HTTP server read timeout. | +| `write_timeout` | No | feedapi default | HTTP server write timeout. | +| `idle_timeout` | No | feedapi default | HTTP keep-alive idle timeout. | + +### `databases` + +`databases` must contain at least one entry. `weatherapi` opens all configured +databases and uses the first entry as the primary weather data store for all +implemented reads. + +| Field | Required | Description | +| --- | --- | --- | +| `name` | Yes | Database handle name. The first configured name is selected as primary by `cmd/weatherapi`. | +| `driver` | Yes | Database driver. The implemented deployment uses `postgres`. | +| `uri` | Yes | PostgreSQL connection URI. | +| `username` | Yes | Database username. | +| `password` | Yes | Database password. Use secret injection in real deployments. | +| `max_open_conns` | No | Maximum open connections for the database pool. | +| `max_idle_conns` | No | Maximum idle connections for the database pool. | +| `conn_max_lifetime` | No | Maximum lifetime for pooled connections. | +| `conn_max_idle_time` | No | Maximum idle time for pooled connections. | + +The database must already contain the weatherfeeder-owned tables read by +`weatherapi`. This service does not ingest weather data and does not create or +migrate those tables. + +### `templates` + +| Field | Required | Description | +| --- | --- | --- | +| `base_dir` | Yes | Directory containing the `*.txt.tmpl` files used for text responses. | + +The repository includes templates under [`templates/`](../templates/). The +Docker image copies this directory to `/weatherapi/templates` and runs with +`/weatherapi` as the working directory. + +## Validation and Defaults + +Configuration is loaded by feedapi. `cmd/weatherapi` adds one local validation +rule: at least one database entry is required. + +Documented server defaults come from feedapi. Unknown YAML fields are not +documented as rejected by `weatherapi`; treat unrecognized fields as unsupported +configuration. + +## Secrets + +Do not commit production passwords, tokens, private hostnames, or private +connection strings. The examples use placeholders. Inject real values through +your deployment tooling before starting the service. + +## Related Docs + +- [`docs/cli.md`](cli.md): command-line usage and config path precedence +- [`docs/api.md`](api.md): HTTP format negotiation and API behavior diff --git a/examples/config.minimal.yml b/examples/config.minimal.yml new file mode 100644 index 0000000..84256fd --- /dev/null +++ b/examples/config.minimal.yml @@ -0,0 +1,13 @@ +server: + listen_addr: ":8080" + default_format: json + +databases: + - name: weatherdb + driver: postgres + uri: postgres://localhost:5432/weatherdb?sslmode=disable + username: weatherapi + password: change-me + +templates: + base_dir: templates diff --git a/examples/config.production.yml b/examples/config.production.yml new file mode 100644 index 0000000..134013e --- /dev/null +++ b/examples/config.production.yml @@ -0,0 +1,20 @@ +server: + listen_addr: ":8080" + default_format: json + read_timeout: 5s + write_timeout: 10s + idle_timeout: 120s + +databases: + - name: weatherdb + driver: postgres + uri: postgres://postgres.example.internal:5432/weatherdb?sslmode=require + username: weatherapi + password: ${WEATHERAPI_DB_PASSWORD} + max_open_conns: 10 + max_idle_conns: 5 + conn_max_lifetime: 30m + conn_max_idle_time: 5m + +templates: + base_dir: templates