11// Copyright (c) Microsoft Corporation.
22// Licensed under the MIT License.
33
4- use crate :: args:: { ConfigSubCommand , DscType , OutputFormat , ResourceSubCommand } ;
4+ use crate :: args:: { ConfigSubCommand , DscType , ExtensionSubCommand , OutputFormat , ResourceSubCommand } ;
55use crate :: resolve:: { get_contents, Include } ;
66use crate :: resource_command:: { get_resource, self } ;
77use crate :: tablewriter:: Table ;
@@ -16,6 +16,8 @@ use dsc_lib::{
1616 config_result:: ResourceGetResult ,
1717 Configurator ,
1818 } ,
19+ discovery:: discovery_trait:: DiscoveryKind ,
20+ discovery:: command_discovery:: ImportedManifest ,
1921 dscerror:: DscError ,
2022 DscManager ,
2123 dscresources:: invoke_result:: {
@@ -25,6 +27,7 @@ use dsc_lib::{
2527 } ,
2628 dscresources:: dscresource:: { Capability , ImplementedAs , Invoke } ,
2729 dscresources:: resource_manifest:: { import_manifest, ResourceManifest } ,
30+ extensions:: dscextension:: Capability as ExtensionCapability ,
2831 progress:: ProgressFormat ,
2932} ;
3033use rust_i18n:: t;
@@ -543,6 +546,22 @@ pub fn validate_config(config: &Configuration, progress_format: ProgressFormat)
543546 Ok ( ( ) )
544547}
545548
549+ pub fn extension ( subcommand : & ExtensionSubCommand , progress_format : ProgressFormat ) {
550+ let mut dsc = match DscManager :: new ( ) {
551+ Ok ( dsc) => dsc,
552+ Err ( err) => {
553+ error ! ( "Error: {err}" ) ;
554+ exit ( EXIT_DSC_ERROR ) ;
555+ }
556+ } ;
557+
558+ match subcommand {
559+ ExtensionSubCommand :: List { extension_name, output_format} => {
560+ list_extensions ( & mut dsc, extension_name. as_ref ( ) , output_format. as_ref ( ) , progress_format) ;
561+ } ,
562+ }
563+ }
564+
546565#[ allow( clippy:: too_many_lines) ]
547566pub fn resource ( subcommand : & ResourceSubCommand , progress_format : ProgressFormat ) {
548567 let mut dsc = match DscManager :: new ( ) {
@@ -592,6 +611,62 @@ pub fn resource(subcommand: &ResourceSubCommand, progress_format: ProgressFormat
592611 }
593612}
594613
614+ fn list_extensions ( dsc : & mut DscManager , extension_name : Option < & String > , format : Option < & OutputFormat > , progress_format : ProgressFormat ) {
615+ let mut write_table = false ;
616+ let mut table = Table :: new ( & [
617+ t ! ( "subcommand.tableHeader_type" ) . to_string ( ) . as_ref ( ) ,
618+ t ! ( "subcommand.tableHeader_version" ) . to_string ( ) . as_ref ( ) ,
619+ t ! ( "subcommand.tableHeader_capabilities" ) . to_string ( ) . as_ref ( ) ,
620+ t ! ( "subcommand.tableHeader_description" ) . to_string ( ) . as_ref ( ) ,
621+ ] ) ;
622+ if format. is_none ( ) && io:: stdout ( ) . is_terminal ( ) {
623+ // write as table if format is not specified and interactive
624+ write_table = true ;
625+ }
626+ let mut include_separator = false ;
627+ for manifest_resource in dsc. list_available ( & DiscoveryKind :: Extension , extension_name. unwrap_or ( & String :: from ( "*" ) ) , "" , progress_format) {
628+ if let ImportedManifest :: Extension ( extension) = manifest_resource {
629+ let mut capabilities = "-" . to_string ( ) ;
630+ let capability_types = [
631+ ( ExtensionCapability :: Discover , "d" ) ,
632+ ] ;
633+
634+ for ( i, ( capability, letter) ) in capability_types. iter ( ) . enumerate ( ) {
635+ if extension. capabilities . contains ( capability) {
636+ capabilities. replace_range ( i..=i, letter) ;
637+ }
638+ }
639+
640+ if write_table {
641+ table. add_row ( vec ! [
642+ extension. type_name,
643+ extension. version,
644+ capabilities,
645+ extension. description. unwrap_or_default( )
646+ ] ) ;
647+ }
648+ else {
649+ // convert to json
650+ let json = match serde_json:: to_string ( & extension) {
651+ Ok ( json) => json,
652+ Err ( err) => {
653+ error ! ( "JSON: {err}" ) ;
654+ exit ( EXIT_JSON_ERROR ) ;
655+ }
656+ } ;
657+ write_object ( & json, format, include_separator) ;
658+ include_separator = true ;
659+ // insert newline separating instances if writing to console
660+ if io:: stdout ( ) . is_terminal ( ) { println ! ( ) ; }
661+ }
662+ }
663+ }
664+
665+ if write_table {
666+ table. print ( ) ;
667+ }
668+ }
669+
595670fn list_resources ( dsc : & mut DscManager , resource_name : Option < & String > , adapter_name : Option < & String > , description : Option < & String > , tags : Option < & Vec < String > > , format : Option < & OutputFormat > , progress_format : ProgressFormat ) {
596671 let mut write_table = false ;
597672 let mut table = Table :: new ( & [
@@ -607,86 +682,88 @@ fn list_resources(dsc: &mut DscManager, resource_name: Option<&String>, adapter_
607682 write_table = true ;
608683 }
609684 let mut include_separator = false ;
610- for resource in dsc. list_available_resources ( resource_name. unwrap_or ( & String :: from ( "*" ) ) , adapter_name. unwrap_or ( & String :: new ( ) ) , progress_format) {
611- let mut capabilities = "--------" . to_string ( ) ;
612- let capability_types = [
613- ( Capability :: Get , "g" ) ,
614- ( Capability :: Set , "s" ) ,
615- ( Capability :: SetHandlesExist , "x" ) ,
616- ( Capability :: WhatIf , "w" ) ,
617- ( Capability :: Test , "t" ) ,
618- ( Capability :: Delete , "d" ) ,
619- ( Capability :: Export , "e" ) ,
620- ( Capability :: Resolve , "r" ) ,
621- ] ;
622-
623- for ( i, ( capability, letter) ) in capability_types. iter ( ) . enumerate ( ) {
624- if resource. capabilities . contains ( capability) {
625- capabilities. replace_range ( i..=i, letter) ;
685+ for manifest_resource in dsc. list_available ( & DiscoveryKind :: Resource , resource_name. unwrap_or ( & String :: from ( "*" ) ) , adapter_name. unwrap_or ( & String :: new ( ) ) , progress_format) {
686+ if let ImportedManifest :: Resource ( resource) = manifest_resource {
687+ let mut capabilities = "--------" . to_string ( ) ;
688+ let capability_types = [
689+ ( Capability :: Get , "g" ) ,
690+ ( Capability :: Set , "s" ) ,
691+ ( Capability :: SetHandlesExist , "x" ) ,
692+ ( Capability :: WhatIf , "w" ) ,
693+ ( Capability :: Test , "t" ) ,
694+ ( Capability :: Delete , "d" ) ,
695+ ( Capability :: Export , "e" ) ,
696+ ( Capability :: Resolve , "r" ) ,
697+ ] ;
698+
699+ for ( i, ( capability, letter) ) in capability_types. iter ( ) . enumerate ( ) {
700+ if resource. capabilities . contains ( capability) {
701+ capabilities. replace_range ( i..=i, letter) ;
702+ }
626703 }
627- }
628704
629- // if description, tags, or write_table is specified, pull resource manifest if it exists
630- if let Some ( ref resource_manifest) = resource. manifest {
631- let manifest = match import_manifest ( resource_manifest. clone ( ) ) {
632- Ok ( resource_manifest) => resource_manifest,
633- Err ( err) => {
634- error ! ( "{} {}: {err}" , t!( "subcommand.invalidManifest" ) , resource. type_name) ;
705+ // if description, tags, or write_table is specified, pull resource manifest if it exists
706+ if let Some ( ref resource_manifest) = resource. manifest {
707+ let manifest = match import_manifest ( resource_manifest. clone ( ) ) {
708+ Ok ( resource_manifest) => resource_manifest,
709+ Err ( err) => {
710+ error ! ( "{} {}: {err}" , t!( "subcommand.invalidManifest" ) , resource. type_name) ;
711+ continue ;
712+ }
713+ } ;
714+
715+ // if description is specified, skip if resource description does not contain it
716+ if description. is_some ( ) &&
717+ ( manifest. description . is_none ( ) | !manifest. description . unwrap_or_default ( ) . to_lowercase ( ) . contains ( & description. unwrap_or ( & String :: new ( ) ) . to_lowercase ( ) ) ) {
635718 continue ;
636719 }
637- } ;
638-
639- // if description is specified, skip if resource description does not contain it
640- if description. is_some ( ) &&
641- ( manifest. description . is_none ( ) | !manifest. description . unwrap_or_default ( ) . to_lowercase ( ) . contains ( & description. unwrap_or ( & String :: new ( ) ) . to_lowercase ( ) ) ) {
642- continue ;
643- }
644720
645- // if tags is specified, skip if resource tags do not contain the tags
646- if let Some ( tags) = tags {
647- let Some ( manifest_tags) = manifest. tags else { continue ; } ;
721+ // if tags is specified, skip if resource tags do not contain the tags
722+ if let Some ( tags) = tags {
723+ let Some ( manifest_tags) = manifest. tags else { continue ; } ;
648724
649- let mut found = false ;
650- for tag_to_find in tags {
651- for tag in & manifest_tags {
652- if tag. to_lowercase ( ) == tag_to_find. to_lowercase ( ) {
653- found = true ;
654- break ;
725+ let mut found = false ;
726+ for tag_to_find in tags {
727+ for tag in & manifest_tags {
728+ if tag. to_lowercase ( ) == tag_to_find. to_lowercase ( ) {
729+ found = true ;
730+ break ;
731+ }
655732 }
656733 }
734+ if !found { continue ; }
735+ }
736+ } else {
737+ // resource does not have a manifest but filtering on description or tags was requested - skip such resource
738+ if description. is_some ( ) || tags. is_some ( ) {
739+ continue ;
657740 }
658- if !found { continue ; }
659- }
660- } else {
661- // resource does not have a manifest but filtering on description or tags was requested - skip such resource
662- if description. is_some ( ) || tags. is_some ( ) {
663- continue ;
664741 }
665- }
666742
667- if write_table {
668- table. add_row ( vec ! [
669- resource. type_name,
670- format!( "{:?}" , resource. kind) ,
671- resource. version,
672- capabilities,
673- resource. require_adapter. unwrap_or_default( ) ,
674- resource. description. unwrap_or_default( )
675- ] ) ;
676- }
677- else {
678- // convert to json
679- let json = match serde_json:: to_string ( & resource) {
680- Ok ( json) => json,
681- Err ( err) => {
682- error ! ( "JSON: {err}" ) ;
683- exit ( EXIT_JSON_ERROR ) ;
684- }
685- } ;
686- write_object ( & json, format, include_separator) ;
687- include_separator = true ;
688- // insert newline separating instances if writing to console
689- if io:: stdout ( ) . is_terminal ( ) { println ! ( ) ; }
743+ if write_table {
744+ table. add_row ( vec ! [
745+ resource. type_name,
746+ format!( "{:?}" , resource. kind) ,
747+ resource. version,
748+ capabilities,
749+ resource. require_adapter. unwrap_or_default( ) ,
750+ resource. description. unwrap_or_default( )
751+ ] ) ;
752+ }
753+ else {
754+ // convert to json
755+ let json = match serde_json:: to_string ( & resource) {
756+ Ok ( json) => json,
757+ Err ( err) => {
758+ error ! ( "JSON: {err}" ) ;
759+ exit ( EXIT_JSON_ERROR ) ;
760+ }
761+ } ;
762+ write_object ( & json, format, include_separator) ;
763+ include_separator = true ;
764+ // insert newline separating instances if writing to console
765+ if io:: stdout ( ) . is_terminal ( ) { println ! ( ) ; }
766+ }
690767 }
691768 }
692769
0 commit comments