Alerting: Remove transitional notifications API endpoints (#102713)
* Remove transitional notifications API endpoints * Fix openapi spec * Fix path test * Remove API tests related to removed endpoints
This commit is contained in:
@@ -181,12 +181,6 @@ func (api *API) RegisterAPIEndpoints(m *metrics.API) {
|
||||
hist: api.Historian,
|
||||
}), m)
|
||||
|
||||
api.RegisterNotificationsApiEndpoints(NewNotificationsApi(&NotificationSrv{
|
||||
logger: logger,
|
||||
receiverService: api.ReceiverService,
|
||||
muteTimingService: api.MuteTimings,
|
||||
}), m)
|
||||
|
||||
if api.FeatureManager.IsEnabledGlobally(featuremgmt.FlagAlertingConversionAPI) {
|
||||
api.RegisterConvertPrometheusApiEndpoints(NewConvertPrometheusApi(
|
||||
NewConvertPrometheusSrv(
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
. "github.com/grafana/grafana/pkg/services/ngalert/api/compat"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
)
|
||||
|
||||
type NotificationSrv struct {
|
||||
logger log.Logger
|
||||
receiverService ReceiverService
|
||||
muteTimingService MuteTimingService // defined in api_provisioning.go
|
||||
}
|
||||
|
||||
type ReceiverService interface {
|
||||
GetReceiver(ctx context.Context, q models.GetReceiverQuery, u identity.Requester) (*models.Receiver, error)
|
||||
ListReceivers(ctx context.Context, q models.ListReceiversQuery, user identity.Requester) ([]*models.Receiver, error)
|
||||
}
|
||||
|
||||
func (srv *NotificationSrv) RouteGetTimeInterval(c *contextmodel.ReqContext, name string) response.Response {
|
||||
muteTimeInterval, err := srv.muteTimingService.GetMuteTiming(c.Req.Context(), name, c.OrgID)
|
||||
if err != nil {
|
||||
return errorToResponse(err)
|
||||
}
|
||||
return response.JSON(http.StatusOK, muteTimeInterval) // TODO convert to timing interval
|
||||
}
|
||||
|
||||
func (srv *NotificationSrv) RouteGetTimeIntervals(c *contextmodel.ReqContext) response.Response {
|
||||
muteTimeIntervals, err := srv.muteTimingService.GetMuteTimings(c.Req.Context(), c.OrgID)
|
||||
if err != nil {
|
||||
return errorToResponse(err)
|
||||
}
|
||||
return response.JSON(http.StatusOK, muteTimeIntervals) // TODO convert to timing interval
|
||||
}
|
||||
|
||||
func (srv *NotificationSrv) RouteGetReceiver(c *contextmodel.ReqContext, name string) response.Response {
|
||||
q := models.GetReceiverQuery{
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
Name: name,
|
||||
Decrypt: c.QueryBool("decrypt"),
|
||||
}
|
||||
|
||||
receiver, err := srv.receiverService.GetReceiver(c.Req.Context(), q, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.ErrOrFallback(http.StatusInternalServerError, "failed to get receiver", err)
|
||||
}
|
||||
|
||||
gettable, err := GettableApiReceiverFromReceiver(receiver)
|
||||
if err != nil {
|
||||
return response.ErrOrFallback(http.StatusInternalServerError, "failed to convert receiver", err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, gettable)
|
||||
}
|
||||
|
||||
func (srv *NotificationSrv) RouteGetReceivers(c *contextmodel.ReqContext) response.Response {
|
||||
q := models.ListReceiversQuery{
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
Names: c.QueryStrings("names"),
|
||||
Limit: c.QueryInt("limit"),
|
||||
Offset: c.QueryInt("offset"),
|
||||
}
|
||||
|
||||
receivers, err := srv.receiverService.ListReceivers(c.Req.Context(), q, c.SignedInUser)
|
||||
if err != nil {
|
||||
return response.ErrOrFallback(http.StatusInternalServerError, "failed to get receiver groups", err)
|
||||
}
|
||||
|
||||
gettables, err := GettableApiReceiversFromReceivers(receivers)
|
||||
if err != nil {
|
||||
return response.ErrOrFallback(http.StatusInternalServerError, "failed to convert receivers", err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, gettables)
|
||||
}
|
||||
@@ -1,409 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/log/logtest"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
ac "github.com/grafana/grafana/pkg/services/ngalert/accesscontrol"
|
||||
. "github.com/grafana/grafana/pkg/services/ngalert/api/compat"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/notifier"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/notifier/legacy_storage"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/tests/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRouteGetReceiver(t *testing.T) {
|
||||
fakeReceiverSvc := fakes.NewFakeReceiverService()
|
||||
|
||||
t.Run("returns expected model", func(t *testing.T) {
|
||||
expected := &models.Receiver{
|
||||
Name: "receiver1",
|
||||
Integrations: []*models.Integration{
|
||||
{
|
||||
UID: "uid1",
|
||||
Name: "receiver1",
|
||||
Config: models.IntegrationConfig{Type: "slack"},
|
||||
},
|
||||
},
|
||||
}
|
||||
fakeReceiverSvc.GetReceiverFn = func(ctx context.Context, q models.GetReceiverQuery, u identity.Requester) (*models.Receiver, error) {
|
||||
return expected, nil
|
||||
}
|
||||
handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc))
|
||||
rc := testReqCtx("GET")
|
||||
resp := handler.handleRouteGetReceiver(&rc, "receiver1")
|
||||
require.Equal(t, http.StatusOK, resp.Status())
|
||||
gettables, err := GettableApiReceiverFromReceiver(expected)
|
||||
require.NoError(t, err)
|
||||
json, err := json.Marshal(gettables)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, json, resp.Body())
|
||||
})
|
||||
|
||||
t.Run("builds query from request context and url param", func(t *testing.T) {
|
||||
fakeReceiverSvc.GetReceiverFn = func(ctx context.Context, q models.GetReceiverQuery, u identity.Requester) (*models.Receiver, error) {
|
||||
return &models.Receiver{}, nil
|
||||
}
|
||||
handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc))
|
||||
rc := testReqCtx("GET")
|
||||
rc.Context.Req.Form.Set("decrypt", "true")
|
||||
resp := handler.handleRouteGetReceiver(&rc, "receiver1")
|
||||
require.Equal(t, http.StatusOK, resp.Status())
|
||||
|
||||
call := fakeReceiverSvc.PopMethodCall()
|
||||
require.Equal(t, "GetReceiver", call.Method)
|
||||
expectedQ := models.GetReceiverQuery{
|
||||
Name: "receiver1",
|
||||
Decrypt: true,
|
||||
OrgID: 1,
|
||||
}
|
||||
require.Equal(t, expectedQ, call.Args[1])
|
||||
})
|
||||
|
||||
t.Run("should pass along not found response", func(t *testing.T) {
|
||||
fakeReceiverSvc.GetReceiverFn = func(ctx context.Context, q models.GetReceiverQuery, u identity.Requester) (*models.Receiver, error) {
|
||||
return nil, legacy_storage.ErrReceiverNotFound.Errorf("")
|
||||
}
|
||||
handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc))
|
||||
rc := testReqCtx("GET")
|
||||
resp := handler.handleRouteGetReceiver(&rc, "receiver1")
|
||||
require.Equal(t, http.StatusNotFound, resp.Status())
|
||||
})
|
||||
|
||||
t.Run("should pass along permission denied response", func(t *testing.T) {
|
||||
fakeReceiverSvc.GetReceiverFn = func(ctx context.Context, q models.GetReceiverQuery, u identity.Requester) (*models.Receiver, error) {
|
||||
return nil, ac.ErrAuthorizationBase.Errorf("")
|
||||
}
|
||||
handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc))
|
||||
rc := testReqCtx("GET")
|
||||
resp := handler.handleRouteGetReceiver(&rc, "receiver1")
|
||||
require.Equal(t, http.StatusForbidden, resp.Status())
|
||||
})
|
||||
}
|
||||
|
||||
func TestRouteGetReceivers(t *testing.T) {
|
||||
fakeReceiverSvc := fakes.NewFakeReceiverService()
|
||||
|
||||
t.Run("returns expected model", func(t *testing.T) {
|
||||
expected := []*models.Receiver{
|
||||
{
|
||||
Name: "receiver1",
|
||||
Integrations: []*models.Integration{
|
||||
{
|
||||
UID: "uid1",
|
||||
Name: "receiver1",
|
||||
Config: models.IntegrationConfig{Type: "slack"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
fakeReceiverSvc.ListReceiversFn = func(ctx context.Context, q models.ListReceiversQuery, u identity.Requester) ([]*models.Receiver, error) {
|
||||
return expected, nil
|
||||
}
|
||||
handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc))
|
||||
rc := testReqCtx("GET")
|
||||
rc.Context.Req.Form.Set("names", "receiver1")
|
||||
resp := handler.handleRouteGetReceivers(&rc)
|
||||
require.Equal(t, http.StatusOK, resp.Status())
|
||||
gettables, err := GettableApiReceiversFromReceivers(expected)
|
||||
require.NoError(t, err)
|
||||
jsonBody, err := json.Marshal(gettables)
|
||||
require.NoError(t, err)
|
||||
require.JSONEq(t, string(jsonBody), string(resp.Body()))
|
||||
})
|
||||
|
||||
t.Run("builds query from request context", func(t *testing.T) {
|
||||
fakeReceiverSvc.ListReceiversFn = func(ctx context.Context, q models.ListReceiversQuery, u identity.Requester) ([]*models.Receiver, error) {
|
||||
return nil, nil
|
||||
}
|
||||
handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc))
|
||||
rc := testReqCtx("GET")
|
||||
rc.Context.Req.Form.Set("names", "receiver1")
|
||||
rc.Context.Req.Form.Add("names", "receiver2")
|
||||
rc.Context.Req.Form.Set("limit", "1")
|
||||
rc.Context.Req.Form.Set("offset", "2")
|
||||
rc.Context.Req.Form.Set("decrypt", "true")
|
||||
resp := handler.handleRouteGetReceivers(&rc)
|
||||
require.Equal(t, http.StatusOK, resp.Status())
|
||||
|
||||
call := fakeReceiverSvc.PopMethodCall()
|
||||
require.Equal(t, "ListReceivers", call.Method)
|
||||
expectedQ := models.ListReceiversQuery{
|
||||
Names: []string{"receiver1", "receiver2"},
|
||||
Limit: 1,
|
||||
Offset: 2,
|
||||
OrgID: 1,
|
||||
}
|
||||
require.Equal(t, expectedQ, call.Args[1])
|
||||
})
|
||||
|
||||
t.Run("should pass along permission denied response", func(t *testing.T) {
|
||||
fakeReceiverSvc.ListReceiversFn = func(ctx context.Context, q models.ListReceiversQuery, u identity.Requester) ([]*models.Receiver, error) {
|
||||
return nil, ac.ErrAuthorizationBase.Errorf("")
|
||||
}
|
||||
handler := NewNotificationsApi(newNotificationSrv(fakeReceiverSvc))
|
||||
rc := testReqCtx("GET")
|
||||
resp := handler.handleRouteGetReceivers(&rc)
|
||||
require.Equal(t, http.StatusForbidden, resp.Status())
|
||||
})
|
||||
}
|
||||
|
||||
func TestRouteGetReceiversResponses(t *testing.T) {
|
||||
createTestEnv := func(t *testing.T, testConfig string) testEnvironment {
|
||||
env := createTestEnv(t, testConfig)
|
||||
env.ac = &recordingAccessControlFake{
|
||||
Callback: func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) {
|
||||
if strings.Contains(evaluator.String(), accesscontrol.ActionAlertingNotificationsRead) {
|
||||
return true, nil
|
||||
}
|
||||
if strings.Contains(evaluator.String(), accesscontrol.ActionAlertingReceiversList) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
},
|
||||
}
|
||||
return env
|
||||
}
|
||||
|
||||
t.Run("list receivers", func(t *testing.T) {
|
||||
t.Run("GET returns 200", func(t *testing.T) {
|
||||
env := createTestEnv(t, testConfig)
|
||||
sut := createNotificationSrvSutFromEnv(t, &env)
|
||||
rc := createTestRequestCtx()
|
||||
|
||||
response := sut.RouteGetReceivers(&rc)
|
||||
|
||||
require.Equal(t, 200, response.Status())
|
||||
})
|
||||
|
||||
t.Run("json body content is as expected", func(t *testing.T) {
|
||||
expectedListResponse := `[{"name":"grafana-default-email","grafana_managed_receiver_configs":[{"uid":"ad95bd8a-49ed-4adc-bf89-1b444fa1aa5b","name":"grafana-default-email","type":"email","disableResolveMessage":false,"secureFields":{}}]},{"name":"multiple integrations","grafana_managed_receiver_configs":[{"uid":"c2090fda-f824-4add-b545-5a4d5c2ef082","name":"multiple integrations","type":"prometheus-alertmanager","disableResolveMessage":false,"secureFields":{}},{"uid":"c84539ec-f87e-4fc5-9a91-7a687d34bbd1","name":"multiple integrations","type":"discord","disableResolveMessage":false,"secureFields":{}}]},{"name":"pagerduty test","grafana_managed_receiver_configs":[{"uid":"b9bf06f8-bde2-4438-9d4a-bba0522dcd4d","name":"pagerduty test","type":"pagerduty","disableResolveMessage":false,"secureFields":{}}]},{"name":"slack test","grafana_managed_receiver_configs":[{"uid":"cbfd0976-8228-4126-b672-4419f30a9e50","name":"slack test","type":"slack","disableResolveMessage":false,"secureFields":{}}]}]`
|
||||
t.Run("limit offset", func(t *testing.T) {
|
||||
env := createTestEnv(t, testContactPointConfig)
|
||||
sut := createNotificationSrvSutFromEnv(t, &env)
|
||||
rc := createTestRequestCtx()
|
||||
|
||||
rc.Context.Req.Header.Add("Accept", "application/json")
|
||||
rc.Context.Req.Form.Set("decrypt", "false")
|
||||
|
||||
var expected []definitions.GettableApiReceiver
|
||||
err := json.Unmarshal([]byte(expectedListResponse), &expected)
|
||||
require.NoError(t, err)
|
||||
type testcase struct {
|
||||
limit int
|
||||
offset int
|
||||
expected []definitions.GettableApiReceiver
|
||||
}
|
||||
testcases := []testcase{
|
||||
{limit: 1, offset: 0, expected: expected[:1]},
|
||||
{limit: 2, offset: 0, expected: expected[:2]},
|
||||
{limit: 4, offset: 0, expected: expected[:4]},
|
||||
{limit: 1, offset: 1, expected: expected[1:2]},
|
||||
{limit: 2, offset: 2, expected: expected[2:4]},
|
||||
{limit: 2, offset: 99, expected: []definitions.GettableApiReceiver{}},
|
||||
{limit: 0, offset: 0, expected: expected},
|
||||
{limit: 0, offset: 1, expected: expected[1:]},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
t.Run(fmt.Sprintf("limit %d offset %d", tc.limit, tc.offset), func(t *testing.T) {
|
||||
rc.Context.Req.Form.Set("limit", strconv.Itoa(tc.limit))
|
||||
rc.Context.Req.Form.Set("offset", strconv.Itoa(tc.offset))
|
||||
|
||||
response := sut.RouteGetReceivers(&rc)
|
||||
require.Equal(t, 200, response.Status())
|
||||
|
||||
var configs []definitions.GettableApiReceiver
|
||||
err := json.Unmarshal(response.Body(), &configs)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, tc.expected, configs)
|
||||
})
|
||||
}
|
||||
})
|
||||
t.Run("decrypt false with read permissions, does not have settings", func(t *testing.T) {
|
||||
env := createTestEnv(t, testContactPointConfig)
|
||||
sut := createNotificationSrvSutFromEnv(t, &env)
|
||||
rc := createTestRequestCtx()
|
||||
|
||||
rc.Context.Req.Header.Add("Accept", "application/json")
|
||||
rc.Context.Req.Form.Set("decrypt", "false")
|
||||
|
||||
response := sut.RouteGetReceivers(&rc)
|
||||
|
||||
require.Equal(t, 200, response.Status())
|
||||
require.Equal(t, expectedListResponse, string(response.Body()))
|
||||
})
|
||||
t.Run("decrypt false with only list permissions, does not have settings", func(t *testing.T) {
|
||||
env := createTestEnv(t, testContactPointConfig)
|
||||
env.ac = &recordingAccessControlFake{
|
||||
Callback: func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) {
|
||||
if strings.Contains(evaluator.String(), accesscontrol.ActionAlertingReceiversList) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
},
|
||||
}
|
||||
sut := createNotificationSrvSutFromEnv(t, &env)
|
||||
rc := createTestRequestCtx()
|
||||
|
||||
rc.Context.Req.Header.Add("Accept", "application/json")
|
||||
rc.Context.Req.Form.Set("decrypt", "false")
|
||||
|
||||
response := sut.RouteGetReceivers(&rc)
|
||||
|
||||
require.Equal(t, 200, response.Status())
|
||||
require.Equal(t, expectedListResponse, string(response.Body()))
|
||||
})
|
||||
t.Run("decrypt true with all permissions, does not have settings", func(t *testing.T) {
|
||||
env := createTestEnv(t, testContactPointConfig)
|
||||
env.ac = &recordingAccessControlFake{
|
||||
Callback: func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) {
|
||||
return true, nil
|
||||
},
|
||||
}
|
||||
sut := createNotificationSrvSutFromEnv(t, &env)
|
||||
rc := createTestRequestCtx()
|
||||
|
||||
rc.Context.Req.Header.Add("Accept", "application/json")
|
||||
rc.Context.Req.Form.Set("decrypt", "true")
|
||||
|
||||
response := sut.RouteGetReceivers(&rc)
|
||||
|
||||
require.Equal(t, 200, response.Status())
|
||||
require.Equal(t, expectedListResponse, string(response.Body()))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("get receiver", func(t *testing.T) {
|
||||
t.Run("GET returns 200", func(t *testing.T) {
|
||||
env := createTestEnv(t, testConfig)
|
||||
sut := createNotificationSrvSutFromEnv(t, &env)
|
||||
rc := createTestRequestCtx()
|
||||
|
||||
response := sut.RouteGetReceiver(&rc, "grafana-default-email")
|
||||
|
||||
require.Equal(t, 200, response.Status())
|
||||
})
|
||||
|
||||
t.Run("decrypt true without secrets:read permissions returns 403", func(t *testing.T) {
|
||||
recPermCheck := false
|
||||
env := createTestEnv(t, testConfig)
|
||||
env.ac = &recordingAccessControlFake{
|
||||
Callback: func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) {
|
||||
if strings.Contains(evaluator.String(), accesscontrol.ActionAlertingReceiversReadSecrets) {
|
||||
recPermCheck = true
|
||||
}
|
||||
return false, nil
|
||||
},
|
||||
}
|
||||
|
||||
sut := createNotificationSrvSutFromEnv(t, &env)
|
||||
rc := createTestRequestCtx()
|
||||
|
||||
rc.Context.Req.Form.Set("decrypt", "true")
|
||||
|
||||
response := sut.RouteGetReceiver(&rc, "grafana-default-email")
|
||||
|
||||
require.True(t, recPermCheck)
|
||||
require.Equal(t, 403, response.Status())
|
||||
})
|
||||
|
||||
t.Run("json body content is as expected", func(t *testing.T) {
|
||||
expectedRedactedResponse := `{"name":"multiple integrations","grafana_managed_receiver_configs":[{"uid":"c2090fda-f824-4add-b545-5a4d5c2ef082","name":"multiple integrations","type":"prometheus-alertmanager","disableResolveMessage":true,"settings":{"basicAuthUser":"test","url":"http://localhost:9093"},"secureFields":{"basicAuthPassword":true}},{"uid":"c84539ec-f87e-4fc5-9a91-7a687d34bbd1","name":"multiple integrations","type":"discord","disableResolveMessage":false,"settings":{"avatar_url":"some avatar","use_discord_username":true},"secureFields":{"url":true}}]}`
|
||||
expectedDecryptedResponse := `{"name":"multiple integrations","grafana_managed_receiver_configs":[{"uid":"c2090fda-f824-4add-b545-5a4d5c2ef082","name":"multiple integrations","type":"prometheus-alertmanager","disableResolveMessage":true,"settings":{"basicAuthPassword":"testpass","basicAuthUser":"test","url":"http://localhost:9093"},"secureFields":{"basicAuthPassword":true}},{"uid":"c84539ec-f87e-4fc5-9a91-7a687d34bbd1","name":"multiple integrations","type":"discord","disableResolveMessage":false,"settings":{"avatar_url":"some avatar","url":"some url","use_discord_username":true},"secureFields":{"url":true}}]}`
|
||||
t.Run("decrypt false", func(t *testing.T) {
|
||||
env := createTestEnv(t, testContactPointConfig)
|
||||
sut := createNotificationSrvSutFromEnv(t, &env)
|
||||
rc := createTestRequestCtx()
|
||||
|
||||
rc.Context.Req.Header.Add("Accept", "application/json")
|
||||
rc.Context.Req.Form.Set("decrypt", "false")
|
||||
|
||||
response := sut.RouteGetReceiver(&rc, "multiple integrations")
|
||||
|
||||
require.Equal(t, 200, response.Status())
|
||||
require.Equal(t, expectedRedactedResponse, string(response.Body()))
|
||||
})
|
||||
t.Run("decrypt true", func(t *testing.T) {
|
||||
env := createTestEnv(t, testContactPointConfig)
|
||||
env.ac = &recordingAccessControlFake{
|
||||
Callback: func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) {
|
||||
return true, nil
|
||||
},
|
||||
}
|
||||
sut := createNotificationSrvSutFromEnv(t, &env)
|
||||
rc := createTestRequestCtx()
|
||||
|
||||
rc.Context.Req.Header.Add("Accept", "application/json")
|
||||
rc.Context.Req.Form.Set("decrypt", "true")
|
||||
|
||||
response := sut.RouteGetReceiver(&rc, "multiple integrations")
|
||||
|
||||
require.Equal(t, 200, response.Status())
|
||||
require.Equal(t, expectedDecryptedResponse, string(response.Body()))
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func createNotificationSrvSutFromEnv(t *testing.T, env *testEnvironment) NotificationSrv {
|
||||
t.Helper()
|
||||
|
||||
receiverSvc := notifier.NewReceiverService(
|
||||
ac.NewReceiverAccess[*models.Receiver](env.ac, false),
|
||||
legacy_storage.NewAlertmanagerConfigStore(env.configs),
|
||||
env.prov,
|
||||
env.store,
|
||||
env.secrets,
|
||||
env.xact,
|
||||
env.log,
|
||||
fakes.NewFakeReceiverPermissionsService(),
|
||||
tracing.InitializeTracerForTest(),
|
||||
)
|
||||
return NotificationSrv{
|
||||
logger: env.log,
|
||||
receiverService: receiverSvc,
|
||||
}
|
||||
}
|
||||
|
||||
func newNotificationSrv(receiverService ReceiverService) *NotificationSrv {
|
||||
return &NotificationSrv{
|
||||
logger: log.NewNopLogger(),
|
||||
receiverService: receiverService,
|
||||
}
|
||||
}
|
||||
|
||||
func testReqCtx(method string) contextmodel.ReqContext {
|
||||
return contextmodel.ReqContext{
|
||||
Context: &web.Context{
|
||||
Req: &http.Request{
|
||||
Header: make(http.Header),
|
||||
Form: make(url.Values),
|
||||
},
|
||||
Resp: web.NewResponseWriter(method, httptest.NewRecorder()),
|
||||
},
|
||||
SignedInUser: &user.SignedInUser{
|
||||
OrgID: 1,
|
||||
},
|
||||
Logger: &logtest.Fake{},
|
||||
}
|
||||
}
|
||||
@@ -72,21 +72,6 @@ func (api *API) authorize(method, path string) web.Handler {
|
||||
case http.MethodGet + "/api/v1/rules/history":
|
||||
eval = ac.EvalPermission(ac.ActionAlertingRuleRead)
|
||||
|
||||
// Grafana receivers paths
|
||||
case http.MethodGet + "/api/v1/notifications/receivers":
|
||||
// additional authorization is done at the service level
|
||||
eval = ac.EvalAny(
|
||||
ac.EvalPermission(ac.ActionAlertingNotificationsRead),
|
||||
ac.EvalPermission(ac.ActionAlertingReceiversList),
|
||||
ac.EvalPermission(ac.ActionAlertingReceiversRead),
|
||||
ac.EvalPermission(ac.ActionAlertingReceiversReadSecrets),
|
||||
)
|
||||
case http.MethodGet + "/api/v1/notifications/receivers/{Name}":
|
||||
eval = ac.EvalAny(
|
||||
ac.EvalPermission(ac.ActionAlertingReceiversRead),
|
||||
ac.EvalPermission(ac.ActionAlertingReceiversReadSecrets),
|
||||
)
|
||||
|
||||
// Grafana, Prometheus-compatible Paths
|
||||
case http.MethodGet + "/api/prometheus/grafana/api/v1/rules":
|
||||
eval = ac.EvalPermission(ac.ActionAlertingRuleRead)
|
||||
@@ -442,14 +427,6 @@ func (api *API) authorize(method, path string) web.Handler {
|
||||
ac.EvalPermission(ac.ActionAlertingProvisioningSetStatus),
|
||||
),
|
||||
)
|
||||
case http.MethodGet + "/api/v1/notifications/time-intervals/{name}",
|
||||
http.MethodGet + "/api/v1/notifications/time-intervals":
|
||||
eval = ac.EvalAny(
|
||||
ac.EvalPermission(ac.ActionAlertingNotificationsRead),
|
||||
ac.EvalPermission(ac.ActionAlertingNotificationsTimeIntervalsRead),
|
||||
ac.EvalPermission(ac.ActionAlertingProvisioningRead),
|
||||
ac.EvalPermission(ac.ActionAlertingNotificationsProvisioningRead), // organization scope
|
||||
)
|
||||
}
|
||||
|
||||
if eval != nil {
|
||||
|
||||
@@ -41,7 +41,7 @@ func TestAuthorize(t *testing.T) {
|
||||
}
|
||||
paths[p] = methods
|
||||
}
|
||||
require.Len(t, paths, 67)
|
||||
require.Len(t, paths, 63)
|
||||
|
||||
ac := acmock.New()
|
||||
api := &API{AccessControl: ac, FeatureManager: featuremgmt.WithFeatures()}
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
/*Package api contains base API implementation of unified alerting
|
||||
*
|
||||
*Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
|
||||
*
|
||||
*Do not manually edit these files, please find ngalert/api/swagger-codegen/ for commands on how to generate them.
|
||||
*/
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/middleware/requestmeta"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/metrics"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
type NotificationsApi interface {
|
||||
RouteGetReceiver(*contextmodel.ReqContext) response.Response
|
||||
RouteGetReceivers(*contextmodel.ReqContext) response.Response
|
||||
RouteNotificationsGetTimeInterval(*contextmodel.ReqContext) response.Response
|
||||
RouteNotificationsGetTimeIntervals(*contextmodel.ReqContext) response.Response
|
||||
}
|
||||
|
||||
func (f *NotificationsApiHandler) RouteGetReceiver(ctx *contextmodel.ReqContext) response.Response {
|
||||
// Parse Path Parameters
|
||||
nameParam := web.Params(ctx.Req)[":name"]
|
||||
return f.handleRouteGetReceiver(ctx, nameParam)
|
||||
}
|
||||
func (f *NotificationsApiHandler) RouteGetReceivers(ctx *contextmodel.ReqContext) response.Response {
|
||||
return f.handleRouteGetReceivers(ctx)
|
||||
}
|
||||
func (f *NotificationsApiHandler) RouteNotificationsGetTimeInterval(ctx *contextmodel.ReqContext) response.Response {
|
||||
// Parse Path Parameters
|
||||
nameParam := web.Params(ctx.Req)[":name"]
|
||||
return f.handleRouteNotificationsGetTimeInterval(ctx, nameParam)
|
||||
}
|
||||
func (f *NotificationsApiHandler) RouteNotificationsGetTimeIntervals(ctx *contextmodel.ReqContext) response.Response {
|
||||
return f.handleRouteNotificationsGetTimeIntervals(ctx)
|
||||
}
|
||||
|
||||
func (api *API) RegisterNotificationsApiEndpoints(srv NotificationsApi, m *metrics.API) {
|
||||
api.RouteRegister.Group("", func(group routing.RouteRegister) {
|
||||
group.Get(
|
||||
toMacaronPath("/api/v1/notifications/receivers/{Name}"),
|
||||
requestmeta.SetOwner(requestmeta.TeamAlerting),
|
||||
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
|
||||
api.authorize(http.MethodGet, "/api/v1/notifications/receivers/{Name}"),
|
||||
metrics.Instrument(
|
||||
http.MethodGet,
|
||||
"/api/v1/notifications/receivers/{Name}",
|
||||
api.Hooks.Wrap(srv.RouteGetReceiver),
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Get(
|
||||
toMacaronPath("/api/v1/notifications/receivers"),
|
||||
requestmeta.SetOwner(requestmeta.TeamAlerting),
|
||||
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
|
||||
api.authorize(http.MethodGet, "/api/v1/notifications/receivers"),
|
||||
metrics.Instrument(
|
||||
http.MethodGet,
|
||||
"/api/v1/notifications/receivers",
|
||||
api.Hooks.Wrap(srv.RouteGetReceivers),
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Get(
|
||||
toMacaronPath("/api/v1/notifications/time-intervals/{name}"),
|
||||
requestmeta.SetOwner(requestmeta.TeamAlerting),
|
||||
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
|
||||
api.authorize(http.MethodGet, "/api/v1/notifications/time-intervals/{name}"),
|
||||
metrics.Instrument(
|
||||
http.MethodGet,
|
||||
"/api/v1/notifications/time-intervals/{name}",
|
||||
api.Hooks.Wrap(srv.RouteNotificationsGetTimeInterval),
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Get(
|
||||
toMacaronPath("/api/v1/notifications/time-intervals"),
|
||||
requestmeta.SetOwner(requestmeta.TeamAlerting),
|
||||
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
|
||||
api.authorize(http.MethodGet, "/api/v1/notifications/time-intervals"),
|
||||
metrics.Instrument(
|
||||
http.MethodGet,
|
||||
"/api/v1/notifications/time-intervals",
|
||||
api.Hooks.Wrap(srv.RouteNotificationsGetTimeIntervals),
|
||||
m,
|
||||
),
|
||||
)
|
||||
}, middleware.ReqSignedIn)
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
)
|
||||
|
||||
type NotificationsApiHandler struct {
|
||||
notificationSrv *NotificationSrv
|
||||
}
|
||||
|
||||
func NewNotificationsApi(notificationSrv *NotificationSrv) *NotificationsApiHandler {
|
||||
return &NotificationsApiHandler{
|
||||
notificationSrv: notificationSrv,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *NotificationsApiHandler) handleRouteNotificationsGetTimeInterval(ctx *contextmodel.ReqContext, name string) response.Response {
|
||||
return f.notificationSrv.RouteGetTimeInterval(ctx, name)
|
||||
}
|
||||
|
||||
func (f *NotificationsApiHandler) handleRouteNotificationsGetTimeIntervals(ctx *contextmodel.ReqContext) response.Response {
|
||||
return f.notificationSrv.RouteGetTimeIntervals(ctx)
|
||||
}
|
||||
|
||||
func (f *NotificationsApiHandler) handleRouteGetReceiver(ctx *contextmodel.ReqContext, name string) response.Response {
|
||||
return f.notificationSrv.RouteGetReceiver(ctx, name)
|
||||
}
|
||||
|
||||
func (f *NotificationsApiHandler) handleRouteGetReceivers(ctx *contextmodel.ReqContext) response.Response {
|
||||
return f.notificationSrv.RouteGetReceivers(ctx)
|
||||
}
|
||||
@@ -1789,26 +1789,6 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"GettableTimeIntervals": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"provenance": {
|
||||
"$ref": "#/definitions/Provenance"
|
||||
},
|
||||
"time_intervals": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeIntervalItem"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"GettableUserConfig": {
|
||||
"properties": {
|
||||
"alertmanager_config": {
|
||||
@@ -2950,23 +2930,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"PostableTimeIntervals": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"time_intervals": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeIntervalItem"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"PostableUserConfig": {
|
||||
"properties": {
|
||||
"alertmanager_config": {
|
||||
@@ -4492,55 +4455,6 @@
|
||||
"title": "TimeInterval represents a named set of time intervals for which a route should be muted.",
|
||||
"type": "object"
|
||||
},
|
||||
"TimeIntervalItem": {
|
||||
"properties": {
|
||||
"days_of_month": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"location": {
|
||||
"type": "string"
|
||||
},
|
||||
"months": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"times": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeIntervalTimeRange"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"weekdays": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"years": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"TimeIntervalTimeRange": {
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"type": "string"
|
||||
},
|
||||
"start_time": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"TimeRange": {
|
||||
"description": "Redefining this to avoid an import cycle",
|
||||
"properties": {
|
||||
@@ -5120,7 +5034,6 @@
|
||||
"type": "object"
|
||||
},
|
||||
"gettableSilences": {
|
||||
"description": "GettableSilences gettable silences",
|
||||
"items": {
|
||||
"$ref": "#/definitions/gettableSilence",
|
||||
"type": "object"
|
||||
@@ -6561,36 +6474,6 @@
|
||||
"application/json"
|
||||
],
|
||||
"responses": {
|
||||
"GetAllIntervalsResponse": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/GettableTimeIntervals"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"GetIntervalsByNameResponse": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/GettableTimeIntervals"
|
||||
}
|
||||
},
|
||||
"GetReceiverResponse": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/GettableApiReceiver"
|
||||
}
|
||||
},
|
||||
"GetReceiversResponse": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/GettableApiReceiver"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"GettableHistoricUserConfigs": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
package definitions
|
||||
|
||||
// swagger:route GET /v1/notifications/receivers/{Name} notifications RouteGetReceiver
|
||||
//
|
||||
// Get a receiver by name.
|
||||
//
|
||||
// This API is designated to internal use only and can be removed or changed at any time without prior notice.
|
||||
//
|
||||
// Deprecated: true
|
||||
// Responses:
|
||||
// 200: GetReceiverResponse
|
||||
// 403: PermissionDenied
|
||||
// 404: NotFound
|
||||
|
||||
// swagger:route GET /v1/notifications/receivers notifications RouteGetReceivers
|
||||
//
|
||||
// Get all receivers.
|
||||
//
|
||||
// This API is designated to internal use only and can be removed or changed at any time without prior notice.
|
||||
//
|
||||
// Deprecated: true
|
||||
// Responses:
|
||||
// 200: GetReceiversResponse
|
||||
// 403: PermissionDenied
|
||||
|
||||
// swagger:parameters RouteGetReceiver
|
||||
type GetReceiverParams struct {
|
||||
// in:path
|
||||
// required: true
|
||||
Name string `json:"name"`
|
||||
// in:query
|
||||
// required: false
|
||||
Decrypt bool `json:"decrypt"`
|
||||
}
|
||||
|
||||
// swagger:parameters RouteGetReceivers
|
||||
type GetReceiversParams struct {
|
||||
// in:query
|
||||
// required: false
|
||||
Names []string `json:"names"`
|
||||
// in:query
|
||||
// required: false
|
||||
Limit int `json:"limit"`
|
||||
// in:query
|
||||
// required: false
|
||||
Offset int `json:"offset"`
|
||||
// in:query
|
||||
// required: false
|
||||
Decrypt bool `json:"decrypt"`
|
||||
}
|
||||
|
||||
// swagger:response GetReceiverResponse
|
||||
type GetReceiverResponse struct {
|
||||
// in:body
|
||||
Body GettableApiReceiver
|
||||
}
|
||||
|
||||
// swagger:response GetReceiversResponse
|
||||
type GetReceiversResponse struct {
|
||||
// in:body
|
||||
Body []GettableApiReceiver
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package definitions
|
||||
|
||||
// swagger:route GET /v1/notifications/time-intervals notifications RouteNotificationsGetTimeIntervals
|
||||
//
|
||||
// Get all the time intervals
|
||||
//
|
||||
// This API is designated to internal use only and can be removed or changed at any time without prior notice.
|
||||
//
|
||||
// Deprecated: true
|
||||
// Responses:
|
||||
// 200: GetAllIntervalsResponse
|
||||
// 403: ForbiddenError
|
||||
|
||||
// swagger:route GET /v1/notifications/time-intervals/{name} notifications RouteNotificationsGetTimeInterval
|
||||
//
|
||||
// Get a time interval by name.
|
||||
//
|
||||
// This API is designated to internal use only and can be removed or changed at any time without prior notice.
|
||||
//
|
||||
// Deprecated: true
|
||||
// Responses:
|
||||
// 200: GetIntervalsByNameResponse
|
||||
// 404: NotFound
|
||||
// 403: ForbiddenError
|
||||
|
||||
// swagger:parameters RouteNotificationsGetTimeInterval
|
||||
type RouteTimeIntervalNameParam struct {
|
||||
// Time interval name
|
||||
// in:path
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// swagger:response GetAllIntervalsResponse
|
||||
type GetAllIntervalsResponse struct {
|
||||
// in:body
|
||||
Body []GettableTimeIntervals
|
||||
}
|
||||
|
||||
// swagger:response GetIntervalsByNameResponse
|
||||
type GetIntervalsByNameResponse struct {
|
||||
// in:body
|
||||
Body GettableTimeIntervals
|
||||
}
|
||||
|
||||
// swagger:model
|
||||
type PostableTimeIntervals struct {
|
||||
Name string `json:"name" hcl:"name"`
|
||||
Version string `json:"version,omitempty"`
|
||||
TimeIntervals []TimeIntervalItem `json:"time_intervals" hcl:"intervals,block"`
|
||||
}
|
||||
|
||||
type TimeIntervalItem struct {
|
||||
Times []TimeIntervalTimeRange `json:"times,omitempty" hcl:"times,block"`
|
||||
Weekdays *[]string `json:"weekdays,omitempty" hcl:"weekdays"`
|
||||
DaysOfMonth *[]string `json:"days_of_month,omitempty" hcl:"days_of_month"`
|
||||
Months *[]string `json:"months,omitempty" hcl:"months"`
|
||||
Years *[]string `json:"years,omitempty" hcl:"years"`
|
||||
Location *string `json:"location,omitempty" hcl:"location"`
|
||||
}
|
||||
|
||||
type TimeIntervalTimeRange struct {
|
||||
StartMinute string `json:"start_time" hcl:"start"`
|
||||
EndMinute string `json:"end_time" hcl:"end"`
|
||||
}
|
||||
|
||||
// swagger:model
|
||||
type GettableTimeIntervals struct {
|
||||
Name string `json:"name" hcl:"name"`
|
||||
TimeIntervals []TimeIntervalItem `json:"time_intervals" hcl:"intervals,block"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Provenance Provenance `json:"provenance,omitempty"`
|
||||
}
|
||||
@@ -1789,26 +1789,6 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"GettableTimeIntervals": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"provenance": {
|
||||
"$ref": "#/definitions/Provenance"
|
||||
},
|
||||
"time_intervals": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeIntervalItem"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"GettableUserConfig": {
|
||||
"properties": {
|
||||
"alertmanager_config": {
|
||||
@@ -2950,23 +2930,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"PostableTimeIntervals": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"time_intervals": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeIntervalItem"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"PostableUserConfig": {
|
||||
"properties": {
|
||||
"alertmanager_config": {
|
||||
@@ -4492,55 +4455,6 @@
|
||||
"title": "TimeInterval represents a named set of time intervals for which a route should be muted.",
|
||||
"type": "object"
|
||||
},
|
||||
"TimeIntervalItem": {
|
||||
"properties": {
|
||||
"days_of_month": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"location": {
|
||||
"type": "string"
|
||||
},
|
||||
"months": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"times": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeIntervalTimeRange"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"weekdays": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"years": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"TimeIntervalTimeRange": {
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"type": "string"
|
||||
},
|
||||
"start_time": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"TimeRange": {
|
||||
"description": "Redefining this to avoid an import cycle",
|
||||
"properties": {
|
||||
@@ -8029,155 +7943,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/notifications/receivers": {
|
||||
"get": {
|
||||
"deprecated": true,
|
||||
"description": "This API is designated to internal use only and can be removed or changed at any time without prior notice.",
|
||||
"operationId": "RouteGetReceivers",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": "names",
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"format": "int64",
|
||||
"in": "query",
|
||||
"name": "limit",
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"format": "int64",
|
||||
"in": "query",
|
||||
"name": "offset",
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "decrypt",
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/GetReceiversResponse"
|
||||
},
|
||||
"403": {
|
||||
"description": "PermissionDenied",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/PermissionDenied"
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": "Get all receivers.",
|
||||
"tags": [
|
||||
"notifications"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/notifications/receivers/{Name}": {
|
||||
"get": {
|
||||
"deprecated": true,
|
||||
"description": "This API is designated to internal use only and can be removed or changed at any time without prior notice.",
|
||||
"operationId": "RouteGetReceiver",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "name",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "decrypt",
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/GetReceiverResponse"
|
||||
},
|
||||
"403": {
|
||||
"description": "PermissionDenied",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/PermissionDenied"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "NotFound",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/NotFound"
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": "Get a receiver by name.",
|
||||
"tags": [
|
||||
"notifications"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/notifications/time-intervals": {
|
||||
"get": {
|
||||
"deprecated": true,
|
||||
"description": "This API is designated to internal use only and can be removed or changed at any time without prior notice.",
|
||||
"operationId": "RouteNotificationsGetTimeIntervals",
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/GetAllIntervalsResponse"
|
||||
},
|
||||
"403": {
|
||||
"description": "ForbiddenError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ForbiddenError"
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": "Get all the time intervals",
|
||||
"tags": [
|
||||
"notifications"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/notifications/time-intervals/{name}": {
|
||||
"get": {
|
||||
"deprecated": true,
|
||||
"description": "This API is designated to internal use only and can be removed or changed at any time without prior notice.",
|
||||
"operationId": "RouteNotificationsGetTimeInterval",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Time interval name",
|
||||
"in": "path",
|
||||
"name": "name",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/GetIntervalsByNameResponse"
|
||||
},
|
||||
"403": {
|
||||
"description": "ForbiddenError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ForbiddenError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "NotFound",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/NotFound"
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": "Get a time interval by name.",
|
||||
"tags": [
|
||||
"notifications"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/provisioning/alert-rules": {
|
||||
"get": {
|
||||
"operationId": "RouteGetAlertRules",
|
||||
@@ -9557,36 +9322,6 @@
|
||||
"application/json"
|
||||
],
|
||||
"responses": {
|
||||
"GetAllIntervalsResponse": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/GettableTimeIntervals"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"GetIntervalsByNameResponse": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/GettableTimeIntervals"
|
||||
}
|
||||
},
|
||||
"GetReceiverResponse": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/GettableApiReceiver"
|
||||
}
|
||||
},
|
||||
"GetReceiversResponse": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/GettableApiReceiver"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"GettableHistoricUserConfigs": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
|
||||
@@ -2671,155 +2671,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/notifications/receivers": {
|
||||
"get": {
|
||||
"description": "This API is designated to internal use only and can be removed or changed at any time without prior notice.",
|
||||
"tags": [
|
||||
"notifications"
|
||||
],
|
||||
"summary": "Get all receivers.",
|
||||
"operationId": "RouteGetReceivers",
|
||||
"deprecated": true,
|
||||
"parameters": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": "names",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"name": "offset",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"name": "decrypt",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/GetReceiversResponse"
|
||||
},
|
||||
"403": {
|
||||
"description": "PermissionDenied",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/PermissionDenied"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/notifications/receivers/{Name}": {
|
||||
"get": {
|
||||
"description": "This API is designated to internal use only and can be removed or changed at any time without prior notice.",
|
||||
"tags": [
|
||||
"notifications"
|
||||
],
|
||||
"summary": "Get a receiver by name.",
|
||||
"operationId": "RouteGetReceiver",
|
||||
"deprecated": true,
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "name",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"name": "decrypt",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/GetReceiverResponse"
|
||||
},
|
||||
"403": {
|
||||
"description": "PermissionDenied",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/PermissionDenied"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "NotFound",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/NotFound"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/notifications/time-intervals": {
|
||||
"get": {
|
||||
"description": "This API is designated to internal use only and can be removed or changed at any time without prior notice.",
|
||||
"tags": [
|
||||
"notifications"
|
||||
],
|
||||
"summary": "Get all the time intervals",
|
||||
"operationId": "RouteNotificationsGetTimeIntervals",
|
||||
"deprecated": true,
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/GetAllIntervalsResponse"
|
||||
},
|
||||
"403": {
|
||||
"description": "ForbiddenError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ForbiddenError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/notifications/time-intervals/{name}": {
|
||||
"get": {
|
||||
"description": "This API is designated to internal use only and can be removed or changed at any time without prior notice.",
|
||||
"tags": [
|
||||
"notifications"
|
||||
],
|
||||
"summary": "Get a time interval by name.",
|
||||
"operationId": "RouteNotificationsGetTimeInterval",
|
||||
"deprecated": true,
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Time interval name",
|
||||
"name": "name",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/GetIntervalsByNameResponse"
|
||||
},
|
||||
"403": {
|
||||
"description": "ForbiddenError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ForbiddenError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "NotFound",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/NotFound"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/provisioning/alert-rules": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -6013,26 +5864,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"GettableTimeIntervals": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"provenance": {
|
||||
"$ref": "#/definitions/Provenance"
|
||||
},
|
||||
"time_intervals": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeIntervalItem"
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GettableUserConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -7175,23 +7006,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"PostableTimeIntervals": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"time_intervals": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeIntervalItem"
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PostableUserConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -8717,55 +8531,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"TimeIntervalItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"days_of_month": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"type": "string"
|
||||
},
|
||||
"months": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"times": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeIntervalTimeRange"
|
||||
}
|
||||
},
|
||||
"weekdays": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"years": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"TimeIntervalTimeRange": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"type": "string"
|
||||
},
|
||||
"start_time": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TimeRange": {
|
||||
"description": "Redefining this to avoid an import cycle",
|
||||
"type": "object",
|
||||
@@ -9595,36 +9360,6 @@
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"GetAllIntervalsResponse": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/GettableTimeIntervals"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GetIntervalsByNameResponse": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/GettableTimeIntervals"
|
||||
}
|
||||
},
|
||||
"GetReceiverResponse": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/GettableApiReceiver"
|
||||
}
|
||||
},
|
||||
"GetReceiversResponse": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/GettableApiReceiver"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GettableHistoricUserConfigs": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
|
||||
@@ -1,204 +0,0 @@
|
||||
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, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
|
||||
createUser(t, env.SQLStore, env.Cfg, 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)
|
||||
})
|
||||
}
|
||||
@@ -1019,24 +1019,6 @@ func (a apiClient) GetRuleHistoryWithStatus(t *testing.T, ruleUID string) (data.
|
||||
return sendRequestJSON[data.Frame](t, req, http.StatusOK)
|
||||
}
|
||||
|
||||
func (a apiClient) GetAllTimeIntervalsWithStatus(t *testing.T) ([]apimodels.GettableTimeIntervals, int, string) {
|
||||
t.Helper()
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/v1/notifications/time-intervals", a.url), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
return sendRequestJSON[[]apimodels.GettableTimeIntervals](t, req, http.StatusOK)
|
||||
}
|
||||
|
||||
func (a apiClient) GetTimeIntervalByNameWithStatus(t *testing.T, name string) (apimodels.GettableTimeIntervals, int, string) {
|
||||
t.Helper()
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/v1/notifications/time-intervals/%s", a.url, name), nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
return sendRequestJSON[apimodels.GettableTimeIntervals](t, req, http.StatusOK)
|
||||
}
|
||||
|
||||
func (a apiClient) CreateReceiverWithStatus(t *testing.T, receiver apimodels.EmbeddedContactPoint) (apimodels.EmbeddedContactPoint, int, string) {
|
||||
t.Helper()
|
||||
|
||||
|
||||
@@ -16270,26 +16270,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"GettableTimeIntervals": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"provenance": {
|
||||
"$ref": "#/definitions/Provenance"
|
||||
},
|
||||
"time_intervals": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeIntervalItem"
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GettableUserConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -18579,23 +18559,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"PostableTimeIntervals": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"time_intervals": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeIntervalItem"
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PostableUserConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -21593,55 +21556,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"TimeIntervalItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"days_of_month": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"type": "string"
|
||||
},
|
||||
"months": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"times": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeIntervalTimeRange"
|
||||
}
|
||||
},
|
||||
"weekdays": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"years": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"TimeIntervalTimeRange": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"type": "string"
|
||||
},
|
||||
"start_time": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TimeRange": {
|
||||
"description": "Redefining this to avoid an import cycle",
|
||||
"type": "object",
|
||||
@@ -23049,7 +22963,6 @@
|
||||
}
|
||||
},
|
||||
"gettableSilences": {
|
||||
"description": "GettableSilences gettable silences",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
@@ -23433,36 +23346,6 @@
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"GetAllIntervalsResponse": {
|
||||
"description": "(empty)",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/GettableTimeIntervals"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GetIntervalsByNameResponse": {
|
||||
"description": "(empty)",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/GettableTimeIntervals"
|
||||
}
|
||||
},
|
||||
"GetReceiverResponse": {
|
||||
"description": "(empty)",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/GettableApiReceiver"
|
||||
}
|
||||
},
|
||||
"GetReceiversResponse": {
|
||||
"description": "(empty)",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/GettableApiReceiver"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GettableHistoricUserConfigs": {
|
||||
"description": "(empty)",
|
||||
"schema": {
|
||||
|
||||
@@ -1,52 +1,6 @@
|
||||
{
|
||||
"components": {
|
||||
"responses": {
|
||||
"GetAllIntervalsResponse": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/GettableTimeIntervals"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "(empty)"
|
||||
},
|
||||
"GetIntervalsByNameResponse": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/GettableTimeIntervals"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "(empty)"
|
||||
},
|
||||
"GetReceiverResponse": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/GettableApiReceiver"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "(empty)"
|
||||
},
|
||||
"GetReceiversResponse": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/GettableApiReceiver"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "(empty)"
|
||||
},
|
||||
"GettableHistoricUserConfigs": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
@@ -6333,26 +6287,6 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"GettableTimeIntervals": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"provenance": {
|
||||
"$ref": "#/components/schemas/Provenance"
|
||||
},
|
||||
"time_intervals": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/TimeIntervalItem"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"GettableUserConfig": {
|
||||
"properties": {
|
||||
"alertmanager_config": {
|
||||
@@ -8642,23 +8576,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"PostableTimeIntervals": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"time_intervals": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/TimeIntervalItem"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"PostableUserConfig": {
|
||||
"properties": {
|
||||
"alertmanager_config": {
|
||||
@@ -11655,55 +11572,6 @@
|
||||
"title": "TimeInterval represents a named set of time intervals for which a route should be muted.",
|
||||
"type": "object"
|
||||
},
|
||||
"TimeIntervalItem": {
|
||||
"properties": {
|
||||
"days_of_month": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"location": {
|
||||
"type": "string"
|
||||
},
|
||||
"months": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"times": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/TimeIntervalTimeRange"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"weekdays": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"years": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"TimeIntervalTimeRange": {
|
||||
"properties": {
|
||||
"end_time": {
|
||||
"type": "string"
|
||||
},
|
||||
"start_time": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"TimeRange": {
|
||||
"description": "Redefining this to avoid an import cycle",
|
||||
"properties": {
|
||||
@@ -13109,7 +12977,6 @@
|
||||
"type": "object"
|
||||
},
|
||||
"gettableSilences": {
|
||||
"description": "GettableSilences gettable silences",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/gettableSilence"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user