1
1
// Copyright (c) Microsoft Corporation.
2
2
// Licensed under the MIT License.
3
3
4
- use crate :: args:: { ConfigSubCommand , DscType , OutputFormat , ResourceSubCommand } ;
4
+ use crate :: args:: { ConfigSubCommand , DscType , ExtensionSubCommand , OutputFormat , ResourceSubCommand } ;
5
5
use crate :: resolve:: { get_contents, Include } ;
6
6
use crate :: resource_command:: { get_resource, self } ;
7
7
use crate :: tablewriter:: Table ;
@@ -16,6 +16,8 @@ use dsc_lib::{
16
16
config_result:: ResourceGetResult ,
17
17
Configurator ,
18
18
} ,
19
+ discovery:: discovery_trait:: DiscoveryKind ,
20
+ discovery:: command_discovery:: ImportedManifest ,
19
21
dscerror:: DscError ,
20
22
DscManager ,
21
23
dscresources:: invoke_result:: {
@@ -25,6 +27,7 @@ use dsc_lib::{
25
27
} ,
26
28
dscresources:: dscresource:: { Capability , ImplementedAs , Invoke } ,
27
29
dscresources:: resource_manifest:: { import_manifest, ResourceManifest } ,
30
+ extensions:: dscextension:: Capability as ExtensionCapability ,
28
31
progress:: ProgressFormat ,
29
32
} ;
30
33
use rust_i18n:: t;
@@ -543,6 +546,22 @@ pub fn validate_config(config: &Configuration, progress_format: ProgressFormat)
543
546
Ok ( ( ) )
544
547
}
545
548
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
+
546
565
#[ allow( clippy:: too_many_lines) ]
547
566
pub fn resource ( subcommand : & ResourceSubCommand , progress_format : ProgressFormat ) {
548
567
let mut dsc = match DscManager :: new ( ) {
@@ -592,6 +611,62 @@ pub fn resource(subcommand: &ResourceSubCommand, progress_format: ProgressFormat
592
611
}
593
612
}
594
613
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
+
595
670
fn 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 ) {
596
671
let mut write_table = false ;
597
672
let mut table = Table :: new ( & [
@@ -607,86 +682,88 @@ fn list_resources(dsc: &mut DscManager, resource_name: Option<&String>, adapter_
607
682
write_table = true ;
608
683
}
609
684
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
+ }
626
703
}
627
- }
628
704
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 ( ) ) ) {
635
718
continue ;
636
719
}
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
- }
644
720
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 ; } ;
648
724
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
+ }
655
732
}
656
733
}
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 ;
657
740
}
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 ;
664
741
}
665
- }
666
742
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
+ }
690
767
}
691
768
}
692
769
0 commit comments