This repository was archived by the owner on May 19, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathreader.go
140 lines (113 loc) · 3.47 KB
/
reader.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
129
130
131
132
133
134
135
136
137
138
139
140
package config
import (
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"github.com/imdario/mergo"
"gopkg.in/yaml.v2"
)
// ReadConfigs Reads yaml files from configuration directory with sub folders
// as application stage and merges config files in one configuration per stage
func ReadConfigs(cfgPath string) ([]byte, error) {
if cfgPath == "" {
cfgPath = "./configuration"
}
cfgPath = strings.TrimRight(cfgPath, "/")
iSay("Config path: `%v`", cfgPath)
if _, err := os.Stat(cfgPath); os.IsNotExist(err) {
return nil, err
}
stage := getStage()
var (
fileList = map[string][]string{}
stageDir string
configPathDepth int
)
err := filepath.Walk(cfgPath, func(path string, f os.FileInfo, err error) error {
pathLen := len(strings.Split(path, "/"))
if cfgPath == path {
configPathDepth = pathLen + 1
if strings.Contains(cfgPath, "./") {
configPathDepth = pathLen
}
return nil
}
if pathLen > configPathDepth+1 {
return filepath.SkipDir
}
if f.IsDir() && pathLen == configPathDepth {
stageDir = f.Name()
return nil
}
if filepath.Ext(f.Name()) == ".yaml" && (stageDir == "defaults" || stageDir == stage) {
fileList[stageDir] = append(fileList[stageDir], f.Name())
}
return nil
})
if err != nil {
iSay("Some error while walking through config dir!: `%+v`", err)
return nil, err
}
// check defaults config existence. Fall down if not
if _, ok := fileList["defaults"]; !ok || len(fileList["defaults"]) == 0 {
log.Fatal("[config] defaults config is not found! Fall down.")
}
fileListResult := make(map[string][]string)
configs := make(map[string]map[string]interface{})
for folder, files := range fileList {
for _, file := range files {
configBytes, err := ioutil.ReadFile(cfgPath + "/" + folder + "/" + file)
if err != nil {
log.Fatalf("[config] Error reading config file %s: %v", cfgPath+"/"+folder+"/"+file, err)
}
var configFromFile map[string]map[string]interface{}
if err = yaml.Unmarshal(configBytes, &configFromFile); err != nil {
log.Fatalf("[config] %s %s config read fail! Fall down.", folder, file)
}
if _, ok := configFromFile[folder]; !ok {
iSay("File %s excluded from %s (it is not for this stage)!", file, folder)
continue
}
if _, ok := configs[folder]; !ok {
configs[folder] = configFromFile[folder]
}
cc := configs[folder]
if err := mergo.Merge(&cc, configFromFile[folder], mergo.WithOverride); err != nil {
log.Fatalf("[config] merging files in folder error: %s", err)
}
configs[folder] = cc
fileListResult[folder] = append(fileListResult[folder], file)
}
}
iSay("Config files: `%+v`", fileListResult)
config := configs["defaults"]
c, ok := configs[stage]
if ok {
if err := mergo.Merge(&config, c, mergo.WithOverride); err != nil {
log.Fatalf("[config] merging error: %s", err)
}
iSay("Stage `%s` config is loaded and merged with `defaults`", stage)
}
return yaml.Marshal(config)
}
// iSay Logs in stdout when quiet mode is off
func iSay(pattern string, args ...interface{}) {
// if quietMode == false {
log.Printf("[config] "+pattern, args...)
// }
}
// getStage Load configuration for stage with fallback to 'development'
func getStage() (stage string) {
stage = GetEnv("STAGE", "development")
iSay("Current stage: `%s`", stage)
return
}
// GetEnv Getting var from ENV with fallback param on empty
func GetEnv(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok {
return value
}
return fallback
}