github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/configs/userconfig/config_test.go (about) 1 package userconfig 2 3 import ( 4 "encoding/json" 5 "strconv" 6 "strings" 7 "testing" 8 "time" 9 10 "github.com/go-kit/log" 11 "github.com/prometheus/common/model" 12 "github.com/prometheus/prometheus/pkg/labels" 13 "github.com/prometheus/prometheus/pkg/rulefmt" 14 "github.com/prometheus/prometheus/promql/parser" 15 "github.com/prometheus/prometheus/rules" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 "gopkg.in/yaml.v3" 19 20 util_log "github.com/cortexproject/cortex/pkg/util/log" 21 ) 22 23 var legacyRulesFile = `ALERT TestAlert 24 IF up == 0 25 FOR 5m 26 LABELS { severity = "critical" } 27 ANNOTATIONS { 28 message = "I am a message" 29 }` 30 31 var ruleFile = `groups: 32 - name: example 33 rules: 34 - alert: TestAlert 35 expr: up == 0 36 for: 5m 37 labels: 38 severity: critical 39 annotations: 40 message: I am a message` 41 42 func TestUnmarshalJSONLegacyConfigWithMissingRuleFormatVersionSucceeds(t *testing.T) { 43 actual := Config{} 44 buf := []byte(`{"rules_files": {"a": "b"}}`) 45 assert.Nil(t, json.Unmarshal(buf, &actual)) 46 47 expected := Config{ 48 RulesConfig: RulesConfig{ 49 Files: map[string]string{ 50 "a": "b", 51 }, 52 FormatVersion: RuleFormatV1, 53 }, 54 } 55 56 assert.Equal(t, expected, actual) 57 } 58 59 func TestUnmarshalYAMLLegacyConfigWithMissingRuleFormatVersionSucceeds(t *testing.T) { 60 actual := Config{} 61 buf := []byte(strings.TrimSpace(` 62 rule_format_version: '1' 63 rules_files: 64 a: b 65 `)) 66 assert.Nil(t, yaml.Unmarshal(buf, &actual)) 67 68 expected := Config{ 69 RulesConfig: RulesConfig{ 70 Files: map[string]string{ 71 "a": "b", 72 }, 73 FormatVersion: RuleFormatV1, 74 }, 75 } 76 77 assert.Equal(t, expected, actual) 78 } 79 80 func TestParseLegacyAlerts(t *testing.T) { 81 parsed, err := parser.ParseExpr("up == 0") 82 require.NoError(t, err) 83 rule := rules.NewAlertingRule( 84 "TestAlert", 85 parsed, 86 5*time.Minute, 87 labels.Labels{ 88 labels.Label{Name: "severity", Value: "critical"}, 89 }, 90 labels.Labels{ 91 labels.Label{Name: "message", Value: "I am a message"}, 92 }, 93 nil, 94 "", 95 true, 96 log.With(util_log.Logger, "alert", "TestAlert"), 97 ) 98 99 for i, tc := range []struct { 100 cfg RulesConfig 101 expected map[string][]rules.Rule 102 }{ 103 { 104 cfg: RulesConfig{ 105 FormatVersion: RuleFormatV1, 106 Files: map[string]string{ 107 "legacy.rules": ` 108 ALERT TestAlert 109 IF up == 0 110 FOR 5m 111 LABELS { severity = "critical" } 112 ANNOTATIONS { 113 message = "I am a message" 114 } 115 `, 116 }, 117 }, 118 expected: map[string][]rules.Rule{ 119 "legacy.rules": {rule}, 120 }, 121 }, 122 { 123 cfg: RulesConfig{ 124 FormatVersion: RuleFormatV2, 125 Files: map[string]string{ 126 "alerts.yaml": ` 127 groups: 128 - name: example 129 rules: 130 - alert: TestAlert 131 expr: up == 0 132 for: 5m 133 labels: 134 severity: critical 135 annotations: 136 message: I am a message 137 `, 138 }, 139 }, 140 expected: map[string][]rules.Rule{ 141 "example;alerts.yaml": {rule}, 142 }, 143 }, 144 } { 145 t.Run(strconv.Itoa(i), func(t *testing.T) { 146 rules, err := tc.cfg.Parse() 147 require.NoError(t, err) 148 require.Equal(t, tc.expected, rules) 149 }) 150 } 151 } 152 153 func TestParseFormatted(t *testing.T) { 154 dur, err := model.ParseDuration("5m") 155 require.NoError(t, err) 156 157 rulesV1 := []rulefmt.RuleNode{ 158 { 159 Alert: yaml.Node{Value: "TestAlert"}, 160 Expr: yaml.Node{Value: "up == 0"}, 161 For: dur, 162 Labels: map[string]string{ 163 "severity": "critical", 164 }, 165 Annotations: map[string]string{ 166 "message": "I am a message", 167 }, 168 }, 169 } 170 171 alertNode := yaml.Node{Line: 4, Column: 12} 172 alertNode.SetString("TestAlert") 173 exprNode := yaml.Node{Line: 5, Column: 11} 174 exprNode.SetString("up == 0") 175 rulesV2 := []rulefmt.RuleNode{ 176 { 177 Alert: alertNode, 178 Expr: exprNode, 179 For: dur, 180 Labels: map[string]string{ 181 "severity": "critical", 182 }, 183 Annotations: map[string]string{ 184 "message": "I am a message", 185 }, 186 }, 187 } 188 189 for i, tc := range []struct { 190 cfg RulesConfig 191 expected map[string]rulefmt.RuleGroups 192 }{ 193 { 194 cfg: RulesConfig{ 195 FormatVersion: RuleFormatV1, 196 Files: map[string]string{ 197 "legacy.rules": legacyRulesFile, 198 }, 199 }, 200 expected: map[string]rulefmt.RuleGroups{ 201 "legacy.rules": { 202 Groups: []rulefmt.RuleGroup{ 203 { 204 Name: "rg:legacy.rules", 205 Rules: rulesV1, 206 }, 207 }, 208 }, 209 }, 210 }, 211 { 212 cfg: RulesConfig{ 213 FormatVersion: RuleFormatV2, 214 Files: map[string]string{ 215 "alerts.yaml": ruleFile, 216 }, 217 }, 218 expected: map[string]rulefmt.RuleGroups{ 219 "alerts.yaml": { 220 Groups: []rulefmt.RuleGroup{ 221 { 222 Name: "example", 223 Rules: rulesV2, 224 }, 225 }, 226 }, 227 }, 228 }, 229 } { 230 t.Run(strconv.Itoa(i), func(t *testing.T) { 231 rules, err := tc.cfg.ParseFormatted() 232 require.NoError(t, err) 233 require.Equal(t, tc.expected, rules) 234 }) 235 } 236 }