Make an explicitly selected profile take precedence over auth environment variables#5702
Merged
Conversation
Collaborator
Integration test reportCommit: 29d2b24
23 interesting tests: 13 SKIP, 8 RECOVERED, 2 flaky
Top 5 slowest tests (at least 2 minutes):
|
fe17837 to
ae05b0e
Compare
72b1acb to
b2c4d95
Compare
b2c4d95 to
aeb17ab
Compare
aeb17ab to
7ce0ce7
Compare
7ce0ce7 to
e16df4f
Compare
simonfaltum
reviewed
Jul 2, 2026
ca6bf4e to
8fd0e5f
Compare
simonfaltum
approved these changes
Jul 2, 2026
simonfaltum
left a comment
Member
There was a problem hiding this comment.
I think there is one more thing for us to fix but otherwise looks good. Approving to unblock
6c639fd to
05b591a
Compare
When --profile is set explicitly, host and auth credentials from the profile now win over DATABRICKS_HOST/DATABRICKS_TOKEN and other auth env vars. Previously the SDK's env-first loader order silently shadowed the selected profile (#5096).
Extend the --profile precedence fix (#5096): - ResolveNonAuthFromEnv now also skips auth_type and discovery_url, which are tagged auth:"-" in the SDK and so are invisible to HasAuthAttribute, letting DATABRICKS_AUTH_TYPE/DATABRICKS_DISCOVERY_URL shadow the profile. It also records the env source so `auth describe` and debug output match the SDK loader. - Workspace.Client uses ResolveNonAuthFromEnv when a profile is set (from --profile or workspace.profile) so env auth vars no longer shadow the profile for bundle commands. - Use the reserved .test TLD for new test fixture hosts so the SDK's well-known host metadata resolver fast-fails instead of stalling on a live network lookup.
A host-only profile combined with DATABRICKS_TOKEN previously failed because the profile loader chain stopped at the config file. Append config.ConfigAttributes after the profile so the environment can fill auth fields the profile does not provide, while the profile still wins for any field it sets (#5096).
- Centralize the explicit-profile loader chain in databrickscfg.ProfileAuthLoaders and extract applyProfileAuthPrecedence so all call sites share one rule. - Skip host, routing IDs (workspace_id/account_id) and SDK-internal auth-steering env attrs; guard the classification with a test that fails on SDK drift. - Apply profile precedence to `databricks api --profile`. - Let env gap-fill auth fields a host-only profile leaves empty. - Add bundle host+profile coverage and acceptance tests; clarify rationale comments.
The no---profile branch in `databricks api` pinned [__settings__].default_profile unconditionally, so a conflicting default profile could be merged with env auth (DATABRICKS_HOST/DATABRICKS_TOKEN), failing with "more than one authorization method configured" (the #5616 class already fixed for MustWorkspaceClient). Share the guard: export resolveDefaultProfile as ResolveDefaultProfile and call it from cmd/api, so the default profile is skipped when DATABRICKS_HOST is set. Adds an acceptance case with env PAT + conflicting default_profile.
The final loader in ProfileAuthLoaders was the SDK's config.ConfigAttributes, which re-reads every still-empty attribute from the environment after the profile is loaded. That let host/routing/auth-steering env vars (auth_type, discovery_url, audience, cloud, workspace_id, account_id) shadow an explicitly selected profile, e.g. DATABRICKS_AUTH_TYPE=basic forcing basic auth over a profile's PAT (#5096). Replace it with resolveAuthGapFromEnv, a filtered env loader that skips nonAuthEnvSkipAttrs but still gap-fills real auth attrs, so a complete conflicting env auth method surfaces as an error rather than being silently dropped. Add an end-to-end ProfileAuthLoaders test covering the steering-env repro.
05b591a to
8ef7b6a
Compare
A selected profile skips host/routing/auth-steering env vars so they can't shadow it (#5096), but the host was skipped in both the env-first and the gap-fill passes. A profile that leaves the host empty (or can't be resolved) then never fell back to DATABRICKS_HOST and failed with "cannot configure default credentials". Treat the host like an auth attribute: skip it only in the env-first pass so the profile still owns it, then gap-fill it from env after the profile, mirroring the existing token gap-fill. Routing/auth-steering attrs stay skipped in both passes.
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.
Why
With an explicit profile (
--profileor a bundle'sworkspace.profile), auth env vars (DATABRICKS_HOST,DATABRICKS_TOKEN, ...) silently shadowed it: the SDK reads env before the config file and never overwrites an already-set field.Separately,
databricks apiwithout--profilepinned[__settings__].default_profileunconditionally, so a conflicting default profile could still be merged with env auth and fail with "more than one authorization method configured" (the same#5616class already fixed forMustWorkspaceClient).Changes
Fixes #5096
When a profile is selected explicitly, use a shared loader chain (
databrickscfg.ProfileAuthLoaders) so the profile wins for host/auth/routing, while env still gap-fills only the auth fields the profile leaves empty (e.g. host-only profile +DATABRICKS_TOKEN). Non-auth env vars (e.g.cluster_id) stay env-first via a smallResolveNonAuthFromEnvloader. Wired intoMustWorkspaceClient,MustAccountClient,Workspace.Client, anddatabricks api.For
databricks apiwithout--profile, share the#5616default-profile guard instead of duplicating it:resolveDefaultProfileis exported asResolveDefaultProfileand called fromcmd/api, so adefault_profileis skipped whenDATABRICKS_HOSTis set (single source of truth withMustWorkspaceClient, no drift).Explicit design choices:
DATABRICKS_CONFIG_PROFILEkeeps the SDK's env-first precedence.NormalizeDatabricksConfigFromEnv, so a SPOG-styleDATABRICKS_HOST(?o=/?a=) no longer overrides the profile; the profile's host is authoritative.Tests
--profile/workspace.profilewins over auth env;DATABRICKS_CONFIG_PROFILEstays env-first; host-only profile fills its token from env; conflicting-method error.databricks apiwithout--profileuses env auth and ignores a conflictingdefault_profilewhenDATABRICKS_HOSTis set (fails pre-fix with "more than one authorization method configured").auth:"-") env-backed attribute that hasn't been classified as auth-steering vs. env-first.