Alerting: create wrapper for Alertmanager to enable org level isolation (#37320)

Introduces org-level isolation for the Alertmanager and its components.

Silences, Alerts and Contact points are not separated by org and are not shared between them.

Co-authored with @davidmparrott and @papagian
This commit is contained in:
David Parrott
2021-08-24 03:28:09 -07:00
committed by GitHub
parent 7ebf4027a7
commit 7fbeefc090
19 changed files with 673 additions and 148 deletions
@@ -6,6 +6,9 @@ import (
"net/http"
"regexp"
"testing"
"time"
"github.com/grafana/grafana/pkg/services/ngalert/notifier"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/models"
@@ -16,6 +19,13 @@ import (
)
func TestAlertmanagerConfigurationIsTransactional(t *testing.T) {
// TODO: We need a reliable way to ensure Alertmanagers have synced correctly.
// For now, make them sync quicker.
p := notifier.SyncOrgsPollInterval
notifier.SyncOrgsPollInterval = 2 * time.Second
t.Cleanup(func() {
notifier.SyncOrgsPollInterval = p
})
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
EnableFeatureToggles: []string{"ngalert"},
DisableAnonymous: true,
@@ -85,7 +95,7 @@ func TestAlertmanagerConfigurationIsTransactional(t *testing.T) {
}
`
resp := postRequest(t, alertConfigURL, payload, http.StatusBadRequest) // nolint
require.JSONEq(t, `{"message":"failed to save and apply Alertmanager configuration: the receiver is invalid: failed to validate receiver \"slack.receiver\" of type \"slack\": token must be specified when using the Slack chat API"}`, getBody(t, resp.Body))
require.JSONEq(t, `{"message":"failed to save and apply Alertmanager configuration: failed to build integration map: the receiver is invalid: failed to validate receiver \"slack.receiver\" of type \"slack\": token must be specified when using the Slack chat API"}`, getBody(t, resp.Body))
resp = getRequest(t, alertConfigURL, http.StatusOK) // nolint
require.JSONEq(t, defaultAlertmanagerConfigJSON, getBody(t, resp.Body))
@@ -94,6 +104,13 @@ func TestAlertmanagerConfigurationIsTransactional(t *testing.T) {
// editor42 from organisation 42 posts configuration
alertConfigURL = fmt.Sprintf("http://editor-42:editor-42@%s/api/alertmanager/grafana/config/api/v1/alerts", grafanaListedAddr)
// Before we start operating, make sure we've synced this org.
require.Eventually(t, func() bool {
resp, err := http.Get(alertConfigURL) // nolint
require.NoError(t, err)
return resp.StatusCode == http.StatusOK
}, 10*time.Second, 2*time.Second)
// Post the alertmanager config.
{
mockChannel := newMockNotificationChannel(t, grafanaListedAddr)