Skip to content

Infer Docker registry host from workspace profile - #6782

Merged
pietern merged 1 commit into
mainfrom
chen-shou_data/stack/auth-docker-infer-region-hosts
Sep 24, 2026
Merged

pietern merged 1 commit into
mainfrom
chen-shou_data/stack/auth-docker-infer-region-hosts

Conversation

@yolocs

@yolocs yolocs commented Sep 21, 2026 •

Copy link
Copy Markdown
Collaborator

🥞 Stacked PR (generated by git ns)

Use this link to review incremental changes.


Changes

Docker setup now needs only a workspace profile. The CLI resolves the workspace ID, obtains the workspace region from its metastore summary, derives the full Artifact Registry hostname, and configures Docker for that host:

$ databricks auth docker configure --profile PROD
Configured Docker credential helper for 1234567890123456.container.us-west-2.cloud.databricks.com
Updated Docker config: /Users/alice/.docker/config.json
Installed Docker credential helper: /usr/local/bin/docker-credential-databricks

Users no longer need to look up and supply the workspace home region. The existing --region flag remains available for compatibility, emits a deprecation warning when used, and is scheduled for removal in the next release.

The new read-only host command returns both the derived registry hostname and whether Docker is already configured to use the Databricks credential helper:

$ databricks auth docker host --profile PROD
Registry host: 1234567890123456.container.us-west-2.cloud.databricks.com
Credential helper configured: YES

Structured output makes the result available to scripts without reconstructing the hostname:

$ databricks auth docker host --profile PROD --output json
{
  "host": "1234567890123456.container.us-west-2.cloud.databricks.com",
  "configured": true
}

Both commands now turn an invalid OAuth refresh token into a direct recovery step instead of exposing the underlying token request:

$ databricks auth docker host --profile EXPIRED
Error: A new access token could not be retrieved because the refresh token is invalid. To reauthenticate, run the following command:
  $ databricks auth login --profile EXPIRED

Profiles whose host is not a Databricks workspace domain fail before any workspace request or Docker configuration change:

$ databricks auth docker host --profile CUSTOM
Error: profile "CUSTOM" does not target a supported Databricks workspace host. Select a workspace profile, or create one with databricks auth login --host <workspace-url> --profile <name>

To run these flows end to end against the acceptance test server, a workspace served from http://127.0.0.1 maps to a .localhost registry DNS zone (e.g. 900800700600.container.us-west-2.localhost). This is the same local-testing exception OAuth login already makes for http://127.0.0.1 hosts. The credential helper returns tokens for .localhost registries only to profiles on http://127.0.0.1, so a real workspace's token never reaches a local registry. The test server also gains a default metastore_summary handler.

Why

Workspace profiles do not expose the home region directly, and asking users to discover it separately made Docker setup unnecessarily error-prone. The workspace metastore already provides the matching region, so the CLI can derive the correct registry host from the selected profile and expose that same result for later commands and automation.

The error handling keeps authentication and profile-selection failures actionable, especially when a saved OAuth session has expired or an account profile is selected accidentally.

Tests

Acceptance tests in acceptance/cmd/auth/docker/ now run the real flow against the test server, without --region and without rewriting the profile mid-test:

  • configure: host reports the helper as not configured; configure resolves the workspace ID (SCIM) and region (metastore summary), saves workspace_id to the profile, and writes the exact Docker config; host --output json reports it as configured; docker-credential-databricks get returns a token. Recorded requests show which API calls each step makes. A rerun leaves the Docker config unchanged, and the deprecated --region flag makes no API calls.
  • configure-errors: unsupported flags, conflicting profile selectors, a non-Databricks host, and a duplicate workspace_id all fail without creating the Docker config or changing profiles.
  • host: text and JSON output, credsStore detection, and the profile is never modified.
  • token: cached vs. refreshed token, unknown workspace, non-registry host, --profile rejected, a test-server registry never matching a remote profile, duplicate profiles.
  • invalid-refresh-token: host, configure, and token all print the re-login command, and no Docker config is created.

