1
+ //
2
+ // Copyright (c) Microsoft Corporation.
3
+ //
4
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
10
+ // THE SOFTWARE.
11
+ //
12
+
13
+ using System ;
14
+ using System . Collections . Generic ;
15
+ using System . Linq ;
16
+ using System . Management . Automation . Language ;
17
+ using Microsoft . Windows . Powershell . ScriptAnalyzer . Generic ;
18
+ using System . ComponentModel . Composition ;
19
+ using System . Globalization ;
20
+ using System . IO ;
21
+ using System . Management . Automation ;
22
+
23
+ namespace Microsoft . Windows . Powershell . ScriptAnalyzer . BuiltinRules
24
+ {
25
+ /// <summary>
26
+ /// DscExamplesPresent: Checks that DSC examples for given resource are present.
27
+ /// Rule expects directory Examples to be present:
28
+ /// For non-class based resources it should exist at the same folder level as DSCResources folder.
29
+ /// For class based resources it should be present at the same folder level as resource psm1 file.
30
+ /// Examples folder should contain sample configuration for given resource - file name should contain resource's name.
31
+ /// </summary>
32
+ [ Export ( typeof ( IDSCResourceRule ) ) ]
33
+ public class DscExamplesPresent : IDSCResourceRule
34
+ {
35
+ /// <summary>
36
+ /// AnalyzeDSCResource: Analyzes given DSC Resource
37
+ /// </summary>
38
+ /// <param name="ast">The script's ast</param>
39
+ /// <param name="fileName">The name of the script file being analyzed</param>
40
+ /// <returns>The results of the analysis</returns>
41
+ public IEnumerable < DiagnosticRecord > AnalyzeDSCResource ( Ast ast , string fileName )
42
+ {
43
+ String fileNameOnly = Path . GetFileName ( fileName ) ;
44
+ String resourceName = Path . GetFileNameWithoutExtension ( fileNameOnly ) ;
45
+ String examplesQuery = String . Format ( "*{0}*" , resourceName ) ;
46
+ Boolean examplesPresent = false ;
47
+ String expectedExamplesPath = Path . Combine ( new String [ ] { fileName , ".." , ".." , ".." , "Examples" } ) ;
48
+
49
+ // Verify examples are present
50
+ if ( Directory . Exists ( expectedExamplesPath ) )
51
+ {
52
+ DirectoryInfo examplesFolder = new DirectoryInfo ( expectedExamplesPath ) ;
53
+ FileInfo [ ] exampleFiles = examplesFolder . GetFiles ( examplesQuery ) ;
54
+ if ( exampleFiles . Length != 0 )
55
+ {
56
+ examplesPresent = true ;
57
+ }
58
+ }
59
+
60
+ // Return error if no examples present
61
+ if ( ! examplesPresent )
62
+ {
63
+ yield return new DiagnosticRecord ( string . Format ( CultureInfo . CurrentCulture , Strings . DscExamplesPresentNoExamplesError , resourceName ) ,
64
+ ast . Extent , GetName ( ) , DiagnosticSeverity . Information , fileName ) ;
65
+ }
66
+ }
67
+
68
+ /// <summary>
69
+ /// AnalyzeDSCClass: Analyzes given DSC class
70
+ /// </summary>
71
+ /// <param name="ast"></param>
72
+ /// <param name="fileName"></param>
73
+ /// <returns></returns>
74
+ public IEnumerable < DiagnosticRecord > AnalyzeDSCClass ( Ast ast , string fileName )
75
+ {
76
+ String resourceName = null ;
77
+
78
+ IEnumerable < Ast > dscClasses = ast . FindAll ( item =>
79
+ item is TypeDefinitionAst
80
+ && ( ( item as TypeDefinitionAst ) . IsClass )
81
+ && ( item as TypeDefinitionAst ) . Attributes . Any ( attr => String . Equals ( "DSCResource" , attr . TypeName . FullName , StringComparison . OrdinalIgnoreCase ) ) , true ) ;
82
+
83
+ foreach ( TypeDefinitionAst dscClass in dscClasses )
84
+ {
85
+ resourceName = dscClass . Name ;
86
+
87
+ String examplesQuery = String . Format ( "*{0}*" , resourceName ) ;
88
+ Boolean examplesPresent = false ;
89
+ String expectedExamplesPath = Path . Combine ( new String [ ] { fileName , ".." , "Examples" } ) ;
90
+
91
+ // Verify examples are present
92
+ if ( Directory . Exists ( expectedExamplesPath ) )
93
+ {
94
+ DirectoryInfo examplesFolder = new DirectoryInfo ( expectedExamplesPath ) ;
95
+ FileInfo [ ] exampleFiles = examplesFolder . GetFiles ( examplesQuery ) ;
96
+ if ( exampleFiles . Length != 0 )
97
+ {
98
+ examplesPresent = true ;
99
+ }
100
+ }
101
+
102
+ // Return error if no examples present
103
+ if ( ! examplesPresent )
104
+ {
105
+ yield return new DiagnosticRecord ( string . Format ( CultureInfo . CurrentCulture , Strings . DscExamplesPresentNoExamplesError , resourceName ) ,
106
+ dscClass . Extent , GetName ( ) , DiagnosticSeverity . Information , fileName ) ;
107
+ }
108
+ }
109
+ }
110
+
111
+ /// <summary>
112
+ /// GetName: Retrieves the name of this rule.
113
+ /// </summary>
114
+ /// <returns>The name of this rule</returns>
115
+ public string GetName ( )
116
+ {
117
+ return string . Format ( CultureInfo . CurrentCulture , Strings . NameSpaceFormat , GetSourceName ( ) , Strings . DscExamplesPresent ) ;
118
+ }
119
+
120
+ /// <summary>
121
+ /// GetCommonName: Retrieves the Common name of this rule.
122
+ /// </summary>
123
+ /// <returns>The common name of this rule</returns>
124
+ public string GetCommonName ( )
125
+ {
126
+ return string . Format ( CultureInfo . CurrentCulture , Strings . DscExamplesPresentCommonName ) ;
127
+ }
128
+
129
+ /// <summary>
130
+ /// GetDescription: Retrieves the description of this rule.
131
+ /// </summary>
132
+ /// <returns>The description of this rule</returns>
133
+ public string GetDescription ( )
134
+ {
135
+ return string . Format ( CultureInfo . CurrentCulture , Strings . DscExamplesPresentDescription ) ;
136
+ }
137
+
138
+ /// <summary>
139
+ /// GetSourceType: Retrieves the type of the rule: builtin, managed or module.
140
+ /// </summary>
141
+ public SourceType GetSourceType ( )
142
+ {
143
+ return SourceType . Builtin ;
144
+ }
145
+
146
+ /// <summary>
147
+ /// GetSeverity: Retrieves the severity of the rule: error, warning or information.
148
+ /// </summary>
149
+ /// <returns></returns>
150
+ public RuleSeverity GetSeverity ( )
151
+ {
152
+ return RuleSeverity . Information ;
153
+ }
154
+
155
+ /// <summary>
156
+ /// GetSourceName: Retrieves the module/assembly name the rule is from.
157
+ /// </summary>
158
+ public string GetSourceName ( )
159
+ {
160
+ return string . Format ( CultureInfo . CurrentCulture , Strings . DSCSourceName ) ;
161
+ }
162
+ }
163
+
164
+ }
0 commit comments