grafana/pkg/tests/api/alerting/api_notifications_time_interval_test.go
Yuri Tseretyan d1073deefd
Alerting: Time intervals API (read only endpoints) (#81672)
* declare new API and models GettableTimeIntervals, PostableTimeIntervals
* add new actions alert.notifications.time-intervals:read and alert.notifications.time-intervals:write.
* update existing alerting roles with the read action. Add to all alerting roles.
* add integration tests
2024-02-01 15:17:13 -05:00

205 lines
6.0 KiB
Go

package alerting
import (
"net/http"
"slices"
"strings"
"testing"
"time"
"github.com/prometheus/alertmanager/config"
"github.com/prometheus/alertmanager/timeinterval"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
"github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/tests/testinfra"
"github.com/grafana/grafana/pkg/util"
)
func TestTimeInterval(t *testing.T) {
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
DisableLegacyAlerting: true,
EnableUnifiedAlerting: true,
DisableAnonymous: true,
AppModeProduction: true,
})
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
createUser(t, store, user.CreateUserCommand{
DefaultOrgRole: string(org.RoleAdmin),
Password: "admin",
Login: "admin",
})
apiClient := newAlertingApiClient(grafanaListedAddr, "admin", "admin")
t.Run("default config should return empty list", func(t *testing.T) {
mt, status, body := apiClient.GetAllTimeIntervalsWithStatus(t)
requireStatusCode(t, http.StatusOK, status, body)
require.Empty(t, mt)
})
emptyTimeInterval := definitions.PostableTimeIntervals{
Name: "Empty Mute Timing",
TimeIntervals: []definitions.TimeIntervalItem{},
}
func() {
// TODO replace with Time-Interval later
emptyMuteTiming := definitions.MuteTimeInterval{
MuteTimeInterval: config.MuteTimeInterval{
Name: "Empty Mute Timing",
TimeIntervals: []timeinterval.TimeInterval{},
},
}
// TODO replace with create interval API
// t.Run("should create a new mute timing without any intervals", func(t *testing.T) {
mt, status, body := apiClient.CreateMuteTimingWithStatus(t, emptyMuteTiming)
requireStatusCode(t, http.StatusCreated, status, body)
require.Equal(t, emptyMuteTiming.MuteTimeInterval, mt.MuteTimeInterval)
require.EqualValues(t, models.ProvenanceAPI, mt.Provenance)
// })
anotherMuteTiming := definitions.MuteTimeInterval{
MuteTimeInterval: config.MuteTimeInterval{
Name: "Not Empty Mute Timing",
TimeIntervals: []timeinterval.TimeInterval{
{
Times: []timeinterval.TimeRange{
{
StartMinute: 10,
EndMinute: 45,
},
},
Weekdays: []timeinterval.WeekdayRange{
{
InclusiveRange: timeinterval.InclusiveRange{
Begin: 0,
End: 2,
},
},
{
InclusiveRange: timeinterval.InclusiveRange{
Begin: 4,
End: 5,
},
},
},
DaysOfMonth: []timeinterval.DayOfMonthRange{
{
InclusiveRange: timeinterval.InclusiveRange{
Begin: 1,
End: 7,
},
},
{
InclusiveRange: timeinterval.InclusiveRange{
Begin: 14,
End: 28,
},
},
},
Months: []timeinterval.MonthRange{
{
InclusiveRange: timeinterval.InclusiveRange{
Begin: 1,
End: 5,
},
},
},
Years: []timeinterval.YearRange{
{
InclusiveRange: timeinterval.InclusiveRange{
Begin: 2024,
End: 2025,
},
},
},
Location: &timeinterval.Location{
Location: time.UTC,
},
},
},
},
}
// t.Run("should create a new mute timing with some settings", func(t *testing.T) {
mt, status, body = apiClient.CreateMuteTimingWithStatus(t, anotherMuteTiming)
requireStatusCode(t, http.StatusCreated, status, body)
require.Equal(t, anotherMuteTiming.MuteTimeInterval, mt.MuteTimeInterval)
require.EqualValues(t, models.ProvenanceAPI, mt.Provenance)
// })
}()
anotherTimeInterval := definitions.PostableTimeIntervals{
Name: "Not Empty Mute Timing",
TimeIntervals: []definitions.TimeIntervalItem{
{
Times: []definitions.TimeIntervalTimeRange{
{
StartMinute: "00:10",
EndMinute: "00:45",
},
},
Weekdays: util.Pointer([]string{
"sunday:tuesday",
"thursday:friday",
}),
DaysOfMonth: util.Pointer([]string{
"1:7",
"14:28",
}),
Months: util.Pointer([]string{
"1:5",
}),
Years: util.Pointer([]string{
"2024:2025",
}),
Location: util.Pointer("UTC"),
},
},
}
t.Run("should return time interval by name", func(t *testing.T) {
ti, status, body := apiClient.GetTimeIntervalByNameWithStatus(t, emptyTimeInterval.Name)
requireStatusCode(t, http.StatusOK, status, body)
require.Equal(t, emptyTimeInterval.TimeIntervals, ti.TimeIntervals)
require.Equal(t, emptyTimeInterval.Name, ti.Name)
require.EqualValues(t, models.ProvenanceAPI, ti.Provenance)
ti, status, body = apiClient.GetTimeIntervalByNameWithStatus(t, anotherTimeInterval.Name)
requireStatusCode(t, http.StatusOK, status, body)
require.Equal(t, anotherTimeInterval.TimeIntervals, ti.TimeIntervals)
require.Equal(t, anotherTimeInterval.Name, ti.Name)
require.EqualValues(t, models.ProvenanceAPI, ti.Provenance)
})
t.Run("should return NotFound if time interval does not exist", func(t *testing.T) {
_, status, body := apiClient.GetTimeIntervalByNameWithStatus(t, "some-missing-timing")
requireStatusCode(t, http.StatusNotFound, status, body)
})
t.Run("should return all mute timings", func(t *testing.T) {
mt, status, body := apiClient.GetAllTimeIntervalsWithStatus(t)
requireStatusCode(t, http.StatusOK, status, body)
require.Len(t, mt, 2)
slices.SortFunc(mt, func(a, b definitions.GettableTimeIntervals) int {
return strings.Compare(a.Name, b.Name)
})
require.Equal(t, emptyTimeInterval.TimeIntervals, mt[0].TimeIntervals)
require.Equal(t, emptyTimeInterval.Name, mt[0].Name)
require.EqualValues(t, models.ProvenanceAPI, mt[0].Provenance)
require.Equal(t, anotherTimeInterval.TimeIntervals, mt[1].TimeIntervals)
require.Equal(t, anotherTimeInterval.Name, mt[1].Name)
require.EqualValues(t, models.ProvenanceAPI, mt[1].Provenance)
})
}