Skip to content

feat: multiple config filepath support. #149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This is a simple configuration reading tool. It just does the following:
- [Installation](#installation)
- [Usage](#usage)
- [Read Configuration](#read-configuration)
- [Read Configuration From List Of Paths](#read-configuration-from-list-of-paths)
- [Read Environment Variables Only](#read-environment-variables-only)
- [Update Environment Variables](#update-environment-variables)
- [Description](#description)
Expand Down Expand Up @@ -89,6 +90,40 @@ This will do the following:
1. reads environment variables and overwrites values from the file with the values which was found in the environment (`env` tag);
1. if no value was found on the first two steps, the field will be filled with the default value (`env-default` tag) if it is set.

### Read Configuration From List Of Paths

If you have a usecase of having different config path based on environment or whatsoever, all the paths can be configured and last valid path will be used to read the configuration.

```go
import "github.com/ilyakaznacheev/cleanenv"

type ConfigDatabase struct {
Port string `yaml:"port" env:"PORT" env-default:"5432"`
Host string `yaml:"host" env:"HOST" env-default:"localhost"`
Name string `yaml:"name" env:"NAME" env-default:"postgres"`
User string `yaml:"user" env:"USER" env-default:"user"`
Password string `yaml:"password" env:"PASSWORD"`
}

var cfg ConfigDatabase

cleanenv.AddConfigPath("config.yml")
cleanenv.AddConfigPath("/dev/config.yml")
cleanenv.AddConfigPath("/prod/config.yml")

err := cleanenv.Read(&cfg)
if err != nil {
...
}
```

This will do the following:

1. reads last valid path among added paths.
2. parse configuration file according to YAML format (`yaml` tag in this case);
3. reads environment variables and overwrites values from the file with the values which was found in the environment (`env` tag);
4. if no value was found on the first two steps, the field will be filled with the default value (`env-default` tag) if it is set.

### Read Environment Variables Only

Sometimes you don't want to use configuration files at all, or you may want to use `.env` file format instead. Thus, you can limit yourself with only reading environment variables:
Expand Down
34 changes: 34 additions & 0 deletions cleanenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,40 @@ type Updater interface {
Update() error
}

// paths holds user provided path.
var paths = make([]string, 0, 4)

// AddConfigPath gives ability to add miltiple paths based on environment or use cases.
func AddConfigPath(path string) {
paths = append(paths, path)
}

// getValidConfigPath returns one valid path from list of paths.
// If multiple valid paths exist, last one will be returned.
func getValidConfigPath() (string, error) {
var valid string

for _, path := range paths {
if _, err := os.Stat(path); err == nil {
valid = path
}
}
if valid == "" {
return "", fmt.Errorf("%w: no valid config file found in configured path", os.ErrNotExist)
}

return valid, nil
}

// Read reads the config based on path set by AddConfigPaths.
func Read(cfg interface{}) error {
path, err := getValidConfigPath()
if err != nil {
return err
}
return ReadConfig(path, cfg)
}

// ReadConfig reads configuration file and parses it depending on tags in structure provided.
// Then it reads and parses
//
Expand Down
Loading
Loading