Skip to content

Commit 33289b9

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 0332ae5 commit 33289b9

3 files changed

Lines changed: 70 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
@@ -1059,6 +1059,9 @@ def _validate_token_scopes(self, token: oauth.Token):
10591059
# --profile support added in CLI v0.207.1: https://github.com/databricks/cli/pull/855
10601060
_CLI_VERSION_FOR_PROFILE = CliVersion(0, 207, 1)
10611061

1062+
# --force-refresh support added in CLI v0.296.0: https://github.com/databricks/cli/pull/4767
1063+
_CLI_VERSION_FOR_FORCE_REFRESH = CliVersion(0, 296, 0)
1064+
10621065
# Captures "vX.Y.Z" plus any prerelease/build-metadata suffix so dev
10631066
# builds like "v0.0.0-dev+abcdef" can be distinguished from detection
10641067
# failure and compared against release versions.
@@ -1120,7 +1123,25 @@ def _resolve_cli_command(cli_path: str, cfg: "Config") -> List[str]:
11201123

11211124
@staticmethod
11221125
def _build_cli_command(cli_path: str, cfg: "Config", version: CliVersion) -> List[str]:
1123-
"""Build the `auth token` command.
1126+
"""Build the full CLI command, including capability-gated flags.
1127+
1128+
Delegates the profile/host decision to _build_core_cli_command and
1129+
appends --force-refresh when supported.
1130+
"""
1131+
cmd = DatabricksCliTokenSource._build_core_cli_command(cli_path, cfg, version)
1132+
if version >= DatabricksCliTokenSource._CLI_VERSION_FOR_FORCE_REFRESH:
1133+
cmd.append("--force-refresh")
1134+
else:
1135+
logger.warning(
1136+
f"Databricks CLI {version} does not support --force-refresh "
1137+
f"(requires >= {DatabricksCliTokenSource._CLI_VERSION_FOR_FORCE_REFRESH}). "
1138+
"The CLI's token cache may provide stale tokens."
1139+
)
1140+
return cmd
1141+
1142+
@staticmethod
1143+
def _build_core_cli_command(cli_path: str, cfg: "Config", version: CliVersion) -> List[str]:
1144+
"""Build the base `auth token` command without capability-gated flags.
11241145
11251146
Falls back to --host when --profile is either not configured or not
11261147
supported by the installed CLI. Raises ValueError describing which

tests/test_credentials_provider.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,42 @@ def _make_cfg(*, profile=None, host=None, account_id=None):
451451
_CV(0, 0, 0),
452452
[_CLI, "auth", "token", "--host", _HOST],
453453
),
454+
(
455+
"host with force-refresh",
456+
_make_cfg(host=_HOST),
457+
_CV(0, 296, 0),
458+
[_CLI, "auth", "token", "--host", _HOST, "--force-refresh"],
459+
),
460+
(
461+
"account host with force-refresh",
462+
_make_cfg(host=_ACCT_HOST, account_id="acct-123"),
463+
_CV(0, 296, 0),
464+
[_CLI, "auth", "token", "--host", _ACCT_HOST, "--account-id", "acct-123", "--force-refresh"],
465+
),
466+
(
467+
"profile with force-refresh",
468+
_make_cfg(profile="my-profile", host=_HOST),
469+
_CV(0, 296, 0),
470+
[_CLI, "auth", "token", "--profile", "my-profile", "--force-refresh"],
471+
),
472+
(
473+
"profile supports profile but not force-refresh",
474+
_make_cfg(profile="my-profile", host=_HOST),
475+
_CV(0, 207, 1),
476+
[_CLI, "auth", "token", "--profile", "my-profile"],
477+
),
478+
(
479+
"profile-only with force-refresh",
480+
_make_cfg(profile="my-profile"),
481+
_CV(0, 296, 0),
482+
[_CLI, "auth", "token", "--profile", "my-profile", "--force-refresh"],
483+
),
484+
(
485+
"zero version, host only, no force-refresh",
486+
_make_cfg(host=_HOST),
487+
_CV(0, 0, 0),
488+
[_CLI, "auth", "token", "--host", _HOST],
489+
),
454490
],
455491
)
456492
def test_build_cli_command(name, cfg, version, expected):
@@ -527,6 +563,17 @@ def test_resolve_cli_command_wraps_missing_config_error(mocker):
527563
credentials_provider.DatabricksCliTokenSource._resolve_cli_command(_CLI, cfg)
528564

529565

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

0 commit comments

Comments
 (0)