@@ -32,6 +32,8 @@ import (
3232 "github.com/prometheus/common/version"
3333 "github.com/rs/cors"
3434
35+ alertgroupinfolist_ops "github.com/prometheus/alertmanager/api/v2/restapi/operations/alertgroupinfolist"
36+
3537 "github.com/prometheus/alertmanager/api/metrics"
3638 open_api_models "github.com/prometheus/alertmanager/api/v2/models"
3739 "github.com/prometheus/alertmanager/api/v2/restapi"
@@ -55,14 +57,15 @@ import (
5557
5658// API represents an Alertmanager API v2.
5759type API struct {
58- peer cluster.ClusterPeer
59- silences * silence.Silences
60- alerts provider.Alerts
61- alertGroups groupsFn
62- getAlertStatus getAlertStatusFn
63- groupMutedFunc groupMutedFunc
64- apiCallback callback.Callback
65- 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+ groupMutedFunc groupMutedFunc
67+ apiCallback callback.Callback
68+ uptime time.Time
6669
6770 // mtx protects alertmanagerConfig, setAlertStatus and route.
6871 mtx sync.RWMutex
@@ -81,6 +84,7 @@ type API struct {
8184type (
8285 groupsFn func (func (* dispatch.Route ) bool , func (* types.Alert , time.Time ) bool ) (dispatch.AlertGroups , map [prometheus_model.Fingerprint ][]string )
8386 groupMutedFunc func (routeID , groupKey string ) ([]string , bool )
87+ groupInfosFn func (func (* dispatch.Route ) bool ) dispatch.AlertGroupInfos
8488 getAlertStatusFn func (prometheus_model.Fingerprint ) types.AlertStatus
8589 setAlertStatusFn func (prometheus_model.LabelSet )
8690)
8993func NewAPI (
9094 alerts provider.Alerts ,
9195 gf groupsFn ,
96+ gif groupInfosFn ,
9297 asf getAlertStatusFn ,
9398 gmf groupMutedFunc ,
9499 silences * silence.Silences ,
@@ -101,16 +106,17 @@ func NewAPI(
101106 apiCallback = callback.NoopAPICallback {}
102107 }
103108 api := API {
104- alerts : alerts ,
105- getAlertStatus : asf ,
106- alertGroups : gf ,
107- groupMutedFunc : gmf ,
108- peer : peer ,
109- silences : silences ,
110- apiCallback : apiCallback ,
111- logger : l ,
112- m : metrics .NewAlerts (r ),
113- uptime : time .Now (),
109+ alerts : alerts ,
110+ getAlertStatus : asf ,
111+ alertGroups : gf ,
112+ alertGroupInfos : gif ,
113+ groupMutedFunc : gmf ,
114+ peer : peer ,
115+ silences : silences ,
116+ apiCallback : apiCallback ,
117+ logger : l ,
118+ m : metrics .NewAlerts (r ),
119+ uptime : time .Now (),
114120 }
115121
116122 // Load embedded swagger file.
@@ -134,6 +140,7 @@ func NewAPI(
134140 openAPI .AlertGetAlertsHandler = alert_ops .GetAlertsHandlerFunc (api .getAlertsHandler )
135141 openAPI .AlertPostAlertsHandler = alert_ops .PostAlertsHandlerFunc (api .postAlertsHandler )
136142 openAPI .AlertgroupGetAlertGroupsHandler = alertgroup_ops .GetAlertGroupsHandlerFunc (api .getAlertGroupsHandler )
143+ openAPI .AlertgroupinfolistGetAlertGroupInfoListHandler = alertgroupinfolist_ops .GetAlertGroupInfoListHandlerFunc (api .getAlertGroupInfoListHandler )
137144 openAPI .GeneralGetStatusHandler = general_ops .GetStatusHandlerFunc (api .getStatusHandler )
138145 openAPI .ReceiverGetReceiversHandler = receiver_ops .GetReceiversHandlerFunc (api .getReceiversHandler )
139146 openAPI .SilenceDeleteSilenceHandler = silence_ops .DeleteSilenceHandlerFunc (api .deleteSilenceHandler )
@@ -453,6 +460,78 @@ func (api *API) getAlertGroupsHandler(params alertgroup_ops.GetAlertGroupsParams
453460 return alertgroup_ops .NewGetAlertGroupsOK ().WithPayload (callbackRes )
454461}
455462
463+ func (api * API ) getAlertGroupInfoListHandler (params alertgroupinfolist_ops.GetAlertGroupInfoListParams ) middleware.Responder {
464+ logger := api .requestLogger (params .HTTPRequest )
465+
466+ var receiverFilter * regexp.Regexp
467+ var err error
468+ if params .Receiver != nil {
469+ receiverFilter , err = regexp .Compile ("^(?:" + * params .Receiver + ")$" )
470+ if err != nil {
471+ logger .Error ("Failed to compile receiver regex" , "err" , err )
472+ return alertgroupinfolist_ops .
473+ NewGetAlertGroupInfoListBadRequest ().
474+ WithPayload (
475+ fmt .Sprintf ("failed to parse receiver param: %v" , err .Error ()),
476+ )
477+ }
478+ }
479+
480+ rf := func (receiverFilter * regexp.Regexp ) func (r * dispatch.Route ) bool {
481+ return func (r * dispatch.Route ) bool {
482+ receiver := r .RouteOpts .Receiver
483+ if receiverFilter != nil && ! receiverFilter .MatchString (receiver ) {
484+ return false
485+ }
486+ return true
487+ }
488+ }(receiverFilter )
489+
490+ if err = validateNextToken (params .NextToken ); err != nil {
491+ logger .Error ("Failed to parse NextToken parameter" , "err" , err )
492+ return alertgroupinfolist_ops .
493+ NewGetAlertGroupInfoListBadRequest ().
494+ WithPayload (
495+ fmt .Sprintf ("failed to parse NextToken param: %v" , * params .NextToken ),
496+ )
497+ }
498+
499+ if err = validateMaxResult (params .MaxResults ); err != nil {
500+ logger .Error ("Failed to parse MaxResults parameter" , "err" , err )
501+ return alertgroupinfolist_ops .
502+ NewGetAlertGroupInfoListBadRequest ().
503+ WithPayload (
504+ fmt .Sprintf ("failed to parse MaxResults param: %v" , * params .MaxResults ),
505+ )
506+ }
507+
508+ ags := api .alertGroupInfos (rf )
509+ alertGroupInfos := make ([]* open_api_models.AlertGroupInfo , 0 , len (ags ))
510+ for _ , alertGroup := range ags {
511+
512+ // Skip the aggregation group if the next token is set and hasn't arrived the nextToken item yet.
513+ if params .NextToken != nil && * params .NextToken >= alertGroup .ID {
514+ continue
515+ }
516+
517+ ag := & open_api_models.AlertGroupInfo {
518+ Receiver : & open_api_models.Receiver {Name : & alertGroup .Receiver },
519+ Labels : ModelLabelSetToAPILabelSet (alertGroup .Labels ),
520+ ID : & alertGroup .ID ,
521+ }
522+ alertGroupInfos = append (alertGroupInfos , ag )
523+ }
524+
525+ returnAlertGroupInfos , nextItem := AlertGroupInfoListTruncate (alertGroupInfos , params .MaxResults )
526+
527+ response := & open_api_models.AlertGroupInfoList {
528+ AlertGroupInfoList : returnAlertGroupInfos ,
529+ NextToken : nextItem ,
530+ }
531+
532+ return alertgroupinfolist_ops .NewGetAlertGroupInfoListOK ().WithPayload (response )
533+ }
534+
456535func (api * API ) alertFilter (matchers []* labels.Matcher , silenced , inhibited , active bool ) func (a * types.Alert , now time.Time ) bool {
457536 return func (a * types.Alert , now time.Time ) bool {
458537 if ! a .EndsAt .IsZero () && a .EndsAt .Before (now ) {
@@ -742,3 +821,22 @@ func getSwaggerSpec() (*loads.Document, *analysis.Spec, error) {
742821 swaggerSpecAnalysisCache = analysis .New (swaggerSpec .Spec ())
743822 return swaggerSpec , swaggerSpecAnalysisCache , nil
744823}
824+
825+ func validateMaxResult (maxItem * int64 ) error {
826+ if maxItem != nil {
827+ if * maxItem < 0 {
828+ return errors .New ("the maxItem need to be larger than or equal to 0" )
829+ }
830+ }
831+ return nil
832+ }
833+
834+ func validateNextToken (nextToken * string ) error {
835+ if nextToken != nil {
836+ match , _ := regexp .MatchString ("^[a-fA-F0-9]{40}$" , * nextToken )
837+ if ! match {
838+ return fmt .Errorf ("invalid nextToken: %s" , * nextToken )
839+ }
840+ }
841+ return nil
842+ }
0 commit comments