@@ -8,43 +8,27 @@ use std::collections::HashMap;
88const ENDPOINT_URL : & str = "__endpoint__url" ;
99const ENDPOINT_NAME : & str = "__endpoint__name" ;
1010const ENDPOINT_GEOHASH : & str = "__endpoint__geohash" ;
11- const TARGET_TAG : & str = "__target_tag" ;
1211
1312async fn handler ( State ( config) : State < Config > ) -> ( StatusCode , Json < Response > ) {
14- // Group targets by tags
15- // Map: tag -> list of targets
16- let grouped_targets: HashMap < String , Vec < String > > = config
17- . target
18- . iter ( )
19- . map ( |target| {
20- target
21- . tags
22- . iter ( )
23- . map ( |tag| ( tag. clone ( ) , target. url . clone ( ) ) )
24- . collect :: < Vec < ( String , String ) > > ( )
25- } )
26- . flatten ( )
27- . fold ( HashMap :: new ( ) , |mut acc, ( tag, url) | {
28- acc. entry ( tag) . or_insert_with ( Vec :: new) . push ( url) ;
29- acc
30- } ) ;
31-
32- // generate config for each endpoint and tag combination
13+ // Generate config for each target and endpoint combination
3314 let resp: Vec < FileConfig > = config
3415 . endpoint
3516 . iter ( )
36- . map ( |endpoint| {
37- grouped_targets. iter ( ) . map ( |( tag, targets) | FileConfig {
38- targets : targets. clone ( ) ,
39- labels : HashMap :: from ( [
17+ . flat_map ( |endpoint| {
18+ config. target . iter ( ) . map ( |target| {
19+ let mut labels = HashMap :: from ( [
4020 ( ENDPOINT_URL . to_string ( ) , endpoint. address . clone ( ) ) ,
4121 ( ENDPOINT_NAME . to_string ( ) , endpoint. name . clone ( ) ) ,
4222 ( ENDPOINT_GEOHASH . to_string ( ) , endpoint. geohash . clone ( ) ) ,
43- ( TARGET_TAG . to_string ( ) , tag. clone ( ) ) ,
44- ] ) ,
23+ ] ) ;
24+ labels. extend ( target. labels . clone ( ) ) ;
25+
26+ FileConfig {
27+ targets : vec ! [ target. url. clone( ) ] ,
28+ labels,
29+ }
4530 } )
4631 } )
47- . flatten ( )
4832 . collect ( ) ;
4933
5034 ( StatusCode :: OK , Json ( resp) )
@@ -66,22 +50,33 @@ mod tests {
6650
6751 // 创建测试用的模拟配置
6852 fn create_test_config ( ) -> crate :: config:: Config {
53+ use std:: collections:: HashMap ;
54+
6955 crate :: config:: Config {
7056 target : vec ! [
7157 crate :: config:: Target {
7258 module: "http_2xx" . to_string( ) ,
7359 url: "https://example1.com" . to_string( ) ,
74- tags: vec![ "web" . to_string( ) , "api" . to_string( ) ] ,
60+ labels: HashMap :: from( [
61+ ( "type" . to_string( ) , "web" . to_string( ) ) ,
62+ ( "env" . to_string( ) , "prod" . to_string( ) ) ,
63+ ] ) ,
7564 } ,
7665 crate :: config:: Target {
7766 module: "http_2xx" . to_string( ) ,
7867 url: "https://example2.com" . to_string( ) ,
79- tags: vec![ "web" . to_string( ) ] ,
68+ labels: HashMap :: from( [
69+ ( "type" . to_string( ) , "web" . to_string( ) ) ,
70+ ( "env" . to_string( ) , "staging" . to_string( ) ) ,
71+ ] ) ,
8072 } ,
8173 crate :: config:: Target {
8274 module: "http_2xx" . to_string( ) ,
8375 url: "https://api.example.com" . to_string( ) ,
84- tags: vec![ "api" . to_string( ) ] ,
76+ labels: HashMap :: from( [
77+ ( "type" . to_string( ) , "api" . to_string( ) ) ,
78+ ( "env" . to_string( ) , "prod" . to_string( ) ) ,
79+ ] ) ,
8580 } ,
8681 ] ,
8782 endpoint : vec ! [
@@ -139,7 +134,8 @@ mod tests {
139134 assert ! ( config. labels. contains_key( ENDPOINT_URL ) ) ;
140135 assert ! ( config. labels. contains_key( ENDPOINT_NAME ) ) ;
141136 assert ! ( config. labels. contains_key( ENDPOINT_GEOHASH ) ) ;
142- assert ! ( config. labels. contains_key( TARGET_TAG ) ) ;
137+ // 验证有 target 的 labels
138+ assert ! ( config. labels. contains_key( "type" ) ) ;
143139 assert ! ( !config. targets. is_empty( ) ) ;
144140 }
145141 }
@@ -158,23 +154,23 @@ mod tests {
158154 // 验证响应结构
159155 assert ! ( !json_response. is_empty( ) ) ;
160156
161- // 验证标签分组逻辑
157+ // 验证标签逻辑
162158 let web_configs: Vec < _ > = json_response
163159 . iter ( )
164- . filter ( |config| config. labels . get ( TARGET_TAG ) == Some ( & "web" . to_string ( ) ) )
160+ . filter ( |config| config. labels . get ( "type" ) == Some ( & "web" . to_string ( ) ) )
165161 . collect ( ) ;
166162 let api_configs: Vec < _ > = json_response
167163 . iter ( )
168- . filter ( |config| config. labels . get ( TARGET_TAG ) == Some ( & "api" . to_string ( ) ) )
164+ . filter ( |config| config. labels . get ( "type" ) == Some ( & "api" . to_string ( ) ) )
169165 . collect ( ) ;
170166
171- // web tag 应该包含 2 个 targets (example1.com 和 example2.com )
172- assert_eq ! ( web_configs. len( ) , 2 ) ; // 2 endpoints * 1 web tag group
173- assert ! ( web_configs. iter( ) . any ( |config| config. targets. len( ) == 2 ) ) ;
167+ // web type 应该有 4 个配置 (2 endpoints * 2 web targets )
168+ assert_eq ! ( web_configs. len( ) , 4 ) ; // 2 endpoints * 2 web targets
169+ assert ! ( web_configs. iter( ) . all ( |config| config. targets. len( ) == 1 ) ) ;
174170
175- // api tag 应该包含 2 个 targets (example1.com 和 api.example.com )
176- assert_eq ! ( api_configs. len( ) , 2 ) ; // 2 endpoints * 1 api tag group
177- assert ! ( api_configs. iter( ) . any ( |config| config. targets. len( ) == 2 ) ) ;
171+ // api type 应该有 2 个配置 (2 endpoints * 1 api target )
172+ assert_eq ! ( api_configs. len( ) , 2 ) ; // 2 endpoints * 1 api target
173+ assert ! ( api_configs. iter( ) . all ( |config| config. targets. len( ) == 1 ) ) ;
178174 }
179175
180176 #[ tokio:: test]
@@ -186,7 +182,10 @@ mod tests {
186182 test_config. target . push ( crate :: config:: Target {
187183 module : "http_2xx" . to_string ( ) ,
188184 url : "https://test3.com" . to_string ( ) ,
189- tags : vec ! [ "monitoring" . to_string( ) ] ,
185+ labels : HashMap :: from ( [
186+ ( "type" . to_string ( ) , "monitoring" . to_string ( ) ) ,
187+ ( "env" . to_string ( ) , "prod" . to_string ( ) ) ,
188+ ] ) ,
190189 } ) ;
191190
192191 test_config. endpoint . push ( crate :: config:: Endpoint {
@@ -206,13 +205,13 @@ mod tests {
206205 // 验证有监控标签的配置
207206 let monitoring_configs: Vec < _ > = json_response
208207 . iter ( )
209- . filter ( |config| config. labels . get ( TARGET_TAG ) == Some ( & "monitoring" . to_string ( ) ) )
208+ . filter ( |config| config. labels . get ( "type" ) == Some ( & "monitoring" . to_string ( ) ) )
210209 . collect ( ) ;
211210
212- assert_eq ! ( monitoring_configs. len( ) , 3 ) ; // 3 endpoints * 1 monitoring tag group
211+ assert_eq ! ( monitoring_configs. len( ) , 3 ) ; // 3 endpoints * 1 monitoring target
213212 assert ! ( monitoring_configs
214213 . iter( )
215- . any ( |config| config. targets. len( ) == 1 ) ) ;
214+ . all ( |config| config. targets. len( ) == 1 ) ) ;
216215 }
217216
218217 #[ tokio:: test]
@@ -235,16 +234,16 @@ mod tests {
235234
236235 #[ tokio:: test]
237236 async fn test_single_target_multiple_tags ( ) {
238- // 测试单个 target 有多个 tags 的情况
237+ // 测试单个 target 有多个 labels 的情况
239238 let config = crate :: config:: Config {
240239 target : vec ! [ crate :: config:: Target {
241240 module: "http_2xx" . to_string( ) ,
242241 url: "https://multi-tag.com" . to_string( ) ,
243- tags : vec! [
244- " web". to_string( ) ,
245- "api ". to_string( ) ,
246- "monitoring ". to_string( ) ,
247- ] ,
242+ labels : HashMap :: from ( [
243+ ( "type" . to_string ( ) , " web". to_string( ) ) ,
244+ ( "env ". to_string( ) , "prod" . to_string ( ) ) ,
245+ ( "service ". to_string( ) , "api" . to_string ( ) ) ,
246+ ] ) ,
248247 } ] ,
249248 endpoint : vec ! [ crate :: config:: Endpoint {
250249 address: "test.example.com:443" . to_string( ) ,
@@ -261,43 +260,55 @@ mod tests {
261260
262261 let json_response: Response = response. json ( ) ;
263262
264- // 应该有 3 个配置项(每个 tag 一个 )
265- assert_eq ! ( json_response. len( ) , 3 ) ;
263+ // 应该有 1 个配置项(1 endpoint * 1 target )
264+ assert_eq ! ( json_response. len( ) , 1 ) ;
266265
267- // 验证每个配置项都包含相同的 target
268- for config in & json_response {
269- assert_eq ! ( config. targets. len( ) , 1 ) ;
270- assert_eq ! ( config. targets[ 0 ] , "https://multi-tag.com" ) ;
271- }
266+ // 验证配置项包含 target 和所有 labels
267+ let config = & json_response[ 0 ] ;
268+ assert_eq ! ( config. targets. len( ) , 1 ) ;
269+ assert_eq ! ( config. targets[ 0 ] , "https://multi-tag.com" ) ;
270+ assert_eq ! ( config. labels. get( "type" ) , Some ( & "web" . to_string( ) ) ) ;
271+ assert_eq ! ( config. labels. get( "env" ) , Some ( & "prod" . to_string( ) ) ) ;
272+ assert_eq ! ( config. labels. get( "service" ) , Some ( & "api" . to_string( ) ) ) ;
272273 }
273274
274275 #[ test]
275- fn test_target_grouping_logic ( ) {
276+ fn test_target_processing_logic ( ) {
276277 let test_config = create_test_config ( ) ;
277- let mut grouped_targets: HashMap < String , Vec < String > > = HashMap :: new ( ) ;
278-
279- // 测试分组逻辑
280- for target in test_config. target . iter ( ) {
281- for tag in & target. tags {
282- grouped_targets
283- . entry ( tag. clone ( ) )
284- . or_default ( )
285- . push ( target. url . clone ( ) ) ;
278+
279+ // 测试处理逻辑:每个 target 和 endpoint 组合生成一个 FileConfig
280+ let mut file_configs = Vec :: new ( ) ;
281+
282+ for endpoint in & test_config. endpoint {
283+ for target in & test_config. target {
284+ let mut labels = HashMap :: from ( [
285+ ( ENDPOINT_URL . to_string ( ) , endpoint. address . clone ( ) ) ,
286+ ( ENDPOINT_NAME . to_string ( ) , endpoint. name . clone ( ) ) ,
287+ ( ENDPOINT_GEOHASH . to_string ( ) , endpoint. geohash . clone ( ) ) ,
288+ ] ) ;
289+
290+ for ( key, value) in & target. labels {
291+ labels. insert ( key. clone ( ) , value. clone ( ) ) ;
292+ }
293+
294+ file_configs. push ( FileConfig {
295+ targets : vec ! [ target. url. clone( ) ] ,
296+ labels,
297+ } ) ;
286298 }
287299 }
288300
289- // 验证分组结果
290- assert_eq ! ( grouped_targets. len( ) , 2 ) ; // web 和 api 两个标签
291-
292- let web_targets = grouped_targets. get ( "web" ) . unwrap ( ) ;
293- assert_eq ! ( web_targets. len( ) , 2 ) ;
294- assert ! ( web_targets. contains( & "https://example1.com" . to_string( ) ) ) ;
295- assert ! ( web_targets. contains( & "https://example2.com" . to_string( ) ) ) ;
301+ // 验证处理结果 - 应该有 6 个配置 (2 endpoints * 3 targets)
302+ assert_eq ! ( file_configs. len( ) , 6 ) ;
296303
297- let api_targets = grouped_targets. get ( "api" ) . unwrap ( ) ;
298- assert_eq ! ( api_targets. len( ) , 2 ) ;
299- assert ! ( api_targets. contains( & "https://example1.com" . to_string( ) ) ) ;
300- assert ! ( api_targets. contains( & "https://api.example.com" . to_string( ) ) ) ;
304+ // 验证每个配置都包含正确的 target 和 labels
305+ for config in & file_configs {
306+ assert_eq ! ( config. targets. len( ) , 1 ) ; // 每个配置只有一个 target
307+ assert ! ( config. labels. contains_key( ENDPOINT_URL ) ) ;
308+ assert ! ( config. labels. contains_key( ENDPOINT_NAME ) ) ;
309+ assert ! ( config. labels. contains_key( ENDPOINT_GEOHASH ) ) ;
310+ assert ! ( config. labels. contains_key( "type" ) ) ; // target 的 label
311+ }
301312 }
302313
303314 #[ test]
@@ -310,20 +321,18 @@ mod tests {
310321 labels. insert ( ENDPOINT_URL . to_string ( ) , "test.example.com:443" . to_string ( ) ) ;
311322 labels. insert ( ENDPOINT_NAME . to_string ( ) , "TestEndpoint" . to_string ( ) ) ;
312323 labels. insert ( ENDPOINT_GEOHASH . to_string ( ) , "test_hash" . to_string ( ) ) ;
313- labels. insert ( TARGET_TAG . to_string ( ) , "test_tag" . to_string ( ) ) ;
324+ labels. insert ( "type" . to_string ( ) , "web" . to_string ( ) ) ;
325+ labels. insert ( "env" . to_string ( ) , "prod" . to_string ( ) ) ;
314326
315327 let file_config = FileConfig { targets, labels } ;
316328
317329 assert_eq ! ( file_config. targets. len( ) , 2 ) ;
318- assert_eq ! ( file_config. labels. len( ) , 4 ) ;
330+ assert_eq ! ( file_config. labels. len( ) , 5 ) ;
319331 assert_eq ! (
320332 file_config. labels. get( ENDPOINT_NAME ) ,
321333 Some ( & "TestEndpoint" . to_string( ) )
322334 ) ;
323- assert_eq ! (
324- file_config. labels. get( TARGET_TAG ) ,
325- Some ( & "test_tag" . to_string( ) )
326- ) ;
335+ assert_eq ! ( file_config. labels. get( "type" ) , Some ( & "web" . to_string( ) ) ) ;
327336 }
328337
329338 #[ tokio:: test]
0 commit comments