@@ -23,7 +23,10 @@ import (
2323 "strconv"
2424 "testing"
2525 "time"
26-
26+ "github.com/prometheus/alertmanager/dispatch"
27+ alert_ops "github.com/prometheus/alertmanager/api/v2/restapi/operations/alert"
28+ alertgroup_ops "github.com/prometheus/alertmanager/api/v2/restapi/operations/alertgroup"
29+ "github.com/prometheus/alertmanager/util/callback"
2730 "github.com/go-openapi/runtime"
2831 "github.com/go-openapi/runtime/middleware"
2932 "github.com/go-openapi/strfmt"
@@ -584,3 +587,222 @@ receivers:
584587 require .Equal (t , tc .body , string (body ))
585588 }
586589}
590+
591+ func TestListAlertsHandler (t * testing.T ) {
592+ now := time .Now ()
593+ alerts := []* types.Alert {
594+ {
595+ Alert : model.Alert {
596+ Labels : model.LabelSet {"alertname" : "alert1" },
597+ StartsAt : now .Add (- time .Minute ),
598+ },
599+ },
600+ {
601+ Alert : model.Alert {
602+ Labels : model.LabelSet {"alertname" : "alert2" },
603+ StartsAt : now .Add (- time .Minute ),
604+ },
605+ },
606+ {
607+ Alert : model.Alert {
608+ Labels : model.LabelSet {"alertname" : "alert3" },
609+ StartsAt : now .Add (- time .Minute ),
610+ },
611+ },
612+ {
613+ Alert : model.Alert {
614+ Labels : model.LabelSet {"alertname" : "alert4" },
615+ StartsAt : now .Add (- time .Minute ),
616+ },
617+ },
618+ {
619+ Alert : model.Alert {
620+ Labels : model.LabelSet {"alertname" : "alert5" },
621+ StartsAt : now .Add (- time .Minute ),
622+ },
623+ },
624+ }
625+
626+ for _ , tc := range []struct {
627+ name string
628+ expectedCode int
629+ anames []string
630+ callback callback.Callback
631+ }{
632+ {
633+ "no call back" ,
634+ 200 ,
635+ []string {"alert3" , "alert2" , "alert1" , "alert5" , "alert4" },
636+ callback.NoopAPICallback {},
637+ },
638+ {
639+ "callback: only return 1 alert" ,
640+ 200 ,
641+ []string {"alert3" },
642+ limitNumberOfAlertsReturnedCallback {limit : 1 },
643+ },
644+ {
645+ "callback: only return 3 alert" ,
646+ 200 ,
647+ []string {"alert3" , "alert2" , "alert1" },
648+ limitNumberOfAlertsReturnedCallback {limit : 3 },
649+ },
650+ } {
651+ t .Run (tc .name , func (t * testing.T ) {
652+ alertsProvider := newFakeAlerts (alerts )
653+ api := API {
654+ uptime : time .Now (),
655+ getAlertStatus : getAlertStatus ,
656+ logger : log .NewNopLogger (),
657+ apiCallback : tc .callback ,
658+ alerts : alertsProvider ,
659+ setAlertStatus : func (model.LabelSet ) {},
660+ }
661+ api .route = dispatch .NewRoute (& config.Route {Receiver : "def-receiver" }, nil )
662+ r , err := http .NewRequest ("GET" , "/api/v2/alerts" , nil )
663+ require .NoError (t , err )
664+
665+ w := httptest .NewRecorder ()
666+ p := runtime .TextProducer ()
667+ silence := false
668+ inhibited := false
669+ active := true
670+ responder := api .getAlertsHandler (alert_ops.GetAlertsParams {
671+ HTTPRequest : r ,
672+ Silenced : & silence ,
673+ Inhibited : & inhibited ,
674+ Active : & active ,
675+ })
676+ responder .WriteResponse (w , p )
677+ body , _ := io .ReadAll (w .Result ().Body )
678+
679+ require .Equal (t , tc .expectedCode , w .Code )
680+ retAlerts := open_api_models.GettableAlerts {}
681+ err = json .Unmarshal (body , & retAlerts )
682+ if err != nil {
683+ t .Fatalf ("Unexpected error %v" , err )
684+ }
685+ anames := []string {}
686+ for _ , a := range retAlerts {
687+ name , ok := a .Labels ["alertname" ]
688+ if ok {
689+ anames = append (anames , string (name ))
690+ }
691+ }
692+ require .Equal (t , tc .anames , anames )
693+ })
694+ }
695+ }
696+
697+ func TestGetAlertGroupsHandler (t * testing.T ) {
698+ var startAt time.Time
699+ alerts := []* types.Alert {
700+ {
701+ Alert : model.Alert {
702+ Labels : model.LabelSet {"state" : "active" , "alertname" : "alert1" },
703+ StartsAt : startAt ,
704+ },
705+ },
706+ {
707+ Alert : model.Alert {
708+ Labels : model.LabelSet {"state" : "unprocessed" , "alertname" : "alert2" },
709+ StartsAt : startAt ,
710+ },
711+ },
712+ }
713+ aginfos := dispatch.AlertGroups {
714+ & dispatch.AlertGroup {
715+ Labels : model.LabelSet {
716+ "alertname" : "TestingAlert" ,
717+ },
718+ Receiver : "testing" ,
719+ Alerts : alerts [:1 ],
720+ },
721+ & dispatch.AlertGroup {
722+ Labels : model.LabelSet {
723+ "alertname" : "HighErrorRate" ,
724+ },
725+ Receiver : "prod" ,
726+ Alerts : alerts [:2 ],
727+ },
728+ }
729+ for _ , tc := range []struct {
730+ name string
731+ numberOfAG int
732+ expectedCode int
733+ callback callback.Callback
734+ }{
735+ {
736+ "no call back" ,
737+ 2 ,
738+ 200 ,
739+ callback.NoopAPICallback {},
740+ },
741+ {
742+ "callback: only return 1 alert group" ,
743+ 1 ,
744+ 200 ,
745+ limitNumberOfAlertsReturnedCallback {limit : 1 },
746+ },
747+ {
748+ "callback: only return 2 alert group" ,
749+ 2 ,
750+ 200 ,
751+ limitNumberOfAlertsReturnedCallback {limit : 2 },
752+ },
753+ } {
754+ t .Run (tc .name , func (t * testing.T ) {
755+ api := API {
756+ uptime : time .Now (),
757+ alertGroups : func (func (* dispatch.Route ) bool , func (* types.Alert , time.Time ) bool ) (dispatch.AlertGroups , map [model.Fingerprint ][]string ) {
758+ return aginfos , nil
759+ },
760+ getAlertStatus : getAlertStatus ,
761+ logger : log .NewNopLogger (),
762+ apiCallback : tc .callback ,
763+ }
764+ r , err := http .NewRequest ("GET" , "/api/v2/alertgroups" , nil )
765+ require .NoError (t , err )
766+
767+ w := httptest .NewRecorder ()
768+ p := runtime .TextProducer ()
769+ silence := false
770+ inhibited := false
771+ active := true
772+ responder := api .getAlertGroupsHandler (alertgroup_ops.GetAlertGroupsParams {
773+ HTTPRequest : r ,
774+ Silenced : & silence ,
775+ Inhibited : & inhibited ,
776+ Active : & active ,
777+ })
778+ responder .WriteResponse (w , p )
779+ body , _ := io .ReadAll (w .Result ().Body )
780+
781+ require .Equal (t , tc .expectedCode , w .Code )
782+ retAlertGroups := open_api_models.AlertGroups {}
783+ err = json .Unmarshal (body , & retAlertGroups )
784+ if err != nil {
785+ t .Fatalf ("Unexpected error %v" , err )
786+ }
787+ require .Equal (t , tc .numberOfAG , len (retAlertGroups ))
788+ })
789+ }
790+ }
791+
792+ type limitNumberOfAlertsReturnedCallback struct {
793+ limit int
794+ }
795+
796+ func (n limitNumberOfAlertsReturnedCallback ) V2GetAlertsCallback (alerts open_api_models.GettableAlerts ) (open_api_models.GettableAlerts , error ) {
797+ return alerts [:n .limit ], nil
798+ }
799+
800+ func (n limitNumberOfAlertsReturnedCallback ) V2GetAlertGroupsCallback (alertgroups open_api_models.AlertGroups ) (open_api_models.AlertGroups , error ) {
801+ return alertgroups [:n .limit ], nil
802+ }
803+
804+ func getAlertStatus (model.Fingerprint ) types.AlertStatus {
805+ status := types.AlertStatus {SilencedBy : []string {}, InhibitedBy : []string {}}
806+ status .State = types .AlertStateActive
807+ return status
808+ }
0 commit comments