Unit tests that walked these flows through mocks were removed. The remaining ones cover what the test server can't reach: shim install ordering, the PATH warning, metastore failures, and the workspace_id = none sentinel.

  • go test ./acceptance -run 'TestAccept/cmd/auth' -count=1 (129 passed)
  • go test ./cmd/auth/... ./libs/dockercredentials/... ./libs/testserver/...
  • ./task lint-q, ./task fmt-q, ./task ws

This pull request and its description were written by Isaac.

@yolocs
yolocs force-pushed the chen-shou_data/stack/auth-docker-infer-region-hosts branch from d4fef20 to 416ca6a Compare September 21, 2026 17:30
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 3a91fa6

Run: 35892694001

Env ✅​pass 🙈​skip Time
✅​ aws linux 276 21 5:50
✅​ aws windows 278 19 4:20
✅​ azure linux 275 21 6:43
✅​ azure windows 277 19 5:07
✅​ gcp linux 276 21 5:57
✅​ gcp windows 278 19 4:29
Top 3 slowest tests (at least 2 minutes):
duration env testname
3:31 azure windows TestAccept
3:29 aws windows TestAccept
3:26 gcp windows TestAccept

@yolocs
yolocs force-pushed the chen-shou_data/stack/auth-docker-infer-region-hosts branch from 416ca6a to 319effe Compare September 21, 2026 19:09
@yolocs
yolocs marked this pull request as ready for review September 21, 2026 19:38
@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Approval status: pending

/cmd/auth/ - needs approval

7 files changed
Suggested: @simonfaltum
Also eligible: @renaudhartert-db, @hectorcast-db, @parthban-db, @tanmay-db, @Divyansh-db, @tejaskochar-db, @mihaimitrea-db, @chrisst, @rauchy

General files (require maintainer)

6 files changed
Based on git history:

  • @pietern -- recent work in cmd/auth/docker/, libs/dockercredentials/, .nextchanges/cli/

Any maintainer (@andrewnester, @anton-107, @denik, @pietern, @shreyas-goenka, @simonfaltum, @renaudhartert-db, @janniklasrose, @lennartkats-db, @rugpanov, @rclarey) can approve all areas.
See OWNERS for ownership rules.

@yolocs
yolocs force-pushed the chen-shou_data/stack/auth-docker-infer-region-hosts branch from 319effe to 62668a9 Compare September 22, 2026 06:07

@pietern pietern left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests in this PR mock pretty much everything and then go through e2e flows.

I recommend testing the units independently and reserving e2e for acc tests.

Comment thread libs/dockercredentials/docker_config_test.go
@yolocs
yolocs force-pushed the chen-shou_data/stack/auth-docker-infer-region-hosts branch from 62668a9 to e07b06f Compare September 22, 2026 18:43
@yolocs
yolocs requested review from a team as code owners September 22, 2026 18:43
@yolocs
yolocs force-pushed the chen-shou_data/stack/auth-docker-infer-region-hosts branch 2 times, most recently from fc154fa to 2e32231 Compare September 23, 2026 05:36
@yolocs

yolocs commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator Author

The tests in this PR mock pretty much everything and then go through e2e flows.

I recommend testing the units independently and reserving e2e for acc tests.

@pietern

I restructured the unit tests to exercise each component directly, covering host derivation, helper status, output formats, errors, and config immutability.

I couldn’t add a successful host acceptance test without a much larger change because the logic depends on the profile’s workspace domain. I believe the existing configure acceptance test still provides solid end-to-end coverage of the Docker helper flow.

Co-authored-by: Isaac <no-reply@databricks.com>
@yolocs
yolocs force-pushed the chen-shou_data/stack/auth-docker-infer-region-hosts branch from 2e32231 to 3a91fa6 Compare September 23, 2026 17:00
@pietern
pietern added this pull request to the merge queue Sep 24, 2026
Merged via the queue into main with commit 92335ba Sep 24, 2026
31 checks passed
@pietern
pietern deleted the chen-shou_data/stack/auth-docker-infer-region-hosts branch September 24, 2026 08:41
deco-sdk-tagging Bot added a commit that referenced this pull request Sep 24, 2026
## Release v1.18.0

