Skip to content

Commit

Permalink
feat: notEmpty tag (#174)
Browse files Browse the repository at this point in the history
Signed-off-by: Carlos A Becker <caarlos0@gmail.com>
  • Loading branch information
caarlos0 committed May 15, 2021
1 parent 4eb989e commit b2f4697
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 17 deletions.
36 changes: 19 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Build Status](https://img.shields.io/github/workflow/status/caarlos0/env/build?style=for-the-badge)](https://github.com/caarlos0/env/actions?workflow=build)
[![Coverage Status](https://img.shields.io/codecov/c/gh/caarlos0/env.svg?logo=codecov&style=for-the-badge)](https://codecov.io/gh/caarlos0/env)
[![](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=for-the-badge)](http://godoc.org/github.com/caarlos0/env/v6)
[![](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=for-the-badge)](https://pkg.go.dev/github.com/caarlos0/env/v6)

Simple lib to parse envs to structs in Go.

Expand All @@ -17,11 +17,7 @@ import (
"fmt"
"time"

// if using go modules
"github.com/caarlos0/env/v6"

// if using dep/others
"github.com/caarlos0/env"
)

type config struct {
Expand Down Expand Up @@ -142,18 +138,25 @@ And then you can parse `Config` with `env.Parse`.

## Required fields

The `env` tag option `required` (e.g., `env:"tagKey,required"`) can be added
to ensure that some environment variable is set. In the example above,
an error is returned if the `config` struct is changed to:
The `env` tag option `required` (e.g., `env:"tagKey,required"`) can be added to ensure that some environment variable is set.
In the example above, an error is returned if the `config` struct is changed to:

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

## Not Empty fields

While `required` demands the environment variable to be check, it doesn't check its value.
If you want to make sure the environment is set and not emtpy, you need to use the `notEmpty` tag option instead (`env:"SOME_ENV,notEmpty"`).

Example:

```go
type config struct {
Home string `env:"HOME"`
Port int `env:"PORT" envDefault:"3000"`
IsProduction bool `env:"PRODUCTION"`
Hosts []string `env:"HOSTS" envSeparator:":"`
SecretKey string `env:"SECRET_KEY,required"`
SecretKey string `env:"SECRET_KEY,notEmpty"`
}
```

Expand Down Expand Up @@ -183,7 +186,7 @@ package main
import (
"fmt"
"time"
"github.com/caarlos0/env"
"github.com/caarlos0/env/v6"
)

type config struct {
Expand Down Expand Up @@ -213,7 +216,6 @@ $ SECRET=/tmp/secret \
{Secret:qwerty Password:dvorak Certificate:coleman}
```


## Options

### Environment
Expand All @@ -231,7 +233,7 @@ import (
"fmt"
"log"

"github.com/caarlos0/env"
"github.com/caarlos0/env/v6"
)

type Config struct {
Expand Down Expand Up @@ -267,7 +269,7 @@ import (
"fmt"
"log"

"github.com/caarlos0/env"
"github.com/caarlos0/env/v6"
)

type Config struct {
Expand Down
7 changes: 7 additions & 0 deletions env.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ func get(field reflect.StructField, opts []Options) (val string, err error) {
var exists bool
var loadFile bool
var unset bool
var notEmpty bool
expand := strings.EqualFold(field.Tag.Get("envExpand"), "true")

key, tags := parseKeyForOption(field.Tag.Get(getTagName(opts)))
Expand All @@ -233,6 +234,8 @@ func get(field reflect.StructField, opts []Options) (val string, err error) {
required = true
case "unset":
unset = true
case "notEmpty":
notEmpty = true
default:
return "", fmt.Errorf("env: tag option %q not supported", tag)
}
Expand All @@ -253,6 +256,10 @@ func get(field reflect.StructField, opts []Options) (val string, err error) {
return "", fmt.Errorf(`env: required environment variable %q is not set`, key)
}

if notEmpty && val == "" {
return "", fmt.Errorf("env: environment variable %q should not be empty", key)
}

if loadFile && val != "" {
filename := val
val, err = getFromFile(filename)
Expand Down
38 changes: 38 additions & 0 deletions env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,44 @@ func TestErrorRequiredNotSet(t *testing.T) {
isErrorWithMessage(t, Parse(&config{}), `env: required environment variable "IS_REQUIRED" is not set`)
}

func TestNoErrorNotEmptySet(t *testing.T) {
is := is.New(t)
os.Setenv("IS_REQUIRED", "1")
defer os.Clearenv()
type config struct {
IsRequired string `env:"IS_REQUIRED,notEmpty"`
}
is.NoErr(Parse(&config{}))
}

func TestNoErrorRequiredAndNotEmptySet(t *testing.T) {
is := is.New(t)
os.Setenv("IS_REQUIRED", "1")
defer os.Clearenv()
type config struct {
IsRequired string `env:"IS_REQUIRED,required,notEmpty"`
}
is.NoErr(Parse(&config{}))
}

func TestErrorNotEmptySet(t *testing.T) {
os.Setenv("IS_REQUIRED", "")
defer os.Clearenv()
type config struct {
IsRequired string `env:"IS_REQUIRED,notEmpty"`
}
isErrorWithMessage(t, Parse(&config{}), `env: environment variable "IS_REQUIRED" should not be empty`)
}

func TestErrorRequiredAndNotEmptySet(t *testing.T) {
os.Setenv("IS_REQUIRED", "")
defer os.Clearenv()
type config struct {
IsRequired string `env:"IS_REQUIRED,notEmpty,required"`
}
isErrorWithMessage(t, Parse(&config{}), `env: environment variable "IS_REQUIRED" should not be empty`)
}

func TestErrorRequiredNotSetWithDefault(t *testing.T) {
is := is.New(t)

Expand Down

0 comments on commit b2f4697

Please sign in to comment.