diff --git a/pkg/services/ngalert/api/api.go b/pkg/services/ngalert/api/api.go index f99a6e12d45..1c6e54fa257 100644 --- a/pkg/services/ngalert/api/api.go +++ b/pkg/services/ngalert/api/api.go @@ -85,6 +85,9 @@ type API struct { Historian Historian AppUrl *url.URL + + // Hooks can be used to replace API handlers for specific paths. + Hooks *Hooks } // RegisterAPIEndpoints registers API handlers diff --git a/pkg/services/ngalert/api/generated_base_api_alertmanager.go b/pkg/services/ngalert/api/generated_base_api_alertmanager.go index d474837b9ec..9b7911f8f2a 100644 --- a/pkg/services/ngalert/api/generated_base_api_alertmanager.go +++ b/pkg/services/ngalert/api/generated_base_api_alertmanager.go @@ -184,7 +184,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodPost, "/api/alertmanager/grafana/api/v2/silences", - srv.RouteCreateGrafanaSilence, + api.Hooks.Wrap(srv.RouteCreateGrafanaSilence), m, ), ) @@ -194,7 +194,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodPost, "/api/alertmanager/{DatasourceUID}/api/v2/silences", - srv.RouteCreateSilence, + api.Hooks.Wrap(srv.RouteCreateSilence), m, ), ) @@ -204,7 +204,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodDelete, "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts", - srv.RouteDeleteAlertingConfig, + api.Hooks.Wrap(srv.RouteDeleteAlertingConfig), m, ), ) @@ -214,7 +214,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodDelete, "/api/alertmanager/grafana/config/api/v1/alerts", - srv.RouteDeleteGrafanaAlertingConfig, + api.Hooks.Wrap(srv.RouteDeleteGrafanaAlertingConfig), m, ), ) @@ -224,7 +224,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodDelete, "/api/alertmanager/grafana/api/v2/silence/{SilenceId}", - srv.RouteDeleteGrafanaSilence, + api.Hooks.Wrap(srv.RouteDeleteGrafanaSilence), m, ), ) @@ -234,7 +234,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodDelete, "/api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}", - srv.RouteDeleteSilence, + api.Hooks.Wrap(srv.RouteDeleteSilence), m, ), ) @@ -244,7 +244,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/{DatasourceUID}/api/v2/alerts/groups", - srv.RouteGetAMAlertGroups, + api.Hooks.Wrap(srv.RouteGetAMAlertGroups), m, ), ) @@ -254,7 +254,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/{DatasourceUID}/api/v2/alerts", - srv.RouteGetAMAlerts, + api.Hooks.Wrap(srv.RouteGetAMAlerts), m, ), ) @@ -264,7 +264,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/{DatasourceUID}/api/v2/status", - srv.RouteGetAMStatus, + api.Hooks.Wrap(srv.RouteGetAMStatus), m, ), ) @@ -274,7 +274,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts", - srv.RouteGetAlertingConfig, + api.Hooks.Wrap(srv.RouteGetAlertingConfig), m, ), ) @@ -284,7 +284,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/grafana/api/v2/alerts/groups", - srv.RouteGetGrafanaAMAlertGroups, + api.Hooks.Wrap(srv.RouteGetGrafanaAMAlertGroups), m, ), ) @@ -294,7 +294,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/grafana/api/v2/alerts", - srv.RouteGetGrafanaAMAlerts, + api.Hooks.Wrap(srv.RouteGetGrafanaAMAlerts), m, ), ) @@ -304,7 +304,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/grafana/api/v2/status", - srv.RouteGetGrafanaAMStatus, + api.Hooks.Wrap(srv.RouteGetGrafanaAMStatus), m, ), ) @@ -314,7 +314,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/grafana/config/api/v1/alerts", - srv.RouteGetGrafanaAlertingConfig, + api.Hooks.Wrap(srv.RouteGetGrafanaAlertingConfig), m, ), ) @@ -324,7 +324,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/grafana/config/history", - srv.RouteGetGrafanaAlertingConfigHistory, + api.Hooks.Wrap(srv.RouteGetGrafanaAlertingConfigHistory), m, ), ) @@ -334,7 +334,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/grafana/config/api/v1/receivers", - srv.RouteGetGrafanaReceivers, + api.Hooks.Wrap(srv.RouteGetGrafanaReceivers), m, ), ) @@ -344,7 +344,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/grafana/api/v2/silence/{SilenceId}", - srv.RouteGetGrafanaSilence, + api.Hooks.Wrap(srv.RouteGetGrafanaSilence), m, ), ) @@ -354,7 +354,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/grafana/api/v2/silences", - srv.RouteGetGrafanaSilences, + api.Hooks.Wrap(srv.RouteGetGrafanaSilences), m, ), ) @@ -364,7 +364,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}", - srv.RouteGetSilence, + api.Hooks.Wrap(srv.RouteGetSilence), m, ), ) @@ -374,7 +374,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodGet, "/api/alertmanager/{DatasourceUID}/api/v2/silences", - srv.RouteGetSilences, + api.Hooks.Wrap(srv.RouteGetSilences), m, ), ) @@ -384,7 +384,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodPost, "/api/alertmanager/{DatasourceUID}/api/v2/alerts", - srv.RoutePostAMAlerts, + api.Hooks.Wrap(srv.RoutePostAMAlerts), m, ), ) @@ -394,7 +394,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodPost, "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts", - srv.RoutePostAlertingConfig, + api.Hooks.Wrap(srv.RoutePostAlertingConfig), m, ), ) @@ -404,7 +404,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodPost, "/api/alertmanager/grafana/config/api/v1/alerts", - srv.RoutePostGrafanaAlertingConfig, + api.Hooks.Wrap(srv.RoutePostGrafanaAlertingConfig), m, ), ) @@ -414,7 +414,7 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApi, m *metrics metrics.Instrument( http.MethodPost, "/api/alertmanager/grafana/config/api/v1/receivers/test", - srv.RoutePostTestGrafanaReceivers, + api.Hooks.Wrap(srv.RoutePostTestGrafanaReceivers), m, ), ) diff --git a/pkg/services/ngalert/api/generated_base_api_configuration.go b/pkg/services/ngalert/api/generated_base_api_configuration.go index c0685d12a1c..abb1bbc87ae 100644 --- a/pkg/services/ngalert/api/generated_base_api_configuration.go +++ b/pkg/services/ngalert/api/generated_base_api_configuration.go @@ -55,7 +55,7 @@ func (api *API) RegisterConfigurationApiEndpoints(srv ConfigurationApi, m *metri metrics.Instrument( http.MethodDelete, "/api/v1/ngalert/admin_config", - srv.RouteDeleteNGalertConfig, + api.Hooks.Wrap(srv.RouteDeleteNGalertConfig), m, ), ) @@ -65,7 +65,7 @@ func (api *API) RegisterConfigurationApiEndpoints(srv ConfigurationApi, m *metri metrics.Instrument( http.MethodGet, "/api/v1/ngalert/alertmanagers", - srv.RouteGetAlertmanagers, + api.Hooks.Wrap(srv.RouteGetAlertmanagers), m, ), ) @@ -75,7 +75,7 @@ func (api *API) RegisterConfigurationApiEndpoints(srv ConfigurationApi, m *metri metrics.Instrument( http.MethodGet, "/api/v1/ngalert/admin_config", - srv.RouteGetNGalertConfig, + api.Hooks.Wrap(srv.RouteGetNGalertConfig), m, ), ) @@ -85,7 +85,7 @@ func (api *API) RegisterConfigurationApiEndpoints(srv ConfigurationApi, m *metri metrics.Instrument( http.MethodGet, "/api/v1/ngalert", - srv.RouteGetStatus, + api.Hooks.Wrap(srv.RouteGetStatus), m, ), ) @@ -95,7 +95,7 @@ func (api *API) RegisterConfigurationApiEndpoints(srv ConfigurationApi, m *metri metrics.Instrument( http.MethodPost, "/api/v1/ngalert/admin_config", - srv.RoutePostNGalertConfig, + api.Hooks.Wrap(srv.RoutePostNGalertConfig), m, ), ) diff --git a/pkg/services/ngalert/api/generated_base_api_history.go b/pkg/services/ngalert/api/generated_base_api_history.go index 8f352d366c8..f8a616d2894 100644 --- a/pkg/services/ngalert/api/generated_base_api_history.go +++ b/pkg/services/ngalert/api/generated_base_api_history.go @@ -32,7 +32,7 @@ func (api *API) RegisterHistoryApiEndpoints(srv HistoryApi, m *metrics.API) { metrics.Instrument( http.MethodGet, "/api/v1/rules/history", - srv.RouteGetStateHistory, + api.Hooks.Wrap(srv.RouteGetStateHistory), m, ), ) diff --git a/pkg/services/ngalert/api/generated_base_api_prometheus.go b/pkg/services/ngalert/api/generated_base_api_prometheus.go index a4f04e25199..34b584d7a83 100644 --- a/pkg/services/ngalert/api/generated_base_api_prometheus.go +++ b/pkg/services/ngalert/api/generated_base_api_prometheus.go @@ -49,7 +49,7 @@ func (api *API) RegisterPrometheusApiEndpoints(srv PrometheusApi, m *metrics.API metrics.Instrument( http.MethodGet, "/api/prometheus/{DatasourceUID}/api/v1/alerts", - srv.RouteGetAlertStatuses, + api.Hooks.Wrap(srv.RouteGetAlertStatuses), m, ), ) @@ -59,7 +59,7 @@ func (api *API) RegisterPrometheusApiEndpoints(srv PrometheusApi, m *metrics.API metrics.Instrument( http.MethodGet, "/api/prometheus/grafana/api/v1/alerts", - srv.RouteGetGrafanaAlertStatuses, + api.Hooks.Wrap(srv.RouteGetGrafanaAlertStatuses), m, ), ) @@ -69,7 +69,7 @@ func (api *API) RegisterPrometheusApiEndpoints(srv PrometheusApi, m *metrics.API metrics.Instrument( http.MethodGet, "/api/prometheus/grafana/api/v1/rules", - srv.RouteGetGrafanaRuleStatuses, + api.Hooks.Wrap(srv.RouteGetGrafanaRuleStatuses), m, ), ) @@ -79,7 +79,7 @@ func (api *API) RegisterPrometheusApiEndpoints(srv PrometheusApi, m *metrics.API metrics.Instrument( http.MethodGet, "/api/prometheus/{DatasourceUID}/api/v1/rules", - srv.RouteGetRuleStatuses, + api.Hooks.Wrap(srv.RouteGetRuleStatuses), m, ), ) diff --git a/pkg/services/ngalert/api/generated_base_api_provisioning.go b/pkg/services/ngalert/api/generated_base_api_provisioning.go index f3e6ed66c32..6921fbc2007 100644 --- a/pkg/services/ngalert/api/generated_base_api_provisioning.go +++ b/pkg/services/ngalert/api/generated_base_api_provisioning.go @@ -212,7 +212,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodDelete, "/api/v1/provisioning/alert-rules/{UID}", - srv.RouteDeleteAlertRule, + api.Hooks.Wrap(srv.RouteDeleteAlertRule), m, ), ) @@ -222,7 +222,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodDelete, "/api/v1/provisioning/contact-points/{UID}", - srv.RouteDeleteContactpoints, + api.Hooks.Wrap(srv.RouteDeleteContactpoints), m, ), ) @@ -232,7 +232,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodDelete, "/api/v1/provisioning/mute-timings/{name}", - srv.RouteDeleteMuteTiming, + api.Hooks.Wrap(srv.RouteDeleteMuteTiming), m, ), ) @@ -242,7 +242,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodDelete, "/api/v1/provisioning/templates/{name}", - srv.RouteDeleteTemplate, + api.Hooks.Wrap(srv.RouteDeleteTemplate), m, ), ) @@ -252,7 +252,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodGet, "/api/v1/provisioning/alert-rules/{UID}", - srv.RouteGetAlertRule, + api.Hooks.Wrap(srv.RouteGetAlertRule), m, ), ) @@ -262,7 +262,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodGet, "/api/v1/provisioning/alert-rules/{UID}/export", - srv.RouteGetAlertRuleExport, + api.Hooks.Wrap(srv.RouteGetAlertRuleExport), m, ), ) @@ -272,7 +272,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodGet, "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}", - srv.RouteGetAlertRuleGroup, + api.Hooks.Wrap(srv.RouteGetAlertRuleGroup), m, ), ) @@ -282,7 +282,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodGet, "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}/export", - srv.RouteGetAlertRuleGroupExport, + api.Hooks.Wrap(srv.RouteGetAlertRuleGroupExport), m, ), ) @@ -292,7 +292,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodGet, "/api/v1/provisioning/alert-rules", - srv.RouteGetAlertRules, + api.Hooks.Wrap(srv.RouteGetAlertRules), m, ), ) @@ -302,7 +302,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodGet, "/api/v1/provisioning/alert-rules/export", - srv.RouteGetAlertRulesExport, + api.Hooks.Wrap(srv.RouteGetAlertRulesExport), m, ), ) @@ -312,7 +312,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodGet, "/api/v1/provisioning/contact-points", - srv.RouteGetContactpoints, + api.Hooks.Wrap(srv.RouteGetContactpoints), m, ), ) @@ -322,7 +322,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodGet, "/api/v1/provisioning/mute-timings/{name}", - srv.RouteGetMuteTiming, + api.Hooks.Wrap(srv.RouteGetMuteTiming), m, ), ) @@ -332,7 +332,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodGet, "/api/v1/provisioning/mute-timings", - srv.RouteGetMuteTimings, + api.Hooks.Wrap(srv.RouteGetMuteTimings), m, ), ) @@ -342,7 +342,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodGet, "/api/v1/provisioning/policies", - srv.RouteGetPolicyTree, + api.Hooks.Wrap(srv.RouteGetPolicyTree), m, ), ) @@ -352,7 +352,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodGet, "/api/v1/provisioning/templates/{name}", - srv.RouteGetTemplate, + api.Hooks.Wrap(srv.RouteGetTemplate), m, ), ) @@ -362,7 +362,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodGet, "/api/v1/provisioning/templates", - srv.RouteGetTemplates, + api.Hooks.Wrap(srv.RouteGetTemplates), m, ), ) @@ -372,7 +372,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodPost, "/api/v1/provisioning/alert-rules", - srv.RoutePostAlertRule, + api.Hooks.Wrap(srv.RoutePostAlertRule), m, ), ) @@ -382,7 +382,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodPost, "/api/v1/provisioning/contact-points", - srv.RoutePostContactpoints, + api.Hooks.Wrap(srv.RoutePostContactpoints), m, ), ) @@ -392,7 +392,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodPost, "/api/v1/provisioning/mute-timings", - srv.RoutePostMuteTiming, + api.Hooks.Wrap(srv.RoutePostMuteTiming), m, ), ) @@ -402,7 +402,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodPut, "/api/v1/provisioning/alert-rules/{UID}", - srv.RoutePutAlertRule, + api.Hooks.Wrap(srv.RoutePutAlertRule), m, ), ) @@ -412,7 +412,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodPut, "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}", - srv.RoutePutAlertRuleGroup, + api.Hooks.Wrap(srv.RoutePutAlertRuleGroup), m, ), ) @@ -422,7 +422,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodPut, "/api/v1/provisioning/contact-points/{UID}", - srv.RoutePutContactpoint, + api.Hooks.Wrap(srv.RoutePutContactpoint), m, ), ) @@ -432,7 +432,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodPut, "/api/v1/provisioning/mute-timings/{name}", - srv.RoutePutMuteTiming, + api.Hooks.Wrap(srv.RoutePutMuteTiming), m, ), ) @@ -442,7 +442,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodPut, "/api/v1/provisioning/policies", - srv.RoutePutPolicyTree, + api.Hooks.Wrap(srv.RoutePutPolicyTree), m, ), ) @@ -452,7 +452,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodPut, "/api/v1/provisioning/templates/{name}", - srv.RoutePutTemplate, + api.Hooks.Wrap(srv.RoutePutTemplate), m, ), ) @@ -462,7 +462,7 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApi, m *metrics metrics.Instrument( http.MethodDelete, "/api/v1/provisioning/policies", - srv.RouteResetPolicyTree, + api.Hooks.Wrap(srv.RouteResetPolicyTree), m, ), ) diff --git a/pkg/services/ngalert/api/generated_base_api_ruler.go b/pkg/services/ngalert/api/generated_base_api_ruler.go index b5687db2a3f..1142093103b 100644 --- a/pkg/services/ngalert/api/generated_base_api_ruler.go +++ b/pkg/services/ngalert/api/generated_base_api_ruler.go @@ -119,7 +119,7 @@ func (api *API) RegisterRulerApiEndpoints(srv RulerApi, m *metrics.API) { metrics.Instrument( http.MethodDelete, "/api/ruler/grafana/api/v1/rules/{Namespace}/{Groupname}", - srv.RouteDeleteGrafanaRuleGroupConfig, + api.Hooks.Wrap(srv.RouteDeleteGrafanaRuleGroupConfig), m, ), ) @@ -129,7 +129,7 @@ func (api *API) RegisterRulerApiEndpoints(srv RulerApi, m *metrics.API) { metrics.Instrument( http.MethodDelete, "/api/ruler/grafana/api/v1/rules/{Namespace}", - srv.RouteDeleteNamespaceGrafanaRulesConfig, + api.Hooks.Wrap(srv.RouteDeleteNamespaceGrafanaRulesConfig), m, ), ) @@ -139,7 +139,7 @@ func (api *API) RegisterRulerApiEndpoints(srv RulerApi, m *metrics.API) { metrics.Instrument( http.MethodDelete, "/api/ruler/{DatasourceUID}/api/v1/rules/{Namespace}", - srv.RouteDeleteNamespaceRulesConfig, + api.Hooks.Wrap(srv.RouteDeleteNamespaceRulesConfig), m, ), ) @@ -149,7 +149,7 @@ func (api *API) RegisterRulerApiEndpoints(srv RulerApi, m *metrics.API) { metrics.Instrument( http.MethodDelete, "/api/ruler/{DatasourceUID}/api/v1/rules/{Namespace}/{Groupname}", - srv.RouteDeleteRuleGroupConfig, + api.Hooks.Wrap(srv.RouteDeleteRuleGroupConfig), m, ), ) @@ -159,7 +159,7 @@ func (api *API) RegisterRulerApiEndpoints(srv RulerApi, m *metrics.API) { metrics.Instrument( http.MethodGet, "/api/ruler/grafana/api/v1/rules/{Namespace}/{Groupname}", - srv.RouteGetGrafanaRuleGroupConfig, + api.Hooks.Wrap(srv.RouteGetGrafanaRuleGroupConfig), m, ), ) @@ -169,7 +169,7 @@ func (api *API) RegisterRulerApiEndpoints(srv RulerApi, m *metrics.API) { metrics.Instrument( http.MethodGet, "/api/ruler/grafana/api/v1/rules", - srv.RouteGetGrafanaRulesConfig, + api.Hooks.Wrap(srv.RouteGetGrafanaRulesConfig), m, ), ) @@ -179,7 +179,7 @@ func (api *API) RegisterRulerApiEndpoints(srv RulerApi, m *metrics.API) { metrics.Instrument( http.MethodGet, "/api/ruler/grafana/api/v1/rules/{Namespace}", - srv.RouteGetNamespaceGrafanaRulesConfig, + api.Hooks.Wrap(srv.RouteGetNamespaceGrafanaRulesConfig), m, ), ) @@ -189,7 +189,7 @@ func (api *API) RegisterRulerApiEndpoints(srv RulerApi, m *metrics.API) { metrics.Instrument( http.MethodGet, "/api/ruler/{DatasourceUID}/api/v1/rules/{Namespace}", - srv.RouteGetNamespaceRulesConfig, + api.Hooks.Wrap(srv.RouteGetNamespaceRulesConfig), m, ), ) @@ -199,7 +199,7 @@ func (api *API) RegisterRulerApiEndpoints(srv RulerApi, m *metrics.API) { metrics.Instrument( http.MethodGet, "/api/ruler/{DatasourceUID}/api/v1/rules/{Namespace}/{Groupname}", - srv.RouteGetRulegGroupConfig, + api.Hooks.Wrap(srv.RouteGetRulegGroupConfig), m, ), ) @@ -209,7 +209,7 @@ func (api *API) RegisterRulerApiEndpoints(srv RulerApi, m *metrics.API) { metrics.Instrument( http.MethodGet, "/api/ruler/{DatasourceUID}/api/v1/rules", - srv.RouteGetRulesConfig, + api.Hooks.Wrap(srv.RouteGetRulesConfig), m, ), ) @@ -219,7 +219,7 @@ func (api *API) RegisterRulerApiEndpoints(srv RulerApi, m *metrics.API) { metrics.Instrument( http.MethodPost, "/api/ruler/grafana/api/v1/rules/{Namespace}", - srv.RoutePostNameGrafanaRulesConfig, + api.Hooks.Wrap(srv.RoutePostNameGrafanaRulesConfig), m, ), ) @@ -229,7 +229,7 @@ func (api *API) RegisterRulerApiEndpoints(srv RulerApi, m *metrics.API) { metrics.Instrument( http.MethodPost, "/api/ruler/{DatasourceUID}/api/v1/rules/{Namespace}", - srv.RoutePostNameRulesConfig, + api.Hooks.Wrap(srv.RoutePostNameRulesConfig), m, ), ) diff --git a/pkg/services/ngalert/api/generated_base_api_testing.go b/pkg/services/ngalert/api/generated_base_api_testing.go index 6b3e104efab..342d0460b5f 100644 --- a/pkg/services/ngalert/api/generated_base_api_testing.go +++ b/pkg/services/ngalert/api/generated_base_api_testing.go @@ -68,7 +68,7 @@ func (api *API) RegisterTestingApiEndpoints(srv TestingApi, m *metrics.API) { metrics.Instrument( http.MethodPost, "/api/v1/rule/backtest", - srv.BacktestConfig, + api.Hooks.Wrap(srv.BacktestConfig), m, ), ) @@ -78,7 +78,7 @@ func (api *API) RegisterTestingApiEndpoints(srv TestingApi, m *metrics.API) { metrics.Instrument( http.MethodPost, "/api/v1/eval", - srv.RouteEvalQueries, + api.Hooks.Wrap(srv.RouteEvalQueries), m, ), ) @@ -88,7 +88,7 @@ func (api *API) RegisterTestingApiEndpoints(srv TestingApi, m *metrics.API) { metrics.Instrument( http.MethodPost, "/api/v1/rule/test/{DatasourceUID}", - srv.RouteTestRuleConfig, + api.Hooks.Wrap(srv.RouteTestRuleConfig), m, ), ) @@ -98,7 +98,7 @@ func (api *API) RegisterTestingApiEndpoints(srv TestingApi, m *metrics.API) { metrics.Instrument( http.MethodPost, "/api/v1/rule/test/grafana", - srv.RouteTestRuleGrafanaConfig, + api.Hooks.Wrap(srv.RouteTestRuleGrafanaConfig), m, ), ) diff --git a/pkg/services/ngalert/api/hooks.go b/pkg/services/ngalert/api/hooks.go new file mode 100644 index 00000000000..8b6c4dad804 --- /dev/null +++ b/pkg/services/ngalert/api/hooks.go @@ -0,0 +1,43 @@ +package api + +import ( + "github.com/grafana/grafana/pkg/api/response" + "github.com/grafana/grafana/pkg/infra/log" + contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" +) + +type RequestHandlerFunc func(*contextmodel.ReqContext) response.Response + +type Hooks struct { + logger log.Logger + hooks map[string]RequestHandlerFunc +} + +// NewHooks creates an empty set of request handler hooks. Hooks can be used +// to replace handlers for specific paths. +func NewHooks(logger log.Logger) *Hooks { + return &Hooks{ + logger: logger, + hooks: make(map[string]RequestHandlerFunc), + } +} + +// Add creates a new request hook for a path, causing requests to the path to +// be handled by the hook function, and not the original handler. +func (h *Hooks) Set(path string, hook RequestHandlerFunc) { + h.logger.Info("setting hook override for the specified route", "path", path) + h.hooks[path] = hook +} + +// Wrap returns a new handler which will intercept paths with hooks configured, +// and invoke the hooked in handler instead. If no hook is configured for a path, +// then the given handler is invoked. +func (h *Hooks) Wrap(next RequestHandlerFunc) RequestHandlerFunc { + return func(req *contextmodel.ReqContext) response.Response { + if hook, ok := h.hooks[req.Context.Req.URL.Path]; ok { + h.logger.Debug("hook defined - invoking new handler", "path", req.Context.Req.URL.Path) + return hook(req) + } + return next(req) + } +} diff --git a/pkg/services/ngalert/api/tooling/swagger-codegen/templates/controller-api.mustache b/pkg/services/ngalert/api/tooling/swagger-codegen/templates/controller-api.mustache index 7a7f7498108..7e15282fa38 100644 --- a/pkg/services/ngalert/api/tooling/swagger-codegen/templates/controller-api.mustache +++ b/pkg/services/ngalert/api/tooling/swagger-codegen/templates/controller-api.mustache @@ -40,7 +40,7 @@ func (api *API) Register{{classname}}Endpoints(srv {{classname}}, m *metrics.API metrics.Instrument( http.Method{{httpMethod}}, "{{{path}}}", - srv.{{nickname}}, + api.Hooks.Wrap(srv.{{nickname}}), m, ), ){{/operation}}{{/operations}} diff --git a/pkg/services/ngalert/ngalert.go b/pkg/services/ngalert/ngalert.go index 08f3c256fe2..7e4477bdb3d 100644 --- a/pkg/services/ngalert/ngalert.go +++ b/pkg/services/ngalert/ngalert.go @@ -127,6 +127,7 @@ type AlertNG struct { stateManager *state.Manager folderService folder.Service dashboardService dashboards.DashboardService + api *api.API // Alerting notification services MultiOrgAlertmanager *notifier.MultiOrgAlertmanager @@ -246,7 +247,7 @@ func (ng *AlertNG) init() error { int64(ng.Cfg.UnifiedAlerting.DefaultRuleEvaluationInterval.Seconds()), int64(ng.Cfg.UnifiedAlerting.BaseInterval.Seconds()), ng.Log) - api := api.API{ + ng.api = &api.API{ Cfg: ng.Cfg, DatasourceCache: ng.DataSourceCache, DatasourceService: ng.DataSourceService, @@ -271,8 +272,9 @@ func (ng *AlertNG) init() error { FeatureManager: ng.FeatureToggles, AppUrl: appUrl, Historian: history, + Hooks: api.NewHooks(ng.Log), } - api.RegisterAPIEndpoints(ng.Metrics.GetAPIMetrics()) + ng.api.RegisterAPIEndpoints(ng.Metrics.GetAPIMetrics()) defaultLimits, err := readQuotaConfig(ng.Cfg) if err != nil { @@ -282,7 +284,7 @@ func (ng *AlertNG) init() error { if err := ng.QuotaService.RegisterQuotaReporter("a.NewUsageReporter{ TargetSrv: models.QuotaTargetSrv, DefaultLimits: defaultLimits, - Reporter: api.Usage, + Reporter: ng.api.Usage, }); err != nil { return err } @@ -349,6 +351,12 @@ func (ng *AlertNG) IsDisabled() bool { return !ng.Cfg.UnifiedAlerting.IsEnabled() } +// GetHooks returns a facility for replacing handlers for paths. The handler hook for a path +// is invoked after all other middleware is invoked (authentication, instrumentation). +func (ng *AlertNG) GetHooks() *api.Hooks { + return ng.api.Hooks +} + func readQuotaConfig(cfg *setting.Cfg) (*quota.Map, error) { limits := "a.Map{}