diff --git a/powershell-adapter/Tests/win_powershellgroup.tests.ps1 b/powershell-adapter/Tests/win_powershellgroup.tests.ps1 index ec305840..e2258888 100644 --- a/powershell-adapter/Tests/win_powershellgroup.tests.ps1 +++ b/powershell-adapter/Tests/win_powershellgroup.tests.ps1 @@ -322,6 +322,22 @@ class PSClassResource { [void] Set() { } + + static [PSClassResource[]] Export() + { + $resultList = [System.Collections.Generic.List[PSClassResource]]::new() + $resultCount = 5 + if ($env:PSClassResourceResultCount) { + $resultCount = $env:PSClassResourceResultCount + } + 1..$resultCount | %{ + $obj = New-Object PSClassResource + $obj.Name = "Object$_" + $resultList.Add($obj) + } + + return $resultList.ToArray() + } } '@ @@ -350,4 +366,12 @@ class PSClassResource { $LASTEXITCODE | Should -Be 0 $out.afterstate.InDesiredState | Should -Be $true } + + It 'Export works with class-based PS DSC resources' -Skip:(!$IsWindows) { + + $out = dsc resource export -r PSClassResource/PSClassResource | ConvertFrom-Json + $LASTEXITCODE | Should -Be 0 + $out | Should -Not -BeNullOrEmpty + $out.resources.count | Should -Be 5 + } } \ No newline at end of file diff --git a/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 b/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 index a6cd6e43..6bd1b32d 100644 --- a/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 +++ b/powershell-adapter/psDscAdapter/win_psDscAdapter.psm1 @@ -438,9 +438,21 @@ function Invoke-DscOperation { $addToActualState.properties = [psobject]@{'InDesiredState' = $Result } } 'Export' { - $t = $dscResourceInstance.GetType() - $method = $t.GetMethod('Export') - $resultArray = $method.Invoke($null, $null) + $method = ValidateMethod -operation $Operation -class $dscResourceInstance + $resultArray = @() + $raw_obj_array = $method.Invoke($null, $null) + foreach ($raw_obj in $raw_obj_array) { + $Result_obj = @{} + $ValidProperties | ForEach-Object { + if ($raw_obj.$_ -is [System.Enum]) { + $Result_obj[$_] = $raw_obj.$_.ToString() + } + else { + $Result_obj[$_] = $raw_obj.$_ + } + } + $resultArray += $Result_obj + } $addToActualState = $resultArray } } @@ -532,6 +544,33 @@ function GetTypeInstanceFromModule { return $instance } +# ValidateMethod checks if the specified method exists in the class +function ValidateMethod { + param ( + [Parameter(Mandatory = $true)] + [ValidateSet('Export', 'WhatIf')] + [string] $operation, + [Parameter(Mandatory = $true)] + [object] $class + ) + + $t = $class.GetType() + $methods = $t.GetMethods() | Where-Object -Property Name -EQ $operation + $method = foreach ($mt in $methods) { + if ($mt.GetParameters().Count -eq 0) { + $mt + break + } + } + + if ($null -eq $method) { + "Method '$operation' not implemented by resource '$($t.Name)'" | Write-DscTrace -Operation Error + exit 1 + } + + return $method +} + # cached resource class dscResourceCacheEntry { [string] $Type diff --git a/powershell-adapter/windowspowershell.dsc.resource.json b/powershell-adapter/windowspowershell.dsc.resource.json index ba6aabfb..297b44d0 100644 --- a/powershell-adapter/windowspowershell.dsc.resource.json +++ b/powershell-adapter/windowspowershell.dsc.resource.json @@ -1,41 +1,14 @@ { - "$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json", - "type": "Microsoft.Windows/WindowsPowerShell", - "version": "0.1.0", - "kind": "adapter", - "description": "Resource adapter to classic DSC Powershell resources in Windows PowerShell.", - "tags": [ - "PowerShell" - ], - "adapter": { - "list": { - "executable": "powershell", - "args": [ - "-NoLogo", - "-NonInteractive", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-Command", - "./psDscAdapter/powershell.resource.ps1 List" - ] - }, - "config": "full" - }, - "get": { - "executable": "powershell", - "args": [ - "-NoLogo", - "-NonInteractive", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-Command", - "$Input | ./psDscAdapter/powershell.resource.ps1 Get" - ], - "input": "stdin" - }, - "set": { + "$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json", + "type": "Microsoft.Windows/WindowsPowerShell", + "version": "0.1.0", + "kind": "adapter", + "description": "Resource adapter to classic DSC Powershell resources in Windows PowerShell.", + "tags": [ + "PowerShell" + ], + "adapter": { + "list": { "executable": "powershell", "args": [ "-NoLogo", @@ -44,39 +17,80 @@ "-ExecutionPolicy", "Bypass", "-Command", - "$Input | ./psDscAdapter/powershell.resource.ps1 Set" - ], - "input": "stdin", - "preTest": true - }, - "test": { - "executable": "powershell", - "args": [ - "-NoLogo", - "-NonInteractive", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-Command", - "$Input | ./psDscAdapter/powershell.resource.ps1 Test" - ], - "input": "stdin", - "return": "state" - }, - "validate": { - "executable": "powershell", - "args": [ - "-NoLogo", - "-NonInteractive", - "-NoProfile", - "-ExecutionPolicy", - "Bypass", - "-Command", - "$Input | ./psDscAdapter/powershell.resource.ps1 Validate" - ] - }, - "exitCodes": { - "0": "Success", - "1": "Error" - } + "./psDscAdapter/powershell.resource.ps1 List" + ] + }, + "config": "full" + }, + "get": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Get" + ], + "input": "stdin" + }, + "set": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Set" + ], + "input": "stdin", + "preTest": true + }, + "test": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Test" + ], + "input": "stdin", + "return": "state" + }, + "export": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Export" + ], + "input": "stdin", + "return": "state" + }, + "validate": { + "executable": "powershell", + "args": [ + "-NoLogo", + "-NonInteractive", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "$Input | ./psDscAdapter/powershell.resource.ps1 Validate" + ] + }, + "exitCodes": { + "0": "Success", + "1": "Error" } +}