Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PSAdapter support for class inheritance #469

Merged
merged 2 commits into from
Jun 20, 2024
Merged
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 @@ -8,8 +8,14 @@ enum EnumPropEnumeration {
Expected
}

class BaseTestClass
{
[DscProperty()]
[string] $BaseProperty
}

[DscResource()]
class TestClassResource
class TestClassResource : BaseTestClass
{
[DscProperty(Key)]
[string] $Name
Expand Down
9 changes: 9 additions & 0 deletions powershell-adapter/Tests/powershellgroup.resource.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,13 @@ Describe 'PowerShell adapter resource tests' {
$res.actualState.result.count | Should -Be 5
$res.actualState.result| % {$_.Name | Should -Not -BeNullOrEmpty}
}

It 'Verify inheritance works in class-based resources' {

$r = dsc resource list '*' -a Microsoft.DSC/PowerShell
$LASTEXITCODE | Should -Be 0
$resources = $r | ConvertFrom-Json
$t = $resources | ? {$_.Type -eq 'TestClassResource/TestClassResource'}
$t.properties | Should -Contain "BaseProperty"
}
}
130 changes: 71 additions & 59 deletions powershell-adapter/psDscAdapter/psDscAdapter.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,57 @@ function Get-DSCResourceModules
return $dscModulePsd1List
}

function Add-AstMembers {
param(
$AllTypeDefinitions,
$TypeAst,
$Properties
)

foreach($TypeConstraint in $TypeAst.BaseTypes) {
$t = $AllTypeDefinitions | Where-Object {$_.Name -eq $TypeConstraint.TypeName.Name}
if ($t) {
Add-AstMembers $AllTypeDefinitions $t $Properties
}
}

foreach ($member in $TypeAst.Members)
{
$property = $member -as [System.Management.Automation.Language.PropertyMemberAst]
if (($property -eq $null) -or ($property.IsStatic))
{
continue;
}
$skipProperty = $true
$isKeyProperty = $false
foreach($attr in $property.Attributes)
{
if ($attr.TypeName.Name -eq 'DscProperty')
{
$skipProperty = $false
foreach($attrArg in $attr.NamedArguments)
{
if ($attrArg.ArgumentName -eq 'Key')
{
$isKeyProperty = $true
break
}
}
}
}
if ($skipProperty)
{
continue;
}

[DscResourcePropertyInfo]$prop = [DscResourcePropertyInfo]::new()
$prop.Name = $property.Name
$prop.PropertyType = $property.PropertyType.TypeName.Name
$prop.IsMandatory = $isKeyProperty
$Properties.Add($prop)
}
}

function FindAndParseResourceDefinitions
{
[CmdletBinding(HelpUri = '')]
Expand All @@ -68,7 +119,6 @@ function FindAndParseResourceDefinitions
}

"Loading resources from file '$filePath'" | Write-DscTrace -Operation Trace
#TODO: Handle class inheritance
#TODO: Ensure embedded instances in properties are working correctly
[System.Management.Automation.Language.Token[]] $tokens = $null
[System.Management.Automation.Language.ParseError[]] $errors = $null
Expand All @@ -78,76 +128,38 @@ function FindAndParseResourceDefinitions
$e | Out-String | Write-DscTrace -Operation Error
}

$resourceDefinitions = $ast.FindAll(
$typeDefinitions = $ast.FindAll(
{
$typeAst = $args[0] -as [System.Management.Automation.Language.TypeDefinitionAst]
if ($typeAst)
{
foreach($a in $typeAst.Attributes)
{
if ($a.TypeName.Name -eq 'DscResource')
{
return $true;
}
}
}

return $false;
return $typeAst -ne $null;
},
$false);

$resourceList = [System.Collections.Generic.List[DscResourceInfo]]::new()

foreach($typeDefinitionAst in $resourceDefinitions)
foreach($typeDefinitionAst in $typeDefinitions)
{
$DscResourceInfo = [DscResourceInfo]::new()
$DscResourceInfo.Name = $typeDefinitionAst.Name
$DscResourceInfo.ResourceType = $typeDefinitionAst.Name
$DscResourceInfo.FriendlyName = $typeDefinitionAst.Name
$DscResourceInfo.ImplementationDetail = 'ClassBased'
$DscResourceInfo.Module = $filePath
$DscResourceInfo.Path = $filePath
#TODO: ModuleName, Version and ParentPath should be taken from psd1 contents
$DscResourceInfo.ModuleName = [System.IO.Path]::GetFileNameWithoutExtension($filePath)
$DscResourceInfo.ParentPath = [System.IO.Path]::GetDirectoryName($filePath)

$DscResourceInfo.Properties = [System.Collections.Generic.List[DscResourcePropertyInfo]]::new()
foreach ($member in $typeDefinitionAst.Members)
foreach($a in $typeDefinitionAst.Attributes)
{
$property = $member -as [System.Management.Automation.Language.PropertyMemberAst]
if (($property -eq $null) -or ($property.IsStatic))
if ($a.TypeName.Name -eq 'DscResource')
{
continue;
}
$skipProperty = $true
$isKeyProperty = $false
foreach($attr in $property.Attributes)
{
if ($attr.TypeName.Name -eq 'DscProperty')
{
$skipProperty = $false
foreach($attrArg in $attr.NamedArguments)
{
if ($attrArg.ArgumentName -eq 'Key')
{
$isKeyProperty = $true
}
}
}
}
if ($skipProperty)
{
continue;
$DscResourceInfo = [DscResourceInfo]::new()
$DscResourceInfo.Name = $typeDefinitionAst.Name
$DscResourceInfo.ResourceType = $typeDefinitionAst.Name
$DscResourceInfo.FriendlyName = $typeDefinitionAst.Name
$DscResourceInfo.ImplementationDetail = 'ClassBased'
$DscResourceInfo.Module = $filePath
$DscResourceInfo.Path = $filePath
#TODO: ModuleName, Version and ParentPath should be taken from psd1 contents
$DscResourceInfo.ModuleName = [System.IO.Path]::GetFileNameWithoutExtension($filePath)
$DscResourceInfo.ParentPath = [System.IO.Path]::GetDirectoryName($filePath)

$DscResourceInfo.Properties = [System.Collections.Generic.List[DscResourcePropertyInfo]]::new()
Add-AstMembers $typeDefinitions $typeDefinitionAst $DscResourceInfo.Properties

$resourceList.Add($DscResourceInfo)
}

[DscResourcePropertyInfo]$prop = [DscResourcePropertyInfo]::new()
$prop.Name = $property.Name
$prop.PropertyType = $property.PropertyType.TypeName.Name
$prop.IsMandatory = $isKeyProperty
$DscResourceInfo.Properties.Add($prop)
}

$resourceList.Add($DscResourceInfo)
}

return $resourceList
Expand Down
Loading