diff --git a/cmd/alertmanager/main.go b/cmd/alertmanager/main.go index 18aec9ef..0a6c0727 100644 --- a/cmd/alertmanager/main.go +++ b/cmd/alertmanager/main.go @@ -131,7 +131,7 @@ const defaultClusterAddr = "0.0.0.0:9094" // buildReceiverIntegrations builds a list of integration notifiers off of a // receiver config. -func buildReceiverIntegrations(nc *config.Receiver, tmpl *template.Template, logger log.Logger) ([]notify.Integration, error) { +func buildReceiverIntegrations(nc config.Receiver, tmpl *template.Template, logger log.Logger) ([]notify.Integration, error) { var ( errs types.MultiError integrations []notify.Integration diff --git a/cmd/alertmanager/main_test.go b/cmd/alertmanager/main_test.go index ff3460a2..bc2a450d 100644 --- a/cmd/alertmanager/main_test.go +++ b/cmd/alertmanager/main_test.go @@ -31,12 +31,12 @@ func (s sendResolved) SendResolved() bool { return bool(s) } func TestBuildReceiverIntegrations(t *testing.T) { for _, tc := range []struct { - receiver *config.Receiver + receiver config.Receiver err bool exp []notify.Integration }{ { - receiver: &config.Receiver{ + receiver: config.Receiver{ Name: "foo", WebhookConfigs: []*config.WebhookConfig{ { @@ -56,7 +56,7 @@ func TestBuildReceiverIntegrations(t *testing.T) { }, }, { - receiver: &config.Receiver{ + receiver: config.Receiver{ Name: "foo", WebhookConfigs: []*config.WebhookConfig{ { diff --git a/config/config.go b/config/config.go index 21698681..d85dbe14 100644 --- a/config/config.go +++ b/config/config.go @@ -295,11 +295,11 @@ func (ti *TimeInterval) UnmarshalYAML(unmarshal func(interface{}) error) error { // Config is the top-level configuration for Alertmanager's config files. type Config struct { - Global *GlobalConfig `yaml:"global,omitempty" json:"global,omitempty"` - Route *Route `yaml:"route,omitempty" json:"route,omitempty"` - InhibitRules []*InhibitRule `yaml:"inhibit_rules,omitempty" json:"inhibit_rules,omitempty"` - Receivers []*Receiver `yaml:"receivers,omitempty" json:"receivers,omitempty"` - Templates []string `yaml:"templates" json:"templates"` + Global *GlobalConfig `yaml:"global,omitempty" json:"global,omitempty"` + Route *Route `yaml:"route,omitempty" json:"route,omitempty"` + InhibitRules []InhibitRule `yaml:"inhibit_rules,omitempty" json:"inhibit_rules,omitempty"` + Receivers []Receiver `yaml:"receivers,omitempty" json:"receivers,omitempty"` + Templates []string `yaml:"templates" json:"templates"` // Deprecated. Remove before v1.0 release. MuteTimeIntervals []MuteTimeInterval `yaml:"mute_time_intervals,omitempty" json:"mute_time_intervals,omitempty"` TimeIntervals []TimeInterval `yaml:"time_intervals,omitempty" json:"time_intervals,omitempty"` diff --git a/config/config_test.go b/config/config_test.go index 5855eac7..7631d37c 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -895,7 +895,7 @@ func TestEmptyFieldsAndRegex(t *testing.T) { }, }, }, - Receivers: []*Receiver{ + Receivers: []Receiver{ { Name: "team-X-mails", EmailConfigs: []*EmailConfig{ diff --git a/inhibit/inhibit.go b/inhibit/inhibit.go index 0b90485b..a8f96f28 100644 --- a/inhibit/inhibit.go +++ b/inhibit/inhibit.go @@ -44,7 +44,7 @@ type Inhibitor struct { } // NewInhibitor returns a new Inhibitor. -func NewInhibitor(ap provider.Alerts, rs []*config.InhibitRule, mk types.Marker, logger log.Logger) *Inhibitor { +func NewInhibitor(ap provider.Alerts, rs []config.InhibitRule, mk types.Marker, logger log.Logger) *Inhibitor { ih := &Inhibitor{ alerts: ap, marker: mk, @@ -166,7 +166,7 @@ type InhibitRule struct { } // NewInhibitRule returns a new InhibitRule based on a configuration definition. -func NewInhibitRule(cr *config.InhibitRule) *InhibitRule { +func NewInhibitRule(cr config.InhibitRule) *InhibitRule { var ( sourcem labels.Matchers targetm labels.Matchers diff --git a/inhibit/inhibit_test.go b/inhibit/inhibit_test.go index 1b34bf88..24089a67 100644 --- a/inhibit/inhibit_test.go +++ b/inhibit/inhibit_test.go @@ -153,7 +153,7 @@ func TestInhibitRuleMatches(t *testing.T) { } m := types.NewMarker(prometheus.NewRegistry()) - ih := NewInhibitor(nil, []*config.InhibitRule{&rule1, &rule2}, m, nopLogger) + ih := NewInhibitor(nil, []config.InhibitRule{rule1, rule2}, m, nopLogger) now := time.Now() // Active alert that matches the source filter of rule1. sourceAlert1 := &types.Alert{ @@ -249,7 +249,7 @@ func TestInhibitRuleMatchers(t *testing.T) { } m := types.NewMarker(prometheus.NewRegistry()) - ih := NewInhibitor(nil, []*config.InhibitRule{&rule1, &rule2}, m, nopLogger) + ih := NewInhibitor(nil, []config.InhibitRule{rule1, rule2}, m, nopLogger) now := time.Now() // Active alert that matches the source filter of rule1. sourceAlert1 := &types.Alert{ @@ -370,8 +370,8 @@ func TestInhibit(t *testing.T) { t.Parallel() now := time.Now() - inhibitRule := func() *config.InhibitRule { - return &config.InhibitRule{ + inhibitRule := func() config.InhibitRule { + return config.InhibitRule{ SourceMatch: map[string]string{"s": "1"}, TargetMatch: map[string]string{"t": "1"}, Equal: model.LabelNames{"e"}, @@ -452,7 +452,7 @@ func TestInhibit(t *testing.T) { } { ap := newFakeAlerts(tc.alerts) mk := types.NewMarker(prometheus.NewRegistry()) - inhibitor := NewInhibitor(ap, []*config.InhibitRule{inhibitRule()}, mk, nopLogger) + inhibitor := NewInhibitor(ap, []config.InhibitRule{inhibitRule()}, mk, nopLogger) go func() { for ap.finished != nil { diff --git a/test/with_api_v2/acceptance/inhibit_test.go b/test/with_api_v2/acceptance/inhibit_test.go index 61502e04..e4f303ec 100644 --- a/test/with_api_v2/acceptance/inhibit_test.go +++ b/test/with_api_v2/acceptance/inhibit_test.go @@ -154,3 +154,39 @@ inhibit_rules: t.Log(co.Check()) } + +func TestEmptyInhibitionRule(t *testing.T) { + t.Parallel() + + // This integration test checks that when we have empty inhibition rules, + // there is no panic caused by null-pointer references. + + conf := ` +route: + receiver: "default" + group_by: [] + group_wait: 1s + group_interval: 1s + repeat_interval: 1s + +receivers: +- name: "default" + webhook_configs: + - url: 'http://%s' + +inhibit_rules: +- +` + + at := NewAcceptanceTest(t, &AcceptanceOpts{ + Tolerance: 150 * time.Millisecond, + }) + + co := at.Collector("webhook") + wh := NewWebhook(t, co) + + at.AlertmanagerCluster(fmt.Sprintf(conf, wh.Address()), 1) + at.Run() + + t.Log(co.Check()) +}