### CLI

 * The AI Runtime commands have moved to `databricks air`. The previous `databricks experimental air` path now directs users to the new command. ([#6722](#6722))
 * Write local state, cache, and config files atomically so an interrupted or concurrent write cannot corrupt them. ([#6708](#6708))
 * Deprecate `--region` in `databricks auth docker configure` ahead of its removal in the next release, infer the Artifact Registry region when it is omitted, and add `databricks auth docker host --profile <name>` to show the profile's registry host and credential-helper status. ([#6782](#6782))
 * Return `UNAUTHENTICATED` instead of `INVALID_REFRESH_TOKEN` when `databricks auth token --output json` cannot refresh a cached U2M token. ([#6731](#6731))
 * Retry the current-user (SCIM `Me`) lookup on transient HTTP 500 responses so a temporarily-unavailable backend no longer fails bundle commands outright. ([#6766](#6766))
 * Preserve workspace-file and volume access for SSH server descendants when the bootstrap notebook exits and the server survives. ([#6645](#6645))
 * `ssh connect` and `ssh setup` now accept a `--keep-detached-processes` flag to keep processes detached from the SSH session (`tmux`, `setsid`, `nohup`) running after the tunnel shuts down. Teardown then terminates only the tunnel's own process group, and the bootstrap job run is held open while any detached process is still running, so the survivors keep their `/Workspace` and `/Volumes` access. A held-open run also suppresses cluster autotermination, so the flag is off by default, is bounded by `--server-timeout`, and is dedicated-cluster only. Without it, the server now logs a warning naming the detached processes it is about to destroy, instead of sweeping them silently. ([#6387](#6387))

### Bundles

 * direct: Allow clearing a catalog's or schema's `custom_max_retention_hours` by removing it from configuration. ([#6792](#6792))
 * direct: Allow clearing a genie space's `description` and a secret's `comment` by removing them from configuration. ([#6789](#6789))
 * Fix direct-engine deploy recreating an MLflow experiment on every deploy when its `trace_location` was set out-of-band. ([#6787](#6787))
 * direct: Store a Genie space's `serialized_space` in state as a content hash instead of its full contents. ([#6707](#6707))
 * Fix `bundle deploy` failing with "Invalid python file reference" for jobs that use `git_source` with a `spark_python_task` on the direct engine. ([#6751](#6751))
 * Fixed the direct engine mishandling UC grants that combine `ALL_PRIVILEGES` with a privilege it does not imply (`MANAGE`, `READ_METADATA`, `EXTERNAL_USE_SCHEMA`, `EXTERNAL_USE_LOCATION`): such privileges were dropped when granted and left behind when revoked, so the deployment never converged. ([#6733](#6733), [#6743](#6743))
 * Don't fail migration if clean up actions fail. ([#6772](#6772))
 * Ignore the backend-provided `spark.sql.ansi.enabled: "true"` pipeline configuration default when detecting direct-engine drift. ([#6816](#6816))
 * Fix recreating a postgres synced table sometimes failing with a 409 ALREADY_EXISTS error while the previous table is still being deleted. ([#6728](#6728))
 * Direct engine no longer recreates a resource when an immutable field the config omits was populated by the backend. ([#6790](#6790))

### Dependency Updates

 * Bump dependencies with known vulnerabilities. ([#6723](#6723))
 * Bump `github.com/databricks/databricks-sdk-go` from v0.178.0 to v0.182.0. ([#6817](#6817))
 * Bump the Databricks Terraform provider from v1.132.0 to v1.134.0. ([#6818](#6818))
@eng-dev-ecosystem-bot

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 92335ba

Run: 35976747207

Env ❌​FAIL 🔄​flaky ✅​pass 🙈​skip Time
🔄​ aws linux 6 1690 1087 238:12
🔄​ aws windows 3 1594 1112 272:51
🔄​ azure linux 3 1502 1138 182:01
🔄​ azure windows 3 1403 1163 210:39
❌​ gcp linux 3 1488 1142 181:33
✅​ gcp windows 1392 1167 235:43
13 interesting tests: 10 flaky, 3 FAIL
Test Name aws linux aws windows azure linux azure windows gcp linux
❌​ TestAccept ✅​p 🔄​f 🔄​f 🔄​f ❌​F
❌​ TestAccept/bundle/config-remote-sync/multiple_resources ✅​p 🙈​s ✅​p 🙈​s ❌​F
❌​ TestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ✅​p ✅​p ❌​F
🔄​ TestAccept/bundle/resources/apps/lifecycle-started 🔄​f ✅​p ✅​p ✅​p ✅​p
🔄​ TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS= 🔄​f ✅​p ✅​p ✅​p ✅​p
🔄​ TestAccept/bundle/resources/dashboards/change-name 🔄​f ✅​p ✅​p ✅​p ✅​p
🔄​ TestAccept/bundle/resources/dashboards/change-name/DATABRICKS_BUNDLE_ENGINE=terraform/DMS= 🔄​f ✅​p ✅​p ✅​p ✅​p
🔄​ TestAccept/bundle/resources/postgres_endpoints/update_suspend_timeout ✅​p 🔄​f 🙈​s 🙈​s 🙈​s
🔄​ TestAccept/bundle/resources/postgres_endpoints/update_suspend_timeout/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ✅​p 🔄​f
🔄​ TestAccept/bundle/resources/postgres_synced_tables/recreate/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true 🔄​f ✅​p
🔄​ TestAccept/bundle/resources/postgres_synced_tables/recreate/DATABRICKS_BUNDLE_ENGINE=terraform/DMS= 🔄​f ✅​p
🔄​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name ✅​p ✅​p 🔄​f 🔄​f ✅​p
🔄​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true ✅​p ✅​p 🔄​f 🔄​f ✅​p
Top 50 slowest tests (at least 2 minutes):
duration env testname
11:59 gcp windows TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
11:45 gcp windows TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
11:12 gcp windows TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
10:55 gcp windows TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
10:49 gcp linux TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
10:36 aws windows TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
10:23 gcp linux TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
10:19 gcp linux TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
10:08 aws linux TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
9:19 gcp linux TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
9:14 aws linux TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
8:23 gcp linux TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
8:22 gcp linux TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
8:21 gcp linux TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
8:16 aws windows TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
8:12 aws linux TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
8:11 gcp windows TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
8:09 gcp windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
8:01 gcp windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
7:39 gcp linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=
7:33 gcp linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
7:33 aws windows TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
7:31 gcp linux TestAccept/bundle/resources/clusters/resize-terminated-fallback/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
7:19 gcp linux TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
7:16 aws linux TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
7:09 azure windows TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
7:08 azure windows TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
7:07 azure windows TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
7:04 aws linux TestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
7:04 gcp linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=
7:02 aws linux TestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
7:01 gcp windows TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
6:58 aws windows TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
6:58 gcp windows TestAccept/bundle/resources/clusters/deploy/local_ssd_count/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
6:55 gcp linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
6:46 azure linux TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
6:46 aws windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=1
6:40 azure linux TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
6:28 azure linux TestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
6:16 azure linux TestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=terraform/DMS=
6:05 azure linux TestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
6:01 aws windows TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
5:58 aws windows TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
5:45 azure windows TestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
5:42 gcp windows TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true
5:33 aws windows TestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=terraform/DMS=
5:30 aws linux TestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=terraform/DMS=
5:30 aws windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/DMS=true/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=
5:29 aws linux TestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct/DMS=
5:15 azure linux TestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=direct/DMS=

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants