3
3
4
4
Describe ' WindowsPowerShell adapter resource tests - requires elevated permissions' {
5
5
6
- BeforeAll {
7
- if ($isWindows ) {
8
- winrm quickconfig - quiet - force
9
- }
10
- $OldPSModulePath = $env: PSModulePath
11
- $env: PSModulePath += [System.IO.Path ]::PathSeparator + $PSScriptRoot
12
-
13
- $winpsConfigPath = Join-path $PSScriptRoot " winps_resource.dsc.yaml"
14
- if ($isWindows ) {
15
- $cacheFilePath_v5 = Join-Path $env: LocalAppData " dsc" " WindowsPSAdapterCache.json"
16
- }
17
- }
18
- AfterAll {
19
- $env: PSModulePath = $OldPSModulePath
6
+ BeforeAll {
7
+ if ($isWindows ) {
8
+ winrm quickconfig - quiet - force
20
9
}
10
+ $OldPSModulePath = $env: PSModulePath
11
+ $env: PSModulePath += [System.IO.Path ]::PathSeparator + $PSScriptRoot
21
12
22
- BeforeEach {
23
- if ($isWindows ) {
24
- Remove-Item - Force - ea SilentlyContinue - Path $cacheFilePath_v5
25
- }
13
+ $winpsConfigPath = Join-path $PSScriptRoot " winps_resource.dsc.yaml"
14
+ if ($isWindows ) {
15
+ $cacheFilePath_v5 = Join-Path $env: LocalAppData " dsc" " WindowsPSAdapterCache.json"
26
16
}
17
+ }
18
+ AfterAll {
19
+ $env: PSModulePath = $OldPSModulePath
27
20
28
- It ' Windows PowerShell adapter supports File resource' - Skip:(! $IsWindows ){
21
+ # Remove after all the tests are done
22
+ Remove-Module $script :winPSModule - Force - ErrorAction Ignore
23
+ }
29
24
30
- $r = dsc resource list -- adapter Microsoft.Windows/ WindowsPowerShell
31
- $LASTEXITCODE | Should - Be 0
32
- $resources = $r | ConvertFrom-Json
33
- ($resources | Where-Object {$_.Type -eq ' PSDesiredStateConfiguration/File' }).Count | Should - Be 1
25
+ BeforeEach {
26
+ if ($isWindows ) {
27
+ Remove-Item - Force - ea SilentlyContinue - Path $cacheFilePath_v5
34
28
}
29
+ }
35
30
36
- It ' Get works on Binary " File" resource' - Skip:(! $IsWindows ){
31
+ It ' Windows PowerShell adapter supports File resource' - Skip:(! $IsWindows ) {
37
32
38
- $testFile = " $testdrive \test.txt"
39
- ' test' | Set-Content - Path $testFile - Force
40
- $r = ' {"DestinationPath":"' + $testFile.replace (' \' , ' \\' ) + ' "}' | dsc resource get - r ' PSDesiredStateConfiguration/File' -f -
41
- $LASTEXITCODE | Should - Be 0
42
- $res = $r | ConvertFrom-Json
43
- $res.actualState.DestinationPath | Should - Be " $testFile "
44
- }
33
+ $r = dsc resource list -- adapter Microsoft.Windows/ WindowsPowerShell
34
+ $LASTEXITCODE | Should - Be 0
35
+ $resources = $r | ConvertFrom-Json
36
+ ($resources | Where-Object { $_.Type -eq ' PSDesiredStateConfiguration/File' }).Count | Should - Be 1
37
+ }
45
38
46
- It ' Set works on Binary "File" resource' - Skip:(! $IsWindows ){
39
+ It ' Get works on Binary "File" resource' - Skip:(! $IsWindows ) {
47
40
48
- $testFile = " $testdrive \test.txt"
49
- $null = ' {"DestinationPath":"' + $testFile.replace (' \' , ' \\' ) + ' ", type: File, contents: HelloWorld, Ensure: present}' | dsc resource set - r ' PSDesiredStateConfiguration/File' -f -
50
- $LASTEXITCODE | Should - Be 0
51
- Get-Content - Raw - Path $testFile | Should - Be " HelloWorld"
52
- }
41
+ $testFile = " $testdrive \test.txt"
42
+ ' test' | Set-Content - Path $testFile - Force
43
+ $r = ' {"DestinationPath":"' + $testFile.replace (' \' , ' \\' ) + ' "}' | dsc resource get - r ' PSDesiredStateConfiguration/File' -f -
44
+ $LASTEXITCODE | Should - Be 0
45
+ $res = $r | ConvertFrom-Json
46
+ $res.actualState.DestinationPath | Should - Be " $testFile "
47
+ }
53
48
54
- It ' Get works on traditional "Script " resource' - Skip:(! $IsWindows ){
49
+ It ' Set works on Binary "File " resource' - Skip:(! $IsWindows ) {
55
50
56
- $testFile = " $testdrive \test.txt"
57
- ' test' | Set-Content - Path $testFile - Force
58
- $r = ' {"GetScript": "@{result = $(Get-Content ' + $testFile.replace (' \' , ' \\' ) + ' )}", "SetScript": "throw", "TestScript": "throw"}' | dsc resource get - r ' PSDesiredStateConfiguration/Script' -f -
59
- $LASTEXITCODE | Should - Be 0
60
- $res = $r | ConvertFrom-Json
61
- $res.actualState.result | Should - Be ' test'
62
- }
51
+ $testFile = " $testdrive \test.txt"
52
+ $null = ' {"DestinationPath":"' + $testFile.replace (' \' , ' \\' ) + ' ", type: File, contents: HelloWorld, Ensure: present}' | dsc resource set - r ' PSDesiredStateConfiguration/File' -f -
53
+ $LASTEXITCODE | Should - Be 0
54
+ Get-Content - Raw - Path $testFile | Should - Be " HelloWorld"
55
+ }
63
56
64
- It ' Get works on config with File resource for WinPS ' - Skip:(! $IsWindows ){
57
+ It ' Get works on traditional "Script" resource' - Skip:(! $IsWindows ) {
65
58
66
- $testFile = " $testdrive \test.txt"
67
- ' test' | Set-Content - Path $testFile - Force
68
- $r = (Get-Content - Raw $winpsConfigPath ).Replace( ' c:\test.txt ' , " $testFile " ) | dsc config get -f -
69
- $LASTEXITCODE | Should - Be 0
70
- $res = $r | ConvertFrom-Json
71
- $res.results [ 0 ].result. actualState.result[ 0 ].properties.DestinationPath | Should - Be " $testFile "
72
- }
59
+ $testFile = " $testdrive \test.txt"
60
+ ' test' | Set-Content - Path $testFile - Force
61
+ $r = ' {"GetScript": "@{result = $ (Get-Content ' + $testFile .replace ( ' \ ' , ' \\ ' ) + ' )}", "SetScript": "throw", "TestScript": "throw"} ' | dsc resource get - r ' PSDesiredStateConfiguration/Script ' -f -
62
+ $LASTEXITCODE | Should - Be 0
63
+ $res = $r | ConvertFrom-Json
64
+ $res.actualState.result | Should - Be ' test '
65
+ }
73
66
74
- It ' Verify that there are no cache rebuilds for several sequential executions' - Skip:(! $IsWindows ) {
75
- # remove cache file
76
- $cacheFilePath = Join-Path $env: LocalAppData " dsc\WindowsPSAdapterCache.json"
77
- Remove-Item - Force - Path $cacheFilePath - ErrorAction Ignore
67
+ It ' Get works on config with File resource for WinPS' - Skip:(! $IsWindows ) {
78
68
79
- # first execution should build the cache
80
- dsc - l trace resource list - a Microsoft.Windows/ WindowsPowerShell 2> $TestDrive / tracing.txt
81
- " $TestDrive /tracing.txt" | Should - FileContentMatchExactly ' Constructing Get-DscResource cache'
69
+ $testFile = " $testdrive \test.txt"
70
+ ' test' | Set-Content - Path $testFile - Force
71
+ $r = (Get-Content - Raw $winpsConfigPath ).Replace(' c:\test.txt' , " $testFile " ) | dsc config get -f -
72
+ $LASTEXITCODE | Should - Be 0
73
+ $res = $r | ConvertFrom-Json
74
+ $res.results [0 ].result.actualState.result[0 ].properties.DestinationPath | Should - Be " $testFile "
75
+ }
82
76
83
- # next executions following shortly after should Not rebuild the cache
84
- 1 .. 3 | ForEach-Object {
85
- dsc - l trace resource list - a Microsoft.Windows/ WindowsPowerShell 2> $TestDrive / tracing.txt
86
- " $TestDrive /tracing.txt" | Should -Not - FileContentMatchExactly ' Constructing Get-DscResource cache'
87
- }
77
+ It ' Verify that there are no cache rebuilds for several sequential executions' - Skip:(! $IsWindows ) {
78
+ # remove cache file
79
+ $cacheFilePath = Join-Path $env: LocalAppData " dsc\WindowsPSAdapterCache.json"
80
+ Remove-Item - Force - Path $cacheFilePath - ErrorAction Ignore
81
+
82
+ # first execution should build the cache
83
+ dsc - l trace resource list - a Microsoft.Windows/ WindowsPowerShell 2> $TestDrive / tracing.txt
84
+ " $TestDrive /tracing.txt" | Should - FileContentMatchExactly ' Constructing Get-DscResource cache'
85
+
86
+ # next executions following shortly after should Not rebuild the cache
87
+ 1 .. 3 | ForEach-Object {
88
+ dsc - l trace resource list - a Microsoft.Windows/ WindowsPowerShell 2> $TestDrive / tracing.txt
89
+ " $TestDrive /tracing.txt" | Should -Not - FileContentMatchExactly ' Constructing Get-DscResource cache'
88
90
}
91
+ }
89
92
90
- It ' Verify if assertion is used that no module is cleared in the cache' - Skip:(! $IsWindows ) {
91
- # create a test file in the test drive
92
- $testFile = " $testdrive \test.txt"
93
- New-Item - Path $testFile - ItemType File - Force | Out-Null
93
+ It ' Verify if assertion is used that no module is cleared in the cache' - Skip:(! $IsWindows ) {
94
+ # create a test file in the test drive
95
+ $testFile = " $testdrive \test.txt"
96
+ New-Item - Path $testFile - ItemType File - Force | Out-Null
94
97
95
- # remove cache file
96
- $cacheFilePath = Join-Path $env: LocalAppData " dsc\WindowsPSAdapterCache.json"
97
- Remove-Item - Force - Path $cacheFilePath - ErrorAction Ignore
98
+ # remove cache file
99
+ $cacheFilePath = Join-Path $env: LocalAppData " dsc\WindowsPSAdapterCache.json"
100
+ Remove-Item - Force - Path $cacheFilePath - ErrorAction Ignore
98
101
99
- # build the cache
100
- dsc resource list -- adapter Microsoft.Windows/ WindowsPowerShell | Out-Null
102
+ # build the cache
103
+ dsc resource list -- adapter Microsoft.Windows/ WindowsPowerShell | Out-Null
101
104
102
- # Create a test module in the test drive
103
- $testModuleDir = " $testdrive \TestModule\1.0.0"
104
- New-Item - Path $testModuleDir - ItemType Directory - Force | Out-Null
105
+ # Create a test module in the test drive
106
+ $testModuleDir = " $testdrive \TestModule\1.0.0"
107
+ New-Item - Path $testModuleDir - ItemType Directory - Force | Out-Null
105
108
106
- $manifestContent = @"
109
+ $manifestContent = @"
107
110
@{
108
111
RootModule = 'TestModule.psm1'
109
112
ModuleVersion = '1.0.0'
@@ -120,17 +123,17 @@ Describe 'WindowsPowerShell adapter resource tests - requires elevated permissio
120
123
AliasesToExport = @()
121
124
}
122
125
"@
123
- Set-Content - Path " $testModuleDir \TestModule.psd1" - Value $manifestContent
126
+ Set-Content - Path " $testModuleDir \TestModule.psd1" - Value $manifestContent
124
127
125
- $scriptContent = @"
128
+ $scriptContent = @"
126
129
Write-Host 'The DSC world!'
127
130
"@
128
- Set-Content - Path " $testModuleDir \TestModule.psm1" - Value $scriptContent
131
+ Set-Content - Path " $testModuleDir \TestModule.psm1" - Value $scriptContent
129
132
130
- # Add the test module directory to PSModulePath
131
- $env: PSModulePath += [System.IO.Path ]::PathSeparator + $testdrive
133
+ # Add the test module directory to PSModulePath
134
+ $env: PSModulePath += [System.IO.Path ]::PathSeparator + $testdrive
132
135
133
- $yaml = @"
136
+ $yaml = @"
134
137
`$ schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
135
138
resources:
136
139
- name: File
@@ -164,25 +167,25 @@ resources:
164
167
- "[resourceId('Microsoft.Windows/WindowsPowerShell', 'File')]"
165
168
- "[resourceId('Microsoft.DSC/Assertion', 'File present')]"
166
169
"@
167
- # output to file for Windows PowerShell 5.1
168
- $filePath = " $testdrive \test.assertion.dsc.resource.yaml"
169
- $yaml | Set-Content - Path $filePath - Force
170
- dsc config test -f $filePath 2> " $TestDrive /error.txt"
171
- $LASTEXITCODE | Should - Be 2
172
-
173
- $cache = Get-Content - Path $cacheFilePath - Raw | ConvertFrom-Json
174
- $cache.ResourceCache.Type | Should - Contain ' PSTestModule/TestPSRepository'
175
- $cache.ResourceCache.Type | Should - Contain ' PSDesiredStateConfiguration/File'
176
- }
170
+ # output to file for Windows PowerShell 5.1
171
+ $filePath = " $testdrive \test.assertion.dsc.resource.yaml"
172
+ $yaml | Set-Content - Path $filePath - Force
173
+ dsc config test -f $filePath 2> " $TestDrive /error.txt"
174
+ $LASTEXITCODE | Should - Be 2
175
+
176
+ $cache = Get-Content - Path $cacheFilePath - Raw | ConvertFrom-Json
177
+ $cache.ResourceCache.Type | Should - Contain ' PSTestModule/TestPSRepository'
178
+ $cache.ResourceCache.Type | Should - Contain ' PSDesiredStateConfiguration/File'
179
+ }
177
180
178
- It ' _inDesiredState is returned correction: <Context>' - Skip:(! $IsWindows ) - TestCases @ (
179
- @ { Context = ' Both running' ; FirstState = ' Running' ; SecondState = ' Running' }
180
- @ { Context = ' Both stopped' ; FirstState = ' Stopped' ; SecondState = ' Stopped' }
181
- @ { Context = ' First Stopped' ; FirstState = ' Stopped' ; SecondState = ' Running' }
182
- @ { Context = ' First Running' ; FirstState = ' Running' ; SecondState = ' Stopped' }
183
- ) {
184
- param ($Context , $FirstState , $SecondState )
185
- $yaml = @"
181
+ It ' _inDesiredState is returned correction: <Context>' - Skip:(! $IsWindows ) - TestCases @ (
182
+ @ { Context = ' Both running' ; FirstState = ' Running' ; SecondState = ' Running' }
183
+ @ { Context = ' Both stopped' ; FirstState = ' Stopped' ; SecondState = ' Stopped' }
184
+ @ { Context = ' First Stopped' ; FirstState = ' Stopped' ; SecondState = ' Running' }
185
+ @ { Context = ' First Running' ; FirstState = ' Running' ; SecondState = ' Stopped' }
186
+ ) {
187
+ param ($Context , $FirstState , $SecondState )
188
+ $yaml = @"
186
189
`$ schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
187
190
resources:
188
191
- name: Use Windows PowerShell resources
@@ -201,14 +204,68 @@ resources:
201
204
State: $SecondState
202
205
"@
203
206
204
- $inDesiredState = if ($FirstState -eq $SecondState ) {
205
- $FirstState -eq (Get-Service Spooler).Status
206
- } else {
207
- $false
208
- }
207
+ $inDesiredState = if ($FirstState -eq $SecondState ) {
208
+ $FirstState -eq (Get-Service Spooler).Status
209
+ }
210
+ else {
211
+ $false
212
+ }
213
+
214
+ $out = dsc config test - i $yaml | ConvertFrom-Json
215
+ $LASTEXITCODE | Should - Be 0
216
+ $out.results [0 ].result.inDesiredState | Should - Be $inDesiredState
217
+ }
209
218
210
- $out = dsc config test - i $yaml | ConvertFrom-Json
211
- $LASTEXITCODE | Should - Be 0
212
- $out.results [0 ].result.inDesiredState | Should - Be $inDesiredState
219
+ It ' Config works with credential object' - Skip:(! $IsWindows ) {
220
+ BeforeDiscovery {
221
+ $script :winPSModule = Resolve-Path - Path (Join-Path $PSScriptRoot ' ..' ' psDscAdapter' ' win_psDscAdapter.psm1' ) | Select-Object - ExpandProperty Path
222
+ Import-Module $winPSModule - Force - ErrorAction Stop
223
+
224
+ # Mock the command to work on GitHub runners because Microsoft.PowerShell.Security is not available
225
+ Mock - CommandName ConvertTo-SecureString - MockWith { [System.Security.SecureString ]::new() }
213
226
}
227
+
228
+ $jsonInput = @ {
229
+ resources = @ {
230
+ name = ' Service info'
231
+ type = ' PSDesiredStateConfiguration/Service'
232
+ properties = @ {
233
+ Name = ' Spooler'
234
+ Credential = @ {
235
+ UserName = ' User'
236
+ Password = ' Password'
237
+ }
238
+ }
239
+ }
240
+ } | ConvertTo-Json - Depth 10
241
+
242
+ # Instead of calling dsc.exe we call the cmdlet directly to be able to test the output and mocks
243
+ $resourceObject = Get-DscResourceObject - jsonInput $jsonInput
244
+ $cacheEntry = Invoke-DscCacheRefresh - Module PSDesiredStateConfiguration
245
+
246
+ $out = Invoke-DscOperation - Operation Test - DesiredState $resourceObject - dscResourceCache $cacheEntry
247
+ $LASTEXITCODE | Should - Be 0
248
+ $out.properties.InDesiredState.InDesiredState | Should - Be $false
249
+
250
+ Should - Invoke - CommandName ConvertTo-SecureString - Exactly - Times 1 - Scope It
251
+ }
252
+
253
+ It ' Config does not work when credential properties are missing required fields' - Skip:(! $IsWindows ) {
254
+ $yaml = @"
255
+ `$ schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
256
+ resources:
257
+ - name: Service info
258
+ type: PsDesiredStateConfiguration/Service
259
+ properties:
260
+ Name: Spooler
261
+ Credential:
262
+ UserName: 'User'
263
+ OtherProperty: 'Password'
264
+ "@
265
+ # Compared to PowerShell we use test here as it filters out the properties
266
+ $out = dsc config test - i $yaml 2>&1 | Out-String
267
+ $LASTEXITCODE | Should - Be 2
268
+ $out | Should -Not - BeNullOrEmpty
269
+ $out | Should - BeLike " *ERROR*Credential object 'Credential' requires both 'username' and 'password' properties*"
270
+ }
214
271
}
0 commit comments