Skip to content

Commit 6fa58ce

Browse files
author
Steve Lee (POWERSHELL HE/HIM) (from Dev Box)
committed
Fixes and tests
1 parent 5435e59 commit 6fa58ce

File tree

6 files changed

+274
-74
lines changed

6 files changed

+274
-74
lines changed

build.ps1

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ $filesForWindowsPackage = @(
5353
'osinfo.dsc.resource.json',
5454
'powershell.dsc.resource.json',
5555
'psDscAdapter/',
56+
'psscript.ps1',
57+
'psscript.dsc.resource.json',
58+
'winpsscript.dsc.resource.json',
5659
'reboot_pending.dsc.resource.json',
5760
'reboot_pending.resource.ps1',
5861
'registry.dsc.resource.json',
@@ -87,6 +90,8 @@ $filesForLinuxPackage = @(
8790
'osinfo.dsc.resource.json',
8891
'powershell.dsc.resource.json',
8992
'psDscAdapter/',
93+
'psscript.ps1',
94+
'psscript.dsc.resource.json',
9095
'RunCommandOnSet.dsc.resource.json',
9196
'runcommandonset',
9297
'sshdconfig',
@@ -109,6 +114,8 @@ $filesForMacPackage = @(
109114
'osinfo.dsc.resource.json',
110115
'powershell.dsc.resource.json',
111116
'psDscAdapter/',
117+
'psscript.ps1',
118+
'psscript.dsc.resource.json',
112119
'RunCommandOnSet.dsc.resource.json',
113120
'runcommandonset',
114121
'sshdconfig',
@@ -300,6 +307,7 @@ if (!$SkipBuild) {
300307
"dscecho",
301308
"osinfo",
302309
"powershell-adapter",
310+
'resources/psscript',
303311
"process",
304312
"runcommandonset",
305313
"sshdconfig",

resources/PSScript/copy_files.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
./psscript.ps1

resources/PSScript/psscript.dsc.resource.json

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
3-
"type": "Microsoft.DSC.Transitional/PowerShell7Script",
4-
"description": "Enable running PS7 scripts inline",
3+
"type": "Microsoft.DSC.Transitional/PowerShellScript",
4+
"description": "Enable running PowerShell 7 scripts inline",
55
"version": "0.1.0",
66
"get": {
77
"executable": "pwsh",
@@ -12,9 +12,10 @@
1212
"-ExecutionPolicy",
1313
"Bypass",
1414
"-Command",
15-
"-Command",
16-
"$Input | ./psscript.ps1 get"
17-
]
15+
"$input | ./psscript.ps1",
16+
"get"
17+
],
18+
"input": "stdin"
1819
},
1920
"set": {
2021
"executable": "pwsh",
@@ -25,9 +26,12 @@
2526
"-ExecutionPolicy",
2627
"Bypass",
2728
"-Command",
28-
"-Command",
29-
"$Input | ./psscript.ps1 set"
30-
]
29+
"$input | ./psscript.ps1",
30+
"set"
31+
],
32+
"implementsPretest": true,
33+
"input": "stdin",
34+
"return": "state"
3135
},
3236
"test": {
3337
"executable": "pwsh",
@@ -38,43 +42,36 @@
3842
"-ExecutionPolicy",
3943
"Bypass",
4044
"-Command",
41-
"$Input | ./psscript.ps1 test"
42-
]
43-
},
44-
"export": {
45-
"executable": "pwsh",
46-
"args": [
47-
"-NoLogo",
48-
"-NonInteractive",
49-
"-NoProfile",
50-
"-ExecutionPolicy",
51-
"Bypass",
52-
"-Command",
53-
"$Input | ./psscript.ps1 export"
54-
]
45+
"$input | ./psscript.ps1",
46+
"test"
47+
],
48+
"input": "stdin",
49+
"return": "state"
5550
},
5651
"exitCodes": {
5752
"0": "Success",
58-
"1": "PowerShell script execution failed"
53+
"1": "PowerShell script execution failed",
54+
"2": "PowerShell exception occurred"
5955
},
6056
"schema": {
6157
"embedded": {
6258
"type": "object",
6359
"properties": {
6460
"getScript": {
65-
"type": ["string", null]
61+
"type": ["string", "null"]
6662
},
6763
"setScript": {
68-
"type": ["string", null]
64+
"type": ["string", "null"]
6965
},
7066
"testScript": {
71-
"type": ["string", null]
72-
},
73-
"exportScript": {
74-
"type": ["string", null]
67+
"type": ["string", "null"]
7568
},
7669
"output": {
77-
"type": ["object", null]
70+
"type": ["object", "null"]
71+
},
72+
"_inDesiredState": {
73+
"type": ["boolean", "null"],
74+
"default": null
7875
}
7976
}
8077
}

resources/PSScript/psscript.ps1

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
[CmdletBinding()]
44
param(
55
[Parameter(Mandatory = $true, Position = 0)]
6-
[ValidateSet('Get', 'Set', 'Test', 'Export')]
6+
[ValidateSet('Get', 'Set', 'Test')]
77
[string]$Operation,
8-
[Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $true)]
9-
[string]$jsonInput = '@{}'
8+
[Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true)]
9+
[string]$jsonInput
1010
)
1111

