@@ -7,7 +7,7 @@ use crate::dscresources::dscresource::{Capability, DscResource, ImplementedAs};
77use crate :: dscresources:: resource_manifest:: { import_manifest, validate_semver, Kind , ResourceManifest , SchemaKind } ;
88use crate :: dscresources:: command_resource:: invoke_command;
99use crate :: dscerror:: DscError ;
10- use crate :: extensions:: dscextension:: { self , DscExtension } ;
10+ use crate :: extensions:: dscextension:: { self , DscExtension , Capability as ExtensionCapability } ;
1111use crate :: extensions:: extension_manifest:: ExtensionManifest ;
1212use crate :: progress:: { ProgressBar , ProgressFormat } ;
1313use linked_hash_map:: LinkedHashMap ;
@@ -68,6 +68,7 @@ impl Default for ResourcePathSetting {
6868}
6969
7070impl CommandDiscovery {
71+ #[ must_use]
7172 pub fn new ( progress_format : ProgressFormat ) -> CommandDiscovery {
7273 CommandDiscovery {
7374 adapters : BTreeMap :: new ( ) ,
@@ -184,6 +185,11 @@ impl ResourceDiscovery for CommandDiscovery {
184185 fn discover ( & mut self , kind : & DiscoveryKind , filter : & str ) -> Result < ( ) , DscError > {
185186 info ! ( "{}" , t!( "discovery.commandDiscovery.discoverResources" , filter = filter) ) ;
186187
188+ // if kind is DscResource, we need to discover extensions first
189+ if * kind == DiscoveryKind :: Resource {
190+ self . discover ( & DiscoveryKind :: Extension , "*" ) ?;
191+ }
192+
187193 let regex_str = convert_wildcard_to_regex ( filter) ;
188194 debug ! ( "Using regex {regex_str} as filter for adapter name" ) ;
189195 let mut regex_builder = RegexBuilder :: new ( & regex_str) ;
@@ -193,7 +199,14 @@ impl ResourceDiscovery for CommandDiscovery {
193199 } ;
194200
195201 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+ }
197210
198211 let mut adapters = BTreeMap :: < String , Vec < DscResource > > :: new ( ) ;
199212 let mut resources = BTreeMap :: < String , Vec < DscResource > > :: new ( ) ;
@@ -217,7 +230,7 @@ impl ResourceDiscovery for CommandDiscovery {
217230 let file_name_lowercase = file_name. to_lowercase ( ) ;
218231 if ( kind == & DiscoveryKind :: Resource && DSC_RESOURCE_EXTENSIONS . iter ( ) . any ( |ext| file_name_lowercase. ends_with ( ext) ) ) ||
219232 ( 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( ) ) ) ;
221234 let resource = match load_manifest ( & path)
222235 {
223236 Ok ( r) => r,
@@ -274,10 +287,31 @@ impl ResourceDiscovery for CommandDiscovery {
274287 }
275288
276289 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+
281315 Ok ( ( ) )
282316 }
283317
@@ -505,7 +539,6 @@ impl ResourceDiscovery for CommandDiscovery {
505539 }
506540}
507541
508- // helper to insert a resource into a vector of resources in order of newest to oldest
509542// 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
510543fn insert_resource ( resources : & mut BTreeMap < String , Vec < DscResource > > , resource : & DscResource , skip_duplicate_version : bool ) {
511544 if resources. contains_key ( & resource. type_name ) {
@@ -548,36 +581,48 @@ fn insert_resource(resources: &mut BTreeMap<String, Vec<DscResource>>, resource:
548581 }
549582}
550583
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 > {
552598 let contents = fs:: read_to_string ( path) ?;
553599 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 ) ) ;
557603 }
558- let manifest = match serde_json:: from_str :: < ExtensionManifest > ( & contents) {
604+ let manifest = match serde_json:: from_str :: < ResourceManifest > ( & contents) {
559605 Ok ( manifest) => manifest,
560606 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) ) ;
562608 }
563609 } ;
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 ) ) ;
566612 }
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) ) ;
580617 }
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) )
581626}
582627
583628fn load_resource_manifest ( path : & Path , manifest : & ResourceManifest ) -> Result < DscResource , DscError > {
@@ -663,7 +708,7 @@ fn load_extension_manifest(path: &Path, manifest: &ExtensionManifest) -> Result<
663708 capabilities,
664709 path : path. to_str ( ) . unwrap ( ) . to_string ( ) ,
665710 directory : path. parent ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_string ( ) ,
666- manifest : Some ( serde_json:: to_value ( manifest) ?) ,
711+ manifest : serde_json:: to_value ( manifest) ?,
667712 ..Default :: default ( )
668713 } ;
669714
0 commit comments