@@ -7,7 +7,7 @@ use crate::dscresources::dscresource::{Capability, DscResource, ImplementedAs};
7
7
use crate :: dscresources:: resource_manifest:: { import_manifest, validate_semver, Kind , ResourceManifest , SchemaKind } ;
8
8
use crate :: dscresources:: command_resource:: invoke_command;
9
9
use crate :: dscerror:: DscError ;
10
- use crate :: extensions:: dscextension:: { self , DscExtension } ;
10
+ use crate :: extensions:: dscextension:: { self , DscExtension , Capability as ExtensionCapability } ;
11
11
use crate :: extensions:: extension_manifest:: ExtensionManifest ;
12
12
use crate :: progress:: { ProgressBar , ProgressFormat } ;
13
13
use linked_hash_map:: LinkedHashMap ;
@@ -68,6 +68,7 @@ impl Default for ResourcePathSetting {
68
68
}
69
69
70
70
impl CommandDiscovery {
71
+ #[ must_use]
71
72
pub fn new ( progress_format : ProgressFormat ) -> CommandDiscovery {
72
73
CommandDiscovery {
73
74
adapters : BTreeMap :: new ( ) ,
@@ -184,6 +185,11 @@ impl ResourceDiscovery for CommandDiscovery {
184
185
fn discover ( & mut self , kind : & DiscoveryKind , filter : & str ) -> Result < ( ) , DscError > {
185
186
info ! ( "{}" , t!( "discovery.commandDiscovery.discoverResources" , filter = filter) ) ;
186
187
188
+ // if kind is DscResource, we need to discover extensions first
189
+ if * kind == DiscoveryKind :: Resource {
190
+ self . discover ( & DiscoveryKind :: Extension , "*" ) ?;
191
+ }
192
+
187
193
let regex_str = convert_wildcard_to_regex ( filter) ;
188
194
debug ! ( "Using regex {regex_str} as filter for adapter name" ) ;
189
195
let mut regex_builder = RegexBuilder :: new ( & regex_str) ;
@@ -193,7 +199,14 @@ impl ResourceDiscovery for CommandDiscovery {
193
199
} ;
194
200
195
201
let mut progress = ProgressBar :: new ( 1 , self . progress_format ) ?;
196
- progress. write_activity ( t ! ( "discovery.commandDiscovery.progressSearching" ) . to_string ( ) . as_str ( ) ) ;
202
+ match kind {
203
+ DiscoveryKind :: Resource => {
204
+ progress. write_activity ( t ! ( "discovery.commandDiscovery.progressSearching" ) . to_string ( ) . as_str ( ) ) ;
205
+ } ,
206
+ DiscoveryKind :: Extension => {
207
+ progress. write_activity ( t ! ( "discovery.commandDiscovery.extensionSearching" ) . to_string ( ) . as_str ( ) ) ;
208
+ }
209
+ }
197
210
198
211
let mut adapters = BTreeMap :: < String , Vec < DscResource > > :: new ( ) ;
199
212
let mut resources = BTreeMap :: < String , Vec < DscResource > > :: new ( ) ;
@@ -217,7 +230,7 @@ impl ResourceDiscovery for CommandDiscovery {
217
230
let file_name_lowercase = file_name. to_lowercase ( ) ;
218
231
if ( kind == & DiscoveryKind :: Resource && DSC_RESOURCE_EXTENSIONS . iter ( ) . any ( |ext| file_name_lowercase. ends_with ( ext) ) ) ||
219
232
( kind == & DiscoveryKind :: Extension && DSC_EXTENSION_EXTENSIONS . iter ( ) . any ( |ext| file_name_lowercase. ends_with ( ext) ) ) {
220
- trace ! ( "{}" , t!( "discovery.commandDiscovery.foundManifest " , path = path. to_string_lossy( ) ) ) ;
233
+ trace ! ( "{}" , t!( "discovery.commandDiscovery.foundResourceManifest " , path = path. to_string_lossy( ) ) ) ;
221
234
let resource = match load_manifest ( & path)
222
235
{
223
236
Ok ( r) => r,
@@ -274,10 +287,31 @@ impl ResourceDiscovery for CommandDiscovery {
274
287
}
275
288
276
289
progress. write_increment ( 1 ) ;
277
- debug ! ( "Found {} matching non-adapter-based resources" , resources. len( ) ) ;
278
- self . adapters = adapters;
279
- self . resources = resources;
280
- self . extensions = extensions;
290
+
291
+ match kind {
292
+ DiscoveryKind :: Resource => {
293
+ // Now we need to call discover extensions and add those resource to the list of resources
294
+ for ( _extension_name, extension) in self . extensions . iter ( ) {
295
+ if extension. capabilities . contains ( & ExtensionCapability :: Discover ) {
296
+ debug ! ( "{}" , t!( "discovery.commandDiscovery.callingExtension" , extension = extension. type_name) ) ;
297
+ let discovered_resources = extension. discover ( ) ?;
298
+ debug ! ( "{}" , t!( "discovery.commandDiscovery.extensionFoundResources" , extension = extension. type_name, count = discovered_resources. len( ) ) ) ;
299
+ for resource in discovered_resources {
300
+ if regex. is_match ( & resource. type_name ) {
301
+ trace ! ( "{}" , t!( "discovery.commandDiscovery.extensionResourceFound" , resource = resource. type_name) ) ;
302
+ insert_resource ( & mut resources, & resource, true ) ;
303
+ }
304
+ }
305
+ }
306
+ }
307
+ self . adapters = adapters;
308
+ self . resources = resources;
309
+ } ,
310
+ DiscoveryKind :: Extension => {
311
+ self . extensions = extensions;
312
+ }
313
+ }
314
+
281
315
Ok ( ( ) )
282
316
}
283
317
@@ -505,7 +539,6 @@ impl ResourceDiscovery for CommandDiscovery {
505
539
}
506
540
}
507
541
508
- // helper to insert a resource into a vector of resources in order of newest to oldest
509
542
// TODO: This should be a BTreeMap of the resource name and a BTreeMap of the version and DscResource, this keeps it version sorted more efficiently
510
543
fn insert_resource ( resources : & mut BTreeMap < String , Vec < DscResource > > , resource : & DscResource , skip_duplicate_version : bool ) {
511
544
if resources. contains_key ( & resource. type_name ) {
@@ -548,36 +581,48 @@ fn insert_resource(resources: &mut BTreeMap<String, Vec<DscResource>>, resource:
548
581
}
549
582
}
550
583
551
- fn load_manifest ( path : & Path ) -> Result < ManifestResource , DscError > {
584
+ /// Loads a manifest from the given path and returns a `ManifestResource`.
585
+ ///
586
+ /// # Arguments
587
+ ///
588
+ /// * `path` - The path to the manifest file.
589
+ ///
590
+ /// # Returns
591
+ ///
592
+ /// * `ManifestResource` if the manifest was loaded successfully.
593
+ ///
594
+ /// # Errors
595
+ ///
596
+ /// * Returns a `DscError` if the manifest could not be loaded or parsed.
597
+ pub fn load_manifest ( path : & Path ) -> Result < ManifestResource , DscError > {
552
598
let contents = fs:: read_to_string ( path) ?;
553
599
if path. extension ( ) == Some ( OsStr :: new ( "json" ) ) {
554
- if let Ok ( manifest) = serde_json:: from_str :: < ResourceManifest > ( & contents) {
555
- let resource = load_resource_manifest ( path, & manifest) ?;
556
- return Ok ( ManifestResource :: Resource ( resource ) ) ;
600
+ if let Ok ( manifest) = serde_json:: from_str :: < ExtensionManifest > ( & contents) {
601
+ let extension = load_extension_manifest ( path, & manifest) ?;
602
+ return Ok ( ManifestResource :: Extension ( extension ) ) ;
557
603
}
558
- let manifest = match serde_json:: from_str :: < ExtensionManifest > ( & contents) {
604
+ let manifest = match serde_json:: from_str :: < ResourceManifest > ( & contents) {
559
605
Ok ( manifest) => manifest,
560
606
Err ( err) => {
561
- return Err ( DscError :: Validation ( format ! ( "Invalid manifest { path:?} version value: { err}" ) ) ) ;
607
+ return Err ( DscError :: Manifest ( t ! ( "discovery.commandDiscovery.invalidManifest" , resource = path. to_string_lossy ( ) ) . to_string ( ) , err) ) ;
562
608
}
563
609
} ;
564
- let extension = load_extension_manifest ( path, & manifest) ?;
565
- return Ok ( ManifestResource :: Extension ( extension ) ) ;
610
+ let resource = load_resource_manifest ( path, & manifest) ?;
611
+ return Ok ( ManifestResource :: Resource ( resource ) ) ;
566
612
}
567
- else {
568
- if let Ok ( manifest) = serde_yaml:: from_str :: < ResourceManifest > ( & contents) {
569
- let resource = load_resource_manifest ( path, & manifest) ?;
570
- return Ok ( ManifestResource :: Resource ( resource) ) ;
571
- }
572
- let manifest = match serde_yaml:: from_str :: < ExtensionManifest > ( & contents) {
573
- Ok ( manifest) => manifest,
574
- Err ( err) => {
575
- return Err ( DscError :: Validation ( format ! ( "Invalid manifest {path:?} version value: {err}" ) ) ) ;
576
- }
577
- } ;
578
- let extension = load_extension_manifest ( path, & manifest) ?;
579
- return Ok ( ManifestResource :: Extension ( extension) ) ;
613
+
614
+ if let Ok ( manifest) = serde_yaml:: from_str :: < ResourceManifest > ( & contents) {
615
+ let resource = load_resource_manifest ( path, & manifest) ?;
616
+ return Ok ( ManifestResource :: Resource ( resource) ) ;
580
617
}
618
+ let manifest = match serde_yaml:: from_str :: < ExtensionManifest > ( & contents) {
619
+ Ok ( manifest) => manifest,
620
+ Err ( err) => {
621
+ return Err ( DscError :: Validation ( format ! ( "Invalid manifest {path:?} version value: {err}" ) ) ) ;
622
+ }
623
+ } ;
624
+ let extension = load_extension_manifest ( path, & manifest) ?;
625
+ Ok ( ManifestResource :: Extension ( extension) )
581
626
}
582
627
583
628
fn load_resource_manifest ( path : & Path , manifest : & ResourceManifest ) -> Result < DscResource , DscError > {
@@ -663,7 +708,7 @@ fn load_extension_manifest(path: &Path, manifest: &ExtensionManifest) -> Result<
663
708
capabilities,
664
709
path : path. to_str ( ) . unwrap ( ) . to_string ( ) ,
665
710
directory : path. parent ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_string ( ) ,
666
- manifest : Some ( serde_json:: to_value ( manifest) ?) ,
711
+ manifest : serde_json:: to_value ( manifest) ?,
667
712
..Default :: default ( )
668
713
} ;
669
714
0 commit comments