Repository: VictoriaMetrics/VictoriaMetrics
Pull request #6502 (2024-06-18 09:28:32)

vmalert-tool: exit normally when no rule is defined under rule group
address https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6500


Patch:
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 564dd58a8..e80d199fc 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -50,6 +50,7 @@ See also [LTS releases](https://docs.victoriametrics.com/lts-releases/).
 * BUGFIX: [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) and `vmstorage` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): add validation for the max value specified for `-retentionPeriod`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6330) for details.
 * BUGFIX: [vmselect](https://docs.victoriametrics.com/cluster-victoriametrics/): calculate the exact number of [raw samples](https://docs.victoriametrics.com/keyconcepts/#raw-samples) during query processing, the limit is specified via command-line flag `-search.maxSamplesPerQuery`. Previously, samples could have been over-counted and lead to false-positive errors of `maxSamplesPerQuery`limit exceeded. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5851).
 * BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): **copy row** button in Table view produces unexpected result. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6421) and [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/6495).
+* BUGFIX: [vmalert-tool](https://docs.victoriametrics.com/vmalert-tool/): prevent hanging when processing groups without rules. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6500).
 
 ## [v1.102.0-rc1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.102.0-rc1)
 


Test patch:
diff --git a/app/vmalert-tool/unittest/testdata/rules.yaml b/app/vmalert-tool/unittest/testdata/rules.yaml
index f7455c6d8..c69897ebe 100644
--- a/app/vmalert-tool/unittest/testdata/rules.yaml
+++ b/app/vmalert-tool/unittest/testdata/rules.yaml
@@ -37,3 +37,6 @@ groups:
     rules:
       - record: t3
         expr: t1
+
+  - name: emptyGroup
+    rules: []
diff --git a/app/vmalert-tool/unittest/unittest.go b/app/vmalert-tool/unittest/unittest.go
index aaf61af68..9597589b5 100644
--- a/app/vmalert-tool/unittest/unittest.go
+++ b/app/vmalert-tool/unittest/unittest.go
@@ -142,10 +142,10 @@ func verifyTestGroup(group testGroup) error {
 			return fmt.Errorf("\n%s    missing required filed \"alertname\"", testGroupName)
 		}
 		if !disableAlertgroupLabel && at.GroupName == "" {
-			return fmt.Errorf("\n%s    missing required filed \"groupname\" when flag \"disableAlertGroupLabel\" is false", testGroupName)
+			return fmt.Errorf("\n%s    missing required filed \"groupname\" when flag \"disableAlertgroupLabel\" is false", testGroupName)
 		}
 		if disableAlertgroupLabel && at.GroupName != "" {
-			return fmt.Errorf("\n%s    shouldn't set filed \"groupname\" when flag \"disableAlertGroupLabel\" is true", testGroupName)
+			return fmt.Errorf("\n%s    shouldn't set filed \"groupname\" when flag \"disableAlertgroupLabel\" is true", testGroupName)
 		}
 		if at.EvalTime == nil {
 			return fmt.Errorf("\n%s    missing required filed \"eval_time\"", testGroupName)
@@ -316,6 +316,9 @@ func (tg *testGroup) test(evalInterval time.Duration, groupOrderMap map[string]i
 	maxEvalTime := testStartTime.Add(tg.maxEvalTime())
 	for ts := testStartTime; ts.Before(maxEvalTime) || ts.Equal(maxEvalTime); ts = ts.Add(evalInterval) {
 		for _, g := range groups {
+			if len(g.Rules) == 0 {
+				continue
+			}
 			errs := g.ExecOnce(context.Background(), func() []notifier.Notifier { return nil }, rw, ts)
 			for err := range errs {
 				if err != nil {
@@ -374,7 +377,7 @@ func (tg *testGroup) test(evalInterval time.Duration, groupOrderMap map[string]i
 						if expAlert.ExpLabels == nil {
 							expAlert.ExpLabels = make(map[string]string)
 						}
-						// alertGroupNameLabel is added as additional labels when `disableAlertGroupLabel` is false
+						// alertGroupNameLabel is added as additional labels when `disableAlertgroupLabel` is false
 						if !disableAlertgroupLabel {
 							expAlert.ExpLabels["alertgroup"] = groupname
 						}