-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathconfigbuilder.go
132 lines (111 loc) · 3.59 KB
/
configbuilder.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
package config
import (
"bytes"
"crypto/md5"
"errors"
"fmt"
"github.com/imdario/mergo"
"github.com/jinzhu/copier"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
"io"
"os"
"strconv"
)
type builder struct {
config *Config
configPath string
}
func (b *builder) newConfig(configPath string) (*Config, []error) {
var errs []error
if file, loadErrs := b.loadConfig(configPath); loadErrs != nil {
return nil, loadErrs
} else {
if readErr := b.Read(file); readErr != nil {
return nil, []error{fmt.Errorf("newConfig: failed to read file: %v; error: %w", file.Name(), readErr)}
}
}
for _, service := range b.config.Services {
service.setClient(service.mergedComponents().Client)
}
var collErr error
var dbErrs []error
// initialize the Collector for each crawler
for _, crawler := range b.config.Crawlers {
if crawler.Collector, collErr = crawler.collector(); collErr != nil {
errs = appendAndLog(fmt.Errorf("newConfig: failed to build crawler; error: %w", collErr), errs)
}
}
for _, database := range b.config.Databases {
if database.Pool, dbErrs = database.DatabaseService(); dbErrs != nil {
errs = appendAndLog(fmt.Errorf("newConfig: %v", dbErrs), errs)
}
}
return b.config, errs
}
func (b *builder) loadConfig(configPath string) (*os.File, []error) {
if file, loadErr := b.Load(configPath); loadErr != nil {
return nil, []error{fmt.Errorf("newConfig: %w", loadErr)}
} else {
return file, nil
}
}
func (b *builder) Load(path string) (file *os.File, err error) {
log.Tracef("Loading config: %v", path)
b.configPath = path
if file, err = os.Open(path); err != nil {
return nil, fmt.Errorf("Load: failed to open config file %v; %w", path, err)
}
return file, err
}
func (b *builder) Read(configData io.Reader) (err error) {
if b.config, err = initialConfig(configData); err != nil {
return err
}
if mergeErr := mergeServiceComponentConfigs(b.config); mergeErr != nil {
return fmt.Errorf("Read: failed to merge component configs, error: %w", mergeErr)
}
return nil
}
func initialConfig(data io.Reader) (*Config, error) {
buf := new(bytes.Buffer)
if _, buffErr := io.Copy(buf, data); buffErr != nil {
return nil, fmt.Errorf("initialConfig: failed to read config data; err: %w", buffErr)
}
config := new(Config)
if err := yaml.Unmarshal(buf.Bytes(), &config); err != nil {
return nil, fmt.Errorf("initialConfig: failed unmarshalling config data; err: %w", err)
}
config.Hash = fmt.Sprintf("%x", md5.Sum(buf.Bytes()))
return config, nil
}
func mergeServiceComponentConfigs(c *Config) error {
for i, service := range c.Services {
if mergeErr := mergeConfigs(&service.ComponentConfigOverrides, &c.ComponentConfigs, &service.mergedComponentConfigs); mergeErr != nil {
return fmt.Errorf("mergeServiceComponentConfigs: failed to merging component config: %v; error %w", i, mergeErr)
}
}
return nil
}
func mergeConfigs(override *ComponentConfigs, defaultC *ComponentConfigs, mergedC *ComponentConfigs) error {
if mergedC == nil {
return errors.New("mergeConfigs: nil pointer passed for merged components")
}
if err := copier.Copy(mergedC, override); err != nil && override != nil {
return fmt.Errorf("mergeConfigs: failed to copy config overrides; error: %w", err)
}
if err := mergo.Merge(mergedC, defaultC); err != nil && defaultC != nil {
return fmt.Errorf("mergeConfigs: failed to copy config defaults; error: %w", err)
}
return nil
}
func toInt(str string) int {
res := 0
var err error
if str != "" {
if res, err = strconv.Atoi(str); err != nil {
log.Errorf("toInt: failed to convert '%s' to int; error: %v", str, err)
}
}
return res
}