@@ -12,8 +12,10 @@ use self::config_doc::{Configuration, DataType};
12
12
use self :: depends_on:: get_resource_invocation_order;
13
13
use self :: config_result:: { ConfigurationGetResult , ConfigurationSetResult , ConfigurationTestResult , ConfigurationExportResult } ;
14
14
use self :: contraints:: { check_length, check_number_limits, check_allowed_values} ;
15
+ use indicatif:: { ProgressBar , ProgressStyle } ;
15
16
use serde_json:: { Map , Value } ;
16
- use std:: collections:: { HashMap , HashSet } ;
17
+ use std:: collections:: HashMap ;
18
+ use std:: time:: Duration ;
17
19
use tracing:: { debug, trace} ;
18
20
19
21
pub mod context;
@@ -131,6 +133,15 @@ fn escape_property_values(properties: &Map<String, Value>) -> Result<Option<Map<
131
133
Ok ( Some ( result) )
132
134
}
133
135
136
+ fn get_progress_bar ( len : u64 ) -> Result < ProgressBar , DscError > {
137
+ let pb = ProgressBar :: new ( len) ;
138
+ pb. enable_steady_tick ( Duration :: from_millis ( 120 ) ) ;
139
+ pb. set_style ( ProgressStyle :: with_template (
140
+ "{spinner:.green} [{elapsed_precise:.cyan}] [{bar:40.cyan/blue}] {pos:>7}/{len:7} {msg:.yellow}"
141
+ ) ?) ;
142
+ Ok ( pb)
143
+ }
144
+
134
145
impl Configurator {
135
146
/// Create a new `Configurator` instance.
136
147
///
@@ -164,8 +175,11 @@ impl Configurator {
164
175
pub fn invoke_get ( & mut self , _error_action : ErrorAction , _progress_callback : impl Fn ( ) + ' static ) -> Result < ConfigurationGetResult , DscError > {
165
176
let config = self . validate_config ( ) ?;
166
177
let mut result = ConfigurationGetResult :: new ( ) ;
167
- for resource in get_resource_invocation_order ( & config, & mut self . statement_parser , & self . context ) ? {
168
- trace ! ( "Get resource '{}' named: {}" , resource. resource_type, resource. name) ;
178
+ let resources = get_resource_invocation_order ( & config, & mut self . statement_parser , & self . context ) ?;
179
+ let pb = get_progress_bar ( resources. len ( ) as u64 ) ?;
180
+ for resource in resources {
181
+ pb. inc ( 1 ) ;
182
+ pb. set_message ( format ! ( "Get '{}'" , resource. name) ) ;
169
183
let properties = self . invoke_property_expressions ( & resource. properties ) ?;
170
184
let Some ( dsc_resource) = self . discovery . find_resource ( & resource. resource_type . to_lowercase ( ) ) else {
171
185
return Err ( DscError :: ResourceNotFound ( resource. resource_type ) ) ;
@@ -181,6 +195,7 @@ impl Configurator {
181
195
result. results . push ( resource_result) ;
182
196
}
183
197
198
+ pb. finish_with_message ( "Get configuration completed" ) ;
184
199
Ok ( result)
185
200
}
186
201
@@ -197,7 +212,11 @@ impl Configurator {
197
212
pub fn invoke_set ( & mut self , skip_test : bool , _error_action : ErrorAction , _progress_callback : impl Fn ( ) + ' static ) -> Result < ConfigurationSetResult , DscError > {
198
213
let config = self . validate_config ( ) ?;
199
214
let mut result = ConfigurationSetResult :: new ( ) ;
200
- for resource in get_resource_invocation_order ( & config, & mut self . statement_parser , & self . context ) ? {
215
+ let resources = get_resource_invocation_order ( & config, & mut self . statement_parser , & self . context ) ?;
216
+ let pb = get_progress_bar ( resources. len ( ) as u64 ) ?;
217
+ for resource in resources {
218
+ pb. inc ( 1 ) ;
219
+ pb. set_message ( format ! ( "Set '{}'" , resource. name) ) ;
201
220
let properties = self . invoke_property_expressions ( & resource. properties ) ?;
202
221
let Some ( dsc_resource) = self . discovery . find_resource ( & resource. resource_type . to_lowercase ( ) ) else {
203
222
return Err ( DscError :: ResourceNotFound ( resource. resource_type ) ) ;
@@ -213,6 +232,7 @@ impl Configurator {
213
232
result. results . push ( resource_result) ;
214
233
}
215
234
235
+ pb. finish_with_message ( "Set configuration completed" ) ;
216
236
Ok ( result)
217
237
}
218
238
@@ -229,7 +249,11 @@ impl Configurator {
229
249
pub fn invoke_test ( & mut self , _error_action : ErrorAction , _progress_callback : impl Fn ( ) + ' static ) -> Result < ConfigurationTestResult , DscError > {
230
250
let config = self . validate_config ( ) ?;
231
251
let mut result = ConfigurationTestResult :: new ( ) ;
232
- for resource in get_resource_invocation_order ( & config, & mut self . statement_parser , & self . context ) ? {
252
+ let resources = get_resource_invocation_order ( & config, & mut self . statement_parser , & self . context ) ?;
253
+ let pb = get_progress_bar ( resources. len ( ) as u64 ) ?;
254
+ for resource in resources {
255
+ pb. inc ( 1 ) ;
256
+ pb. set_message ( format ! ( "Test '{}'" , resource. name) ) ;
233
257
let properties = self . invoke_property_expressions ( & resource. properties ) ?;
234
258
let Some ( dsc_resource) = self . discovery . find_resource ( & resource. resource_type . to_lowercase ( ) ) else {
235
259
return Err ( DscError :: ResourceNotFound ( resource. resource_type ) ) ;
@@ -245,6 +269,7 @@ impl Configurator {
245
269
result. results . push ( resource_result) ;
246
270
}
247
271
272
+ pb. finish_with_message ( "Test configuration completed" ) ;
248
273
Ok ( result)
249
274
}
250
275
@@ -265,17 +290,13 @@ impl Configurator {
265
290
pub fn invoke_export ( & mut self , _error_action : ErrorAction , _progress_callback : impl Fn ( ) + ' static ) -> Result < ConfigurationExportResult , DscError > {
266
291
let config = self . validate_config ( ) ?;
267
292
268
- let duplicates = Self :: find_duplicate_resource_types ( & config) ;
269
- if !duplicates. is_empty ( )
270
- {
271
- let duplicates_string = & duplicates. join ( "," ) ;
272
- return Err ( DscError :: Validation ( format ! ( "Resource(s) {duplicates_string} specified multiple times" ) ) ) ;
273
- }
274
-
275
293
let mut result = ConfigurationExportResult :: new ( ) ;
276
294
let mut conf = config_doc:: Configuration :: new ( ) ;
277
295
278
- for resource in get_resource_invocation_order ( & config, & mut self . statement_parser , & self . context ) ? {
296
+ let pb = get_progress_bar ( config. resources . len ( ) as u64 ) ?;
297
+ for resource in & config. resources {
298
+ pb. inc ( 1 ) ;
299
+ pb. set_message ( format ! ( "Export '{}'" , resource. name) ) ;
279
300
let Some ( dsc_resource) = self . discovery . find_resource ( & resource. resource_type . to_lowercase ( ) ) else {
280
301
return Err ( DscError :: ResourceNotFound ( resource. resource_type . clone ( ) ) ) ;
281
302
} ;
@@ -285,7 +306,7 @@ impl Configurator {
285
306
}
286
307
287
308
result. result = Some ( conf) ;
288
-
309
+ pb . finish_with_message ( "Export configuration completed" ) ;
289
310
Ok ( result)
290
311
}
291
312
@@ -369,27 +390,6 @@ impl Configurator {
369
390
Ok ( ( ) )
370
391
}
371
392
372
- fn find_duplicate_resource_types ( config : & Configuration ) -> Vec < String >
373
- {
374
- let mut map: HashMap < & String , i32 > = HashMap :: new ( ) ;
375
- let mut result: HashSet < String > = HashSet :: new ( ) ;
376
- let resource_list = & config. resources ;
377
- if resource_list. is_empty ( ) {
378
- return Vec :: new ( ) ;
379
- }
380
-
381
- for r in resource_list
382
- {
383
- let v = map. entry ( & r. resource_type ) . or_insert ( 0 ) ;
384
- * v += 1 ;
385
- if * v > 1 {
386
- result. insert ( r. resource_type . clone ( ) ) ;
387
- }
388
- }
389
-
390
- result. into_iter ( ) . collect ( )
391
- }
392
-
393
393
fn validate_config ( & mut self ) -> Result < Configuration , DscError > {
394
394
let config: Configuration = serde_json:: from_str ( self . config . as_str ( ) ) ?;
395
395
0 commit comments