1212
$traceQueue = [System.Collections.Queue]::new()
@@ -17,11 +17,17 @@ function Write-DscTrace {
1717
[ValidateSet('Error', 'Warn', 'Info', 'Debug', 'Trace')]
1818
[string]$Level,
1919
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
20-
[string]$Message
20+
[string]$Message,
21+
[switch]$Now
2122
)
2223

2324
$trace = @{$Level.ToLower() = $Message } | ConvertTo-Json -Compress
24-
$traceQueue.Enqueue($trace)
25+
26+
if ($Now) {
27+
$host.ui.WriteErrorLine($trace)
28+
} else {
29+
$traceQueue.Enqueue($trace)
30+
}
2531
}
2632

2733
$scriptObject = $jsonInput | ConvertFrom-Json
@@ -36,13 +42,18 @@ $script = switch ($Operation) {
3642
'Test' {
3743
$scriptObject.TestScript
3844
}
39-
'Export' {
40-
$scriptObject.ExportScript
41-
}
4245
}
4346

4447
if ($null -eq $script) {
45-
Write-DscTrace -Level Info -Message "No script found for operation '$Operation'."
48+
Write-DscTrace -Now -Level Info -Message "No script found for operation '$Operation'."
49+
if ($Operation -eq 'Test') {
50+
# if not implemented, we return it's in desired state
51+
@{ _inDesiredState = $true } | ConvertTo-Json -Compress
52+
exit 0
53+
}
54+
55+
# write an empty json object to stdout
56+
'{}'
4657
exit 0
4758
}
4859

@@ -105,6 +116,14 @@ While ($traceQueue.Count -gt 0) {
105116
$host.ui.WriteErrorLine($trace)
106117
}
107118

108-
@{
109-
output = $outputObjects
110-
} | ConvertTo-Json -Compress -Depth 10
119+
# Test should return a single boolean value indicating if in the desired state
120+
if ($Operation -eq 'Test') {
121+
if ($outputObjects.Count -eq 1 -and $outputObjects[0] -is [bool]) {
122+
@{ _inDesiredState = $outputObjects[0] } | ConvertTo-Json -Compress
123+
} else {
124+
Write-DscTrace -Now -Level Error -Message 'Test operation did not return a single boolean value.'
125+
exit 1
126+
}
127+
} else {
128+
@{ output = $outputObjects } | ConvertTo-Json -Compress -Depth 10
129+
}

