mirror of
https://github.com/prometheus/alertmanager
synced 2024-12-25 07:32:19 +00:00
api/v2: sort silences similarly to v1 api (#1786)
* api/v2: sort silences similarly to v1 api Sort the queried silences to match behaviour in the v1 api. Sort silences in-place instead of creating multiple slices. Use separate function for sorting silences for easier testing. Add unit test for sort order. Signed-off-by: Paul Gier <pgier@redhat.com>
This commit is contained in:
parent
c5e7dca3dc
commit
3ffe6cfdc8
@ -508,9 +508,49 @@ func (api *API) getSilencesHandler(params silence_ops.GetSilencesParams) middlew
|
||||
sils = append(sils, &silence)
|
||||
}
|
||||
|
||||
sortSilences(sils)
|
||||
|
||||
return silence_ops.NewGetSilencesOK().WithPayload(sils)
|
||||
}
|
||||
|
||||
var (
|
||||
silenceStateOrder = map[types.SilenceState]int{
|
||||
types.SilenceStateActive: 1,
|
||||
types.SilenceStatePending: 2,
|
||||
types.SilenceStateExpired: 3,
|
||||
}
|
||||
)
|
||||
|
||||
// sortSilences sorts first according to the state "active, pending, expired"
|
||||
// then by end time or start time depending on the state.
|
||||
// active silences should show the next to expire first
|
||||
// pending silences are ordered based on which one starts next
|
||||
// expired are ordered base on which one expired most recently
|
||||
func sortSilences(sils open_api_models.GettableSilences) {
|
||||
sort.Slice(sils, func(i, j int) bool {
|
||||
state1 := types.SilenceState(*sils[i].Status.State)
|
||||
state2 := types.SilenceState(*sils[j].Status.State)
|
||||
if state1 != state2 {
|
||||
return silenceStateOrder[state1] < silenceStateOrder[state2]
|
||||
}
|
||||
switch state1 {
|
||||
case types.SilenceStateActive:
|
||||
endsAt1 := time.Time(*sils[i].Silence.EndsAt)
|
||||
endsAt2 := time.Time(*sils[j].Silence.EndsAt)
|
||||
return endsAt1.Before(endsAt2)
|
||||
case types.SilenceStatePending:
|
||||
startsAt1 := time.Time(*sils[i].Silence.StartsAt)
|
||||
startsAt2 := time.Time(*sils[j].Silence.StartsAt)
|
||||
return startsAt1.Before(startsAt2)
|
||||
case types.SilenceStateExpired:
|
||||
endsAt1 := time.Time(*sils[i].Silence.EndsAt)
|
||||
endsAt2 := time.Time(*sils[j].Silence.EndsAt)
|
||||
return endsAt1.After(endsAt2)
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
func gettableSilenceMatchesFilterLabels(s open_api_models.GettableSilence, matchers []*labels.Matcher) bool {
|
||||
sms := make(map[string]string)
|
||||
for _, m := range s.Matchers {
|
||||
|
@ -14,9 +14,13 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
open_api_models "github.com/prometheus/alertmanager/api/v2/models"
|
||||
general_ops "github.com/prometheus/alertmanager/api/v2/restapi/operations/general"
|
||||
"github.com/prometheus/alertmanager/config"
|
||||
)
|
||||
@ -48,3 +52,73 @@ func TestGetStatusHandlerWithNilPeer(t *testing.T) {
|
||||
t.Fatal("expected cluster name to be empty, violating the openapi specification")
|
||||
}
|
||||
}
|
||||
|
||||
func assertEqualStrings(t *testing.T, expected string, actual string) {
|
||||
if expected != actual {
|
||||
t.Fatal("expected: ", expected, ", actual: ", actual)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
testComment = "comment"
|
||||
createdBy = "test"
|
||||
)
|
||||
|
||||
func gettableSilence(id string, state string,
|
||||
updatedAt string, start string, end string,
|
||||
) *open_api_models.GettableSilence {
|
||||
|
||||
updAt, err := strfmt.ParseDateTime(updatedAt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
strAt, err := strfmt.ParseDateTime(start)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
endAt, err := strfmt.ParseDateTime(end)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &open_api_models.GettableSilence{
|
||||
Silence: open_api_models.Silence{
|
||||
StartsAt: &strAt,
|
||||
EndsAt: &endAt,
|
||||
Comment: &testComment,
|
||||
CreatedBy: &createdBy,
|
||||
},
|
||||
ID: &id,
|
||||
UpdatedAt: &updAt,
|
||||
Status: &open_api_models.SilenceStatus{
|
||||
State: &state,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSilencesHandler(t *testing.T) {
|
||||
|
||||
updateTime := "2019-01-01T12:00:00+00:00"
|
||||
silences := []*open_api_models.GettableSilence{
|
||||
gettableSilence("silence-6-expired", "expired", updateTime,
|
||||
"2019-01-01T12:00:00+00:00", "2019-01-01T11:00:00+00:00"),
|
||||
gettableSilence("silence-1-active", "active", updateTime,
|
||||
"2019-01-01T12:00:00+00:00", "2019-01-01T13:00:00+00:00"),
|
||||
gettableSilence("silence-7-expired", "expired", updateTime,
|
||||
"2019-01-01T12:00:00+00:00", "2019-01-01T10:00:00+00:00"),
|
||||
gettableSilence("silence-5-expired", "expired", updateTime,
|
||||
"2019-01-01T12:00:00+00:00", "2019-01-01T12:00:00+00:00"),
|
||||
gettableSilence("silence-0-active", "active", updateTime,
|
||||
"2019-01-01T12:00:00+00:00", "2019-01-01T12:00:00+00:00"),
|
||||
gettableSilence("silence-4-pending", "pending", updateTime,
|
||||
"2019-01-01T13:00:00+00:00", "2019-01-01T12:00:00+00:00"),
|
||||
gettableSilence("silence-3-pending", "pending", updateTime,
|
||||
"2019-01-01T12:00:00+00:00", "2019-01-01T12:00:00+00:00"),
|
||||
gettableSilence("silence-2-active", "active", updateTime,
|
||||
"2019-01-01T12:00:00+00:00", "2019-01-01T14:00:00+00:00"),
|
||||
}
|
||||
sortSilences(open_api_models.GettableSilences(silences))
|
||||
|
||||
for i, sil := range silences {
|
||||
assertEqualStrings(t, "silence-"+strconv.Itoa(i)+"-"+*sil.Status.State, *sil.ID)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user