-
Notifications
You must be signed in to change notification settings - Fork 0
/
config.go
128 lines (106 loc) · 3.36 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package huner
import (
"errors"
"fmt"
"os"
"path"
"strings"
"github.com/kamva/gutil"
"github.com/kamva/hexa/hlog"
"github.com/kamva/tracer"
"github.com/mitchellh/mapstructure"
"github.com/spf13/viper"
)
const EnvironmentTest = "test" // We can use this reserved env name for test environments. it's completely optional.
type ConfigFilePathsOptions struct {
EtcPath string // e.g., senna
HomePath string // e.g., /home/mehran/senna/order
FileName string // e.g., config
FileExtension string // e.g., json or yaml
Environment string // (optional) e.g., staging
}
// EtcPath returns path to the /etc directory.
// Later we can make its base path os dependant.
func EtcPath(p string) string {
return path.Join("/etc", p)
}
func EnvKeysPrefix() string {
return os.Getenv("HEXA_CONF_PREFIX")
}
// EnvironmentKey returns the key we can use to get the run environment.
func EnvironmentKey(prefix string) string {
key := "ENV"
if prefix != "" {
return fmt.Sprintf("%s_%s", prefix, key)
}
return key
}
// ConfigFilePaths generates config path as follow:
// - {EtcPath}/{configFile.configExtension}
// - {HomePath}/{configFile.configExtension}
// - {HomePath}/{configFile.{environment}.configExtension}
// - {HomePath}/.env
// - {HomePath}/.{environment}.env
// If you set onlyEnvDependant to true, it just includes files that include the
// environment name in their config file name.
func ConfigFilePaths(o ConfigFilePathsOptions, onlyEnvDependant bool) []string {
confFile := fmt.Sprintf("%s.%s", o.FileName, o.FileExtension)
var files []string
if !onlyEnvDependant { // including crossEnv paths.
files = append(files,
path.Join(o.EtcPath, confFile), // {EtcPath}/{configFile.configExtension}
path.Join(o.HomePath, confFile), // {HomePath}/{configFile.configExtension}
path.Join(o.HomePath, ".env"), // {HomePath}/.env
)
}
if o.Environment != "" {
files = append(files,
// {HomePath}/{configFile}.{env}.{extension}
path.Join(o.HomePath, fmt.Sprintf("%s.%s.%s", o.FileName, o.Environment, o.FileExtension)),
// {HomePath}/.{env}.env
path.Join(o.HomePath, fmt.Sprintf(".%s.env", o.Environment)),
)
}
var existedFiles []string
for _, f := range files {
if gutil.FileExists(f) {
existedFiles = append(existedFiles, f)
}
}
hlog.Debug("generated config file paths",
hlog.String("search_paths", strings.Join(files, ",")),
hlog.String("existed_paths", strings.Join(existedFiles, ",")),
hlog.String("paths_config", fmt.Sprintf("%+v", o)),
)
return existedFiles
}
// ViperDecoderTagName sets the tag name on a viper decoder.
func ViperDecoderTagName(name string) viper.DecoderConfigOption {
return func(cfg *mapstructure.DecoderConfig) { cfg.TagName = name }
}
// NewViperConfig returns new instance of the viper
func NewViperConfig(envPrefix string, files []string) (*viper.Viper, error) {
v := viper.New()
if len(files) == 0 {
return nil, tracer.Trace(errors.New("at least one config files should be exists"))
}
isFirst := true
for _, f := range files {
v.SetConfigFile(f)
if isFirst {
isFirst = false
if err := v.ReadInConfig(); err != nil {
return nil, tracer.Trace(err)
}
continue
}
if err := v.MergeInConfig(); err != nil {
return nil, tracer.Trace(err)
}
}
v.AllowEmptyEnv(true)
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
v.SetEnvPrefix(envPrefix)
v.AutomaticEnv()
return v, nil
}