forked from prometheus/alertmanager
/
silence_update.go
116 lines (100 loc) · 3.1 KB
/
silence_update.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
package cli
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"path"
"time"
"github.com/alecthomas/kingpin"
"github.com/prometheus/alertmanager/cli/format"
"github.com/prometheus/alertmanager/types"
)
type getResponse struct {
Status string `json:"status"`
Data types.Silence `json:"data,omitempty"`
ErrorType string `json:"errorType,omitempty"`
Error string `json:"error,omitempty"`
}
var (
updateCmd = silenceCmd.Command("update", "Update silences")
updateExpires = updateCmd.Flag("expires", "Duration of silence").Short('e').Duration()
updateExpiresOn = updateCmd.Flag("expire-on", "Expire at a certain time (Overwrites expires) RFC3339 format 2006-01-02T15:04:05Z07:00").Time(time.RFC3339)
updateComment = updateCmd.Flag("comment", "A comment to help describe the silence").Short('c').String()
updateIds = updateCmd.Arg("update-ids", "Silence IDs to update").Strings()
)
func init() {
updateCmd.Action(update)
longHelpText["silence update"] = `Extend or update existing silence in Alertmanager.`
}
func update(element *kingpin.ParseElement, ctx *kingpin.ParseContext) error {
if len(*updateIds) < 1 {
return fmt.Errorf("no silence IDs specified")
}
alertmanagerUrl := GetAlertmanagerURL("/api/v1/silence")
var updatedSilences []types.Silence
for _, silenceId := range *updateIds {
silence, err := getSilenceById(silenceId, alertmanagerUrl)
if err != nil {
return err
}
silence, err = updateSilence(silence)
if err != nil {
return err
}
updatedSilences = append(updatedSilences, *silence)
}
if *silenceQuiet {
for _, silence := range updatedSilences {
fmt.Println(silence.ID)
}
} else {
formatter, found := format.Formatters[*output]
if !found {
return fmt.Errorf("unknown output formatter")
}
formatter.FormatSilences(updatedSilences)
}
return nil
}
// This takes an url.URL and not a pointer as we will modify it for our API call.
func getSilenceById(silenceId string, baseUrl url.URL) (*types.Silence, error) {
baseUrl.Path = path.Join(baseUrl.Path, silenceId)
res, err := http.Get(baseUrl.String())
if err != nil {
return nil, err
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, fmt.Errorf("couldn't read response body: %v", err)
}
if res.StatusCode == 404 {
return nil, fmt.Errorf("no silence found with id: %v", silenceId)
}
if res.StatusCode != 200 {
return nil, fmt.Errorf("received %d response from Alertmanager: %v", res.StatusCode, body)
}
var response getResponse
err = json.Unmarshal(body, &response)
return &response.Data, nil
}
func updateSilence(silence *types.Silence) (*types.Silence, error) {
if *updateExpires != 0 {
silence.EndsAt = time.Now().UTC().Add(*updateExpires)
}
// expire-on will override expires value if both are specified
if !(*updateExpiresOn).IsZero() {
silence.EndsAt = *updateExpiresOn
}
if *updateComment != "" {
silence.Comment = *updateComment
}
// addSilence can also be used to update an existing silence
_, err := addSilence(silence)
if err != nil {
return nil, err
}
return silence, nil
}