Repository navigation
Copy only the named schemas in data copy (#124) - #134
Conversation
|
@romamo Decision needed: the approved spec 007 names the flag
Also in this PR, for your information (decided under the spec's own wording): without the flag, the empty-target and row-count checks now cover every non-system schema, not only Reply here with a number or your own answer; shipmill takes this up on the tick after your reply. |
|
Decision by @romamo, relayed by Claude Code
|
cloudfall data copy dumped every schema but its empty-target and row-count checks read only public, so the receipt vouched for one schema of many. A repeatable --source-schema now selects what pg_dump takes, and both checks read exactly the selected schemas; without it the dump command is unchanged and the checks cover every non-system schema of the source. The receipt records spec.schemas and a schema per table. Schema names reach SQL only as one psql variable that psql quotes as a literal, and reach pg_dump as shell-quoted, double-quoted patterns. The spec names the flag --schema; treaty reserves that name for printing a command's schema, so the flag is --source-schema. Fixes #124 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A --source-schema name reaches the engine as an Ansible extra var, and
Ansible templates extra vars: a name such as {{ lookup('pipe', 'id') }}
ran a command on the management host. Names are now a PostgresSchemaName:
non-empty, at most 63 bytes, no control character and no brace, refused
as a usage error before any plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
324e19c to
c6a0cbc
Compare
The maintainer chose --source-schema (MCP source_schema) on #134: treaty reserves --schema on every command. Only the flag's name changes. Co-authored-by: shipmill-romamo[bot] <338557544+shipmill-romamo[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The data-copy receipt now reads the selected schemas and the parsed tables, so the replay sets both and runs the role's table-recording task. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review before merge, on
Left for #125: a named schema missing from the source is skipped while the receipt's |
Summary
cloudfall data copydumped every schema of the source, but its empty-target check and its row-count query read onlypublic, so the receipt's "per-table row counts matched" vouched for one schema of many (S-007). This PR adds a repeatable source-schema selection:data copy --source-schema NAME(repeatable; thedata_copyMCP tool gets asource_schemalist).pg_dumpgets one--schemaper name, and the empty-target check and the row-count check read exactly the selected schemaspg_dumpcommand is byte-for-byte the 0.7.0 one, and the plan's extra vars are unchanged. The selected schemas are every source schema exceptpg_catalog,information_schema,pg_toast, and thepg_temp_*/pg_toast_temp_*families, read from the source before the empty-target checkschema,table,rowsline per base table, ordered by schema and tablespec.schemas(sorted) and aschemaon eachspec.tables[]entry besidetableandrows. This is additive: no JSON schema, schema lock, or SDK reader exists forDataMigrationReceipt, andtable/rowskeep their meaning--yessays either "dump schemas app, public of the database ..." or "dump every non-system schema of the database ..."Injection safety. Schema names never go into SQL text. They reach psql as a single
--set cloudfall_data_schemas=<JSON array>value (one argv element, or onequoted shell word on the source side), and the SQL reads it back as:'cloudfall_data_schemas', which psql quotes as a literal. The queries now run from stdin with--no-psqlrc --set ON_ERROR_STOP=1. On thepg_dumpside, each name is double-quoted as a literal pattern (internal"doubled) and then shell-quoted. This holds without #126's name check: a test passesBad;Name"$(touch x)and gets back one quoted argument.Spec deviation. S-007 calls the flag
--schema. treaty reserves--schemafor printing a command's schema (REQ-F-079), so registering it fails at import. The flag is therefore--source-schema, which pairs with--source-url-file. The spec text and the #125/#126 wording should follow, or treaty would need to free the name.Out of scope here: the preflight refusals and
pg_restore --single-transaction(#125), and name validation andmigrate --data-schema(#126). Until #125 adds--extension, a--source-schemacopy dumps no extensions, so a selected table that needs one fails at restore.Fixes #124
Test plan
uv run ruff check .,uv run mypy: cleanansible-lintrun fromengine/ansible(where itsansible.cfglives): passed, production profileansible-playbook --syntax-checkonplaybooks/data.ymlagainst the rendered example inventory: passedpytest engine/tests sdk/tests/test_data_migration.py sdk/tests/test_lifecycle.py sdk/tests/test_app.py sdk/tests/test_commands.py sdk/tests/test_agent_server.py sdk/tests/test_project.py: 179 passedengine/tests/test_data_migration_role.pyruns the role's tasks through Ansible's ownTemplar: the dump command with and without names, the schema selection, the psql variable, the empty-target assertion, and the receipt built from CSV lines (including a quotedodd, "name"table)psql/postgres. S-007-1 to S-007-5 are covered only as rendered and unit tests. The SQL itself (thejsonb_array_elements_text(:'var'::jsonb)filter, thepg_namespacequery, psql running the queries from stdin) has not been executed against a server. A proving run should check themPlan
specs.py coverage --spec 007)🤖 Generated with Claude Code