-
Notifications
You must be signed in to change notification settings - Fork 59
Add custom scopes support in OAuth authentication methods #1374
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fbf6a6a
31a8405
e2a79db
92f329d
e26fd32
d3118c4
59ff78c
8aa33e5
b6a5fb6
86e7559
04d32a2
229483b
39b0010
73b90af
dab2f87
c6eea37
cfa26f9
8ad6dd7
8a4c1b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| package config | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/google/go-cmp/cmp" | ||
| ) | ||
|
|
||
| // TestConfigFile_Configure_ListParsing tests that comma-separated list values | ||
| // in configuration files are correctly parsed into slices. | ||
| func TestConfigFile_Configure_ListParsing(t *testing.T) { | ||
| testCases := []struct { | ||
| name string | ||
| profile string | ||
| want []string | ||
| }{ | ||
| { | ||
| name: "single item", | ||
| profile: "single-item", | ||
| want: []string{"clusters"}, | ||
| }, | ||
| { | ||
| name: "multiple items", | ||
| profile: "multiple-items", | ||
| want: []string{"alpha", "beta", "gamma"}, | ||
| }, | ||
| { | ||
| name: "whitespace around items is trimmed", | ||
| profile: "whitespace-around-items", | ||
| want: []string{"alpha", "beta", "gamma"}, | ||
| }, | ||
| { | ||
| name: "empty items are filtered out", | ||
| profile: "empty-items-filtered", | ||
| want: []string{"alpha", "beta"}, | ||
| }, | ||
| { | ||
| name: "whitespace-only items are filtered out", | ||
| profile: "whitespace-only-items-filtered", | ||
| want: []string{"alpha", "beta"}, | ||
| }, | ||
| } | ||
|
|
||
| for _, tc := range testCases { | ||
| t.Run(tc.name, func(t *testing.T) { | ||
| withMockEnv(t, map[string]string{}) | ||
|
|
||
| cfg := &Config{ | ||
| Profile: tc.profile, | ||
| ConfigFile: "testdata/list-parsing/.databrickscfg", | ||
| } | ||
| err := ConfigFile.Configure(cfg) | ||
| if err != nil { | ||
| t.Fatalf("Configure failed: %v", err) | ||
| } | ||
| if diff := cmp.Diff(tc.want, cfg.Scopes); diff != "" { | ||
| t.Errorf("list mismatch (-want +got):\n%s", diff) | ||
| } | ||
| }) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,22 +3,93 @@ package config | |
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| "github.com/google/go-cmp/cmp" | ||
Tejas-Kochar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ) | ||
|
|
||
| // withMockEnv mocks environment variables for testing config file loading | ||
| // without relying on the actual system environment or filesystem. | ||
| // getUserHomeDir falls back to the real implementation when HOME is not in | ||
| // the env map, allowing tests to optionally override HOME without breaking | ||
| // tests that don't need to control the home directory path. | ||
| func withMockEnv(t *testing.T, env map[string]string) { | ||
| original := getenv | ||
| originalUserHomeDir := getUserHomeDir | ||
| t.Cleanup(func() { | ||
| getenv = original | ||
| getUserHomeDir = originalUserHomeDir | ||
| }) | ||
| getenv = func(key string) string { | ||
| return env[key] | ||
| } | ||
| getUserHomeDir = func() (string, error) { | ||
| if home, ok := env["HOME"]; ok { | ||
| return home, nil | ||
| } | ||
| return originalUserHomeDir() | ||
| } | ||
| } | ||
|
|
||
| func TestConfigFileLoad(t *testing.T) { | ||
| f, err := LoadFile("testdata/.databrickscfg") | ||
| require.NoError(t, err) | ||
| assert.NotNil(t, f) | ||
| if err != nil { | ||
| t.Fatalf("LoadFile failed: %v", err) | ||
| } | ||
| if f == nil { | ||
| t.Fatal("expected file to be non-nil") | ||
| } | ||
|
|
||
| for _, name := range []string{ | ||
| "password-with-double-quotes", | ||
| "password-with-single-quotes", | ||
| "password-without-quotes", | ||
| } { | ||
| section := f.Section(name) | ||
| require.NotNil(t, section) | ||
| assert.Equal(t, "%Y#X$Z", section.Key("password").String()) | ||
| if section == nil { | ||
| t.Fatalf("expected section %q to be non-nil", name) | ||
| } | ||
| if got, want := section.Key("password").String(), "%Y#X$Z"; got != want { | ||
| t.Errorf("password mismatch for %q: got %q, want %q", name, got, want) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| func TestConfigFile_Scopes(t *testing.T) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we remove this test? It looks redundant with the two tests we have added. If you decide to keep it, please update: withMockEnv(t, map[string]string{})
t.Setenv("HOME", "testdata/scopes")to withMockEnv(t, map[string]string{"HOME": "testdata/scopes"})
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer keeping it as it acts as an integration test and ensures backwards compatibility (the first case checks that "all-apis" is used if no scopes are provided in the config file). Made the change. |
||
| tests := []struct { | ||
| name string | ||
| profile string | ||
| want []string | ||
| }{ | ||
| { | ||
| name: "empty defaults to all-apis", | ||
| profile: "scope-empty", | ||
| want: []string{"all-apis"}, | ||
| }, | ||
| { | ||
| name: "single scope", | ||
| profile: "scope-single", | ||
| want: []string{"clusters"}, | ||
| }, | ||
| { | ||
| name: "multiple scopes sorted", | ||
| profile: "scope-multiple", | ||
| want: []string{"clusters", "files:read", "iam:read", "jobs", "mlflow", "model-serving", "pipelines"}, | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| withMockEnv(t, map[string]string{ | ||
| "HOME": "testdata/scopes", | ||
| }) | ||
|
|
||
| cfg := &Config{Profile: tt.profile} | ||
| err := cfg.EnsureResolved() | ||
| if err != nil { | ||
| t.Fatalf("EnsureResolved failed: %v", err) | ||
| } | ||
| if diff := cmp.Diff(tt.want, cfg.GetScopes()); diff != "" { | ||
| t.Errorf("GetScopes mismatch (-want +got):\n%s", diff) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.