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,156 @@ 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 , "" )
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.utf8.😄" ,
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+ err = c .SetRuleGroup (ruleGroup , "namespace" )
167+ require .NoError (t , err )
168+ require .NoError (t , cortex .WaitSumMetricsWithOptions (e2e .Equals (1 ), []string {"cortex_ruler_managers_total" }), e2e .WithLabelMatchers (labels .MustNewMatcher (labels .MatchEqual , "user" , "user-1" )))
169+ require .NoError (t , cortex .WaitSumMetricsWithOptions (e2e .Equals (1 ), []string {"cortex_ruler_rule_groups_in_store" }, e2e .WithLabelMatchers (
170+ labels .MustNewMatcher (labels .MatchEqual , "user" , "user-1" )),
171+ e2e .WaitMissingMetrics ,
172+ ))
63173}
64174
65- func Test_Distributor_UTF8ValidationPerTenant (t * testing.T ) {
175+ func Test_PushQuery_UTF8 (t * testing.T ) {
66176 s , err := e2e .NewScenario (networkName )
67177 require .NoError (t , err )
68178 defer s .Close ()
@@ -71,22 +181,12 @@ func Test_Distributor_UTF8ValidationPerTenant(t *testing.T) {
71181 minio := e2edb .NewMinio (9000 , bucketName )
72182 require .NoError (t , s .StartAndWaitReady (minio ))
73183
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-
83184 // Start Cortex components.
84185 require .NoError (t , copyFileToSharedDir (s , "docs/configuration/single-process-config-blocks.yaml" , cortexConfigFile ))
85186
86187 flags := map [string ]string {
87188 "-auth.enabled" : "true" ,
88- "-runtime-config.file" : filePath ,
89- "-runtime-config.backend" : "filesystem" ,
189+ "-name-validation-scheme" : "utf8" ,
90190 // ingester
91191 "-blocks-storage.s3.access-key-id" : e2edb .MinioAccessKey ,
92192 "-blocks-storage.s3.secret-access-key" : e2edb .MinioSecretKey ,
@@ -104,34 +204,62 @@ overrides:
104204 cortex := e2ecortex .NewSingleBinaryWithConfigFile ("cortex-1" , cortexConfigFile , flags , "" , 9009 , 9095 )
105205 require .NoError (t , s .StartAndWaitReady (cortex ))
106206
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" )
207+ c , err := e2ecortex .NewClient (cortex .HTTPEndpoint (), cortex .HTTPEndpoint (), "" , "" , "user-1" )
113208 require .NoError (t , err )
114209
115210 now := time .Now ()
116211
117- utf8Series , _ := generateSeries ("series_1 " , now , prompb.Label {Name : "test.utf8.metric" , Value : "😄" })
212+ utf8Series , _ := generateSeries ("series.1 " , now , prompb.Label {Name : "test.utf8.metric" , Value : "😄" })
118213 legacySeries , _ := generateSeries ("series_2" , now , prompb.Label {Name : "job" , Value : "test" })
119214
120- res , err := user1Client .Push (legacySeries )
215+ metadata := []prompb.MetricMetadata {
216+ {
217+ MetricFamilyName : "metadata.name" ,
218+ Help : "metadata.help" ,
219+ Unit : "metadata.unit" ,
220+ },
221+ }
222+
223+ res , err := c .Push (legacySeries , metadata ... )
121224 require .NoError (t , err )
122225 require .Equal (t , 200 , res .StatusCode )
123226
124- // utf8Series push should be fail for user-1
125- res , err = user1Client .Push (utf8Series )
227+ // utf8Series push should be success
228+ res , err = c .Push (utf8Series )
126229 require .NoError (t , err )
127- require .Equal (t , 400 , res .StatusCode )
230+ require .Equal (t , 200 , res .StatusCode )
128231
129- res , err = user2Client .Push (legacySeries )
232+ // utf8 querying
233+ // c.f. https://prometheus.io/docs/guides/utf8/#querying
234+ query := `{"series.1", "test.utf8.metric"="😄"}`
235+ queryResult , err := c .Query (query , now )
130236 require .NoError (t , err )
131237 require .Equal (t , 200 , res .StatusCode )
238+ require .Equal (t , model .ValVector , queryResult .Type ())
239+ vec := queryResult .(model.Vector )
240+ require .Equal (t , 1 , len (vec ))
132241
133- // utf8Series push should be success for user-2
134- res , err = user2Client .Push (utf8Series )
242+ // label names
243+ start := now
244+ end := now .Add (time .Minute * 5 )
245+ labelNames , err := c .LabelNames (start , end )
135246 require .NoError (t , err )
136- require .Equal (t , 200 , res .StatusCode )
247+ require .Equal (t , []string {"__name__" , "job" , "test.utf8.metric" }, labelNames )
248+
249+ // series
250+ series , err := c .Series ([]string {`{"test.utf8.metric"="😄"}` }, start , end )
251+ require .NoError (t , err )
252+ require .Equal (t , 1 , len (series ))
253+ require .Equal (t , `{__name__="series.1", test.utf8.metric="😄"}` , series [0 ].String ())
254+
255+ // label values
256+ labelValues , err := c .LabelValues ("test.utf8.metric" , start , end , nil )
257+ require .NoError (t , err )
258+ require .Equal (t , 1 , len (labelValues ))
259+ require .Equal (t , model .LabelValue ("😄" ), labelValues [0 ])
260+
261+ // metadata
262+ metadataResult , err := c .Metadata ("metadata.name" , "" )
263+ require .NoError (t , err )
264+ require .Equal (t , 1 , len (metadataResult ))
137265}
0 commit comments