-
Notifications
You must be signed in to change notification settings - Fork 0
/
loader.go
89 lines (83 loc) · 2.12 KB
/
loader.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
package envloader
import (
"bufio"
"fmt"
"log"
"os"
"reflect"
"strings"
)
const (
tagName = "env"
)
//ParseEnv takes a pointer to a struct and an env file name and populates that struct with the values
func ParseEnv(e interface{}, filename string) {
envMap := createEnvMap(filename)
envVal := reflect.ValueOf(e)
if envVal.Kind() != reflect.Pointer {
log.Fatal("error you must pass a pointer to the env struct")
}
if envVal.IsNil() {
log.Fatal("error env struct was empty")
}
envEl := envVal.Elem()
envType := reflect.TypeOf(e).Elem()
for i := 0; i < envType.NumField(); i++ {
t := envType.Field(i)
v := envEl.Field(i)
tag := strings.Split(t.Tag.Get(tagName), ",")
tagId := tag[0]
required := strings.Split(tag[1], "=")[1]
envVar := envMap[tagId]
if envVar == "" && required == "true" {
log.Fatalf("env variable %v is required got empty string", tagId)
} else if envVar == "" && required == "false" {
fmt.Printf("%v is empty var in map and is not required '%v' not set\n", tagId, t.Name)
} else {
v.SetString(envVar)
}
}
}
func createEnvMap(f string) map[string]string {
em := make(map[string]string)
file, err := os.Open(f)
if err != nil {
log.Fatal(f, " file not found")
}
defer file.Close()
s := bufio.NewScanner(file)
s.Split(bufio.ScanLines)
for s.Scan() {
line := s.Text()
comment := strings.ContainsAny(line, "#")
if !comment {
xs := splitKeyValue(line)
em[xs[0]] = xs[1]
}
if comment {
skipLine := strings.HasPrefix(line, "#")
if !skipLine {
xs, err := splitKeyValueComment(line)
if err == nil {
em[xs[0]] = xs[1]
}
}
}
}
return em
}
//splitKeyValue splits an env file line into a slice of strings
func splitKeyValue(line string) []string {
return strings.SplitN(line, "=", 2)
}
//splitKeyValueComment takes an env file line and removes any inline comment and passes it to splitKeyValue
func splitKeyValueComment(line string) ([]string, error) {
before, _, found := strings.Cut(line, "#")
if !found {
err := fmt.Errorf("error ")
fmt.Println(err)
return []string{}, err
}
trim := strings.Trim(before, " ")
return splitKeyValue(trim), nil
}