feat(postgres) — PostGIS, posé par le playbook et non par une image custom #52

Merged
arcodange merged 1 commits from arcodange/postgis-pour-kadans into main 2026-08-08 11:59:41 +02:00
Owner

Kadans doit ranger le contour d'un quartier en vraie géométrie (geometry(MultiPolygon,4326), ST_Contains, index GiST) — demande fondateur du 2026-08-08. L'extension n'existait nulle part : mesuré sur pi2, pg_available_extensions ne rend aucune ligne postgis%.

Arbitrage fondateur : on garde postgres:16.3-alpine et on pose l'extension par Ansible, comme ce playbook pose déjà les bases applicatives et le rôle pgbouncer. Pas d'image custom.

⚠ Pourquoi le recalage de chemins n'est pas facultatif

Mesuré sur pi2 (arm64), dans un conteneur jetable. apk add postgis seul réussit, et CREATE EXTENSION postgis échoue quand même :

ERROR:  extension "postgis" is not available
DETAIL: Could not open extension control file
        "/usr/local/share/postgresql/extension/postgis.control"

Le paquet Alpine vise la disposition d'Alpine (/usr/share/postgresql16, /usr/lib/postgresql16) ; l'image officielle postgres:16-alpine compile le serveur dans /usr/local. Les fichiers sont sur le disque, le serveur regarde ailleurs.

Après recalage, dans le même conteneur jetable :

CREATE EXTENSION
3.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
{"type":"Polygon","coordinates":[[[4.8,45.7],[4.9,45.7],[4.9,45.8],[4.8,45.8],[4.8,45.7]]]}

Ne pas « simplifier » en un apk add nu : apk add --simulate dit OK, l'installation dit OK, et l'extension reste inutilisable. C'est exactement le genre de vert qui ne prouve rien.

⚠ Installation par CONTENEUR, pas par volume — la limite est écrite

