Skip to content

Commit

Permalink
feat: accept expand as an option to the env tag
Browse files Browse the repository at this point in the history
  • Loading branch information
caarlos0 committed Apr 10, 2023
1 parent fac0414 commit c9dcca5
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 13 deletions.
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type config struct {
IsProduction bool `env:"PRODUCTION"`
Hosts []string `env:"HOSTS" envSeparator:":"`
Duration time.Duration `env:"DURATION"`
TempFolder string `env:"TEMP_FOLDER" envDefault:"${HOME}/tmp" envExpand:"true"`
TempFolder string `env:"TEMP_FOLDER,expand" envDefault:"${HOME}/tmp"`
}

func main() {
Expand Down Expand Up @@ -102,10 +102,6 @@ case of absence of it in the environment.
By default, slice types will split the environment value on `,`; you can change
this behavior by setting the `envSeparator` tag.

If you set the `envExpand` tag, environment variables (either in `${var}` or
`$var` format) in the string will be replaced according with the actual value
of the variable.

## Custom Parser Funcs

If you have a type that is not supported out of the box by the lib, you are able
Expand Down Expand Up @@ -158,6 +154,21 @@ type config struct {
}
```

## Expand vars

If you set the `expand` option, environment variables (either in `${var}` or
`$var` format) in the string will be replaced according with the actual value
of the variable. For example:

```go
type config struct {
SecretKey string `env:"SECRET_KEY,expand"`
}
```

This also works with `envDefault`.


## Not Empty fields

While `required` demands the environment variable to be set, it doesn't check its value.
Expand Down
5 changes: 4 additions & 1 deletion env.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ func get(field reflect.StructField, opts Options) (val string, err error) {
var loadFile bool
var unset bool
var notEmpty bool
var expand bool

required := opts.RequiredIfNoDef
ownKey, tags := parseKeyForOption(field.Tag.Get(opts.TagName))
Expand All @@ -271,14 +272,16 @@ func get(field reflect.StructField, opts Options) (val string, err error) {
unset = true
case "notEmpty":
notEmpty = true
case "expand":
expand = true
default:
return "", newNoSupportedTagOptionError(tag)
}
}

prefix := opts.Prefix
key := prefix + ownKey
expand := strings.EqualFold(field.Tag.Get("envExpand"), "true")
expand = expand || strings.EqualFold(field.Tag.Get("envExpand"), "true")
defaultValue, defExists := field.Tag.Lookup("envDefault")
val, exists, isDefault = getOr(key, defaultValue, defExists, opts.Environment)

Expand Down
17 changes: 10 additions & 7 deletions env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -930,12 +930,13 @@ func TestErrorRequiredNotSetWithDefault(t *testing.T) {

func TestParseExpandOption(t *testing.T) {
type config struct {
Host string `env:"HOST" envDefault:"localhost"`
Port int `env:"PORT" envDefault:"3000" envExpand:"True"`
SecretKey string `env:"SECRET_KEY" envExpand:"True"`
ExpandKey string `env:"EXPAND_KEY"`
CompoundKey string `env:"HOST_PORT" envDefault:"${HOST}:${PORT}" envExpand:"True"`
Default string `env:"DEFAULT" envDefault:"def1" envExpand:"True"`
Host string `env:"HOST" envDefault:"localhost"`
Port int `env:"PORT" envDefault:"3000" envExpand:"True"`
SecretKey string `env:"SECRET_KEY" envExpand:"True"`
ExpandKey string `env:"EXPAND_KEY"`
CompoundKey string `env:"HOST_PORT" envDefault:"${HOST}:${PORT}" envExpand:"True"`
Default string `env:"DEFAULT" envDefault:"def1" envExpand:"True"`
AnotherCompoundKey string `env:"HOST_PORT,expand" envDefault:"${HOST}:${PORT}"`
}

t.Setenv("HOST", "localhost")
Expand All @@ -952,6 +953,7 @@ func TestParseExpandOption(t *testing.T) {
isEqual(t, "qwerty12345", cfg.SecretKey)
isEqual(t, "qwerty12345", cfg.ExpandKey)
isEqual(t, "localhost:3000", cfg.CompoundKey)
isEqual(t, "localhost:3000", cfg.AnotherCompoundKey)
isEqual(t, "def1", cfg.Default)
}

Expand Down Expand Up @@ -1309,6 +1311,7 @@ func ExampleParse() {
Home string `env:"HOME,required"`
Port int `env:"PORT" envDefault:"3000"`
IsProduction bool `env:"PRODUCTION"`
TempFolder string `env:"TEMP_FOLDER,expand" envDefault:"${HOME}/.tmp"`
Inner inner
}
os.Setenv("HOME", "/tmp/fakehome")
Expand All @@ -1317,7 +1320,7 @@ func ExampleParse() {
fmt.Println("failed:", err)
}
fmt.Printf("%+v", cfg)
// Output: {Home:/tmp/fakehome Port:3000 IsProduction:false Inner:{Foo:foobar}}
// Output: {Home:/tmp/fakehome Port:3000 IsProduction:false TempFolder:/tmp/fakehome/.tmp Inner:{Foo:foobar}}
}

func ExampleParse_onSet() {
Expand Down

0 comments on commit c9dcca5

Please sign in to comment.