Add test for PromQL braces when parsing lists of matchers (#3507)

* Add test for PromQL braces when parsing lists of matchers

Signed-off-by: George Robinson <george.robinson@grafana.com>

* Use acceptance tests

Signed-off-by: George Robinson <george.robinson@grafana.com>

* Add test creating silence with braces

Signed-off-by: George Robinson <george.robinson@grafana.com>

---------

Signed-off-by: George Robinson <george.robinson@grafana.com>
This commit is contained in:
George Robinson 2023-09-12 17:00:18 +01:00 committed by GitHub
parent aa3e345017
commit 5ba9b9c7c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 21 deletions

View File

@ -490,9 +490,10 @@ func (am *Alertmanager) addAlertCommand(alert *TestAlert) ([]byte, error) {
} }
// QueryAlerts uses the amtool cli to query alerts. // QueryAlerts uses the amtool cli to query alerts.
func (am *Alertmanager) QueryAlerts() ([]TestAlert, error) { func (am *Alertmanager) QueryAlerts(match ...string) ([]TestAlert, error) {
amURLFlag := "--alertmanager.url=" + am.getURL("/") amURLFlag := "--alertmanager.url=" + am.getURL("/")
cmd := exec.Command(amtool, amURLFlag, "alert", "query") args := append([]string{amURLFlag, "alert", "query"}, match...)
cmd := exec.Command(amtool, args...)
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
if err != nil { if err != nil {
return nil, err return nil, err
@ -558,9 +559,9 @@ func (am *Alertmanager) addSilenceCommand(sil *TestSilence) ([]byte, error) {
} }
// QuerySilence queries the current silences using the 'amtool silence query' command. // QuerySilence queries the current silences using the 'amtool silence query' command.
func (am *Alertmanager) QuerySilence() ([]TestSilence, error) { func (am *Alertmanager) QuerySilence(match ...string) ([]TestSilence, error) {
amURLFlag := "--alertmanager.url=" + am.getURL("/") amURLFlag := "--alertmanager.url=" + am.getURL("/")
args := []string{amURLFlag, "silence", "query"} args := append([]string{amURLFlag, "silence", "query"}, match...)
cmd := exec.Command(amtool, args...) cmd := exec.Command(amtool, args...)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {

View File

@ -21,6 +21,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/prometheus/alertmanager/api/v2/models"
. "github.com/prometheus/alertmanager/test/cli" . "github.com/prometheus/alertmanager/test/cli"
) )
@ -114,13 +115,26 @@ receivers:
am.AddAlerts(alert1, alert2) am.AddAlerts(alert1, alert2)
alerts, err := am.QueryAlerts() alerts, err := am.QueryAlerts()
if err != nil { require.NoError(t, err)
t.Fatal("Failed to query alerts", err) require.Len(t, alerts, 2)
}
expectedAlerts := 2 // Get the first alert using the alertname heuristic
if len(alerts) != expectedAlerts { alerts, err = am.QueryAlerts("test1")
t.Fatalf("Incorrect number of alerts, expected %v, got %v", expectedAlerts, len(alerts)) require.NoError(t, err)
} require.Len(t, alerts, 1)
// QueryAlerts uses the simple output option, which means just the alertname
// label is printed. We can assert that querying works as expected as we know
// there are two alerts called "test1" and "test2".
expectedLabels := models.LabelSet{"name": "test1"}
require.True(t, alerts[0].HasLabels(expectedLabels))
// Get the second alert
alerts, err = am.QueryAlerts("alertname=test2")
require.NoError(t, err)
require.Len(t, alerts, 1)
expectedLabels = models.LabelSet{"name": "test2"}
require.True(t, alerts[0].HasLabels(expectedLabels))
} }
func TestQuerySilence(t *testing.T) { func TestQuerySilence(t *testing.T) {
@ -153,20 +167,30 @@ receivers:
am := amc.Members()[0] am := amc.Members()[0]
silence1 := Silence(0, 4).Match("alertname=test1", "severity=warn").Comment("test1") silence1 := Silence(0, 4).Match("test1", "severity=warn").Comment("test1")
silence2 := Silence(0, 4).Match("foo").Comment("test foo") silence2 := Silence(0, 4).Match("alertname=test2", "severity=warn").Comment("test2")
silence3 := Silence(0, 4).Match("{alertname=test3}", "severity=warn").Comment("test3")
am.SetSilence(0, silence1) am.SetSilence(0, silence1)
am.SetSilence(0, silence2) am.SetSilence(0, silence2)
am.SetSilence(0, silence3)
// Get all silences
sils, err := am.QuerySilence() sils, err := am.QuerySilence()
if err != nil { require.NoError(t, err)
t.Error("Failed to query silences: ", err) require.Len(t, sils, 3)
} expected1 := []string{"alertname=\"test1\"", "severity=\"warn\""}
expectedSils := 2 require.Equal(t, expected1, sils[0].GetMatches())
if len(sils) != expectedSils { expected2 := []string{"alertname=\"test2\"", "severity=\"warn\""}
t.Errorf("Incorrect number of silences queried, expected: %v, actual: %v", expectedSils, len(sils)) require.Equal(t, expected2, sils[1].GetMatches())
} expected3 := []string{"alertname=\"{alertname=test3}\"", "severity=\"warn\""}
require.Equal(t, expected3, sils[2].GetMatches())
// Get the first silence using the alertname heuristic
sils, err = am.QuerySilence("test1")
require.NoError(t, err)
require.Len(t, sils, 1)
require.Equal(t, expected1, sils[0].GetMatches())
} }
func TestRoutesShow(t *testing.T) { func TestRoutesShow(t *testing.T) {

View File

@ -76,7 +76,12 @@ func (s *TestSilence) Match(v ...string) *TestSilence {
return s return s
} }
// MatchRE adds a new regex matcher to the silence // GetMatches returns the plain matchers for the silence.
func (s TestSilence) GetMatches() []string {
return s.match
}
// MatchRE adds a new regex matcher to the silence.
func (s *TestSilence) MatchRE(v ...string) *TestSilence { func (s *TestSilence) MatchRE(v ...string) *TestSilence {
if len(v)%2 == 1 { if len(v)%2 == 1 {
panic("bad key/values") panic("bad key/values")
@ -85,6 +90,11 @@ func (s *TestSilence) MatchRE(v ...string) *TestSilence {
return s return s
} }
// GetMatchREs returns the regex matchers for the silence.
func (s *TestSilence) GetMatchREs() []string {
return s.matchRE
}
// Comment sets the comment to the silence. // Comment sets the comment to the silence.
func (s *TestSilence) Comment(c string) *TestSilence { func (s *TestSilence) Comment(c string) *TestSilence {
s.comment = c s.comment = c
@ -185,6 +195,11 @@ func (a *TestAlert) Active(tss ...float64) *TestAlert {
return a return a
} }
// HasLabels returns true if the two label sets are equivalent, otherwise false.
func (a *TestAlert) HasLabels(labels models.LabelSet) bool {
return reflect.DeepEqual(a.labels, labels)
}
func equalAlerts(a, b *models.GettableAlert, opts *AcceptanceOpts) bool { func equalAlerts(a, b *models.GettableAlert, opts *AcceptanceOpts) bool {
if !reflect.DeepEqual(a.Labels, b.Labels) { if !reflect.DeepEqual(a.Labels, b.Labels) {
return false return false