From 697aeae5ab3b3bd1001100f88f9996b95766bb55 Mon Sep 17 00:00:00 2001 From: Aaron Tainter Date: Mon, 29 Jul 2024 11:12:33 -0700 Subject: [PATCH 1/4] Add environment variable overrides for cli environment configs --- .gitignore | 1 + README.md | 43 +++++++++++++++++++++++++++++ internal/config/config.go | 57 ++++++++++++++++++++++++++++++--------- 3 files changed, 88 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 438f867..ad9a234 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ dist bin +.idea diff --git a/README.md b/README.md index b6d66a1..18ce38e 100644 --- a/README.md +++ b/README.md @@ -49,3 +49,46 @@ Once initialized, the CLI is ready to use: ```shell workos [cmd] [args] ``` + +### Environment Variables +WorkOS CLI support environment variables for initialization and environment management. + +| Environment Variable | Description | Supported Values | +|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|----------------------| +| WORKOS_ACTIVE_ENVIRONMENT | Sets the selected environment in your .workos.json file. Use `env` to override environment configs with other environment variable overrides. | | +| WORKOS_ENVIRONMENTS_ENV_NAME | Sets the name of the environment | | +| WORKOS_ENVIRONMENTS_ENV_ENDPOINT | Sets the base endpoint for the environment | | +| WORKOS_ENVIRONMENTS_ENV_API_KEY | Sets the API key for the environment | | +| WORKOS_ENVIRONMENTS_ENV_TYPE | Sets the env type for the environment | Production / Sandbox | + +#### Examples + +##### Set the active environment + +```shell +export WORKOS_ACTIVE_ENVIRONMENT=local +``` + +```json +// .workos.json +{ + "environments": { + "local": { + "endpoint": "http://localhost:8001", + "apiKey": "", + "type": "Sandbox", + "name": "local" + } + } +} +``` + +##### Headless Mode + +```shell +export WORKOS_ACTIVE_ENVIRONMENT=env +export WORKOS_ENVIRONMENTS_ENV_NAME=local +export WORKOS_ENVIRONMENTS_ENV_ENDPOINT=http://localhost:8001 +export WORKOS_ENVIRONMENTS_ENV_API_KEY= +export WORKOS_ENVIRONMENTS_ENV_TYPE=Sandbox +``` diff --git a/internal/config/config.go b/internal/config/config.go index 9d42df3..163777d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -3,17 +3,19 @@ package config import ( "encoding/json" "errors" - "io/fs" - "os" - "github.com/spf13/cobra" "github.com/spf13/viper" + "io/fs" + "os" + "strings" ) const ( - FilePrefix = ".workos" - FileExtension = "json" - FileName = FilePrefix + "." + FileExtension + EnvVarPrefix = "WORKOS" + EnvVarHeadlessMode = "env" + FilePrefix = ".workos" + FileExtension = "json" + FileName = FilePrefix + "." + FileExtension ) type Config struct { @@ -44,22 +46,50 @@ func (c Config) Write() error { return nil } -func LoadConfig() *Config { - // Look for .workos.json in HOME dir and create an empty version if it doesn't exist - homeDir, err := os.UserHomeDir() - cobra.CheckErr(err) - _, err = os.Stat(homeDir + "/" + FileName) +// Creates an empty config file if it doesn't exist +func createEmptyConfigFile(dir string) { + _, err := os.Stat(dir + "/" + FileName) if errors.Is(err, fs.ErrNotExist) { emptyJson := []byte("{}") - err = os.WriteFile(homeDir+"/"+FileName, emptyJson, 0644) + err = os.WriteFile(dir+"/"+FileName, emptyJson, 0644) cobra.CheckErr(err) } +} + +// Loads config values from environment variables if active environment is set to headless mode +// Supports overriding nested json keys with environment variables +// e.g. environments.env.endpoint -> WORKOS_ENVIRONMENTS_ENV_ENDPOINT +func loadEnvVarOverrides() { + viper.SetEnvPrefix(EnvVarPrefix) + // replace '.' in env var names with '_' to support overriding nested json keys + viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) + // read in environment variables that match + viper.AutomaticEnv() + + _ = viper.BindEnv("active_environment") + activeEnvironment := viper.Get("active_environment") + + // Binds environment variables to nested json keys which allows unmarshalling into struct + if activeEnvironment == EnvVarHeadlessMode { + _ = viper.BindEnv("environments.env.endpoint") + _ = viper.BindEnv("environments.env.type") + _ = viper.BindEnv("environments.env.name") + _ = viper.BindEnv("environments.env.api_key") + } +} + +func LoadConfig() *Config { + homeDir, err := os.UserHomeDir() + cobra.CheckErr(err) + createEmptyConfigFile(homeDir) // Load config from ~/.workos.json viper.AddConfigPath(homeDir) viper.SetConfigType(FileExtension) viper.SetConfigName(FilePrefix) - viper.AutomaticEnv() // read in environment variables that match + + loadEnvVarOverrides() + err = viper.ReadInConfig() cobra.CheckErr(err) @@ -67,5 +97,6 @@ func LoadConfig() *Config { var config Config err = viper.Unmarshal(&config) cobra.CheckErr(err) + return &config } From d1cfe046138661a3945cd4184dd65ff9da202ced Mon Sep 17 00:00:00 2001 From: Aaron Tainter Date: Mon, 29 Jul 2024 11:17:00 -0700 Subject: [PATCH 2/4] Fix formatting issue in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 18ce38e..1719e6f 100644 --- a/README.md +++ b/README.md @@ -69,8 +69,8 @@ WorkOS CLI support environment variables for initialization and environment mana export WORKOS_ACTIVE_ENVIRONMENT=local ``` +`.workos.json` ```json -// .workos.json { "environments": { "local": { From df00ad77e8b19854882503c70d2351a1e622dc0e Mon Sep 17 00:00:00 2001 From: Aaron Tainter Date: Mon, 29 Jul 2024 11:24:14 -0700 Subject: [PATCH 3/4] Remove extra line --- internal/config/config.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/config/config.go b/internal/config/config.go index 163777d..c7a3fc6 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -97,6 +97,5 @@ func LoadConfig() *Config { var config Config err = viper.Unmarshal(&config) cobra.CheckErr(err) - return &config } From 502ff129bbf6d13d67f68221829087a3fdd0d2ed Mon Sep 17 00:00:00 2001 From: Aaron Tainter Date: Mon, 29 Jul 2024 11:29:19 -0700 Subject: [PATCH 4/4] Change env var naming for clarity --- README.md | 24 ++++++++++++------------ internal/config/config.go | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 1719e6f..cbf29a1 100644 --- a/README.md +++ b/README.md @@ -53,13 +53,13 @@ workos [cmd] [args] ### Environment Variables WorkOS CLI support environment variables for initialization and environment management. -| Environment Variable | Description | Supported Values | -|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|----------------------| -| WORKOS_ACTIVE_ENVIRONMENT | Sets the selected environment in your .workos.json file. Use `env` to override environment configs with other environment variable overrides. | | -| WORKOS_ENVIRONMENTS_ENV_NAME | Sets the name of the environment | | -| WORKOS_ENVIRONMENTS_ENV_ENDPOINT | Sets the base endpoint for the environment | | -| WORKOS_ENVIRONMENTS_ENV_API_KEY | Sets the API key for the environment | | -| WORKOS_ENVIRONMENTS_ENV_TYPE | Sets the env type for the environment | Production / Sandbox | +| Environment Variable | Description | Supported Values | +|---------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|----------------------| +| WORKOS_ACTIVE_ENVIRONMENT | Sets the selected environment in your .workos.json file. Use `headless` to override environment configs with other environment variable overrides. | | +| WORKOS_ENVIRONMENTS_HEADLESS_NAME | Sets the name of the environment | | +| WORKOS_ENVIRONMENTS_HEADLESS_ENDPOINT | Sets the base endpoint for the environment | | +| WORKOS_ENVIRONMENTS_HEADLESS_API_KEY | Sets the API key for the environment | | +| WORKOS_ENVIRONMENTS_HEADLESS_TYPE | Sets the env type for the environment | Production / Sandbox | #### Examples @@ -86,9 +86,9 @@ export WORKOS_ACTIVE_ENVIRONMENT=local ##### Headless Mode ```shell -export WORKOS_ACTIVE_ENVIRONMENT=env -export WORKOS_ENVIRONMENTS_ENV_NAME=local -export WORKOS_ENVIRONMENTS_ENV_ENDPOINT=http://localhost:8001 -export WORKOS_ENVIRONMENTS_ENV_API_KEY= -export WORKOS_ENVIRONMENTS_ENV_TYPE=Sandbox +export WORKOS_ACTIVE_ENVIRONMENT=headless +export WORKOS_ENVIRONMENTS_HEADLESS_NAME=local +export WORKOS_ENVIRONMENTS_HEADLESS_ENDPOINT=http://localhost:8001 +export WORKOS_ENVIRONMENTS_HEADLESS_API_KEY= +export WORKOS_ENVIRONMENTS_HEADLESS_TYPE=Sandbox ``` diff --git a/internal/config/config.go b/internal/config/config.go index c7a3fc6..090a287 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -12,7 +12,7 @@ import ( const ( EnvVarPrefix = "WORKOS" - EnvVarHeadlessMode = "env" + EnvVarHeadlessMode = "headless" FilePrefix = ".workos" FileExtension = "json" FileName = FilePrefix + "." + FileExtension @@ -58,7 +58,7 @@ func createEmptyConfigFile(dir string) { // Loads config values from environment variables if active environment is set to headless mode // Supports overriding nested json keys with environment variables -// e.g. environments.env.endpoint -> WORKOS_ENVIRONMENTS_ENV_ENDPOINT +// e.g. environments.headless.endpoint -> WORKOS_ENVIRONMENTS_HEADLESS_ENDPOINT func loadEnvVarOverrides() { viper.SetEnvPrefix(EnvVarPrefix) // replace '.' in env var names with '_' to support overriding nested json keys @@ -71,10 +71,10 @@ func loadEnvVarOverrides() { // Binds environment variables to nested json keys which allows unmarshalling into struct if activeEnvironment == EnvVarHeadlessMode { - _ = viper.BindEnv("environments.env.endpoint") - _ = viper.BindEnv("environments.env.type") - _ = viper.BindEnv("environments.env.name") - _ = viper.BindEnv("environments.env.api_key") + _ = viper.BindEnv("environments.headless.endpoint") + _ = viper.BindEnv("environments.headless.type") + _ = viper.BindEnv("environments.headless.name") + _ = viper.BindEnv("environments.headless.api_key") } }