PostgreSQL state and drift¶
AI-translated from Russian.
From odpm 4.3 onward, PostgreSQL cluster configuration (compose, odoo.conf, data directory, application role) is tracked via .odpm/database/last_run.json. This is separate from Odoo database operations (-d, --db-backup, --db-restore).
Why it exists¶
Database “truth” used to be spread across .env, docker-compose.yml, odoo.conf, the bind-mounted data directory, and the live PostgreSQL cluster. Renaming a service, changing ports, or reusing an old data dir often failed deep inside the container.
odpm now:
- Collects configuration fingerprints.
- Compares them to the last snapshot (
last_run.json). - Surfaces drift in
odpm planand beforecompose up. - Adopts legacy projects without a snapshot on first startup.
.odpm/database/last_run.json¶
| Property | Value |
|---|---|
| Generated by | odpm automatically |
| Git | do not commit (like runtime/config.json) |
| Container mount | .odpm/database → /run/odpm/database (read-write for checker) |
schema_version |
1 |
The snapshot includes:
compose— PostgreSQL service name, image tag, absolute data path, host port;odoo_conf—db_host,db_port,db_user;cluster— non-empty data dir, PostgreSQL major (PG_VERSION), application role and presence.
When the baseline is updated¶
| Event | Writer |
|---|---|
First run without last_run.json |
Adoption — before compose up (role + baseline) |
| Successful credential check in checker | Checker — after TCP and psql as db_user |
Adoption runs once. While the file exists, only drift vs the saved snapshot is reported.
Legacy project adoption¶
If last_run.json is missing (typical with an inherited PostgreSQL data directory), odpm before the full stack:
- Starts PostgreSQL if needed.
- Runs
ensure_app_role— creates or updates the application role (defaultodoo), including single-user bootstrap when no admin login role exists. - Writes the current configuration as baseline.
Adoption does not:
- reassign PostgreSQL owners of existing Odoo databases;
- drop or restore Odoo databases;
- auto-wipe the data directory on PostgreSQL major changes.
See also legacy-project.md.
Drift kinds and severity¶
| KIND | Severity | Behaviour |
|---|---|---|
first_run |
info | No snapshot; baseline adopted on startup |
service_name, db_host_mismatch, host_port |
low | Warning in plan |
odpm_scenario, data_dir_empty_changed |
medium | Interactive prompt or --accept-database-drift |
data_path, postgres_major, app_role_missing |
high | Prompt; blocks container start without resolution |
Prepare step database.drift in odpm plan reflects mismatches before compose is written.
Interactive resolution¶
With a TTY, odpm prompts (accept new data path, create role, show wipe instructions, etc.). Without TTY — error listing KINDs; use --accept-database-drift=KIND (repeatable).
Accepted KIND values:
data_pathpostgres_majorapp_role_missingodpm_scenariodata_dir_empty_changed
See non-interactive runs.
database subcommand¶
odpm database status
odpm database status --format json
odpm database ensure-role
| Command | Purpose |
|---|---|
database status |
Fingerprints, drift, live probes (postgres container, readiness, role) |
database status --format json |
Same as JSON for scripts |
database ensure-role |
Create or update the application role in a running PostgreSQL |
Commands run prepare (without compose up) when needed to read configuration.
.env and odoo.conf¶
POSTGRES_SERVICE_NAME in .env sets the compose service name and the expected db_host in odoo.conf. On mismatch:
- prepare step
template.odoo_confregenerates the config; - drift
db_host_mismatchappears in plan.
Odoo databases: backup, restore, drop¶
--db-drop, --db-restore, --db-backup operate on Odoo databases inside the cluster, not on last_run.json.
On a legacy cluster a database may exist but be owned by another PostgreSQL user. Standard Odoo exp_drop then skips silently; odpm falls back to direct DROP DATABASE and fails clearly if the database remains.
Example:
odpm -d test_db --db-drop --db-restore my_backup.zip -i -u --set-admin-pass
Troubleshooting¶
odpm database status
odpm plan --skip-start
docker compose logs db-dev # service name from POSTGRES_SERVICE_NAME
After renaming the postgres service, remove orphan containers:
docker compose down --remove-orphans
What odpm does not automate¶
- Data migration on PostgreSQL major upgrades (backup + wipe per prompt instructions).
ALTER DATABASE … OWNER TOfor old Odoo DBs — use--db-dropor manualpsql.- Sharing
last_run.jsonacross machines — snapshot is local per environment directory.