Alerting: API to read rule groups using mimirtool (#100674)

This commit is contained in:
Alexander Akhmetov
2025-02-25 15:49:08 +01:00
committed by GitHub
parent d83db31a23
commit 6eb335a8ce
18 changed files with 836 additions and 125 deletions
+84 -29
View File
@@ -546,14 +546,14 @@ func (a apiClient) PostSilence(t *testing.T, s apimodels.PostableSilence) (apimo
req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/api/alertmanager/grafana/api/v2/silences", a.url), bytes.NewReader(b))
require.NoError(t, err)
req.Header.Set("Content-Type", "application/json")
return sendRequest[apimodels.PostSilencesOKBody](t, req, http.StatusAccepted)
return sendRequestJSON[apimodels.PostSilencesOKBody](t, req, http.StatusAccepted)
}
func (a apiClient) GetSilence(t *testing.T, id string) (apimodels.GettableSilence, int, string) {
t.Helper()
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/alertmanager/grafana/api/v2/silence/%s", a.url, id), nil)
require.NoError(t, err)
return sendRequest[apimodels.GettableSilence](t, req, http.StatusOK)
return sendRequestJSON[apimodels.GettableSilence](t, req, http.StatusOK)
}
func (a apiClient) GetSilences(t *testing.T, filters ...string) (apimodels.GettableSilences, int, string) {
@@ -568,7 +568,7 @@ func (a apiClient) GetSilences(t *testing.T, filters ...string) (apimodels.Getta
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
require.NoError(t, err)
return sendRequest[apimodels.GettableSilences](t, req, http.StatusOK)
return sendRequestJSON[apimodels.GettableSilences](t, req, http.StatusOK)
}
func (a apiClient) DeleteSilence(t *testing.T, id string) (any, int, string) {
@@ -580,7 +580,7 @@ func (a apiClient) DeleteSilence(t *testing.T, id string) (any, int, string) {
Message string `json:"message"`
}
return sendRequest[dynamic](t, req, http.StatusOK)
return sendRequestJSON[dynamic](t, req, http.StatusOK)
}
func (a apiClient) GetRulesGroup(t *testing.T, folder string, group string) (apimodels.RuleGroupConfigResponse, int) {
@@ -694,7 +694,7 @@ func (a apiClient) GetRuleGroupProvisioning(t *testing.T, folderUID string, grou
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/v1/provisioning/folder/%s/rule-groups/%s", a.url, folderUID, groupName), nil)
require.NoError(t, err)
return sendRequest[apimodels.AlertRuleGroup](t, req, http.StatusOK)
return sendRequestJSON[apimodels.AlertRuleGroup](t, req, http.StatusOK)
}
func (a apiClient) CreateOrUpdateRuleGroupProvisioning(t *testing.T, group apimodels.AlertRuleGroup) (apimodels.AlertRuleGroup, int, string) {
@@ -709,7 +709,7 @@ func (a apiClient) CreateOrUpdateRuleGroupProvisioning(t *testing.T, group apimo
require.NoError(t, err)
req.Header.Add("Content-Type", "application/json")
return sendRequest[apimodels.AlertRuleGroup](t, req, http.StatusOK)
return sendRequestJSON[apimodels.AlertRuleGroup](t, req, http.StatusOK)
}
func (a apiClient) SubmitRuleForBacktesting(t *testing.T, config apimodels.BacktestConfig) (int, string) {
@@ -808,7 +808,7 @@ func (a apiClient) GetAllMuteTimingsWithStatus(t *testing.T) (apimodels.MuteTimi
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/v1/provisioning/mute-timings", a.url), nil)
require.NoError(t, err)
return sendRequest[apimodels.MuteTimings](t, req, http.StatusOK)
return sendRequestJSON[apimodels.MuteTimings](t, req, http.StatusOK)
}
func (a apiClient) GetMuteTimingByNameWithStatus(t *testing.T, name string) (apimodels.MuteTimeInterval, int, string) {
@@ -817,7 +817,7 @@ func (a apiClient) GetMuteTimingByNameWithStatus(t *testing.T, name string) (api
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/v1/provisioning/mute-timings/%s", a.url, name), nil)
require.NoError(t, err)
return sendRequest[apimodels.MuteTimeInterval](t, req, http.StatusOK)
return sendRequestJSON[apimodels.MuteTimeInterval](t, req, http.StatusOK)
}
func (a apiClient) CreateMuteTimingWithStatus(t *testing.T, interval apimodels.MuteTimeInterval) (apimodels.MuteTimeInterval, int, string) {
@@ -832,7 +832,7 @@ func (a apiClient) CreateMuteTimingWithStatus(t *testing.T, interval apimodels.M
req.Header.Add("Content-Type", "application/json")
require.NoError(t, err)
return sendRequest[apimodels.MuteTimeInterval](t, req, http.StatusCreated)
return sendRequestJSON[apimodels.MuteTimeInterval](t, req, http.StatusCreated)
}
func (a apiClient) EnsureMuteTiming(t *testing.T, interval apimodels.MuteTimeInterval) {
@@ -854,7 +854,7 @@ func (a apiClient) UpdateMuteTimingWithStatus(t *testing.T, interval apimodels.M
req.Header.Add("Content-Type", "application/json")
require.NoError(t, err)
return sendRequest[apimodels.MuteTimeInterval](t, req, http.StatusAccepted)
return sendRequestJSON[apimodels.MuteTimeInterval](t, req, http.StatusAccepted)
}
func (a apiClient) DeleteMuteTimingWithStatus(t *testing.T, name string) (int, string) {
@@ -908,7 +908,7 @@ func (a apiClient) GetRouteWithStatus(t *testing.T) (apimodels.Route, int, strin
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/v1/provisioning/policies", a.url), nil)
require.NoError(t, err)
return sendRequest[apimodels.Route](t, req, http.StatusOK)
return sendRequestJSON[apimodels.Route](t, req, http.StatusOK)
}
func (a apiClient) GetRoute(t *testing.T) apimodels.Route {
@@ -989,7 +989,7 @@ func (a apiClient) GetRuleHistoryWithStatus(t *testing.T, ruleUID string) (data.
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
require.NoError(t, err)
return sendRequest[data.Frame](t, req, http.StatusOK)
return sendRequestJSON[data.Frame](t, req, http.StatusOK)
}
func (a apiClient) GetAllTimeIntervalsWithStatus(t *testing.T) ([]apimodels.GettableTimeIntervals, int, string) {
@@ -998,7 +998,7 @@ func (a apiClient) GetAllTimeIntervalsWithStatus(t *testing.T) ([]apimodels.Gett
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/v1/notifications/time-intervals", a.url), nil)
require.NoError(t, err)
return sendRequest[[]apimodels.GettableTimeIntervals](t, req, http.StatusOK)
return sendRequestJSON[[]apimodels.GettableTimeIntervals](t, req, http.StatusOK)
}
func (a apiClient) GetTimeIntervalByNameWithStatus(t *testing.T, name string) (apimodels.GettableTimeIntervals, int, string) {
@@ -1007,7 +1007,7 @@ func (a apiClient) GetTimeIntervalByNameWithStatus(t *testing.T, name string) (a
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/v1/notifications/time-intervals/%s", a.url, name), nil)
require.NoError(t, err)
return sendRequest[apimodels.GettableTimeIntervals](t, req, http.StatusOK)
return sendRequestJSON[apimodels.GettableTimeIntervals](t, req, http.StatusOK)
}
func (a apiClient) CreateReceiverWithStatus(t *testing.T, receiver apimodels.EmbeddedContactPoint) (apimodels.EmbeddedContactPoint, int, string) {
@@ -1022,7 +1022,7 @@ func (a apiClient) CreateReceiverWithStatus(t *testing.T, receiver apimodels.Emb
req.Header.Add("Content-Type", "application/json")
require.NoError(t, err)
return sendRequest[apimodels.EmbeddedContactPoint](t, req, http.StatusAccepted)
return sendRequestJSON[apimodels.EmbeddedContactPoint](t, req, http.StatusAccepted)
}
func (a apiClient) EnsureReceiver(t *testing.T, receiver apimodels.EmbeddedContactPoint) {
@@ -1075,33 +1075,33 @@ func (a apiClient) GetAlertmanagerConfigWithStatus(t *testing.T) (apimodels.Gett
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/alertmanager/grafana/config/api/v1/alerts", a.url), nil)
require.NoError(t, err)
return sendRequest[apimodels.GettableUserConfig](t, req, http.StatusOK)
return sendRequestJSON[apimodels.GettableUserConfig](t, req, http.StatusOK)
}
func (a apiClient) GetActiveAlertsWithStatus(t *testing.T) (apimodels.AlertGroups, int, string) {
t.Helper()
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/alertmanager/grafana/api/v2/alerts/groups", a.url), nil)
require.NoError(t, err)
return sendRequest[apimodels.AlertGroups](t, req, http.StatusOK)
return sendRequestJSON[apimodels.AlertGroups](t, req, http.StatusOK)
}
func (a apiClient) GetRuleVersionsWithStatus(t *testing.T, ruleUID string) (apimodels.GettableRuleVersions, int, string) {
t.Helper()
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/ruler/grafana/api/v1/rule/%s/versions", a.url, ruleUID), nil)
require.NoError(t, err)
return sendRequest[apimodels.GettableRuleVersions](t, req, http.StatusOK)
return sendRequestJSON[apimodels.GettableRuleVersions](t, req, http.StatusOK)
}
func (a apiClient) GetRuleByUID(t *testing.T, ruleUID string) apimodels.GettableExtendedRuleNode {
t.Helper()
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/ruler/grafana/api/v1/rule/%s", a.url, ruleUID), nil)
require.NoError(t, err)
rule, status, raw := sendRequest[apimodels.GettableExtendedRuleNode](t, req, http.StatusOK)
rule, status, raw := sendRequestJSON[apimodels.GettableExtendedRuleNode](t, req, http.StatusOK)
requireStatusCode(t, http.StatusOK, status, raw)
return rule
}
func (a apiClient) ConvertPrometheusPostRuleGroup(t *testing.T, namespaceTitle, datasourceUID string, promGroup apimodels.PrometheusRuleGroup, headers map[string]string) {
func (a apiClient) ConvertPrometheusPostRuleGroup(t *testing.T, namespaceTitle, datasourceUID string, promGroup apimodels.PrometheusRuleGroup, headers map[string]string) (apimodels.ConvertPrometheusResponse, int, string) {
t.Helper()
data, err := yaml.Marshal(promGroup)
@@ -1116,30 +1116,85 @@ func (a apiClient) ConvertPrometheusPostRuleGroup(t *testing.T, namespaceTitle,
req.Header.Add(key, value)
}
_, status, raw := sendRequest[apimodels.ConvertPrometheusResponse](t, req, http.StatusAccepted)
requireStatusCode(t, http.StatusAccepted, status, raw)
return sendRequestJSON[apimodels.ConvertPrometheusResponse](t, req, http.StatusAccepted)
}
func sendRequest[T any](t *testing.T, req *http.Request, successStatusCode int) (T, int, string) {
func (a apiClient) ConvertPrometheusGetRuleGroupRules(t *testing.T, namespaceTitle, groupName string) apimodels.PrometheusRuleGroup {
t.Helper()
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/convert/prometheus/config/v1/rules/%s/%s", a.url, namespaceTitle, groupName), nil)
require.NoError(t, err)
rule, status, raw := sendRequestYAML[apimodels.PrometheusRuleGroup](t, req, http.StatusOK)
requireStatusCode(t, http.StatusOK, status, raw)
return rule
}
func (a apiClient) ConvertPrometheusGetNamespaceRules(t *testing.T, namespaceTitle string) map[string][]apimodels.PrometheusRuleGroup {
t.Helper()
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/convert/prometheus/config/v1/rules/%s", a.url, namespaceTitle), nil)
require.NoError(t, err)
ns, status, raw := sendRequestYAML[map[string][]apimodels.PrometheusRuleGroup](t, req, http.StatusOK)
requireStatusCode(t, http.StatusOK, status, raw)
return ns
}
func (a apiClient) ConvertPrometheusGetAllRules(t *testing.T) map[string][]apimodels.PrometheusRuleGroup {
t.Helper()
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/convert/prometheus/config/v1/rules", a.url), nil)
require.NoError(t, err)
result, status, raw := sendRequestYAML[map[string][]apimodels.PrometheusRuleGroup](t, req, http.StatusOK)
requireStatusCode(t, http.StatusOK, status, raw)
return result
}
func sendRequestRaw(t *testing.T, req *http.Request) ([]byte, int, error) {
t.Helper()
client := &http.Client{}
resp, err := client.Do(req)
require.NoError(t, err)
if err != nil {
return nil, 0, err
}
defer func() {
_ = resp.Body.Close()
}()
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, 0, err
}
return body, resp.StatusCode, nil
}
func sendRequestJSON[T any](t *testing.T, req *http.Request, successStatusCode int) (T, int, string) {
t.Helper()
var result T
if resp.StatusCode != successStatusCode {
return result, resp.StatusCode, string(body)
body, statusCode, err := sendRequestRaw(t, req)
require.NoError(t, err)
if statusCode != successStatusCode {
return result, statusCode, string(body)
}
err = json.Unmarshal(body, &result)
require.NoError(t, err)
return result, resp.StatusCode, string(body)
return result, statusCode, string(body)
}
func sendRequestYAML[T any](t *testing.T, req *http.Request, successStatusCode int) (T, int, string) {
t.Helper()
var result T
body, statusCode, err := sendRequestRaw(t, req)
require.NoError(t, err)
if statusCode != successStatusCode {
return result, statusCode, string(body)
}
err = yaml.Unmarshal(body, &result)
require.NoError(t, err)
return result, statusCode, string(body)
}
func requireStatusCode(t *testing.T, expected, actual int, response string) {