Skip to content

Commit 1a77e80

Browse files
committed
Merge branch 'wmi-set-operation' of https://github.com/Gijsreyn/operation-methods into wmi-set-operation
2 parents 0f3f7c0 + d5fa70c commit 1a77e80

File tree

5 files changed

+101
-10
lines changed

5 files changed

+101
-10
lines changed

powershell-adapter/Tests/powershellgroup.resource.tests.ps1

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ Describe 'PowerShell adapter resource tests' {
2727
$r = dsc resource list '*' -a Microsoft.DSC/PowerShell
2828
$LASTEXITCODE | Should -Be 0
2929
$resources = $r | ConvertFrom-Json
30-
($resources | ? { $_.Type -eq 'TestClassResource/TestClassResource' }).Count | Should -Be 1
30+
($resources | Where-Object { $_.Type -eq 'TestClassResource/TestClassResource' }).Count | Should -Be 1
31+
($resources | Where-Object -Property type -EQ 'TestClassResource/TestClassResource').capabilities | Should -BeIn @('get', 'set', 'test', 'export')
32+
($resources | Where-Object -Property type -EQ 'TestClassResource/NoExport').capabilities | Should -BeIn @('get', 'set', 'test')
3133
}
3234

3335
It 'Get works on class-based resource' {

powershell-adapter/Tests/win_powershellgroup.tests.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ class PSClassResource {
373373
$LASTEXITCODE | Should -Be 0
374374
$out.type | Should -Contain 'PSClassResource/PSClassResource'
375375
$out | Where-Object -Property type -EQ PSClassResource/PSClassResource | Select-Object -ExpandProperty implementedAs | Should -Be 1 # Class-based
376+
($out | Where-Object -Property type -EQ 'PSClassResource/PSClassResource').capabilities | Should -BeIn @('get', 'test', 'set', 'export')
376377
}
377378

378379
It 'Get works with class-based PS DSC resources' -Skip:(!$IsWindows) {

powershell-adapter/psDscAdapter/powershell.resource.ps1

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,13 @@ switch ($Operation) {
9191
# TODO: for perf, it is better to take capabilities from psd1 in Invoke-DscCacheRefresh, not by extra call to Get-Module
9292
if ($DscResourceInfo.ModuleName) {
9393
$module = Get-Module -Name $DscResourceInfo.ModuleName -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1
94-
if ($module.PrivateData.PSData.DscCapabilities) {
94+
# If the DscResourceInfo does have capabilities, use them or else use the module's capabilities
95+
if ($DscResourceInfo.Capabilities) {
96+
$capabilities = $DscResourceInfo.Capabilities
97+
} elseif ($module.PrivateData.PSData.DscCapabilities) {
98+
9599
$capabilities = $module.PrivateData.PSData.DscCapabilities
96-
}
97-
else {
100+
} else {
98101
$capabilities = @('get', 'set', 'test')
99102
}
100103
}

powershell-adapter/psDscAdapter/psDscAdapter.psm1

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Copyright (c) Microsoft Corporation.
22
# Licensed under the MIT License.
33

4-
$script:CurrentCacheSchemaVersion = 2
4+
$script:CurrentCacheSchemaVersion = 3
55

66
function Write-DscTrace {
77
param(
@@ -60,7 +60,7 @@ function Add-AstMembers {
6060

6161
foreach ($member in $TypeAst.Members) {
6262
$property = $member -as [System.Management.Automation.Language.PropertyMemberAst]
63-
if (($property -eq $null) -or ($property.IsStatic)) {
63+
if (($null -eq $property) -or ($property.IsStatic)) {
6464
continue;
6565
}
6666
$skipProperty = $true
@@ -117,7 +117,7 @@ function FindAndParseResourceDefinitions {
117117
$typeDefinitions = $ast.FindAll(
118118
{
119119
$typeAst = $args[0] -as [System.Management.Automation.Language.TypeDefinitionAst]
120-
return $typeAst -ne $null;
120+
return $null -ne $typeAst;
121121
},
122122
$false);
123123

@@ -139,6 +139,7 @@ function FindAndParseResourceDefinitions {
139139
$DscResourceInfo.Version = $moduleVersion
140140

141141
$DscResourceInfo.Properties = [System.Collections.Generic.List[DscResourcePropertyInfo]]::new()
142+
$DscResourceInfo.Capabilities = GetClassBasedCapabilities $typeDefinitionAst.Members
142143
Add-AstMembers $typeDefinitions $typeDefinitionAst $DscResourceInfo.Properties
143144

144145
$resourceList.Add($DscResourceInfo)
@@ -325,7 +326,7 @@ function Invoke-DscCacheRefresh {
325326

326327
# fill in resource files (and their last-write-times) that will be used for up-do-date checks
327328
$lastWriteTimes = @{}
328-
Get-ChildItem -Recurse -File -Path $dscResource.ParentPath -Include "*.ps1", "*.psd1", "*.psm1", "*.mof" -ea Ignore | % {
329+
Get-ChildItem -Recurse -File -Path $dscResource.ParentPath -Include "*.ps1", "*.psd1", "*.psm1", "*.mof" -ea Ignore | ForEach-Object {
329330
$lastWriteTimes.Add($_.FullName, $_.LastWriteTime)
330331
}
331332

@@ -338,7 +339,7 @@ function Invoke-DscCacheRefresh {
338339

339340
[dscResourceCache]$cache = [dscResourceCache]::new()
340341
$cache.ResourceCache = $dscResourceCacheEntries
341-
$m = $env:PSModulePath -split [IO.Path]::PathSeparator | % { Get-ChildItem -Directory -Path $_ -Depth 1 -ea SilentlyContinue }
342+
$m = $env:PSModulePath -split [IO.Path]::PathSeparator | ForEach-Object { Get-ChildItem -Directory -Path $_ -Depth 1 -ea SilentlyContinue }
342343
$cache.PSModulePaths = $m.FullName
343344
$cache.CacheSchemaVersion = $script:CurrentCacheSchemaVersion
344345

@@ -529,6 +530,28 @@ function GetTypeInstanceFromModule {
529530
return $instance
530531
}
531532

533+
function GetClassBasedCapabilities ($functionMemberAst) {
534+
$capabilities = [System.Collections.Generic.List[string[]]]::new()
535+
# These are the methods that we can potentially expect in a class-based DSC resource.
536+
$availableMethods = @('get', 'set', 'setHandlesExist', 'whatIf', 'test', 'delete', 'export')
537+
$methods = $functionMemberAst | Where-Object { $_ -is [System.Management.Automation.Language.FunctionMemberAst] -and $_.Name -in $availableMethods }
538+
539+
foreach ($method in $methods.Name) {
540+
# We go through each method to properly case handle the method names.
541+
switch ($method) {
542+
'Get' { $capabilities.Add('get') }
543+
'Set' { $capabilities.Add('set') }
544+
'Test' { $capabilities.Add('test') }
545+
'WhatIf' { $capabilities.Add('whatIf') }
546+
'SetHandlesExist' { $capabilities.Add('setHandlesExist') }
547+
'Delete' { $capabilities.Add('delete') }
548+
'Export' { $capabilities.Add('export') }
549+
}
550+
}
551+
552+
return ($capabilities | Select-Object -Unique)
553+
}
554+
532555
# cached resource
533556
class dscResourceCacheEntry {
534557
[string] $Type
@@ -578,4 +601,5 @@ class DscResourceInfo {
578601
[string] $ImplementedAs
579602
[string] $CompanyName
580603
[System.Collections.Generic.List[DscResourcePropertyInfo]] $Properties
604+
[string[]] $Capabilities
581605
}

powershell-adapter/psDscAdapter/win_psDscAdapter.psm1

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ function Invoke-DscCacheRefresh {
226226
if ($null -ne $properties) {
227227
$DscResourceInfo.Properties = $properties
228228
}
229+
230+
$dscResourceInfo.Capabilities = GetClassBasedCapabilities -filePath $dscResource.Path -className $dscResource.Name
229231
}
230232

231233
# fill in resource files (and their last-write-times) that will be used for up-do-date checks
@@ -632,6 +634,64 @@ function GetClassBasedProperties {
632634
}
633635
}
634636

637+
function GetClassBasedCapabilities {
638+
param (
639+
[Parameter(Mandatory = $true)]
640+
[string] $filePath,
641+
642+
[Parameter(Mandatory = $true)]
643+
[string] $className
644+
)
645+
646+
if (".psd1" -notcontains ([System.IO.Path]::GetExtension($filePath))) {
647+
return @('get', 'set', 'test')
648+
}
649+
650+
$module = $filePath.Replace('.psd1', '.psm1')
651+
652+
if (Test-Path $module -ErrorAction Ignore) {
653+
[System.Management.Automation.Language.Token[]] $tokens = $null
654+
[System.Management.Automation.Language.ParseError[]] $errors = $null
655+
$ast = [System.Management.Automation.Language.Parser]::ParseFile($module, [ref]$tokens, [ref]$errors)
656+
foreach ($e in $errors) {
657+
$e | Out-String | Write-DscTrace -Operation Error
658+
}
659+
660+
$typeDefinitions = $ast.FindAll(
661+
{
662+
$typeAst = $args[0] -as [System.Management.Automation.Language.TypeDefinitionAst]
663+
return $null -ne $typeAst;
664+
},
665+
$false);
666+
667+
668+
$capabilities = [System.Collections.Generic.List[string[]]]::new()
669+
$availableMethods = @('get', 'set', 'setHandlesExist', 'whatIf', 'test', 'delete', 'export')
670+
foreach ($typeDefinitionAst in $typeDefinitions) {
671+
foreach ($a in $typeDefinitionAst.Attributes) {
672+
if ($a.TypeName.Name -eq 'DscResource' -and $a.Parent.Name -eq $className) {
673+
$methods = $typeDefinitionAst.Members | Where-Object { $_ -is [System.Management.Automation.Language.FunctionMemberAst] -and $_.Name -in $availableMethods }
674+
675+
foreach ($method in $methods.Name) {
676+
# We go through each method to properly case handle the method names.
677+
switch ($method) {
678+
'Get' { $capabilities.Add('get') }
679+
'Set' { $capabilities.Add('set') }
680+
'Test' { $capabilities.Add('test') }
681+
'WhatIf' { $capabilities.Add('whatIf') }
682+
'SetHandlesExist' { $capabilities.Add('setHandlesExist') }
683+
'Delete' { $capabilities.Add('delete') }
684+
'Export' { $capabilities.Add('export') }
685+
}
686+
}
687+
}
688+
}
689+
}
690+
691+
return $capabilities
692+
}
693+
}
694+
635695
# cached resource
636696
class dscResourceCacheEntry {
637697
[string] $Type
@@ -681,4 +741,5 @@ class DscResourceInfo {
681741
[string] $ImplementedAs
682742
[string] $CompanyName
683743
[psobject[]] $Properties
684-
}
744+
[string[]] $Capabilities
745+
}

0 commit comments

Comments
 (0)