@@ -17,7 +17,7 @@ use std::ffi::OsStr;
17
17
use std:: fs:: File ;
18
18
use std:: io:: BufReader ;
19
19
use std:: path:: { Path , PathBuf } ;
20
- use tracing:: { debug, error , info, trace, warn, warn_span, Span } ;
20
+ use tracing:: { debug, info, trace, warn, warn_span} ;
21
21
use tracing_indicatif:: span_ext:: IndicatifSpanExt ;
22
22
23
23
pub struct CommandDiscovery {
@@ -273,144 +273,52 @@ impl ResourceDiscovery for CommandDiscovery {
273
273
Ok ( resources)
274
274
}
275
275
276
- # [ allow ( clippy :: too_many_lines ) ]
276
+ // TODO: handle version requirements
277
277
fn find_resources ( & mut self , required_resource_types : & [ String ] ) -> Result < BTreeMap < String , DscResource > , DscError >
278
278
{
279
279
debug ! ( "Searching for resources: {:?}" , required_resource_types) ;
280
+ self . discover_resources ( "*" ) ?;
280
281
281
- let pb_span = warn_span ! ( "" ) ;
282
- pb_span. pb_set_style ( & ProgressStyle :: with_template (
283
- "{spinner:.green} [{elapsed_precise:.cyan}] [{bar:40.cyan/blue}] {pos:>7}/{len:7} {msg:.yellow}"
284
- ) ?) ;
285
- pb_span. pb_set_message ( "Searching for resources" ) ;
286
- let _ = pb_span. enter ( ) ;
287
-
288
- let mut resources: BTreeMap < String , DscResource > = BTreeMap :: new ( ) ;
289
- let mut adapter_resources: BTreeMap < String , DscResource > = BTreeMap :: new ( ) ;
282
+ let mut found_resources = BTreeMap :: < String , DscResource > :: new ( ) ;
290
283
let mut remaining_required_resource_types = required_resource_types. to_owned ( ) ;
291
284
292
- if let Ok ( paths) = CommandDiscovery :: get_resource_paths ( ) {
293
- for path in paths {
294
- debug ! ( "Searching in {:?}" , path) ;
295
- if path. exists ( ) && path. is_dir ( ) {
296
- for entry in path. read_dir ( ) . unwrap ( ) {
297
- let entry = entry. unwrap ( ) ;
298
- let path = entry. path ( ) ;
299
- if path. is_file ( ) {
300
- let file_name = path. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
301
- let file_name_lowercase = file_name. to_lowercase ( ) ;
302
- if file_name_lowercase. ends_with ( ".dsc.resource.json" ) ||
303
- file_name_lowercase. ends_with ( ".dsc.resource.yaml" ) ||
304
- file_name_lowercase. ends_with ( ".dsc.resource.yml" ) {
305
- let resource = match load_manifest ( & path)
306
- {
307
- Ok ( r) => r,
308
- Err ( e) => {
309
- /* In case of non-list resource/config operations:
310
- At this point we can't determine whether or not the bad manifest contains resource that is requested by resource/config operation
311
- if it is, then "ResouceNotFound" error will be issued later
312
- and here we just record the error into debug stream.*/
313
- debug ! ( "{}" , e) ;
314
- continue ;
315
- } ,
316
- } ;
285
+ for ( resource_name, resources) in self . resources . iter ( ) {
286
+ let Some ( resource ) = resources. first ( ) else {
287
+ // skip if no resources
288
+ continue ;
289
+ } ;
317
290
318
- if let Some ( ref manifest) = resource. manifest {
319
- let manifest = import_manifest ( manifest. clone ( ) ) ?;
320
- if manifest. kind == Some ( Kind :: Adapter ) {
321
- adapter_resources. insert ( resource. type_name . to_lowercase ( ) , resource. clone ( ) ) ;
322
- resources. insert ( resource. type_name . to_lowercase ( ) , resource. clone ( ) ) ;
323
- }
324
- }
325
- if remaining_required_resource_types. contains ( & resource. type_name . to_lowercase ( ) )
326
- {
327
- remaining_required_resource_types. retain ( |x| * x != resource. type_name . to_lowercase ( ) ) ;
328
- debug ! ( "Found {} in {}" , & resource. type_name, path. display( ) ) ;
329
- Span :: current ( ) . pb_inc ( 1 ) ;
330
- resources. insert ( resource. type_name . to_lowercase ( ) , resource) ;
331
- if remaining_required_resource_types. is_empty ( )
332
- {
333
- return Ok ( resources) ;
334
- }
335
- }
336
- }
337
- }
338
- }
291
+ if remaining_required_resource_types. contains ( & resource_name. to_lowercase ( ) )
292
+ {
293
+ // remove the resource from the list of required resources
294
+ remaining_required_resource_types. retain ( |x| * x != resource_name. to_lowercase ( ) ) ;
295
+ found_resources. insert ( resource_name. to_lowercase ( ) , resource. clone ( ) ) ;
296
+ if remaining_required_resource_types. is_empty ( )
297
+ {
298
+ return Ok ( found_resources) ;
339
299
}
340
300
}
341
301
}
342
- debug ! ( "Found {} matching non-adapter-based resources" , resources . len( ) ) ;
302
+ debug ! ( "Found {} matching non-adapter-based resources" , found_resources . len( ) ) ;
343
303
344
304
// now go through the adapter resources and add them to the list of resources
345
- for adapter in adapter_resources {
346
- debug ! ( "Enumerating resources for adapter '{}'" , adapter. 1 . type_name) ;
347
- let pb_adapter_span = warn_span ! ( "" ) ;
348
- pb_adapter_span. pb_set_style ( & ProgressStyle :: with_template (
349
- "{spinner:.green} [{elapsed_precise:.cyan}] {msg:.white}"
350
- ) ?) ;
351
- pb_adapter_span. pb_set_message ( format ! ( "Enumerating resources for adapter '{}'" , adapter. 1 . type_name) . as_str ( ) ) ;
352
- let _ = pb_adapter_span. enter ( ) ;
353
- let adapter_resource = adapter. 1 ;
354
- let adapter_type_name = adapter_resource. type_name . clone ( ) ;
355
- let manifest = if let Some ( manifest) = adapter_resource. manifest {
356
- if let Ok ( manifest) = import_manifest ( manifest) {
357
- manifest
358
- } else {
359
- return Err ( DscError :: Operation ( format ! ( "Failed to import manifest for '{}'" , adapter_resource. type_name. clone( ) ) ) ) ;
360
- }
361
- } else {
362
- return Err ( DscError :: MissingManifest ( adapter_resource. type_name . clone ( ) ) ) ;
305
+ for ( adapted_name, adapted_resource) in self . adapted_resources . iter ( ) {
306
+ let Some ( adapted_resource) = adapted_resource. first ( ) else {
307
+ // skip if no resources
308
+ continue ;
363
309
} ;
364
- let mut adapter_resources_count = 0 ;
365
- // invoke the list command
366
- let list_command = manifest. adapter . unwrap ( ) . list ;
367
- let ( exit_code, stdout, stderr) = match invoke_command ( & list_command. executable , list_command. args , None , Some ( & adapter_resource. directory ) , None )
368
- {
369
- Ok ( ( exit_code, stdout, stderr) ) => ( exit_code, stdout, stderr) ,
370
- Err ( e) => {
371
- /* In case of non-list resource/config operations:
372
- print failure from adapter as error because this adapter was specifically requested by current resource/config operation*/
373
- error ! ( "Could not start {}: {}" , list_command. executable, e) ;
374
- continue ;
375
- } ,
376
- } ;
377
- log_resource_traces ( & stderr) ;
378
310
379
- if exit_code != 0 {
380
- /* In case of non-list resource/config operations:
381
- print failure from adapter as error because this adapter was specifically requested by current resource/config operation*/
382
- error ! ( "Adapter failed to list resources with exit code {exit_code}: {stderr}" ) ;
383
- }
384
-
385
- for line in stdout. lines ( ) {
386
- match serde_json:: from_str :: < DscResource > ( line) {
387
- Result :: Ok ( resource) => {
388
- if resource. require_adapter . is_none ( ) {
389
- error ! ( "{}" , DscError :: MissingRequires ( adapter. 0 . clone( ) , resource. type_name. clone( ) ) . to_string( ) ) ;
390
- continue ;
391
- }
392
- if remaining_required_resource_types. contains ( & resource. type_name . to_lowercase ( ) )
393
- {
394
- remaining_required_resource_types. retain ( |x| * x != resource. type_name . to_lowercase ( ) ) ;
395
- debug ! ( "Found {} in {}" , & resource. type_name, & resource. path) ;
396
- resources. insert ( resource. type_name . to_lowercase ( ) , resource) ;
397
- adapter_resources_count += 1 ;
398
- if remaining_required_resource_types. is_empty ( )
399
- {
400
- return Ok ( resources) ;
401
- }
402
- }
403
- } ,
404
- Result :: Err ( err) => {
405
- error ! ( "Failed to parse resource: {line} -> {err}" ) ;
406
- continue ;
407
- }
408
- } ;
311
+ if remaining_required_resource_types. contains ( & adapted_name. to_lowercase ( ) )
312
+ {
313
+ remaining_required_resource_types. retain ( |x| * x != adapted_name. to_lowercase ( ) ) ;
314
+ found_resources. insert ( adapted_name. to_lowercase ( ) , adapted_resource. clone ( ) ) ;
315
+ if remaining_required_resource_types. is_empty ( )
316
+ {
317
+ return Ok ( found_resources) ;
318
+ }
409
319
}
410
-
411
- debug ! ( "Adapter '{}' listed {} matching resources" , adapter_type_name, adapter_resources_count) ;
412
320
}
413
- Ok ( resources )
321
+ Ok ( found_resources )
414
322
}
415
323
}
416
324
@@ -423,8 +331,15 @@ fn insert_resource(resources: &mut BTreeMap<String, Vec<DscResource>>, resource:
423
331
} ;
424
332
// compare the resource versions and insert newest to oldest using semver
425
333
let mut insert_index = resource_versions. len ( ) ;
426
- for ( index, resource_version) in resource_versions. iter ( ) . enumerate ( ) {
427
- if Version :: parse ( & resource_version. version ) ? < Version :: parse ( & resource. version ) ? {
334
+ for ( index, resource_instance) in resource_versions. iter ( ) . enumerate ( ) {
335
+ let resource_instance_version = Version :: parse ( & resource_instance. version ) ?;
336
+ let resource_version = Version :: parse ( & resource. version ) ?;
337
+ // if the version already exists, we skip
338
+ if resource_instance_version == resource_version {
339
+ return Ok ( ( ) ) ;
340
+ }
341
+
342
+ if resource_instance_version < resource_version {
428
343
insert_index = index;
429
344
break ;
430
345
}
0 commit comments