-
Notifications
You must be signed in to change notification settings - Fork 1
/
config.go
154 lines (129 loc) · 4.39 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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Config contains logic that is related with our application's configutation.
// Configuration can come from environmental variables or yaml config file.
package main
import (
"strconv"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
// YamlRequests encapsulates yaml objects that represent the
// array that holds the requests with the monitoring domains.
type YamlRequests struct {
Requests []YamlRequest `yaml:"requests"`
}
// getCleanRequests holds the logic that gets the requests from the
// yaml config, and verify for each one if they are valid.
// At the end it returns a list of dnsStream structures that can be used
// further.
func (r *YamlRequests) getCleanRequests() ([]*dnsStream, error) {
if len(r.Requests) == 0 {
return []*dnsStream{}, errors.Errorf("Yaml configuration seems empty or malformed, cannot proceed with no valid requests")
}
cleanRequests := []*dnsStream{}
for _, req := range r.Requests {
c, err := req.getCleanRequest()
if err != nil {
log.Error(err.Error())
continue
}
cleanRequests = append(cleanRequests, c)
}
if len(cleanRequests) == 0 {
return []*dnsStream{}, errors.Errorf("No valid requests found inside the request sections coming from yaml config")
}
return cleanRequests, nil
}
// YamlRequest encapsulates yaml objects that represent single
// requests for a domain that we want to monitor.
type YamlRequest struct {
Domain string `yaml:"domain"`
QueryType string `yaml:"queryType"`
Resolver *string `yaml:"resolver"`
ExpectedResponse []string `yaml:"expectedRespone"`
ExpectedResponseCode *string `yaml:"expectedResponseCode"`
Interval *int `yaml:"interval"`
}
// getCleanRequest holds the logic of cleaning a request for a domain
// coming from the yaml config and returns a dnsStream structure that
// can be used further in our code.
func (r *YamlRequest) getCleanRequest() (*dnsStream, error) {
dr := &dnsRequest{r.Domain, r.QueryType, r.Resolver, r.ExpectedResponse, nil}
if dr.queryType == "" {
dr.queryType = "A"
}
if dr.domain == "" {
return nil, errors.New("domain needs to be a valid domain and not empty string")
}
if r.ExpectedResponseCode != nil {
rCode, err := newRCode(*r.ExpectedResponseCode)
if err != nil {
return nil, err
}
dr.expectedResponseCode = &rCode
}
interval := 360 // Default interval loop at 5min
if r.Interval != nil {
interval = *r.Interval
}
return newDNSStream(dr, interval), nil
}
// Config holds all our configuration coming from user that our app needs
type config struct {
appPort int
logLevel string
watchdogRequests []*dnsStream
}
// newConfig constructs and returns the struct that will host
// all our configuration variables
func newConfig() (*config, error) {
initViper()
r, err := getYamlConfig()
if err != nil {
return nil, errors.Wrap(err, "Couldn't get a yaml config")
}
cleanDNSRequests, err := r.getCleanRequests()
if err != nil {
return nil, errors.Wrap(err, "Couldn't get a valid yaml config")
}
port := viper.GetString("app_port")
intPort, ok := strconv.Atoi(port)
if ok != nil {
return nil, errors.New("Couldn't get a valid integer for the DNS_VERIFIER_PORT configuration variable")
}
return &config{
appPort: intPort,
logLevel: viper.GetString("log_level"),
watchdogRequests: cleanDNSRequests,
}, nil
}
// initViper initializes all viper configuration that we need.
func initViper() {
// Set global options
viper.AddConfigPath(".")
viper.AddConfigPath("/etc/dns-verifier")
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.SetEnvPrefix("dns_verifier")
// Set default for our existing env variables
viper.SetDefault("APP_PORT", "3333")
viper.SetDefault("LOG_LEVEL", "DEBUG")
viper.SetDefault("INTERVAL", 30)
// Enable VIPER to read Environment Variables
viper.AutomaticEnv()
}
// getYamlConfig reads the config yaml file that contains the user's
// requests for monitoring domains. After successfully reading the file
// the funciton return a YamlRequests struct that contains all info from
// the file.
func getYamlConfig() (*YamlRequests, error) {
if err := viper.ReadInConfig(); err != nil {
return nil, errors.Wrap(err, "Error reading config file")
}
var yr YamlRequests
err := viper.Unmarshal(&yr)
if err != nil {
return nil, errors.Wrap(err, "Unable to decode config yaml into struct")
}
return &yr, nil
}