Skip to content

Commit

Permalink
feat!: accept expand as an option to the env tag (#263)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: this replaces the `envExpand` tag with the `expand`
option to the `env` tag, to be more consistent with other boolean
options.

closes #262

Signed-off-by: Carlos A Becker <caarlos0@users.noreply.github.com>
  • Loading branch information
caarlos0 committed Jun 20, 2023
1 parent 390412e commit 7a25c17
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 14 deletions.
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,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 @@ -168,6 +164,20 @@ type config struct {
> value.
> This also means that custom parser funcs will not be invoked.
## 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
Expand Down Expand Up @@ -214,7 +224,7 @@ import (
type config struct {
Secret string `env:"SECRET,file"`
Password string `env:"PASSWORD,file" envDefault:"/tmp/password"`
Certificate string `env:"CERTIFICATE,file" envDefault:"${CERTIFICATE_FILE}" envExpand:"true"`
Certificate string `env:"CERTIFICATE,file,expand" envDefault:"${CERTIFICATE_FILE}"`
}

func main() {
Expand Down
4 changes: 3 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,15 @@ 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")
defaultValue, defExists := field.Tag.Lookup("envDefault")
val, exists, isDefault = getOr(key, defaultValue, defExists, opts.Environment)

Expand Down
13 changes: 7 additions & 6 deletions env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -933,11 +933,11 @@ 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"`
Port int `env:"PORT,expand" envDefault:"3000"`
SecretKey string `env:"SECRET_KEY,expand"`
ExpandKey string `env:"EXPAND_KEY"`
CompoundKey string `env:"HOST_PORT" envDefault:"${HOST}:${PORT}" envExpand:"True"`
Default string `env:"DEFAULT" envDefault:"def1" envExpand:"True"`
CompoundKey string `env:"HOST_PORT,expand" envDefault:"${HOST}:${PORT}"`
Default string `env:"DEFAULT,expand" envDefault:"def1"`
}

t.Setenv("HOST", "localhost")
Expand Down Expand Up @@ -1311,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 @@ -1319,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 Expand Up @@ -1495,7 +1496,7 @@ func TestFileBadFile(t *testing.T) {

func TestFileWithDefault(t *testing.T) {
type config struct {
SecretKey string `env:"SECRET_KEY,file" envDefault:"${FILE}" envExpand:"true"`
SecretKey string `env:"SECRET_KEY,file,expand" envDefault:"${FILE}"`
}

dir := t.TempDir()
Expand Down
2 changes: 1 addition & 1 deletion error.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (e NoParserError) Error() string {
}

// This error occurs when the given tag is not supported
// In-built supported tags: "", "file", "required", "unset", "notEmpty", "envDefault", "envExpand", "envSeparator"
// In-built supported tags: "", "file", "required", "unset", "notEmpty", "expand", "envDefault", "envSeparator"
// How to create a custom tag: https://github.com/caarlos0/env#changing-default-tag-name
type NoSupportedTagOptionError struct {
Tag string
Expand Down

0 comments on commit 7a25c17

Please sign in to comment.