giswater-cli 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- giswater_admin/README.md +733 -0
- giswater_admin/__init__.py +47 -0
- giswater_admin/__main__.py +11 -0
- giswater_admin/__version__.py +3 -0
- giswater_admin/adapters/__init__.py +0 -0
- giswater_admin/adapters/psycopg2_adapter.py +165 -0
- giswater_admin/cli/__init__.py +5 -0
- giswater_admin/cli/context.py +65 -0
- giswater_admin/cli/main.py +46 -0
- giswater_admin/cli/parser/__init__.py +32 -0
- giswater_admin/cli/parser/db.py +22 -0
- giswater_admin/cli/parser/global_.py +64 -0
- giswater_admin/cli/parser/manifest.py +22 -0
- giswater_admin/cli/parser/meta.py +66 -0
- giswater_admin/cli/parser/network.py +40 -0
- giswater_admin/cli/parser/schema_group.py +113 -0
- giswater_admin/cli/version_args.py +14 -0
- giswater_admin/commands/__init__.py +1 -0
- giswater_admin/commands/_helpers.py +269 -0
- giswater_admin/commands/config.py +49 -0
- giswater_admin/commands/create.py +259 -0
- giswater_admin/commands/dbmodel.py +179 -0
- giswater_admin/commands/drop.py +41 -0
- giswater_admin/commands/init_db.py +75 -0
- giswater_admin/commands/manifest.py +56 -0
- giswater_admin/commands/network.py +83 -0
- giswater_admin/commands/schema_cmd.py +245 -0
- giswater_admin/commands/update.py +151 -0
- giswater_admin/commands/update_network.py +121 -0
- giswater_admin/commands/version.py +38 -0
- giswater_admin/conn.py +113 -0
- giswater_admin/engine/__init__.py +74 -0
- giswater_admin/engine/builder.py +640 -0
- giswater_admin/engine/cancel.py +22 -0
- giswater_admin/engine/changelog.py +208 -0
- giswater_admin/engine/manifest.py +238 -0
- giswater_admin/engine/network_update.py +228 -0
- giswater_admin/engine/schema_catalog.py +904 -0
- giswater_admin/engine/sql_runner.py +191 -0
- giswater_admin/engine/templating.py +83 -0
- giswater_admin/engine/timing_report.py +127 -0
- giswater_admin/engine/version_guard.py +43 -0
- giswater_admin/install/__init__.py +61 -0
- giswater_admin/install/config.py +147 -0
- giswater_admin/install/dbmodel_paths.py +98 -0
- giswater_admin/install/releases.py +167 -0
- giswater_admin/install/schema_version.py +168 -0
- giswater_admin/log_format.py +308 -0
- giswater_admin/output.py +132 -0
- giswater_admin/paths.py +27 -0
- giswater_admin/releases.py +33 -0
- giswater_admin/user_config.py +35 -0
- giswater_cli-0.1.1.dist-info/METADATA +761 -0
- giswater_cli-0.1.1.dist-info/RECORD +58 -0
- giswater_cli-0.1.1.dist-info/WHEEL +5 -0
- giswater_cli-0.1.1.dist-info/entry_points.txt +2 -0
- giswater_cli-0.1.1.dist-info/licenses/LICENSE +675 -0
- giswater_cli-0.1.1.dist-info/top_level.txt +1 -0
giswater_admin/README.md
ADDED
|
@@ -0,0 +1,733 @@
|
|
|
1
|
+
# giswater-admin
|
|
2
|
+
|
|
3
|
+
Headless CLI and engine for the Giswater database schema lifecycle (create, upgrade, drop, inspect). It reads the same YAML manifests under `dbmodel/manifests/` and runs the same `SchemaBuilder` as the QGIS plugin (`GwSchemaBuilderTask` + `QtDbAdapter`), so automation, CI, and the desktop UI do not diverge on SQL execution logic.
|
|
4
|
+
|
|
5
|
+
**See also:** [dbmodel README — Schema architecture](../dbmodel/README.md#schema-architecture) · [dbmodel README — Testing](../dbmodel/README.md#testing)
|
|
6
|
+
|
|
7
|
+
## Table of contents
|
|
8
|
+
|
|
9
|
+
1. [Overview](#overview)
|
|
10
|
+
2. [Where to run it](#where-to-run-it)
|
|
11
|
+
3. [Architecture](#architecture)
|
|
12
|
+
4. [Install](#install)
|
|
13
|
+
5. [Connection](#connection)
|
|
14
|
+
6. [Invocation rules](#invocation-rules)
|
|
15
|
+
7. [Global options](#global-options)
|
|
16
|
+
8. [Commands reference](#commands-reference)
|
|
17
|
+
9. [Kinds and manifest profiles](#kinds-and-manifest-profiles)
|
|
18
|
+
10. [Timing and output](#timing-and-output)
|
|
19
|
+
11. [QGIS integration](#qgis-integration)
|
|
20
|
+
12. [Unit tests](#unit-tests)
|
|
21
|
+
13. [Extending the model](#extending-the-model)
|
|
22
|
+
14. [Keeping docs in sync](#keeping-docs-in-sync)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Overview
|
|
27
|
+
|
|
28
|
+
| Layer | Path | Role |
|
|
29
|
+
|-------|------|------|
|
|
30
|
+
| CLI entry | `giswater_admin/cli/` | Argument parsing, dispatch, context |
|
|
31
|
+
| Commands | `giswater_admin/commands/` | Subcommand handlers (`create`, `dbmodel`, …) |
|
|
32
|
+
| Install | `giswater_admin/install/` | User config, dbmodel cache, release downloads |
|
|
33
|
+
| Engine | `giswater_admin/engine/` | `SchemaBuilder`, manifests, SQL runner (shared with QGIS) |
|
|
34
|
+
| Shared I/O | `conn.py`, `output.py`, `log_format.py` | Connection, stdout/stderr formatting |
|
|
35
|
+
|
|
36
|
+
Legacy shims at package root (`paths.py`, `user_config.py`, `releases.py`) re-export from `install/` for backward compatibility.
|
|
37
|
+
|
|
38
|
+
| Piece | Role |
|
|
39
|
+
|-------|------|
|
|
40
|
+
| `cli/parser/` | Subcommand registration split by domain |
|
|
41
|
+
| `cli/context.py` | Resolve dbmodel path and schema version before dispatch |
|
|
42
|
+
| `cli/main.py` | `main()` entrypoint |
|
|
43
|
+
| `dbmodel/manifests/*.yaml` | Phase graphs per schema kind |
|
|
44
|
+
| `dbmodel/schemas/` | SQL sources (DDL, functions, updates, samples) |
|
|
45
|
+
|
|
46
|
+
Typical flow for a new database:
|
|
47
|
+
|
|
48
|
+
1. Create an empty PostgreSQL database (outside this CLI).
|
|
49
|
+
2. `db init` — cluster extensions once per database.
|
|
50
|
+
3. `schema main create` / `schema addon create` — build project and satellite schemas.
|
|
51
|
+
4. `schema addon integrate` — wire satellites into ws/ud parents.
|
|
52
|
+
5. `network show` — inspect topology; `network update` — lockstep upgrade.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Where to run it
|
|
57
|
+
|
|
58
|
+
| Context | Command |
|
|
59
|
+
|---------|---------|
|
|
60
|
+
| **Global CLI (recommended)** | `gw create …` after `pipx install giswater-cli` |
|
|
61
|
+
| Plugin repo checkout | `python3 -m giswater_admin …` or `gw …` with dev dbmodel |
|
|
62
|
+
| Custom dbmodel tree | `gw create … --dbmodel-path /path/to/dbmodel` |
|
|
63
|
+
| CI / Docker tests | See [dbmodel testing](../dbmodel/README.md#testing) |
|
|
64
|
+
| QGIS | N/A (in-process) | `GwSchemaBuilderTask` — no subprocess |
|
|
65
|
+
|
|
66
|
+
**Requirements:** Python 3.9+, PostgreSQL with PostGIS/pgRouting on the **server**.
|
|
67
|
+
|
|
68
|
+
**dbmodel resolution order** (when `--dbmodel-path` is omitted):
|
|
69
|
+
|
|
70
|
+
1. `--dbmodel-path`
|
|
71
|
+
2. `GW_DBMODEL_PATH` environment variable
|
|
72
|
+
3. User config (`gw dbmodel use …`)
|
|
73
|
+
4. Sibling `dbmodel/` in a plugin repo checkout
|
|
74
|
+
|
|
75
|
+
If nothing matches, run `gw dbmodel install latest` or `gw dbmodel use dev --root /path/to/repo`.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Architecture
|
|
80
|
+
|
|
81
|
+
```mermaid
|
|
82
|
+
flowchart TB
|
|
83
|
+
subgraph hosts [Execution contexts]
|
|
84
|
+
CLI["gw / python -m giswater_admin"]
|
|
85
|
+
QGIS["GwSchemaBuilderTask + QtDbAdapter"]
|
|
86
|
+
CI["dbmodel/test/bootstrap_inner.sh"]
|
|
87
|
+
end
|
|
88
|
+
subgraph engine [giswater_admin/engine]
|
|
89
|
+
Manifest["manifests/*.yaml"]
|
|
90
|
+
Builder["SchemaBuilder"]
|
|
91
|
+
Runner["sql_runner"]
|
|
92
|
+
end
|
|
93
|
+
subgraph dbmodel_tree [dbmodel/]
|
|
94
|
+
Schemas["schemas/..."]
|
|
95
|
+
Updates["updates M/m/p"]
|
|
96
|
+
end
|
|
97
|
+
PG[(PostgreSQL)]
|
|
98
|
+
CLI --> Builder
|
|
99
|
+
QGIS --> Builder
|
|
100
|
+
CI --> CLI
|
|
101
|
+
Builder --> Manifest
|
|
102
|
+
Builder --> Runner
|
|
103
|
+
Runner --> Schemas
|
|
104
|
+
Runner --> Updates
|
|
105
|
+
Runner --> PG
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Phase types** (declared in manifests, implemented in `engine/manifest.py`):
|
|
109
|
+
|
|
110
|
+
| Type | Behavior |
|
|
111
|
+
|------|----------|
|
|
112
|
+
| `sql_dir` | Run every `*.sql` in listed folders (optional `recursive`) |
|
|
113
|
+
| `version_walk` | Walk `updates/<M>/<m>/<p>/` semver-ordered; `roots:` for ws/ud (common then kind) |
|
|
114
|
+
| `sql_function` | `SELECT schema.fn($${JSON}$$)` (e.g. `lastprocess`) |
|
|
115
|
+
| `sql_file` | Single file with optional `fallback_source` |
|
|
116
|
+
| `sql_inline` | Literal SQL in YAML |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Install
|
|
121
|
+
|
|
122
|
+
### Global CLI (Windows / Linux / macOS)
|
|
123
|
+
|
|
124
|
+
Install [pipx](https://pipx.pypa.io/) once, then install the CLI package:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# macOS
|
|
128
|
+
brew install pipx && pipx ensurepath
|
|
129
|
+
|
|
130
|
+
# Windows / Linux (if pipx is not installed yet)
|
|
131
|
+
python3 -m pip install --user pipx
|
|
132
|
+
python3 -m pipx ensurepath
|
|
133
|
+
|
|
134
|
+
# All platforms
|
|
135
|
+
pipx install giswater-cli
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Download a published dbmodel (from the same plugin ZIP used by QGIS):
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
gw dbmodel install latest --set-active
|
|
142
|
+
gw version
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Typical first run:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
gw db init --conn "postgresql://user:pass@127.0.0.1:5432/mydb"
|
|
149
|
+
gw schema main create --type ws --name demo --profile empty --conn "postgresql://user:pass@127.0.0.1:5432/mydb"
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Development without a release** (use your local checkout):
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
gw dbmodel use dev --root /path/to/giswater_qgis_plugin
|
|
156
|
+
gw schema main create --type ws --name test_dev --conn "$CONN" --check
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Config and cache locations:
|
|
160
|
+
|
|
161
|
+
| OS | Config | Release cache |
|
|
162
|
+
|----|--------|---------------|
|
|
163
|
+
| Linux / macOS | `~/.config/giswater/config.yaml` | `~/.local/share/giswater/releases/` |
|
|
164
|
+
| Windows | `%APPDATA%/giswater/config.yaml` | `%LOCALAPPDATA%/giswater/releases/` |
|
|
165
|
+
|
|
166
|
+
### From the plugin repository (contributors)
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
cd /path/to/giswater_qgis_plugin
|
|
170
|
+
python3 -m pip install -e .
|
|
171
|
+
# or legacy:
|
|
172
|
+
python3 -m pip install -r giswater_admin/requirements.txt
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Optional virtualenv:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
python3 -m venv .venv && source .venv/bin/activate
|
|
179
|
+
pip install -e .
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**OS packages (server side)** — names vary by distro; install PostGIS and pgRouting for your PostgreSQL major version:
|
|
183
|
+
|
|
184
|
+
- Debian/Ubuntu: `postgresql-16-postgis-3`, `postgresql-16-pgrouting`, …
|
|
185
|
+
- macOS (Homebrew): `postgresql@16`, `postgis`
|
|
186
|
+
- Windows: PostGIS/pgRouting matching your PostgreSQL installer
|
|
187
|
+
|
|
188
|
+
Verify:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
gw --help
|
|
192
|
+
# or
|
|
193
|
+
python3 -m giswater_admin --help
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### dbmodel management commands
|
|
197
|
+
|
|
198
|
+
| Command | Purpose |
|
|
199
|
+
|---------|---------|
|
|
200
|
+
| `gw dbmodel install latest` | Download plugin ZIP and cache `dbmodel/` |
|
|
201
|
+
| `gw dbmodel install 4.9.0` | Install a specific release |
|
|
202
|
+
| `gw dbmodel list` | Cached versions + remote latest |
|
|
203
|
+
| `gw dbmodel use latest` | Activate latest cached/remote version |
|
|
204
|
+
| `gw dbmodel use dev --root PATH` | Use `PATH/dbmodel` from a checkout |
|
|
205
|
+
| `gw config get` / `gw config set KEY VALUE` | Persistent settings |
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Versioning
|
|
210
|
+
|
|
211
|
+
Two independent version numbers:
|
|
212
|
+
|
|
213
|
+
| Version | Example | Meaning |
|
|
214
|
+
|---------|---------|---------|
|
|
215
|
+
| **CLI** (`gw version` → `cli`) | `0.1.0` | The `giswater-cli` tool: commands, fixes, packaging. Bump with [`scripts/bump_cli_version.py`](../scripts/bump_cli_version.py). |
|
|
216
|
+
| **Schema / dbmodel** (`gw version` → `dbmodel-version`) | `4.15.0` | Giswater release whose SQL and `updates/` patches are applied. Comes from the active dbmodel, not from the CLI version. |
|
|
217
|
+
|
|
218
|
+
A single CLI release can create or upgrade schemas for any installed dbmodel version:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
gw dbmodel install 4.14.0 && gw dbmodel use 4.14.0
|
|
222
|
+
gw create --kind ws --schema legacy --conn "$CONN"
|
|
223
|
+
|
|
224
|
+
gw dbmodel install 4.16.0 && gw dbmodel use 4.16.0
|
|
225
|
+
gw create --kind ws --schema current --conn "$CONN"
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Use `--plugin-version X.Y.Z` to override the schema release when auto-detection is not possible (e.g. a custom `--dbmodel-path` without `metadata.txt`).
|
|
229
|
+
|
|
230
|
+
### CLI releases (`cli-v*`)
|
|
231
|
+
|
|
232
|
+
The CLI is released **independently** from the QGIS plugin:
|
|
233
|
+
|
|
234
|
+
| Event | Tag example | Publishes |
|
|
235
|
+
|-------|-------------|-----------|
|
|
236
|
+
| Plugin Giswater | `v4.16.0` | `giswater.zip` + dbmodel (see repo `release-plugin.yml`) |
|
|
237
|
+
| CLI `gw` | `cli-v0.1.0` | PyPI `giswater-cli` + wheel on GitHub Release |
|
|
238
|
+
|
|
239
|
+
Maintain [`giswater_admin/CHANGELOG.md`](CHANGELOG.md) (Keep a Changelog format) before each release.
|
|
240
|
+
|
|
241
|
+
**First release (`0.1.0`)** — document changes under `## [Unreleased]`, then:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
python3 scripts/prepare_cli_release.py 0.1.0 --create-github-release
|
|
245
|
+
python3 scripts/prepare_cli_release.py 0.1.0 --execute --create-github-release
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
(`pyproject.toml` and `giswater_admin/__version__.py` must already be `0.1.0`.)
|
|
249
|
+
|
|
250
|
+
**Subsequent releases** (e.g. `0.2.0`):
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
python3 scripts/bump_cli_version.py 0.2.0
|
|
254
|
+
# Add changes under ## [Unreleased] in giswater_admin/CHANGELOG.md
|
|
255
|
+
python3 scripts/prepare_cli_release.py 0.2.0 --create-github-release
|
|
256
|
+
python3 scripts/prepare_cli_release.py 0.2.0 --execute --create-github-release
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
When the GitHub Release is published, CI (`.github/workflows/release-cli.yml`) runs tests, validates versions, builds `dist/*`, publishes to PyPI via OIDC (Trusted Publisher, environment `pypi`), and attaches wheels to the release.
|
|
260
|
+
|
|
261
|
+
**One-time PyPI setup:** register a pending publisher at https://pypi.org/manage/account/publishing/ with project `giswater-cli`, owner `Giswater`, repository `giswater_qgis_plugin`, workflow `release-cli.yml`, environment `pypi`. Create the matching `pypi` environment in GitHub repo settings.
|
|
262
|
+
|
|
263
|
+
Users install the tool once (`pipx install giswater-cli`) and refresh schema SQL with `gw dbmodel install` when a new plugin version ships.
|
|
264
|
+
|
|
265
|
+
### Testing locally
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
cd /path/to/giswater_qgis_plugin
|
|
269
|
+
python3 -m pip install -e .
|
|
270
|
+
|
|
271
|
+
# Ensure gw is on PATH (macOS user install example)
|
|
272
|
+
export PATH="$HOME/Library/Python/3.9/bin:$PATH"
|
|
273
|
+
|
|
274
|
+
gw version
|
|
275
|
+
python3 -m pytest test/cli/ -q
|
|
276
|
+
|
|
277
|
+
# Offline schema plan (no DB)
|
|
278
|
+
gw create --kind ws --schema test --profile empty --check \
|
|
279
|
+
--conn "postgresql://user@127.0.0.1:5432/mydb"
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Connection
|
|
285
|
+
|
|
286
|
+
Resolution order (first match wins):
|
|
287
|
+
|
|
288
|
+
1. `--conn` — `postgresql://user:pass@host:port/dbname` (or `postgres://…`)
|
|
289
|
+
2. `--config` — YAML with `host`, `port`, `user`, `password`, `dbname`, and/or `service`
|
|
290
|
+
3. Environment — `PGHOST`, `PGPORT`, `PGUSER`, `PGPASSWORD`, `PGDATABASE`, `PGSERVICE`
|
|
291
|
+
|
|
292
|
+
**Superuser:** mutating commands (`db init`, `schema` create/integrate/update/drop, `network update`, and `--check` with a live connection) require a PostgreSQL **superuser**. Read-only commands (`schema list`, `network show`) work with any role that can `SELECT` Giswater schemas and `pg_catalog`.
|
|
293
|
+
|
|
294
|
+
### Linux / macOS
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
export CONN='postgresql://gisadmin:secret@127.0.0.1:5432/giswater_cli'
|
|
298
|
+
python3 -m giswater_admin status --conn "$CONN"
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Windows (PowerShell)
|
|
302
|
+
|
|
303
|
+
```powershell
|
|
304
|
+
$env:CONN = "postgresql://gisadmin:secret@127.0.0.1:5432/giswater_cli"
|
|
305
|
+
py -3 -m giswater_admin status --conn $env:CONN
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Config file
|
|
309
|
+
|
|
310
|
+
```yaml
|
|
311
|
+
host: 127.0.0.1
|
|
312
|
+
port: 5432
|
|
313
|
+
user: gisadmin
|
|
314
|
+
password: secret
|
|
315
|
+
dbname: giswater_cli
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
python3 -m giswater_admin status --config /path/conn.yaml
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**`--check`:** many subcommands only print the plan or SQL and do not write to the database. `db init --check` does not require a connection.
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Invocation rules
|
|
327
|
+
|
|
328
|
+
Global options are on the **parent parser of each subcommand**. They must appear **after** the subcommand name:
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
# Correct
|
|
332
|
+
python3 -m giswater_admin schema main create --type ws --name demo --profile empty --json
|
|
333
|
+
|
|
334
|
+
# Wrong (root parser does not define --json)
|
|
335
|
+
python3 -m giswater_admin --json create ...
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## Global options
|
|
341
|
+
|
|
342
|
+
Available on subcommands that include the shared parent parser (`schema …`, `network …`, `db init`, legacy aliases, `manifest list|validate`).
|
|
343
|
+
|
|
344
|
+
| Option | Description |
|
|
345
|
+
|--------|-------------|
|
|
346
|
+
| `--json` | Single JSON object on **stdout** (for `jq`, CI, scripts). |
|
|
347
|
+
| `--quiet` | Suppress info-level progress on stderr; errors/warnings remain. |
|
|
348
|
+
| `-v` / `--verbose` | One aligned line per executed SQL path on stderr. |
|
|
349
|
+
| `-d` / `--debug` | Like `-v` plus `DEBUG` logs with SQL previews. |
|
|
350
|
+
| `--timing` | `── Done … ──` summary (per phase + slowest files). With `-v`, adds ms per file. |
|
|
351
|
+
| `--timing-threshold-ms N` | With `-v --timing`, only log files with duration ≥ N ms. |
|
|
352
|
+
| `--timing-top K` | Number of slowest files in summary (default: 20). |
|
|
353
|
+
| `--timing-detail` | With `--json --timing`, include full per-file list in the JSON payload. |
|
|
354
|
+
| `--dbmodel-path DIR` | Root of the dbmodel tree (default: sibling `dbmodel/` in the plugin repo). |
|
|
355
|
+
|
|
356
|
+
**Connection group** (where applicable):
|
|
357
|
+
|
|
358
|
+
| Option | Description |
|
|
359
|
+
|--------|-------------|
|
|
360
|
+
| `--conn` | PostgreSQL URL. |
|
|
361
|
+
| `--config` | Path to connection YAML. |
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Commands reference
|
|
366
|
+
|
|
367
|
+
Base syntax:
|
|
368
|
+
|
|
369
|
+
```text
|
|
370
|
+
python3 -m giswater_admin <subcommand> [subcommand options] [global options]
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Exit codes: **0** success, **1** failure (parse, I/O, PostgreSQL, SQL, invalid plan).
|
|
374
|
+
|
|
375
|
+
### Command tree
|
|
376
|
+
|
|
377
|
+
```text
|
|
378
|
+
gw db init
|
|
379
|
+
gw schema main create | update | drop
|
|
380
|
+
gw schema addon create | integrate | update | drop
|
|
381
|
+
gw network show | update
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Legacy aliases (`create`, `update`, `drop`, `status`, `init-db`, `update-network`, `audit …`) still work but print a deprecation warning to stderr and are hidden from `--help`.
|
|
385
|
+
|
|
386
|
+
| Old | New |
|
|
387
|
+
|-----|-----|
|
|
388
|
+
| `gw create --kind ws --schema x` | `gw schema main create --type ws --name x` |
|
|
389
|
+
| `gw update --schema ws` | `gw schema main update --name ws` |
|
|
390
|
+
| `gw status` | `gw network show --flat` |
|
|
391
|
+
| `gw init-db` | `gw db init` |
|
|
392
|
+
| `gw update-network` | `gw network update` |
|
|
393
|
+
| `gw audit structure` | `gw schema addon create --type audit` |
|
|
394
|
+
| `gw audit activate --schema ws` | `gw schema addon integrate --type audit --parent ws` |
|
|
395
|
+
|
|
396
|
+
Use `--version X.Y.Z` everywhere (replaces `--plugin-version` / `--to-version`).
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
### `db init`
|
|
401
|
+
|
|
402
|
+
Creates extensions in order: `postgis` → `postgis_raster` → `tablefunc` → `pgrouting` → `unaccent` (optional `postgres_fdw` with `--with-fdw`). Run **once per database** before the first schema create.
|
|
403
|
+
|
|
404
|
+
| Option | Description |
|
|
405
|
+
|--------|-------------|
|
|
406
|
+
| `--with-fdw` | Also `CREATE EXTENSION postgres_fdw`. |
|
|
407
|
+
| `--with-pgtap` | Also `CREATE EXTENSION pgtap` (for dbmodel tests). |
|
|
408
|
+
| `--continue-on-error` | Try all extensions after a failure (default: stop on first error). |
|
|
409
|
+
| `--check` | Print SQL only; no connection required. |
|
|
410
|
+
| `--conn` / `--config` | Connection (optional with `--check`). |
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
gw db init --conn "$CONN"
|
|
414
|
+
gw db init --conn "$CONN" --with-fdw --with-pgtap
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
### `schema main`
|
|
420
|
+
|
|
421
|
+
ws/ud project schemas.
|
|
422
|
+
|
|
423
|
+
#### `schema main create`
|
|
424
|
+
|
|
425
|
+
| Option | Description |
|
|
426
|
+
|--------|-------------|
|
|
427
|
+
| `--type` | **Required.** `ws` \| `ud` |
|
|
428
|
+
| `--name` | Schema name (default: same as `--type`, e.g. `ws`). |
|
|
429
|
+
| `--profile` | `empty` \| `sample` \| `inventory` (maps to manifest `empty`, `sample_full`, `sample_inv`). |
|
|
430
|
+
| `--lang` | Locale folder (default `en_US`). |
|
|
431
|
+
| `--srid` | EPSG code (default `25831`). |
|
|
432
|
+
| `--version` | Giswater schema release X.Y.Z (default: from active dbmodel). |
|
|
433
|
+
| `--check` | Plan only. |
|
|
434
|
+
| `--conn` / `--config` | Connection. |
|
|
435
|
+
|
|
436
|
+
```bash
|
|
437
|
+
gw schema main create --type ws --name ws1 --profile sample --lang es_ES --conn "$CONN"
|
|
438
|
+
gw schema main create --type ud --profile empty --conn "$CONN"
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
#### `schema main update`
|
|
442
|
+
|
|
443
|
+
Upgrades one isolated ws/ud schema. **Blocked** if the schema belongs to an interconnected network (use `network update`). **Downgrades forbidden.**
|
|
444
|
+
|
|
445
|
+
| Option | Description |
|
|
446
|
+
|--------|-------------|
|
|
447
|
+
| `--name` | **Required.** Existing schema. |
|
|
448
|
+
| `--version` | Target version (default: active dbmodel). |
|
|
449
|
+
| `--check` | Plan only. |
|
|
450
|
+
| `--conn` / `--config` | Connection. |
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
gw schema main update --name ws1 --version 4.16.0 --conn "$CONN"
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
#### `schema main drop`
|
|
457
|
+
|
|
458
|
+
| Option | Description |
|
|
459
|
+
|--------|-------------|
|
|
460
|
+
| `--name` | **Required.** |
|
|
461
|
+
| `--yes` | **Required** to execute. |
|
|
462
|
+
| `--cascade` | `DROP SCHEMA … CASCADE`. |
|
|
463
|
+
| `--check` | SQL only. |
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
### `schema addon`
|
|
468
|
+
|
|
469
|
+
Shared satellite schemas (`utils`, `cibs`, `cm`, `am`, `audit`).
|
|
470
|
+
|
|
471
|
+
#### `schema addon create`
|
|
472
|
+
|
|
473
|
+
Bootstrap a standalone addon (no parent wiring yet).
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
gw schema addon create --type utils --conn "$CONN"
|
|
477
|
+
gw schema addon create --type cibs --name cibs --conn "$CONN"
|
|
478
|
+
gw schema addon create --type audit --conn "$CONN"
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
#### `schema addon integrate`
|
|
482
|
+
|
|
483
|
+
Wire an addon into one ws/ud parent. Run once per parent (e.g. integrate utils with `ws`, then again with `ud`).
|
|
484
|
+
|
|
485
|
+
| Option | Description |
|
|
486
|
+
|--------|-------------|
|
|
487
|
+
| `--type` | **Required.** `utils` \| `cibs` \| `cm` \| `am` \| `audit` |
|
|
488
|
+
| `--parent` | **Required.** Parent ws or ud schema name. |
|
|
489
|
+
| `--name` | Addon schema name (default: same as `--type`). |
|
|
490
|
+
|
|
491
|
+
```bash
|
|
492
|
+
gw schema addon integrate --type utils --parent ws --conn "$CONN"
|
|
493
|
+
gw schema addon integrate --type cibs --parent ud --conn "$CONN"
|
|
494
|
+
gw schema addon integrate --type audit --parent ws --conn "$CONN"
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
#### `schema addon update`
|
|
498
|
+
|
|
499
|
+
Upgrades a **standalone** addon only. If integrated in a network → use `network update`. Downgrades forbidden.
|
|
500
|
+
|
|
501
|
+
```bash
|
|
502
|
+
gw schema addon update --type cibs --version 4.16.0 --conn "$CONN"
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
#### `schema addon drop`
|
|
506
|
+
|
|
507
|
+
```bash
|
|
508
|
+
gw schema addon drop --type utils --yes --cascade --conn "$CONN"
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
#### `schema list`
|
|
512
|
+
|
|
513
|
+
Read-only inventory of schemas with `sys_version`. No superuser required.
|
|
514
|
+
|
|
515
|
+
| Option | Description |
|
|
516
|
+
|--------|-------------|
|
|
517
|
+
| `--tier` | `all` (default), `main` (ws/ud), or `addon` (utils, cibs, am, cm, audit). |
|
|
518
|
+
| `--type` | Repeatable filter: `ws`, `ud`, `utils`, `cibs`, `am`, `cm`, `audit`. |
|
|
519
|
+
| `--conn` / `--config` | Connection. |
|
|
520
|
+
| `--json` | Machine-readable output. |
|
|
521
|
+
|
|
522
|
+
```bash
|
|
523
|
+
gw schema list --conn "$CONN"
|
|
524
|
+
gw schema list --conn "$CONN" --tier main
|
|
525
|
+
gw schema list --conn "$CONN" --tier addon --type cibs --json
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
---
|
|
529
|
+
|
|
530
|
+
### `network show`
|
|
531
|
+
|
|
532
|
+
Scans the whole database (all schemas with `sys_version`) and shows the interconnected Giswater network: ws/ud networks, shared satellites, integration links, version skew, and unlinked schemas.
|
|
533
|
+
|
|
534
|
+
| Option | Description |
|
|
535
|
+
|--------|-------------|
|
|
536
|
+
| `--flat` | Deprecated; use `schema list` instead. |
|
|
537
|
+
| `--schema` | Optional. Focus on the cluster containing this schema. |
|
|
538
|
+
| `--conn` / `--config` | Connection. |
|
|
539
|
+
|
|
540
|
+
```bash
|
|
541
|
+
gw network show --conn "$CONN"
|
|
542
|
+
gw network show --flat --conn "$CONN" --json
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
---
|
|
546
|
+
|
|
547
|
+
### `network update`
|
|
548
|
+
|
|
549
|
+
Lockstep upgrade of the discovered network. For each semver folder (e.g. 4.16.0), runs `utils → cibs → ws → ud → …` before advancing. **Downgrades forbidden** (target must be ≥ every member version).
|
|
550
|
+
|
|
551
|
+
| Option | Description |
|
|
552
|
+
|--------|-------------|
|
|
553
|
+
| `--version` | Target version (default: active dbmodel). |
|
|
554
|
+
| `--locale` | Default `en_US`. |
|
|
555
|
+
| `--check` | Print lockstep plan only. |
|
|
556
|
+
| `--conn` / `--config` | Connection. |
|
|
557
|
+
|
|
558
|
+
```bash
|
|
559
|
+
gw network update --version 4.16.0 --conn "$CONN" --check
|
|
560
|
+
gw network update --version 4.16.0 --conn "$CONN"
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
**E2E smoke** (empty DB, create @ 4.15.0, upgrade @ 4.16.0):
|
|
564
|
+
|
|
565
|
+
```bash
|
|
566
|
+
export CONN='postgresql://user@host:port/giswater_admin_cli'
|
|
567
|
+
chmod +x scripts/gw_e2e_satellites.sh scripts/gw_e2e_network_update.sh
|
|
568
|
+
./scripts/gw_e2e_network_update.sh
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
Fixtures under `dbmodel/schemas/**/updates/4/16/0/` (`gw_lockstep_*`) validate cross-schema ordering.
|
|
572
|
+
|
|
573
|
+
---
|
|
574
|
+
|
|
575
|
+
### Legacy commands (deprecated)
|
|
576
|
+
|
|
577
|
+
The following still work with stderr warnings:
|
|
578
|
+
|
|
579
|
+
- **`create`** — use `schema main create` or `schema addon create` / `integrate`
|
|
580
|
+
- **`update`** — use `schema main update` or `schema addon update`
|
|
581
|
+
- **`drop`** — use `schema main drop` or `schema addon drop`
|
|
582
|
+
- **`status`** — use `network show --flat`
|
|
583
|
+
- **`init-db`** — use `db init`
|
|
584
|
+
- **`update-network`** — use `network update`
|
|
585
|
+
- **`audit structure|activate|drop`** — use `schema addon create|integrate|drop --type audit`
|
|
586
|
+
|
|
587
|
+
See the migration table at the top of this section.
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
591
|
+
### `manifest`
|
|
592
|
+
|
|
593
|
+
#### `manifest list`
|
|
594
|
+
|
|
595
|
+
Lists YAML files under `--dbmodel-path/manifests/`.
|
|
596
|
+
|
|
597
|
+
```bash
|
|
598
|
+
python3 -m giswater_admin manifest list
|
|
599
|
+
python3 -m giswater_admin manifest list --dbmodel-path ./dbmodel --json
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
#### `manifest validate`
|
|
603
|
+
|
|
604
|
+
Validates a manifest file.
|
|
605
|
+
|
|
606
|
+
| Argument | Description |
|
|
607
|
+
|----------|-------------|
|
|
608
|
+
| `path` | Path to `<kind>.yaml` |
|
|
609
|
+
|
|
610
|
+
```bash
|
|
611
|
+
python3 -m giswater_admin manifest validate dbmodel/manifests/ws.yaml
|
|
612
|
+
python3 -m giswater_admin manifest validate dbmodel/manifests/ws.yaml --json
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
---
|
|
616
|
+
|
|
617
|
+
### End-to-end example (ws + ud + utils)
|
|
618
|
+
|
|
619
|
+
```bash
|
|
620
|
+
set -e
|
|
621
|
+
export CONN='postgresql://gisadmin:secret@127.0.0.1:5432/giswater_cli'
|
|
622
|
+
|
|
623
|
+
gw db init --conn "$CONN"
|
|
624
|
+
gw schema main create --type ws --name ws_test --profile sample --conn "$CONN"
|
|
625
|
+
gw schema main create --type ud --name ud_test --profile sample --conn "$CONN"
|
|
626
|
+
gw schema addon create --type utils --conn "$CONN"
|
|
627
|
+
gw schema addon integrate --type utils --parent ws_test --conn "$CONN"
|
|
628
|
+
gw network show --flat --conn "$CONN" --json | python3 -m json.tool
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
## Kinds and manifest profiles
|
|
634
|
+
|
|
635
|
+
| `kind` | Typical profiles | Notes |
|
|
636
|
+
|--------|------------------|-------|
|
|
637
|
+
| **ws** | `empty`, `sample_full`, `sample_inv`, `dev`, `ci`, `update` | Water supply. Updates: `schemas/main/common/updates` then `schemas/main/ws/updates`. |
|
|
638
|
+
| **ud** | same as ws | Sewerage. Updates: common then `schemas/main/ud/updates`. |
|
|
639
|
+
| **utils** | `empty`, `integrate_ws`, `integrate_ud`, `copy_data`, `update` | Standalone create; integrate ws/ud separately; version in `utils.sys_version`. |
|
|
640
|
+
| **am** | `empty`, `update` | Asset management singleton. |
|
|
641
|
+
| **cm** | `bootstrap`, `integrate`, `update` | Bootstrap standalone, then `schema addon integrate --parent …`. |
|
|
642
|
+
| **audit** | `empty`, `integrate`, `update` | Same flow as other addons via `schema addon create|integrate`. |
|
|
643
|
+
|
|
644
|
+
**ws/ud profiles** (from [manifests/ws.yaml](../dbmodel/manifests/ws.yaml)):
|
|
645
|
+
|
|
646
|
+
| Profile | Phases (summary) |
|
|
647
|
+
|---------|------------------|
|
|
648
|
+
| `empty` | `load_base` → `updates` → `lastprocess` → `final_pass` |
|
|
649
|
+
| `sample_full` | … → `load_sample` → `final_pass` |
|
|
650
|
+
| `sample_inv` | … → `load_sample` → `load_inv` → `final_pass` |
|
|
651
|
+
| `dev` | … → `load_dev` → `final_pass` |
|
|
652
|
+
| `ci` | … → `load_sample` → `final_pass` (used by pgTAP bootstrap) |
|
|
653
|
+
| `update` | `reload_fct_ftrg` → `updates` → `lastprocess_upgrade` |
|
|
654
|
+
|
|
655
|
+
Details and folder layout: [dbmodel README — Schema architecture](../dbmodel/README.md#schema-architecture).
|
|
656
|
+
|
|
657
|
+
---
|
|
658
|
+
|
|
659
|
+
## Timing and output
|
|
660
|
+
|
|
661
|
+
| Stream | Content |
|
|
662
|
+
|--------|---------|
|
|
663
|
+
| **stdout** | Final result (YAML or JSON with `--json`). |
|
|
664
|
+
| **stderr** | Progress (`log_format.py`), warnings, errors; `-v`/`-d` add per-file lines. |
|
|
665
|
+
|
|
666
|
+
Example stderr with `-v --timing`:
|
|
667
|
+
|
|
668
|
+
```text
|
|
669
|
+
── Schema build: ws / gw_ws_test profile=empty v4.9.0 ──
|
|
670
|
+
[581/723] phase updates
|
|
671
|
+
[581/723] 1.2s ws/updates/4/2/0/dml.sql
|
|
672
|
+
── Done 10.4s 723 files ──
|
|
673
|
+
updates 7.1s (612 files, 68.0%)
|
|
674
|
+
Slowest:
|
|
675
|
+
3241ms updates ws/updates/4/2/0/dml.sql
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
Paths are shortened using `--dbmodel-path` as the root prefix.
|
|
679
|
+
|
|
680
|
+
```bash
|
|
681
|
+
# Slow SQL files during create
|
|
682
|
+
python3 -m giswater_admin create --kind ws --schema gw_ws_test --profile empty \
|
|
683
|
+
--timing --timing-top 30 -v --timing-threshold-ms 30 \
|
|
684
|
+
--conn "$CONN" 2>&1 | tee /tmp/gw_create_timing.log
|
|
685
|
+
|
|
686
|
+
# JSON timing for jq
|
|
687
|
+
python3 -m giswater_admin create --kind ws --schema gw_ws_test --profile empty \
|
|
688
|
+
--timing --timing-detail --json --conn "$CONN" 2>/dev/null | \
|
|
689
|
+
jq '.timing.slowest_by_phase.updates[:20]'
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
Timing is **per SQL file** only (not per PL/pgSQL function step).
|
|
693
|
+
|
|
694
|
+
---
|
|
695
|
+
|
|
696
|
+
## QGIS integration
|
|
697
|
+
|
|
698
|
+
The plugin builds `BuildParams`, runs `SchemaBuilder` in `core/threads/schema_builder_task.py` via `QtDbAdapter`, and can show the same formatted progress in the **Giswater PY** log. After a build, `summarize_build()` from `engine/timing_report.py` feeds the create-project dialog timing label.
|
|
699
|
+
|
|
700
|
+
---
|
|
701
|
+
|
|
702
|
+
## Unit tests
|
|
703
|
+
|
|
704
|
+
No Docker required:
|
|
705
|
+
|
|
706
|
+
```bash
|
|
707
|
+
# From plugin repo root
|
|
708
|
+
python3 -m pytest test/cli test/engine -v
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
Optional smoke tests against a real cluster (skipped without `PGSERVICE` / `PGDATABASE`):
|
|
712
|
+
|
|
713
|
+
```bash
|
|
714
|
+
PGSERVICE=localhost_giswater python3 -m pytest test/engine/smoke -v
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
Database integration tests: [dbmodel/README.md#testing](../dbmodel/README.md#testing).
|
|
718
|
+
|
|
719
|
+
---
|
|
720
|
+
|
|
721
|
+
## Extending the model
|
|
722
|
+
|
|
723
|
+
1. Add or edit `dbmodel/manifests/<kind>.yaml`.
|
|
724
|
+
2. For a new `kind`, register it in `giswater_admin/cli.py` (`--kind` choices and command validation if needed).
|
|
725
|
+
3. Validate: `python3 -m giswater_admin manifest validate dbmodel/manifests/<kind>.yaml`.
|
|
726
|
+
|
|
727
|
+
Supported phase types: `sql_dir`, `version_walk` (`root:` or `roots:`), `sql_file`, `sql_function`, `sql_inline`. `dir_walk` is deprecated.
|
|
728
|
+
|
|
729
|
+
---
|
|
730
|
+
|
|
731
|
+
## Keeping docs in sync
|
|
732
|
+
|
|
733
|
+
When you add or change CLI flags, update **both** `giswater_admin/cli.py` and this README (global options + affected subcommand tables). A future improvement could dump `argparse` help in CI; that is not automated yet.
|