-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtarget.go
142 lines (125 loc) · 3.8 KB
/
target.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
package main
import (
"fmt"
"reflect"
"time"
log "github.com/Sirupsen/logrus"
"github.com/imdario/mergo"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
)
// SentryTarget defines an url to monitor
type SentryTarget struct {
Name string `mapstructure:"name"`
URL string `mapstructure:"url"`
CheckInterval string `mapstructure:"interval"`
FollowRedirects bool `mapstructure:"follow_redirects"`
ReturnCodes []int `mapstructure:"return_codes"`
FromEmail string `mapstructure:"from_email"`
AlertEmail interface{} `mapstructure:"alert_email"`
AlertEmailList []string
interval time.Duration
nextCheckTime time.Time
LastReturnCode int
CurrentState bool
}
// NewTarget create a sentry target from an interface
func NewTarget(val interface{}) (*SentryTarget, error) {
t := new(SentryTarget)
err := mapstructure.Decode(val, t)
if err != nil {
return nil, errors.Wrapf(err, "error decoding target")
}
targetMap, err := getRawTargetMap(val)
if err != nil {
return nil, errors.Wrapf(err, "incorrect target type")
}
if v, ok := targetMap["follow_redirects"]; ok {
t.FollowRedirects = v.(bool)
} else {
t.FollowRedirects = true
}
if len(t.CheckInterval) > 0 {
t.interval, err = time.ParseDuration(t.CheckInterval)
if err != nil {
return nil, errors.Wrapf(err, "error parsing interval target=%s", t.Name)
}
}
t.nextCheckTime = time.Now().UTC()
t.nextCheckTime = t.nextCheckTime.Add(time.Duration(-1 * t.nextCheckTime.Nanosecond()))
t.CurrentState = true
t.AlertEmailList, err = decodeVerifiedEmailList(t.AlertEmail)
if err != nil {
return nil, errors.Wrapf(err, "error parsing alert_email target=%s", t.Name)
}
if len(t.FromEmail) > 0 {
verifiedEmail, err := FormatEmail(t.FromEmail)
if err != nil {
return nil, errors.Wrapf(err, "email format not valid: %s", t.FromEmail)
}
t.FromEmail = verifiedEmail
}
return t, nil
}
// SpawnTarget creates a new target with missing fields defaulted to our values
func (t *SentryTarget) SpawnTarget(val interface{}) (*SentryTarget, error) {
s, err := NewTarget(val)
if err != nil {
return nil, err
}
err = mergo.Merge(s, t)
if err != nil {
return nil, err
}
targetMap, err := getRawTargetMap(val)
if err != nil {
return nil, errors.Wrapf(err, "incorrect target type")
}
if v, ok := targetMap["follow_redirects"]; ok {
s.FollowRedirects = v.(bool)
} else {
s.FollowRedirects = t.FollowRedirects
}
if len(s.CheckInterval) > 0 {
s.interval, err = time.ParseDuration(s.CheckInterval)
if err != nil {
return nil, fmt.Errorf("error parsing interval: %v", err)
}
}
s.nextCheckTime = time.Now().UTC()
return s, nil
}
// NeedsCheck returns if this target needs to be checked
func (t *SentryTarget) NeedsCheck() bool {
return time.Now().UTC().After(t.nextCheckTime)
}
// ResetRunTime sets the next run time one interval from Now
func (t *SentryTarget) ResetRunTime() {
t.nextCheckTime = t.nextCheckTime.Add(t.interval)
log.Debugf("target: next check for %s is %s", t.Name,
t.nextCheckTime.Format("Jan 02, 2006 15:04:05 UTC"))
}
// IsStatusValid checks if the given status code is valid
func (t *SentryTarget) IsStatusValid(statusCode int) bool {
for _, code := range t.ReturnCodes {
if statusCode == code {
return true
}
}
return false
}
func getRawTargetMap(val interface{}) (map[string]interface{}, error) {
var targetMap map[string]interface{}
switch val.(type) {
case map[string]interface{}:
targetMap = val.(map[string]interface{})
case map[interface{}]interface{}:
targetMap = make(map[string]interface{})
for key, value := range val.(map[interface{}]interface{}) {
targetMap[key.(string)] = value
}
default:
return nil, errors.Errorf("target is an unknown format: %v", reflect.TypeOf(val))
}
return targetMap, nil
}