apk add écrit dans la couche inscriptible du conteneur, pas dans le volume. Recréer le conteneur (changement d'image, --force-recreate) efface PostGIS pendant que les données gardent leurs colonnes géométriques : toute requête spatiale casse jusqu'au prochain passage du playbook.

C'est la contrepartie assumée du « pas d'image custom ». Trois choses la rendent tenable, et elles sont dans le code :

  1. l'installation vient après le déploiement compose — si celui-ci a recréé le conteneur, la couche est neuve et PostGIS reparti avec ; c'est ce qui rend le couple rejouable ;
  2. les tâches sont idempotentes (apk add l'est, les copies écrasent des fichiers identiques) ;
  3. une tâche de vérification qui échoue au lieu de rassurer.

La vérification ne se contente pas d'un code de retour

Elle exige que la base rende USE_GEOS=1 et un vrai Point GeoJSON avec son SRID appliqué :

failed_when: >-
  postgis_verifier.rc != 0
  or 'USE_GEOS=1' not in postgis_verifier.stdout
  or '"type":"Point"' not in postgis_verifier.stdout

Un bouchon qui répondrait une chaîne vide passerait un simple rc == 0 et ne prouverait rien. Un playbook vert sur une extension absente ferait atterrir le symptôme dans Kadans, des jours plus tard, déguisé en bug applicatif — c'est précisément le mode d'échec qu'on refuse.

Vérifié sur le conteneur RÉEL, sans le modifier

Le conteneur de prod tourne depuis 3 mois ; ses dépôts APK pouvaient avoir dérivé. Contrôlé en lecture seule :

  • apk add --simulate postgis → résout postgis 3.4.2-r2, 62 paquets, OK: 181 MiB ;
  • pg_config --sharedir / --pkglibdir/usr/local/share/postgresql et /usr/local/lib/postgresql, exactement ce que supposent les variables ;
  • SELECT count(*) FROM pg_extension WHERE extname='postgis' sur kadans0, rien n'est encore posé.

ansible-playbook --syntax-check passe (le seul avertissement, variable using reserved name 'namespace', est pré-existant et vit dans le second play, non touché).

Ce que cette PR ne fait PAS

  • Elle n'a pas été jouée contre la prod. Cette base porte 9 bases dont gitea — la forge et la CI en dépendent. Le lancement reste au fondateur.
  • Elle ne crée aucune table ni colonne géométrique : c'est le travail de kadans-api, qui vient ensuite et qui ne peut pas migrer avant que cette extension existe.
  • Elle n'active PostGIS que sur kadans (postgis.databases). Ajouter une base est une ligne.

Pour jouer

ansible-playbook -i ansible/arcodange/factory/inventory \
  ansible/arcodange/factory/playbooks/setup/postgres.yml

La tâche « Report the PostGIS version in use » affiche la version obtenue par base.

🤖 Generated with Claude Code

https://claude.ai/code/session_01J4UE4AmX5PAMN6c6Q6Fey9

Kadans doit ranger le **contour d'un quartier** en vraie géométrie (`geometry(MultiPolygon,4326)`, `ST_Contains`, index GiST) — demande fondateur du 2026-08-08. L'extension n'existait nulle part : mesuré sur pi2, `pg_available_extensions` ne rend **aucune** ligne `postgis%`. Arbitrage fondateur : on **garde `postgres:16.3-alpine`** et on pose l'extension par Ansible, comme ce playbook pose déjà les bases applicatives et le rôle pgbouncer. **Pas d'image custom.** ## ⚠ Pourquoi le recalage de chemins n'est pas facultatif Mesuré sur pi2 (arm64), dans un conteneur jetable. `apk add postgis` **seul réussit**, et `CREATE EXTENSION postgis` échoue quand même : ``` ERROR: extension "postgis" is not available DETAIL: Could not open extension control file "/usr/local/share/postgresql/extension/postgis.control" ``` Le paquet Alpine vise la disposition d'**Alpine** (`/usr/share/postgresql16`, `/usr/lib/postgresql16`) ; l'image officielle `postgres:16-alpine` compile le serveur dans `/usr/local`. **Les fichiers sont sur le disque, le serveur regarde ailleurs.** Après recalage, dans le même conteneur jetable : ``` CREATE EXTENSION 3.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1 {"type":"Polygon","coordinates":[[[4.8,45.7],[4.9,45.7],[4.9,45.8],[4.8,45.8],[4.8,45.7]]]} ``` **Ne pas « simplifier » en un `apk add` nu** : `apk add --simulate` dit OK, l'installation dit OK, et l'extension reste inutilisable. C'est exactement le genre de vert qui ne prouve rien. ## ⚠ Installation par CONTENEUR, pas par volume — la limite est écrite `apk add` écrit dans la **couche inscriptible** du conteneur, pas dans le volume. Recréer le conteneur (changement d'image, `--force-recreate`) **efface PostGIS** pendant que les données gardent leurs colonnes géométriques : toute requête spatiale casse jusqu'au prochain passage du playbook. C'est la contrepartie assumée du « pas d'image custom ». Trois choses la rendent tenable, et elles sont dans le code : 1. l'installation vient **après** le déploiement compose — si celui-ci a recréé le conteneur, la couche est neuve et PostGIS reparti avec ; c'est ce qui rend le couple rejouable ; 2. les tâches sont **idempotentes** (`apk add` l'est, les copies écrasent des fichiers identiques) ; 3. une tâche de **vérification** qui échoue au lieu de rassurer. ## La vérification ne se contente pas d'un code de retour Elle exige que la base rende **`USE_GEOS=1`** *et* un vrai `Point` GeoJSON avec son SRID appliqué : ```yaml failed_when: >- postgis_verifier.rc != 0 or 'USE_GEOS=1' not in postgis_verifier.stdout or '"type":"Point"' not in postgis_verifier.stdout ``` Un bouchon qui répondrait une chaîne vide passerait un simple `rc == 0` et ne prouverait rien. Un playbook vert sur une extension absente ferait atterrir le symptôme **dans Kadans, des jours plus tard, déguisé en bug applicatif** — c'est précisément le mode d'échec qu'on refuse. ## Vérifié sur le conteneur RÉEL, sans le modifier Le conteneur de prod tourne depuis 3 mois ; ses dépôts APK pouvaient avoir dérivé. Contrôlé en lecture seule : - `apk add --simulate postgis` → résout **`postgis 3.4.2-r2`**, 62 paquets, `OK: 181 MiB` ; - `pg_config --sharedir` / `--pkglibdir` → `/usr/local/share/postgresql` et `/usr/local/lib/postgresql`, exactement ce que supposent les variables ; - `SELECT count(*) FROM pg_extension WHERE extname='postgis'` sur `kadans` → **0**, rien n'est encore posé. `ansible-playbook --syntax-check` passe (le seul avertissement, `variable using reserved name 'namespace'`, est **pré-existant** et vit dans le second play, non touché). ## Ce que cette PR ne fait PAS - **Elle n'a pas été jouée contre la prod.** Cette base porte **9 bases dont `gitea`** — la forge et la CI en dépendent. Le lancement reste au fondateur. - Elle ne crée **aucune** table ni colonne géométrique : c'est le travail de `kadans-api`, qui vient ensuite et qui ne peut pas migrer avant que cette extension existe. - Elle n'active PostGIS que sur `kadans` (`postgis.databases`). Ajouter une base est une ligne. ## Pour jouer ```bash ansible-playbook -i ansible/arcodange/factory/inventory \ ansible/arcodange/factory/playbooks/setup/postgres.yml ``` La tâche « Report the PostGIS version in use » affiche la version obtenue par base. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01J4UE4AmX5PAMN6c6Q6Fey9
arcodange added 1 commit 2026-08-08 09:47:12 +02:00
Kadans doit ranger le contour d'un quartier en vraie géométrie
(geometry(MultiPolygon,4326), ST_Contains, index GiST). L'extension
n'existait nulle part : mesuré sur pi2, `pg_available_extensions` ne
rendait AUCUNE ligne `postgis%`.

