2021-04-29 11:15:15 -05:00
package alerting
import (
"bytes"
2021-12-22 04:02:42 -06:00
"context"
2021-04-29 11:15:15 -05:00
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"testing"
"time"
2021-05-04 11:16:28 -05:00
"github.com/grafana/grafana/pkg/bus"
2022-01-20 04:10:12 -06:00
"github.com/grafana/grafana/pkg/infra/tracing"
2021-04-29 11:15:15 -05:00
"github.com/grafana/grafana/pkg/models"
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/tests/testinfra"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAlertRulePermissions ( t * testing . T ) {
// Setup Grafana and its Database
2022-01-20 04:10:12 -06:00
_ , err := tracing . InitializeTracerForTest ( )
require . NoError ( t , err )
2021-04-29 11:15:15 -05:00
dir , path := testinfra . CreateGrafDir ( t , testinfra . GrafanaOpts {
2021-09-29 09:16:40 -05:00
DisableLegacyAlerting : true ,
EnableUnifiedAlerting : true ,
DisableAnonymous : true ,
2021-04-29 11:15:15 -05:00
} )
2021-08-25 08:11:22 -05:00
grafanaListedAddr , store := testinfra . StartGrafana ( t , dir , path )
2021-05-04 11:16:28 -05:00
// override bus to get the GetSignedInUserQuery handler
store . Bus = bus . GetBus ( )
2021-04-29 11:15:15 -05:00
2021-05-04 11:16:28 -05:00
// Create a user to make authenticated requests
2021-08-12 08:04:09 -05:00
createUser ( t , store , models . CreateUserCommand {
DefaultOrgRole : string ( models . ROLE_EDITOR ) ,
Password : "password" ,
Login : "grafana" ,
} )
2021-05-04 11:16:28 -05:00
2021-04-29 11:15:15 -05:00
// Create the namespace we'll save our alerts to.
2022-01-20 04:10:12 -06:00
_ , err = createFolder ( t , store , 0 , "folder1" )
2021-05-20 07:49:33 -05:00
require . NoError ( t , err )
2021-04-29 11:15:15 -05:00
2021-05-20 07:49:33 -05:00
_ , err = createFolder ( t , store , 0 , "folder2" )
2021-04-29 11:15:15 -05:00
// Create the namespace we'll save our alerts to.
2021-05-20 07:49:33 -05:00
require . NoError ( t , err )
2021-04-29 11:15:15 -05:00
// Create rule under folder1
2021-05-20 07:49:33 -05:00
createRule ( t , grafanaListedAddr , "folder1" , "grafana" , "password" )
2021-04-29 11:15:15 -05:00
// Create rule under folder2
2021-05-20 07:49:33 -05:00
createRule ( t , grafanaListedAddr , "folder2" , "grafana" , "password" )
2021-04-29 11:15:15 -05:00
// With the rules created, let's make sure that rule definitions are stored.
{
2021-05-04 11:16:28 -05:00
u := fmt . Sprintf ( "http://grafana:password@%s/api/ruler/grafana/api/v1/rules" , grafanaListedAddr )
2021-04-29 11:15:15 -05:00
// nolint:gosec
resp , err := http . Get ( u )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
2021-10-04 10:33:55 -05:00
assert . Equal ( t , resp . StatusCode , 200 )
2021-04-29 11:15:15 -05:00
body , _ := rulesNamespaceWithoutVariableValues ( t , b )
expectedGetNamespaceResponseBody := `
{
"folder1" : [
{
"name" : "arulegroup" ,
"interval" : "1m" ,
"rules" : [
{
"annotations" : {
"annotation1" : "val1"
} ,
"expr" : "" ,
"for" : "2m" ,
"labels" : {
"label1" : "val1"
} ,
"grafana_alert" : {
"id" : 1 ,
2021-05-04 11:16:28 -05:00
"orgId" : 1 ,
2021-04-29 11:15:15 -05:00
"title" : "rule under folder folder1" ,
"condition" : "A" ,
"data" : [
{
"refId" : "A" ,
"queryType" : "" ,
"relativeTimeRange" : {
"from" : 18000 ,
"to" : 10800
} ,
"datasourceUid" : "-100" ,
"model" : {
"expression" : "2 + 3 \u003E 1" ,
"intervalMs" : 1000 ,
2021-05-17 11:46:52 -05:00
"maxDataPoints" : 43200 ,
2021-04-29 11:15:15 -05:00
"type" : "math"
}
}
] ,
"updated" : "2021-02-21T01:10:30Z" ,
"intervalSeconds" : 60 ,
"version" : 1 ,
"uid" : "uid" ,
"namespace_uid" : "nsuid" ,
"namespace_id" : 1 ,
"rule_group" : "arulegroup" ,
"no_data_state" : "NoData" ,
"exec_err_state" : "Alerting"
}
}
]
}
] ,
"folder2" : [
{
"name" : "arulegroup" ,
"interval" : "1m" ,
"rules" : [
{
"annotations" : {
"annotation1" : "val1"
} ,
"expr" : "" ,
"for" : "2m" ,
"labels" : {
"label1" : "val1"
} ,
"grafana_alert" : {
"id" : 2 ,
2021-05-04 11:16:28 -05:00
"orgId" : 1 ,
2021-04-29 11:15:15 -05:00
"title" : "rule under folder folder2" ,
"condition" : "A" ,
"data" : [
{
"refId" : "A" ,
"queryType" : "" ,
"relativeTimeRange" : {
"from" : 18000 ,
"to" : 10800
} ,
"datasourceUid" : "-100" ,
"model" : {
"expression" : "2 + 3 \u003E 1" ,
"intervalMs" : 1000 ,
2021-05-17 11:46:52 -05:00
"maxDataPoints" : 43200 ,
2021-04-29 11:15:15 -05:00
"type" : "math"
}
}
] ,
"updated" : "2021-02-21T01:10:30Z" ,
"intervalSeconds" : 60 ,
"version" : 1 ,
"uid" : "uid" ,
"namespace_uid" : "nsuid" ,
"namespace_id" : 2 ,
"rule_group" : "arulegroup" ,
"no_data_state" : "NoData" ,
"exec_err_state" : "Alerting"
}
}
]
}
]
} `
assert . JSONEq ( t , expectedGetNamespaceResponseBody , body )
// remove permissions from folder2
2021-12-22 04:02:42 -06:00
require . NoError ( t , store . UpdateDashboardACL ( context . Background ( ) , 2 , nil ) )
2021-04-29 11:15:15 -05:00
// make sure that folder2 is not included in the response
// nolint:gosec
resp , err = http . Get ( u )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err = ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
2021-10-04 10:33:55 -05:00
assert . Equal ( t , resp . StatusCode , 200 )
2021-04-29 11:15:15 -05:00
body , _ = rulesNamespaceWithoutVariableValues ( t , b )
expectedGetNamespaceResponseBody = `
{
"folder1" : [
{
"name" : "arulegroup" ,
"interval" : "1m" ,
"rules" : [
{
"annotations" : {
"annotation1" : "val1"
} ,
"expr" : "" ,
"for" : "2m" ,
"labels" : {
"label1" : "val1"
} ,
"grafana_alert" : {
"id" : 1 ,
2021-05-04 11:16:28 -05:00
"orgId" : 1 ,
2021-04-29 11:15:15 -05:00
"title" : "rule under folder folder1" ,
"condition" : "A" ,
"data" : [
{
"refId" : "A" ,
"queryType" : "" ,
"relativeTimeRange" : {
"from" : 18000 ,
"to" : 10800
} ,
"datasourceUid" : "-100" ,
"model" : {
"expression" : "2 + 3 \u003E 1" ,
"intervalMs" : 1000 ,
2021-05-17 11:46:52 -05:00
"maxDataPoints" : 43200 ,
2021-04-29 11:15:15 -05:00
"type" : "math"
}
}
] ,
"updated" : "2021-02-21T01:10:30Z" ,
"intervalSeconds" : 60 ,
"version" : 1 ,
"uid" : "uid" ,
"namespace_uid" : "nsuid" ,
"namespace_id" : 1 ,
"rule_group" : "arulegroup" ,
"no_data_state" : "NoData" ,
"exec_err_state" : "Alerting"
}
}
]
}
]
} `
assert . JSONEq ( t , expectedGetNamespaceResponseBody , body )
}
2021-11-08 07:26:08 -06:00
// Remove permissions from ALL folders.
2021-12-22 04:02:42 -06:00
require . NoError ( t , store . UpdateDashboardACL ( context . Background ( ) , 1 , nil ) )
2021-11-08 07:26:08 -06:00
{
u := fmt . Sprintf ( "http://grafana:password@%s/api/ruler/grafana/api/v1/rules" , grafanaListedAddr )
// nolint:gosec
resp , err := http . Get ( u )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
assert . Equal ( t , resp . StatusCode , 200 )
require . JSONEq ( t , ` { } ` , string ( b ) )
}
2021-04-29 11:15:15 -05:00
}
2021-05-20 07:49:33 -05:00
func createRule ( t * testing . T , grafanaListedAddr string , folder string , user , password string ) {
2021-04-29 11:15:15 -05:00
t . Helper ( )
interval , err := model . ParseDuration ( "1m" )
require . NoError ( t , err )
rules := apimodels . PostableRuleGroupConfig {
Name : "arulegroup" ,
Interval : interval ,
Rules : [ ] apimodels . PostableExtendedRuleNode {
{
ApiRuleNode : & apimodels . ApiRuleNode {
For : 2 * interval ,
Labels : map [ string ] string { "label1" : "val1" } ,
Annotations : map [ string ] string { "annotation1" : "val1" } ,
} ,
GrafanaManagedAlert : & apimodels . PostableGrafanaRule {
Title : fmt . Sprintf ( "rule under folder %s" , folder ) ,
Condition : "A" ,
Data : [ ] ngmodels . AlertQuery {
{
RefID : "A" ,
RelativeTimeRange : ngmodels . RelativeTimeRange {
From : ngmodels . Duration ( time . Duration ( 5 ) * time . Hour ) ,
To : ngmodels . Duration ( time . Duration ( 3 ) * time . Hour ) ,
} ,
DatasourceUID : "-100" ,
Model : json . RawMessage ( ` {
"type" : "math" ,
"expression" : "2 + 3 > 1"
} ` ) ,
} ,
} ,
} ,
} ,
} ,
}
buf := bytes . Buffer { }
enc := json . NewEncoder ( & buf )
err = enc . Encode ( & rules )
require . NoError ( t , err )
2021-05-20 07:49:33 -05:00
u := fmt . Sprintf ( "http://%s:%s@%s/api/ruler/grafana/api/v1/rules/%s" , user , password , grafanaListedAddr , folder )
2021-04-29 11:15:15 -05:00
// nolint:gosec
resp , err := http . Post ( u , "application/json" , & buf )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
assert . Equal ( t , http . StatusAccepted , resp . StatusCode )
require . JSONEq ( t , ` { "message":"rule group updated successfully"} ` , string ( b ) )
}
2021-06-04 12:45:26 -05:00
func TestAlertRuleConflictingTitle ( t * testing . T ) {
2022-01-20 04:10:12 -06:00
_ , err := tracing . InitializeTracerForTest ( )
require . NoError ( t , err )
2021-06-04 12:45:26 -05:00
// Setup Grafana and its Database
dir , path := testinfra . CreateGrafDir ( t , testinfra . GrafanaOpts {
2021-09-29 09:16:40 -05:00
DisableLegacyAlerting : true ,
EnableUnifiedAlerting : true ,
EnableQuota : true ,
DisableAnonymous : true ,
ViewersCanEdit : true ,
2021-06-04 12:45:26 -05:00
} )
2021-08-25 08:11:22 -05:00
grafanaListedAddr , store := testinfra . StartGrafana ( t , dir , path )
2021-06-04 12:45:26 -05:00
// override bus to get the GetSignedInUserQuery handler
store . Bus = bus . GetBus ( )
// Create the namespace we'll save our alerts to.
2022-01-20 04:10:12 -06:00
_ , err = createFolder ( t , store , 0 , "folder1" )
2021-06-04 12:45:26 -05:00
require . NoError ( t , err )
_ , err = createFolder ( t , store , 0 , "folder2" )
require . NoError ( t , err )
// Create user
2021-08-12 08:04:09 -05:00
createUser ( t , store , models . CreateUserCommand {
DefaultOrgRole : string ( models . ROLE_ADMIN ) ,
Password : "admin" ,
Login : "admin" ,
} )
2021-06-04 12:45:26 -05:00
interval , err := model . ParseDuration ( "1m" )
require . NoError ( t , err )
rules := apimodels . PostableRuleGroupConfig {
Name : "arulegroup" ,
Rules : [ ] apimodels . PostableExtendedRuleNode {
{
ApiRuleNode : & apimodels . ApiRuleNode {
For : interval ,
Labels : map [ string ] string { "label1" : "val1" } ,
Annotations : map [ string ] string { "annotation1" : "val1" } ,
} ,
// this rule does not explicitly set no data and error states
// therefore it should get the default values
GrafanaManagedAlert : & apimodels . PostableGrafanaRule {
Title : "AlwaysFiring" ,
Condition : "A" ,
Data : [ ] ngmodels . AlertQuery {
{
RefID : "A" ,
RelativeTimeRange : ngmodels . RelativeTimeRange {
From : ngmodels . Duration ( time . Duration ( 5 ) * time . Hour ) ,
To : ngmodels . Duration ( time . Duration ( 3 ) * time . Hour ) ,
} ,
DatasourceUID : "-100" ,
Model : json . RawMessage ( ` {
"type" : "math" ,
"expression" : "2 + 3 > 1"
} ` ) ,
} ,
} ,
} ,
} ,
} ,
}
buf := bytes . Buffer { }
enc := json . NewEncoder ( & buf )
err = enc . Encode ( & rules )
require . NoError ( t , err )
u := fmt . Sprintf ( "http://admin:admin@%s/api/ruler/grafana/api/v1/rules/folder1" , grafanaListedAddr )
// nolint:gosec
resp , err := http . Post ( u , "application/json" , & buf )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
assert . Equal ( t , http . StatusAccepted , resp . StatusCode )
require . JSONEq ( t , ` { "message":"rule group updated successfully"} ` , string ( b ) )
t . Run ( "trying to create alert with same title under same folder should fail" , func ( t * testing . T ) {
buf := bytes . Buffer { }
enc := json . NewEncoder ( & buf )
err = enc . Encode ( & rules )
require . NoError ( t , err )
u := fmt . Sprintf ( "http://admin:admin@%s/api/ruler/grafana/api/v1/rules/folder1" , grafanaListedAddr )
// nolint:gosec
resp , err := http . Post ( u , "application/json" , & buf )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
assert . Equal ( t , http . StatusInternalServerError , resp . StatusCode )
2022-01-21 08:44:11 -06:00
require . JSONEq ( t , ` { "message": "failed to update rule group: a conflicting alert rule is found: rule title under the same organisation and folder should be unique","error":"failed to update rule group: a conflicting alert rule is found: rule title under the same organisation and folder should be unique"} ` , string ( b ) )
2021-06-04 12:45:26 -05:00
} )
t . Run ( "trying to create alert with same title under another folder should succeed" , func ( t * testing . T ) {
buf := bytes . Buffer { }
enc := json . NewEncoder ( & buf )
err = enc . Encode ( & rules )
require . NoError ( t , err )
u := fmt . Sprintf ( "http://admin:admin@%s/api/ruler/grafana/api/v1/rules/folder2" , grafanaListedAddr )
// nolint:gosec
resp , err := http . Post ( u , "application/json" , & buf )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
assert . Equal ( t , http . StatusAccepted , resp . StatusCode )
require . JSONEq ( t , ` { "message":"rule group updated successfully"} ` , string ( b ) )
} )
}
2021-10-04 10:33:55 -05:00
func TestRulerRulesFilterByDashboard ( t * testing . T ) {
2022-01-20 04:10:12 -06:00
_ , err := tracing . InitializeTracerForTest ( )
require . NoError ( t , err )
2021-10-04 10:33:55 -05:00
dir , path := testinfra . CreateGrafDir ( t , testinfra . GrafanaOpts {
EnableFeatureToggles : [ ] string { "ngalert" } ,
DisableAnonymous : true ,
} )
grafanaListedAddr , store := testinfra . StartGrafana ( t , dir , path )
// override bus to get the GetSignedInUserQuery handler
store . Bus = bus . GetBus ( )
// Create the namespace under default organisation (orgID = 1) where we'll save our alerts to.
dashboardUID , err := createFolder ( t , store , 0 , "default" )
require . NoError ( t , err )
// Create a user to make authenticated requests
createUser ( t , store , models . CreateUserCommand {
DefaultOrgRole : string ( models . ROLE_EDITOR ) ,
Password : "password" ,
Login : "grafana" ,
} )
interval , err := model . ParseDuration ( "10s" )
require . NoError ( t , err )
// Now, let's create some rules
{
rules := apimodels . PostableRuleGroupConfig {
Name : "anotherrulegroup" ,
Rules : [ ] apimodels . PostableExtendedRuleNode {
{
ApiRuleNode : & apimodels . ApiRuleNode {
For : interval ,
Labels : map [ string ] string { } ,
Annotations : map [ string ] string {
"__dashboardUid__" : dashboardUID ,
"__panelId__" : "1" ,
} ,
} ,
GrafanaManagedAlert : & apimodels . PostableGrafanaRule {
Title : "AlwaysFiring" ,
Condition : "A" ,
Data : [ ] ngmodels . AlertQuery {
{
RefID : "A" ,
RelativeTimeRange : ngmodels . RelativeTimeRange {
From : ngmodels . Duration ( time . Duration ( 5 ) * time . Hour ) ,
To : ngmodels . Duration ( time . Duration ( 3 ) * time . Hour ) ,
} ,
DatasourceUID : "-100" ,
Model : json . RawMessage ( ` {
"type" : "math" ,
"expression" : "2 + 3 > 1"
} ` ) ,
} ,
} ,
} ,
} ,
{
GrafanaManagedAlert : & apimodels . PostableGrafanaRule {
Title : "AlwaysFiringButSilenced" ,
Condition : "A" ,
Data : [ ] ngmodels . AlertQuery {
{
RefID : "A" ,
RelativeTimeRange : ngmodels . RelativeTimeRange {
From : ngmodels . Duration ( time . Duration ( 5 ) * time . Hour ) ,
To : ngmodels . Duration ( time . Duration ( 3 ) * time . Hour ) ,
} ,
DatasourceUID : "-100" ,
Model : json . RawMessage ( ` {
"type" : "math" ,
"expression" : "2 + 3 > 1"
} ` ) ,
} ,
} ,
NoDataState : apimodels . NoDataState ( ngmodels . Alerting ) ,
ExecErrState : apimodels . ExecutionErrorState ( ngmodels . AlertingErrState ) ,
} ,
} ,
} ,
}
buf := bytes . Buffer { }
enc := json . NewEncoder ( & buf )
err := enc . Encode ( & rules )
require . NoError ( t , err )
u := fmt . Sprintf ( "http://grafana:password@%s/api/ruler/grafana/api/v1/rules/default" , grafanaListedAddr )
// nolint:gosec
resp , err := http . Post ( u , "application/json" , & buf )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
assert . Equal ( t , resp . StatusCode , 202 )
require . JSONEq ( t , ` { "message":"rule group updated successfully"} ` , string ( b ) )
}
expectedAllJSON := fmt . Sprintf ( `
{
"default" : [ {
"name" : "anotherrulegroup" ,
"interval" : "1m" ,
"rules" : [ {
"expr" : "" ,
"for" : "10s" ,
"annotations" : {
"__dashboardUid__" : "%s" ,
"__panelId__" : "1"
} ,
"grafana_alert" : {
"id" : 1 ,
"orgId" : 1 ,
"title" : "AlwaysFiring" ,
"condition" : "A" ,
"data" : [ {
"refId" : "A" ,
"queryType" : "" ,
"relativeTimeRange" : {
"from" : 18000 ,
"to" : 10800
} ,
"datasourceUid" : "-100" ,
"model" : {
"expression" : "2 + 3 \u003e 1" ,
"intervalMs" : 1000 ,
"maxDataPoints" : 43200 ,
"type" : "math"
}
} ] ,
"updated" : "2021-02-21T01:10:30Z" ,
"intervalSeconds" : 60 ,
"version" : 1 ,
"uid" : "uid" ,
"namespace_uid" : "nsuid" ,
"namespace_id" : 1 ,
"rule_group" : "anotherrulegroup" ,
"no_data_state" : "NoData" ,
"exec_err_state" : "Alerting"
}
} , {
"expr" : "" ,
"grafana_alert" : {
"id" : 2 ,
"orgId" : 1 ,
"title" : "AlwaysFiringButSilenced" ,
"condition" : "A" ,
"data" : [ {
"refId" : "A" ,
"queryType" : "" ,
"relativeTimeRange" : {
"from" : 18000 ,
"to" : 10800
} ,
"datasourceUid" : "-100" ,
"model" : {
"expression" : "2 + 3 \u003e 1" ,
"intervalMs" : 1000 ,
"maxDataPoints" : 43200 ,
"type" : "math"
}
} ] ,
"updated" : "2021-02-21T01:10:30Z" ,
"intervalSeconds" : 60 ,
"version" : 1 ,
"uid" : "uid" ,
"namespace_uid" : "nsuid" ,
"namespace_id" : 1 ,
"rule_group" : "anotherrulegroup" ,
"no_data_state" : "Alerting" ,
"exec_err_state" : "Alerting"
}
} ]
} ]
} ` , dashboardUID )
expectedFilteredByJSON := fmt . Sprintf ( `
{
"default" : [ {
"name" : "anotherrulegroup" ,
"interval" : "1m" ,
"rules" : [ {
"expr" : "" ,
"for" : "10s" ,
"annotations" : {
"__dashboardUid__" : "%s" ,
"__panelId__" : "1"
} ,
"grafana_alert" : {
"id" : 1 ,
"orgId" : 1 ,
"title" : "AlwaysFiring" ,
"condition" : "A" ,
"data" : [ {
"refId" : "A" ,
"queryType" : "" ,
"relativeTimeRange" : {
"from" : 18000 ,
"to" : 10800
} ,
"datasourceUid" : "-100" ,
"model" : {
"expression" : "2 + 3 \u003e 1" ,
"intervalMs" : 1000 ,
"maxDataPoints" : 43200 ,
"type" : "math"
}
} ] ,
"updated" : "2021-02-21T01:10:30Z" ,
"intervalSeconds" : 60 ,
"version" : 1 ,
"uid" : "uid" ,
"namespace_uid" : "nsuid" ,
"namespace_id" : 1 ,
"rule_group" : "anotherrulegroup" ,
"no_data_state" : "NoData" ,
"exec_err_state" : "Alerting"
}
} ]
} ]
} ` , dashboardUID )
expectedNoneJSON := ` { } `
// Now, let's see how this looks like.
{
promRulesURL := fmt . Sprintf ( "http://grafana:password@%s/api/ruler/grafana/api/v1/rules" , grafanaListedAddr )
// nolint:gosec
resp , err := http . Get ( promRulesURL )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
require . Equal ( t , 200 , resp . StatusCode )
body , _ := rulesNamespaceWithoutVariableValues ( t , b )
require . JSONEq ( t , expectedAllJSON , body )
}
// Now, let's check we get the same rule when filtering by dashboard_uid
{
promRulesURL := fmt . Sprintf ( "http://grafana:password@%s/api/ruler/grafana/api/v1/rules?dashboard_uid=%s" , grafanaListedAddr , dashboardUID )
// nolint:gosec
resp , err := http . Get ( promRulesURL )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
require . Equal ( t , 200 , resp . StatusCode )
body , _ := rulesNamespaceWithoutVariableValues ( t , b )
require . JSONEq ( t , expectedFilteredByJSON , body )
}
// Now, let's check we get no rules when filtering by an unknown dashboard_uid
{
promRulesURL := fmt . Sprintf ( "http://grafana:password@%s/api/ruler/grafana/api/v1/rules?dashboard_uid=%s" , grafanaListedAddr , "abc" )
// nolint:gosec
resp , err := http . Get ( promRulesURL )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
require . Equal ( t , 200 , resp . StatusCode )
require . JSONEq ( t , expectedNoneJSON , string ( b ) )
}
// Now, let's check we get the same rule when filtering by dashboard_uid and panel_id
{
promRulesURL := fmt . Sprintf ( "http://grafana:password@%s/api/ruler/grafana/api/v1/rules?dashboard_uid=%s&panel_id=1" , grafanaListedAddr , dashboardUID )
// nolint:gosec
resp , err := http . Get ( promRulesURL )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
require . Equal ( t , 200 , resp . StatusCode )
body , _ := rulesNamespaceWithoutVariableValues ( t , b )
require . JSONEq ( t , expectedFilteredByJSON , body )
}
// Now, let's check we get no rules when filtering by dashboard_uid and unknown panel_id
{
promRulesURL := fmt . Sprintf ( "http://grafana:password@%s/api/ruler/grafana/api/v1/rules?dashboard_uid=%s&panel_id=2" , grafanaListedAddr , dashboardUID )
// nolint:gosec
resp , err := http . Get ( promRulesURL )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
require . Equal ( t , 200 , resp . StatusCode )
require . JSONEq ( t , expectedNoneJSON , string ( b ) )
}
// Now, let's check an invalid panel_id returns a 400 Bad Request response
{
promRulesURL := fmt . Sprintf ( "http://grafana:password@%s/api/ruler/grafana/api/v1/rules?dashboard_uid=%s&panel_id=invalid" , grafanaListedAddr , dashboardUID )
// nolint:gosec
resp , err := http . Get ( promRulesURL )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
require . Equal ( t , http . StatusBadRequest , resp . StatusCode )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
2022-01-21 08:44:11 -06:00
require . JSONEq ( t , ` { "message": "invalid panel_id: strconv.ParseInt: parsing \"invalid\": invalid syntax","error":"invalid panel_id: strconv.ParseInt: parsing \"invalid\": invalid syntax"} ` , string ( b ) )
2021-10-04 10:33:55 -05:00
}
// Now, let's check a panel_id without dashboard_uid returns a 400 Bad Request response
{
promRulesURL := fmt . Sprintf ( "http://grafana:password@%s/api/ruler/grafana/api/v1/rules?panel_id=1" , grafanaListedAddr )
// nolint:gosec
resp , err := http . Get ( promRulesURL )
require . NoError ( t , err )
t . Cleanup ( func ( ) {
err := resp . Body . Close ( )
require . NoError ( t , err )
} )
require . Equal ( t , http . StatusBadRequest , resp . StatusCode )
b , err := ioutil . ReadAll ( resp . Body )
require . NoError ( t , err )
2022-01-21 08:44:11 -06:00
require . JSONEq ( t , ` { "message": "panel_id must be set with dashboard_uid","error":"panel_id must be set with dashboard_uid"} ` , string ( b ) )
2021-10-04 10:33:55 -05:00
}
}