Support UTF-8 label matchers: Add more acceptance tests for braces when using amtool (#3523)
* Add tests for PromQL braces when using amtool alert Signed-off-by: George Robinson <george.robinson@grafana.com> --------- Signed-off-by: George Robinson <george.robinson@grafana.com>
This commit is contained in:
parent
5ba9b9c7c3
commit
5a462df83a
|
@ -457,27 +457,46 @@ func Version() (string, error) {
|
||||||
|
|
||||||
// AddAlertsAt declares alerts that are to be added to the Alertmanager
|
// AddAlertsAt declares alerts that are to be added to the Alertmanager
|
||||||
// server at a relative point in time.
|
// server at a relative point in time.
|
||||||
func (am *Alertmanager) AddAlertsAt(at float64, alerts ...*TestAlert) {
|
func (am *Alertmanager) AddAlertsAt(omitEquals bool, at float64, alerts ...*TestAlert) {
|
||||||
am.t.Do(at, func() {
|
am.t.Do(at, func() {
|
||||||
am.AddAlerts(alerts...)
|
am.AddAlerts(omitEquals, alerts...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAlerts declares alerts that are to be added to the Alertmanager server.
|
// AddAlerts declares alerts that are to be added to the Alertmanager server.
|
||||||
func (am *Alertmanager) AddAlerts(alerts ...*TestAlert) {
|
// The omitEquals option omits alertname= from the command line args passed to
|
||||||
|
// amtool and instead uses the alertname value as the first argument to the command.
|
||||||
|
// For example `amtool alert add foo` instead of `amtool alert add alertname=foo`.
|
||||||
|
// This has been added to allow certain tests to test adding alerts both with and
|
||||||
|
// without alertname=. All other tests that use AddAlerts as a fixture can set this
|
||||||
|
// to false.
|
||||||
|
func (am *Alertmanager) AddAlerts(omitEquals bool, alerts ...*TestAlert) {
|
||||||
for _, alert := range alerts {
|
for _, alert := range alerts {
|
||||||
out, err := am.addAlertCommand(alert)
|
out, err := am.addAlertCommand(omitEquals, alert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
am.t.Errorf("Error adding alert: %v\nOutput: %s", err, string(out))
|
am.t.Errorf("Error adding alert: %v\nOutput: %s", err, string(out))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *Alertmanager) addAlertCommand(alert *TestAlert) ([]byte, error) {
|
func (am *Alertmanager) addAlertCommand(omitEquals bool, alert *TestAlert) ([]byte, error) {
|
||||||
amURLFlag := "--alertmanager.url=" + am.getURL("/")
|
amURLFlag := "--alertmanager.url=" + am.getURL("/")
|
||||||
args := []string{amURLFlag, "alert", "add"}
|
args := []string{amURLFlag, "alert", "add"}
|
||||||
for key, val := range alert.labels {
|
// Make a copy of the labels
|
||||||
args = append(args, key+"="+val)
|
labels := make(models.LabelSet, len(alert.labels))
|
||||||
|
for k, v := range alert.labels {
|
||||||
|
labels[k] = v
|
||||||
|
}
|
||||||
|
if omitEquals {
|
||||||
|
// If alertname is present and omitEquals is true then the command should
|
||||||
|
// be `amtool alert add foo ...` and not `amtool alert add alertname=foo ...`.
|
||||||
|
if alertname, ok := labels["alertname"]; ok {
|
||||||
|
args = append(args, alertname)
|
||||||
|
delete(labels, "alertname")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for k, v := range labels {
|
||||||
|
args = append(args, k+"="+v)
|
||||||
}
|
}
|
||||||
startsAt := strfmt.DateTime(am.opts.expandTime(alert.startsAt))
|
startsAt := strfmt.DateTime(am.opts.expandTime(alert.startsAt))
|
||||||
args = append(args, "--start="+startsAt.String())
|
args = append(args, "--start="+startsAt.String())
|
||||||
|
@ -522,7 +541,7 @@ func parseAlertQueryResponse(data []byte) ([]TestAlert, error) {
|
||||||
}
|
}
|
||||||
summary := strings.TrimSpace(line[summPos:])
|
summary := strings.TrimSpace(line[summPos:])
|
||||||
alert := TestAlert{
|
alert := TestAlert{
|
||||||
labels: models.LabelSet{"name": alertName},
|
labels: models.LabelSet{"alertname": alertName},
|
||||||
startsAt: float64(startsAt.Unix()),
|
startsAt: float64(startsAt.Unix()),
|
||||||
summary: summary,
|
summary: summary,
|
||||||
}
|
}
|
||||||
|
@ -670,13 +689,13 @@ func (am *Alertmanager) showRouteCommand() ([]byte, error) {
|
||||||
return cmd.CombinedOutput()
|
return cmd.CombinedOutput()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *Alertmanager) TestRoute() ([]byte, error) {
|
func (am *Alertmanager) TestRoute(labels ...string) ([]byte, error) {
|
||||||
return am.testRouteCommand()
|
return am.testRouteCommand(labels...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *Alertmanager) testRouteCommand() ([]byte, error) {
|
func (am *Alertmanager) testRouteCommand(labels ...string) ([]byte, error) {
|
||||||
amURLFlag := "--alertmanager.url=" + am.getURL("/")
|
amURLFlag := "--alertmanager.url=" + am.getURL("/")
|
||||||
args := []string{amURLFlag, "config", "routes", "test"}
|
args := append([]string{amURLFlag, "config", "routes", "test"}, labels...)
|
||||||
cmd := exec.Command(amtool, args...)
|
cmd := exec.Command(amtool, args...)
|
||||||
return cmd.CombinedOutput()
|
return cmd.CombinedOutput()
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ receivers:
|
||||||
am := amc.Members()[0]
|
am := amc.Members()[0]
|
||||||
|
|
||||||
alert1 := Alert("alertname", "test1").Active(1, 2)
|
alert1 := Alert("alertname", "test1").Active(1, 2)
|
||||||
am.AddAlertsAt(0, alert1)
|
am.AddAlertsAt(false, 0, alert1)
|
||||||
co.Want(Between(1, 2), Alert("alertname", "test1").Active(1))
|
co.Want(Between(1, 2), Alert("alertname", "test1").Active(1))
|
||||||
|
|
||||||
at.Run()
|
at.Run()
|
||||||
|
@ -111,12 +111,13 @@ receivers:
|
||||||
am := amc.Members()[0]
|
am := amc.Members()[0]
|
||||||
|
|
||||||
alert1 := Alert("alertname", "test1", "severity", "warning").Active(1)
|
alert1 := Alert("alertname", "test1", "severity", "warning").Active(1)
|
||||||
alert2 := Alert("alertname", "test2", "severity", "info").Active(1)
|
alert2 := Alert("alertname", "alertname=test2", "severity", "info").Active(1)
|
||||||
am.AddAlerts(alert1, alert2)
|
alert3 := Alert("alertname", "{alertname=test3}", "severity", "info").Active(1)
|
||||||
|
am.AddAlerts(true, alert1, alert2, alert3)
|
||||||
|
|
||||||
alerts, err := am.QueryAlerts()
|
alerts, err := am.QueryAlerts()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, alerts, 2)
|
require.Len(t, alerts, 3)
|
||||||
|
|
||||||
// Get the first alert using the alertname heuristic
|
// Get the first alert using the alertname heuristic
|
||||||
alerts, err = am.QueryAlerts("test1")
|
alerts, err = am.QueryAlerts("test1")
|
||||||
|
@ -126,14 +127,21 @@ receivers:
|
||||||
// QueryAlerts uses the simple output option, which means just the alertname
|
// 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
|
// label is printed. We can assert that querying works as expected as we know
|
||||||
// there are two alerts called "test1" and "test2".
|
// there are two alerts called "test1" and "test2".
|
||||||
expectedLabels := models.LabelSet{"name": "test1"}
|
expectedLabels := models.LabelSet{"alertname": "test1"}
|
||||||
require.True(t, alerts[0].HasLabels(expectedLabels))
|
require.True(t, alerts[0].HasLabels(expectedLabels))
|
||||||
|
|
||||||
// Get the second alert
|
// Get the second alert
|
||||||
alerts, err = am.QueryAlerts("alertname=test2")
|
alerts, err = am.QueryAlerts("alertname=test2")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, alerts, 1)
|
require.Len(t, alerts, 1)
|
||||||
expectedLabels = models.LabelSet{"name": "test2"}
|
expectedLabels = models.LabelSet{"alertname": "test2"}
|
||||||
|
require.True(t, alerts[0].HasLabels(expectedLabels))
|
||||||
|
|
||||||
|
// Get the third alert
|
||||||
|
alerts, err = am.QueryAlerts("{alertname=test3}")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, alerts, 1)
|
||||||
|
expectedLabels = models.LabelSet{"alertname": "{alertname=test3}"}
|
||||||
require.True(t, alerts[0].HasLabels(expectedLabels))
|
require.True(t, alerts[0].HasLabels(expectedLabels))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,4 +265,9 @@ receivers:
|
||||||
am := amc.Members()[0]
|
am := amc.Members()[0]
|
||||||
_, err := am.TestRoute()
|
_, err := am.TestRoute()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Bad labels should return error
|
||||||
|
out, err := am.TestRoute("{foo=bar}")
|
||||||
|
require.EqualError(t, err, "exit status 1")
|
||||||
|
require.Equal(t, "amtool: error: Failed to parse labels: bad matcher format: {foo=bar}\n\n", string(out))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue