Skip to content

Commit a78d53c

Browse files
Pass --force-refresh to CLI auth token command
Pass --force-refresh to the Databricks CLI auth token command when the CLI supports it (>= v0.296.0), bypassing the CLI's internal token cache. The SDK manages its own token caching. When the SDK considers its token stale and shells out to `databricks auth token`, the CLI may return a cached token that is about to expire from the SDK's perspective. The --force-refresh flag guarantees a freshly minted token. With the version detection infrastructure from the parent commit, adding --force-refresh is a one-constant, one-if change. See: databricks/cli#4767
1 parent 13e5ee8 commit a78d53c

3 files changed

Lines changed: 76 additions & 1 deletion

File tree

NEXT_CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Release v0.106.0
44

55
### New Features and Improvements
6+
* Pass `--force-refresh` to Databricks CLI `auth token` command so the SDK always receives a freshly minted token instead of a potentially stale one from the CLI's internal cache.
67

78
### Security
89

databricks/sdk/credentials_provider.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,9 @@ def _validate_token_scopes(self, token: oauth.Token):
10161016
# --profile support added in CLI v0.207.1: https://github.com/databricks/cli/pull/855
10171017
_CLI_VERSION_FOR_PROFILE = CliVersion(0, 207, 1)
10181018

1019+
# --force-refresh support added in CLI v0.296.0: https://github.com/databricks/cli/pull/4767
1020+
_CLI_VERSION_FOR_FORCE_REFRESH = CliVersion(0, 296, 0)
1021+
10191022
@staticmethod
10201023
def _parse_cli_version(output: str) -> CliVersion:
10211024
"""Parse the JSON output of `databricks version --output json`.
@@ -1083,7 +1086,25 @@ def _resolve_cli_command(cli_path: str, cfg: "Config") -> List[str]:
10831086

10841087
@staticmethod
10851088
def _build_cli_command(cli_path: str, cfg: "Config", version: CliVersion) -> List[str]:
1086-
"""Build the `auth token` command.
1089+
"""Build the full CLI command, including capability-gated flags.
1090+
1091+
Delegates the profile/host decision to _build_core_cli_command and
1092+
appends --force-refresh when supported.
1093+
"""
1094+
cmd = DatabricksCliTokenSource._build_core_cli_command(cli_path, cfg, version)
1095+
if version >= DatabricksCliTokenSource._CLI_VERSION_FOR_FORCE_REFRESH:
1096+
cmd.append("--force-refresh")
1097+
else:
1098+
logger.warning(
1099+
f"Databricks CLI {version} does not support --force-refresh "
1100+
f"(requires >= {DatabricksCliTokenSource._CLI_VERSION_FOR_FORCE_REFRESH}). "
1101+
"The CLI's token cache may provide stale tokens."
1102+
)
1103+
return cmd
1104+
1105+
@staticmethod
1106+
def _build_core_cli_command(cli_path: str, cfg: "Config", version: CliVersion) -> List[str]:
1107+
"""Build the base `auth token` command without capability-gated flags.
10871108
10881109
Falls back to --host when --profile is either not configured or not
10891110
supported by the installed CLI. Raises ValueError describing which

tests/test_credentials_provider.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,48 @@ def _make_cfg(*, profile=None, host=None, account_id=None):
435435
_CV(0, 0, 0),
436436
[_CLI, "auth", "token", "--host", _HOST],
437437
),
438+
(
439+
"host with force-refresh",
440+
_make_cfg(host=_HOST),
441+
_CV(0, 296, 0),
442+
[_CLI, "auth", "token", "--host", _HOST, "--force-refresh"],
443+
),
444+
(
445+
"account host with force-refresh",
446+
_make_cfg(host=_ACCT_HOST, account_id="acct-123"),
447+
_CV(0, 296, 0),
448+
[_CLI, "auth", "token", "--host", _ACCT_HOST, "--account-id", "acct-123", "--force-refresh"],
449+
),
450+
(
451+
"profile with force-refresh",
452+
_make_cfg(profile="my-profile", host=_HOST),
453+
_CV(0, 296, 0),
454+
[_CLI, "auth", "token", "--profile", "my-profile", "--force-refresh"],
455+
),
456+
(
457+
"profile supports profile but not force-refresh",
458+
_make_cfg(profile="my-profile", host=_HOST),
459+
_CV(0, 207, 1),
460+
[_CLI, "auth", "token", "--profile", "my-profile"],
461+
),
462+
(
463+
"profile-only with force-refresh",
464+
_make_cfg(profile="my-profile"),
465+
_CV(0, 296, 0),
466+
[_CLI, "auth", "token", "--profile", "my-profile", "--force-refresh"],
467+
),
468+
(
469+
"unknown version, host only, no force-refresh",
470+
_make_cfg(host=_HOST),
471+
_CV(),
472+
[_CLI, "auth", "token", "--host", _HOST],
473+
),
474+
(
475+
"dev-build version, host only, no force-refresh",
476+
_make_cfg(host=_HOST),
477+
_CV(0, 0, 0),
478+
[_CLI, "auth", "token", "--host", _HOST],
479+
),
438480
],
439481
)
440482
def test_build_cli_command(name, cfg, version, expected):
@@ -517,6 +559,17 @@ def test_resolve_cli_command_wraps_missing_config_error(mocker):
517559
credentials_provider.DatabricksCliTokenSource._resolve_cli_command(_CLI, cfg)
518560

519561

562+
def test_build_cli_command_force_refresh_unsupported_logs_warning(caplog):
563+
import logging
564+
565+
cfg = _make_cfg(host=_HOST)
566+
with caplog.at_level(logging.WARNING, logger="databricks.sdk.credentials_provider"):
567+
credentials_provider.DatabricksCliTokenSource._build_cli_command(_CLI, cfg, _CV(0, 295, 0))
568+
assert any(
569+
"does not support --force-refresh" in rec.message and rec.levelname == "WARNING" for rec in caplog.records
570+
)
571+
572+
520573
# Tests for cloud-agnostic hosts and removed cloud checks
521574
class TestCloudAgnosticHosts:
522575
"""Tests that credential providers work with cloud-agnostic hosts after removing is_azure/is_gcp checks."""

0 commit comments

Comments
 (0)