[HDX-12246] migrate: support customer-required clusters (6.4) - #74
Merged
Conversation
Since turbine-api 6.3 (HDX-11681), project creation requires an existing
Customer on the target cluster, and tables may only reference storages and
credentials that are members of the project's customer (HDX-11643). The
`migrate` command previously forwarded the source project body verbatim,
which fails against 6.4 targets.
Add a customer-resolution and membership pre-flight step to the global
`migrate` command:
- New `migrate/customer.py`:
- Detects whether the target requires a customer from the projects
OPTIONS metadata, so pre-6.3 targets are untouched (no version checks).
- Resolves the target customer from `--target-customer` (name or UUID),
an existing target project's immutable customer, or an interactive
picker; offers to create the customer when missing, mapping 401/403 to
an actionable insufficient-permissions message.
- Registers the migrated table's non-default storages and autoingest
credentials with the customer (add_storage / add_credential), always
behind a confirmation, running before any resource is created so a
decline or 403 never leaves a half-migrated project.
- `resources.py`: strip the source customer/org, inject the resolved
customer on project create, and run the membership pre-flight.
- `commands.py`: add `--target-customer` / `-tc` and document it.
Verified live across versions: 6.4 AIO (flag, picker, creation offer,
inheritance, conflicting-flag warning, storage membership accept/decline)
and a local v6.0.17 pre-customer cluster (old->new upgrade injects the
customer; new->old skips all customer logic).
Bumps hdxcli to 1.0.84.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Only the migrate command is actively maintained and the live-cluster acceptance suite (tests/command_line_interface) has no migrate cases, so pushes now run `pytest tests --ignore=tests/command_line_interface` with no cluster secrets. The acceptance suite moves to an opt-in workflow_dispatch job that still receives the HDXCLI_TESTS_CLUSTER_* secrets. Also bump actions/checkout and actions/setup-python to v7 (node24), matching the runtime GitHub already forces on this workflow. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
hdx-heatherblairs
self-requested a review
September 8, 2026 21:17
…emberships Follow-up fixes from code review: - Customer feature detection now reads the projects OPTIONS `required` flag instead of mere field presence. Field-present-but-optional clusters (6.1-6.3.x, which auto-assign the default customer) no longer get pushed into the customer picker: with no --target-customer they are left to the server's default (previously this aborted a non-interactive run and forced interaction on a migration that used to just work). An explicit --target-customer is still honored on such clusters; the picker is only entered when the target actually requires a customer. - Customer creation trusts the POST response body for the created uuid/name instead of re-reading the list by the typed name, which broke for names the server slugifies (e.g. spaces to dashes) — previously it errored after mutating the target. `find_customer` also matches the slugified form. - ensure_storage_memberships / ensure_credential_memberships continue past a resource without a `customers` field instead of returning, so one such resource no longer abandons registration of the rest. - Strip `hdx_deployment_id` from the copied project body: some cluster versions (e.g. released 6.3.x) expose it as writable in the projects metadata, so the adapter would copy the source's value and the create fails as a duplicate. The target derives its own. Verified live on released v6.3.1 (optional customer field): a full `migrate --only resources` with no --target-customer completes non-interactively, the target project gets its own deployment_id and the server-assigned default customer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
….1-6.3 Cross-version review found that 6.1, 6.2 and 6.3 clusters expose a `customers` field on storage/credential serializers but do not yet provide the customer `add_storage`/`add_credential` actions (those arrive in 6.4 together with membership enforcement). So with --target-customer against such a cluster, a non-member non-default storage or autoingest credential made hdxcli POST to a nonexistent endpoint and abort on the raw 404. Treat 404/405 from the membership-registration call as "the target manages membership itself" and skip it. Correct on 6.1-6.3, which attach the storage/credential to the customer server-side at table-create time and do not enforce membership; harmless on 6.4+ where the action exists. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
hdx-heatherblairs
approved these changes
Sep 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Retrofits the global
hdxcli migratecommand for turbine-api 6.4's multi-org breaking changes.Since turbine-api 6.3 (HDX-11681), project creation requires an existing Customer on the target cluster, and tables may only reference storages/credentials that are members of the project's customer (HDX-11643).
migratepreviously forwarded the source project body verbatim (carrying the source cluster's customer UUID), which fails against 6.4 targets — exactly the break flagged on the ticket.Changes
migrate/customer.pyOPTIONSmetadata, so pre-6.3 targets are untouched (no version checks).--target-customer(name or UUID) → an existing target project's immutable customer → an interactive picker; offers to create the customer when missing, mapping 401/403 to an actionable insufficient-permissions message.add_storage/add_credential), always behind a confirmation, running before any resource is created so a decline or 403 never leaves a half-migrated project.resources.py— strip the sourcecustomer/org, inject the resolved customer on project create, run the membership pre-flight.commands.py— add--target-customer/-tcand document it.Scope
Per the ticket comment, this covers only the global
migratecommand, which is the only hdxcli command maintained going forward. The config-onlyproject migrate(and the sharedmigrate_resource_configengine) andhdxcli project createhave the same 6.3+ break; they are legacy commands and are intentionally not being updated. There is no follow-up planned for them.Testing
tests/test_migrate_customer.py(resolution precedence, OPTIONS gating, collectors, default-candidate rule). Full suite green.v6.3.0-rc.1-193): flag resolution, interactive picker, customer creation offer, existing-project inheritance, conflicting-flag warning, and the storage-membership pre-flight (decline aborts before any creation; accept runsadd_storageand the table create passes validation).Notes
run_tests.ymlnow runs only the hermetic unit tests on push (pytest tests --ignore=tests/command_line_interface). The live-cluster acceptance suite covers the legacy CRUD commands, has nomigratecases, and on 6.x has known failures unrelated to this PR, so it moves to an opt-inworkflow_dispatchjob.actions/checkoutandactions/setup-pythonare bumped to v7 (node24).🤖 Generated with Claude Code