/
backends.go
138 lines (128 loc) · 3.56 KB
/
backends.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
package backends
import (
"fmt"
"log"
"reflect"
"github.com/go-playground/validator/v10"
"github.com/mitchellh/mapstructure"
"github.com/spf13/cobra"
)
type BackendInterface interface {
GetConfig() interface{}
Send(config interface{}, title string, message string, status *bool) error
}
var backends = make(map[string]BackendInterface)
var validate = validator.New()
func RegisterFlags(cmd ...*cobra.Command) {
for _, c := range cmd {
c.Flags().StringSlice("backends", []string{}, "")
}
for backendKey, b := range backends {
t := reflect.TypeOf(b.GetConfig())
for i := 0; i < t.NumField(); i++ {
registerFlag(backendKey, t.Field(i).Tag.Get("mapstructure"), t.Field(i), cmd...)
}
}
}
func registerFlag(backendKey string, key string, field reflect.StructField, cmd ...*cobra.Command) {
kind := field.Type.Kind()
if kind == reflect.Ptr {
kind = field.Type.Elem().Kind()
}
switch kind {
case reflect.String:
for _, c := range cmd {
c.Flags().String(fmt.Sprintf("%s.%s", backendKey, key), "", "")
}
case reflect.Int:
for _, c := range cmd {
c.Flags().Int(fmt.Sprintf("%s.%s", backendKey, key), 0, "")
}
}
}
func OverrideConfigs(cfg *map[string]interface{}, cmd *cobra.Command) {
bflag := cmd.Flags().Lookup("backends")
var bs []interface{}
if bflag.Changed {
val, err := cmd.Flags().GetStringSlice("backends")
if err != nil {
log.Fatal(err)
}
for _, v := range val {
bs = append(bs, v)
}
(*cfg)["backends"] = bs
}
for backendKey, b := range backends {
if (*cfg)[backendKey] == nil {
(*cfg)[backendKey] = map[interface{}]interface{}{}
}
t := reflect.TypeOf(b.GetConfig())
for i := 0; i < t.NumField(); i++ {
overrideConfig((*cfg)[backendKey], backendKey, t.Field(i).Tag.Get("mapstructure"), t.Field(i), cmd)
}
}
}
func overrideConfig(cfg interface{}, backendKey string, key string, field reflect.StructField, cmd *cobra.Command) {
kind := field.Type.Kind()
if kind == reflect.Ptr {
kind = field.Type.Elem().Kind()
}
switch kind {
case reflect.String:
v := cmd.Flags().Lookup(fmt.Sprintf("%s.%s", backendKey, key))
if !v.Changed {
return
}
val, err := cmd.Flags().GetString(fmt.Sprintf("%s.%s", backendKey, key))
if err != nil {
log.Fatal(err)
}
cfg.(map[interface{}]interface{})[key] = val
case reflect.Int:
v := cmd.Flags().Lookup(fmt.Sprintf("%s.%s", backendKey, key))
if !v.Changed {
return
}
val, err := cmd.Flags().GetInt(fmt.Sprintf("%s.%s", backendKey, key))
if err != nil {
log.Fatal(err)
}
cfg.(map[interface{}]interface{})[key] = val
}
}
func Send(cfg map[string]interface{}, title string, msg string, status *bool) error {
backendIfaces, ok := cfg["backends"]
if !ok {
return fmt.Errorf("no backends configured")
}
backendKeysIface, ok := backendIfaces.([]interface{})
if !ok {
return fmt.Errorf("backends is not a list")
}
for _, backendKeyIface := range backendKeysIface {
backendKey, ok := backendKeyIface.(string)
if !ok {
log.Println(fmt.Errorf("backend is not a string"))
continue
}
b, ok := backends[backendKey]
if !ok {
log.Println(fmt.Errorf("backend %s not found", backendKey))
continue
}
cfgStruct := b.GetConfig()
if err := mapstructure.Decode(cfg[backendKey], &cfgStruct); err != nil {
log.Println(fmt.Errorf("error decoding backend %s config: %s", backendKey, err))
continue
}
if err := validate.Struct(cfgStruct); err != nil {
log.Println(fmt.Errorf("error validating backend %s config: %s", backendKey, err))
continue
}
if err := b.Send(cfgStruct, title, msg, status); err != nil {
return err
}
}
return nil
}