Skip to content

Commit 1a58787

Browse files
committed
Add FilteredExport resource and update export method handling
1 parent 1310751 commit 1a58787

File tree

5 files changed

+137
-14
lines changed

5 files changed

+137
-14
lines changed

adapters/powershell/Tests/TestClassResource/0.0.1/TestClassResource.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ VariablesToExport = @()
3434
AliasesToExport = @()
3535

3636
# DSC resources to export from this module
37-
DscResourcesToExport = @('TestClassResource', 'NoExport')
37+
DscResourcesToExport = @('TestClassResource', 'NoExport', 'FilteredExport')
3838

3939
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
4040
PrivateData = @{

adapters/powershell/Tests/TestClassResource/0.0.1/TestClassResource.psm1

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,52 @@ class NoExport: BaseTestClass
155155
}
156156
}
157157

158+
[DscResource()]
159+
class FilteredExport : BaseTestClass
160+
{
161+
[DscProperty(Key)]
162+
[string] $Name
163+
164+
[DscProperty()]
165+
[string] $Prop1
166+
167+
[void] Set()
168+
{
169+
}
170+
171+
[bool] Test()
172+
{
173+
return $true
174+
}
175+
176+
[FilteredExport] Get()
177+
{
178+
return $this
179+
}
180+
181+
static [FilteredExport[]] Export()
182+
{
183+
$resultList = [List[FilteredExport]]::new()
184+
$obj = New-Object FilteredExport
185+
$obj.Name = "DefaultObject"
186+
$obj.Prop1 = "Default Property"
187+
$resultList.Add($obj)
188+
189+
return $resultList.ToArray()
190+
}
191+
192+
static [FilteredExport[]] Export([FilteredExport]$Name)
193+
{
194+
$resultList = [List[FilteredExport]]::new()
195+
$obj = New-Object FilteredExport
196+
$obj.Name = $Name
197+
$obj.Prop1 = "Filtered Property for $Name"
198+
$resultList.Add($obj)
199+
200+
return $resultList.ToArray()
201+
}
202+
}
203+
158204
function Test-World()
159205
{
160206
"Hello world from PSTestModule!"

adapters/powershell/Tests/powershellgroup.config.tests.ps1

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,49 @@ Describe 'PowerShell adapter resource tests' {
105105
$out | Should -BeLike "*ERROR*Export method not implemented by resource 'TestClassResource/NoExport'*"
106106
}
107107

108+
It 'Export works with filtered export property' {
109+
$yaml = @'
110+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
111+
resources:
112+
- name: Working with class-based resources
113+
type: Microsoft.DSC/PowerShell
114+
properties:
115+
resources:
116+
- name: Class-resource Info
117+
type: TestClassResource/FilteredExport
118+
properties:
119+
Name: 'FilteredExport'
120+
'@
121+
$out = $yaml | dsc -l trace config export -f - 2> "$TestDrive/export_trace.txt"
122+
$LASTEXITCODE | Should -Be 0
123+
$res = $out | ConvertFrom-Json
124+
$res.'$schema' | Should -BeExactly 'https://aka.ms/dsc/schemas/v3/bundled/config/document.json'
125+
$res.'resources' | Should -Not -BeNullOrEmpty
126+
$res.resources[0].properties.result.count | Should -Be 1
127+
$res.resources[0].properties.result[0].Name | Should -Be "FilteredExport"
128+
$res.resources[0].properties.result[0].Prop1 | Should -Be "Filtered Property for FilteredExport"
129+
"$TestDrive/export_trace.txt" | Should -FileContentMatch "Properties provided for filtered export"
130+
}
131+
132+
It 'Export fails when filtered export is requested but not implemented' {
133+
$yaml = @'
134+
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
135+
resources:
136+
- name: Working with class-based resources
137+
type: Microsoft.DSC/PowerShell
138+
properties:
139+
resources:
140+
- name: Class-resource Info
141+
type: TestClassResource/NoExport
142+
properties:
143+
Name: 'SomeFilter'
144+
'@
145+
$out = $yaml | dsc config export -f - 2>&1 | Out-String
146+
$LASTEXITCODE | Should -Be 2
147+
$out | Should -Not -BeNullOrEmpty
148+
$out | Should -BeLike "*ERROR*Export method with parameters not implemented by resource 'TestClassResource/NoExport'*"
149+
}
150+
108151
It 'Custom psmodulepath in config works' {
109152

110153
$OldPSModulePath = $env:PSModulePath

adapters/powershell/psDscAdapter/powershell.resource.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ switch ($Operation) {
181181
# process the INPUT (desiredState) for each resource as dscresourceInfo and return the OUTPUT as actualState
182182
$actualState = $psDscAdapter.invoke( { param($op, $ds, $dscResourceCache) Invoke-DscOperation -Operation $op -DesiredState $ds -dscResourceCache $dscResourceCache }, $Operation, $ds, $dscResourceCache)
183183
if ($null -eq $actualState) {
184-
Write-DscTrace -Operation Error -Message 'Incomplete GET for resource ' + $ds.Name
184+
"Failed to invoke operation '{0}' for resource name '{1}'." -f $Operation, $ds.Name | Write-DscTrace -Operation Error
185185
exit 1
186186
}
187187
if ($null -ne $actualState.Properties -and $actualState.Properties.InDesiredState -eq $false) {

adapters/powershell/psDscAdapter/psDscAdapter.psm1

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,42 @@ function FindAndParseResourceDefinitions {
150150
return $resourceList
151151
}
152152

153+
function GetExportMethod ($ResourceType, $HasFilterProperties, $ResourceTypeName) {
154+
$methods = $ResourceType.GetMethods() | Where-Object { $_.Name -eq 'Export' }
155+
$method = $null
156+
157+
if ($HasFilterProperties) {
158+
"Properties provided for filtered export" | Write-DscTrace -Operation Trace
159+
$method = foreach ($mt in $methods) {
160+
if ($mt.GetParameters().Count -gt 0) {
161+
$mt
162+
break
163+
}
164+
}
165+
166+
if ($null -eq $method) {
167+
"Export method with parameters not implemented by resource '$ResourceTypeName'. Filtered export is not supported." | Write-DscTrace -Operation Error
168+
exit 1
169+
}
170+
}
171+
else {
172+
"No properties provided, using parameterless export" | Write-DscTrace -Operation Trace
173+
$method = foreach ($mt in $methods) {
174+
if ($mt.GetParameters().Count -eq 0) {
175+
$mt
176+
break
177+
}
178+
}
179+
180+
if ($null -eq $method) {
181+
"Export method not implemented by resource '$ResourceTypeName'" | Write-DscTrace -Operation Error
182+
exit 1
183+
}
184+
}
185+
186+
return $method
187+
}
188+
153189
function LoadPowerShellClassResourcesFromModule {
154190
[CmdletBinding(HelpUri = '')]
155191
param(
@@ -471,20 +507,18 @@ function Invoke-DscOperation {
471507
}
472508
'Export' {
473509
$t = $dscResourceInstance.GetType()
474-
$methods = $t.GetMethods() | Where-Object { $_.Name -eq 'Export' }
475-
$method = foreach ($mt in $methods) {
476-
if ($mt.GetParameters().Count -eq 0) {
477-
$mt
478-
break
479-
}
480-
}
510+
$hasFilter = $null -ne $DesiredState.properties -and
511+
($DesiredState.properties.PSObject.Properties | Measure-Object).Count -gt 0
512+
513+
$method = GetExportMethod -ResourceType $t -HasFilterProperties $hasFilter -ResourceTypeName $DesiredState.Type
481514

482-
if ($null -eq $method) {
483-
"Export method not implemented by resource '$($DesiredState.Type)'" | Write-DscTrace -Operation Error
484-
exit 1
485-
}
486515
$resultArray = @()
487-
$raw_obj_array = $method.Invoke($null, $null)
516+
if ($hasFilter) {
517+
$raw_obj_array = $method.Invoke($null, @($dscResourceInstance))
518+
} else {
519+
$raw_obj_array = $method.Invoke($null, $null)
520+
}
521+
488522
foreach ($raw_obj in $raw_obj_array) {
489523
$Result_obj = @{}
490524
$ValidProperties | ForEach-Object {

0 commit comments

Comments
 (0)