From acee83171a1d5297df66854a71564d0554260162 Mon Sep 17 00:00:00 2001 From: Chris Battarbee Date: Thu, 4 Apr 2024 14:52:14 +0100 Subject: [PATCH] Add query parameter to only search for incidents of a specific severity --- apiserver/internal/server/incidents.go | 32 ++++++++++++++++++++++++-- common/api/api.go | 20 ++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/apiserver/internal/server/incidents.go b/apiserver/internal/server/incidents.go index fe7f363..099c384 100644 --- a/apiserver/internal/server/incidents.go +++ b/apiserver/internal/server/incidents.go @@ -10,6 +10,7 @@ import ( "net/http" "sort" "strconv" + "strings" ) type IncidentsResponse struct { @@ -19,6 +20,7 @@ type IncidentsResponse struct { // incidents is a handler for the /incidents endpoint. // It has a required query parameter of statusPageUrl +// It has an optional query parameter of impact (default is all), which is an array of impacts e.g. impact=critical,major,minor,none to exclude maintenance func (s *Server) incidents(context *gin.Context) { ctx := context.Request.Context() statusPageUrl := context.Query("statusPageUrl") @@ -27,6 +29,20 @@ func (s *Server) incidents(context *gin.Context) { return } + impactQuery := context.Query("impact") + var impacts []api.Impact + if impactQuery != "" { + impactsStr := strings.Split(impactQuery, ",") + for _, impactStr := range impactsStr { + impact, err := api.ParseImpact(impactStr) + if err != nil { + context.JSON(http.StatusBadRequest, gin.H{"error": "invalid impact"}) + return + } + impacts = append(impacts, impact) + } + } + var limit *int = nil if limitStr := context.Query("limit"); limitStr != "" { limitInt, err := strconv.Atoi(limitStr) @@ -56,7 +72,7 @@ func (s *Server) incidents(context *gin.Context) { } // Attempt to get the incidents from the cache - incidents, found, err := s.getIncidentsFromCache(ctx, statusPageUrl) + incidents, found, err := s.getIncidentsFromCache(ctx, statusPageUrl, impacts) if err != nil { s.logger.Error("failed to get incidents from cache", zap.Error(err)) context.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get incidents from cache"}) @@ -100,7 +116,7 @@ func sortIncidentsDescending(incidents []api.Incident) { // getIncidentsFromCache attempts to get the incidents from the cache. // If the incidents are found in the cache, it returns them. // If the incidents are not found in the cache, it returns false for the second return value. -func (s *Server) getIncidentsFromCache(ctx context.Context, statusPageUrl string) ([]api.Incident, bool, error) { +func (s *Server) getIncidentsFromCache(ctx context.Context, statusPageUrl string, impacts []api.Impact) ([]api.Incident, bool, error) { incidents, found := s.incidentCache.Get(statusPageUrl) if !found { return nil, false, nil @@ -111,6 +127,18 @@ func (s *Server) getIncidentsFromCache(ctx context.Context, statusPageUrl string return nil, false, errors.New("failed to cast incidents to []api.Incident") } + if len(impacts) > 0 { + var filteredIncidents []api.Incident + for _, incident := range incidentsCasted { + for _, impact := range impacts { + if incident.Impact == impact { + filteredIncidents = append(filteredIncidents, incident) + } + } + } + incidentsCasted = filteredIncidents + } + return incidentsCasted, true, nil } diff --git a/common/api/api.go b/common/api/api.go index 857a28d..0f224b9 100644 --- a/common/api/api.go +++ b/common/api/api.go @@ -3,6 +3,7 @@ package api import ( "database/sql/driver" "encoding/json" + "github.com/pkg/errors" "time" ) @@ -16,6 +17,25 @@ const ( ImpactNone Impact = "none" ) +var ErrInvalidImpact = errors.New("invalid impact") + +func ParseImpact(impact string) (Impact, error) { + switch impact { + case "minor": + return ImpactMinor, nil + case "major": + return ImpactMajor, nil + case "critical": + return ImpactCritical, nil + case "maintenance": + return ImpactMaintenance, nil + case "none": + return ImpactNone, nil + default: + return "", ErrInvalidImpact + } +} + type IncidentEventArray []IncidentEvent func (sla *IncidentEventArray) Scan(src interface{}) error {