-
Notifications
You must be signed in to change notification settings - Fork 61
Expand file tree
/
Copy pathdsc_discovery.tests.ps1
More file actions
345 lines (309 loc) · 14.1 KB
/
dsc_discovery.tests.ps1
File metadata and controls
345 lines (309 loc) · 14.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
Describe 'tests for resource discovery' {
BeforeAll {
$script:lookupTableFilePath = if ($IsWindows) {
Join-Path $env:LocalAppData "dsc\AdaptedResourcesLookupTable.json"
} else {
Join-Path $env:HOME ".dsc" "AdaptedResourcesLookupTable.json"
}
}
AfterEach {
Remove-Item -Path "$testdrive/test.dsc.resource.*" -ErrorAction SilentlyContinue
}
It 'Use DSC_RESOURCE_PATH instead of PATH when defined' {
$resourceJson = @'
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
"type": "DSC/TestPathResource",
"version": "0.1.0",
"get": {
"executable": "dsc"
}
}
'@
try {
$oldPath = $env:PATH
$env:DSC_RESOURCE_PATH = $testdrive
Set-Content -Path "$testdrive/test.dsc.resource.json" -Value $resourceJson
$resources = dsc resource list | ConvertFrom-Json
$resources.Count | Should -Be 1
$resources.type | Should -BeExactly 'DSC/TestPathResource'
}
finally {
$env:PATH = $oldPath
$env:DSC_RESOURCE_PATH = $null
}
}
Context 'Forced discovery using $testdrive' {
BeforeAll {
$env:DSC_RESOURCE_PATH = $testdrive
}
AfterAll {
$env:DSC_RESOURCE_PATH = $null
}
It 'support discovering <extension>' -TestCases @(
@{ extension = 'yaml' }
@{ extension = 'yml' }
) {
param($extension)
$resourceYaml = @'
$schema: https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json
type: DSC/TestYamlResource
version: 0.1.0
get:
executable: dsc
'@
Set-Content -Path "$testdrive/test.dsc.resource.$extension" -Value $resourceYaml
$resources = dsc resource list | ConvertFrom-Json
$resources.Count | Should -Be 1
$resources.type | Should -BeExactly 'DSC/TestYamlResource'
}
It 'does not support discovering a file with an extension that is not json or yaml' {
param($extension)
$resourceInput = @'
$schema: https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json
type: DSC/TestYamlResource
version: 0.1.0
get:
executable: dsc
'@
Set-Content -Path "$testdrive/test.dsc.resource.txt" -Value $resourceInput
$resources = dsc resource list | ConvertFrom-Json
$resources.Count | Should -Be 0
}
It 'warns on invalid semver' {
$manifest = @'
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
"type": "Test/InvalidSemver",
"version": "1.1.0..1",
"get": {
"executable": "dsctest"
},
"schema": {
"command": {
"executable": "dsctest"
}
}
}
'@
Set-Content -Path "$testdrive/test.dsc.resource.json" -Value $manifest
$null = dsc resource list 2> "$testdrive/error.txt"
"$testdrive/error.txt" | Should -FileContentMatchExactly 'WARN.*?does not use semver' -Because (Get-Content -Raw "$testdrive/error.txt")
}
}
It 'Ensure List operation populates adapter lookup table' {
# remove adapter lookup table file
Remove-Item -Force -Path $script:lookupTableFilePath -ErrorAction SilentlyContinue
Test-Path $script:lookupTableFilePath -PathType Leaf | Should -BeFalse
# perform List on an adapter - this should create adapter lookup table file
$oldPSModulePath = $env:PSModulePath
$TestClassResourcePath = Resolve-Path "$PSScriptRoot/../../adapters/powershell/Tests"
$env:DSC_RESOURCE_PATH = $null
$env:PSModulePath += [System.IO.Path]::PathSeparator + $TestClassResourcePath
dsc resource list -a Microsoft.DSC/PowerShell | Out-Null
$script:lookupTableFilePath | Should -FileContentMatchExactly 'Microsoft.DSC/PowerShell'
Test-Path $script:lookupTableFilePath -PathType Leaf | Should -BeTrue
$env:PSModulePath = $oldPSModulePath
}
It 'Ensure non-List operation populates adapter lookup table' {
# remove adapter lookup table file
Remove-Item -Force -Path $script:lookupTableFilePath -ErrorAction SilentlyContinue
Test-Path $script:lookupTableFilePath -PathType Leaf | Should -BeFalse
# perform Get on an adapter - this should create adapter lookup table file
$oldPSModulePath = $env:PSModulePath
$TestClassResourcePath = Resolve-Path "$PSScriptRoot/../../adapters/powershell/Tests"
$env:DSC_RESOURCE_PATH = $null
$env:PSModulePath += [System.IO.Path]::PathSeparator + $TestClassResourcePath
"{'Name':'TestClassResource1'}" | dsc resource get -r 'TestClassResource/TestClassResource' -f - | Out-Null
Test-Path $script:lookupTableFilePath -PathType Leaf | Should -BeTrue
$script:lookupTableFilePath | Should -FileContentMatchExactly 'testclassresource/testclassresource'
$env:PSModulePath = $oldPSModulePath
}
It 'Verify adapter lookup table is used on repeat invocations' {
$oldPSModulePath = $env:PSModulePath
$TestClassResourcePath = Resolve-Path "$PSScriptRoot/../../adapters/powershell/Tests"
$env:DSC_RESOURCE_PATH = $null
$env:PSModulePath += [System.IO.Path]::PathSeparator + $TestClassResourcePath
# remove adapter lookup table file
Remove-Item -Force -Path $script:lookupTableFilePath -ErrorAction Stop
Test-Path $script:lookupTableFilePath -PathType Leaf | Should -BeFalse
# initial invocation should populate and save adapter lookup table
$null = dsc -l trace resource list -a 'Microsoft.*/PowerShell' 2> $TestDrive/tracing.txt
"$TestDrive/tracing.txt" | Should -FileContentMatchExactly "Read 0 items into lookup table"
"$TestDrive/tracing.txt" | Should -FileContentMatchExactly "Saving lookup table" -Because (Get-Content -Raw "$TestDrive/tracing.txt")
# second invocation (without an update) should use but not save adapter lookup table
"{'Name':'TestClassResource1'}" | dsc -l trace resource get -r 'TestClassResource/TestClassResource' -f - 2> $TestDrive/tracing.txt
"$TestDrive/tracing.txt" | Should -Not -FileContentMatchExactly "Saving lookup table" -Because (Get-Content -Raw "$TestDrive/tracing.txt")
# third invocation (with an update) should save updated adapter lookup table
$null = dsc -l trace resource list -a Test/TestGroup 2> $TestDrive/tracing.txt
"$TestDrive/tracing.txt" | Should -FileContentMatchExactly "Saving lookup table"
$env:PSModulePath = $oldPSModulePath
}
It 'Verify non-zero exit code when resource not found: <cmdline>' -TestCases @(
@{ cmdline = "dsc resource get -r abc/def" }
@{ cmdline = "dsc resource get --all -r abc/def" }
@{ cmdline = "dsc resource set -r abc/def -i 'abc'" }
@{ cmdline = "dsc resource test -r abc/def -i 'abc'" }
@{ cmdline = "dsc resource delete -r abc/def -i 'abc'" }
@{ cmdline = "dsc resource export -r abc/def" }
@{ cmdline = "dsc resource schema -r abc/def" }
) {
param($cmdline)
Invoke-Expression $cmdline 2>$null
$LASTEXITCODE | Should -Be 7
}
It 'Verify warning message when executable not found for: <operation>' -TestCases @(
@{ operation = 'get' }
@{ operation = 'set' }
@{ operation = 'test' }
@{ operation = 'delete' }
@{ operation = 'export' }
@{ operation = 'resolve' }
) {
param($operation)
$manifest = @"
{
"`$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
"type": "Test/ExecutableNotFound",
"version": "0.1.0",
"$operation": {
"executable": "doesNotExist"
}
}
"@
$oldPath = $env:DSC_RESOURCE_PATH
try {
$env:DSC_RESOURCE_PATH = $testdrive
Set-Content -Path "$testdrive/test.dsc.resource.json" -Value $manifest
$out = dsc -l info resource list 'Test/ExecutableNotFound' 2> "$testdrive/error.txt" | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.Count | Should -Be 1
$out.Type | Should -BeExactly 'Test/ExecutableNotFound'
$out.Kind | Should -BeExactly 'resource'
(Get-Content -Path "$testdrive/error.txt" -Raw)
(Get-Content -Path "$testdrive/error.txt" -Raw) | Should -Match "INFO.*?Executable 'doesNotExist' not found"
}
finally {
$env:DSC_RESOURCE_PATH = $oldPath
}
}
It 'DSC_RESOURCE_PATH should be used for executable lookup' {
$dscTest = Get-Command dscecho -ErrorAction Stop
$target = if ($IsWindows) {
'echoIt.exe'
} else {
'echoIt'
}
Copy-Item -Path "$($dscTest.Source)" -Destination "$testdrive\$target"
$manifest = Get-Content -Raw -Path "$(Split-Path -Path $dscTest.Source -Parent)\echo.dsc.resource.json" | ConvertFrom-Json
$manifest.type = 'Test/MyEcho'
$manifest.get.executable = $target
$manifest.set = $null
$manifest.test = $null
$manifest.schema.command.executable = $target
Set-Content -Path "$testdrive/test.dsc.resource.json" -Value ($manifest | ConvertTo-Json -Depth 10)
$oldPath = $env:DSC_RESOURCE_PATH
try {
$env:DSC_RESOURCE_PATH = $testdrive
$out = dsc resource get -r 'Test/MyEcho' -i '{"output":"Custom"}' 2> "$testdrive/error.txt" | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$out.actualState.output | Should -BeExactly 'Custom'
dsc resource get -r 'Microsoft.DSC.Debug/Echo' -i '{"output":"Custom"}' 2> "$testdrive/error.txt" | ConvertFrom-Json
$LASTEXITCODE | Should -Be 7
Get-Content -Raw -Path "$testdrive/error.txt" | Should -Match "ERROR.*?Resource not found"
}
finally {
$env:DSC_RESOURCE_PATH = $oldPath
}
}
It 'Resource manifest using relative path to exe: <path>' -TestCases @(
@{ path = '../dscecho'; success = $true }
@{ path = '../foo/dscecho'; success = $false }
) {
param($path, $success)
$manifest = @"
{
"`$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
"type": "Microsoft.DSC.Debug/Echo",
"version": "1.0.0",
"description": "Echo resource for testing and debugging purposes",
"get": {
"executable": "$path",
"args": [
{
"jsonInputArg": "--input",
"mandatory": true
}
]
},
"schema": {
"command": {
"executable": "$path"
}
}
}
"@
$dscEcho = Get-Command dscecho -ErrorAction Stop
# copy to testdrive
Copy-Item -Path "$($dscEcho.Source)" -Destination $testdrive
# create manifest in subfolder
$subfolder = Join-Path $testdrive 'subfolder'
New-Item -Path $subfolder -ItemType Directory -Force | Out-Null
Set-Content -Path (Join-Path $subfolder 'test.dsc.resource.json') -Value $manifest
try {
$env:DSC_RESOURCE_PATH = $subfolder
$out = dsc resource get -r 'Microsoft.DSC.Debug/Echo' -i '{"output":"RelativePathTest"}' 2> "$testdrive/error.txt" | ConvertFrom-Json
if ($success) {
$LASTEXITCODE | Should -Be 0 -Because (Get-Content -Raw -Path "$testdrive/error.txt")
$out.actualState.output | Should -BeExactly 'RelativePathTest'
} else {
$LASTEXITCODE | Should -Be 2 -Because (Get-Content -Raw -Path "$testdrive/error.txt")
(Get-Content -Raw -Path "$testdrive/error.txt") | Should -Match "ERROR.*?Executable '\.\./foo/dscecho(\.exe)?' not found"
}
}
finally {
$env:DSC_RESOURCE_PATH = $null
}
}
It 'Resource discovery directive can be set to <mode>' -TestCases @(
@{ mode = 'resourceDiscovery: preDeployment' }
@{ mode = 'resourceDiscovery: duringDeployment' }
@{ mode = '' }
) {
param($mode)
$guid = (New-Guid).Guid.Replace('-', '')
$manifestPath = Join-Path (Split-Path (Get-Command dscecho -ErrorAction Stop).Source -Parent) echo.dsc.resource.json
$config_yaml = @"
`$schema: https://aka.ms/dsc/schemas/v3/bundled/config/manifest.json
directives:
$mode
resources:
- type: Test/CopyResource
name: This should be found and executed
properties:
sourceFile: $manifestPath
typeName: "Test/$guid"
- type: Test/$guid
name: This is the new resource
properties:
output: Hello World
"@
$out = dsc -l trace config get -i $config_yaml 2> "$testdrive/tracing.txt"
$traceLog = Get-Content -Raw -Path "$testdrive/tracing.txt"
if ($mode -notlike '*duringDeployment') {
$LASTEXITCODE | Should -Be 2
$out | Should -BeNullOrEmpty
$traceLog | Should -Match "ERROR.*?Resource not found: Test/$guid"
$traceLog | Should -Not -Match "Invoking get for 'Test/CopyResource'"
} else {
$LASTEXITCODE | Should -Be 0 -Because (Get-Content -Raw -Path "$testdrive/tracing.txt")
$output = $out | ConvertFrom-Json
$output.results[0].result.actualState.typeName | Should -BeExactly "Test/$guid" -Because $out
$output.results[1].result.actualState.output | Should -BeExactly 'Hello World' -Because $out
$traceLog | Should -Match "Invoking get for 'Test/$guid'"
$traceLog | Should -Match "Skipping resource discovery due to 'resourceDiscovery' mode set to 'DuringDeployment'"
}
}
}