envconfig icon indicating copy to clipboard operation
envconfig copied to clipboard

Feature Request: multiple names for fields

Open ErinCall opened this issue 5 years ago • 4 comments

I'd like to be able to specify multiple/alternate names for a config field. I'm envisioning a rough equivalent to the EnvVars setting in urfave/cli:

type Config struct {
  SomeSetting string `envconfig:"setting_name,deprecated_name"`
}

Right now, we're working around it with multiple structs:

type LegacyConfig struct {
  SomeSetting string `envconfig:"deprecated_name"`
}

type Config struct {
  SomeSetting string `envconfig:"setting_name"`
}

func Main() {
  var lCfg LegacyConfig
  envconfig.Process(&lCfg)
  cfg := Config{
    SomeSetting: lCfg.SomeSetting,
  }
  envconfig.Process(&cfg)
}

ErinCall avatar Jan 13 '20 17:01 ErinCall

How should ordering work? I think the big challenge will be dealing with the ambiguous nature of an env var being unset vs set to empty.

kelseyhightower avatar Jun 24 '20 13:06 kelseyhightower

Couldn't we use the order provided ? In this case:

  1. setting_name
  2. deprecated_name

But I would argue that the order should not matter here actually. Users should only set one of these environment variables and envconfig pick the first one that is not nil.

afarbos avatar Feb 12 '21 17:02 afarbos

Not exactly what you asked for but you can work around this by creating two entries and a function to return any non-empty one:

type Config struct {
   SomethingNew string `envconfig:setting_name`
   SomethingOld string `envconfig:deprecated_name`
}

func (cfg *Config) Something() string {
    if cfg.SomethingNew != "" {
        return cfg.SomethingNew
    }
    return cfg.SomethingOld
}

tomercagan avatar May 13 '21 11:05 tomercagan

Maybe the ordering is not that important. You won't likely see both being set explicitly, since you either specify the deprecated key name because you haven't migrated yet or migrated to the new key and won't be setting the old anymore. In that case it could be a either or setting that guards this but you should not specify both?

EDIT: maybe something like this:

type Config struct {
  SomeSetting string `envconfig:"setting_name" alternative:"deprecated_name"`
}

or

type Config struct {
  SomeSetting string `envconfig:"setting_name" deprecated:"deprecated_name"`
}

In the second example it could even be possible to add a way to handle the usage of deprecated keys (e.g. logging?)

jan-xyz avatar Jul 26 '21 09:07 jan-xyz