user10267174
user10267174

Reputation: 51

Issues with overriding config using ENV variables in Viper

We are using Viper to read and parse our config file and all of that works without any issues.

However we are not able to override some of our config values using env variables. These are specific use cases where the config is bound to a struct or an array of structs.

Here is an example from our config.yaml:

app:
    verifiers:
      - name: "test1"
        url: "http://test1.url"
        cache: "5000ms"
      - name: "test2"
        url: "http://test2.url"
        cache: "10000ms"

Which is bound to the following structs (golang):

type App struct {
    AppConfig   Config      `yaml:"app" mapstructure:"app"`
}

type Config struct {
    Verifiers []VerifierConfig `json:"verifiers"         yaml:"verifiers"         mapstructure:"verifiers"`
}

type VerifierConfig struct {
    Name     string            `json:"name"                   yaml:"name"                   mapstructure:"name"`
    URL      string            `json:"url,omitempty"          yaml:"url,omitempty"          mapstructure:"url"`
    cache    jsontime.Duration `json:"cache"                  yaml:"cache"                  mapstructure:"cache"`
}

We are unable to override the value of verifiers using env variables.

Here are the Viper options we have used:

viper.AutomaticEnv()
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

Has anyone experienced a similar issue or can confirm that Viper does not support such a use case?

Any pointers would be greatly appreciated.

Thanks

Upvotes: 2

Views: 6318

Answers (1)

shubhendu
shubhendu

Reputation: 223

viper cannot read env variables inside config file. You have to replace them in .go file where value is being used. Here is an example on how I achieved:

Ask Viper to consider system environment variable with "ENV" prefix, that means viper expects "ENV_MONGO_USER" and "ENV_MONGO_PASSWORD" as system environment variables

viper.AutomaticEnv()
viper.SetEnvPrefix(viper.GetString("ENV"))
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

In yml file:

mongodb:
 url: "mongodb+srv://${username}:${password}@xxxxxxx.mongodb.net/"
 database: "test" 

In mongodb connection file: (before making db connection, replace ${username} and ${password} with respective environment variables but viper will read those variables without prefix )

const BasePath = "mongodb"
mongoDbUrl := viper.GetString(fmt.Sprintf("%s.%s", BasePath, "url"))
username := viper.GetString("MONGO_USER")
password := viper.GetString("MONGO_PASSWORD")
replacer := strings.NewReplacer("${username}", username, "${password}", password)
mongoDbUrl = replacer.Replace(mongoDbUrl)

Upvotes: 3

Related Questions