Skip to content

Commit

Permalink
move logic to computeConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
santihernandezc committed Jan 22, 2025
1 parent 0709703 commit a32f18d
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 73 deletions.
60 changes: 28 additions & 32 deletions pkg/alertmanager/multitenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -669,38 +669,31 @@ func (am *MultitenantAlertmanager) syncConfigs(ctx context.Context, cfgMap map[s
level.Debug(am.logger).Log("msg", "adding configurations", "num_configs", len(cfgMap))
userAlertmanagersToStop := map[string]*Alertmanager{}
for user, cfgs := range cfgMap {
cfg, err := am.computeConfig(cfgs)
cfg, startAM, err := am.computeConfig(cfgs)
if err != nil {
am.multitenantMetrics.lastReloadSuccessful.WithLabelValues(user).Set(float64(0))
level.Warn(am.logger).Log("msg", "error computing config", "err", err)
continue
}

if am.cfg.GrafanaAlertmanagerTenantSuffix != "" {
if !cfg.usingGrafanaConfig && strings.HasSuffix(user, am.cfg.GrafanaAlertmanagerTenantSuffix) {
// Avoid starting the Alertmanager for Grafana tenants not using a Grafana configuration.
level.Debug(am.logger).Log("msg", "not initializing alertmanager for grafana tenant without promoted, non-default configuration", "user", user)
am.alertmanagersMtx.Lock()
if userAM, ok := am.alertmanagers[user]; ok {
userAlertmanagersToStop[user] = userAM
delete(am.alertmanagers, user)
delete(am.cfgs, user)
am.multitenantMetrics.lastReloadSuccessful.DeleteLabelValues(user)
am.multitenantMetrics.lastReloadSuccessfulTimestamp.DeleteLabelValues(user)
am.alertmanagerMetrics.removeUserRegistry(user)
}
am.alertmanagersMtx.Unlock()
continue
if !startAM {
level.Debug(am.logger).Log("msg", "not initializing alertmanager for grafana tenant without promoted, non-default configuration", "user", user)
am.alertmanagersMtx.Lock()
if userAM, ok := am.alertmanagers[user]; ok {
// Stop the Alertmanager if already running.
userAlertmanagersToStop[user] = userAM
delete(am.alertmanagers, user)
delete(am.cfgs, user)
am.multitenantMetrics.lastReloadSuccessful.DeleteLabelValues(user)
am.multitenantMetrics.lastReloadSuccessfulTimestamp.DeleteLabelValues(user)
am.alertmanagerMetrics.removeUserRegistry(user)
}
am.alertmanagersMtx.Unlock()
continue
}

// Promote state if needed.
if err := am.syncStates(ctx, cfg); err != nil {
level.Error(am.logger).Log("msg", "error syncing states", "err", err, "user", user)
}
} else {
if err := am.syncStates(ctx, cfg); err != nil {
level.Error(am.logger).Log("msg", "error syncing states", "err", err, "user", user)
}
if err := am.syncStates(ctx, cfg); err != nil {
level.Error(am.logger).Log("msg", "error syncing states", "err", err, "user", user)
}

if err := am.setConfig(cfg); err != nil {
Expand Down Expand Up @@ -735,41 +728,44 @@ func (am *MultitenantAlertmanager) syncConfigs(ctx context.Context, cfgMap map[s
}

// computeConfig takes an AlertConfigDescs struct containing Mimir and Grafana configurations.
// It returns the final configuration and external URL the Alertmanager will use.
func (am *MultitenantAlertmanager) computeConfig(cfgs alertspb.AlertConfigDescs) (amConfig, error) {
// It returns the final configuration and a bool indicating whether the Alertmanager shoould be started for the tenant.
func (am *MultitenantAlertmanager) computeConfig(cfgs alertspb.AlertConfigDescs) (amConfig, bool, error) {
cfg := amConfig{
AlertConfigDesc: cfgs.Mimir,
tmplExternalURL: am.cfg.ExternalURL.URL,
}

isGrafanaTenant := am.cfg.GrafanaAlertmanagerTenantSuffix != "" && strings.HasSuffix(cfgs.Mimir.User, am.cfg.GrafanaAlertmanagerTenantSuffix)
switch {
// Mimir configuration.
case !cfgs.Grafana.Promoted:
level.Debug(am.logger).Log("msg", "grafana configuration not promoted, using mimir config", "user", cfgs.Mimir.User)
return cfg, nil
return cfg, !isGrafanaTenant, nil

case cfgs.Grafana.Default:
level.Debug(am.logger).Log("msg", "grafana configuration is default, using mimir config", "user", cfgs.Mimir.User)
return cfg, nil
return cfg, !isGrafanaTenant, nil

case cfgs.Grafana.RawConfig == "":
level.Debug(am.logger).Log("msg", "grafana configuration is empty, using mimir config", "user", cfgs.Mimir.User)
return cfg, nil
return cfg, !isGrafanaTenant, nil

// Grafana configuration.
case cfgs.Mimir.RawConfig == am.fallbackConfig:
level.Debug(am.logger).Log("msg", "mimir configuration is default, using grafana config with the default globals", "user", cfgs.Mimir.User)
return createUsableGrafanaConfig(cfgs.Grafana, cfgs.Mimir.RawConfig)
cfg, err := createUsableGrafanaConfig(cfgs.Grafana, cfgs.Mimir.RawConfig)
return cfg, true, err

case cfgs.Mimir.RawConfig == "":
level.Debug(am.logger).Log("msg", "mimir configuration is empty, using grafana config with the default globals", "user", cfgs.Grafana.User)
return createUsableGrafanaConfig(cfgs.Grafana, am.fallbackConfig)
cfg, err := createUsableGrafanaConfig(cfgs.Grafana, am.fallbackConfig)
return cfg, true, err

// Both configurations.
// TODO: merge configurations.
default:
level.Warn(am.logger).Log("msg", "merging configurations not implemented, using mimir config", "user", cfgs.Mimir.User)
return cfg, nil
return cfg, true, nil
}
}

Expand Down
94 changes: 53 additions & 41 deletions pkg/alertmanager/multitenant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2506,6 +2506,11 @@ func TestComputeConfig(t *testing.T) {
cfg := mockAlertmanagerConfig(t)
am := setupSingleMultitenantAlertmanager(t, cfg, store, nil, featurecontrol.NoopFlags{}, log.NewNopLogger(), reg)

reg2 := prometheus.NewPedanticRegistry()
cfg2 := mockAlertmanagerConfig(t)
cfg2.GrafanaAlertmanagerTenantSuffix = "-grafana"
amWithSuffix := setupSingleMultitenantAlertmanager(t, cfg2, store, nil, featurecontrol.NoopFlags{}, log.NewNopLogger(), reg2)

var grafanaCfg GrafanaAlertmanagerConfig
require.NoError(t, json.Unmarshal([]byte(grafanaConfig), &grafanaCfg))

Expand All @@ -2523,6 +2528,7 @@ func TestComputeConfig(t *testing.T) {
tests := []struct {
name string
cfg alertspb.AlertConfigDescs
expStartAM bool
expErr string
expCfg alertspb.AlertConfigDesc
expURL string
Expand All @@ -2532,12 +2538,13 @@ func TestComputeConfig(t *testing.T) {
name: "no grafana configuration",
cfg: alertspb.AlertConfigDescs{
Mimir: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: simpleConfigOne,
},
},
expStartAM: false,
expCfg: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: simpleConfigOne,
},
expURL: mimirExternalURL,
Expand All @@ -2546,20 +2553,21 @@ func TestComputeConfig(t *testing.T) {
name: "empty grafana configuration",
cfg: alertspb.AlertConfigDescs{
Mimir: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: simpleConfigOne,
},
Grafana: alertspb.GrafanaAlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: "",
Default: false,
Promoted: true,
ExternalUrl: grafanaExternalURL,
StaticHeaders: map[string]string{"Test-Header": "test-value"},
},
},
expStartAM: false,
expCfg: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: simpleConfigOne,
},
expURL: mimirExternalURL,
Expand All @@ -2568,19 +2576,20 @@ func TestComputeConfig(t *testing.T) {
name: "grafana configuration is not promoted",
cfg: alertspb.AlertConfigDescs{
Mimir: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: simpleConfigOne,
},
Grafana: alertspb.GrafanaAlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: grafanaConfig,
Promoted: false,
ExternalUrl: grafanaExternalURL,
StaticHeaders: map[string]string{"Test-Header": "test-value"},
},
},
expStartAM: false,
expCfg: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: simpleConfigOne,
},
expURL: mimirExternalURL,
Expand All @@ -2589,62 +2598,44 @@ func TestComputeConfig(t *testing.T) {
name: "grafana configuration is default",
cfg: alertspb.AlertConfigDescs{
Mimir: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: simpleConfigOne,
},
Grafana: alertspb.GrafanaAlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: grafanaConfig,
Default: true,
Promoted: true,
ExternalUrl: grafanaExternalURL,
StaticHeaders: map[string]string{"Test-Header": "test-value"},
},
},
expStartAM: false,
expCfg: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: simpleConfigOne,
},
expURL: mimirExternalURL,
},
{
name: "no mimir configuration",
cfg: alertspb.AlertConfigDescs{
Grafana: alertspb.GrafanaAlertConfigDesc{
User: "user",
RawConfig: grafanaConfig,
Default: false,
Promoted: true,
ExternalUrl: grafanaExternalURL,
StaticHeaders: map[string]string{"Test-Header": "test-value"},
},
},
expCfg: alertspb.AlertConfigDesc{
User: "user",
RawConfig: string(combinedCfg),
Templates: []*alertspb.TemplateDesc{},
},
expURL: grafanaExternalURL,
expHeaders: map[string]string{"Test-Header": "test-value"},
},
{
name: "empty mimir configuration",
cfg: alertspb.AlertConfigDescs{
Mimir: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: "",
},
Grafana: alertspb.GrafanaAlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: grafanaConfig,
Default: false,
Promoted: true,
ExternalUrl: grafanaExternalURL,
StaticHeaders: map[string]string{"Test-Header-1": "test-value-1", "Test-Header-2": "test-value-2"},
},
},
expStartAM: true,
expCfg: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: string(combinedCfg),
Templates: []*alertspb.TemplateDesc{},
},
Expand All @@ -2655,20 +2646,21 @@ func TestComputeConfig(t *testing.T) {
name: "default mimir configuration",
cfg: alertspb.AlertConfigDescs{
Mimir: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: am.fallbackConfig,
},
Grafana: alertspb.GrafanaAlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: grafanaConfig,
Default: false,
Promoted: true,
ExternalUrl: grafanaExternalURL,
StaticHeaders: map[string]string{"Test-Header-1": "test-value-1", "Test-Header-2": "test-value-2"},
},
},
expStartAM: true,
expCfg: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: string(combinedCfg),
Templates: []*alertspb.TemplateDesc{},
},
Expand All @@ -2680,20 +2672,21 @@ func TestComputeConfig(t *testing.T) {
name: "both mimir and grafana configurations (merging not implemented)",
cfg: alertspb.AlertConfigDescs{
Mimir: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: simpleConfigOne,
},
Grafana: alertspb.GrafanaAlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: grafanaConfig,
Default: false,
Promoted: true,
ExternalUrl: grafanaExternalURL,
StaticHeaders: map[string]string{"Test-Header-1": "test-value-1", "Test-Header-2": "test-value-2"},
},
},
expStartAM: true,
expCfg: alertspb.AlertConfigDesc{
User: "user",
User: "user-grafana",
RawConfig: simpleConfigOne,
},
expURL: am.cfg.ExternalURL.String(),
Expand All @@ -2702,12 +2695,31 @@ func TestComputeConfig(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
cfg, err := am.computeConfig(test.cfg)
cfg, startAM, err := am.computeConfig(test.cfg)
if test.expErr != "" {
require.EqualError(t, err, test.expErr)
return
}

require.True(t, startAM)
require.NoError(t, err)
require.Equal(t, test.expCfg, cfg.AlertConfigDesc)
require.Equal(t, test.expURL, cfg.tmplExternalURL.String())
require.Equal(t, test.expHeaders, cfg.staticHeaders)
})

t.Run(fmt.Sprintf("%s with Grafana tenant suffix", test.name), func(t *testing.T) {
cfg, startAM, err := amWithSuffix.computeConfig(test.cfg)
if test.expErr != "" {
require.EqualError(t, err, test.expErr)
return
}

if !test.expStartAM {
require.False(t, startAM)
return
}
require.True(t, startAM)
require.NoError(t, err)
require.Equal(t, test.expCfg, cfg.AlertConfigDesc)
require.Equal(t, test.expURL, cfg.tmplExternalURL.String())
Expand Down

0 comments on commit a32f18d

Please sign in to comment.