Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ VariablesToExport = @()
AliasesToExport = @()

# DSC resources to export from this module
DscResourcesToExport = @('TestClassResource', 'NoExport')
DscResourcesToExport = @('TestClassResource', 'NoExport', 'FilteredExport')

# 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.
PrivateData = @{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,52 @@ class NoExport: BaseTestClass
}
}

[DscResource()]
class FilteredExport : BaseTestClass
{
[DscProperty(Key)]
[string] $Name

[DscProperty()]
[string] $Prop1

[void] Set()
{
}

[bool] Test()
{
return $true
}

[FilteredExport] Get()
{
return $this
}

static [FilteredExport[]] Export()
{
$resultList = [List[FilteredExport]]::new()
$obj = New-Object FilteredExport
$obj.Name = "DefaultObject"
$obj.Prop1 = "Default Property"
$resultList.Add($obj)

return $resultList.ToArray()
}

static [FilteredExport[]] Export([FilteredExport]$Name)
{
$resultList = [List[FilteredExport]]::new()
$obj = New-Object FilteredExport
$obj.Name = $Name
$obj.Prop1 = "Filtered Property for $Name"
$resultList.Add($obj)

return $resultList.ToArray()
}
}

function Test-World()
{
"Hello world from PSTestModule!"
Expand Down
43 changes: 43 additions & 0 deletions adapters/powershell/Tests/powershellgroup.config.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,49 @@ Describe 'PowerShell adapter resource tests' {
$out | Should -BeLike "*ERROR*Export method not implemented by resource 'TestClassResource/NoExport'*"
}

It 'Export works with filtered export property' {
$yaml = @'
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Working with class-based resources
type: Microsoft.DSC/PowerShell
properties:
resources:
- name: Class-resource Info
type: TestClassResource/FilteredExport
properties:
Name: 'FilteredExport'
'@
$out = $yaml | dsc -l trace config export -f - 2> "$TestDrive/export_trace.txt"
$LASTEXITCODE | Should -Be 0
$res = $out | ConvertFrom-Json
$res.'$schema' | Should -BeExactly 'https://aka.ms/dsc/schemas/v3/bundled/config/document.json'
$res.'resources' | Should -Not -BeNullOrEmpty
$res.resources[0].properties.result.count | Should -Be 1
$res.resources[0].properties.result[0].Name | Should -Be "FilteredExport"
$res.resources[0].properties.result[0].Prop1 | Should -Be "Filtered Property for FilteredExport"
"$TestDrive/export_trace.txt" | Should -FileContentMatch "Properties provided for filtered export"
}

It 'Export fails when filtered export is requested but not implemented' {
$yaml = @'
$schema: https://aka.ms/dsc/schemas/v3/bundled/config/document.json
resources:
- name: Working with class-based resources
type: Microsoft.DSC/PowerShell
properties:
resources:
- name: Class-resource Info
type: TestClassResource/NoExport
properties:
Name: 'SomeFilter'
'@
$out = $yaml | dsc config export -f - 2>&1 | Out-String
$LASTEXITCODE | Should -Be 2
$out | Should -Not -BeNullOrEmpty
$out | Should -BeLike "*ERROR*Export method with parameters not implemented by resource 'TestClassResource/NoExport'*"
}

It 'Custom psmodulepath in config works' {

$OldPSModulePath = $env:PSModulePath
Expand Down
2 changes: 1 addition & 1 deletion adapters/powershell/psDscAdapter/powershell.resource.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ switch ($Operation) {
# process the INPUT (desiredState) for each resource as dscresourceInfo and return the OUTPUT as actualState
$actualState = $psDscAdapter.invoke( { param($op, $ds, $dscResourceCache) Invoke-DscOperation -Operation $op -DesiredState $ds -dscResourceCache $dscResourceCache }, $Operation, $ds, $dscResourceCache)
if ($null -eq $actualState) {
Write-DscTrace -Operation Error -Message 'Incomplete GET for resource ' + $ds.Name
"Failed to invoke operation '{0}' for resource name '{1}'." -f $Operation, $ds.Name | Write-DscTrace -Operation Error
exit 1
}
if ($null -ne $actualState.Properties -and $actualState.Properties.InDesiredState -eq $false) {
Expand Down
58 changes: 46 additions & 12 deletions adapters/powershell/psDscAdapter/psDscAdapter.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,42 @@ function FindAndParseResourceDefinitions {
return $resourceList
}

function GetExportMethod ($ResourceType, $HasFilterProperties, $ResourceTypeName) {
$methods = $ResourceType.GetMethods() | Where-Object { $_.Name -eq 'Export' }
$method = $null

if ($HasFilterProperties) {
"Properties provided for filtered export" | Write-DscTrace -Operation Trace
$method = foreach ($mt in $methods) {
if ($mt.GetParameters().Count -gt 0) {
$mt
break
}
}

if ($null -eq $method) {
"Export method with parameters not implemented by resource '$ResourceTypeName'. Filtered export is not supported." | Write-DscTrace -Operation Error
exit 1
}
}
else {
"No properties provided, using parameterless export" | Write-DscTrace -Operation Trace
$method = foreach ($mt in $methods) {
if ($mt.GetParameters().Count -eq 0) {
$mt
break
}
}

if ($null -eq $method) {
"Export method not implemented by resource '$ResourceTypeName'" | Write-DscTrace -Operation Error
exit 1
}
}

return $method
}

function LoadPowerShellClassResourcesFromModule {
[CmdletBinding(HelpUri = '')]
param(
Expand Down Expand Up @@ -471,20 +507,18 @@ function Invoke-DscOperation {
}
'Export' {
$t = $dscResourceInstance.GetType()
$methods = $t.GetMethods() | Where-Object { $_.Name -eq 'Export' }
$method = foreach ($mt in $methods) {
if ($mt.GetParameters().Count -eq 0) {
$mt
break
}
}
$hasFilter = $null -ne $DesiredState.properties -and
($DesiredState.properties.PSObject.Properties | Measure-Object).Count -gt 0

$method = GetExportMethod -ResourceType $t -HasFilterProperties $hasFilter -ResourceTypeName $DesiredState.Type

if ($null -eq $method) {
"Export method not implemented by resource '$($DesiredState.Type)'" | Write-DscTrace -Operation Error
exit 1
}
$resultArray = @()
$raw_obj_array = $method.Invoke($null, $null)
if ($hasFilter) {
$raw_obj_array = $method.Invoke($null, @($dscResourceInstance))
} else {
$raw_obj_array = $method.Invoke($null, $null)
}

foreach ($raw_obj in $raw_obj_array) {
$Result_obj = @{}
$ValidProperties | ForEach-Object {
Expand Down