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