cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.3.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/config/config.go

244lines · modecode

1package config
2
3import (
4 "encoding/json"
5 "fmt"
6 "os"
7 "strings"
8 "time"
9
10 "github.com/cloudflare/pint/internal/checks"
11 "github.com/cloudflare/pint/internal/parser"
12
13 "github.com/hashicorp/hcl/v2/hclsimple"
14 "github.com/prometheus/common/model"
15 "github.com/rs/zerolog/log"
16)
17
18type Config struct {
19 CI *CI `hcl:"ci,block"`
20 Repository *Repository `hcl:"repository,block"`
21 Prometheus []PrometheusConfig `hcl:"prometheus,block"`
22 Checks *Checks `hcl:"checks,block"`
23 Rules []Rule `hcl:"rule,block"`
24}
25
26func (cfg *Config) SetDisabledChecks(offline bool, l []string) {
27 disabled := map[string]struct{}{}
28 if offline {
29 for _, name := range checks.OnlineChecks {
30 disabled[name] = struct{}{}
31 }
32 }
33 for _, s := range l {
34 re := strictRegex(s)
35 for _, name := range checks.CheckNames {
36 if re.MatchString(name) {
37 disabled[name] = struct{}{}
38 }
39 }
40 }
41 for name := range disabled {
42 var found bool
43 for _, c := range cfg.Checks.Disabled {
44 if c == name {
45 found = true
46 }
47 }
48 if !found {
49 cfg.Checks.Disabled = append(cfg.Checks.Disabled, name)
50 }
51 }
52}
53
54func (cfg Config) String() string {
55 content, _ := json.MarshalIndent(cfg, "", " ")
56 return string(content)
57}
58
59func (cfg Config) GetChecksForRule(path string, r parser.Rule) []checks.RuleChecker {
60 enabled := []checks.RuleChecker{}
61
62 if isEnabled(cfg.Checks.Enabled, cfg.Checks.Disabled, checks.SyntaxCheckName, r) {
63 enabled = append(enabled, checks.NewSyntaxCheck())
64 }
65
66 proms := []PrometheusConfig{}
67 for _, prom := range cfg.Prometheus {
68 if prom.isEnabledForPath(path) {
69 proms = append(proms, prom)
70 }
71 }
72 for _, rule := range cfg.Rules {
73 for _, c := range rule.resolveChecks(path, r, cfg.Checks.Enabled, cfg.Checks.Disabled, proms) {
74 if r.HasComment(fmt.Sprintf("disable %s", removeRedundantSpaces(c.String()))) {
75 log.Debug().
76 Str("path", path).
77 Str("check", c.String()).
78 Msg("Check disabled by comment")
79 continue
80 }
81 enabled = append(enabled, c)
82 }
83 }
84
85 el := []string{}
86 for _, e := range enabled {
87 el = append(el, fmt.Sprintf("%v", e))
88 }
89 name := "unknown"
90 if r.AlertingRule != nil {
91 name = r.AlertingRule.Alert.Value.Value
92 } else if r.RecordingRule != nil {
93 name = r.RecordingRule.Record.Value.Value
94 }
95 log.Debug().Strs("enabled", el).Str("path", path).Str("rule", name).Msg("Configured checks for rule")
96
97 return enabled
98}
99
100func Load(path string, failOnMissing bool) (cfg Config, err error) {
101 cfg = Config{
102 CI: &CI{
103 MaxCommits: 20,
104 BaseBranch: "master",
105 },
106 Checks: &Checks{
107 Enabled: checks.CheckNames,
108 Disabled: []string{},
109 },
110 Rules: []Rule{},
111 }
112
113 if _, err := os.Stat(path); err == nil || failOnMissing {
114 log.Info().Str("path", path).Msg("Loading configuration file")
115 err = hclsimple.DecodeFile(path, nil, &cfg)
116 if err != nil {
117 return cfg, err
118 }
119 }
120
121 if cfg.CI != nil {
122 if err = cfg.CI.validate(); err != nil {
123 return cfg, err
124 }
125 }
126
127 if cfg.Repository != nil && cfg.Repository.BitBucket != nil {
128 if err = cfg.Repository.BitBucket.validate(); err != nil {
129 return cfg, err
130 }
131 }
132
133 if cfg.Repository != nil && cfg.Repository.GitHub != nil {
134 if err = cfg.Repository.GitHub.validate(); err != nil {
135 return cfg, err
136 }
137 }
138
139 if cfg.Checks != nil {
140 if err = cfg.Checks.validate(); err != nil {
141 return cfg, err
142 }
143 }
144
145 for _, prom := range cfg.Prometheus {
146 if err = prom.validate(); err != nil {
147 return cfg, err
148 }
149 }
150
151 for _, rule := range cfg.Rules {
152 if rule.Match != nil {
153 if err = rule.Match.validate(true); err != nil {
154 return cfg, err
155 }
156 }
157 if rule.Ignore != nil {
158 if err = rule.Ignore.validate(false); err != nil {
159 return cfg, err
160 }
161 }
162
163 for _, aggr := range rule.Aggregate {
164 if err = aggr.validate(); err != nil {
165 return cfg, err
166 }
167 }
168
169 if rule.Rate != nil {
170 if err = rule.Rate.validate(); err != nil {
171 return cfg, err
172 }
173 }
174
175 for _, ann := range rule.Annotation {
176 if err = ann.validate(); err != nil {
177 return cfg, err
178 }
179 }
180
181 for _, lab := range rule.Label {
182 if err = lab.validate(); err != nil {
183 return cfg, err
184 }
185 }
186
187 if rule.Cost != nil {
188 if err = rule.Cost.validate(); err != nil {
189 return cfg, err
190 }
191 }
192
193 if rule.Series != nil {
194 if err = rule.Series.validate(); err != nil {
195 return cfg, err
196 }
197 }
198
199 if rule.Alerts != nil {
200 if err = rule.Alerts.validate(); err != nil {
201 return cfg, err
202 }
203 }
204
205 for _, reject := range rule.Reject {
206 if err = reject.validate(); err != nil {
207 return cfg, err
208 }
209
210 }
211
212 if rule.Comparison != nil {
213 if err = rule.Comparison.validate(); err != nil {
214 return cfg, err
215 }
216 }
217
218 if rule.Template != nil {
219 if err = rule.Template.validate(); err != nil {
220 return cfg, err
221 }
222 }
223
224 if rule.VectorMatching != nil {
225 if err = rule.VectorMatching.validate(); err != nil {
226 return cfg, err
227 }
228 }
229 }
230
231 return cfg, nil
232}
233
234func parseDuration(d string) (time.Duration, error) {
235 mdur, err := model.ParseDuration(d)
236 if err != nil {
237 return 0, err
238 }
239 return time.Duration(mdur), nil
240}
241
242func removeRedundantSpaces(line string) string {
243 return strings.Join(strings.Fields(line), " ")
244}
245