@@ -33,6 +33,18 @@ account_id = def456
3333experimental_is_unified_host = true
3434`
3535
36+ var logoutTestTokensCackeConfig = map [string ]* oauth2.Token {
37+ "my-workspace" : {AccessToken : "shared-workspace-token" },
38+ "shared-workspace" : {AccessToken : "shared-workspace-token" },
39+ "my-unique-workspace" : {AccessToken : "my-unique-workspace-token" },
40+ "my-account" : {AccessToken : "my-account-token" },
41+ "my-unified" : {AccessToken : "my-unified-token" },
42+ "https://my-workspace.cloud.databricks.com" : {AccessToken : "shared-workspace-host-token" },
43+ "https://my-unique-workspace.cloud.databricks.com" : {AccessToken : "unique-workspace-host-token" },
44+ "https://accounts.cloud.databricks.com/oidc/accounts/abc123" : {AccessToken : "account-host-token" },
45+ "https://unified.cloud.databricks.com/oidc/accounts/def456" : {AccessToken : "unified-host-token" },
46+ }
47+
3648func writeTempConfig (t * testing.T , content string ) string {
3749 t .Helper ()
3850 path := filepath .Join (t .TempDir (), ".databrickscfg" )
@@ -42,30 +54,55 @@ func writeTempConfig(t *testing.T, content string) string {
4254
4355func TestLogout (t * testing.T ) {
4456 cases := []struct {
45- name string
46- profileName string
47- force bool
48- wantErr string
57+ name string
58+ profileName string
59+ hostBasedKey string
60+ isSharedKey bool
61+ force bool
62+ wantErr string
4963 }{
5064 {
51- name : "existing profile with force" ,
52- profileName : "my-workspace" ,
53- force : true ,
65+ name : "existing workspace profile with shared host" ,
66+ profileName : "my-workspace" ,
67+ hostBasedKey : "https://my-workspace.cloud.databricks.com" ,
68+ isSharedKey : true ,
69+ force : true ,
70+ },
71+ {
72+ name : "existing workspace profile with unique host" ,
73+ profileName : "my-unique-workspace" ,
74+ hostBasedKey : "https://my-unique-workspace.cloud.databricks.com" ,
75+ isSharedKey : false ,
76+ force : true ,
5477 },
5578 {
56- name : "existing profile without force in non-interactive mode" ,
79+ name : "existing account profile" ,
80+ profileName : "my-account" ,
81+ hostBasedKey : "https://accounts.cloud.databricks.com/oidc/accounts/abc123" ,
82+ isSharedKey : false ,
83+ force : true ,
84+ },
85+ {
86+ name : "existing unified profile" ,
87+ profileName : "my-unified" ,
88+ hostBasedKey : "https://unified.cloud.databricks.com/oidc/accounts/def456" ,
89+ isSharedKey : false ,
90+ force : true ,
91+ },
92+ {
93+ name : "existing workspace profile without force in non-interactive mode" ,
5794 profileName : "my-workspace" ,
5895 force : false ,
5996 wantErr : "please specify --force to skip confirmation in non-interactive mode" ,
6097 },
6198 {
62- name : "non-existing profile with force" ,
99+ name : "non-existing workspace profile with force" ,
63100 profileName : "nonexistent" ,
64101 force : true ,
65102 wantErr : `profile "nonexistent" not found` ,
66103 },
67104 {
68- name : "non-existing profile without force" ,
105+ name : "non-existing workspace profile without force" ,
69106 profileName : "nonexistent" ,
70107 force : false ,
71108 wantErr : `profile "nonexistent" not found` ,
@@ -79,10 +116,7 @@ func TestLogout(t *testing.T) {
79116 t .Setenv ("DATABRICKS_CONFIG_FILE" , configPath )
80117
81118 tokenCache := & inMemoryTokenCache {
82- Tokens : map [string ]* oauth2.Token {
83- "my-workspace" : {AccessToken : "token1" },
84- "https://my-workspace.cloud.databricks.com" : {AccessToken : "token1" },
85- },
119+ Tokens : logoutTestTokensCackeConfig ,
86120 }
87121
88122 err := runLogout (ctx , logoutArgs {
@@ -92,6 +126,7 @@ func TestLogout(t *testing.T) {
92126 tokenCache : tokenCache ,
93127 configFilePath : configPath ,
94128 })
129+
95130 if tc .wantErr != "" {
96131 assert .ErrorContains (t , err , tc .wantErr )
97132 return
@@ -101,84 +136,14 @@ func TestLogout(t *testing.T) {
101136 // Verify profile was removed from config.
102137 profiles , err := profile .DefaultProfiler .LoadProfiles (ctx , profile .WithName (tc .profileName ))
103138 require .NoError (t , err )
104- assert .Empty (t , profiles )
139+ assert .Empty (t , profiles , "expected profile %q to be removed" , tc . profileName )
105140
106141 // Verify tokens were cleaned up.
107- assert .Nil (t , tokenCache .Tokens [tc .profileName ])
108- })
109- }
110- }
111-
112- func TestLogoutTokenCacheCleanup (t * testing.T ) {
113- cases := []struct {
114- name string
115- profileName string
116- tokens map [string ]* oauth2.Token
117- wantRemoved []string
118- wantPreserved []string
119- }{
120- {
121- name : "workspace shared host preserves host-keyed token" ,
122- profileName : "my-workspace" ,
123- tokens : map [string ]* oauth2.Token {
124- "my-workspace" : {AccessToken : "token1" },
125- "shared-workspace" : {AccessToken : "token2" },
126- "https://my-workspace.cloud.databricks.com" : {AccessToken : "host-token" },
127- },
128- wantRemoved : []string {"my-workspace" },
129- wantPreserved : []string {"https://my-workspace.cloud.databricks.com" , "shared-workspace" },
130- },
131- {
132- name : "workspace unique host clears host-keyed token" ,
133- profileName : "my-unique-workspace" ,
134- tokens : map [string ]* oauth2.Token {
135- "my-unique-workspace" : {AccessToken : "token1" },
136- "https://my-unique-workspace.cloud.databricks.com" : {AccessToken : "host-token" },
137- },
138- wantRemoved : []string {"my-unique-workspace" , "https://my-unique-workspace.cloud.databricks.com" },
139- },
140- {
141- name : "account profile clears OIDC-keyed token" ,
142- profileName : "my-account" ,
143- tokens : map [string ]* oauth2.Token {
144- "my-account" : {AccessToken : "token1" },
145- "https://accounts.cloud.databricks.com/oidc/accounts/abc123" : {AccessToken : "account-token" },
146- },
147- wantRemoved : []string {"my-account" , "https://accounts.cloud.databricks.com/oidc/accounts/abc123" },
148- },
149- {
150- name : "unified profile clears OIDC-keyed token" ,
151- profileName : "my-unified" ,
152- tokens : map [string ]* oauth2.Token {
153- "my-unified" : {AccessToken : "token1" },
154- "https://unified.cloud.databricks.com/oidc/accounts/def456" : {AccessToken : "unified-token" },
155- },
156- wantRemoved : []string {"my-unified" , "https://unified.cloud.databricks.com/oidc/accounts/def456" },
157- },
158- }
159-
160- for _ , tc := range cases {
161- t .Run (tc .name , func (t * testing.T ) {
162- ctx := cmdio .MockDiscard (context .Background ())
163- configPath := writeTempConfig (t , logoutTestConfig )
164- t .Setenv ("DATABRICKS_CONFIG_FILE" , configPath )
165-
166- tokenCache := & inMemoryTokenCache {Tokens : tc .tokens }
167-
168- err := runLogout (ctx , logoutArgs {
169- profileName : tc .profileName ,
170- force : true ,
171- profiler : profile .DefaultProfiler ,
172- tokenCache : tokenCache ,
173- configFilePath : configPath ,
174- })
175- require .NoError (t , err )
176-
177- for _ , key := range tc .wantRemoved {
178- assert .Nil (t , tokenCache .Tokens [key ], "expected token %q to be removed" , key )
179- }
180- for _ , key := range tc .wantPreserved {
181- assert .NotNil (t , tokenCache .Tokens [key ], "expected token %q to be preserved" , key )
142+ assert .Nil (t , tokenCache .Tokens [tc .profileName ], "expected token %q to be removed" , tc .profileName )
143+ if tc .isSharedKey {
144+ assert .NotNil (t , tokenCache .Tokens [tc .hostBasedKey ], "expected token %q to be preserved" , tc .hostBasedKey )
145+ } else {
146+ assert .Nil (t , tokenCache .Tokens [tc .hostBasedKey ], "expected token %q to be removed" , tc .hostBasedKey )
182147 }
183148 })
184149 }
0 commit comments