From 571a817c710db1fb395a46187f593d77d7260e60 Mon Sep 17 00:00:00 2001 From: jeremytchang <78522362+jeremytchang@users.noreply.github.com> Date: Thu, 10 Feb 2022 10:33:52 -0800 Subject: [PATCH] feat: Implemented Go SDK env var handling (#975) Also added unit tests for it that will leave existing environment variables undisturbed. (Will store env vars before test and restore env vars after test) --- go/rtl/constants.go | 7 ++- go/rtl/settings.go | 44 +++++++++++++++-- go/rtl/settings_test.go | 104 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 5 deletions(-) diff --git a/go/rtl/constants.go b/go/rtl/constants.go index 377b5575f..d6ec3dc75 100644 --- a/go/rtl/constants.go +++ b/go/rtl/constants.go @@ -1,5 +1,10 @@ package rtl const ( - DefaultApiVersion = "4.0" + baseUrlEnvKey = "LOOKERSDK_BASE_URL" + apiVersionEnvKey = "LOOKERSDK_API_VERSION" + verifySslEnvKey = "LOOKERSDK_VERIFY_SSL" + timeoutEnvKey = "LOOKERSDK_TIMEOUT" + clientIdEnvKey = "LOOKERSDK_CLIENT_ID" + clientSecretEnvKey = "LOOKERSDK_CLIENT_SECRET" ) diff --git a/go/rtl/settings.go b/go/rtl/settings.go index fc8279241..d476616e2 100644 --- a/go/rtl/settings.go +++ b/go/rtl/settings.go @@ -3,6 +3,9 @@ package rtl import ( "fmt" "gopkg.in/ini.v1" + "os" + "strconv" + "strings" ) var defaultSectionName string = "Looker" @@ -18,15 +21,19 @@ type ApiSettings struct { ApiVersion string `ini:"api_version"` } +var defaultSettings ApiSettings = ApiSettings{ + VerifySsl: true, + ApiVersion: "4.0", + Timeout: 120, +} + func NewSettingsFromFile(file string, section *string) (ApiSettings, error) { if section == nil { section = &defaultSectionName } - s := ApiSettings{ - VerifySsl: true, - ApiVersion: DefaultApiVersion, - } + // Default values + s := defaultSettings cfg, err := ini.Load(file) if err != nil { @@ -37,3 +44,32 @@ func NewSettingsFromFile(file string, section *string) (ApiSettings, error) { return s, err } + +func NewSettingsFromEnv() (ApiSettings, error) { + settings := defaultSettings + + if v, present := os.LookupEnv(baseUrlEnvKey); present { + settings.BaseUrl = v + } + if v, present := os.LookupEnv(apiVersionEnvKey); present { + settings.ApiVersion = v + } + if v, present := os.LookupEnv(verifySslEnvKey); present { + s := strings.ToLower(v) + settings.VerifySsl = s == "true" || s == "t" || s == "1" || s == "y" || s == "yes" + } + if v, present := os.LookupEnv(timeoutEnvKey); present { + timeout, err := strconv.ParseInt(v,10,32) + if err == nil { + settings.Timeout = int32(timeout) + } + } + if v, present := os.LookupEnv(clientIdEnvKey); present { + settings.ClientId = v + } + if v, present := os.LookupEnv(clientSecretEnvKey); present { + settings.ClientSecret = v + } + + return settings, nil +} diff --git a/go/rtl/settings_test.go b/go/rtl/settings_test.go index 5bd8b040a..51d83d53d 100644 --- a/go/rtl/settings_test.go +++ b/go/rtl/settings_test.go @@ -1,6 +1,7 @@ package rtl import ( + "os" "reflect" "testing" ) @@ -48,3 +49,106 @@ func TestNewSettingsFromFile(t *testing.T) { }) } } + +type pair struct { + k string + v string +} + +func TestNewSettingsFromEnv(t *testing.T) { + getEnv := func() []pair { + var pairs []pair + + if v,present := os.LookupEnv(baseUrlEnvKey); present { + pairs = append(pairs, pair{ k: baseUrlEnvKey, v: v }) + } + if v,present := os.LookupEnv(apiVersionEnvKey); present { + pairs = append(pairs, pair{ k: apiVersionEnvKey, v: v }) + } + if v,present := os.LookupEnv(verifySslEnvKey); present { + pairs = append(pairs, pair{ k: verifySslEnvKey, v: v }) + } + if v,present := os.LookupEnv(timeoutEnvKey); present { + pairs = append(pairs, pair{ k: timeoutEnvKey, v: v }) + } + if v,present := os.LookupEnv(clientIdEnvKey); present { + pairs = append(pairs, pair{ k: clientIdEnvKey, v: v }) + } + if v,present := os.LookupEnv(clientSecretEnvKey); present { + pairs = append(pairs, pair{ k: clientSecretEnvKey, v: v }) + } + + return pairs + } + + clearEnv := func() { + os.Unsetenv(baseUrlEnvKey) + os.Unsetenv(apiVersionEnvKey) + os.Unsetenv(verifySslEnvKey) + os.Unsetenv(timeoutEnvKey) + os.Unsetenv(clientIdEnvKey) + os.Unsetenv(clientSecretEnvKey) + } + + setEnv := func(pairs []pair ) { + clearEnv() + for _, pair := range pairs { + os.Setenv(pair.k, pair.v) + } + } + + tests := []struct { + name string + env []pair + want ApiSettings + }{ + { + name: "NewSettingsFromEnv() returns settings when all environment variables set", + env: []pair { + {baseUrlEnvKey, "url"}, + {apiVersionEnvKey, "5.0"}, + {verifySslEnvKey, "false"}, + {timeoutEnvKey, "360"}, + {clientIdEnvKey, "id"}, + {clientSecretEnvKey, "secret"}, + }, + want: ApiSettings{ + BaseUrl: "url", + ApiVersion: "5.0", + VerifySsl: false, + Timeout: 360, + ClientId: "id", + ClientSecret: "secret", + }, + }, + { + name: "NewSettingsFromEnv() sets defaults correctly if env vars not set for them", + env: []pair { + {baseUrlEnvKey, "url"}, + {clientIdEnvKey, "id"}, + {clientSecretEnvKey, "secret"}, + }, + want: ApiSettings{ + BaseUrl: "url", + ApiVersion: "4.0", + VerifySsl: true, + Timeout: 120, + ClientId: "id", + ClientSecret: "secret", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + origEnv := getEnv() + defer setEnv(origEnv) + + setEnv(tt.env) + + got, _ := NewSettingsFromEnv() + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewSettingsFromEnv() got = %v, want %v", got, tt.want) + } + }) + } +}