Skip to content

Add databricks auth switch command for setting the default profile#4651

Open
simonfaltum wants to merge 7 commits intomainfrom
simonfaltum/auth-switch
Open

Add databricks auth switch command for setting the default profile#4651
simonfaltum wants to merge 7 commits intomainfrom
simonfaltum/auth-switch

Conversation

@simonfaltum
Copy link
Member

@simonfaltum simonfaltum commented Mar 4, 2026

Why

There is no way to set which profile is the active default without renaming it to [DEFAULT]. Users with multiple profiles need a simple way to switch between them.

Changes

Before: no mechanism to designate a default profile. Users had to rename sections in ~/.databrickscfg or always pass --profile.

Now: databricks auth switch lets users select a named profile as the default. The choice is stored in a [__databricks-settings__] section with a default_profile key. auth profiles shows a (Default) marker, and auth describe shows the resolved default name.

Why [__databricks-settings__] instead of a top-level key?

INI files place keys that appear before any section header into the [DEFAULT] section. The CLI already uses [DEFAULT] as a regular profile section (with host, token, etc.), so adding default_profile there would mix settings with profile credentials, and the profiles command would try to interpret [DEFAULT] as a profile containing that key. A dedicated [__databricks-settings__] section avoids this collision and is silently ignored by older SDKs (no host key means it is skipped in profile iteration).

Implementation

  • libs/databrickscfg/ops.go: GetDefaultProfile/GetDefaultProfileFrom with fallback resolution (explicit setting, single-profile auto-default, legacy DEFAULT section). SetDefaultProfile to write the setting. Shared backupAndSaveConfigFile and resolveConfigFilePath helpers to deduplicate existing code.
  • cmd/auth/switch.go: new command with --profile flag (non-interactive) and interactive profile picker showing the current default.
  • cmd/auth/profiles.go: (Default) marker in output and default field in JSON.
  • cmd/auth/describe.go: shows resolved default profile name, e.g. profile: default (my-workspace).
  • cmd/auth/login.go + token.go: auto-set default when creating the very first profile.

Resolution wiring (making the CLI actually use default_profile when no --profile is given) is out of scope. That will be a follow-up change touching cmd/root/auth.go and the bundle config path.

Test plan

  • Unit tests for GetDefaultProfile, GetDefaultProfileFrom, SetDefaultProfile (table-driven, covering: explicit setting, single-profile fallback, DEFAULT fallback, no file, round-trip with SaveToProfile)
  • Unit tests for auth switch command (with --profile, profile not found, non-interactive error, settings section written correctly)
  • Unit tests for hasNoProfiles (fresh machine / ErrNoConfiguration, empty file, existing profiles)
  • Unit test for (Default) marker in auth profiles
  • GetDefaultProfile does not create the config file as a side effect (asserted in test)
  • make checks and make lintfull pass
  • Manual: databricks auth switch --profile <name>, verify ~/.databrickscfg has [__databricks-settings__] section
  • Manual: databricks auth profiles shows (Default) marker
  • Manual: databricks auth switch interactive picker shows current default

@simonfaltum simonfaltum marked this pull request as ready for review March 4, 2026 09:31
@eng-dev-ecosystem-bot
Copy link
Collaborator

eng-dev-ecosystem-bot commented Mar 4, 2026

Commit: 58bec97

Run: 22684175504