Arbitrage fondateur (2026-08-08) : on garde `postgres:16.3-alpine` et on
pose l'extension par Ansible, comme le playbook pose déjà les bases et le
rôle pgbouncer. Pas d'image custom.

⚠ POURQUOI LE RECALAGE DE CHEMINS N'EST PAS FACULTATIF — mesuré, arm64.
`apk add postgis` SEUL réussit, et `CREATE EXTENSION postgis` échoue quand
même :

    ERROR: extension "postgis" is not available
    DETAIL: Could not open extension control file
            "/usr/local/share/postgresql/extension/postgis.control"

Le paquet Alpine vise la disposition d'Alpine (/usr/share/postgresql16,
/usr/lib/postgresql16) ; l'image officielle compile le serveur dans
/usr/local. Les fichiers sont là, le serveur regarde ailleurs. Après
recalage : PostGIS 3.4 USE_GEOS=1 USE_PROJ=1, et un polygone lyonnais qui
fait l'aller-retour ST_GeomFromText → ST_AsGeoJSON.

Ne pas « simplifier » en un `apk add` nu : la simulation dit OK,
l'installation dit OK, et l'extension reste inutilisable.

⚠ INSTALLATION PAR CONTENEUR, PAS PAR VOLUME. `apk add` écrit dans la
couche inscriptible : recréer le conteneur efface PostGIS pendant que les
données gardent leurs colonnes géométriques — toute requête spatiale casse
jusqu'au prochain passage du playbook. D'où l'ordre (déploiement compose
PUIS installation), l'idempotence, et surtout la tâche de vérification.

La vérification ne se contente pas d'un code de retour : elle exige que la
base rende USE_GEOS=1 ET un vrai Point GeoJSON avec son SRID. Un bouchon
qui répondrait une chaîne vide passerait un simple `rc == 0` et ne
prouverait rien — un playbook vert sur une extension absente ferait
atterrir le symptôme dans Kadans, des jours plus tard, déguisé en bug
applicatif.

Vérifié sur le conteneur RÉEL sans le modifier : `apk add --simulate`
résout postgis 3.4.2-r2, et `pg_config` y rend bien les deux chemins que
les variables supposent.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01J4UE4AmX5PAMN6c6Q6Fey9
arcodange merged commit 1520ecac41 into main 2026-08-08 11:59:41 +02:00
arcodange deleted branch arcodange/postgis-pour-kadans 2026-08-08 11:59:42 +02:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: arcodange-org/factory#52