Alerting: Remove grafanaManagedRecordingRules feature flag (#105569)
This commit is contained in:
+1
-3
@@ -63,9 +63,7 @@ To configure Grafana-managed recording rules, complete the following steps.
|
||||
|
||||
This section only applies to Grafana OSS and Grafana Enterprise.
|
||||
|
||||
First, enable the `grafanaManagedRecordingRules` [feature flag](ref:configure-feature-toggles).
|
||||
|
||||
Then, enable the feature by setting `enabled = true` in the `[recording_rules]` section of the Grafana config .ini. Provide the URL of your Prometheus-compatible remote-write endpoint in the `url` field, along with optional credentials or headers.
|
||||
Enable the feature by setting `enabled = true` in the `[recording_rules]` section of the Grafana configuration file. Provide the URL of your Prometheus-compatible remote-write endpoint in the `url` field, along with optional credentials or headers.
|
||||
|
||||
```
|
||||
[recording_rules]
|
||||
|
||||
@@ -558,10 +558,6 @@ export interface FeatureToggles {
|
||||
*/
|
||||
disableNumericMetricsSortingInExpressions?: boolean;
|
||||
/**
|
||||
* Enables Grafana-managed recording rules.
|
||||
*/
|
||||
grafanaManagedRecordingRules?: boolean;
|
||||
/**
|
||||
* Enables Query Library feature in Explore
|
||||
*/
|
||||
queryLibrary?: boolean;
|
||||
|
||||
@@ -951,15 +951,6 @@ var (
|
||||
Owner: grafanaOSSBigTent,
|
||||
RequiresRestart: true,
|
||||
},
|
||||
{
|
||||
Name: "grafanaManagedRecordingRules",
|
||||
Description: "Enables Grafana-managed recording rules.",
|
||||
Stage: FeatureStageExperimental,
|
||||
Owner: grafanaAlertingSquad,
|
||||
AllowSelfServe: false,
|
||||
HideFromDocs: true,
|
||||
HideFromAdminPage: true,
|
||||
},
|
||||
{
|
||||
Name: "queryLibrary",
|
||||
Description: "Enables Query Library feature in Explore",
|
||||
|
||||
@@ -123,7 +123,6 @@ oauthRequireSubClaim,experimental,@grafana/identity-access-team,false,false,fals
|
||||
newDashboardWithFiltersAndGroupBy,experimental,@grafana/dashboards-squad,false,false,false
|
||||
cloudWatchNewLabelParsing,GA,@grafana/aws-datasources,false,false,false
|
||||
disableNumericMetricsSortingInExpressions,experimental,@grafana/oss-big-tent,false,true,false
|
||||
grafanaManagedRecordingRules,experimental,@grafana/alerting-squad,false,false,false
|
||||
queryLibrary,experimental,@grafana/grafana-frontend-platform,false,false,false
|
||||
logsExploreTableDefaultVisualization,experimental,@grafana/observability-logs,false,false,true
|
||||
newDashboardSharingComponent,GA,@grafana/sharing-squad,false,false,true
|
||||
|
||||
|
@@ -503,10 +503,6 @@ const (
|
||||
// In server-side expressions, disable the sorting of numeric-kind metrics by their metric name or labels.
|
||||
FlagDisableNumericMetricsSortingInExpressions = "disableNumericMetricsSortingInExpressions"
|
||||
|
||||
// FlagGrafanaManagedRecordingRules
|
||||
// Enables Grafana-managed recording rules.
|
||||
FlagGrafanaManagedRecordingRules = "grafanaManagedRecordingRules"
|
||||
|
||||
// FlagQueryLibrary
|
||||
// Enables Query Library feature in Explore
|
||||
FlagQueryLibrary = "queryLibrary"
|
||||
|
||||
@@ -1401,7 +1401,8 @@
|
||||
"metadata": {
|
||||
"name": "grafanaManagedRecordingRules",
|
||||
"resourceVersion": "1743693517832",
|
||||
"creationTimestamp": "2024-04-22T17:53:16Z"
|
||||
"creationTimestamp": "2024-04-22T17:53:16Z",
|
||||
"deletionTimestamp": "2025-05-16T18:56:20Z"
|
||||
},
|
||||
"spec": {
|
||||
"description": "Enables Grafana-managed recording rules.",
|
||||
|
||||
@@ -344,14 +344,6 @@ func (srv *ProvisioningSrv) RoutePostAlertRule(c *contextmodel.ReqContext, ar de
|
||||
return ErrResp(http.StatusBadRequest, err, "")
|
||||
}
|
||||
|
||||
if upstreamModel.Type() == alerting_models.RuleTypeRecording && !srv.featureManager.IsEnabledGlobally(featuremgmt.FlagGrafanaManagedRecordingRules) {
|
||||
return ErrResp(
|
||||
http.StatusBadRequest,
|
||||
fmt.Errorf("%w: recording rules cannot be created on this instance", alerting_models.ErrAlertRuleFailedValidation),
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
provenance := determineProvenance(c)
|
||||
createdAlertRule, err := srv.alertRules.CreateAlertRule(c.Req.Context(), c.SignedInUser, upstreamModel, alerting_models.Provenance(provenance))
|
||||
if errors.Is(err, alerting_models.ErrAlertRuleFailedValidation) {
|
||||
@@ -377,14 +369,6 @@ func (srv *ProvisioningSrv) RoutePutAlertRule(c *contextmodel.ReqContext, ar def
|
||||
ErrResp(http.StatusBadRequest, err, "")
|
||||
}
|
||||
|
||||
if updated.Type() == alerting_models.RuleTypeRecording && !srv.featureManager.IsEnabledGlobally(featuremgmt.FlagGrafanaManagedRecordingRules) {
|
||||
return ErrResp(
|
||||
http.StatusBadRequest,
|
||||
fmt.Errorf("%w: recording rules cannot be created on this instance", alerting_models.ErrAlertRuleFailedValidation),
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
if UID == "" {
|
||||
// If there is no UID, return 404 as the UID is part of the URL.
|
||||
return response.Empty(http.StatusNotFound)
|
||||
|
||||
@@ -534,95 +534,46 @@ func TestProvisioningApi(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("recording rules", func(t *testing.T) {
|
||||
t.Run("are enabled", func(t *testing.T) {
|
||||
env := createTestEnv(t, testConfig)
|
||||
env.features = featuremgmt.WithFeatures(featuremgmt.FlagGrafanaManagedRecordingRules)
|
||||
env := createTestEnv(t, testConfig)
|
||||
|
||||
t.Run("POST returns 201", func(t *testing.T) {
|
||||
sut := createProvisioningSrvSutFromEnv(t, &env)
|
||||
rc := createTestRequestCtx()
|
||||
rule := createTestRecordingRule("rule", 1)
|
||||
t.Run("POST returns 201", func(t *testing.T) {
|
||||
sut := createProvisioningSrvSutFromEnv(t, &env)
|
||||
rc := createTestRequestCtx()
|
||||
rule := createTestRecordingRule("rule", 1)
|
||||
|
||||
response := sut.RoutePostAlertRule(&rc, rule)
|
||||
response := sut.RoutePostAlertRule(&rc, rule)
|
||||
|
||||
require.Equal(t, 201, response.Status())
|
||||
})
|
||||
|
||||
t.Run("PUT returns 200", func(t *testing.T) {
|
||||
sut := createProvisioningSrvSutFromEnv(t, &env)
|
||||
uid := util.GenerateShortUID()
|
||||
rule := createTestAlertRule("rule", 3)
|
||||
rule.UID = uid
|
||||
|
||||
_, err := sut.folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
UID: rule.FolderUID,
|
||||
Title: "Folder Title",
|
||||
OrgID: rule.OrgID,
|
||||
SignedInUser: &user.SignedInUser{OrgID: rule.OrgID},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
insertRuleInOrg(t, sut, rule, 3)
|
||||
|
||||
// make rule a recording rule
|
||||
rule.Record = &definitions.Record{
|
||||
Metric: "test_metric",
|
||||
From: "A",
|
||||
}
|
||||
|
||||
rc := createTestRequestCtx()
|
||||
rc.OrgID = 3
|
||||
|
||||
response := sut.RoutePutAlertRule(&rc, rule, rule.UID)
|
||||
|
||||
require.Equal(t, 200, response.Status())
|
||||
})
|
||||
require.Equal(t, 201, response.Status())
|
||||
})
|
||||
|
||||
t.Run("are not enabled", func(t *testing.T) {
|
||||
t.Run("POST returns 400", func(t *testing.T) {
|
||||
sut := createProvisioningSrvSut(t)
|
||||
rc := createTestRequestCtx()
|
||||
rule := createTestRecordingRule("rule", 1)
|
||||
t.Run("PUT returns 200", func(t *testing.T) {
|
||||
sut := createProvisioningSrvSutFromEnv(t, &env)
|
||||
uid := util.GenerateShortUID()
|
||||
rule := createTestAlertRule("rule", 3)
|
||||
rule.UID = uid
|
||||
|
||||
response := sut.RoutePostAlertRule(&rc, rule)
|
||||
|
||||
require.Equal(t, 400, response.Status())
|
||||
require.NotEmpty(t, response.Body())
|
||||
require.Contains(t, string(response.Body()), "recording rules cannot be created on this instance")
|
||||
_, err := sut.folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
UID: rule.FolderUID,
|
||||
Title: "Folder Title",
|
||||
OrgID: rule.OrgID,
|
||||
SignedInUser: &user.SignedInUser{OrgID: rule.OrgID},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("PUT returns 400", func(t *testing.T) {
|
||||
sut := createProvisioningSrvSut(t)
|
||||
uid := util.GenerateShortUID()
|
||||
rule := createTestAlertRule("rule", 3)
|
||||
rule.UID = uid
|
||||
insertRuleInOrg(t, sut, rule, 3)
|
||||
|
||||
_, err := sut.folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
UID: rule.FolderUID,
|
||||
Title: "Folder Title",
|
||||
OrgID: rule.OrgID,
|
||||
SignedInUser: &user.SignedInUser{OrgID: rule.OrgID},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
// make rule a recording rule
|
||||
rule.Record = &definitions.Record{
|
||||
Metric: "test_metric",
|
||||
From: "A",
|
||||
}
|
||||
|
||||
insertRuleInOrg(t, sut, rule, 3)
|
||||
rc := createTestRequestCtx()
|
||||
rc.OrgID = 3
|
||||
|
||||
// make rule a recording rule
|
||||
rule.Record = &definitions.Record{
|
||||
Metric: "test_metric",
|
||||
From: "A",
|
||||
}
|
||||
response := sut.RoutePutAlertRule(&rc, rule, rule.UID)
|
||||
|
||||
rc := createTestRequestCtx()
|
||||
rc.OrgID = 3
|
||||
|
||||
response := sut.RoutePutAlertRule(&rc, rule, rule.UID)
|
||||
|
||||
require.Equal(t, 400, response.Status())
|
||||
require.NotEmpty(t, response.Body())
|
||||
require.Contains(t, string(response.Body()), "recording rules cannot be created on this instance")
|
||||
})
|
||||
require.Equal(t, 200, response.Status())
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -974,7 +974,6 @@ func createService(store *fakes.RuleStore, _userService *usertest.FakeUserServic
|
||||
authz: accesscontrol.NewRuleService(acimpl.ProvideAccessControl(featuremgmt.WithFeatures())),
|
||||
amConfigStore: &fakeAMRefresher{},
|
||||
amRefresher: &fakeAMRefresher{},
|
||||
featureManager: featuremgmt.WithFeatures(featuremgmt.FlagGrafanaManagedRecordingRules),
|
||||
userService: userService,
|
||||
conditionValidator: &recordingConditionValidator{},
|
||||
}
|
||||
|
||||
@@ -51,11 +51,6 @@ func makeLimits(cfg *setting.UnifiedAlertingSettings) RuleLimits {
|
||||
return RuleLimitsFromConfig(cfg, baseToggles)
|
||||
}
|
||||
|
||||
func allowRecording(lim RuleLimits) *RuleLimits {
|
||||
lim.RecordingRulesAllowed = true
|
||||
return &lim
|
||||
}
|
||||
|
||||
func validRule() apimodels.PostableExtendedRuleNode {
|
||||
forDuration := model.Duration(rand.Int64N(1000))
|
||||
keepFiringForDuration := model.Duration(rand.Int64N(1000))
|
||||
@@ -447,8 +442,7 @@ func TestValidateRuleNode_NoUID(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "accepts and converts recording rule when toggle is enabled",
|
||||
limits: allowRecording(limits),
|
||||
name: "accepts and converts recording rule",
|
||||
rule: func() *apimodels.PostableExtendedRuleNode {
|
||||
r := validRule()
|
||||
r.GrafanaManagedAlert.Record = &apimodels.Record{Metric: "some_metric", From: "A"}
|
||||
@@ -489,8 +483,7 @@ func TestValidateRuleNode_NoUID(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "recording rules ignore fields that only make sense for Alerting rules",
|
||||
limits: allowRecording(limits),
|
||||
name: "recording rules ignore fields that only make sense for Alerting rules",
|
||||
rule: func() *apimodels.PostableExtendedRuleNode {
|
||||
r := validRule()
|
||||
r.GrafanaManagedAlert.Record = &apimodels.Record{Metric: "some_metric", From: "A"}
|
||||
@@ -673,22 +666,7 @@ func TestValidateRuleNodeFailures_NoUID(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "rejects valid recording rules if toggle is disabled",
|
||||
rule: func() *apimodels.PostableExtendedRuleNode {
|
||||
r := validRule()
|
||||
r.GrafanaManagedAlert.Record = &apimodels.Record{Metric: "some_metric", From: "A"}
|
||||
r.GrafanaManagedAlert.Condition = ""
|
||||
r.GrafanaManagedAlert.NoDataState = ""
|
||||
r.GrafanaManagedAlert.ExecErrState = ""
|
||||
r.GrafanaManagedAlert.NotificationSettings = nil
|
||||
r.For = nil
|
||||
return &r
|
||||
},
|
||||
expErr: "recording rules cannot be created",
|
||||
},
|
||||
{
|
||||
name: "rejects recording rule with invalid metric name",
|
||||
limits: allowRecording(limits),
|
||||
name: "rejects recording rule with invalid metric name",
|
||||
rule: func() *apimodels.PostableExtendedRuleNode {
|
||||
r := validRule()
|
||||
r.GrafanaManagedAlert.Record = &apimodels.Record{Metric: "", From: "A"}
|
||||
@@ -702,8 +680,7 @@ func TestValidateRuleNodeFailures_NoUID(t *testing.T) {
|
||||
expErr: "must be a valid Prometheus metric name",
|
||||
},
|
||||
{
|
||||
name: "rejects recording rule with empty from",
|
||||
limits: allowRecording(limits),
|
||||
name: "rejects recording rule with empty from",
|
||||
rule: func() *apimodels.PostableExtendedRuleNode {
|
||||
r := validRule()
|
||||
r.GrafanaManagedAlert.Record = &apimodels.Record{Metric: "my_metric", From: ""}
|
||||
@@ -717,8 +694,7 @@ func TestValidateRuleNodeFailures_NoUID(t *testing.T) {
|
||||
expErr: "cannot be empty",
|
||||
},
|
||||
{
|
||||
name: "rejects recording rule with from not matching",
|
||||
limits: allowRecording(limits),
|
||||
name: "rejects recording rule with from not matching",
|
||||
rule: func() *apimodels.PostableExtendedRuleNode {
|
||||
r := validRule()
|
||||
r.GrafanaManagedAlert.Record = &apimodels.Record{Metric: "my_metric", From: "NOTEXIST"}
|
||||
|
||||
@@ -23,15 +23,12 @@ type RuleLimits struct {
|
||||
DefaultRuleEvaluationInterval time.Duration
|
||||
// All intervals must be an integer multiple of this duration.
|
||||
BaseInterval time.Duration
|
||||
// Whether recording rules are allowed.
|
||||
RecordingRulesAllowed bool
|
||||
}
|
||||
|
||||
func RuleLimitsFromConfig(cfg *setting.UnifiedAlertingSettings, toggles featuremgmt.FeatureToggles) RuleLimits {
|
||||
return RuleLimits{
|
||||
DefaultRuleEvaluationInterval: cfg.DefaultRuleEvaluationInterval,
|
||||
BaseInterval: cfg.BaseInterval,
|
||||
RecordingRulesAllowed: toggles.IsEnabledGlobally(featuremgmt.FlagGrafanaManagedRecordingRules),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,10 +173,6 @@ func validateAlertingRuleFields(in *apimodels.PostableExtendedRuleNode, newRule
|
||||
// validateRecordingRuleFields validates only the fields on a rule that are specific to Recording rules.
|
||||
// it will load fields that pass validation onto newRule and return the result.
|
||||
func validateRecordingRuleFields(in *apimodels.PostableExtendedRuleNode, newRule ngmodels.AlertRule, limits RuleLimits, canPatch bool) (ngmodels.AlertRule, error) {
|
||||
if !limits.RecordingRulesAllowed {
|
||||
return ngmodels.AlertRule{}, fmt.Errorf("%w: recording rules cannot be created on this instance", ngmodels.ErrAlertRuleFailedValidation)
|
||||
}
|
||||
|
||||
err := ValidateCondition(in.GrafanaManagedAlert.Record.From, in.GrafanaManagedAlert.Data, canPatch)
|
||||
if err != nil {
|
||||
return ngmodels.AlertRule{}, fmt.Errorf("%w: %s", ngmodels.ErrAlertRuleFailedValidation, err.Error())
|
||||
|
||||
@@ -317,10 +317,6 @@ func (ng *AlertNG) init() error {
|
||||
evalFactory := eval.NewEvaluatorFactory(ng.Cfg.UnifiedAlerting, ng.DataSourceCache, ng.ExpressionService)
|
||||
conditionValidator := eval.NewConditionValidator(ng.DataSourceCache, ng.ExpressionService, ng.pluginsStore)
|
||||
|
||||
if !ng.FeatureToggles.IsEnabled(initCtx, featuremgmt.FlagGrafanaManagedRecordingRules) {
|
||||
// Force-disable the feature if the feature toggle is not on - sets us up for feature toggle removal.
|
||||
ng.Cfg.UnifiedAlerting.RecordingRules.Enabled = false
|
||||
}
|
||||
recordingWriter, err := createRecordingWriter(ng.FeatureToggles, ng.Cfg.UnifiedAlerting.RecordingRules, ng.httpClientProvider, ng.DataSourceService, clk, ng.Metrics.GetRemoteWriterMetrics())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize recording writer: %w", err)
|
||||
|
||||
@@ -30,7 +30,7 @@ func TestIntegrationConvertPrometheusNotificationSettings(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources", "grafanaManagedRecordingRules"},
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources"},
|
||||
EnableRecordingRules: true,
|
||||
})
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ func TestIntegrationConvertPrometheusEndpoints_RecordingRuleTargetDatasource(t *
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources", "grafanaManagedRecordingRules"},
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources"},
|
||||
EnableRecordingRules: true,
|
||||
})
|
||||
|
||||
@@ -186,7 +186,7 @@ func TestIntegrationConvertPrometheusEndpoints(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources", "grafanaManagedRecordingRules"},
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources"},
|
||||
EnableRecordingRules: true,
|
||||
})
|
||||
|
||||
@@ -398,7 +398,7 @@ func TestIntegrationConvertPrometheusEndpoints_UpdateRule(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources", "grafanaManagedRecordingRules"},
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources"},
|
||||
EnableRecordingRules: true,
|
||||
})
|
||||
|
||||
@@ -485,7 +485,7 @@ func TestIntegrationConvertPrometheusEndpoints_Conflict(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources", "grafanaManagedRecordingRules"},
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources"},
|
||||
EnableRecordingRules: true,
|
||||
})
|
||||
|
||||
@@ -573,7 +573,7 @@ func TestIntegrationConvertPrometheusEndpoints_CreatePausedRules(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources", "grafanaManagedRecordingRules"},
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources"},
|
||||
EnableRecordingRules: true,
|
||||
})
|
||||
|
||||
@@ -687,7 +687,7 @@ func TestIntegrationConvertPrometheusEndpoints_FolderUIDHeader(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources", "grafanaManagedRecordingRules"},
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources"},
|
||||
EnableRecordingRules: true,
|
||||
})
|
||||
|
||||
@@ -789,7 +789,7 @@ func TestIntegrationConvertPrometheusEndpoints_Provenance(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources", "grafanaManagedRecordingRules"},
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources"},
|
||||
EnableRecordingRules: true,
|
||||
})
|
||||
|
||||
@@ -905,7 +905,7 @@ func TestIntegrationConvertPrometheusEndpoints_Delete(t *testing.T) {
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources", "grafanaManagedRecordingRules"},
|
||||
EnableFeatureToggles: []string{"grafanaManagedRecordingRulesDatasources"},
|
||||
EnableRecordingRules: true,
|
||||
})
|
||||
|
||||
|
||||
@@ -58,10 +58,7 @@ export const GrafanaRules = ({ namespaces, expandAll }: Props) => {
|
||||
const [showExportDrawer, toggleShowExportDrawer] = useToggle(false);
|
||||
const hasGrafanaAlerts = namespaces.length > 0;
|
||||
const { canCreateGrafanaRules } = useRulesAccess();
|
||||
const grafanaRecordingRulesEnabled =
|
||||
config.unifiedAlerting.recordingRulesEnabled &&
|
||||
config.featureToggles.grafanaManagedRecordingRules &&
|
||||
canCreateGrafanaRules;
|
||||
const grafanaRecordingRulesEnabled = config.unifiedAlerting.recordingRulesEnabled && canCreateGrafanaRules;
|
||||
const { t } = useTranslate();
|
||||
return (
|
||||
<section className={styles.wrapper}>
|
||||
|
||||
@@ -7,10 +7,7 @@ import { useRulesAccess } from '../../utils/accessControlHooks';
|
||||
const RecordingRulesButtons = () => {
|
||||
const { canCreateGrafanaRules, canCreateCloudRules } = useRulesAccess();
|
||||
|
||||
const grafanaRecordingRulesEnabled =
|
||||
config.unifiedAlerting.recordingRulesEnabled &&
|
||||
config.featureToggles.grafanaManagedRecordingRules &&
|
||||
canCreateGrafanaRules;
|
||||
const grafanaRecordingRulesEnabled = config.unifiedAlerting.recordingRulesEnabled && canCreateGrafanaRules;
|
||||
|
||||
const { t } = useTranslate();
|
||||
const canCreateAll = canCreateGrafanaRules && canCreateCloudRules && grafanaRecordingRulesEnabled;
|
||||
|
||||
Reference in New Issue
Block a user