Env 🪲​BUG ❌​FAIL 🟨​KNOWN 🔄​flaky 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
🟨​ aws linux 7 1 7 268 778 7:36
🟨​ aws windows 7 1 7 270 776 7:05
🔄​ aws-ucws linux 2 7 7 364 693 8:04
🔄​ aws-ucws windows 2 7 7 366 691 5:48
🪲​ azure linux 1 8 1 1 9 262 776 145:10
🪲​ azure windows 1 8 1 1 9 264 774 145:29
🪲​ azure-ucws linux 1 8 1 1 9 361 689 146:07
🪲​ azure-ucws windows 1 8 1 2 9 362 687 145:29
🪲​ gcp linux 1 8 1 1 9 258 779 145:10
🪲​ gcp windows 1 8 1 1 9 260 777 145:00
25 interesting tests: 8 FAIL, 7 KNOWN, 7 SKIP, 2 flaky, 1 BUG
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
🟨​ TestAccept 🟨​K 🟨​K 💚​R 💚​R 🟨​K 🟨​K 🟨​K 🟨​K 🟨​K 🟨​K
🪲​ TestAccept/bundle/deployment/bind/alert 🙈​s 🙈​s 🙈​s 🙈​s 🪲​B 🪲​B 🪲​B 🪲​B 🪲​B 🪲​B
❌​ TestAccept/bundle/deployment/bind/alert/DATABRICKS_BUNDLE_ENGINE=direct ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/deployment/bind/alert/DATABRICKS_BUNDLE_ENGINE=terraform ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/generate/alert ✅​p ✅​p ✅​p ✅​p ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/generate/alert/DATABRICKS_BUNDLE_ENGINE=direct ✅​p ✅​p ✅​p ✅​p ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/generate/alert/DATABRICKS_BUNDLE_ENGINE=terraform ✅​p ✅​p ✅​p ✅​p ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/alerts/with_file ✅​p ✅​p ✅​p ✅​p ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/alerts/with_file/DATABRICKS_BUNDLE_ENGINE=direct ✅​p ✅​p ✅​p ✅​p ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
❌​ TestAccept/bundle/resources/alerts/with_file/DATABRICKS_BUNDLE_ENGINE=terraform ✅​p ✅​p ✅​p ✅​p ❌​F ❌​F ❌​F ❌​F ❌​F ❌​F
🙈​ TestAccept/bundle/resources/permissions 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions 🟨​K 🟨​K 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions 🟨​K 🟨​K 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R
🙈​ TestAccept/bundle/resources/postgres_branches/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/update_protected 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/without_branch_id 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_endpoints/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/synced_database_tables/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🔄​ TestAccept/ssh/connect-serverless-gpu 🙈​s 🙈​s 🔄​f 🔄​f 🙈​s 🙈​s ✅​p 🔄​f 🙈​s 🙈​s
🔄​ TestAccept/ssh/connection 💚​R 💚​R 🔄​f 🔄​f 💚​R 💚​R 💚​R 🔄​f 💚​R 💚​R
Top 20 slowest tests (at least 2 minutes):
duration env testname
3:48 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:46 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:42 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:40 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:21 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:15 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:12 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:06 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:57 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:52 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:52 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:47 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:46 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:44 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:41 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:15 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:13 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:09 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:05 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:04 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct

simonfaltum and others added 7 commits March 4, 2026 19:48
Introduce a [databricks-cli-settings] section in ~/.databrickscfg with a
default_profile key. The new `auth switch` command lets users select a
named profile as the default, and `auth profiles` shows a (Default) marker
next to it.

The default profile resolution uses fallback logic: explicit setting first,
then single-profile auto-default, then legacy DEFAULT section.

The login flow auto-sets the default when creating the very first profile
so new users get a working default out of the box.

Resolution wiring (making the CLI use default_profile when no --profile
is given) is out of scope for this change.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
hasNoProfiles now treats ErrNoConfiguration (no config file) as "no
profiles" instead of returning false. This ensures the first profile
created on a fresh machine is auto-set as the default.

GetDefaultProfile now uses a read-only file loader (loadConfigFile)
that returns ("", nil) when the file doesn't exist, instead of
loadOrCreateConfigFile which would create the file as a side effect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
auth switch now declares cobra.NoArgs so positional arguments produce
a clear error instead of being silently ignored.

The interactive profile picker label now shows the current default
profile name (e.g. "Current default: e2-dogfood. Select a new default")
so users know what they're changing from.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When no --profile flag is set, auth describe now shows the resolved
default profile name in parentheses, e.g. "profile: default (e2-dogfood)"
instead of just "profile: default".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rtion

Extract resolveConfigFilePath helper to share tilde expansion logic
between loadConfigFile and loadOrCreateConfigFile.

In switch.go interactive path, use the already-loaded config file from
the profiler to resolve the current default instead of re-reading from disk.

Remove duplicate assertion in TestProfilesDefaultMarker.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The auth login acceptance tests now expect the [__databricks-settings__]
section in out.databrickscfg and (Default) marker in auth profiles output,
since first-profile login auto-sets the default.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@simonfaltum simonfaltum force-pushed the simonfaltum/auth-switch branch from 52cc221 to 58bec97 Compare March 4, 2026 18:49
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.

2 participants