forked from golang/oauth2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
make SDKConfig work with newer versions of gcloud
The existing implementation of SDKConfig assumes that the Cloud SDK writes a config file named `credentials`, which contains JSON-encoded OAuth2 credentials for the user. Since version 161.0.0 of the Cloud SDK, that has not been true, as the Cloud SDK has switched to storing credentials in a SQLite database instead of a JSON-encoded file. This change switches from trying to directly read the underlying credential store (which it is now clear can change without notice), to instead invoking the `gcloud` command and asking it for its credentials. This is done using the subcommand ```sh gcloud config config-helper ``` That subcommand is meant to provide auth data to external tools, so it seems to be a more appropriate choice than reading the underlying storage directly. This fixes golang#300
- Loading branch information
Showing
2 changed files
with
90 additions
and
210 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,103 +5,58 @@ | |
package google | ||
|
||
import ( | ||
"reflect" | ||
"strings" | ||
"fmt" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func TestSDKConfig(t *testing.T) { | ||
sdkConfigPath = func() (string, error) { | ||
return "testdata/gcloud", nil | ||
} | ||
|
||
tests := []struct { | ||
account string | ||
accessToken string | ||
err bool | ||
}{ | ||
{"", "bar_access_token", false}, | ||
{"[email protected]", "foo_access_token", false}, | ||
{"[email protected]", "bar_access_token", false}, | ||
{"[email protected]", "", true}, | ||
var helperCallCount int | ||
mockTokenFormat := "Token #%d" | ||
mockHelper := func() (*configHelperResp, error) { | ||
token := fmt.Sprintf(mockTokenFormat, helperCallCount) | ||
helperCallCount += 1 | ||
return &configHelperResp{ | ||
Credential: struct { | ||
AccessToken string `json:"access_token"` | ||
TokenExpiry string `json:"token_expiry"` | ||
}{ | ||
AccessToken: token, | ||
TokenExpiry: time.Now().Format(time.RFC3339), | ||
}, | ||
}, nil | ||
} | ||
for _, tt := range tests { | ||
c, err := NewSDKConfig(tt.account) | ||
if got, want := err != nil, tt.err; got != want { | ||
if !tt.err { | ||
t.Errorf("got %v, want nil", err) | ||
} else { | ||
t.Errorf("got nil, want error") | ||
} | ||
continue | ||
} | ||
mockConfig := &SDKConfig{mockHelper} | ||
for i := 0; i < 10; i++ { | ||
tok, err := mockConfig.Token() | ||
if err != nil { | ||
continue | ||
} | ||
tok := c.initialToken | ||
if tok == nil { | ||
t.Errorf("got nil, want %q", tt.accessToken) | ||
continue | ||
} | ||
if tok.AccessToken != tt.accessToken { | ||
t.Errorf("got %q, want %q", tok.AccessToken, tt.accessToken) | ||
t.Errorf("Unexpected error reading a mock config helper response: %v", err) | ||
} else if got, want := tok.AccessToken, fmt.Sprintf(mockTokenFormat, i); got != want { | ||
t.Errorf("Got access token of %q; wanted %q", got, want) | ||
} | ||
} | ||
} | ||
|
||
func TestParseINI(t *testing.T) { | ||
tests := []struct { | ||
ini string | ||
want map[string]map[string]string | ||
}{ | ||
{ | ||
`root = toor | ||
[foo] | ||
bar = hop | ||
ini = nin | ||
`, | ||
map[string]map[string]string{ | ||
"": {"root": "toor"}, | ||
"foo": {"bar": "hop", "ini": "nin"}, | ||
}, | ||
}, | ||
{ | ||
"\t extra \t = whitespace \t\r\n \t [everywhere] \t \r\n here \t = \t there \t \r\n", | ||
map[string]map[string]string{ | ||
"": {"extra": "whitespace"}, | ||
"everywhere": {"here": "there"}, | ||
}, | ||
}, | ||
{ | ||
`[empty] | ||
[section] | ||
empty= | ||
`, | ||
map[string]map[string]string{ | ||
"": {}, | ||
"empty": {}, | ||
"section": {"empty": ""}, | ||
}, | ||
}, | ||
{ | ||
`ignore | ||
[invalid | ||
=stuff | ||
;comment=true | ||
`, | ||
map[string]map[string]string{ | ||
"": {}, | ||
failingHelper := func() (*configHelperResp, error) { | ||
return nil, fmt.Errorf("mock config helper failure") | ||
} | ||
failingConfig := &SDKConfig{failingHelper} | ||
if tok, err := failingConfig.Token(); err == nil { | ||
t.Errorf("unexpected token response for failing helper: got %v", tok) | ||
} | ||
|
||
badTimestampHelper := func() (*configHelperResp, error) { | ||
return &configHelperResp{ | ||
Credential: struct { | ||
AccessToken string `json:"access_token"` | ||
TokenExpiry string `json:"token_expiry"` | ||
}{ | ||
AccessToken: "Fake token", | ||
TokenExpiry: "The time at which it expires", | ||
}, | ||
}, | ||
}, nil | ||
} | ||
for _, tt := range tests { | ||
result, err := parseINI(strings.NewReader(tt.ini)) | ||
if err != nil { | ||
t.Errorf("parseINI(%q) error %v, want: no error", tt.ini, err) | ||
continue | ||
} | ||
if !reflect.DeepEqual(result, tt.want) { | ||
t.Errorf("parseINI(%q) = %#v, want: %#v", tt.ini, result, tt.want) | ||
} | ||
badTimestampConfig := &SDKConfig{badTimestampHelper} | ||
if tok, err := badTimestampConfig.Token(); err == nil { | ||
t.Errorf("unexpected token response for a helper that returns bad expiry timestamps: got %v", tok) | ||
} | ||
} |