44package integration
55
66import (
7+ "context"
78 "fmt"
89 "path/filepath"
910 "testing"
1011 "time"
1112
13+ amlabels "github.com/prometheus/alertmanager/pkg/labels"
14+ "github.com/prometheus/alertmanager/types"
15+ "github.com/prometheus/common/model"
16+ "github.com/prometheus/prometheus/model/labels"
17+ "github.com/prometheus/prometheus/model/rulefmt"
1218 "github.com/prometheus/prometheus/prompb"
1319 "github.com/stretchr/testify/require"
1420
@@ -17,52 +23,157 @@ import (
1723 "github.com/cortexproject/cortex/integration/e2ecortex"
1824)
1925
20- func Test_RulerExternalLabels_UTF8Validation (t * testing.T ) {
26+ const utf8AlertmanagerConfig = `route:
27+ receiver: dummy
28+ group_by: [group.test.🙂]
29+ routes:
30+ - matchers:
31+ - foo.🙂=bar.🙂
32+ receivers:
33+ - name: dummy`
34+
35+ func Test_Alertmanager_UTF8 (t * testing.T ) {
2136 s , err := e2e .NewScenario (networkName )
2237 require .NoError (t , err )
2338 defer s .Close ()
2439
25- // Start dependencies.
26- minio := e2edb .NewMinio (9000 , bucketName )
40+ flags := mergeFlags (AlertmanagerFlags (), AlertmanagerS3Flags (),
41+ map [string ]string {
42+ "-name-validation-scheme" : "utf8" ,
43+ },
44+ )
45+
46+ minio := e2edb .NewMinio (9000 , alertsBucketName )
2747 require .NoError (t , s .StartAndWaitReady (minio ))
2848
49+ alertmanager := e2ecortex .NewAlertmanager (
50+ "alertmanager" ,
51+ flags ,
52+ "" ,
53+ )
54+
55+ require .NoError (t , s .StartAndWaitReady (alertmanager ))
56+
57+ c , err := e2ecortex .NewClient ("" , "" , alertmanager .HTTPEndpoint (), "" , "user-1" )
58+ require .NoError (t , err )
59+
60+ ctx := context .Background ()
61+
62+ err = c .SetAlertmanagerConfig (ctx , utf8AlertmanagerConfig , map [string ]string {})
63+ require .NoError (t , err )
64+
65+ require .NoError (t , alertmanager .WaitSumMetricsWithOptions (e2e .Equals (1 ), []string {"cortex_alertmanager_config_last_reload_successful" }, e2e .WaitMissingMetrics ))
66+ require .NoError (t , alertmanager .WaitSumMetricsWithOptions (e2e .Greater (0 ), []string {"cortex_alertmanager_config_hash" }, e2e .WaitMissingMetrics ))
67+
68+ silenceId , err := c .CreateSilence (ctx , types.Silence {
69+ Matchers : amlabels.Matchers {
70+ {Name : "silences.name.🙂" , Value : "silences.value.🙂" },
71+ },
72+ Comment : "test silences" ,
73+ StartsAt : time .Now (),
74+ EndsAt : time .Now ().Add (time .Minute ),
75+ })
76+ require .NoError (t , err )
77+ require .NotEmpty (t , silenceId )
78+ require .NoError (t , alertmanager .WaitSumMetrics (e2e .Equals (1 ), "cortex_alertmanager_silences" ))
79+
80+ err = c .SendAlertToAlermanager (ctx , & model.Alert {
81+ Labels : model.LabelSet {
82+ "alert.name.🙂" : "alert.value.🙂" ,
83+ },
84+ StartsAt : time .Now (),
85+ EndsAt : time .Now ().Add (time .Minute ),
86+ })
87+ require .NoError (t , err )
88+ require .NoError (t , alertmanager .WaitSumMetrics (e2e .Equals (1 ), "cortex_alertmanager_alerts_received_total" ))
89+ }
90+
91+ func Test_Ruler_UTF8 (t * testing.T ) {
92+ s , err := e2e .NewScenario (networkName )
93+ require .NoError (t , err )
94+ defer s .Close ()
95+
96+ // Start dependencies.
97+ consul := e2edb .NewConsul ()
98+ minio := e2edb .NewMinio (9000 , rulestoreBucketName , bucketName )
99+ require .NoError (t , s .StartAndWaitReady (consul , minio ))
100+
29101 runtimeConfigYamlFile := `
30102overrides:
31- 'user-2':
32- name_validation_scheme: utf8
103+ 'user-1':
33104 ruler_external_labels:
34105 test.utf8.metric: 😄
35106`
36107 require .NoError (t , writeFileToSharedDir (s , runtimeConfigFile , []byte (runtimeConfigYamlFile )))
37108 filePath := filepath .Join (e2e .ContainerSharedDir , runtimeConfigFile )
38109
39- // Start Cortex components.
40- require .NoError (t , copyFileToSharedDir (s , "docs/configuration/single-process-config-blocks.yaml" , cortexConfigFile ))
110+ flags := mergeFlags (
111+ BlocksStorageFlags (),
112+ RulerFlags (),
113+ map [string ]string {
114+ "-runtime-config.file" : filePath ,
115+ "-runtime-config.backend" : "filesystem" ,
116+ "-name-validation-scheme" : "utf8" ,
41117
42- flags := map [string ]string {
43- "-auth.enabled" : "true" ,
44- "-runtime-config.file" : filePath ,
45- "-runtime-config.backend" : "filesystem" ,
46- // ingester
47- "-blocks-storage.s3.access-key-id" : e2edb .MinioAccessKey ,
48- "-blocks-storage.s3.secret-access-key" : e2edb .MinioSecretKey ,
49- "-blocks-storage.s3.bucket-name" : bucketName ,
50- "-blocks-storage.s3.endpoint" : fmt .Sprintf ("%s-minio-9000:9000" , networkName ),
51- "-blocks-storage.s3.insecure" : "true" ,
52- // alert manager
53- "-alertmanager.web.external-url" : "http://localhost/alertmanager" ,
54- "-alertmanager-storage.backend" : "local" ,
55- "-alertmanager-storage.local.path" : filepath .Join (e2e .ContainerSharedDir , "alertmanager_configs" ),
56- }
118+ "-ring.store" : "consul" ,
119+ "-consul.hostname" : consul .NetworkHTTPEndpoint (),
120+ // ingester
121+ "-blocks-storage.s3.access-key-id" : e2edb .MinioAccessKey ,
122+ "-blocks-storage.s3.secret-access-key" : e2edb .MinioSecretKey ,
123+ "-blocks-storage.s3.bucket-name" : bucketName ,
124+ "-blocks-storage.s3.endpoint" : fmt .Sprintf ("%s-minio-9000:9000" , networkName ),
125+ "-blocks-storage.s3.insecure" : "true" ,
126+ // alert manager
127+ "-alertmanager.web.external-url" : "http://localhost/alertmanager" ,
128+ "-alertmanager-storage.backend" : "local" ,
129+ "-alertmanager-storage.local.path" : filepath .Join (e2e .ContainerSharedDir , "alertmanager_configs" ),
130+ },
131+ )
57132 // make alert manager config dir
58133 require .NoError (t , writeFileToSharedDir (s , "alertmanager_configs" , []byte {}))
59134
60- // The external labels validation should be success
61- cortex := e2ecortex .NewSingleBinaryWithConfigFile ("cortex-1" , cortexConfigFile , flags , "" , 9009 , 9095 )
135+ // Start Cortex.
136+ cortex := e2ecortex .NewSingleBinary ("cortex" , flags , "" , 9009 , 9095 )
62137 require .NoError (t , s .StartAndWaitReady (cortex ))
138+
139+ groupLabels := map [string ]string {
140+ "group_label" : "group_value" ,
141+ }
142+ ruleLabels := map [string ]string {
143+ "rule_label" : "rule_value" ,
144+ }
145+
146+ interval , _ := model .ParseDuration ("1s" )
147+
148+ ruleGroup := rulefmt.RuleGroup {
149+ Name : "rule" ,
150+ Interval : interval ,
151+ Rules : []rulefmt.Rule {{
152+ Alert : "alert_rule" ,
153+ Expr : "up" ,
154+ Labels : ruleLabels ,
155+ }, {
156+ Record : "record_rule" ,
157+ Expr : "up" ,
158+ Labels : ruleLabels ,
159+ }},
160+ Labels : groupLabels ,
161+ }
162+
163+ c , err := e2ecortex .NewClient ("" , "" , "" , cortex .HTTPEndpoint (), "user-1" )
164+ require .NoError (t , err )
165+
166+ // Set rule group to user-1
167+ err = c .SetRuleGroup (ruleGroup , "namespace" )
168+ require .NoError (t , err )
169+ require .NoError (t , cortex .WaitSumMetricsWithOptions (e2e .Equals (1 ), []string {"cortex_ruler_managers_total" }), e2e .WithLabelMatchers (labels .MustNewMatcher (labels .MatchEqual , "user" , "user-1" )))
170+ require .NoError (t , cortex .WaitSumMetricsWithOptions (e2e .Equals (1 ), []string {"cortex_ruler_rule_groups_in_store" }, e2e .WithLabelMatchers (
171+ labels .MustNewMatcher (labels .MatchEqual , "user" , "user-1" )),
172+ e2e .WaitMissingMetrics ,
173+ ))
63174}
64175
65- func Test_Distributor_UTF8ValidationPerTenant (t * testing.T ) {
176+ func Test_PushQuery_UTF8 (t * testing.T ) {
66177 s , err := e2e .NewScenario (networkName )
67178 require .NoError (t , err )
68179 defer s .Close ()
@@ -71,22 +182,12 @@ func Test_Distributor_UTF8ValidationPerTenant(t *testing.T) {
71182 minio := e2edb .NewMinio (9000 , bucketName )
72183 require .NoError (t , s .StartAndWaitReady (minio ))
73184
74- runtimeConfigYamlFile := `
75- overrides:
76- 'user-2':
77- name_validation_scheme: utf8
78- `
79-
80- require .NoError (t , writeFileToSharedDir (s , runtimeConfigFile , []byte (runtimeConfigYamlFile )))
81- filePath := filepath .Join (e2e .ContainerSharedDir , runtimeConfigFile )
82-
83185 // Start Cortex components.
84186 require .NoError (t , copyFileToSharedDir (s , "docs/configuration/single-process-config-blocks.yaml" , cortexConfigFile ))
85187
86188 flags := map [string ]string {
87189 "-auth.enabled" : "true" ,
88- "-runtime-config.file" : filePath ,
89- "-runtime-config.backend" : "filesystem" ,
190+ "-name-validation-scheme" : "utf8" ,
90191 // ingester
91192 "-blocks-storage.s3.access-key-id" : e2edb .MinioAccessKey ,
92193 "-blocks-storage.s3.secret-access-key" : e2edb .MinioSecretKey ,
@@ -104,34 +205,62 @@ overrides:
104205 cortex := e2ecortex .NewSingleBinaryWithConfigFile ("cortex-1" , cortexConfigFile , flags , "" , 9009 , 9095 )
105206 require .NoError (t , s .StartAndWaitReady (cortex ))
106207
107- // user-1 uses legacy validation
108- user1Client , err := e2ecortex .NewClient (cortex .HTTPEndpoint (), "" , "" , "" , "user-1" )
109- require .NoError (t , err )
110-
111- // user-2 uses utf8 validation
112- user2Client , err := e2ecortex .NewClient (cortex .HTTPEndpoint (), "" , "" , "" , "user-2" )
208+ c , err := e2ecortex .NewClient (cortex .HTTPEndpoint (), cortex .HTTPEndpoint (), "" , "" , "user-1" )
113209 require .NoError (t , err )
114210
115211 now := time .Now ()
116212
117- utf8Series , _ := generateSeries ("series_1 " , now , prompb.Label {Name : "test.utf8.metric" , Value : "😄" })
213+ utf8Series , _ := generateSeries ("series.1 " , now , prompb.Label {Name : "test.utf8.metric" , Value : "😄" })
118214 legacySeries , _ := generateSeries ("series_2" , now , prompb.Label {Name : "job" , Value : "test" })
119215
120- res , err := user1Client .Push (legacySeries )
216+ metadata := []prompb.MetricMetadata {
217+ {
218+ MetricFamilyName : fmt .Sprintf ("metadata.name" ),
219+ Help : fmt .Sprintf ("metadata.help" ),
220+ Unit : fmt .Sprintf ("metadata.unit" ),
221+ },
222+ }
223+
224+ res , err := c .Push (legacySeries , metadata ... )
121225 require .NoError (t , err )
122226 require .Equal (t , 200 , res .StatusCode )
123227
124- // utf8Series push should be fail for user-1
125- res , err = user1Client .Push (utf8Series )
228+ // utf8Series push should be success
229+ res , err = c .Push (utf8Series )
126230 require .NoError (t , err )
127- require .Equal (t , 400 , res .StatusCode )
231+ require .Equal (t , 200 , res .StatusCode )
128232
129- res , err = user2Client .Push (legacySeries )
233+ // utf8 querying
234+ // c.f. https://prometheus.io/docs/guides/utf8/#querying
235+ query := `{"series.1", "test.utf8.metric"="😄"}`
236+ queryResult , err := c .Query (query , now )
130237 require .NoError (t , err )
131238 require .Equal (t , 200 , res .StatusCode )
239+ require .Equal (t , model .ValVector , queryResult .Type ())
240+ vec := queryResult .(model.Vector )
241+ require .Equal (t , 1 , len (vec ))
132242
133- // utf8Series push should be success for user-2
134- res , err = user2Client .Push (utf8Series )
243+ // label names
244+ start := now
245+ end := now .Add (time .Minute * 5 )
246+ labelNames , err := c .LabelNames (start , end )
135247 require .NoError (t , err )
136- require .Equal (t , 200 , res .StatusCode )
248+ require .Equal (t , []string {"__name__" , "job" , "test.utf8.metric" }, labelNames )
249+
250+ // series
251+ series , err := c .Series ([]string {`{"test.utf8.metric"="😄"}` }, start , end )
252+ require .NoError (t , err )
253+ require .Equal (t , 1 , len (series ))
254+ require .Equal (t , `{__name__="series.1", test.utf8.metric="😄"}` , series [0 ].String ())
255+
256+ // label values
257+ labelValues , err := c .LabelValues ("test.utf8.metric" , start , end , nil )
258+ require .NoError (t , err )
259+ require .Equal (t , 1 , len (labelValues ))
260+ require .Equal (t , model .LabelValue ("😄" ), labelValues [0 ])
261+
262+ // metadata
263+ metadataResult , err := c .Metadata ("metadata.name" , "" )
264+ require .NoError (t , err )
265+ require .Equal (t , 1 , len (metadataResult ))
137266}
0 commit comments