Skip to content

Commit d557c6d

Browse files
author
Andrew
committed
Stage 2
1 parent 224bbf2 commit d557c6d

File tree

3 files changed

+92
-58
lines changed

3 files changed

+92
-58
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,12 @@ Describe 'PowerShell adapter resource tests' {
2323
Remove-Item -Force -ea SilentlyContinue -Path $cacheFilePath
2424
}
2525

26-
It 'Discovery includes class-based and script-based resources ' -Skip:(!$IsWindows){
26+
It 'Discovery includes class-based resources' -Skip:(!$IsWindows){
2727

2828
$r = dsc resource list * -a Microsoft.DSC/PowerShell
2929
$LASTEXITCODE | Should -Be 0
3030
$resources = $r | ConvertFrom-Json
3131
($resources | ? {$_.Type -eq 'TestClassResource/TestClassResource'}).Count | Should -Be 1
32-
($resources | ? {$_.Type -eq 'PSTestModule/TestPSRepository'}).Count | Should -Be 1
3332
}
3433

3534
It 'Get works on class-based resource' -Skip:(!$IsWindows){

powershell-adapter/psDscAdapter/powershell.resource.ps1

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,10 @@ if ($jsonInput) {
4141
# process the operation requested to the script
4242
switch ($Operation) {
4343
'List' {
44-
Invoke-DscCacheRefresh
45-
#$dscResourceCache = Invoke-DscCacheRefresh
44+
$dscResourceCache = Invoke-DscCacheRefresh
4645

4746
# cache was refreshed on script load
48-
<#foreach ($dscResource in $dscResourceCache) {
47+
foreach ($dscResource in $dscResourceCache) {
4948

5049
# https://learn.microsoft.com/dotnet/api/system.management.automation.dscresourceinfo
5150
$DscResourceInfo = $dscResource.DscResourceInfo
@@ -85,7 +84,7 @@ switch ($Operation) {
8584
[resourceOutput]@{
8685
type = $dscResource.Type
8786
kind = 'Resource'
88-
version = $DscResourceInfo.version.ToString()
87+
version = [string]$DscResourceInfo.version
8988
capabilities = $capabilities
9089
path = $DscResourceInfo.Path
9190
directory = $DscResourceInfo.ParentPath
@@ -95,7 +94,7 @@ switch ($Operation) {
9594
requireAdapter = $requireAdapter
9695
description = $description
9796
} | ConvertTo-Json -Compress
98-
}#>
97+
}
9998
}
10099
{ @('Get','Set','Test','Export') -contains $_ } {
101100
$desiredState = $psDscAdapter.invoke( { param($jsonInput) Get-DscResourceObject -jsonInput $jsonInput }, $jsonInput )

powershell-adapter/psDscAdapter/psDscAdapter.psm1

Lines changed: 87 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ function FindAndParseResourceDefinitions
6666
{
6767
return
6868
}
69-
70-
$filePath
71-
69+
70+
"Loading resources from '$filePath'" | Write-DscTrace -Operation Trace
71+
#TODO: Handle class inheritance
72+
#TODO: Ensure embedded instances in properties are working correctly
7273
[System.Management.Automation.Language.Token[]] $tokens = $null
7374
[System.Management.Automation.Language.ParseError[]] $errors = $null
7475
$ast = [System.Management.Automation.Language.Parser]::ParseFile($filePath, [ref]$tokens, [ref]$errors)
@@ -90,7 +91,61 @@ function FindAndParseResourceDefinitions
9091
},
9192
$false);
9293

93-
$resourceDefinitions.Name
94+
$resourceList = [System.Collections.Generic.List[DscResourceInfo]]::new()
95+
96+
foreach($typeDefinitionAst in $resourceDefinitions)
97+
{
98+
$DscResourceInfo = [DscResourceInfo]::new()
99+
$DscResourceInfo.Name = $typeDefinitionAst.Name
100+
$DscResourceInfo.ResourceType = $typeDefinitionAst.Name
101+
$DscResourceInfo.FriendlyName = $typeDefinitionAst.Name
102+
$DscResourceInfo.ImplementationDetail = 'ClassBased'
103+
$DscResourceInfo.Module = $filePath
104+
$DscResourceInfo.Path = $filePath
105+
#TODO: ModuleName, Version and ParentPath should be taken from psd1 contents
106+
$DscResourceInfo.ModuleName = [System.IO.Path]::GetFileNameWithoutExtension($filePath)
107+
$DscResourceInfo.ParentPath = [System.IO.Path]::GetDirectoryName($filePath)
108+
109+
$DscResourceInfo.Properties = [System.Collections.Generic.List[DscResourcePropertyInfo]]::new()
110+
foreach ($member in $typeDefinitionAst.Members)
111+
{
112+
$property = $member -as [System.Management.Automation.Language.PropertyMemberAst]
113+
if (($property -eq $null) -or ($property.IsStatic))
114+
{
115+
continue;
116+
}
117+
$skipProperty = $true
118+
$isKeyProperty = $false
119+
foreach($attr in $property.Attributes)
120+
{
121+
if ($attr.TypeName.Name -eq 'DscProperty')
122+
{
123+
$skipProperty = $false
124+
foreach($attrArg in $attr.NamedArguments)
125+
{
126+
if ($attrArg.ArgumentName -eq 'Key')
127+
{
128+
$isKeyProperty = $true
129+
}
130+
}
131+
}
132+
}
133+
if ($skipProperty)
134+
{
135+
continue;
136+
}
137+
138+
[DscResourcePropertyInfo]$prop = [DscResourcePropertyInfo]::new()
139+
$prop.Name = $property.Name
140+
$prop.PropertyType = $property.PropertyType.TypeName.Name
141+
$prop.IsMandatory = $isKeyProperty
142+
$DscResourceInfo.Properties.Add($prop)
143+
}
144+
145+
$resourceList.Add($DscResourceInfo)
146+
}
147+
148+
return $resourceList
94149
}
95150

96151
function LoadPowerShellClassResourcesFromModule
@@ -110,28 +165,20 @@ function LoadPowerShellClassResourcesFromModule
110165
$scriptPath = $moduleInfo.Path;
111166
}
112167

113-
FindAndParseResourceDefinitions $scriptPath
168+
$Resources = FindAndParseResourceDefinitions $scriptPath
114169

115170
if ($moduleInfo.NestedModules)
116171
{
117172
foreach ($nestedModule in $moduleInfo.NestedModules)
118173
{
119-
LoadPowerShellClassResourcesFromModule $nestedModule
174+
$resourcesOfNestedModules = LoadPowerShellClassResourcesFromModule $nestedModule
175+
$Resources.AddRange($resourcesOfNestedModules)
120176
}
121177
}
122-
}
123178

124-
function Invoke-DscCacheRefresh {
125-
126-
$dscResourceModulePsd1s = Get-DSCResourceModules
127-
if($null -ne $dscResourceModulePsd1s) {
128-
$modules = Get-Module -ListAvailable -Name ($dscResourceModulePsd1s)
129-
foreach ($mod in $modules)
130-
{
131-
LoadPowerShellClassResourcesFromModule -moduleInfo $mod
132-
}
133-
}
179+
return $Resources
134180
}
181+
135182
<# public function Invoke-DscCacheRefresh
136183
.SYNOPSIS
137184
This function caches the results of the Get-DscResource call to optimize performance.
@@ -144,7 +191,7 @@ function Invoke-DscCacheRefresh {
144191
.EXAMPLE
145192
Invoke-DscCacheRefresh -Module "PSDesiredStateConfiguration"
146193
#>
147-
function Invoke-DscCacheRefresh_ORIGINAL {
194+
function Invoke-DscCacheRefresh {
148195
[CmdletBinding(HelpUri = '')]
149196
param(
150197
[Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
@@ -158,12 +205,8 @@ function Invoke-DscCacheRefresh_ORIGINAL {
158205
# PS 6+ on Windows
159206
Join-Path $env:LocalAppData "dsc\PSAdapterCache.json"
160207
} else {
161-
# either WinPS or PS 6+ on Linux/Mac
162-
if ($PSVersionTable.PSVersion.Major -le 5) {
163-
Join-Path $env:LocalAppData "dsc\WindowsPSAdapterCache.json"
164-
} else {
165-
Join-Path $env:HOME ".dsc" "PSAdapterCache.json"
166-
}
208+
# PS 6+ on Linux/Mac
209+
Join-Path $env:HOME ".dsc" "PSAdapterCache.json"
167210
}
168211

169212
if (Test-Path $cacheFilePath) {
@@ -225,33 +268,18 @@ function Invoke-DscCacheRefresh_ORIGINAL {
225268
# create a list object to store cache of Get-DscResource
226269
[dscResourceCacheEntry[]]$dscResourceCacheEntries = [System.Collections.Generic.List[Object]]::new()
227270

228-
Import-PSDSCModule
229-
$DscResources = Get-DscResource
230-
231-
foreach ($dscResource in $DscResources) {
232-
# resources that shipped in Windows should only be used with Windows PowerShell
233-
if ($dscResource.ParentPath -like "$env:windir\System32\*" -and $PSVersionTable.PSVersion.Major -gt 5) {
234-
continue
235-
}
236-
237-
if ( $dscResource.ImplementationDetail ) {
238-
# only support known dscResourceType
239-
if ([dscResourceType].GetEnumNames() -notcontains $dscResource.ImplementationDetail) {
240-
'WARNING: implementation detail not found: ' + $dscResource.ImplementationDetail | Write-DscTrace
241-
continue
242-
}
243-
}
244-
245-
$DscResourceInfo = [DscResourceInfo]::new()
246-
$dscResource.PSObject.Properties | ForEach-Object -Process {
247-
if ($null -ne $_.Value) {
248-
$DscResourceInfo.$($_.Name) = $_.Value
249-
}
250-
else {
251-
$DscResourceInfo.$($_.Name) = ''
252-
}
271+
$DscResources = [System.Collections.Generic.List[DscResourceInfo]]::new()
272+
$dscResourceModulePsd1s = Get-DSCResourceModules
273+
if($null -ne $dscResourceModulePsd1s) {
274+
$modules = Get-Module -ListAvailable -Name ($dscResourceModulePsd1s)
275+
foreach ($mod in $modules)
276+
{
277+
[System.Collections.Generic.List[DscResourceInfo]]$r = LoadPowerShellClassResourcesFromModule -moduleInfo $mod
278+
$DscResources.AddRange($r)
253279
}
280+
}
254281

282+
foreach ($dscResource in $DscResources) {
255283
$moduleName = $dscResource.ModuleName
256284

257285
# fill in resource files (and their last-write-times) that will be used for up-do-date checks
@@ -262,7 +290,7 @@ function Invoke-DscCacheRefresh_ORIGINAL {
262290

263291
$dscResourceCacheEntries += [dscResourceCacheEntry]@{
264292
Type = "$moduleName/$($dscResource.Name)"
265-
DscResourceInfo = $DscResourceInfo
293+
DscResourceInfo = $dscResource
266294
LastWriteTimes = $lastWriteTimes
267295
}
268296
}
@@ -454,6 +482,14 @@ enum dscResourceType {
454482
Composite
455483
}
456484

485+
class DscResourcePropertyInfo
486+
{
487+
[string] $Name
488+
[string] $PropertyType
489+
[bool] $IsMandatory
490+
[System.Collections.Generic.List[string]] $Values
491+
}
492+
457493
# dsc resource type (settable clone)
458494
class DscResourceInfo {
459495
[dscResourceType] $ImplementationDetail
@@ -467,5 +503,5 @@ class DscResourceInfo {
467503
[string] $ParentPath
468504
[string] $ImplementedAs
469505
[string] $CompanyName
470-
[psobject[]] $Properties
506+
[System.Collections.Generic.List[DscResourcePropertyInfo]] $Properties
471507
}

0 commit comments

Comments
 (0)