Skip to content

Commit 20d0239

Browse files
Fix CLI token source --profile fallback with version detection (databricks#751)
## 🥞 Stacked PR Use this [link](https://github.com/databricks/databricks-sdk-java/pull/751/files) to review incremental changes. - [**stack/cli-force-refresh**](databricks#751) [[Files changed](https://github.com/databricks/databricks-sdk-java/pull/751/files)] - [stack/cli-attempt-chain](databricks#752) [[Files changed](https://github.com/databricks/databricks-sdk-java/pull/752/files/c4e12c18..5ee21871)] --------- ## Summary Replace the broken error-based `--profile` fallback in `CliTokenSource` with version-based CLI detection at init time. Mirrors [databricks/databricks-sdk-go#1605](databricks/databricks-sdk-go#1605) and [databricks/databricks-sdk-py#1377](databricks/databricks-sdk-py#1377). ## Why `--profile` on `databricks auth token` is a global flag, so old CLIs (< v0.207.1) **silently accept it** and then fail with `"cannot fetch credentials"` instead of `"unknown flag: --profile"`. The existing retry check was matching on the latter and never fired — the `--host` fallback it gated was effectively dead code. Switching to `databricks version` + a minimum-version constant makes the fallback reliable and sets up future capability-gated flags (e.g. `--force-refresh` in [databricks#752](databricks#752)) without additional subprocess calls. ## What changed ### Interface changes None. `CliTokenSource` is not part of the public API surface. ### Behavioral changes - `cfg.profile` + CLI < v0.207.1 now correctly falls back to `--host` (previously broken). - `databricks version` failures log a `WARNING` and fall back to the most conservative command. Successful detections are cached per CLI path; failures are not cached and will be retried on the next call. - A default dev build (`v0.0.0-dev`) logs an `INFO` explaining why feature gates are conservative. `AzureCliCredentialsProvider` is untouched. ### Internal changes - New `DatabricksCliVersion` class with a `(major, minor, patch)` triple, an `UNKNOWN` sentinel, an `atLeast()` comparator, and an `isDefaultDevBuild()` helper. - `CliTokenSource` simplified to a single `cmd`; the `fallbackCmd` parameter and its retry logic are removed. - `DatabricksCliCredentialsProvider` gains `getCliVersion`, `probeCliVersion`, `parseCliVersion`, `resolveCliCommand`, and `buildCliCommand` helpers. ## How is this tested? Unit tests in `DatabricksCliVersionTest` cover version comparison (across patch/minor/major), the `UNKNOWN` sentinel, dev-build detection, and `toString` formatting. Unit tests in `DatabricksCliCredentialsProviderTest` cover JSON parsing of `databricks version --output json` (standard, dev build, missing fields, malformed JSON, empty string) and command assembly for every profile/host/version combination (host-only, account host, profile + new CLI, profile + old CLI, unknown version, dev build). `CliTokenSourceTest` retains its parsing and timezone tests; the obsolete fallback tests are dropped.
1 parent 0a68591 commit 20d0239

7 files changed

Lines changed: 913 additions & 225 deletions

File tree

NEXT_CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
### Breaking Changes
88

99
### Bug Fixes
10+
* Fixed Databricks CLI `--profile` fallback by detecting the CLI version at init time. The previous error-based detection was broken because `--profile` is a global Cobra flag silently accepted by old CLIs.
1011

1112
### Security Vulnerabilities
1213

1314
### Documentation
1415

1516
### Internal Changes
17+
* Detect Databricks CLI version at init time via `databricks version --output json`, enabling version-gated flag support. Successful detections are cached per CLI path; subprocess failures fall back to the most conservative command and are retried on the next call.
1618

1719
### API Changes
1820
* Add `createExample()`, `deleteExample()`, `getExample()`, `getPermissionLevels()`, `getPermissions()`, `listExamples()`, `setPermissions()`, `updateExample()` and `updatePermissions()` methods for `workspaceClient.supervisorAgents()` service.

databricks-sdk-java/src/main/java/com/databricks/sdk/core/CliTokenSource.java

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ public class CliTokenSource implements TokenSource {
3030
private String accessTokenField;
3131
private String expiryField;
3232
private Environment env;
33-
// fallbackCmd is tried when the primary command fails with "unknown flag: --profile",
34-
// indicating the CLI is too old to support --profile. Can be removed once support
35-
// for CLI versions predating --profile is dropped.
36-
// See: https://github.com/databricks/databricks-sdk-go/pull/1497
37-
private List<String> fallbackCmd;
3833

3934
/**
4035
* Internal exception that carries the clean stderr message but exposes full output for checks.
@@ -58,24 +53,11 @@ public CliTokenSource(
5853
String accessTokenField,
5954
String expiryField,
6055
Environment env) {
61-
this(cmd, tokenTypeField, accessTokenField, expiryField, env, null);
62-
}
63-
64-
public CliTokenSource(
65-
List<String> cmd,
66-
String tokenTypeField,
67-
String accessTokenField,
68-
String expiryField,
69-
Environment env,
70-
List<String> fallbackCmd) {
71-
super();
7256
this.cmd = OSUtils.get(env).getCliExecutableCommand(cmd);
7357
this.tokenTypeField = tokenTypeField;
7458
this.accessTokenField = accessTokenField;
7559
this.expiryField = expiryField;
7660
this.env = env;
77-
this.fallbackCmd =
78-
fallbackCmd != null ? OSUtils.get(env).getCliExecutableCommand(fallbackCmd) : null;
7961
}
8062

8163
/**
@@ -158,22 +140,6 @@ public Token getToken() {
158140
try {
159141
return execCliCommand(this.cmd);
160142
} catch (IOException e) {
161-
String textToCheck =
162-
e instanceof CliCommandException
163-
? ((CliCommandException) e).getFullOutput()
164-
: e.getMessage();
165-
if (fallbackCmd != null
166-
&& textToCheck != null
167-
&& textToCheck.contains("unknown flag: --profile")) {
168-
LOG.warn(
169-
"Databricks CLI does not support --profile flag. Falling back to --host. "
170-
+ "Please upgrade your CLI to the latest version.");
171-
try {
172-
return execCliCommand(this.fallbackCmd);
173-
} catch (IOException fallbackException) {
174-
throw new DatabricksException(fallbackException.getMessage(), fallbackException);
175-
}
176-
}
177143
throw new DatabricksException(e.getMessage(), e);
178144
}
179145
}

0 commit comments

Comments
 (0)