diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index 078c98e6bf1..086aff122c7 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -7,7 +7,8 @@ ### CLI * Added the `databricks quickstart` command, a short introduction to the CLI that prints a human-friendly guide interactively and an agent-oriented version when run non-interactively ([#5464](https://github.com/databricks/cli/pull/5464)). -* `databricks auth login` no longer prompts for workspace selection when logging in to an account console host (`https://accounts.*`). Pass `--workspace-id` explicitly to store a workspace ID on such a profile ([#5504](https://github.com/databricks/cli/pull/5504)). +* `databricks auth profiles --skip-validate` no longer makes any network calls; the host metadata fetch is skipped along with validation ([#5530](https://github.com/databricks/cli/pull/5530)). + ### Bundles * Set the default `data_security_mode` to `DATA_SECURITY_MODE_AUTO` in bundle templates ([#5452](https://github.com/databricks/cli/pull/5452)). diff --git a/acceptance/auth/host-metadata-cache/output.txt b/acceptance/auth/host-metadata-cache/output.txt index 0b99e9579c8..d059d2bbc4b 100644 --- a/acceptance/auth/host-metadata-cache/output.txt +++ b/acceptance/auth/host-metadata-cache/output.txt @@ -6,8 +6,8 @@ "name": "cached", "host": "[DATABRICKS_URL]", "cloud": "aws", - "auth_type": "", - "valid": false + "auth_type": "pat", + "valid": true } ] } @@ -19,8 +19,8 @@ "name": "cached", "host": "[DATABRICKS_URL]", "cloud": "aws", - "auth_type": "", - "valid": false + "auth_type": "pat", + "valid": true } ] } diff --git a/acceptance/auth/host-metadata-cache/script b/acceptance/auth/host-metadata-cache/script index f7a5f2fe0f8..dd64d1b98a6 100644 --- a/acceptance/auth/host-metadata-cache/script +++ b/acceptance/auth/host-metadata-cache/script @@ -2,7 +2,8 @@ sethome "./home" export DATABRICKS_CACHE_DIR="$TEST_TMP_DIR/cache" # Point a profile at the mock server so auth profiles triggers a host metadata -# fetch. Without a profile the command does nothing and the cache is never read. +# fetch. Validation must stay on: --skip-validate resolves offline and would +# never fetch or populate the cache. cat > "./home/.databrickscfg" </.well-known/databricks-config to enrich + // the config, so without this stub a skip-validate listing still makes + // one network call per profile (and warns when offline). Resolve from + // the config file alone; cloud detection falls back to the host pattern. + cfg.HostMetadataResolver = func(context.Context, string) (*config.HostMetadata, error) { + return nil, nil + } + } _ = cfg.EnsureResolved() if cfg.IsAws() { c.Cloud = "aws" diff --git a/cmd/auth/profiles_test.go b/cmd/auth/profiles_test.go index 59803e210cf..2ebbeed0e60 100644 --- a/cmd/auth/profiles_test.go +++ b/cmd/auth/profiles_test.go @@ -7,6 +7,7 @@ import ( "os" "path/filepath" "runtime" + "sync/atomic" "testing" "github.com/databricks/cli/libs/databrickscfg" @@ -48,6 +49,35 @@ func TestProfiles(t *testing.T) { assert.Equal(t, "pat", profile.AuthType) } +// TestProfileLoadSkipValidateMakesNoRequests guards the --skip-validate +// contract: EnsureResolved would otherwise fetch /.well-known/databricks-config +// for every profile, so the handler counts every request it receives. +func TestProfileLoadSkipValidateMakesNoRequests(t *testing.T) { + var requests atomic.Int32 + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requests.Add(1) + w.WriteHeader(http.StatusNotFound) + })) + t.Cleanup(server.Close) + + dir := t.TempDir() + configFile := filepath.Join(dir, ".databrickscfg") + t.Setenv("HOME", dir) + if runtime.GOOS == "windows" { + t.Setenv("USERPROFILE", dir) + } + + content := "[offline-profile]\nhost = " + server.URL + "\ntoken = test-token\n" + require.NoError(t, os.WriteFile(configFile, []byte(content), 0o600)) + + p := &profileMetadata{Name: "offline-profile", Host: server.URL} + p.Load(t.Context(), configFile, true) + + assert.Zero(t, requests.Load(), "expected no network calls with skipValidate") + assert.Equal(t, server.URL, p.Host) + assert.False(t, p.Valid) +} + func TestProfilesDefaultMarker(t *testing.T) { ctx := t.Context() dir := t.TempDir()