...
1
2
3
4
5
6
7
8
9
10
11
12
13
14 package cli
15
16 import (
17 "context"
18 "errors"
19 "fmt"
20 "time"
21
22 "github.com/go-openapi/strfmt"
23 "github.com/prometheus/common/model"
24 "gopkg.in/alecthomas/kingpin.v2"
25
26 "github.com/prometheus/alertmanager/api/v2/client/silence"
27 "github.com/prometheus/alertmanager/api/v2/models"
28 "github.com/prometheus/alertmanager/cli/format"
29 )
30
31 type silenceUpdateCmd struct {
32 quiet bool
33 duration string
34 start string
35 end string
36 comment string
37 ids []string
38 }
39
40 func configureSilenceUpdateCmd(cc *kingpin.CmdClause) {
41 var (
42 c = &silenceUpdateCmd{}
43 updateCmd = cc.Command("update", "Update silences")
44 )
45 updateCmd.Flag("quiet", "Only show silence ids").Short('q').BoolVar(&c.quiet)
46 updateCmd.Flag("duration", "Duration of silence").Short('d').StringVar(&c.duration)
47 updateCmd.Flag("start", "Set when the silence should start. RFC3339 format 2006-01-02T15:04:05-07:00").StringVar(&c.start)
48 updateCmd.Flag("end", "Set when the silence should end (overwrites duration). RFC3339 format 2006-01-02T15:04:05-07:00").StringVar(&c.end)
49 updateCmd.Flag("comment", "A comment to help describe the silence").Short('c').StringVar(&c.comment)
50 updateCmd.Arg("update-ids", "Silence IDs to update").StringsVar(&c.ids)
51
52 updateCmd.Action(execWithTimeout(c.update))
53 }
54
55 func (c *silenceUpdateCmd) update(ctx context.Context, _ *kingpin.ParseContext) error {
56 if len(c.ids) < 1 {
57 return fmt.Errorf("no silence IDs specified")
58 }
59
60 amclient := NewAlertmanagerClient(alertmanagerURL)
61
62 var updatedSilences []models.GettableSilence
63 for _, silenceID := range c.ids {
64 params := silence.NewGetSilenceParams()
65 params.SilenceID = strfmt.UUID(silenceID)
66 response, err := amclient.Silence.GetSilence(params)
67 if err != nil {
68 return err
69 }
70 sil := response.Payload
71 if c.start != "" {
72 startsAtTime, err := time.Parse(time.RFC3339, c.start)
73 if err != nil {
74 return err
75 }
76 startsAt := strfmt.DateTime(startsAtTime)
77 sil.StartsAt = &startsAt
78 }
79
80 if c.end != "" {
81 endsAtTime, err := time.Parse(time.RFC3339, c.end)
82 if err != nil {
83 return err
84 }
85 endsAt := strfmt.DateTime(endsAtTime)
86 sil.EndsAt = &endsAt
87 } else if c.duration != "" {
88 d, err := model.ParseDuration(c.duration)
89 if err != nil {
90 return err
91 }
92 if d == 0 {
93 return fmt.Errorf("silence duration must be greater than 0")
94 }
95 endsAt := strfmt.DateTime(time.Time(*sil.StartsAt).UTC().Add(time.Duration(d)))
96 sil.EndsAt = &endsAt
97 }
98
99 if time.Time(*sil.StartsAt).After(time.Time(*sil.EndsAt)) {
100 return errors.New("silence cannot start after it ends")
101 }
102
103 if c.comment != "" {
104 sil.Comment = &c.comment
105 }
106
107 ps := &models.PostableSilence{
108 ID: *sil.ID,
109 Silence: sil.Silence,
110 }
111
112 amclient := NewAlertmanagerClient(alertmanagerURL)
113
114 silenceParams := silence.NewPostSilencesParams().WithContext(ctx).WithSilence(ps)
115 postOk, err := amclient.Silence.PostSilences(silenceParams)
116 if err != nil {
117 return err
118 }
119
120 sil.ID = &postOk.Payload.SilenceID
121 updatedSilences = append(updatedSilences, *sil)
122 }
123
124 if c.quiet {
125 for _, silence := range updatedSilences {
126 fmt.Println(silence.ID)
127 }
128 } else {
129 formatter, found := format.Formatters[output]
130 if !found {
131 return fmt.Errorf("unknown output formatter")
132 }
133 if err := formatter.FormatSilences(updatedSilences); err != nil {
134 return fmt.Errorf("error formatting silences: %v", err)
135 }
136 }
137 return nil
138 }
139
View as plain text