1414package v2
1515
1616import (
17+ "errors"
1718 "fmt"
1819 "net/http"
1920 "regexp"
2021 "sort"
2122 "sync"
2223 "time"
2324
24- "github.com/prometheus/alertmanager/util/callback"
2525 "github.com/go-kit/log"
2626 "github.com/go-kit/log/level"
2727 "github.com/go-openapi/analysis"
@@ -33,6 +33,9 @@ import (
3333 "github.com/prometheus/common/version"
3434 "github.com/rs/cors"
3535
36+ alertgroupinfolist_ops "github.com/prometheus/alertmanager/api/v2/restapi/operations/alertgroupinfolist"
37+ "github.com/prometheus/alertmanager/util/callback"
38+
3639 "github.com/prometheus/alertmanager/api/metrics"
3740 open_api_models "github.com/prometheus/alertmanager/api/v2/models"
3841 "github.com/prometheus/alertmanager/api/v2/restapi"
@@ -54,13 +57,14 @@ import (
5457
5558// API represents an Alertmanager API v2
5659type API struct {
57- peer cluster.ClusterPeer
58- silences * silence.Silences
59- alerts provider.Alerts
60- alertGroups groupsFn
61- getAlertStatus getAlertStatusFn
62- apiCallback callback.Callback
63- uptime time.Time
60+ peer cluster.ClusterPeer
61+ silences * silence.Silences
62+ alerts provider.Alerts
63+ alertGroups groupsFn
64+ alertGroupInfos groupInfosFn
65+ getAlertStatus getAlertStatusFn
66+ apiCallback callback.Callback
67+ uptime time.Time
6468
6569 // mtx protects alertmanagerConfig, setAlertStatus and route.
6670 mtx sync.RWMutex
@@ -78,6 +82,7 @@ type API struct {
7882
7983type (
8084 groupsFn func (func (* dispatch.Route ) bool , func (* types.Alert , time.Time ) bool ) (dispatch.AlertGroups , map [prometheus_model.Fingerprint ][]string )
85+ groupInfosFn func (func (* dispatch.Route ) bool ) dispatch.AlertGroupInfos
8186 getAlertStatusFn func (prometheus_model.Fingerprint ) types.AlertStatus
8287 setAlertStatusFn func (prometheus_model.LabelSet )
8388)
8691func NewAPI (
8792 alerts provider.Alerts ,
8893 gf groupsFn ,
94+ gif groupInfosFn ,
8995 sf getAlertStatusFn ,
9096 silences * silence.Silences ,
9197 apiCallback callback.Callback ,
@@ -97,15 +103,16 @@ func NewAPI(
97103 apiCallback = callback.NoopAPICallback {}
98104 }
99105 api := API {
100- alerts : alerts ,
101- getAlertStatus : sf ,
102- alertGroups : gf ,
103- peer : peer ,
104- silences : silences ,
105- apiCallback : apiCallback ,
106- logger : l ,
107- m : metrics .NewAlerts ("v2" , r ),
108- uptime : time .Now (),
106+ alerts : alerts ,
107+ getAlertStatus : sf ,
108+ alertGroups : gf ,
109+ alertGroupInfos : gif ,
110+ peer : peer ,
111+ silences : silences ,
112+ apiCallback : apiCallback ,
113+ logger : l ,
114+ m : metrics .NewAlerts ("v2" , r ),
115+ uptime : time .Now (),
109116 }
110117
111118 // Load embedded swagger file.
@@ -129,6 +136,7 @@ func NewAPI(
129136 openAPI .AlertGetAlertsHandler = alert_ops .GetAlertsHandlerFunc (api .getAlertsHandler )
130137 openAPI .AlertPostAlertsHandler = alert_ops .PostAlertsHandlerFunc (api .postAlertsHandler )
131138 openAPI .AlertgroupGetAlertGroupsHandler = alertgroup_ops .GetAlertGroupsHandlerFunc (api .getAlertGroupsHandler )
139+ openAPI .AlertgroupinfolistGetAlertGroupInfoListHandler = alertgroupinfolist_ops .GetAlertGroupInfoListHandlerFunc (api .getAlertGroupInfoListHandler )
132140 openAPI .GeneralGetStatusHandler = general_ops .GetStatusHandlerFunc (api .getStatusHandler )
133141 openAPI .ReceiverGetReceiversHandler = receiver_ops .GetReceiversHandlerFunc (api .getReceiversHandler )
134142 openAPI .SilenceDeleteSilenceHandler = silence_ops .DeleteSilenceHandlerFunc (api .deleteSilenceHandler )
@@ -443,6 +451,78 @@ func (api *API) getAlertGroupsHandler(params alertgroup_ops.GetAlertGroupsParams
443451 return alertgroup_ops .NewGetAlertGroupsOK ().WithPayload (callbackRes )
444452}
445453
454+ func (api * API ) getAlertGroupInfoListHandler (params alertgroupinfolist_ops.GetAlertGroupInfoListParams ) middleware.Responder {
455+ logger := api .requestLogger (params .HTTPRequest )
456+
457+ var receiverFilter * regexp.Regexp
458+ var err error
459+ if params .Receiver != nil {
460+ receiverFilter , err = regexp .Compile ("^(?:" + * params .Receiver + ")$" )
461+ if err != nil {
462+ level .Error (logger ).Log ("msg" , "Failed to compile receiver regex" , "err" , err )
463+ return alertgroupinfolist_ops .
464+ NewGetAlertGroupInfoListBadRequest ().
465+ WithPayload (
466+ fmt .Sprintf ("failed to parse receiver param: %v" , err .Error ()),
467+ )
468+ }
469+ }
470+
471+ rf := func (receiverFilter * regexp.Regexp ) func (r * dispatch.Route ) bool {
472+ return func (r * dispatch.Route ) bool {
473+ receiver := r .RouteOpts .Receiver
474+ if receiverFilter != nil && ! receiverFilter .MatchString (receiver ) {
475+ return false
476+ }
477+ return true
478+ }
479+ }(receiverFilter )
480+
481+ if err = validateNextToken (params .NextToken ); err != nil {
482+ level .Error (logger ).Log ("msg" , "Failed to parse NextToken parameter" , "err" , err )
483+ return alertgroupinfolist_ops .
484+ NewGetAlertGroupInfoListBadRequest ().
485+ WithPayload (
486+ fmt .Sprintf ("failed to parse NextToken param: %v" , * params .NextToken ),
487+ )
488+ }
489+
490+ if err = validateMaxResult (params .MaxResults ); err != nil {
491+ level .Error (logger ).Log ("msg" , "Failed to parse MaxResults parameter" , "err" , err )
492+ return alertgroupinfolist_ops .
493+ NewGetAlertGroupInfoListBadRequest ().
494+ WithPayload (
495+ fmt .Sprintf ("failed to parse MaxResults param: %v" , * params .MaxResults ),
496+ )
497+ }
498+
499+ ags := api .alertGroupInfos (rf )
500+ alertGroupInfos := make ([]* open_api_models.AlertGroupInfo , 0 , len (ags ))
501+ for _ , alertGroup := range ags {
502+
503+ // Skip the aggregation group if the next token is set and hasn't arrived the nextToken item yet.
504+ if params .NextToken != nil && * params .NextToken >= alertGroup .ID {
505+ continue
506+ }
507+
508+ ag := & open_api_models.AlertGroupInfo {
509+ Receiver : & open_api_models.Receiver {Name : & alertGroup .Receiver },
510+ Labels : ModelLabelSetToAPILabelSet (alertGroup .Labels ),
511+ ID : & alertGroup .ID ,
512+ }
513+ alertGroupInfos = append (alertGroupInfos , ag )
514+ }
515+
516+ returnAlertGroupInfos , nextItem := AlertGroupInfoListTruncate (alertGroupInfos , params .MaxResults )
517+
518+ response := & open_api_models.AlertGroupInfoList {
519+ AlertGroupInfoList : returnAlertGroupInfos ,
520+ NextToken : nextItem ,
521+ }
522+
523+ return alertgroupinfolist_ops .NewGetAlertGroupInfoListOK ().WithPayload (response )
524+ }
525+
446526func (api * API ) alertFilter (matchers []* labels.Matcher , silenced , inhibited , active bool ) func (a * types.Alert , now time.Time ) bool {
447527 return func (a * types.Alert , now time.Time ) bool {
448528 if ! a .EndsAt .IsZero () && a .EndsAt .Before (now ) {
@@ -740,3 +820,22 @@ func getSwaggerSpec() (*loads.Document, *analysis.Spec, error) {
740820 swaggerSpecAnalysisCache = analysis .New (swaggerSpec .Spec ())
741821 return swaggerSpec , swaggerSpecAnalysisCache , nil
742822}
823+
824+ func validateMaxResult (maxItem * int64 ) error {
825+ if maxItem != nil {
826+ if * maxItem < 0 {
827+ return errors .New ("the maxItem need to be larger than or equal to 0" )
828+ }
829+ }
830+ return nil
831+ }
832+
833+ func validateNextToken (nextToken * string ) error {
834+ if nextToken != nil {
835+ match , _ := regexp .MatchString ("^[a-fA-F0-9]{40}$" , * nextToken )
836+ if ! match {
837+ return fmt .Errorf ("invalid nextToken: %s" , * nextToken )
838+ }
839+ }
840+ return nil
841+ }
0 commit comments