33
44Describe ' WindowsPowerShell adapter resource tests - requires elevated permissions' {
55
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
209 }
10+ $OldPSModulePath = $env: PSModulePath
11+ $env: PSModulePath += [System.IO.Path ]::PathSeparator + $PSScriptRoot
2112
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"
2616 }
17+ }
18+ AfterAll {
19+ $env: PSModulePath = $OldPSModulePath
2720
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+ }
2924
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
3428 }
29+ }
3530
36- It ' Get works on Binary " File" resource' - Skip:(! $IsWindows ){
31+ It ' Windows PowerShell adapter supports File resource' - Skip:(! $IsWindows ) {
3732
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+ }
4538
46- It ' Set works on Binary "File" resource' - Skip:(! $IsWindows ){
39+ It ' Get works on Binary "File" resource' - Skip:(! $IsWindows ) {
4740
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+ }
5348
54- It ' Get works on traditional "Script " resource' - Skip:(! $IsWindows ){
49+ It ' Set works on Binary "File " resource' - Skip:(! $IsWindows ) {
5550
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+ }
6356
64- It ' Get works on config with File resource for WinPS ' - Skip:(! $IsWindows ){
57+ It ' Get works on traditional "Script" resource' - Skip:(! $IsWindows ) {
6558
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+ }
7366
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 ) {
7868
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+ }
8276
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'
8890 }
91+ }
8992
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
9497
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
98101
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
101104
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
105108
106- $manifestContent = @"
109+ $manifestContent = @"
107110 @{
108111 RootModule = 'TestModule.psm1'
109112 ModuleVersion = '1.0.0'
@@ -120,17 +123,17 @@ Describe 'WindowsPowerShell adapter resource tests - requires elevated permissio
120123 AliasesToExport = @()
121124 }
122125"@
123- Set-Content - Path " $testModuleDir \TestModule.psd1" - Value $manifestContent
126+ Set-Content - Path " $testModuleDir \TestModule.psd1" - Value $manifestContent
124127
125- $scriptContent = @"
128+ $scriptContent = @"
126129Write-Host 'The DSC world!'
127130"@
128- Set-Content - Path " $testModuleDir \TestModule.psm1" - Value $scriptContent
131+ Set-Content - Path " $testModuleDir \TestModule.psm1" - Value $scriptContent
129132
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
132135
133- $yaml = @"
136+ $yaml = @"
134137`$ schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
135138resources:
136139 - name: File
@@ -164,25 +167,25 @@ resources:
164167 - "[resourceId('Microsoft.Windows/WindowsPowerShell', 'File')]"
165168 - "[resourceId('Microsoft.DSC/Assertion', 'File present')]"
166169"@
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+ }
177180
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 = @"
186189`$ schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
187190resources:
188191 - name: Use Windows PowerShell resources
@@ -201,14 +204,68 @@ resources:
201204 State: $SecondState
202205"@
203206
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+ }
209218
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() }
213226 }
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+ }
214271}
0 commit comments