resources/PSScript/psscript.tests.ps1

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
BeforeDiscovery {
5+
$testCases = if ($IsWindows) {
6+
@(
7+
@{
8+
resourceType = 'Microsoft.DSC.Transitional/PowerShellScript'
9+
}
10+
@{
11+
resourceType = 'Microsoft.DSC.Transitional/WindowsPowerShellScript'
12+
}
13+
)
14+
} else {
15+
@(
16+
@{
17+
resourceType = 'Microsoft.DSC.Transitional/PowerShellScript'
18+
}
19+
)
20+
}
21+
}
22+
23+
Describe 'Tests for PSScript resource' {
24+
It 'Get operation returns the script content for <resourceType>' -TestCases $testCases {
25+
param($resourceType)
26+
27+
$yaml = @"
28+
GetScript: |
29+
"Hello, World!"
30+
1+1
31+
SetScript: |
32+
throw 'This should not be executed'
33+
"@
34+
$result = dsc resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
35+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String)
36+
$result.actualState.output.Count | Should -Be 2 -Because ($result | ConvertTo-Json | Out-String)
37+
$result.actualState.output[0] | Should -BeExactly "Hello, World!"
38+
$result.actualState.output[1] | Should -BeExactly 2
39+
}
40+
41+
It 'Set operation executes the script for <resourceType>' -TestCases $testCases {
42+
param($resourceType)
43+
44+
$yaml = @"
45+
SetScript: |
46+
"Hello, World!"
47+
1+1
48+
"@
49+
$result = dsc resource set -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
50+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String)
51+
$result.afterState.output.Count | Should -Be 2 -Because ($result | ConvertTo-Json | Out-String)
52+
$result.afterState.output[0] | Should -BeExactly "Hello, World!"
53+
$result.afterState.output[1] | Should -BeExactly 2
54+
}
55+
56+
It 'Get w/ Set operation succeeds for <resourceType>' -TestCases $testCases {
57+
param($resourceType)
58+
59+
$yaml = @"
60+
GetScript: |
61+
"Hello, World!"
62+
1+1
63+
SetScript: |
64+
"Hello, World!"
65+
2+2
66+
"@
67+
$result = dsc resource set -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
68+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String)
69+
$result.beforeState.output.Count | Should -Be 2 -Because ($result | ConvertTo-Json | Out-String)
70+
$result.beforeState.output[0] | Should -BeExactly "Hello, World!"
71+
$result.beforeState.output[1] | Should -BeExactly 2
72+
$result.afterState.output.Count | Should -Be 2
73+
$result.afterState.output[0] | Should -BeExactly "Hello, World!"
74+
$result.afterState.output[1] | Should -BeExactly 4
75+
}
76+
77+
It 'Test operation returns in desired state for <resourceType>' -TestCases $testCases {
78+
param($resourceType)
79+
80+
$yaml = @'
81+
TestScript: |
82+
$true
83+
'@
84+
$result = dsc resource test -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
85+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String)
86+
$result.InDesiredState | Should -BeTrue
87+
}
88+
89+
It 'Test operation returns not in desired state for <resourceType>' -TestCases $testCases {
90+
param($resourceType)
91+
92+
$yaml = @'
93+
TestScript: |
94+
$false
95+
'@
96+
$result = dsc resource test -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
97+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String)
98+
$result.InDesiredState | Should -BeFalse
99+
}
100+
101+
It 'Test operation returns error for non-boolean result for <resourceType>' -TestCases $testCases {
102+
param($resourceType)
103+
104+
$yaml = @'
105+
TestScript: |
106+
"This is not a boolean"
107+
'@
108+
$result = dsc resource test -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
109+
$LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String)
110+
$result | Should -BeNullOrEmpty -Because "Test operation should return an error"
111+
(Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*Test operation did not return a single boolean value.*'
112+
}
113+
114+
It 'Test operation returns error for multiple boolean results for <resourceType>' -TestCases $testCases {
115+
param($resourceType)
116+
117+
$yaml = @'
118+
TestScript: |
119+
$true
120+
$false
121+
'@
122+
$result = dsc resource test -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
123+
$LASTEXITCODE | Should -Be 2 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String)
124+
$result | Should -BeNullOrEmpty -Because "Test operation should return an error"
125+
(Get-Content $TestDrive/error.txt -Raw) | Should -BeLike '*Test operation did not return a single boolean value.*'
126+
}
127+
128+
It 'Empty SetScript is ignored for <resourceType>' -TestCases $testCases {
129+
param($resourceType)
130+
131+
$yaml = @'
132+
GetScript: |
133+
"Hello, World!"
134+
1+1
135+
TestScript: |
136+
$true
137+
'@
138+
139+
$result = dsc resource set -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
140+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String)
141+
$result.beforeState.output.Count | Should -Be 2 -Because ($result | ConvertTo-Json | Out-String)
142+
$result.beforeState.output[0] | Should -BeExactly "Hello, World!"
143+
$result.beforeState.output[1] | Should -BeExactly 2
144+
$result.afterState.output.Count | Should -Be 0
145+
}
146+
147+
It 'Empty GetScript is ignored for <resourceType>' -TestCases $testCases {
148+
param($resourceType)
149+
150+
$yaml = @'
151+
SetScript: |
152+
"Hello, World!"
153+
1+1
154+
TestScript: |
155+
$true
156+
'@
157+
$result = dsc resource get -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
158+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String)
159+
$result.actualState.output.Count | Should -Be 0 -Because ($result | ConvertTo-Json | Out-String)
160+
}
161+
162+
It 'Empty TestScript is ignored for <resourceType>' -TestCases $testCases {
163+
param($resourceType)
164+
165+
$yaml = @'
166+
GetScript: |
167+
"Hello, World!"
168+
1+1
169+
SetScript: |
170+
"Hello, World!"
171+
2+2
172+
'@
173+
$result = dsc resource test -r $resourceType -i $yaml 2> $TestDrive/error.txt | ConvertFrom-Json
174+
$LASTEXITCODE | Should -Be 0 -Because (Get-Content $TestDrive/error.txt -Raw | Out-String)
175+
$result.InDesiredState | Should -BeTrue
176+
}
177+
}

0 commit comments

Comments
 (0)